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 char *FindFont P((char *pattern, int targetPxlSize));
255 void PieceMenuPopup P((Widget w, XEvent *event,
256 String *params, Cardinal *num_params));
257 static void PieceMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
258 static void DropMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
259 int EventToSquare P((int x, int limit));
260 void DrawSquare P((int row, int column, ChessSquare piece, int do_flash));
261 void HandleUserMove P((Widget w, XEvent *event,
262 String *prms, Cardinal *nprms));
263 void AnimateUserMove P((Widget w, XEvent * event,
264 String * params, Cardinal * nParams));
265 void CommentPopUp P((char *title, char *label));
266 void CommentPopDown P((void));
267 void CommentCallback P((Widget w, XtPointer client_data,
268 XtPointer call_data));
269 void ICSInputBoxPopUp P((void));
270 void ICSInputBoxPopDown P((void));
271 void FileNamePopUp P((char *label, char *def,
272 FileProc proc, char *openMode));
273 void FileNamePopDown P((void));
274 void FileNameCallback P((Widget w, XtPointer client_data,
275 XtPointer call_data));
276 void FileNameAction P((Widget w, XEvent *event,
277 String *prms, Cardinal *nprms));
278 void AskQuestionReplyAction P((Widget w, XEvent *event,
279 String *prms, Cardinal *nprms));
280 void AskQuestionProc P((Widget w, XEvent *event,
281 String *prms, Cardinal *nprms));
282 void AskQuestionPopDown P((void));
283 void PromotionPopUp P((void));
284 void PromotionPopDown P((void));
285 void PromotionCallback P((Widget w, XtPointer client_data,
286 XtPointer call_data));
287 void EditCommentPopDown P((void));
288 void EditCommentCallback P((Widget w, XtPointer client_data,
289 XtPointer call_data));
290 void SelectCommand P((Widget w, XtPointer client_data, XtPointer call_data));
291 void LoadPositionProc P((Widget w, XEvent *event,
292 String *prms, Cardinal *nprms));
293 void CopyPositionProc P((Widget w, XEvent *event, String *prms,
295 void PastePositionProc P((Widget w, XEvent *event, String *prms,
297 void CopyGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
298 void PasteGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
299 void SaveGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
300 void SavePositionProc P((Widget w, XEvent *event,
301 String *prms, Cardinal *nprms));
302 void MailMoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
303 void ReloadCmailMsgProc P((Widget w, XEvent *event, String *prms,
305 void AnalyzeModeProc P((Widget w, XEvent *event,
306 String *prms, Cardinal *nprms));
307 void AnalyzeFileProc P((Widget w, XEvent *event,
308 String *prms, Cardinal *nprms));
309 void EditGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
310 void EditPositionProc P((Widget w, XEvent *event,
311 String *prms, Cardinal *nprms));
312 void TrainingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
313 void EditCommentProc P((Widget w, XEvent *event,
314 String *prms, Cardinal *nprms));
315 void IcsInputBoxProc P((Widget w, XEvent *event,
316 String *prms, Cardinal *nprms));
317 void EnterKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
318 void AlwaysQueenProc P((Widget w, XEvent *event, String *prms,
320 void AnimateDraggingProc P((Widget w, XEvent *event, String *prms,
322 void AnimateMovingProc P((Widget w, XEvent *event, String *prms,
324 void AutobsProc P((Widget w, XEvent *event, String *prms,
326 void AutoraiseProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
327 void AutosaveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
328 void BlindfoldProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
329 void FlashMovesProc P((Widget w, XEvent *event, String *prms,
331 void HighlightDraggingProc P((Widget w, XEvent *event, String *prms,
333 void HighlightLastMoveProc P((Widget w, XEvent *event, String *prms,
335 void MoveSoundProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
336 void IcsAlarmProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
337 void OldSaveStyleProc P((Widget w, XEvent *event, String *prms,
339 void PeriodicUpdatesProc P((Widget w, XEvent *event, String *prms,
341 void PonderNextMoveProc P((Widget w, XEvent *event, String *prms,
343 void PopupMoveErrorsProc P((Widget w, XEvent *event, String *prms,
345 void PopupExitMessageProc P((Widget w, XEvent *event, String *prms,
347 void PremoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
348 void QuietPlayProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
349 void TestLegalityProc P((Widget w, XEvent *event, String *prms,
351 void AboutGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
352 void DebugProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
353 void NothingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
354 void Iconify P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
355 void DisplayMove P((int moveNumber));
356 void DisplayTitle P((char *title));
357 void ICSInitScript P((void));
358 int LoadGamePopUp P((FILE *f, int gameNumber, char *title));
359 void ErrorPopUp P((char *title, char *text, int modal));
360 void ErrorPopDown P((void));
361 static char *ExpandPathName P((char *path));
362 static void CreateAnimVars P((void));
363 void DragPieceBegin P((int x, int y));
364 static void DragPieceMove P((int x, int y));
365 void DragPieceEnd P((int x, int y));
366 static void DrawDragPiece P((void));
367 char *ModeToWidgetName P((GameMode mode));
368 void EngineOutputUpdate( FrontEndProgramStats * stats );
369 void ShuffleMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
370 void EngineMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
371 void UciMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
372 void TimeControlProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
373 void NewVariantProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
374 void FirstSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
375 void SecondSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
376 void ShufflePopDown P(());
377 void EnginePopDown P(());
378 void UciPopDown P(());
379 void TimeControlPopDown P(());
380 void NewVariantPopDown P(());
381 void SettingsPopDown P(());
382 void SetMenuEnables P((Enables *enab));
385 * XBoard depends on Xt R4 or higher
387 int xtVersion = XtSpecificationRelease;
392 Pixel lightSquareColor, darkSquareColor, whitePieceColor, blackPieceColor,
393 jailSquareColor, highlightSquareColor, premoveHighlightColor;
394 Pixel lowTimeWarningColor;
396 #define LINE_TYPE_NORMAL 0
397 #define LINE_TYPE_HIGHLIGHT 1
398 #define LINE_TYPE_PRE 2
401 GC lightSquareGC, darkSquareGC, jailSquareGC, wdPieceGC, wlPieceGC,
402 bdPieceGC, blPieceGC, wbPieceGC, bwPieceGC, coordGC,
403 wjPieceGC, bjPieceGC;
404 Pixmap iconPixmap, wIconPixmap, bIconPixmap, xMarkPixmap;
405 Widget shellWidget, layoutWidget, formWidget, boardWidget, messageWidget,
406 whiteTimerWidget, blackTimerWidget, titleWidget, widgetList[16],
407 commentShell, promotionShell, whitePieceMenu, blackPieceMenu, dropMenu,
408 menuBarWidget, editShell, errorShell, analysisShell,
409 ICSInputShell, fileNameShell, askQuestionShell;
410 Font clockFontID, coordFontID, countFontID;
411 XFontStruct *clockFontStruct, *coordFontStruct, *countFontStruct;
412 XtAppContext appContext;
414 char *oldICSInteractionTitle;
418 char installDir[] = "."; // [HGM] UCI: needed for UCI; probably needs run-time initializtion
420 Position commentX = -1, commentY = -1;
421 Dimension commentW, commentH;
423 int squareSize, smallLayout = 0, tinyLayout = 0,
424 marginW, marginH, // [HGM] for run-time resizing
425 fromX = -1, fromY = -1, toX, toY, commentUp = False, analysisUp = False,
426 ICSInputBoxUp = False, askQuestionUp = False,
427 filenameUp = False, promotionUp = False, pmFromX = -1, pmFromY = -1,
428 editUp = False, errorUp = False, errorExitStatus = -1, lineGap;
429 Pixel timerForegroundPixel, timerBackgroundPixel;
430 Pixel buttonForegroundPixel, buttonBackgroundPixel;
431 char *chessDir, *programName, *programVersion,
432 *gameCopyFilename, *gamePasteFilename;
436 Pixmap pieceBitmap[2][(int)BlackPawn];
437 Pixmap pieceBitmap2[2][(int)BlackPawn+4]; /* [HGM] pieces */
438 Pixmap xpmPieceBitmap[4][(int)BlackPawn]; /* LL, LD, DL, DD actually used*/
439 Pixmap xpmPieceBitmap2[4][(int)BlackPawn+4]; /* LL, LD, DL, DD set to select from */
440 Pixmap xpmLightSquare, xpmDarkSquare, xpmJailSquare;
441 int useImages=0, useImageSqs;
442 XImage *ximPieceBitmap[4][(int)BlackPawn+4]; /* LL, LD, DL, DD */
443 Pixmap ximMaskPm[(int)BlackPawn]; /* clipmasks, used for XIM pieces */
444 Pixmap ximMaskPm2[(int)BlackPawn+4]; /* clipmasks, used for XIM pieces */
445 XImage *ximLightSquare, *ximDarkSquare;
448 #define pieceToSolid(piece) &pieceBitmap[SOLID][(piece) % (int)BlackPawn]
449 #define pieceToOutline(piece) &pieceBitmap[OUTLINE][(piece) % (int)BlackPawn]
451 #define White(piece) ((int)(piece) < (int)BlackPawn)
453 /* Variables for doing smooth animation. This whole thing
454 would be much easier if the board was double-buffered,
455 but that would require a fairly major rewrite. */
460 GC blitGC, pieceGC, outlineGC;
461 XPoint startSquare, prevFrame, mouseDelta;
465 int startBoardX, startBoardY;
468 /* There can be two pieces being animated at once: a player
469 can begin dragging a piece before the remote opponent has moved. */
471 static AnimState game, player;
473 /* Bitmaps for use as masks when drawing XPM pieces.
474 Need one for each black and white piece. */
475 static Pixmap xpmMask[BlackKing + 1];
477 /* This magic number is the number of intermediate frames used
478 in each half of the animation. For short moves it's reduced
479 by 1. The total number of frames will be factor * 2 + 1. */
482 SizeDefaults sizeDefaults[] = SIZE_DEFAULTS;
484 Enables icsEnables[] = {
485 { "menuFile.Mail Move", False },
486 { "menuFile.Reload CMail Message", False },
487 { "menuMode.Machine Black", False },
488 { "menuMode.Machine White", False },
489 { "menuMode.Analysis Mode", False },
490 { "menuMode.Analyze File", False },
491 { "menuMode.Two Machines", False },
493 { "menuHelp.Hint", False },
494 { "menuHelp.Book", False },
495 { "menuStep.Move Now", False },
496 { "menuOptions.Periodic Updates", False },
497 { "menuOptions.Hide Thinking", False },
498 { "menuOptions.Ponder Next Move", False },
503 Enables ncpEnables[] = {
504 { "menuFile.Mail Move", False },
505 { "menuFile.Reload CMail Message", False },
506 { "menuMode.Machine White", False },
507 { "menuMode.Machine Black", False },
508 { "menuMode.Analysis Mode", False },
509 { "menuMode.Analyze File", False },
510 { "menuMode.Two Machines", False },
511 { "menuMode.ICS Client", False },
512 { "menuMode.ICS Input Box", False },
514 { "menuStep.Revert", False },
515 { "menuStep.Move Now", False },
516 { "menuStep.Retract Move", False },
517 { "menuOptions.Auto Comment", False },
518 { "menuOptions.Auto Flag", False },
519 { "menuOptions.Auto Flip View", False },
520 { "menuOptions.Auto Observe", False },
521 { "menuOptions.Auto Raise Board", False },
522 { "menuOptions.Get Move List", False },
523 { "menuOptions.ICS Alarm", False },
524 { "menuOptions.Move Sound", False },
525 { "menuOptions.Quiet Play", False },
526 { "menuOptions.Hide Thinking", False },
527 { "menuOptions.Periodic Updates", False },
528 { "menuOptions.Ponder Next Move", False },
529 { "menuHelp.Hint", False },
530 { "menuHelp.Book", False },
534 Enables gnuEnables[] = {
535 { "menuMode.ICS Client", False },
536 { "menuMode.ICS Input Box", False },
537 { "menuAction.Accept", False },
538 { "menuAction.Decline", False },
539 { "menuAction.Rematch", False },
540 { "menuAction.Adjourn", False },
541 { "menuAction.Stop Examining", False },
542 { "menuAction.Stop Observing", False },
543 { "menuStep.Revert", False },
544 { "menuOptions.Auto Comment", False },
545 { "menuOptions.Auto Observe", False },
546 { "menuOptions.Auto Raise Board", False },
547 { "menuOptions.Get Move List", False },
548 { "menuOptions.Premove", False },
549 { "menuOptions.Quiet Play", False },
551 /* The next two options rely on SetCmailMode being called *after* */
552 /* SetGNUMode so that when GNU is being used to give hints these */
553 /* menu options are still available */
555 { "menuFile.Mail Move", False },
556 { "menuFile.Reload CMail Message", False },
560 Enables cmailEnables[] = {
562 { "menuAction.Call Flag", False },
563 { "menuAction.Draw", True },
564 { "menuAction.Adjourn", False },
565 { "menuAction.Abort", False },
566 { "menuAction.Stop Observing", False },
567 { "menuAction.Stop Examining", False },
568 { "menuFile.Mail Move", True },
569 { "menuFile.Reload CMail Message", True },
573 Enables trainingOnEnables[] = {
574 { "menuMode.Edit Comment", False },
575 { "menuMode.Pause", False },
576 { "menuStep.Forward", False },
577 { "menuStep.Backward", False },
578 { "menuStep.Forward to End", False },
579 { "menuStep.Back to Start", False },
580 { "menuStep.Move Now", False },
581 { "menuStep.Truncate Game", False },
585 Enables trainingOffEnables[] = {
586 { "menuMode.Edit Comment", True },
587 { "menuMode.Pause", True },
588 { "menuStep.Forward", True },
589 { "menuStep.Backward", True },
590 { "menuStep.Forward to End", True },
591 { "menuStep.Back to Start", True },
592 { "menuStep.Move Now", True },
593 { "menuStep.Truncate Game", True },
597 Enables machineThinkingEnables[] = {
598 { "menuFile.Load Game", False },
599 { "menuFile.Load Next Game", False },
600 { "menuFile.Load Previous Game", False },
601 { "menuFile.Reload Same Game", False },
602 { "menuFile.Paste Game", False },
603 { "menuFile.Load Position", False },
604 { "menuFile.Load Next Position", False },
605 { "menuFile.Load Previous Position", False },
606 { "menuFile.Reload Same Position", False },
607 { "menuFile.Paste Position", False },
608 { "menuMode.Machine White", False },
609 { "menuMode.Machine Black", False },
610 { "menuMode.Two Machines", False },
611 { "menuStep.Retract Move", False },
615 Enables userThinkingEnables[] = {
616 { "menuFile.Load Game", True },
617 { "menuFile.Load Next Game", True },
618 { "menuFile.Load Previous Game", True },
619 { "menuFile.Reload Same Game", True },
620 { "menuFile.Paste Game", True },
621 { "menuFile.Load Position", True },
622 { "menuFile.Load Next Position", True },
623 { "menuFile.Load Previous Position", True },
624 { "menuFile.Reload Same Position", True },
625 { "menuFile.Paste Position", True },
626 { "menuMode.Machine White", True },
627 { "menuMode.Machine Black", True },
628 { "menuMode.Two Machines", True },
629 { "menuStep.Retract Move", True },
635 MenuItem fileMenu[] = {
636 {N_("New Shuffle Game ..."), ShuffleMenuProc},
637 {N_("New Variant ..."), NewVariantProc}, // [HGM] variant: not functional yet
638 {"----", NothingProc},
639 {N_("Save Game"), SaveGameProc},
640 {"----", NothingProc},
641 {N_("Copy Game"), CopyGameProc},
642 {N_("Paste Game"), PasteGameProc},
643 {"----", NothingProc},
644 {N_("Load Position"), LoadPositionProc},
645 // {N_("Load Next Position"), LoadNextPositionProc},
646 // {N_("Load Previous Position"), LoadPrevPositionProc},
647 // {N_("Reload Same Position"), ReloadPositionProc},
648 {N_("Save Position"), SavePositionProc},
649 {"----", NothingProc},
650 {N_("Copy Position"), CopyPositionProc},
651 {N_("Paste Position"), PastePositionProc},
652 {"----", NothingProc},
653 {N_("Mail Move"), MailMoveProc},
654 {N_("Reload CMail Message"), ReloadCmailMsgProc},
655 {"----", NothingProc},
659 MenuItem modeMenu[] = {
660 // {N_("Machine White"), MachineWhiteProc},
661 // {N_("Machine Black"), MachineBlackProc},
662 // {N_("Two Machines"), TwoMachinesProc},
663 {N_("Analysis Mode"), AnalyzeModeProc},
664 {N_("Analyze File"), AnalyzeFileProc },
665 // {N_("ICS Client"), IcsClientProc},
666 {N_("Edit Game"), EditGameProc},
667 {N_("Edit Position"), EditPositionProc},
668 {N_("Training"), TrainingProc},
669 {"----", NothingProc},
670 {N_("Show Engine Output"), EngineOutputProc},
671 {N_("Show Evaluation Graph"), NothingProc}, // [HGM] evalgr: not functional yet
672 {N_("Show Game List"), ShowGameListProc},
673 // {"Show Move History", HistoryShowProc}, // [HGM] hist: activate 4.2.7 code
674 {"----", NothingProc},
675 {N_("Edit Tags"), EditTagsProc},
676 {N_("Edit Comment"), EditCommentProc},
677 {N_("ICS Input Box"), IcsInputBoxProc},
681 MenuItem optionsMenu[] = {
682 // {N_("Flip View"), FlipViewProc},
683 // {"----", NothingProc},
684 {N_("Adjudications ..."), EngineMenuProc},
685 {N_("General Settings ..."), UciMenuProc},
686 {N_("Engine #1 Settings ..."), FirstSettingsProc},
687 {N_("Engine #2 Settings ..."), SecondSettingsProc},
688 {N_("Time Control ..."), TimeControlProc},
689 {"----", NothingProc},
690 {N_("Always Queen"), AlwaysQueenProc},
691 {N_("Animate Dragging"), AnimateDraggingProc},
692 {N_("Animate Moving"), AnimateMovingProc},
693 // {N_("Auto Comment"), AutocommProc},
694 // {N_("Auto Flag"), AutoflagProc},
695 // {N_("Auto Flip View"), AutoflipProc},
696 {N_("Auto Observe"), AutobsProc},
697 {N_("Auto Raise Board"), AutoraiseProc},
698 {N_("Auto Save"), AutosaveProc},
699 {N_("Blindfold"), BlindfoldProc},
700 {N_("Flash Moves"), FlashMovesProc},
701 // {N_("Get Move List"), GetMoveListProc},
703 {N_("Highlight Dragging"), HighlightDraggingProc},
705 {N_("Highlight Last Move"), HighlightLastMoveProc},
706 {N_("Move Sound"), MoveSoundProc},
707 {N_("ICS Alarm"), IcsAlarmProc},
708 {N_("Old Save Style"), OldSaveStyleProc},
709 {N_("Periodic Updates"), PeriodicUpdatesProc},
710 {N_("Ponder Next Move"), PonderNextMoveProc},
711 {N_("Popup Exit Message"), PopupExitMessageProc},
712 {N_("Popup Move Errors"), PopupMoveErrorsProc},
713 {N_("Premove"), PremoveProc},
714 {N_("Quiet Play"), QuietPlayProc},
715 // {N_("Hide Thinking"), HideThinkingProc},
716 {N_("Test Legality"), TestLegalityProc},
721 {N_("File"), fileMenu},
722 {N_("Mode"), modeMenu},
723 {N_("Options"), optionsMenu},
727 #define PIECE_MENU_SIZE 18
728 String pieceMenuStrings[2][PIECE_MENU_SIZE] = {
729 { N_("White"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
730 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
731 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
732 N_("Empty square"), N_("Clear board") },
733 { N_("Black"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
734 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
735 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
736 N_("Empty square"), N_("Clear board") }
738 /* must be in same order as PieceMenuStrings! */
739 ChessSquare pieceMenuTranslation[2][PIECE_MENU_SIZE] = {
740 { WhitePlay, (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
741 WhiteRook, WhiteQueen, WhiteKing, (ChessSquare) 0, WhiteAlfil,
742 WhiteCannon, WhiteAngel, WhiteMarshall, (ChessSquare) 0,
743 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
744 { BlackPlay, (ChessSquare) 0, BlackPawn, BlackKnight, BlackBishop,
745 BlackRook, BlackQueen, BlackKing, (ChessSquare) 0, BlackAlfil,
746 BlackCannon, BlackAngel, BlackMarshall, (ChessSquare) 0,
747 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
750 #define DROP_MENU_SIZE 6
751 String dropMenuStrings[DROP_MENU_SIZE] = {
752 "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"), N_("Queen")
754 /* must be in same order as PieceMenuStrings! */
755 ChessSquare dropMenuTranslation[DROP_MENU_SIZE] = {
756 (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
757 WhiteRook, WhiteQueen
765 DropMenuEnables dmEnables[] = {
774 { XtNborderWidth, 0 },
775 { XtNdefaultDistance, 0 },
779 { XtNborderWidth, 0 },
780 { XtNresizable, (XtArgVal) True },
784 { XtNborderWidth, 0 },
789 XtResource clientResources[] = {
790 { "whitePieceColor", "whitePieceColor", XtRString, sizeof(String),
791 XtOffset(AppDataPtr, whitePieceColor), XtRString,
793 { "blackPieceColor", "blackPieceColor", XtRString, sizeof(String),
794 XtOffset(AppDataPtr, blackPieceColor), XtRString,
796 { "lightSquareColor", "lightSquareColor", XtRString,
797 sizeof(String), XtOffset(AppDataPtr, lightSquareColor),
798 XtRString, LIGHT_SQUARE_COLOR },
799 { "darkSquareColor", "darkSquareColor", XtRString, sizeof(String),
800 XtOffset(AppDataPtr, darkSquareColor), XtRString,
802 { "highlightSquareColor", "highlightSquareColor", XtRString,
803 sizeof(String), XtOffset(AppDataPtr, highlightSquareColor),
804 XtRString, HIGHLIGHT_SQUARE_COLOR },
805 { "premoveHighlightColor", "premoveHighlightColor", XtRString,
806 sizeof(String), XtOffset(AppDataPtr, premoveHighlightColor),
807 XtRString, PREMOVE_HIGHLIGHT_COLOR },
808 { "movesPerSession", "movesPerSession", XtRInt, sizeof(int),
809 XtOffset(AppDataPtr, movesPerSession), XtRImmediate,
810 (XtPointer) MOVES_PER_SESSION },
811 { "timeIncrement", "timeIncrement", XtRInt, sizeof(int),
812 XtOffset(AppDataPtr, timeIncrement), XtRImmediate,
813 (XtPointer) TIME_INCREMENT },
814 { "initString", "initString", XtRString, sizeof(String),
815 XtOffset(AppDataPtr, initString), XtRString, INIT_STRING },
816 { "secondInitString", "secondInitString", XtRString, sizeof(String),
817 XtOffset(AppDataPtr, secondInitString), XtRString, INIT_STRING },
818 { "firstComputerString", "firstComputerString", XtRString,
819 sizeof(String), XtOffset(AppDataPtr, firstComputerString), XtRString,
821 { "secondComputerString", "secondComputerString", XtRString,
822 sizeof(String), XtOffset(AppDataPtr, secondComputerString), XtRString,
824 { "firstChessProgram", "firstChessProgram", XtRString,
825 sizeof(String), XtOffset(AppDataPtr, firstChessProgram),
826 XtRString, FIRST_CHESS_PROGRAM },
827 { "secondChessProgram", "secondChessProgram", XtRString,
828 sizeof(String), XtOffset(AppDataPtr, secondChessProgram),
829 XtRString, SECOND_CHESS_PROGRAM },
830 { "firstPlaysBlack", "firstPlaysBlack", XtRBoolean,
831 sizeof(Boolean), XtOffset(AppDataPtr, firstPlaysBlack),
832 XtRImmediate, (XtPointer) False },
833 { "noChessProgram", "noChessProgram", XtRBoolean,
834 sizeof(Boolean), XtOffset(AppDataPtr, noChessProgram),
835 XtRImmediate, (XtPointer) False },
836 { "firstHost", "firstHost", XtRString, sizeof(String),
837 XtOffset(AppDataPtr, firstHost), XtRString, FIRST_HOST },
838 { "secondHost", "secondHost", XtRString, sizeof(String),
839 XtOffset(AppDataPtr, secondHost), XtRString, SECOND_HOST },
840 { "firstDirectory", "firstDirectory", XtRString, sizeof(String),
841 XtOffset(AppDataPtr, firstDirectory), XtRString, "." },
842 { "secondDirectory", "secondDirectory", XtRString, sizeof(String),
843 XtOffset(AppDataPtr, secondDirectory), XtRString, "." },
844 { "bitmapDirectory", "bitmapDirectory", XtRString,
845 sizeof(String), XtOffset(AppDataPtr, bitmapDirectory),
847 { "remoteShell", "remoteShell", XtRString, sizeof(String),
848 XtOffset(AppDataPtr, remoteShell), XtRString, REMOTE_SHELL },
849 { "remoteUser", "remoteUser", XtRString, sizeof(String),
850 XtOffset(AppDataPtr, remoteUser), XtRString, "" },
851 { "timeDelay", "timeDelay", XtRFloat, sizeof(float),
852 XtOffset(AppDataPtr, timeDelay), XtRString,
853 (XtPointer) TIME_DELAY_QUOTE },
854 { "timeControl", "timeControl", XtRString, sizeof(String),
855 XtOffset(AppDataPtr, timeControl), XtRString,
856 (XtPointer) TIME_CONTROL },
857 { "internetChessServerMode", "internetChessServerMode",
858 XtRBoolean, sizeof(Boolean),
859 XtOffset(AppDataPtr, icsActive), XtRImmediate,
861 { "internetChessServerHost", "internetChessServerHost",
862 XtRString, sizeof(String),
863 XtOffset(AppDataPtr, icsHost),
864 XtRString, (XtPointer) ICS_HOST },
865 { "internetChessServerPort", "internetChessServerPort",
866 XtRString, sizeof(String),
867 XtOffset(AppDataPtr, icsPort), XtRString,
868 (XtPointer) ICS_PORT },
869 { "internetChessServerCommPort", "internetChessServerCommPort",
870 XtRString, sizeof(String),
871 XtOffset(AppDataPtr, icsCommPort), XtRString,
873 { "internetChessServerLogonScript", "internetChessServerLogonScript",
874 XtRString, sizeof(String),
875 XtOffset(AppDataPtr, icsLogon), XtRString,
877 { "internetChessServerHelper", "internetChessServerHelper",
878 XtRString, sizeof(String),
879 XtOffset(AppDataPtr, icsHelper), XtRString, "" },
880 { "internetChessServerInputBox", "internetChessServerInputBox",
881 XtRBoolean, sizeof(Boolean),
882 XtOffset(AppDataPtr, icsInputBox), XtRImmediate,
884 { "icsAlarm", "icsAlarm",
885 XtRBoolean, sizeof(Boolean),
886 XtOffset(AppDataPtr, icsAlarm), XtRImmediate,
888 { "icsAlarmTime", "icsAlarmTime",
890 XtOffset(AppDataPtr, icsAlarmTime), XtRImmediate,
892 { "useTelnet", "useTelnet", XtRBoolean, sizeof(Boolean),
893 XtOffset(AppDataPtr, useTelnet), XtRImmediate,
895 { "telnetProgram", "telnetProgram", XtRString, sizeof(String),
896 XtOffset(AppDataPtr, telnetProgram), XtRString, TELNET_PROGRAM },
897 { "gateway", "gateway", XtRString, sizeof(String),
898 XtOffset(AppDataPtr, gateway), XtRString, "" },
899 { "loadGameFile", "loadGameFile", XtRString, sizeof(String),
900 XtOffset(AppDataPtr, loadGameFile), XtRString, "" },
901 { "loadGameIndex", "loadGameIndex",
903 XtOffset(AppDataPtr, loadGameIndex), XtRImmediate,
905 { "saveGameFile", "saveGameFile", XtRString, sizeof(String),
906 XtOffset(AppDataPtr, saveGameFile), XtRString, "" },
907 { "autoRaiseBoard", "autoRaiseBoard", XtRBoolean,
908 sizeof(Boolean), XtOffset(AppDataPtr, autoRaiseBoard),
909 XtRImmediate, (XtPointer) True },
910 { "autoSaveGames", "autoSaveGames", XtRBoolean,
911 sizeof(Boolean), XtOffset(AppDataPtr, autoSaveGames),
912 XtRImmediate, (XtPointer) False },
913 { "blindfold", "blindfold", XtRBoolean,
914 sizeof(Boolean), XtOffset(AppDataPtr, blindfold),
915 XtRImmediate, (XtPointer) False },
916 { "loadPositionFile", "loadPositionFile", XtRString,
917 sizeof(String), XtOffset(AppDataPtr, loadPositionFile),
919 { "loadPositionIndex", "loadPositionIndex",
921 XtOffset(AppDataPtr, loadPositionIndex), XtRImmediate,
923 { "savePositionFile", "savePositionFile", XtRString,
924 sizeof(String), XtOffset(AppDataPtr, savePositionFile),
926 { "matchMode", "matchMode", XtRBoolean, sizeof(Boolean),
927 XtOffset(AppDataPtr, matchMode), XtRImmediate, (XtPointer) False },
928 { "matchGames", "matchGames", XtRInt, sizeof(int),
929 XtOffset(AppDataPtr, matchGames), XtRImmediate,
931 { "monoMode", "monoMode", XtRBoolean, sizeof(Boolean),
932 XtOffset(AppDataPtr, monoMode), XtRImmediate,
934 { "debugMode", "debugMode", XtRBoolean, sizeof(Boolean),
935 XtOffset(AppDataPtr, debugMode), XtRImmediate,
937 { "clockMode", "clockMode", XtRBoolean, sizeof(Boolean),
938 XtOffset(AppDataPtr, clockMode), XtRImmediate,
940 { "boardSize", "boardSize", XtRString, sizeof(String),
941 XtOffset(AppDataPtr, boardSize), XtRString, "" },
942 { "searchTime", "searchTime", XtRString, sizeof(String),
943 XtOffset(AppDataPtr, searchTime), XtRString,
945 { "searchDepth", "searchDepth", XtRInt, sizeof(int),
946 XtOffset(AppDataPtr, searchDepth), XtRImmediate,
948 { "showCoords", "showCoords", XtRBoolean, sizeof(Boolean),
949 XtOffset(AppDataPtr, showCoords), XtRImmediate,
951 { "showJail", "showJail", XtRInt, sizeof(int),
952 XtOffset(AppDataPtr, showJail), XtRImmediate,
954 { "showThinking", "showThinking", XtRBoolean, sizeof(Boolean),
955 XtOffset(AppDataPtr, showThinking), XtRImmediate,
957 { "ponderNextMove", "ponderNextMove", XtRBoolean, sizeof(Boolean),
958 XtOffset(AppDataPtr, ponderNextMove), XtRImmediate,
960 { "periodicUpdates", "periodicUpdates", XtRBoolean, sizeof(Boolean),
961 XtOffset(AppDataPtr, periodicUpdates), XtRImmediate,
963 { "clockFont", "clockFont", XtRString, sizeof(String),
964 XtOffset(AppDataPtr, clockFont), XtRString, CLOCK_FONT },
965 { "coordFont", "coordFont", XtRString, sizeof(String),
966 XtOffset(AppDataPtr, coordFont), XtRString, COORD_FONT },
967 { "font", "font", XtRString, sizeof(String),
968 XtOffset(AppDataPtr, font), XtRString, DEFAULT_FONT },
969 { "ringBellAfterMoves", "ringBellAfterMoves",
970 XtRBoolean, sizeof(Boolean),
971 XtOffset(AppDataPtr, ringBellAfterMoves),
972 XtRImmediate, (XtPointer) False },
973 { "autoCallFlag", "autoCallFlag", XtRBoolean,
974 sizeof(Boolean), XtOffset(AppDataPtr, autoCallFlag),
975 XtRImmediate, (XtPointer) False },
976 { "autoFlipView", "autoFlipView", XtRBoolean,
977 sizeof(Boolean), XtOffset(AppDataPtr, autoFlipView),
978 XtRImmediate, (XtPointer) True },
979 { "autoObserve", "autoObserve", XtRBoolean,
980 sizeof(Boolean), XtOffset(AppDataPtr, autoObserve),
981 XtRImmediate, (XtPointer) False },
982 { "autoComment", "autoComment", XtRBoolean,
983 sizeof(Boolean), XtOffset(AppDataPtr, autoComment),
984 XtRImmediate, (XtPointer) False },
985 { "getMoveList", "getMoveList", XtRBoolean,
986 sizeof(Boolean), XtOffset(AppDataPtr, getMoveList),
987 XtRImmediate, (XtPointer) True },
989 { "highlightDragging", "highlightDragging", XtRBoolean,
990 sizeof(Boolean), XtOffset(AppDataPtr, highlightDragging),
991 XtRImmediate, (XtPointer) False },
993 { "highlightLastMove", "highlightLastMove", XtRBoolean,
994 sizeof(Boolean), XtOffset(AppDataPtr, highlightLastMove),
995 XtRImmediate, (XtPointer) False },
996 { "premove", "premove", XtRBoolean,
997 sizeof(Boolean), XtOffset(AppDataPtr, premove),
998 XtRImmediate, (XtPointer) True },
999 { "testLegality", "testLegality", XtRBoolean,
1000 sizeof(Boolean), XtOffset(AppDataPtr, testLegality),
1001 XtRImmediate, (XtPointer) True },
1002 { "flipView", "flipView", XtRBoolean,
1003 sizeof(Boolean), XtOffset(AppDataPtr, flipView),
1004 XtRImmediate, (XtPointer) False },
1005 { "cmail", "cmailGameName", XtRString, sizeof(String),
1006 XtOffset(AppDataPtr, cmailGameName), XtRString, "" },
1007 { "alwaysPromoteToQueen", "alwaysPromoteToQueen", XtRBoolean,
1008 sizeof(Boolean), XtOffset(AppDataPtr, alwaysPromoteToQueen),
1009 XtRImmediate, (XtPointer) False },
1010 { "oldSaveStyle", "oldSaveStyle", XtRBoolean,
1011 sizeof(Boolean), XtOffset(AppDataPtr, oldSaveStyle),
1012 XtRImmediate, (XtPointer) False },
1013 { "quietPlay", "quietPlay", XtRBoolean,
1014 sizeof(Boolean), XtOffset(AppDataPtr, quietPlay),
1015 XtRImmediate, (XtPointer) False },
1016 { "titleInWindow", "titleInWindow", XtRBoolean,
1017 sizeof(Boolean), XtOffset(AppDataPtr, titleInWindow),
1018 XtRImmediate, (XtPointer) False },
1019 { "localLineEditing", "localLineEditing", XtRBoolean,
1020 sizeof(Boolean), XtOffset(AppDataPtr, localLineEditing),
1021 XtRImmediate, (XtPointer) True }, /* not implemented, must be True */
1023 { "zippyTalk", "zippyTalk", XtRBoolean,
1024 sizeof(Boolean), XtOffset(AppDataPtr, zippyTalk),
1025 XtRImmediate, (XtPointer) ZIPPY_TALK },
1026 { "zippyPlay", "zippyPlay", XtRBoolean,
1027 sizeof(Boolean), XtOffset(AppDataPtr, zippyPlay),
1028 XtRImmediate, (XtPointer) ZIPPY_PLAY },
1029 { "zippyLines", "zippyLines", XtRString, sizeof(String),
1030 XtOffset(AppDataPtr, zippyLines), XtRString, ZIPPY_LINES },
1031 { "zippyPinhead", "zippyPinhead", XtRString, sizeof(String),
1032 XtOffset(AppDataPtr, zippyPinhead), XtRString, ZIPPY_PINHEAD },
1033 { "zippyPassword", "zippyPassword", XtRString, sizeof(String),
1034 XtOffset(AppDataPtr, zippyPassword), XtRString, ZIPPY_PASSWORD },
1035 { "zippyPassword2", "zippyPassword2", XtRString, sizeof(String),
1036 XtOffset(AppDataPtr, zippyPassword2), XtRString, ZIPPY_PASSWORD2 },
1037 { "zippyWrongPassword", "zippyWrongPassword", XtRString, sizeof(String),
1038 XtOffset(AppDataPtr, zippyWrongPassword), XtRString,
1039 ZIPPY_WRONG_PASSWORD },
1040 { "zippyAcceptOnly", "zippyAcceptOnly", XtRString, sizeof(String),
1041 XtOffset(AppDataPtr, zippyAcceptOnly), XtRString, ZIPPY_ACCEPT_ONLY },
1042 { "zippyUseI", "zippyUseI", XtRBoolean,
1043 sizeof(Boolean), XtOffset(AppDataPtr, zippyUseI),
1044 XtRImmediate, (XtPointer) ZIPPY_USE_I },
1045 { "zippyBughouse", "zippyBughouse", XtRInt,
1046 sizeof(int), XtOffset(AppDataPtr, zippyBughouse),
1047 XtRImmediate, (XtPointer) ZIPPY_BUGHOUSE },
1048 { "zippyNoplayCrafty", "zippyNoplayCrafty", XtRBoolean,
1049 sizeof(Boolean), XtOffset(AppDataPtr, zippyNoplayCrafty),
1050 XtRImmediate, (XtPointer) ZIPPY_NOPLAY_CRAFTY },
1051 { "zippyGameEnd", "zippyGameEnd", XtRString, sizeof(String),
1052 XtOffset(AppDataPtr, zippyGameEnd), XtRString, ZIPPY_GAME_END },
1053 { "zippyGameStart", "zippyGameStart", XtRString, sizeof(String),
1054 XtOffset(AppDataPtr, zippyGameStart), XtRString, ZIPPY_GAME_START },
1055 { "zippyAdjourn", "zippyAdjourn", XtRBoolean,
1056 sizeof(Boolean), XtOffset(AppDataPtr, zippyAdjourn),
1057 XtRImmediate, (XtPointer) ZIPPY_ADJOURN },
1058 { "zippyAbort", "zippyAbort", XtRBoolean,
1059 sizeof(Boolean), XtOffset(AppDataPtr, zippyAbort),
1060 XtRImmediate, (XtPointer) ZIPPY_ABORT },
1061 { "zippyVariants", "zippyVariants", XtRString, sizeof(String),
1062 XtOffset(AppDataPtr, zippyVariants), XtRString, ZIPPY_VARIANTS },
1063 { "zippyMaxGames", "zippyMaxGames", XtRInt, sizeof(int),
1064 XtOffset(AppDataPtr, zippyMaxGames), XtRImmediate,
1065 (XtPointer) ZIPPY_MAX_GAMES },
1066 { "zippyReplayTimeout", "zippyReplayTimeout", XtRInt, sizeof(int),
1067 XtOffset(AppDataPtr, zippyReplayTimeout), XtRImmediate,
1068 (XtPointer) ZIPPY_REPLAY_TIMEOUT },
1069 { "zippyShortGame", "zippyShortGame", XtRInt, sizeof(int),
1070 XtOffset(AppDataPtr, zippyShortGame), XtRImmediate,
1073 { "flashCount", "flashCount", XtRInt, sizeof(int),
1074 XtOffset(AppDataPtr, flashCount), XtRImmediate,
1075 (XtPointer) FLASH_COUNT },
1076 { "flashRate", "flashRate", XtRInt, sizeof(int),
1077 XtOffset(AppDataPtr, flashRate), XtRImmediate,
1078 (XtPointer) FLASH_RATE },
1079 { "pixmapDirectory", "pixmapDirectory", XtRString,
1080 sizeof(String), XtOffset(AppDataPtr, pixmapDirectory),
1082 { "msLoginDelay", "msLoginDelay", XtRInt, sizeof(int),
1083 XtOffset(AppDataPtr, msLoginDelay), XtRImmediate,
1084 (XtPointer) MS_LOGIN_DELAY },
1085 { "colorizeMessages", "colorizeMessages", XtRBoolean,
1086 sizeof(Boolean), XtOffset(AppDataPtr, colorize),
1087 XtRImmediate, (XtPointer) False },
1088 { "colorShout", "colorShout", XtRString,
1089 sizeof(String), XtOffset(AppDataPtr, colorShout),
1090 XtRString, COLOR_SHOUT },
1091 { "colorSShout", "colorSShout", XtRString,
1092 sizeof(String), XtOffset(AppDataPtr, colorSShout),
1093 XtRString, COLOR_SSHOUT },
1094 { "colorChannel1", "colorChannel1", XtRString,
1095 sizeof(String), XtOffset(AppDataPtr, colorChannel1),
1096 XtRString, COLOR_CHANNEL1 },
1097 { "colorChannel", "colorChannel", XtRString,
1098 sizeof(String), XtOffset(AppDataPtr, colorChannel),
1099 XtRString, COLOR_CHANNEL },
1100 { "colorKibitz", "colorKibitz", XtRString,
1101 sizeof(String), XtOffset(AppDataPtr, colorKibitz),
1102 XtRString, COLOR_KIBITZ },
1103 { "colorTell", "colorTell", XtRString,
1104 sizeof(String), XtOffset(AppDataPtr, colorTell),
1105 XtRString, COLOR_TELL },
1106 { "colorChallenge", "colorChallenge", XtRString,
1107 sizeof(String), XtOffset(AppDataPtr, colorChallenge),
1108 XtRString, COLOR_CHALLENGE },
1109 { "colorRequest", "colorRequest", XtRString,
1110 sizeof(String), XtOffset(AppDataPtr, colorRequest),
1111 XtRString, COLOR_REQUEST },
1112 { "colorSeek", "colorSeek", XtRString,
1113 sizeof(String), XtOffset(AppDataPtr, colorSeek),
1114 XtRString, COLOR_SEEK },
1115 { "colorNormal", "colorNormal", XtRString,
1116 sizeof(String), XtOffset(AppDataPtr, colorNormal),
1117 XtRString, COLOR_NORMAL },
1118 { "soundProgram", "soundProgram", XtRString,
1119 sizeof(String), XtOffset(AppDataPtr, soundProgram),
1120 XtRString, "play" },
1121 { "soundShout", "soundShout", XtRString,
1122 sizeof(String), XtOffset(AppDataPtr, soundShout),
1124 { "soundSShout", "soundSShout", XtRString,
1125 sizeof(String), XtOffset(AppDataPtr, soundSShout),
1127 { "soundChannel1", "soundChannel1", XtRString,
1128 sizeof(String), XtOffset(AppDataPtr, soundChannel1),
1130 { "soundChannel", "soundChannel", XtRString,
1131 sizeof(String), XtOffset(AppDataPtr, soundChannel),
1133 { "soundKibitz", "soundKibitz", XtRString,
1134 sizeof(String), XtOffset(AppDataPtr, soundKibitz),
1136 { "soundTell", "soundTell", XtRString,
1137 sizeof(String), XtOffset(AppDataPtr, soundTell),
1139 { "soundChallenge", "soundChallenge", XtRString,
1140 sizeof(String), XtOffset(AppDataPtr, soundChallenge),
1142 { "soundRequest", "soundRequest", XtRString,
1143 sizeof(String), XtOffset(AppDataPtr, soundRequest),
1145 { "soundSeek", "soundSeek", XtRString,
1146 sizeof(String), XtOffset(AppDataPtr, soundSeek),
1148 { "soundMove", "soundMove", XtRString,
1149 sizeof(String), XtOffset(AppDataPtr, soundMove),
1151 { "soundIcsWin", "soundIcsWin", XtRString,
1152 sizeof(String), XtOffset(AppDataPtr, soundIcsWin),
1154 { "soundIcsLoss", "soundIcsLoss", XtRString,
1155 sizeof(String), XtOffset(AppDataPtr, soundIcsLoss),
1157 { "soundIcsDraw", "soundIcsDraw", XtRString,
1158 sizeof(String), XtOffset(AppDataPtr, soundIcsDraw),
1160 { "soundIcsUnfinished", "soundIcsUnfinished", XtRString,
1161 sizeof(String), XtOffset(AppDataPtr, soundIcsUnfinished),
1163 { "soundIcsAlarm", "soundIcsAlarm", XtRString,
1164 sizeof(String), XtOffset(AppDataPtr, soundIcsAlarm),
1166 { "reuseFirst", "reuseFirst", XtRBoolean,
1167 sizeof(Boolean), XtOffset(AppDataPtr, reuseFirst),
1168 XtRImmediate, (XtPointer) True },
1169 { "reuseSecond", "reuseSecond", XtRBoolean,
1170 sizeof(Boolean), XtOffset(AppDataPtr, reuseSecond),
1171 XtRImmediate, (XtPointer) True },
1172 { "animateDragging", "animateDragging", XtRBoolean,
1173 sizeof(Boolean), XtOffset(AppDataPtr, animateDragging),
1174 XtRImmediate, (XtPointer) True },
1175 { "animateMoving", "animateMoving", XtRBoolean,
1176 sizeof(Boolean), XtOffset(AppDataPtr, animate),
1177 XtRImmediate, (XtPointer) True },
1178 { "animateSpeed", "animateSpeed", XtRInt,
1179 sizeof(int), XtOffset(AppDataPtr, animSpeed),
1180 XtRImmediate, (XtPointer)10 },
1181 { "popupExitMessage", "popupExitMessage", XtRBoolean,
1182 sizeof(Boolean), XtOffset(AppDataPtr, popupExitMessage),
1183 XtRImmediate, (XtPointer) True },
1184 { "popupMoveErrors", "popupMoveErrors", XtRBoolean,
1185 sizeof(Boolean), XtOffset(AppDataPtr, popupMoveErrors),
1186 XtRImmediate, (XtPointer) False },
1187 { "fontSizeTolerance", "fontSizeTolerance", XtRInt,
1188 sizeof(int), XtOffset(AppDataPtr, fontSizeTolerance),
1189 XtRImmediate, (XtPointer)4 },
1190 { "initialMode", "initialMode", XtRString,
1191 sizeof(String), XtOffset(AppDataPtr, initialMode),
1192 XtRImmediate, (XtPointer) "" },
1193 { "variant", "variant", XtRString,
1194 sizeof(String), XtOffset(AppDataPtr, variant),
1195 XtRImmediate, (XtPointer) "normal" },
1196 { "firstProtocolVersion", "firstProtocolVersion", XtRInt,
1197 sizeof(int), XtOffset(AppDataPtr, firstProtocolVersion),
1198 XtRImmediate, (XtPointer)PROTOVER },
1199 { "secondProtocolVersion", "secondProtocolVersion", XtRInt,
1200 sizeof(int), XtOffset(AppDataPtr, secondProtocolVersion),
1201 XtRImmediate, (XtPointer)PROTOVER },
1202 { "showButtonBar", "showButtonBar", XtRBoolean,
1203 sizeof(Boolean), XtOffset(AppDataPtr, showButtonBar),
1204 XtRImmediate, (XtPointer) True },
1205 { "lowTimeWarningColor", "lowTimeWarningColor", XtRString,
1206 sizeof(String), XtOffset(AppDataPtr, lowTimeWarningColor),
1207 XtRString, COLOR_LOWTIMEWARNING },
1208 { "lowTimeWarning", "lowTimeWarning", XtRBoolean,
1209 sizeof(Boolean), XtOffset(AppDataPtr, lowTimeWarning),
1210 XtRImmediate, (XtPointer) False },
1211 {"icsEngineAnalyze", "icsEngineAnalyze", XtRBoolean, /* [DM] icsEngineAnalyze */
1212 sizeof(Boolean), XtOffset(AppDataPtr, icsEngineAnalyze),
1213 XtRImmediate, (XtPointer) False },
1214 { "firstScoreAbs", "firstScoreAbs", XtRBoolean,
1215 sizeof(Boolean), XtOffset(AppDataPtr, firstScoreIsAbsolute),
1216 XtRImmediate, (XtPointer) False },
1217 { "secondScoreAbs", "secondScoreAbs", XtRBoolean,
1218 sizeof(Boolean), XtOffset(AppDataPtr, secondScoreIsAbsolute),
1219 XtRImmediate, (XtPointer) False },
1220 { "pgnExtendedInfo", "pgnExtendedInfo", XtRBoolean,
1221 sizeof(Boolean), XtOffset(AppDataPtr, saveExtendedInfoInPGN),
1222 XtRImmediate, (XtPointer) False },
1223 { "hideThinkingFromHuman", "hideThinkingFromHuman", XtRBoolean,
1224 sizeof(Boolean), XtOffset(AppDataPtr, hideThinkingFromHuman),
1225 XtRImmediate, (XtPointer) True },
1226 { "adjudicateLossThreshold", "adjudicateLossThreshold", XtRInt,
1227 sizeof(int), XtOffset(AppDataPtr, adjudicateLossThreshold),
1228 XtRImmediate, (XtPointer) 0},
1229 { "adjudicateDrawMoves", "adjudicateDrawMoves", XtRInt,
1230 sizeof(int), XtOffset(AppDataPtr, adjudicateDrawMoves),
1231 XtRImmediate, (XtPointer) 0},
1232 { "pgnEventHeader", "pgnEventHeader", XtRString,
1233 sizeof(String), XtOffset(AppDataPtr, pgnEventHeader),
1234 XtRImmediate, (XtPointer) "Computer Chess Game" },
1235 { "defaultFrcPosition", "defaultFrcPositon", XtRInt,
1236 sizeof(int), XtOffset(AppDataPtr, defaultFrcPosition),
1237 XtRImmediate, (XtPointer) -1},
1238 { "gameListTags", "gameListTags", XtRString,
1239 sizeof(String), XtOffset(AppDataPtr, gameListTags),
1240 XtRImmediate, (XtPointer) GLT_DEFAULT_TAGS },
1242 // [HGM] 4.3.xx options
1243 { "boardWidth", "boardWidth", XtRInt,
1244 sizeof(int), XtOffset(AppDataPtr, NrFiles),
1245 XtRImmediate, (XtPointer) -1},
1246 { "boardHeight", "boardHeight", XtRInt,
1247 sizeof(int), XtOffset(AppDataPtr, NrRanks),
1248 XtRImmediate, (XtPointer) -1},
1249 { "matchPause", "matchPause", XtRInt,
1250 sizeof(int), XtOffset(AppDataPtr, matchPause),
1251 XtRImmediate, (XtPointer) 10000},
1252 { "holdingsSize", "holdingsSize", XtRInt,
1253 sizeof(int), XtOffset(AppDataPtr, holdingsSize),
1254 XtRImmediate, (XtPointer) -1},
1255 { "flipBlack", "flipBlack", XtRBoolean,
1256 sizeof(Boolean), XtOffset(AppDataPtr, upsideDown),
1257 XtRImmediate, (XtPointer) False},
1258 { "allWhite", "allWhite", XtRBoolean,
1259 sizeof(Boolean), XtOffset(AppDataPtr, allWhite),
1260 XtRImmediate, (XtPointer) False},
1261 { "pieceToCharTable", "pieceToCharTable", XtRString,
1262 sizeof(String), XtOffset(AppDataPtr, pieceToCharTable),
1263 XtRImmediate, (XtPointer) 0},
1264 { "alphaRank", "alphaRank", XtRBoolean,
1265 sizeof(Boolean), XtOffset(AppDataPtr, alphaRank),
1266 XtRImmediate, (XtPointer) False},
1267 { "testClaims", "testClaims", XtRBoolean,
1268 sizeof(Boolean), XtOffset(AppDataPtr, testClaims),
1269 XtRImmediate, (XtPointer) True},
1270 { "checkMates", "checkMates", XtRBoolean,
1271 sizeof(Boolean), XtOffset(AppDataPtr, checkMates),
1272 XtRImmediate, (XtPointer) True},
1273 { "materialDraws", "materialDraws", XtRBoolean,
1274 sizeof(Boolean), XtOffset(AppDataPtr, materialDraws),
1275 XtRImmediate, (XtPointer) True},
1276 { "trivialDraws", "trivialDraws", XtRBoolean,
1277 sizeof(Boolean), XtOffset(AppDataPtr, trivialDraws),
1278 XtRImmediate, (XtPointer) False},
1279 { "ruleMoves", "ruleMoves", XtRInt,
1280 sizeof(int), XtOffset(AppDataPtr, ruleMoves),
1281 XtRImmediate, (XtPointer) 51},
1282 { "repeatsToDraw", "repeatsToDraw", XtRInt,
1283 sizeof(int), XtOffset(AppDataPtr, drawRepeats),
1284 XtRImmediate, (XtPointer) 6},
1285 { "engineDebugOutput", "engineDebugOutput", XtRInt,
1286 sizeof(int), XtOffset(AppDataPtr, engineComments),
1287 XtRImmediate, (XtPointer) 1},
1288 { "userName", "userName", XtRString,
1289 sizeof(int), XtOffset(AppDataPtr, userName),
1290 XtRImmediate, (XtPointer) 0},
1291 { "autoKibitz", "autoKibitz", XtRBoolean,
1292 sizeof(Boolean), XtOffset(AppDataPtr, autoKibitz),
1293 XtRImmediate, (XtPointer) False},
1294 { "firstTimeOdds", "firstTimeOdds", XtRInt,
1295 sizeof(int), XtOffset(AppDataPtr, firstTimeOdds),
1296 XtRImmediate, (XtPointer) 1},
1297 { "secondTimeOdds", "secondTimeOdds", XtRInt,
1298 sizeof(int), XtOffset(AppDataPtr, secondTimeOdds),
1299 XtRImmediate, (XtPointer) 1},
1300 { "timeOddsMode", "timeOddsMode", XtRInt,
1301 sizeof(int), XtOffset(AppDataPtr, timeOddsMode),
1302 XtRImmediate, (XtPointer) 0},
1303 { "firstAccumulateTC", "firstAccumulateTC", XtRInt,
1304 sizeof(int), XtOffset(AppDataPtr, firstAccumulateTC),
1305 XtRImmediate, (XtPointer) 1},
1306 { "secondAccumulateTC", "secondAccumulateTC", XtRInt,
1307 sizeof(int), XtOffset(AppDataPtr, secondAccumulateTC),
1308 XtRImmediate, (XtPointer) 1},
1309 { "firstNPS", "firstNPS", XtRInt,
1310 sizeof(int), XtOffset(AppDataPtr, firstNPS),
1311 XtRImmediate, (XtPointer) -1},
1312 { "secondNPS", "secondNPS", XtRInt,
1313 sizeof(int), XtOffset(AppDataPtr, secondNPS),
1314 XtRImmediate, (XtPointer) -1},
1315 { "serverMoves", "serverMoves", XtRString,
1316 sizeof(String), XtOffset(AppDataPtr, serverMovesName),
1317 XtRImmediate, (XtPointer) 0},
1318 { "serverPause", "serverPause", XtRInt,
1319 sizeof(int), XtOffset(AppDataPtr, serverPause),
1320 XtRImmediate, (XtPointer) 0},
1321 { "suppressLoadMoves", "suppressLoadMoves", XtRBoolean,
1322 sizeof(Boolean), XtOffset(AppDataPtr, suppressLoadMoves),
1323 XtRImmediate, (XtPointer) False},
1324 { "userName", "userName", XtRString,
1325 sizeof(String), XtOffset(AppDataPtr, userName),
1326 XtRImmediate, (XtPointer) 0},
1327 { "egtFormats", "egtFormats", XtRString,
1328 sizeof(String), XtOffset(AppDataPtr, egtFormats),
1329 XtRImmediate, (XtPointer) 0},
1330 { "rewindIndex", "rewindIndex", XtRInt,
1331 sizeof(int), XtOffset(AppDataPtr, rewindIndex),
1332 XtRImmediate, (XtPointer) 0},
1333 { "sameColorGames", "sameColorGames", XtRInt,
1334 sizeof(int), XtOffset(AppDataPtr, sameColorGames),
1335 XtRImmediate, (XtPointer) 0},
1336 { "smpCores", "smpCores", XtRInt,
1337 sizeof(int), XtOffset(AppDataPtr, smpCores),
1338 XtRImmediate, (XtPointer) 1},
1339 { "niceEngines", "niceEngines", XtRInt,
1340 sizeof(int), XtOffset(AppDataPtr, niceEngines),
1341 XtRImmediate, (XtPointer) 0},
1342 { "nameOfDebugFile", "nameOfDebugFile", XtRString,
1343 sizeof(String), XtOffset(AppDataPtr, nameOfDebugFile),
1344 XtRImmediate, (XtPointer) "xboard.debug"},
1345 { "engineDebugOutput", "engineDebugOutput", XtRInt,
1346 sizeof(int), XtOffset(AppDataPtr, engineComments),
1347 XtRImmediate, (XtPointer) 1},
1348 { "noGUI", "noGUI", XtRBoolean,
1349 sizeof(Boolean), XtOffset(AppDataPtr, noGUI),
1350 XtRImmediate, (XtPointer) 0},
1351 { "firstOptions", "firstOptions", XtRString,
1352 sizeof(String), XtOffset(AppDataPtr, firstOptions),
1353 XtRImmediate, (XtPointer) "" },
1354 { "secondOptions", "secondOptions", XtRString,
1355 sizeof(String), XtOffset(AppDataPtr, secondOptions),
1356 XtRImmediate, (XtPointer) "" },
1357 { "firstNeedsNoncompliantFEN", "firstNeedsNoncompliantFEN", XtRString,
1358 sizeof(String), XtOffset(AppDataPtr, fenOverride1),
1359 XtRImmediate, (XtPointer) 0 },
1360 { "secondNeedsNoncompliantFEN", "secondNeedsNoncompliantFEN", XtRString,
1361 sizeof(String), XtOffset(AppDataPtr, fenOverride2),
1362 XtRImmediate, (XtPointer) 0 },
1364 // [HGM] Winboard_x UCI options
1365 { "firstIsUCI", "firstIsUCI", XtRBoolean,
1366 sizeof(Boolean), XtOffset(AppDataPtr, firstIsUCI),
1367 XtRImmediate, (XtPointer) False},
1368 { "secondIsUCI", "secondIsUCI", XtRBoolean,
1369 sizeof(Boolean), XtOffset(AppDataPtr, secondIsUCI),
1370 XtRImmediate, (XtPointer) False},
1371 { "firstHasOwnBookUCI", "firstHasOwnBookUCI", XtRBoolean,
1372 sizeof(Boolean), XtOffset(AppDataPtr, firstHasOwnBookUCI),
1373 XtRImmediate, (XtPointer) True},
1374 { "secondHasOwnBookUCI", "secondHasOwnBookUCI", XtRBoolean,
1375 sizeof(Boolean), XtOffset(AppDataPtr, secondHasOwnBookUCI),
1376 XtRImmediate, (XtPointer) True},
1377 { "usePolyglotBook", "usePolyglotBook", XtRBoolean,
1378 sizeof(Boolean), XtOffset(AppDataPtr, usePolyglotBook),
1379 XtRImmediate, (XtPointer) False},
1380 { "defaultHashSize", "defaultHashSize", XtRInt,
1381 sizeof(int), XtOffset(AppDataPtr, defaultHashSize),
1382 XtRImmediate, (XtPointer) 64},
1383 { "defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XtRInt,
1384 sizeof(int), XtOffset(AppDataPtr, defaultCacheSizeEGTB),
1385 XtRImmediate, (XtPointer) 4},
1386 { "polyglotDir", "polyglotDir", XtRString,
1387 sizeof(String), XtOffset(AppDataPtr, polyglotDir),
1388 XtRImmediate, (XtPointer) "." },
1389 { "polyglotBook", "polyglotBook", XtRString,
1390 sizeof(String), XtOffset(AppDataPtr, polyglotBook),
1391 XtRImmediate, (XtPointer) "" },
1392 { "defaultPathEGTB", "defaultPathEGTB", XtRString,
1393 sizeof(String), XtOffset(AppDataPtr, defaultPathEGTB),
1394 XtRImmediate, (XtPointer) "/usr/local/share/egtb"},
1395 { "delayBeforeQuit", "delayBeforeQuit", XtRInt,
1396 sizeof(int), XtOffset(AppDataPtr, delayBeforeQuit),
1397 XtRImmediate, (XtPointer) 0},
1398 { "delayAfterQuit", "delayAfterQuit", XtRInt,
1399 sizeof(int), XtOffset(AppDataPtr, delayAfterQuit),
1400 XtRImmediate, (XtPointer) 0},
1401 { "keepAlive", "keepAlive", XtRInt,
1402 sizeof(int), XtOffset(AppDataPtr, keepAlive),
1403 XtRImmediate, (XtPointer) 0},
1404 { "forceIllegalMoves", "forceIllegalMoves", XtRBoolean,
1405 sizeof(Boolean), XtOffset(AppDataPtr, forceIllegal),
1406 XtRImmediate, (XtPointer) False},
1409 XrmOptionDescRec shellOptions[] = {
1410 { "-whitePieceColor", "whitePieceColor", XrmoptionSepArg, NULL },
1411 { "-blackPieceColor", "blackPieceColor", XrmoptionSepArg, NULL },
1412 { "-lightSquareColor", "lightSquareColor", XrmoptionSepArg, NULL },
1413 { "-darkSquareColor", "darkSquareColor", XrmoptionSepArg, NULL },
1414 { "-highlightSquareColor", "highlightSquareColor", XrmoptionSepArg, NULL },
1415 { "-premoveHighlightColor", "premoveHighlightColor", XrmoptionSepArg,NULL},
1416 { "-movesPerSession", "movesPerSession", XrmoptionSepArg, NULL },
1417 { "-mps", "movesPerSession", XrmoptionSepArg, NULL },
1418 { "-timeIncrement", "timeIncrement", XrmoptionSepArg, NULL },
1419 { "-inc", "timeIncrement", XrmoptionSepArg, NULL },
1420 { "-initString", "initString", XrmoptionSepArg, NULL },
1421 { "-firstInitString", "initString", XrmoptionSepArg, NULL },
1422 { "-secondInitString", "secondInitString", XrmoptionSepArg, NULL },
1423 { "-firstComputerString", "firstComputerString", XrmoptionSepArg, NULL },
1424 { "-secondComputerString", "secondComputerString", XrmoptionSepArg, NULL },
1425 { "-firstChessProgram", "firstChessProgram", XrmoptionSepArg, NULL },
1426 { "-fcp", "firstChessProgram", XrmoptionSepArg, NULL },
1427 { "-secondChessProgram", "secondChessProgram", XrmoptionSepArg, NULL },
1428 { "-scp", "secondChessProgram", XrmoptionSepArg, NULL },
1429 { "-firstPlaysBlack", "firstPlaysBlack", XrmoptionSepArg, NULL },
1430 { "-fb", "firstPlaysBlack", XrmoptionNoArg, "True" },
1431 { "-xfb", "firstPlaysBlack", XrmoptionNoArg, "False" },
1432 { "-noChessProgram", "noChessProgram", XrmoptionSepArg, NULL },
1433 { "-ncp", "noChessProgram", XrmoptionNoArg, "True" },
1434 { "-xncp", "noChessProgram", XrmoptionNoArg, "False" },
1435 { "-firstHost", "firstHost", XrmoptionSepArg, NULL },
1436 { "-fh", "firstHost", XrmoptionSepArg, NULL },
1437 { "-secondHost", "secondHost", XrmoptionSepArg, NULL },
1438 { "-sh", "secondHost", XrmoptionSepArg, NULL },
1439 { "-firstDirectory", "firstDirectory", XrmoptionSepArg, NULL },
1440 { "-fd", "firstDirectory", XrmoptionSepArg, NULL },
1441 { "-secondDirectory", "secondDirectory", XrmoptionSepArg, NULL },
1442 { "-sd", "secondDirectory", XrmoptionSepArg, NULL },
1443 { "-bitmapDirectory", "bitmapDirectory", XrmoptionSepArg, NULL },
1444 { "-bm", "bitmapDirectory", XrmoptionSepArg, NULL },
1445 { "-remoteShell", "remoteShell", XrmoptionSepArg, NULL },
1446 { "-rsh", "remoteShell", XrmoptionSepArg, NULL },
1447 { "-remoteUser", "remoteUser", XrmoptionSepArg, NULL },
1448 { "-ruser", "remoteUser", XrmoptionSepArg, NULL },
1449 { "-timeDelay", "timeDelay", XrmoptionSepArg, NULL },
1450 { "-td", "timeDelay", XrmoptionSepArg, NULL },
1451 { "-timeControl", "timeControl", XrmoptionSepArg, NULL },
1452 { "-tc", "timeControl", XrmoptionSepArg, NULL },
1453 { "-internetChessServerMode", "internetChessServerMode",
1454 XrmoptionSepArg, NULL },
1455 { "-ics", "internetChessServerMode", XrmoptionNoArg, "True" },
1456 { "-xics", "internetChessServerMode", XrmoptionNoArg, "False" },
1457 { "-internetChessServerHost", "internetChessServerHost",
1458 XrmoptionSepArg, NULL },
1459 { "-icshost", "internetChessServerHost", XrmoptionSepArg, NULL },
1460 { "-internetChessServerPort", "internetChessServerPort",
1461 XrmoptionSepArg, NULL },
1462 { "-icsport", "internetChessServerPort", XrmoptionSepArg, NULL },
1463 { "-internetChessServerCommPort", "internetChessServerCommPort",
1464 XrmoptionSepArg, NULL },
1465 { "-icscomm", "internetChessServerCommPort", XrmoptionSepArg, NULL },
1466 { "-internetChessServerLogonScript", "internetChessServerLogonScript",
1467 XrmoptionSepArg, NULL },
1468 { "-icslogon", "internetChessServerLogonScript", XrmoptionSepArg, NULL },
1469 { "-internetChessServerHelper", "internetChessServerHelper",
1470 XrmoptionSepArg, NULL },
1471 { "-icshelper", "internetChessServerHelper", XrmoptionSepArg, NULL },
1472 { "-internetChessServerInputBox", "internetChessServerInputBox",
1473 XrmoptionSepArg, NULL },
1474 { "-icsinput", "internetChessServerInputBox", XrmoptionNoArg, "True" },
1475 { "-xicsinput", "internetChessServerInputBox", XrmoptionNoArg, "False" },
1476 { "-icsAlarm", "icsAlarm", XrmoptionSepArg, NULL },
1477 { "-alarm", "icsAlarm", XrmoptionNoArg, "True" },
1478 { "-xalarm", "icsAlarm", XrmoptionNoArg, "False" },
1479 { "-icsAlarmTime", "icsAlarmTime", XrmoptionSepArg, NULL },
1480 { "-useTelnet", "useTelnet", XrmoptionSepArg, NULL },
1481 { "-telnet", "useTelnet", XrmoptionNoArg, "True" },
1482 { "-xtelnet", "useTelnet", XrmoptionNoArg, "False" },
1483 { "-telnetProgram", "telnetProgram", XrmoptionSepArg, NULL },
1484 { "-gateway", "gateway", XrmoptionSepArg, NULL },
1485 { "-loadGameFile", "loadGameFile", XrmoptionSepArg, NULL },
1486 { "-lgf", "loadGameFile", XrmoptionSepArg, NULL },
1487 { "-loadGameIndex", "loadGameIndex", XrmoptionSepArg, NULL },
1488 { "-lgi", "loadGameIndex", XrmoptionSepArg, NULL },
1489 { "-saveGameFile", "saveGameFile", XrmoptionSepArg, NULL },
1490 { "-sgf", "saveGameFile", XrmoptionSepArg, NULL },
1491 { "-autoSaveGames", "autoSaveGames", XrmoptionSepArg, NULL },
1492 { "-autosave", "autoSaveGames", XrmoptionNoArg, "True" },
1493 { "-xautosave", "autoSaveGames", XrmoptionNoArg, "False" },
1494 { "-autoRaiseBoard", "autoRaiseBoard", XrmoptionSepArg, NULL },
1495 { "-autoraise", "autoRaiseBoard", XrmoptionNoArg, "True" },
1496 { "-xautoraise", "autoRaiseBoard", XrmoptionNoArg, "False" },
1497 { "-blindfold", "blindfold", XrmoptionSepArg, NULL },
1498 { "-blind", "blindfold", XrmoptionNoArg, "True" },
1499 { "-xblind", "blindfold", XrmoptionNoArg, "False" },
1500 { "-loadPositionFile", "loadPositionFile", XrmoptionSepArg, NULL },
1501 { "-lpf", "loadPositionFile", XrmoptionSepArg, NULL },
1502 { "-loadPositionIndex", "loadPositionIndex", XrmoptionSepArg, NULL },
1503 { "-lpi", "loadPositionIndex", XrmoptionSepArg, NULL },
1504 { "-savePositionFile", "savePositionFile", XrmoptionSepArg, NULL },
1505 { "-spf", "savePositionFile", XrmoptionSepArg, NULL },
1506 { "-matchMode", "matchMode", XrmoptionSepArg, NULL },
1507 { "-mm", "matchMode", XrmoptionNoArg, "True" },
1508 { "-xmm", "matchMode", XrmoptionNoArg, "False" },
1509 { "-matchGames", "matchGames", XrmoptionSepArg, NULL },
1510 { "-mg", "matchGames", XrmoptionSepArg, NULL },
1511 { "-monoMode", "monoMode", XrmoptionSepArg, NULL },
1512 { "-mono", "monoMode", XrmoptionNoArg, "True" },
1513 { "-xmono", "monoMode", XrmoptionNoArg, "False" },
1514 { "-debugMode", "debugMode", XrmoptionSepArg, NULL },
1515 { "-debug", "debugMode", XrmoptionNoArg, "True" },
1516 { "-xdebug", "debugMode", XrmoptionNoArg, "False" },
1517 { "-clockMode", "clockMode", XrmoptionSepArg, NULL },
1518 { "-clock", "clockMode", XrmoptionNoArg, "True" },
1519 { "-xclock", "clockMode", XrmoptionNoArg, "False" },
1520 { "-boardSize", "boardSize", XrmoptionSepArg, NULL },
1521 { "-size", "boardSize", XrmoptionSepArg, NULL },
1522 { "-searchTime", "searchTime", XrmoptionSepArg, NULL },
1523 { "-st", "searchTime", XrmoptionSepArg, NULL },
1524 { "-searchDepth", "searchDepth", XrmoptionSepArg, NULL },
1525 { "-depth", "searchDepth", XrmoptionSepArg, NULL },
1526 { "-showCoords", "showCoords", XrmoptionSepArg, NULL },
1527 { "-coords", "showCoords", XrmoptionNoArg, "True" },
1528 { "-xcoords", "showCoords", XrmoptionNoArg, "False" },
1530 { "-showJail", "showJail", XrmoptionSepArg, NULL },
1531 { "-jail", "showJail", XrmoptionNoArg, "1" },
1532 { "-sidejail", "showJail", XrmoptionNoArg, "2" },
1533 { "-xjail", "showJail", XrmoptionNoArg, "0" },
1535 { "-showThinking", "showThinking", XrmoptionSepArg, NULL },
1536 { "-thinking", "showThinking", XrmoptionNoArg, "True" },
1537 { "-xthinking", "showThinking", XrmoptionNoArg, "False" },
1538 { "-ponderNextMove", "ponderNextMove", XrmoptionSepArg, NULL },
1539 { "-ponder", "ponderNextMove", XrmoptionNoArg, "True" },
1540 { "-xponder", "ponderNextMove", XrmoptionNoArg, "False" },
1541 { "-periodicUpdates", "periodicUpdates", XrmoptionSepArg, NULL },
1542 { "-periodic", "periodicUpdates", XrmoptionNoArg, "True" },
1543 { "-xperiodic", "periodicUpdates", XrmoptionNoArg, "False" },
1544 { "-clockFont", "clockFont", XrmoptionSepArg, NULL },
1545 { "-coordFont", "coordFont", XrmoptionSepArg, NULL },
1546 { "-font", "font", XrmoptionSepArg, NULL },
1547 { "-ringBellAfterMoves", "ringBellAfterMoves", XrmoptionSepArg, NULL },
1548 { "-bell", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1549 { "-xbell", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1550 { "-movesound", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1551 { "-xmovesound", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1552 { "-autoCallFlag", "autoCallFlag", XrmoptionSepArg, NULL },
1553 { "-autoflag", "autoCallFlag", XrmoptionNoArg, "True" },
1554 { "-xautoflag", "autoCallFlag", XrmoptionNoArg, "False" },
1555 { "-autoFlipView", "autoFlipView", XrmoptionSepArg, NULL },
1556 { "-autoflip", "autoFlipView", XrmoptionNoArg, "True" },
1557 { "-xautoflip", "autoFlipView", XrmoptionNoArg, "False" },
1558 { "-autoObserve", "autoObserve", XrmoptionSepArg, NULL },
1559 { "-autobs", "autoObserve", XrmoptionNoArg, "True" },
1560 { "-xautobs", "autoObserve", XrmoptionNoArg, "False" },
1561 { "-autoComment", "autoComment", XrmoptionSepArg, NULL },
1562 { "-autocomm", "autoComment", XrmoptionNoArg, "True" },
1563 { "-xautocomm", "autoComment", XrmoptionNoArg, "False" },
1564 { "-getMoveList", "getMoveList", XrmoptionSepArg, NULL },
1565 { "-moves", "getMoveList", XrmoptionNoArg, "True" },
1566 { "-xmoves", "getMoveList", XrmoptionNoArg, "False" },
1568 { "-highlightDragging", "highlightDragging", XrmoptionSepArg, NULL },
1569 { "-highdrag", "highlightDragging", XrmoptionNoArg, "True" },
1570 { "-xhighdrag", "highlightDragging", XrmoptionNoArg, "False" },
1572 { "-highlightLastMove", "highlightLastMove", XrmoptionSepArg, NULL },
1573 { "-highlight", "highlightLastMove", XrmoptionNoArg, "True" },
1574 { "-xhighlight", "highlightLastMove", XrmoptionNoArg, "False" },
1575 { "-premove", "premove", XrmoptionSepArg, NULL },
1576 { "-pre", "premove", XrmoptionNoArg, "True" },
1577 { "-xpre", "premove", XrmoptionNoArg, "False" },
1578 { "-testLegality", "testLegality", XrmoptionSepArg, NULL },
1579 { "-legal", "testLegality", XrmoptionNoArg, "True" },
1580 { "-xlegal", "testLegality", XrmoptionNoArg, "False" },
1581 { "-flipView", "flipView", XrmoptionSepArg, NULL },
1582 { "-flip", "flipView", XrmoptionNoArg, "True" },
1583 { "-xflip", "flipView", XrmoptionNoArg, "False" },
1584 { "-cmail", "cmailGameName", XrmoptionSepArg, NULL },
1585 { "-alwaysPromoteToQueen", "alwaysPromoteToQueen",
1586 XrmoptionSepArg, NULL },
1587 { "-queen", "alwaysPromoteToQueen", XrmoptionNoArg, "True" },
1588 { "-xqueen", "alwaysPromoteToQueen", XrmoptionNoArg, "False" },
1589 { "-oldSaveStyle", "oldSaveStyle", XrmoptionSepArg, NULL },
1590 { "-oldsave", "oldSaveStyle", XrmoptionNoArg, "True" },
1591 { "-xoldsave", "oldSaveStyle", XrmoptionNoArg, "False" },
1592 { "-quietPlay", "quietPlay", XrmoptionSepArg, NULL },
1593 { "-quiet", "quietPlay", XrmoptionNoArg, "True" },
1594 { "-xquiet", "quietPlay", XrmoptionNoArg, "False" },
1595 { "-titleInWindow", "titleInWindow", XrmoptionSepArg, NULL },
1596 { "-title", "titleInWindow", XrmoptionNoArg, "True" },
1597 { "-xtitle", "titleInWindow", XrmoptionNoArg, "False" },
1599 { "-zippyTalk", "zippyTalk", XrmoptionSepArg, NULL },
1600 { "-zt", "zippyTalk", XrmoptionNoArg, "True" },
1601 { "-xzt", "zippyTalk", XrmoptionNoArg, "False" },
1602 { "-zippyPlay", "zippyPlay", XrmoptionSepArg, NULL },
1603 { "-zp", "zippyPlay", XrmoptionNoArg, "True" },
1604 { "-xzp", "zippyPlay", XrmoptionNoArg, "False" },
1605 { "-zippyLines", "zippyLines", XrmoptionSepArg, NULL },
1606 { "-zippyPinhead", "zippyPinhead", XrmoptionSepArg, NULL },
1607 { "-zippyPassword", "zippyPassword", XrmoptionSepArg, NULL },
1608 { "-zippyPassword2", "zippyPassword2", XrmoptionSepArg, NULL },
1609 { "-zippyWrongPassword", "zippyWrongPassword", XrmoptionSepArg, NULL },
1610 { "-zippyAcceptOnly", "zippyAcceptOnly", XrmoptionSepArg, NULL },
1611 { "-zippyUseI", "zippyUseI", XrmoptionSepArg, NULL },
1612 { "-zui", "zippyUseI", XrmoptionNoArg, "True" },
1613 { "-xzui", "zippyUseI", XrmoptionNoArg, "False" },
1614 { "-zippyBughouse", "zippyBughouse", XrmoptionSepArg, NULL },
1615 { "-zippyNoplayCrafty", "zippyNoplayCrafty", XrmoptionSepArg, NULL },
1616 { "-znc", "zippyNoplayCrafty", XrmoptionNoArg, "True" },
1617 { "-xznc", "zippyNoplayCrafty", XrmoptionNoArg, "False" },
1618 { "-zippyGameEnd", "zippyGameEnd", XrmoptionSepArg, NULL },
1619 { "-zippyGameStart", "zippyGameStart", XrmoptionSepArg, NULL },
1620 { "-zippyAdjourn", "zippyAdjourn", XrmoptionSepArg, NULL },
1621 { "-zadj", "zippyAdjourn", XrmoptionNoArg, "True" },
1622 { "-xzadj", "zippyAdjourn", XrmoptionNoArg, "False" },
1623 { "-zippyAbort", "zippyAbort", XrmoptionSepArg, NULL },
1624 { "-zab", "zippyAbort", XrmoptionNoArg, "True" },
1625 { "-xzab", "zippyAbort", XrmoptionNoArg, "False" },
1626 { "-zippyVariants", "zippyVariants", XrmoptionSepArg, NULL },
1627 { "-zippyMaxGames", "zippyMaxGames", XrmoptionSepArg, NULL },
1628 { "-zippyReplayTimeout", "zippyReplayTimeout", XrmoptionSepArg, NULL },
1629 { "-zippyShortGame", "zippyShortGame", XrmoptionSepArg, NULL },
1631 { "-flashCount", "flashCount", XrmoptionSepArg, NULL },
1632 { "-flash", "flashCount", XrmoptionNoArg, "3" },
1633 { "-xflash", "flashCount", XrmoptionNoArg, "0" },
1634 { "-flashRate", "flashRate", XrmoptionSepArg, NULL },
1635 { "-pixmapDirectory", "pixmapDirectory", XrmoptionSepArg, NULL },
1636 { "-msLoginDelay", "msLoginDelay", XrmoptionSepArg, NULL },
1637 { "-pixmap", "pixmapDirectory", XrmoptionSepArg, NULL },
1638 { "-colorizeMessages", "colorizeMessages", XrmoptionSepArg, NULL },
1639 { "-colorize", "colorizeMessages", XrmoptionNoArg, "True" },
1640 { "-xcolorize", "colorizeMessages", XrmoptionNoArg, "False" },
1641 { "-colorShout", "colorShout", XrmoptionSepArg, NULL },
1642 { "-colorSShout", "colorSShout", XrmoptionSepArg, NULL },
1643 { "-colorCShout", "colorSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1644 { "-colorChannel1", "colorChannel1", XrmoptionSepArg, NULL },
1645 { "-colorChannel", "colorChannel", XrmoptionSepArg, NULL },
1646 { "-colorKibitz", "colorKibitz", XrmoptionSepArg, NULL },
1647 { "-colorTell", "colorTell", XrmoptionSepArg, NULL },
1648 { "-colorChallenge", "colorChallenge", XrmoptionSepArg, NULL },
1649 { "-colorRequest", "colorRequest", XrmoptionSepArg, NULL },
1650 { "-colorSeek", "colorSeek", XrmoptionSepArg, NULL },
1651 { "-colorNormal", "colorNormal", XrmoptionSepArg, NULL },
1652 { "-soundProgram", "soundProgram", XrmoptionSepArg, NULL },
1653 { "-soundShout", "soundShout", XrmoptionSepArg, NULL },
1654 { "-soundSShout", "soundSShout", XrmoptionSepArg, NULL },
1655 { "-soundCShout", "soundSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1656 { "-soundChannel1", "soundChannel1", XrmoptionSepArg, NULL },
1657 { "-soundChannel", "soundChannel", XrmoptionSepArg, NULL },
1658 { "-soundKibitz", "soundKibitz", XrmoptionSepArg, NULL },
1659 { "-soundTell", "soundTell", XrmoptionSepArg, NULL },
1660 { "-soundChallenge", "soundChallenge", XrmoptionSepArg, NULL },
1661 { "-soundRequest", "soundRequest", XrmoptionSepArg, NULL },
1662 { "-soundSeek", "soundSeek", XrmoptionSepArg, NULL },
1663 { "-soundMove", "soundMove", XrmoptionSepArg, NULL },
1664 { "-soundIcsWin", "soundIcsWin", XrmoptionSepArg, NULL },
1665 { "-soundIcsLoss", "soundIcsLoss", XrmoptionSepArg, NULL },
1666 { "-soundIcsDraw", "soundIcsDraw", XrmoptionSepArg, NULL },
1667 { "-soundIcsUnfinished", "soundIcsUnfinished", XrmoptionSepArg, NULL },
1668 { "-soundIcsAlarm", "soundIcsAlarm", XrmoptionSepArg, NULL },
1669 { "-reuseFirst", "reuseFirst", XrmoptionSepArg, NULL },
1670 { "-reuseChessPrograms", "reuseFirst", XrmoptionSepArg, NULL }, /*compat*/
1671 { "-reuse", "reuseFirst", XrmoptionNoArg, "True" },
1672 { "-xreuse", "reuseFirst", XrmoptionNoArg, "False" },
1673 { "-reuseSecond", "reuseSecond", XrmoptionSepArg, NULL },
1674 { "-reuse2", "reuseSecond", XrmoptionNoArg, "True" },
1675 { "-xreuse2", "reuseSecond", XrmoptionNoArg, "False" },
1676 { "-animateMoving", "animateMoving", XrmoptionSepArg, NULL },
1677 { "-animate", "animateMoving", XrmoptionNoArg, "True" },
1678 { "-xanimate", "animateMoving", XrmoptionNoArg, "False" },
1679 { "-animateDragging", "animateDragging", XrmoptionSepArg, NULL },
1680 { "-drag", "animateDragging", XrmoptionNoArg, "True" },
1681 { "-xdrag", "animateDragging", XrmoptionNoArg, "False" },
1682 { "-animateSpeed", "animateSpeed", XrmoptionSepArg, NULL },
1683 { "-popupExitMessage", "popupExitMessage", XrmoptionSepArg, NULL },
1684 { "-exit", "popupExitMessage", XrmoptionNoArg, "True" },
1685 { "-xexit", "popupExitMessage", XrmoptionNoArg, "False" },
1686 { "-popupMoveErrors", "popupMoveErrors", XrmoptionSepArg, NULL },
1687 { "-popup", "popupMoveErrors", XrmoptionNoArg, "True" },
1688 { "-xpopup", "popupMoveErrors", XrmoptionNoArg, "False" },
1689 { "-fontSizeTolerance", "fontSizeTolerance", XrmoptionSepArg, NULL },
1690 { "-initialMode", "initialMode", XrmoptionSepArg, NULL },
1691 { "-mode", "initialMode", XrmoptionSepArg, NULL },
1692 { "-variant", "variant", XrmoptionSepArg, NULL },
1693 { "-firstProtocolVersion", "firstProtocolVersion", XrmoptionSepArg, NULL },
1694 { "-secondProtocolVersion","secondProtocolVersion",XrmoptionSepArg, NULL },
1695 { "-showButtonBar", "showButtonBar", XrmoptionSepArg, NULL },
1696 { "-buttons", "showButtonBar", XrmoptionNoArg, "True" },
1697 { "-xbuttons", "showButtonBar", XrmoptionNoArg, "False" },
1698 { "-lowTimeWarningColor", "lowTimeWarningColor", XrmoptionSepArg, NULL },
1699 { "-lowTimeWarning", "lowTimeWarning", XrmoptionSepArg, NULL },
1700 /* [AS,HR] New features */
1701 { "-firstScoreAbs", "firstScoreAbs", XrmoptionSepArg, NULL },
1702 { "-secondScoreAbs", "secondScoreAbs", XrmoptionSepArg, NULL },
1703 { "-pgnExtendedInfo", "pgnExtendedInfo", XrmoptionSepArg, NULL },
1704 { "-hideThinkingFromHuman", "hideThinkingFromHuman", XrmoptionSepArg, NULL },
1705 { "-adjudicateLossThreshold", "adjudicateLossThreshold", XrmoptionSepArg, NULL },
1706 { "-adjudicateDrawMoves", "adjudicateDrawMoves", XrmoptionSepArg, NULL },
1707 { "-pgnEventHeader", "pgnEventHeader", XrmoptionSepArg, NULL },
1708 { "-firstIsUCI", "firstIsUCI", XrmoptionSepArg, NULL },
1709 { "-secondIsUCI", "secondIsUCI", XrmoptionSepArg, NULL },
1710 { "-fUCI", "firstIsUCI", XrmoptionNoArg, "True" },
1711 { "-sUCI", "secondIsUCI", XrmoptionNoArg, "True" },
1712 { "-firstHasOwnBookUCI", "firstHasOwnBookUCI", XrmoptionSepArg, NULL },
1713 { "-secondHasOwnBookUCI", "secondHasOwnBookUCI", XrmoptionSepArg, NULL },
1714 { "-fNoOwnBookUCI", "firstHasOwnBookUCI", XrmoptionNoArg, "False" },
1715 { "-sNoOwnBookUCI", "secondHasOwnBookUCI", XrmoptionNoArg, "False" },
1716 { "-firstXBook", "firstHasOwnBookUCI", XrmoptionNoArg, "False" },
1717 { "-secondXBook", "secondHasOwnBookUCI", XrmoptionNoArg, "False" },
1718 { "-polyglotDir", "polyglotDir", XrmoptionSepArg, NULL },
1719 { "-usePolyglotBook", "usePolyglotBook", XrmoptionSepArg, NULL },
1720 { "-polyglotBook", "polyglotBook", XrmoptionSepArg, NULL },
1721 { "-defaultHashSize", "defaultHashSize", XrmoptionSepArg, NULL },
1722 { "-defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XrmoptionSepArg, NULL },
1723 { "-defaultPathEGTB", "defaultPathEGTB", XrmoptionSepArg, NULL },
1724 { "-defaultFrcPosition", "defaultFrcPosition", XrmoptionSepArg, NULL },
1725 { "-gameListTags", "gameListTags", XrmoptionSepArg, NULL },
1726 // [HGM] I am sure AS added many more options, but we have to fish them out, from the list in winboard.c
1728 /* [HGM,HR] User-selectable board size */
1729 { "-boardWidth", "boardWidth", XrmoptionSepArg, NULL },
1730 { "-boardHeight", "boardHeight", XrmoptionSepArg, NULL },
1731 { "-matchPause", "matchPause", XrmoptionSepArg, NULL },
1733 /* [HGM] new arguments of 4.3.xx. All except first three are back-end options, which should work immediately */
1734 { "-holdingsSize", "holdingsSize", XrmoptionSepArg, NULL }, // requires extensive front-end changes to work
1735 { "-flipBlack", "flipBlack", XrmoptionSepArg, NULL }, // requires front-end changes to work
1736 { "-allWhite", "allWhite", XrmoptionSepArg, NULL }, // requires front-end changes to work
1737 { "-pieceToCharTable", "pieceToCharTable", XrmoptionSepArg, NULL },
1738 { "-alphaRank", "alphaRank", XrmoptionSepArg, NULL },
1739 { "-testClaims", "testClaims", XrmoptionSepArg, NULL },
1740 { "-checkMates", "checkMates", XrmoptionSepArg, NULL },
1741 { "-materialDraws", "materialDraws", XrmoptionSepArg, NULL },
1742 { "-trivialDraws", "trivialDraws", XrmoptionSepArg, NULL },
1743 { "-ruleMoves", "ruleMoves", XrmoptionSepArg, NULL },
1744 { "-repeatsToDraw", "repeatsToDraw", XrmoptionSepArg, NULL },
1745 { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL },
1746 { "-userName", "userName", XrmoptionSepArg, NULL },
1747 { "-autoKibitz", "autoKibitz", XrmoptionNoArg, "True" },
1748 { "-firstTimeOdds", "firstTimeOdds", XrmoptionSepArg, NULL },
1749 { "-secondTimeOdds", "secondTimeOdds", XrmoptionSepArg, NULL },
1750 { "-timeOddsMode", "timeOddsMode", XrmoptionSepArg, NULL },
1751 { "-firstAccumulateTC", "firstAccumulateTC", XrmoptionSepArg, NULL },
1752 { "-secondAccumulateTC", "secondAccumulateTC", XrmoptionSepArg, NULL },
1753 { "-firstNPS", "firstNPS", XrmoptionSepArg, NULL },
1754 { "-secondNPS", "secondNPS", XrmoptionSepArg, NULL },
1755 { "-serverMoves", "serverMoves", XrmoptionSepArg, NULL },
1756 { "-serverPause", "serverPause", XrmoptionSepArg, NULL },
1757 { "-suppressLoadMoves", "suppressLoadMoves", XrmoptionSepArg, NULL },
1758 { "-egtFormats", "egtFormats", XrmoptionSepArg, NULL },
1759 { "-userName", "userName", XrmoptionSepArg, NULL },
1760 { "-smpCores", "smpCores", XrmoptionSepArg, NULL },
1761 { "-sameColorGames", "sameColorGames", XrmoptionSepArg, NULL },
1762 { "-rewindIndex", "rewindIndex", XrmoptionSepArg, NULL },
1763 { "-niceEngines", "niceEngines", XrmoptionSepArg, NULL },
1764 { "-delayBeforeQuit", "delayBeforeQuit", XrmoptionSepArg, NULL },
1765 { "-delayAfterQuit", "delayAfterQuit", XrmoptionSepArg, NULL },
1766 { "-nameOfDebugFile", "nameOfDebugFile", XrmoptionSepArg, NULL },
1767 { "-debugFile", "nameOfDebugFile", XrmoptionSepArg, NULL },
1768 { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL },
1769 { "-noGUI", "noGUI", XrmoptionNoArg, "True" },
1770 { "-firstOptions", "firstOptions", XrmoptionSepArg, NULL },
1771 { "-secondOptions", "secondOptions", XrmoptionSepArg, NULL },
1772 { "-firstNeedsNoncompliantFEN", "firstNeedsNoncompliantFEN", XrmoptionSepArg, NULL },
1773 { "-secondNeedsNoncompliantFEN", "secondNeedsNoncompliantFEN", XrmoptionSepArg, NULL },
1774 { "-keepAlive", "keepAlive", XrmoptionSepArg, NULL },
1775 { "-forceIllegalMoves", "forceIllegalMoves", XrmoptionNoArg, "True" },
1779 XtActionsRec boardActions[] = {
1780 { "HandleUserMove", HandleUserMove },
1781 { "AnimateUserMove", AnimateUserMove },
1782 { "FileNameAction", FileNameAction },
1783 { "AskQuestionProc", AskQuestionProc },
1784 { "AskQuestionReplyAction", AskQuestionReplyAction },
1785 { "PieceMenuPopup", PieceMenuPopup },
1786 // { "WhiteClock", WhiteClock },
1787 // { "BlackClock", BlackClock },
1788 { "Iconify", Iconify },
1789 { "LoadSelectedProc", LoadSelectedProc },
1790 { "LoadPositionProc", LoadPositionProc },
1791 // { "LoadNextPositionProc", LoadNextPositionProc },
1792 // { "LoadPrevPositionProc", LoadPrevPositionProc },
1793 // { "ReloadPositionProc", ReloadPositionProc },
1794 { "CopyPositionProc", CopyPositionProc },
1795 { "PastePositionProc", PastePositionProc },
1796 { "CopyGameProc", CopyGameProc },
1797 { "PasteGameProc", PasteGameProc },
1798 { "SaveGameProc", SaveGameProc },
1799 { "SavePositionProc", SavePositionProc },
1800 { "MailMoveProc", MailMoveProc },
1801 { "ReloadCmailMsgProc", ReloadCmailMsgProc },
1802 // { "MachineWhiteProc", MachineWhiteProc },
1803 // { "MachineBlackProc", MachineBlackProc },
1804 { "AnalysisModeProc", AnalyzeModeProc },
1805 { "AnalyzeFileProc", AnalyzeFileProc },
1806 // { "TwoMachinesProc", TwoMachinesProc },
1807 // { "IcsClientProc", IcsClientProc },
1808 { "EditGameProc", EditGameProc },
1809 { "EditPositionProc", EditPositionProc },
1810 { "TrainingProc", EditPositionProc },
1811 { "EngineOutputProc", EngineOutputProc}, // [HGM] Winboard_x engine-output window
1812 { "ShowGameListProc", ShowGameListProc },
1813 // { "ShowMoveListProc", HistoryShowProc},
1814 { "EditTagsProc", EditCommentProc },
1815 { "EditCommentProc", EditCommentProc },
1816 { "IcsAlarmProc", IcsAlarmProc },
1817 { "IcsInputBoxProc", IcsInputBoxProc },
1818 // { "AcceptProc", AcceptProc },
1819 // { "DeclineProc", DeclineProc },
1820 // { "RematchProc", RematchProc },
1821 // { "CallFlagProc", CallFlagProc },
1822 // { "DrawProc", DrawProc },
1823 // { "AdjournProc", AdjournProc },
1824 // { "AbortProc", AbortProc },
1825 // { "ResignProc", ResignProc },
1826 // { "AdjuWhiteProc", AdjuWhiteProc },
1827 // { "AdjuBlackProc", AdjuBlackProc },
1828 // { "AdjuDrawProc", AdjuDrawProc },
1829 { "EnterKeyProc", EnterKeyProc },
1830 // { "StopObservingProc", StopObservingProc },
1831 // { "StopExaminingProc", StopExaminingProc },
1832 // { "BackwardProc", BackwardProc },
1833 // { "ForwardProc", ForwardProc },
1834 // { "ToStartProc", ToStartProc },
1835 // { "ToEndProc", ToEndProc },
1836 // { "RevertProc", RevertProc },
1837 // { "TruncateGameProc", TruncateGameProc },
1838 // { "MoveNowProc", MoveNowProc },
1839 // { "RetractMoveProc", RetractMoveProc },
1840 { "AlwaysQueenProc", AlwaysQueenProc },
1841 { "AnimateDraggingProc", AnimateDraggingProc },
1842 { "AnimateMovingProc", AnimateMovingProc },
1843 // { "AutoflagProc", AutoflagProc },
1844 // { "AutoflipProc", AutoflipProc },
1845 { "AutobsProc", AutobsProc },
1846 { "AutoraiseProc", AutoraiseProc },
1847 { "AutosaveProc", AutosaveProc },
1848 { "BlindfoldProc", BlindfoldProc },
1849 { "FlashMovesProc", FlashMovesProc },
1850 // { "FlipViewProc", FlipViewProc },
1851 // { "GetMoveListProc", GetMoveListProc },
1853 { "HighlightDraggingProc", HighlightDraggingProc },
1855 { "HighlightLastMoveProc", HighlightLastMoveProc },
1856 { "IcsAlarmProc", IcsAlarmProc },
1857 { "MoveSoundProc", MoveSoundProc },
1858 { "OldSaveStyleProc", OldSaveStyleProc },
1859 { "PeriodicUpdatesProc", PeriodicUpdatesProc },
1860 { "PonderNextMoveProc", PonderNextMoveProc },
1861 { "PopupExitMessageProc", PopupExitMessageProc },
1862 { "PopupMoveErrorsProc", PopupMoveErrorsProc },
1863 { "PremoveProc", PremoveProc },
1864 { "QuietPlayProc", QuietPlayProc },
1865 // { "ShowThinkingProc", ShowThinkingProc },
1866 // { "HideThinkingProc", HideThinkingProc },
1867 { "TestLegalityProc", TestLegalityProc },
1868 // { "InfoProc", InfoProc },
1869 // { "ManProc", ManProc },
1870 // { "HintProc", HintProc },
1871 // { "BookProc", BookProc },
1872 { "AboutGameProc", AboutGameProc },
1873 { "DebugProc", DebugProc },
1874 { "NothingProc", NothingProc },
1875 { "CommentPopDown", (XtActionProc) CommentPopDown },
1876 { "EditCommentPopDown", (XtActionProc) EditCommentPopDown },
1877 { "TagsPopDown", (XtActionProc) TagsPopDown },
1878 { "ErrorPopDown", (XtActionProc) ErrorPopDown },
1879 { "ICSInputBoxPopDown", (XtActionProc) ICSInputBoxPopDown },
1880 { "AnalysisPopDown", (XtActionProc) AnalysisPopDown },
1881 { "FileNamePopDown", (XtActionProc) FileNamePopDown },
1882 { "AskQuestionPopDown", (XtActionProc) AskQuestionPopDown },
1883 { "GameListPopDown", (XtActionProc) GameListPopDown },
1884 { "PromotionPopDown", (XtActionProc) PromotionPopDown },
1885 // { "HistoryPopDown", (XtActionProc) HistoryPopDown },
1886 { "EngineOutputPopDown", (XtActionProc) EngineOutputPopDown },
1887 { "ShufflePopDown", (XtActionProc) ShufflePopDown },
1888 { "EnginePopDown", (XtActionProc) EnginePopDown },
1889 { "UciPopDown", (XtActionProc) UciPopDown },
1890 { "TimeControlPopDown", (XtActionProc) TimeControlPopDown },
1891 { "NewVariantPopDown", (XtActionProc) NewVariantPopDown },
1892 { "SettingsPopDown", (XtActionProc) SettingsPopDown },
1896 char ICSInputTranslations[] =
1897 "<Key>Return: EnterKeyProc() \n";
1899 String xboardResources[] = {
1900 "*fileName*value.translations: #override\\n <Key>Return: FileNameAction()",
1901 "*question*value.translations: #override\\n <Key>Return: AskQuestionReplyAction()",
1902 "*errorpopup*translations: #override\\n <Key>Return: ErrorPopDown()",
1906 static char *cnames[9] = { "black", "red", "green", "yellow", "blue",
1907 "magenta", "cyan", "white" };
1911 TextColors textColors[(int)NColorClasses];
1913 /* String is: "fg, bg, attr". Which is 0, 1, 2 */
1915 parse_color(str, which)
1919 char *p, buf[100], *d;
1922 if (strlen(str) > 99) /* watch bounds on buf */
1927 for (i=0; i<which; ++i) {
1934 /* Could be looking at something like:
1936 .. in which case we want to stop on a comma also */
1937 while (*p && *p != ',' && !isalpha(*p) && !isdigit(*p))
1941 return -1; /* Use default for empty field */
1944 if (which == 2 || isdigit(*p))
1947 while (*p && isalpha(*p))
1952 for (i=0; i<8; ++i) {
1953 if (!StrCaseCmp(buf, cnames[i]))
1954 return which? (i+40) : (i+30);
1956 if (!StrCaseCmp(buf, "default")) return -1;
1958 fprintf(stderr, _("%s: unrecognized color %s\n"), programName, buf);
1963 parse_cpair(cc, str)
1967 if ((textColors[(int)cc].fg=parse_color(str, 0)) == -2) {
1968 fprintf(stderr, _("%s: can't parse foreground color in `%s'\n"),
1973 /* bg and attr are optional */
1974 textColors[(int)cc].bg = parse_color(str, 1);
1975 if ((textColors[(int)cc].attr = parse_color(str, 2)) < 0) {
1976 textColors[(int)cc].attr = 0;
1982 /* Arrange to catch delete-window events */
1983 Atom wm_delete_window;
1985 CatchDeleteWindow(Widget w, String procname)
1988 XSetWMProtocols(xDisplay, XtWindow(w), &wm_delete_window, 1);
1989 snprintf(buf, sizeof(buf), "<Message>WM_PROTOCOLS: %s() \n", procname);
1990 XtAugmentTranslations(w, XtParseTranslationTable(buf));
1996 /* this should raise the board to the top */
1997 gtk_window_present(GTK_WINDOW(GUI_Window));
2001 #define BoardSize int
2002 void InitDrawingSizes(BoardSize boardSize, int flags)
2003 { // [HGM] resize is functional now, but for board format changes only (nr of ranks, files)
2004 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
2006 XtGeometryResult gres;
2009 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2010 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2012 timerWidth = (boardWidth - sep) / 2;
2014 if (appData.titleInWindow)
2019 w = boardWidth - 2*bor;
2023 w = boardWidth - w - sep - 2*bor - 2; // WIDTH_FUDGE
2027 if(!formWidget) return;
2030 * Inhibit shell resizing.
2033 // [HGM] pieces: tailor piece bitmaps to needs of specific variant
2036 for(i=0; i<4; i++) {
2038 for(p=0; p<=(int)WhiteKing; p++)
2039 xpmPieceBitmap[i][p] = xpmPieceBitmap2[i][p]; // defaults
2040 if(gameInfo.variant == VariantShogi) {
2041 xpmPieceBitmap[i][(int)WhiteCannon] = xpmPieceBitmap2[i][(int)WhiteKing+1];
2042 xpmPieceBitmap[i][(int)WhiteNightrider] = xpmPieceBitmap2[i][(int)WhiteKing+2];
2043 xpmPieceBitmap[i][(int)WhiteSilver] = xpmPieceBitmap2[i][(int)WhiteKing+3];
2044 xpmPieceBitmap[i][(int)WhiteGrasshopper] = xpmPieceBitmap2[i][(int)WhiteKing+4];
2045 xpmPieceBitmap[i][(int)WhiteQueen] = xpmPieceBitmap2[i][(int)WhiteLance];
2048 if(gameInfo.variant == VariantGothic) {
2049 xpmPieceBitmap[i][(int)WhiteMarshall] = xpmPieceBitmap2[i][(int)WhiteSilver];
2053 // [HGM] why are thee ximMasks used at all? the ximPieceBitmaps seem to be never used!
2054 for(p=0; p<=(int)WhiteKing; p++)
2055 ximMaskPm[p] = ximMaskPm2[p]; // defaults
2056 if(gameInfo.variant == VariantShogi) {
2057 ximMaskPm[(int)WhiteCannon] = ximMaskPm2[(int)WhiteKing+1];
2058 ximMaskPm[(int)WhiteNightrider] = ximMaskPm2[(int)WhiteKing+2];
2059 ximMaskPm[(int)WhiteSilver] = ximMaskPm2[(int)WhiteKing+3];
2060 ximMaskPm[(int)WhiteGrasshopper] = ximMaskPm2[(int)WhiteKing+4];
2061 ximMaskPm[(int)WhiteQueen] = ximMaskPm2[(int)WhiteLance];
2064 if(gameInfo.variant == VariantGothic) {
2065 ximMaskPm[(int)WhiteMarshall] = ximMaskPm2[(int)WhiteSilver];
2071 for(i=0; i<2; i++) {
2073 for(p=0; p<=(int)WhiteKing; p++)
2074 pieceBitmap[i][p] = pieceBitmap2[i][p]; // defaults
2075 if(gameInfo.variant == VariantShogi) {
2076 pieceBitmap[i][(int)WhiteCannon] = pieceBitmap2[i][(int)WhiteKing+1];
2077 pieceBitmap[i][(int)WhiteNightrider] = pieceBitmap2[i][(int)WhiteKing+2];
2078 pieceBitmap[i][(int)WhiteSilver] = pieceBitmap2[i][(int)WhiteKing+3];
2079 pieceBitmap[i][(int)WhiteGrasshopper] = pieceBitmap2[i][(int)WhiteKing+4];
2080 pieceBitmap[i][(int)WhiteQueen] = pieceBitmap2[i][(int)WhiteLance];
2083 if(gameInfo.variant == VariantGothic) {
2084 pieceBitmap[i][(int)WhiteMarshall] = pieceBitmap2[i][(int)WhiteSilver];
2094 void EscapeExpand(char *p, char *q)
2095 { // [HGM] initstring: routine to shape up string arguments
2096 while(*p++ = *q++) if(p[-1] == '\\')
2098 case 'n': p[-1] = '\n'; break;
2099 case 'r': p[-1] = '\r'; break;
2100 case 't': p[-1] = '\t'; break;
2101 case '\\': p[-1] = '\\'; break;
2102 case 0: *p = 0; return;
2103 default: p[-1] = q[-1]; break;
2112 int i, j, clockFontPxlSize, coordFontPxlSize, fontPxlSize;
2113 XSetWindowAttributes window_attributes;
2115 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
2116 XrmValue vFrom, vTo;
2117 XtGeometryResult gres;
2120 int forceMono = False;
2124 // [HGM] before anything else, expand any indirection files amongst options
2125 char *argvCopy[1000]; // 1000 seems enough
2126 char newArgs[10000]; // holds actual characters
2129 srandom(time(0)); // [HGM] book: make random truly random
2132 for(i=0; i<argc; i++) {
2133 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2134 //fprintf(stderr, "arg %s\n", argv[i]);
2135 if(argv[i][0] != '@') argvCopy[j++] = argv[i]; else {
2137 FILE *f = fopen(argv[i]+1, "rb");
2138 if(f == NULL) { fprintf(stderr, _("ignore %s\n"), argv[i]); continue; } // do not expand non-existing
2139 argvCopy[j++] = newArgs + k; // get ready for first argument from file
2140 while((c = fgetc(f)) != EOF) { // each line of file inserts 1 argument in the list
2142 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2143 newArgs[k++] = 0; // terminate current arg
2144 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2145 argvCopy[j++] = newArgs + k; // get ready for next
2147 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2161 setbuf(stdout, NULL);
2162 setbuf(stderr, NULL);
2165 programName = strrchr(argv[0], '/');
2166 if (programName == NULL)
2167 programName = argv[0];
2172 XtSetLanguageProc(NULL, NULL, NULL);
2173 bindtextdomain(PACKAGE, LOCALEDIR);
2174 textdomain(PACKAGE);
2178 XtAppInitialize(&appContext, "XBoard", shellOptions,
2179 XtNumber(shellOptions),
2180 &argc, argv, xboardResources, NULL, 0);
2183 gtk_init (&argc, &argv);
2185 /* parse glade file to build widgets */
2187 builder = gtk_builder_new ();
2188 gtk_builder_add_from_file (builder, "gtk-interface.xml", NULL);
2190 /* test if everything worked ok */
2192 GUI_Window = GTK_WIDGET (gtk_builder_get_object (builder, "MainWindow"));
2193 if(!GUI_Window) printf("Error: gtk_builder didn't work!\n");
2195 GUI_History = GTK_WIDGET (gtk_builder_get_object (builder, "MoveHistory"));
2196 if(!GUI_History) printf("Error: gtk_builder didn't work!\n");
2198 GUI_Menubar = GTK_WIDGET (gtk_builder_get_object (builder, "MenuBar"));
2199 if(!GUI_Menubar) printf("Error: gtk_builder didn't work!\n");
2200 GUI_Timer = GTK_WIDGET (gtk_builder_get_object (builder, "Timer"));
2201 if(!GUI_Timer) printf("Error: gtk_builder didn't work!\n");
2202 GUI_Buttonbar = GTK_WIDGET (gtk_builder_get_object (builder, "ButtonBar"));
2203 if(!GUI_Buttonbar) printf("Error: gtk_builder didn't work!\n");
2204 GUI_Board = GTK_WIDGET (gtk_builder_get_object (builder, "Board"));
2205 if(!GUI_Board) printf("Error: gtk_builder didn't work!\n");
2207 GUI_Whiteclock = GTK_WIDGET (gtk_builder_get_object (builder, "WhiteClock"));
2208 if(!GUI_Whiteclock) printf("Error: gtk_builder didn't work!\n");
2210 GUI_Blackclock = GTK_WIDGET (gtk_builder_get_object (builder, "BlackClock"));
2211 if(!GUI_Blackclock) printf("Error: gtk_builder didn't work!\n");
2213 LIST_MoveHistory = GTK_LIST_STORE (gtk_builder_get_object (builder, "MoveHistoryStore"));
2214 if(!LIST_MoveHistory) printf("Error: gtk_builder didn't work!\n");
2217 gtk_builder_connect_signals (builder, NULL);
2219 // don't unref the builder, since we use it to get references to widgets
2220 // g_object_unref (G_OBJECT (builder));
2222 /* end parse glade file */
2226 fprintf(stderr, _("%s: unrecognized argument %s\n"),
2227 programName, argv[1]);
2229 fprintf(stderr, "Recognized options:\n");
2230 for(i = 0; i < XtNumber(shellOptions); i++)
2232 /* print first column */
2233 j = fprintf(stderr, " %s%s", shellOptions[i].option,
2234 (shellOptions[i].argKind == XrmoptionSepArg
2236 /* print second column and end line */
2237 if (++i < XtNumber(shellOptions))
2239 fprintf(stderr, "%*c%s%s\n", 40 - j, ' ',
2240 shellOptions[i].option,
2241 (shellOptions[i].argKind == XrmoptionSepArg
2246 fprintf(stderr, "\n");
2253 if (p == NULL) p = "/tmp";
2254 i = strlen(p) + strlen("/.xboardXXXXXx.pgn") + 1;
2255 gameCopyFilename = (char*) malloc(i);
2256 gamePasteFilename = (char*) malloc(i);
2257 snprintf(gameCopyFilename,i, "%s/.xboard%05uc.pgn", p, getpid());
2258 snprintf(gamePasteFilename,i, "%s/.xboard%05up.pgn", p, getpid());
2260 XtGetApplicationResources(shellWidget, (XtPointer) &appData,
2261 clientResources, XtNumber(clientResources),
2264 { // [HGM] initstring: kludge to fix bad bug. expand '\n' characters in init string and computer string.
2265 static char buf[MSG_SIZ];
2266 EscapeExpand(buf, appData.initString);
2267 appData.initString = strdup(buf);
2268 EscapeExpand(buf, appData.secondInitString);
2269 appData.secondInitString = strdup(buf);
2270 EscapeExpand(buf, appData.firstComputerString);
2271 appData.firstComputerString = strdup(buf);
2272 EscapeExpand(buf, appData.secondComputerString);
2273 appData.secondComputerString = strdup(buf);
2276 if ((chessDir = (char *) getenv("CHESSDIR")) == NULL) {
2279 if (chdir(chessDir) != 0) {
2280 fprintf(stderr, _("%s: can't cd to CHESSDIR: "), programName);
2286 if (appData.debugMode && appData.nameOfDebugFile && strcmp(appData.nameOfDebugFile, "stderr")) {
2287 /* [DM] debug info to file [HGM] make the filename a command-line option, and allow it to remain stderr */
2288 if ((debugFP = fopen(appData.nameOfDebugFile, "w")) == NULL) {
2289 printf(_("Failed to open file '%s'\n"), appData.nameOfDebugFile);
2292 setbuf(debugFP, NULL);
2295 /* [HGM,HR] make sure board size is acceptable */
2296 if(appData.NrFiles > BOARD_SIZE ||
2297 appData.NrRanks > BOARD_SIZE )
2298 DisplayFatalError(_("Recompile with BOARD_SIZE > 12, to support this size"), 0, 2);
2301 /* This feature does not work; animation needs a rewrite */
2302 appData.highlightDragging = FALSE;
2306 xDisplay = XtDisplay(shellWidget);
2307 xScreen = DefaultScreen(xDisplay);
2308 wm_delete_window = XInternAtom(xDisplay, "WM_DELETE_WINDOW", True);
2310 gameInfo.variant = StringToVariant(appData.variant);
2311 InitPosition(FALSE);
2313 /* calc board size */
2314 if (isdigit(appData.boardSize[0]))
2316 i = sscanf(appData.boardSize, "%d,%d,%d,%d,%d,%d,%d", &squareSize,
2317 &lineGap, &clockFontPxlSize, &coordFontPxlSize,
2318 &fontPxlSize, &smallLayout, &tinyLayout);
2321 fprintf(stderr, _("%s: bad boardSize syntax %s\n"),
2322 programName, appData.boardSize);
2327 /* Find some defaults; use the nearest known size */
2328 SizeDefaults *szd, *nearest;
2329 int distance = 99999;
2330 nearest = szd = sizeDefaults;
2331 while (szd->name != NULL)
2333 if (abs(szd->squareSize - squareSize) < distance)
2336 distance = abs(szd->squareSize - squareSize);
2337 if (distance == 0) break;
2341 if (i < 2) lineGap = nearest->lineGap;
2342 if (i < 3) clockFontPxlSize = nearest->clockFontPxlSize;
2343 if (i < 4) coordFontPxlSize = nearest->coordFontPxlSize;
2344 if (i < 5) fontPxlSize = nearest->fontPxlSize;
2345 if (i < 6) smallLayout = nearest->smallLayout;
2346 if (i < 7) tinyLayout = nearest->tinyLayout;
2351 SizeDefaults *szd = sizeDefaults;
2352 if (*appData.boardSize == NULLCHAR)
2354 while (DisplayWidth(xDisplay, xScreen) < szd->minScreenSize
2355 || DisplayHeight(xDisplay, xScreen) < szd->minScreenSize)
2359 if (szd->name == NULL) szd--;
2363 while (szd->name != NULL
2364 && StrCaseCmp(szd->name, appData.boardSize) != 0)
2366 if (szd->name == NULL)
2368 fprintf(stderr, _("%s: unrecognized boardSize name %s\n"),
2369 programName, appData.boardSize);
2373 squareSize = szd->squareSize;
2374 lineGap = szd->lineGap;
2375 clockFontPxlSize = szd->clockFontPxlSize;
2376 coordFontPxlSize = szd->coordFontPxlSize;
2377 fontPxlSize = szd->fontPxlSize;
2378 smallLayout = szd->smallLayout;
2379 tinyLayout = szd->tinyLayout;
2381 /* end figuring out what size to use */
2383 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2384 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2387 * Determine what fonts to use.
2389 appData.clockFont = FindFont(appData.clockFont, clockFontPxlSize);
2390 clockFontID = XLoadFont(xDisplay, appData.clockFont);
2391 clockFontStruct = XQueryFont(xDisplay, clockFontID);
2392 appData.coordFont = FindFont(appData.coordFont, coordFontPxlSize);
2393 coordFontID = XLoadFont(xDisplay, appData.coordFont);
2394 coordFontStruct = XQueryFont(xDisplay, coordFontID);
2395 appData.font = FindFont(appData.font, fontPxlSize);
2396 countFontID = XLoadFont(xDisplay, appData.coordFont); // [HGM] holdings
2397 countFontStruct = XQueryFont(xDisplay, countFontID);
2398 // appData.font = FindFont(appData.font, fontPxlSize);
2400 xdb = XtDatabase(xDisplay);
2401 XrmPutStringResource(&xdb, "*font", appData.font);
2404 * Detect if there are not enough colors available and adapt.
2406 if (DefaultDepth(xDisplay, xScreen) <= 2) {
2407 appData.monoMode = True;
2410 if (!appData.monoMode) {
2411 vFrom.addr = (caddr_t) appData.lightSquareColor;
2412 vFrom.size = strlen(appData.lightSquareColor);
2413 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2414 if (vTo.addr == NULL) {
2415 appData.monoMode = True;
2418 lightSquareColor = *(Pixel *) vTo.addr;
2421 if (!appData.monoMode) {
2422 vFrom.addr = (caddr_t) appData.darkSquareColor;
2423 vFrom.size = strlen(appData.darkSquareColor);
2424 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2425 if (vTo.addr == NULL) {
2426 appData.monoMode = True;
2429 darkSquareColor = *(Pixel *) vTo.addr;
2432 if (!appData.monoMode) {
2433 vFrom.addr = (caddr_t) appData.whitePieceColor;
2434 vFrom.size = strlen(appData.whitePieceColor);
2435 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2436 if (vTo.addr == NULL) {
2437 appData.monoMode = True;
2440 whitePieceColor = *(Pixel *) vTo.addr;
2443 if (!appData.monoMode) {
2444 vFrom.addr = (caddr_t) appData.blackPieceColor;
2445 vFrom.size = strlen(appData.blackPieceColor);
2446 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2447 if (vTo.addr == NULL) {
2448 appData.monoMode = True;
2451 blackPieceColor = *(Pixel *) vTo.addr;
2455 if (!appData.monoMode) {
2456 vFrom.addr = (caddr_t) appData.highlightSquareColor;
2457 vFrom.size = strlen(appData.highlightSquareColor);
2458 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2459 if (vTo.addr == NULL) {
2460 appData.monoMode = True;
2463 highlightSquareColor = *(Pixel *) vTo.addr;
2467 if (!appData.monoMode) {
2468 vFrom.addr = (caddr_t) appData.premoveHighlightColor;
2469 vFrom.size = strlen(appData.premoveHighlightColor);
2470 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2471 if (vTo.addr == NULL) {
2472 appData.monoMode = True;
2475 premoveHighlightColor = *(Pixel *) vTo.addr;
2480 fprintf(stderr, _("%s: too few colors available; trying monochrome mode\n"),
2483 if (appData.bitmapDirectory == NULL ||
2484 appData.bitmapDirectory[0] == NULLCHAR)
2485 appData.bitmapDirectory = DEF_BITMAP_DIR;
2488 if (appData.lowTimeWarning && !appData.monoMode) {
2489 vFrom.addr = (caddr_t) appData.lowTimeWarningColor;
2490 vFrom.size = strlen(appData.lowTimeWarningColor);
2491 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2492 if (vTo.addr == NULL)
2493 appData.monoMode = True;
2495 lowTimeWarningColor = *(Pixel *) vTo.addr;
2498 if (appData.monoMode && appData.debugMode) {
2499 fprintf(stderr, _("white pixel = 0x%lx, black pixel = 0x%lx\n"),
2500 (unsigned long) XWhitePixel(xDisplay, xScreen),
2501 (unsigned long) XBlackPixel(xDisplay, xScreen));
2504 if (parse_cpair(ColorShout, appData.colorShout) < 0 ||
2505 parse_cpair(ColorSShout, appData.colorSShout) < 0 ||
2506 parse_cpair(ColorChannel1, appData.colorChannel1) < 0 ||
2507 parse_cpair(ColorChannel, appData.colorChannel) < 0 ||
2508 parse_cpair(ColorKibitz, appData.colorKibitz) < 0 ||
2509 parse_cpair(ColorTell, appData.colorTell) < 0 ||
2510 parse_cpair(ColorChallenge, appData.colorChallenge) < 0 ||
2511 parse_cpair(ColorRequest, appData.colorRequest) < 0 ||
2512 parse_cpair(ColorSeek, appData.colorSeek) < 0 ||
2513 parse_cpair(ColorNormal, appData.colorNormal) < 0)
2515 if (appData.colorize) {
2517 _("%s: can't parse color names; disabling colorization\n"),
2520 appData.colorize = FALSE;
2522 textColors[ColorNone].fg = textColors[ColorNone].bg = -1;
2523 textColors[ColorNone].attr = 0;
2525 // XtAppAddActions(appContext, boardActions, XtNumber(boardActions));
2531 layoutName = "tinyLayout";
2532 } else if (smallLayout) {
2533 layoutName = "smallLayout";
2535 layoutName = "normalLayout";
2538 if (appData.titleInWindow) {
2539 /* todo check what this appdata does */
2542 if (appData.showButtonBar) {
2543 /* TODO hide button bar if requested */
2547 if (appData.titleInWindow)
2552 if (appData.showButtonBar)
2559 if (appData.showButtonBar)
2569 /* set some checkboxes in the menu according to appData */
2571 if (appData.alwaysPromoteToQueen)
2572 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Always Queen")),TRUE);
2574 if (appData.animateDragging)
2575 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Animate Dragging")),TRUE);
2577 if (appData.animate)
2578 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Animate Moving")),TRUE);
2580 if (appData.autoComment)
2581 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Comment")),TRUE);
2583 if (appData.autoCallFlag)
2584 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Flag")),TRUE);
2586 if (appData.autoFlipView)
2587 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Flip View")),TRUE);
2589 if (appData.autoObserve)
2590 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Observe")),TRUE);
2592 if (appData.autoRaiseBoard)
2593 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Raise Board")),TRUE);
2595 if (appData.autoSaveGames)
2596 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Save")),TRUE);
2598 if (appData.saveGameFile[0] != NULLCHAR)
2600 /* Can't turn this off from menu */
2601 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Save")),TRUE);
2602 gtk_action_set_sensitive(GTK_ACTION (gtk_builder_get_object (builder, "menuOptions.Auto Save")),FALSE);
2605 if (appData.blindfold)
2606 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Blindfold")),TRUE);
2608 if (appData.flashCount > 0)
2609 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Flash Moves")),TRUE);
2611 if (appData.getMoveList)
2612 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Get Move List")),TRUE);
2615 if (appData.highlightDragging)
2616 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Highlight Dragging")),TRUE);
2619 if (appData.highlightLastMove)
2620 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Highlight Last Move")),TRUE);
2622 if (appData.icsAlarm)
2623 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.ICS Alarm")),TRUE);
2625 if (appData.ringBellAfterMoves)
2626 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Move Sound")),TRUE);
2628 if (appData.oldSaveStyle)
2629 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Old Save Style")),TRUE);
2631 if (appData.periodicUpdates)
2632 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Periodic Updates")),TRUE);
2634 if (appData.ponderNextMove)
2635 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Ponder Next Move")),TRUE);
2637 if (appData.popupExitMessage)
2638 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Popup Exit Message")),TRUE);
2640 if (appData.popupMoveErrors)
2641 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Popup Move Errors")),TRUE);
2643 if (appData.premove)
2644 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Premove")),TRUE);
2646 if (appData.quietPlay)
2647 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Quit Play")),TRUE);
2649 if (appData.showCoords)
2650 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Show Coords")),TRUE);
2652 if (appData.showThinking)
2653 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Show Thinking")),TRUE);
2655 if (appData.testLegality)
2656 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Test Legality")),TRUE);
2658 /* end setting check boxes */
2660 /* load square colors */
2661 SVGLightSquare = load_pixbuf("svg/LightSquare.svg",squareSize);
2662 SVGDarkSquare = load_pixbuf("svg/DarkSquare.svg",squareSize);
2663 SVGNeutralSquare = load_pixbuf("svg/NeutralSquare.svg",squareSize);
2665 /* use two icons to indicate if it is white's or black's turn */
2666 WhiteIcon = load_pixbuf("svg/icon_white.svg",0);
2667 BlackIcon = load_pixbuf("svg/icon_black.svg",0);
2668 WindowIcon = WhiteIcon;
2669 gtk_window_set_icon(GTK_WINDOW(GUI_Window),WindowIcon);
2672 /* realize window */
2673 gtk_widget_show (GUI_Window);
2675 /* recalc boardsize */
2680 if (appData.animate || appData.animateDragging)
2685 if (errorExitStatus == -1) {
2686 if (appData.icsActive) {
2687 /* We now wait until we see "login:" from the ICS before
2688 sending the logon script (problems with timestamp otherwise) */
2689 /*ICSInitScript();*/
2690 if (appData.icsInputBox) ICSInputBoxPopUp();
2693 signal(SIGINT, IntSigHandler);
2694 signal(SIGTERM, IntSigHandler);
2695 if (*appData.cmailGameName != NULLCHAR) {
2696 signal(SIGUSR1, CmailSigHandler);
2699 gameInfo.boardWidth = 0; // [HGM] pieces: kludge to ensure InitPosition() calls InitDrawingSizes()
2703 * Create a cursor for the board widget.
2704 * (This needs to be called after the window has been created to have access to board-window)
2707 BoardCursor = gdk_cursor_new(GDK_HAND2);
2708 gdk_window_set_cursor(GUI_Board->window, BoardCursor);
2709 gdk_cursor_destroy(BoardCursor);
2714 if (appData.debugMode) fclose(debugFP); // [DM] debug
2721 if (appData.icsActive && oldICSInteractionTitle != NULL) {
2722 DisplayIcsInteractionTitle(oldICSInteractionTitle);
2724 unlink(gameCopyFilename);
2725 unlink(gamePasteFilename);
2736 CmailSigHandler(sig)
2742 signal(SIGUSR1, SIG_IGN); /* suspend handler */
2744 /* Activate call-back function CmailSigHandlerCallBack() */
2745 OutputToProcess(cmailPR, (char *)(&dummy), sizeof(int), &error);
2747 signal(SIGUSR1, CmailSigHandler); /* re-activate handler */
2751 CmailSigHandlerCallBack(isr, closure, message, count, error)
2759 ReloadCmailMsgEvent(TRUE); /* Reload cmail msg */
2761 /**** end signal code ****/
2771 f = fopen(appData.icsLogon, "r");
2777 strcat(buf, appData.icsLogon);
2778 f = fopen(buf, "r");
2782 ProcessICSInitScript(f);
2789 EditCommentPopDown();
2795 SetMenuEnables(enab)
2800 if (!builder) return;
2801 while (enab->name != NULL) {
2802 o = gtk_builder_get_object(builder, enab->name);
2803 if(GTK_IS_WIDGET(o))
2804 gtk_widget_set_sensitive(GTK_WIDGET (o),enab->value);
2807 if(GTK_IS_ACTION(o))
2808 gtk_action_set_sensitive(GTK_ACTION (o),enab->value);
2810 DisplayError(enab->name, 0);
2818 SetMenuEnables(icsEnables);
2821 if (appData.zippyPlay && !appData.noChessProgram) /* [DM] icsEngineAnalyze */
2822 {}; // XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Analysis Mode"), True);
2829 SetMenuEnables(ncpEnables);
2835 SetMenuEnables(gnuEnables);
2841 SetMenuEnables(cmailEnables);
2847 SetMenuEnables(trainingOnEnables);
2848 if (appData.showButtonBar) {
2849 // XtSetSensitive(buttonBarWidget, False);
2855 SetTrainingModeOff()
2857 SetMenuEnables(trainingOffEnables);
2858 if (appData.showButtonBar) {
2859 // XtSetSensitive(buttonBarWidget, True);
2864 SetUserThinkingEnables()
2866 if (appData.noChessProgram) return;
2867 SetMenuEnables(userThinkingEnables);
2871 SetMachineThinkingEnables()
2873 if (appData.noChessProgram) return;
2874 SetMenuEnables(machineThinkingEnables);
2876 case MachinePlaysBlack:
2877 case MachinePlaysWhite:
2878 case TwoMachinesPlay:
2879 // XtSetSensitive(XtNameToWidget(menuBarWidget,
2880 // ModeToWidgetName(gameMode)), True);
2887 #define Abs(n) ((n)<0 ? -(n) : (n))
2890 * Find a font that matches "pattern" that is as close as
2891 * possible to the targetPxlSize. Prefer fonts that are k
2892 * pixels smaller to fonts that are k pixels larger. The
2893 * pattern must be in the X Consortium standard format,
2894 * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".
2895 * The return value should be freed with XtFree when no
2898 char *FindFont(pattern, targetPxlSize)
2902 char **fonts, *p, *best, *scalable, *scalableTail;
2903 int i, j, nfonts, minerr, err, pxlSize;
2906 char **missing_list;
2908 char *def_string, *base_fnt_lst, strInt[3];
2910 XFontStruct **fnt_list;
2912 base_fnt_lst = calloc(1, strlen(pattern) + 3);
2913 sprintf(strInt, "%d", targetPxlSize);
2914 p = strstr(pattern, "--");
2915 strncpy(base_fnt_lst, pattern, p - pattern + 2);
2916 strcat(base_fnt_lst, strInt);
2917 strcat(base_fnt_lst, strchr(p + 2, '-'));
2919 if ((fntSet = XCreateFontSet(xDisplay,
2923 &def_string)) == NULL) {
2925 fprintf(stderr, _("Unable to create font set.\n"));
2929 nfonts = XFontsOfFontSet(fntSet, &fnt_list, &fonts);
2931 fonts = XListFonts(xDisplay, pattern, 999999, &nfonts);
2933 fprintf(stderr, _("%s: no fonts match pattern %s\n"),
2934 programName, pattern);
2942 for (i=0; i<nfonts; i++) {
2945 if (*p != '-') continue;
2947 if (*p == NULLCHAR) break;
2948 if (*p++ == '-') j++;
2950 if (j < 7) continue;
2953 scalable = fonts[i];
2956 err = pxlSize - targetPxlSize;
2957 if (Abs(err) < Abs(minerr) ||
2958 (minerr > 0 && err < 0 && -err == minerr)) {
2964 if (scalable && Abs(minerr) > appData.fontSizeTolerance) {
2965 /* If the error is too big and there is a scalable font,
2966 use the scalable font. */
2967 int headlen = scalableTail - scalable;
2968 p = (char *) XtMalloc(strlen(scalable) + 10);
2969 while (isdigit(*scalableTail)) scalableTail++;
2970 sprintf(p, "%.*s%d%s", headlen, scalable, targetPxlSize, scalableTail);
2972 p = (char *) XtMalloc(strlen(best) + 1);
2975 if (appData.debugMode) {
2976 fprintf(debugFP, _("resolved %s at pixel size %d\n to %s\n"),
2977 pattern, targetPxlSize, p);
2980 if (missing_count > 0)
2981 XFreeStringList(missing_list);
2982 XFreeFontSet(xDisplay, fntSet);
2984 XFreeFontNames(fonts);
2991 /* GCs are not needed anymore for GTK just left them in here for the moment, since there is a lot of X-code still around that's wants them*/
2993 XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
2994 | GCBackground | GCFunction | GCPlaneMask;
2995 XGCValues gc_values;
2998 gc_values.plane_mask = AllPlanes;
2999 gc_values.line_width = lineGap;
3000 gc_values.line_style = LineSolid;
3001 gc_values.function = GXcopy;
3003 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3004 gc_values.background = XWhitePixel(xDisplay, xScreen);
3005 coordGC = XtGetGC(shellWidget, value_mask, &gc_values);
3006 XSetFont(xDisplay, coordGC, coordFontID);
3008 if (appData.monoMode) {
3009 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3010 gc_values.background = XBlackPixel(xDisplay, xScreen);
3011 lightSquareGC = wbPieceGC
3012 = XtGetGC(shellWidget, value_mask, &gc_values);
3014 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3015 gc_values.background = XWhitePixel(xDisplay, xScreen);
3016 darkSquareGC = bwPieceGC
3017 = XtGetGC(shellWidget, value_mask, &gc_values);
3019 if (DefaultDepth(xDisplay, xScreen) == 1) {
3020 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
3021 gc_values.function = GXcopyInverted;
3022 copyInvertedGC = XtGetGC(shellWidget, value_mask, &gc_values);
3023 gc_values.function = GXcopy;
3024 if (XBlackPixel(xDisplay, xScreen) == 1) {
3025 bwPieceGC = darkSquareGC;
3026 wbPieceGC = copyInvertedGC;
3028 bwPieceGC = copyInvertedGC;
3029 wbPieceGC = lightSquareGC;
3033 gc_values.foreground = lightSquareColor;
3034 gc_values.background = darkSquareColor;
3035 lightSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3037 gc_values.foreground = darkSquareColor;
3038 gc_values.background = lightSquareColor;
3039 darkSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3041 gc_values.foreground = jailSquareColor;
3042 gc_values.background = jailSquareColor;
3043 jailSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3045 gc_values.foreground = whitePieceColor;
3046 gc_values.background = darkSquareColor;
3047 wdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3049 gc_values.foreground = whitePieceColor;
3050 gc_values.background = lightSquareColor;
3051 wlPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3053 gc_values.foreground = whitePieceColor;
3054 gc_values.background = jailSquareColor;
3055 wjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3057 gc_values.foreground = blackPieceColor;
3058 gc_values.background = darkSquareColor;
3059 bdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3061 gc_values.foreground = blackPieceColor;
3062 gc_values.background = lightSquareColor;
3063 blPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3065 gc_values.foreground = blackPieceColor;
3066 gc_values.background = jailSquareColor;
3067 bjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3076 for(i=0;i<MAXPIECES;i++)
3080 g_free(SVGpieces[i]);
3087 SVGLightSquare = load_pixbuf("svg/LightSquare.svg",squareSize);
3088 SVGDarkSquare = load_pixbuf("svg/DarkSquare.svg",squareSize);
3089 SVGNeutralSquare = load_pixbuf("svg/NeutralSquare.svg",squareSize);
3092 /* get some defaults going */
3093 for(i=WhitePawn; i<DemotePiece+1; i++)
3094 SVGpieces[i] = load_pixbuf("svg/NeutralSquare.svg",squareSize);
3096 SVGpieces[WhitePawn] = load_pixbuf("svg/WhitePawn.svg",squareSize);
3097 SVGpieces[WhiteKnight] = load_pixbuf("svg/WhiteKnight.svg",squareSize);
3098 SVGpieces[WhiteBishop] = load_pixbuf("svg/WhiteBishop.svg",squareSize);
3099 SVGpieces[WhiteRook] = load_pixbuf("svg/WhiteRook.svg",squareSize);
3100 SVGpieces[WhiteQueen] = load_pixbuf("svg/WhiteQueen.svg",squareSize);
3101 SVGpieces[WhiteKing] = load_pixbuf("svg/WhiteKing.svg",squareSize);
3103 SVGpieces[BlackPawn] = load_pixbuf("svg/BlackPawn.svg",squareSize);
3104 SVGpieces[BlackKnight] = load_pixbuf("svg/BlackKnight.svg",squareSize);
3105 SVGpieces[BlackBishop] = load_pixbuf("svg/BlackBishop.svg",squareSize);
3106 SVGpieces[BlackRook] = load_pixbuf("svg/BlackRook.svg",squareSize);
3107 SVGpieces[BlackQueen] = load_pixbuf("svg/BlackQueen.svg",squareSize);
3108 SVGpieces[BlackKing] = load_pixbuf("svg/BlackKing.svg",squareSize);
3114 static void MenuBarSelect(w, addr, index)
3119 XtActionProc proc = (XtActionProc) addr;
3121 (proc)(NULL, NULL, NULL, NULL);
3124 void CreateMenuBarPopup(parent, name, mb)
3134 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3137 XtSetArg(args[j], XtNleftMargin, 20); j++;
3138 XtSetArg(args[j], XtNrightMargin, 20); j++;
3140 while (mi->string != NULL) {
3141 if (strcmp(mi->string, "----") == 0) {
3142 entry = XtCreateManagedWidget(mi->string, smeLineObjectClass,
3145 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string)));
3146 entry = XtCreateManagedWidget(mi->string, smeBSBObjectClass,
3148 XtAddCallback(entry, XtNcallback,
3149 (XtCallbackProc) MenuBarSelect,
3150 (caddr_t) mi->proc);
3156 Widget CreateMenuBar(mb)
3160 Widget anchor, menuBar;
3162 char menuName[MSG_SIZ];
3165 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
3166 XtSetArg(args[j], XtNvSpace, 0); j++;
3167 XtSetArg(args[j], XtNborderWidth, 0); j++;
3168 menuBar = XtCreateWidget("menuBar", boxWidgetClass,
3169 formWidget, args, j);
3171 while (mb->name != NULL) {
3172 strcpy(menuName, "menu");
3173 strcat(menuName, mb->name);
3175 XtSetArg(args[j], XtNmenuName, XtNewString(menuName)); j++;
3178 shortName[0] = _(mb->name)[0];
3179 shortName[1] = NULLCHAR;
3180 XtSetArg(args[j], XtNlabel, XtNewString(shortName)); j++;
3183 XtSetArg(args[j], XtNlabel, XtNewString(_(mb->name))); j++;
3186 XtSetArg(args[j], XtNborderWidth, 0); j++;
3187 anchor = XtCreateManagedWidget(mb->name, menuButtonWidgetClass,
3189 CreateMenuBarPopup(menuBar, menuName, mb);
3197 CreatePieceMenu(name, color)
3204 ChessSquare selection;
3206 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3207 boardWidget, args, 0);
3209 for (i = 0; i < PIECE_MENU_SIZE; i++) {
3210 String item = pieceMenuStrings[color][i];
3212 if (strcmp(item, "----") == 0) {
3213 entry = XtCreateManagedWidget(item, smeLineObjectClass,
3216 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
3217 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3219 selection = pieceMenuTranslation[color][i];
3220 XtAddCallback(entry, XtNcallback,
3221 (XtCallbackProc) PieceMenuSelect,
3222 (caddr_t) selection);
3223 if (selection == WhitePawn || selection == BlackPawn) {
3224 XtSetArg(args[0], XtNpopupOnEntry, entry);
3225 XtSetValues(menu, args, 1);
3238 ChessSquare selection;
3240 // whitePieceMenu = CreatePieceMenu("menuW", 0);
3241 // blackPieceMenu = CreatePieceMenu("menuB", 1);
3243 // XtRegisterGrabAction(PieceMenuPopup, True,
3244 // (unsigned)(ButtonPressMask|ButtonReleaseMask),
3245 // GrabModeAsync, GrabModeAsync);
3247 // XtSetArg(args[0], XtNlabel, _("Drop"));
3248 // dropMenu = XtCreatePopupShell("menuD", simpleMenuWidgetClass,
3249 // boardWidget, args, 1);
3250 // for (i = 0; i < DROP_MENU_SIZE; i++) {
3251 // String item = dropMenuStrings[i];
3253 // if (strcmp(item, "----") == 0) {
3254 // entry = XtCreateManagedWidget(item, smeLineObjectClass,
3255 // dropMenu, NULL, 0);
3257 // XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
3258 // entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3259 // dropMenu, args, 1);
3260 // selection = dropMenuTranslation[i];
3261 // XtAddCallback(entry, XtNcallback,
3262 // (XtCallbackProc) DropMenuSelect,
3263 // (caddr_t) selection);
3268 void SetupDropMenu()
3276 for (i=0; i<sizeof(dmEnables)/sizeof(DropMenuEnables); i++) {
3277 entry = XtNameToWidget(dropMenu, dmEnables[i].widget);
3278 p = strchr(gameMode == IcsPlayingWhite ? white_holding : black_holding,
3279 dmEnables[i].piece);
3280 XtSetSensitive(entry, p != NULL || !appData.testLegality
3281 /*!!temp:*/ || (gameInfo.variant == VariantCrazyhouse
3282 && !appData.icsActive));
3284 while (p && *p++ == dmEnables[i].piece) count++;
3285 snprintf(label, sizeof(label), "%s %d", dmEnables[i].widget, count);
3287 XtSetArg(args[j], XtNlabel, label); j++;
3288 XtSetValues(entry, args, j);
3292 void PieceMenuPopup(w, event, params, num_params)
3296 Cardinal *num_params;
3299 if (event->type != ButtonPress) return;
3300 if (errorUp) ErrorPopDown();
3304 whichMenu = params[0];
3306 case IcsPlayingWhite:
3307 case IcsPlayingBlack:
3309 case MachinePlaysWhite:
3310 case MachinePlaysBlack:
3311 if (appData.testLegality &&
3312 gameInfo.variant != VariantBughouse &&
3313 gameInfo.variant != VariantCrazyhouse) return;
3315 whichMenu = "menuD";
3321 if (((pmFromX = EventToSquare(event->xbutton.x, BOARD_WIDTH)) < 0) ||
3322 ((pmFromY = EventToSquare(event->xbutton.y, BOARD_HEIGHT)) < 0)) {
3323 pmFromX = pmFromY = -1;
3327 pmFromX = BOARD_WIDTH - 1 - pmFromX;
3329 pmFromY = BOARD_HEIGHT - 1 - pmFromY;
3331 XtPopupSpringLoaded(XtNameToWidget(boardWidget, whichMenu));
3334 static void PieceMenuSelect(w, piece, junk)
3339 if (pmFromX < 0 || pmFromY < 0) return;
3340 EditPositionMenuEvent(piece, pmFromX, pmFromY);
3343 static void DropMenuSelect(w, piece, junk)
3348 if (pmFromX < 0 || pmFromY < 0) return;
3349 DropMenuEvent(piece, pmFromX, pmFromY);
3353 * If the user selects on a border boundary, return -1; if off the board,
3354 * return -2. Otherwise map the event coordinate to the square.
3356 int EventToSquare(x, limit)
3364 if ((x % (squareSize + lineGap)) >= squareSize)
3366 x /= (squareSize + lineGap);
3372 static void do_flash_delay(msec)
3378 static void drawHighlight(file, rank, line_type)
3379 int file, rank, line_type;
3384 if (lineGap == 0 || appData.blindfold) return;
3388 x = lineGap/2 + ((BOARD_WIDTH-1)-file) *
3389 (squareSize + lineGap);
3390 y = lineGap/2 + rank * (squareSize + lineGap);
3394 x = lineGap/2 + file * (squareSize + lineGap);
3395 y = lineGap/2 + ((BOARD_HEIGHT-1)-rank) *
3396 (squareSize + lineGap);
3400 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
3402 /* draw the highlight */
3403 cairo_move_to (cr, x, y);
3404 cairo_rel_line_to (cr, 0,squareSize+lineGap);
3405 cairo_rel_line_to (cr, squareSize+lineGap,0);
3406 cairo_rel_line_to (cr, 0,-squareSize-lineGap);
3407 cairo_close_path (cr);
3409 cairo_set_line_width (cr, lineGap);
3412 /* TODO: use appdata colors */
3413 case LINE_TYPE_HIGHLIGHT:
3414 cairo_set_source_rgba (cr, 1, 1, 0, 1.0);
3417 cairo_set_source_rgba (cr, 1, 0, 0, 1.0);
3419 case LINE_TYPE_NORMAL:
3421 cairo_set_source_rgba (cr, 0, 1, 0, 1.0);
3432 int hi1X = -1, hi1Y = -1, hi2X = -1, hi2Y = -1;
3433 int pm1X = -1, pm1Y = -1, pm2X = -1, pm2Y = -1;
3436 SetHighlights(fromX, fromY, toX, toY)
3437 int fromX, fromY, toX, toY;
3439 if (hi1X != fromX || hi1Y != fromY)
3441 if (hi1X >= 0 && hi1Y >= 0)
3443 drawHighlight(hi1X, hi1Y, LINE_TYPE_NORMAL);
3445 if (fromX >= 0 && fromY >= 0)
3447 drawHighlight(fromX, fromY, LINE_TYPE_HIGHLIGHT);
3450 if (hi2X != toX || hi2Y != toY)
3452 if (hi2X >= 0 && hi2Y >= 0)
3454 drawHighlight(hi2X, hi2Y, LINE_TYPE_NORMAL);
3456 if (toX >= 0 && toY >= 0)
3458 drawHighlight(toX, toY, LINE_TYPE_HIGHLIGHT);
3472 SetHighlights(-1, -1, -1, -1);
3477 SetPremoveHighlights(fromX, fromY, toX, toY)
3478 int fromX, fromY, toX, toY;
3480 if (pm1X != fromX || pm1Y != fromY)
3482 if (pm1X >= 0 && pm1Y >= 0)
3484 drawHighlight(pm1X, pm1Y, LINE_TYPE_NORMAL);
3486 if (fromX >= 0 && fromY >= 0)
3488 drawHighlight(fromX, fromY, LINE_TYPE_PRE);
3491 if (pm2X != toX || pm2Y != toY)
3493 if (pm2X >= 0 && pm2Y >= 0)
3495 drawHighlight(pm2X, pm2Y, LINE_TYPE_NORMAL);
3497 if (toX >= 0 && toY >= 0)
3499 drawHighlight(toX, toY, LINE_TYPE_PRE);
3512 ClearPremoveHighlights()
3514 SetPremoveHighlights(-1, -1, -1, -1);
3517 static void BlankSquare(x, y, color, piece, dest)
3530 pb = SVGLightSquare;
3532 case 2: /* neutral */
3534 pb = SVGNeutralSquare;
3537 gdk_draw_pixbuf(GDK_WINDOW(GUI_Board->window),NULL,pb,0,0,x,y,-1,-1, GDK_RGB_DITHER_NORMAL, 0, 0);
3541 static void DrawPiece(piece, square_color, x, y, dest)
3543 int square_color, x, y;
3546 /* redraw background, since piece might be transparent in some areas */
3547 BlankSquare(x,y,square_color,piece,dest);
3550 gdk_draw_pixbuf(GDK_WINDOW(GUI_Board->window),NULL,
3551 GDK_PIXBUF(SVGpieces[piece]),0,0,x,y,-1,-1,
3552 GDK_RGB_DITHER_NORMAL, 0, 0);
3556 /* [HR] determine square color depending on chess variant. */
3557 static int SquareColor(row, column)
3562 if (gameInfo.variant == VariantXiangqi) {
3563 if (column >= 3 && column <= 5 && row >= 0 && row <= 2) {
3565 } else if (column >= 3 && column <= 5 && row >= 7 && row <= 9) {
3567 } else if (row <= 4) {
3573 square_color = ((column + row) % 2) == 1;
3576 /* [hgm] holdings: next line makes all holdings squares light */
3577 if(column < BOARD_LEFT || column >= BOARD_RGHT) square_color = 1;
3579 return square_color;
3582 void DrawSquare(row, column, piece, do_flash)
3583 int row, column, do_flash;
3586 int square_color, x, y;
3591 /* Calculate delay in milliseconds (2-delays per complete flash) */
3592 flash_delay = 500 / appData.flashRate;
3594 /* calculate x and y coordinates from row and column */
3597 x = lineGap + ((BOARD_WIDTH-1)-column) *
3598 (squareSize + lineGap);
3599 y = lineGap + row * (squareSize + lineGap);
3603 x = lineGap + column * (squareSize + lineGap);
3604 y = lineGap + ((BOARD_HEIGHT-1)-row) *
3605 (squareSize + lineGap);
3608 square_color = SquareColor(row, column);
3610 // [HGM] holdings: blank out area between board and holdings
3611 if ( column == BOARD_LEFT-1 || column == BOARD_RGHT
3612 || (column == BOARD_LEFT-2 && row < BOARD_HEIGHT-gameInfo.holdingsSize)
3613 || (column == BOARD_RGHT+1 && row >= gameInfo.holdingsSize) )
3615 BlankSquare(x, y, 2, EmptySquare, xBoardWindow);
3617 // [HGM] print piece counts next to holdings
3618 string[1] = NULLCHAR;
3621 cairo_text_extents_t extents;
3626 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
3628 string[0] = '0' + piece;
3630 /* TODO this has to go into the font-selection */
3631 cairo_select_font_face (cr, "Sans",
3632 CAIRO_FONT_SLANT_NORMAL,
3633 CAIRO_FONT_WEIGHT_NORMAL);
3635 cairo_set_font_size (cr, 12.0);
3636 cairo_text_extents (cr, string, &extents);
3638 if (column == (flipView ? BOARD_LEFT-1 : BOARD_RGHT) )
3640 xpos= x + squareSize - extents.width - 2;
3641 ypos= y + extents.y_bearing + 1;
3643 if (column == (flipView ? BOARD_RGHT : BOARD_LEFT-1) && piece > 1)
3646 ypos = y + extents.y_bearing + 1;
3649 /* TODO mono mode? */
3650 cairo_move_to (cr, xpos, ypos);
3651 cairo_text_path (cr, string);
3652 cairo_set_source_rgb (cr, 1.0, 1.0, 1);
3653 cairo_fill_preserve (cr);
3654 cairo_set_source_rgb (cr, 0, 0, 0);
3655 cairo_set_line_width (cr, 0.1);
3664 /* square on the board */
3665 if (piece == EmptySquare || appData.blindfold)
3667 BlankSquare(x, y, square_color, piece, xBoardWindow);
3671 if (do_flash && appData.flashCount > 0)
3673 for (i=0; i<appData.flashCount; ++i)
3676 DrawPiece(piece, square_color, x, y, xBoardWindow);
3677 do_flash_delay(flash_delay);
3679 BlankSquare(x, y, square_color, piece, xBoardWindow);
3680 do_flash_delay(flash_delay);
3683 DrawPiece(piece, square_color, x, y, xBoardWindow);
3687 /* show coordinates if necessary */
3688 if(appData.showCoords)
3690 cairo_text_extents_t extents;
3694 /* TODO this has to go into the font-selection */
3695 cairo_select_font_face (cr, "Sans",
3696 CAIRO_FONT_SLANT_NORMAL,
3697 CAIRO_FONT_WEIGHT_NORMAL);
3698 cairo_set_font_size (cr, 12.0);
3700 string[1] = NULLCHAR;
3703 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
3705 if (row == (flipView ? BOARD_HEIGHT-1 : 0) &&
3706 column >= BOARD_LEFT && column < BOARD_RGHT)
3708 string[0] = 'a' + column - BOARD_LEFT;
3709 cairo_text_extents (cr, string, &extents);
3711 xpos = x + squareSize - extents.width - 2;
3712 ypos = y + squareSize - extents.height - extents.y_bearing - 1;
3714 if (appData.monoMode)
3721 cairo_move_to (cr, xpos, ypos);
3722 cairo_text_path (cr, string);
3723 cairo_set_source_rgb (cr, 0.0, 0.0, 0);
3724 cairo_fill_preserve (cr);
3725 cairo_set_source_rgb (cr, 0, 1.0, 0);
3726 cairo_set_line_width (cr, 0.1);
3729 if ( column == (flipView ? BOARD_RGHT-1 : BOARD_LEFT))
3732 string[0] = ONE + row;
3733 cairo_text_extents (cr, string, &extents);
3736 ypos = y + extents.height + 1;
3738 if (appData.monoMode)
3745 cairo_move_to (cr, xpos, ypos);
3746 cairo_text_path (cr, string);
3747 cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
3748 cairo_fill_preserve (cr);
3749 cairo_set_source_rgb (cr, 0, 0, 1.0);
3750 cairo_set_line_width (cr, 0.1);
3762 /* Returns 1 if there are "too many" differences between b1 and b2
3763 (i.e. more than 1 move was made) */
3764 static int too_many_diffs(b1, b2)
3770 for (i=0; i<BOARD_HEIGHT; ++i) {
3771 for (j=0; j<BOARD_WIDTH; ++j) {
3772 if (b1[i][j] != b2[i][j]) {
3773 if (++c > 4) /* Castling causes 4 diffs */
3782 /* Matrix describing castling maneuvers */
3783 /* Row, ColRookFrom, ColKingFrom, ColRookTo, ColKingTo */
3784 static int castling_matrix[4][5] = {
3785 { 0, 0, 4, 3, 2 }, /* 0-0-0, white */
3786 { 0, 7, 4, 5, 6 }, /* 0-0, white */
3787 { 7, 0, 4, 3, 2 }, /* 0-0-0, black */
3788 { 7, 7, 4, 5, 6 } /* 0-0, black */
3791 /* Checks whether castling occurred. If it did, *rrow and *rcol
3792 are set to the destination (row,col) of the rook that moved.
3794 Returns 1 if castling occurred, 0 if not.
3796 Note: Only handles a max of 1 castling move, so be sure
3797 to call too_many_diffs() first.
3799 static int check_castle_draw(newb, oldb, rrow, rcol)
3806 /* For each type of castling... */
3807 for (i=0; i<4; ++i) {
3808 r = castling_matrix[i];
3810 /* Check the 4 squares involved in the castling move */
3812 for (j=1; j<=4; ++j) {
3813 if (newb[r[0]][r[j]] == oldb[r[0]][r[j]]) {
3820 /* All 4 changed, so it must be a castling move */
3829 static int damage[BOARD_SIZE][BOARD_SIZE];
3832 * event handler for redrawing the board
3834 void DrawPosition( repaint, board)
3835 /*Boolean*/int repaint;
3839 static int lastFlipView = 0;
3840 static int lastBoardValid = 0;
3841 static Board lastBoard;
3844 if (board == NULL) {
3845 if (!lastBoardValid) return;
3848 if (!lastBoardValid || lastFlipView != flipView) {
3849 // XtSetArg(args[0], XtNleftBitmap, (flipView ? xMarkPixmap : None));
3850 // XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flip View"),
3855 * It would be simpler to clear the window with XClearWindow()
3856 * but this causes a very distracting flicker.
3859 if (!repaint && lastBoardValid && lastFlipView == flipView)
3861 /* If too much changes (begin observing new game, etc.), don't
3863 do_flash = too_many_diffs(board, lastBoard) ? 0 : 1;
3865 /* Special check for castling so we don't flash both the king
3866 and the rook (just flash the king). */
3869 if (check_castle_draw(board, lastBoard, &rrow, &rcol))
3871 /* Draw rook with NO flashing. King will be drawn flashing later */
3872 DrawSquare(rrow, rcol, board[rrow][rcol], 0);
3873 lastBoard[rrow][rcol] = board[rrow][rcol];
3877 /* First pass -- Draw (newly) empty squares and repair damage.
3878 This prevents you from having a piece show up twice while it
3879 is flashing on its new square */
3880 for (i = 0; i < BOARD_HEIGHT; i++)
3881 for (j = 0; j < BOARD_WIDTH; j++)
3882 if ((board[i][j] != lastBoard[i][j] && board[i][j] == EmptySquare)
3885 DrawSquare(i, j, board[i][j], 0);
3886 damage[i][j] = False;
3889 /* Second pass -- Draw piece(s) in new position and flash them */
3890 for (i = 0; i < BOARD_HEIGHT; i++)
3891 for (j = 0; j < BOARD_WIDTH; j++)
3892 if (board[i][j] != lastBoard[i][j])
3894 DrawSquare(i, j, board[i][j], do_flash);
3906 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
3908 cairo_set_line_width (cr, lineGap);
3910 /* TODO: use appdata colors */
3911 cairo_set_source_rgba (cr, 0, 1, 0, 1.0);
3915 for (i = 0; i < BOARD_HEIGHT + 1; i++)
3918 x2 = lineGap + BOARD_WIDTH * (squareSize + lineGap);
3919 y1 = y2 = lineGap / 2 + (i * (squareSize + lineGap));
3921 cairo_move_to (cr, x1, y1);
3922 cairo_rel_line_to (cr, x2,0);
3926 for (j = 0; j < BOARD_WIDTH + 1; j++)
3929 y2 = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
3930 x1 = x2 = lineGap / 2 + (j * (squareSize + lineGap));
3932 cairo_move_to (cr, x1, y1);
3933 cairo_rel_line_to (cr, 0, y2);
3942 for (i = 0; i < BOARD_HEIGHT; i++)
3943 for (j = 0; j < BOARD_WIDTH; j++)
3945 DrawSquare(i, j, board[i][j], 0);
3946 damage[i][j] = False;
3950 CopyBoard(lastBoard, board);
3952 lastFlipView = flipView;
3954 /* Draw highlights */
3955 if (pm1X >= 0 && pm1Y >= 0)
3957 drawHighlight(pm1X, pm1Y, LINE_TYPE_PRE);
3959 if (pm2X >= 0 && pm2Y >= 0)
3961 drawHighlight(pm2X, pm2Y, LINE_TYPE_PRE);
3963 if (hi1X >= 0 && hi1Y >= 0)
3965 drawHighlight(hi1X, hi1Y, LINE_TYPE_HIGHLIGHT);
3967 if (hi2X >= 0 && hi2Y >= 0)
3969 drawHighlight(hi2X, hi2Y, LINE_TYPE_HIGHLIGHT);
3972 /* If piece being dragged around board, must redraw that too */
3979 * event handler for parsing user moves
3981 // [HGM] This routine will need quite some reworking. Although the backend still supports the old
3982 // way of doing things, by calling UserMoveEvent() to test the legality of the move and then perform
3983 // it at the end, and doing all kind of preliminary tests here (e.g. to weed out self-captures), it
3984 // should be made to use the new way, of calling UserMoveTest early to determine the legality of the
3985 // move, (which will weed out the illegal selfcaptures and moves into the holdings, and flag promotions),
3986 // and at the end FinishMove() to perform the move after optional promotion popups.
3987 // For now I patched it to allow self-capture with King, and suppress clicks between board and holdings.
3988 void HandleUserMove(w, event, prms, nprms)
3995 Boolean saveAnimate;
3996 static int second = 0, promotionChoice = 0;
3999 if (w != boardWidget || errorExitStatus != -1) return;
4001 x = EventToSquare(event->xbutton.x, BOARD_WIDTH);
4002 y = EventToSquare(event->xbutton.y, BOARD_HEIGHT);
4003 if (!flipView && y >= 0) {
4004 y = BOARD_HEIGHT - 1 - y;
4006 if (flipView && x >= 0) {
4007 x = BOARD_WIDTH - 1 - x;
4010 if(promotionChoice) { // we are waiting for a click to indicate promotion piece
4011 if(event->type == ButtonRelease) return; // ignore upclick of click-click destination
4012 promotionChoice = FALSE; // only one chance: if click not OK it is interpreted as cancel
4013 if(appData.debugMode) fprintf(debugFP, "promotion click, x=%d, y=%d\n", x, y);
4014 if(gameInfo.holdingsWidth &&
4015 (WhiteOnMove(currentMove)
4016 ? x == BOARD_WIDTH-1 && y < gameInfo.holdingsSize && y > 0
4017 : x == 0 && y >= BOARD_HEIGHT - gameInfo.holdingsSize && y < BOARD_HEIGHT-1) ) {
4018 // click in right holdings, for determining promotion piece
4019 ChessSquare p = boards[currentMove][y][x];
4020 if(appData.debugMode) fprintf(debugFP, "square contains %d\n", (int)p);
4021 if(p != EmptySquare) {
4022 FinishMove(NormalMove, fromX, fromY, toX, toY, ToLower(PieceToChar(p)));
4027 DrawPosition(FALSE, boards[currentMove]);
4030 if (event->type == ButtonPress) ErrorPopDown();
4033 if (event->type == ButtonPress) {
4034 // XtPopdown(promotionShell);
4035 // XtDestroyWidget(promotionShell);
4036 promotionUp = False;
4044 /* [HGM] holdings: next 5 lines: ignore all clicks between board and holdings */
4045 if(event->type == ButtonPress
4046 && ( x == BOARD_LEFT-1 ||
4048 (x == BOARD_LEFT-2 && y < BOARD_HEIGHT-gameInfo.holdingsSize ) ||
4049 (x == BOARD_RGHT+1 && y >= gameInfo.holdingsSize)) )
4053 if (event->type == ButtonPress) {
4054 /* First square, prepare to drag */
4055 if (OKToStartUserMove(x, y)) {
4059 DragPieceBegin(event->xbutton.x, event->xbutton.y);
4060 if (appData.highlightDragging) {
4061 SetHighlights(x, y, -1, -1);
4069 if (event->type == ButtonRelease && x == fromX && y == fromY) {
4070 /* Click on single square in stead of drag-drop */
4071 DragPieceEnd(event->xbutton.x, event->xbutton.y);
4072 if (appData.animateDragging) {
4073 /* Undo animation damage if any */
4074 DrawPosition(FALSE, NULL);
4077 /* Second up/down in same square; just abort move */
4082 ClearPremoveHighlights();
4084 /* First upclick in same square; start click-click mode */
4085 SetHighlights(x, y, -1, -1);
4090 moveType = UserMoveTest(fromX, fromY, x, y, NULLCHAR, event->type == ButtonRelease);
4092 if (moveType == Comment) { // kludge for indicating capture-own on Press
4093 /* Clicked again on same color piece -- changed his mind */
4094 /* note that re-clicking same square always hits same color piece */
4095 second = (x == fromX && y == fromY);
4096 if (appData.highlightDragging) {
4097 SetHighlights(x, y, -1, -1);
4101 if (OKToStartUserMove(x, y)) {
4104 DragPieceBegin(event->xbutton.x, event->xbutton.y);
4109 if(moveType == AmbiguousMove) { // kludge to indicate edit-position move
4112 DragPieceEnd(event->xbutton.x, event->xbutton.y);
4113 DrawPosition(FALSE, boards[currentMove]);
4117 /* Complete move; (x,y) is now different from (fromX, fromY) on both Press and Release */
4120 saveAnimate = appData.animate;
4121 if (event->type == ButtonPress) {
4122 /* Finish clickclick move */
4123 if (appData.animate || appData.highlightLastMove) {
4124 SetHighlights(fromX, fromY, toX, toY);
4129 /* Finish drag move */
4130 if (appData.highlightLastMove) {
4131 SetHighlights(fromX, fromY, toX, toY);
4135 DragPieceEnd(event->xbutton.x, event->xbutton.y);
4136 /* Don't animate move and drag both */
4137 appData.animate = FALSE;
4139 if (moveType == WhitePromotionKnight || moveType == BlackPromotionKnight ||
4140 (moveType == WhitePromotionQueen || moveType == BlackPromotionQueen) &&
4141 appData.alwaysPromoteToQueen) { // promotion, but no choice
4142 FinishMove(moveType, fromX, fromY, toX, toY, 'q');
4144 if (moveType == WhitePromotionQueen || moveType == BlackPromotionQueen ) {
4145 SetHighlights(fromX, fromY, toX, toY);
4146 if(gameInfo.variant == VariantSuper || gameInfo.variant == VariantGreat) {
4147 // [HGM] super: promotion to captured piece selected from holdings
4148 ChessSquare p = boards[currentMove][fromY][fromX], q = boards[currentMove][toY][toX];
4149 promotionChoice = TRUE;
4150 // kludge follows to temporarily execute move on display, without promoting yet
4151 boards[currentMove][fromY][fromX] = EmptySquare; // move Pawn to 8th rank
4152 boards[currentMove][toY][toX] = p;
4153 DrawPosition(FALSE, boards[currentMove]);
4154 boards[currentMove][fromY][fromX] = p; // take back, but display stays
4155 boards[currentMove][toY][toX] = q;
4156 DisplayMessage("Click in holdings to choose piece", "");
4160 goto skipClearingFrom; // the skipped stuff is done asynchronously by PromotionCallback
4162 if(moveType != ImpossibleMove) { // valid move, but no promotion
4163 FinishMove(moveType, fromX, fromY, toX, toY, NULLCHAR);
4164 } else { // invalid move; could have set premove
4167 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
4168 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
4171 appData.animate = saveAnimate;
4172 if (appData.animate || appData.animateDragging) {
4173 /* Undo animation damage if needed */
4174 DrawPosition(FALSE, NULL);
4178 void AnimateUserMove (Widget w, XEvent * event,
4179 String * params, Cardinal * nParams)
4181 DragPieceMove(event->xmotion.x, event->xmotion.y);
4184 Widget CommentCreate(name, text, mutable, callback, lines)
4186 int /*Boolean*/ mutable;
4187 XtCallbackProc callback;
4191 Widget shell, layout, form, edit, b_ok, b_cancel, b_clear, b_close, b_edit;
4196 XtSetArg(args[j], XtNwidth, &bw_width); j++;
4197 XtGetValues(boardWidget, args, j);
4200 XtSetArg(args[j], XtNresizable, True); j++;
4203 XtCreatePopupShell(name, topLevelShellWidgetClass,
4204 shellWidget, args, j);
4207 XtCreatePopupShell(name, transientShellWidgetClass,
4208 shellWidget, args, j);
4211 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
4212 layoutArgs, XtNumber(layoutArgs));
4214 XtCreateManagedWidget("form", formWidgetClass, layout,
4215 formArgs, XtNumber(formArgs));
4219 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
4220 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
4222 XtSetArg(args[j], XtNstring, text); j++;
4223 XtSetArg(args[j], XtNtop, XtChainTop); j++;
4224 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4225 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4226 XtSetArg(args[j], XtNright, XtChainRight); j++;
4227 XtSetArg(args[j], XtNresizable, True); j++;
4228 XtSetArg(args[j], XtNwidth, bw_width); j++; /*force wider than buttons*/
4229 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
4230 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
4231 XtSetArg(args[j], XtNautoFill, True); j++;
4232 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
4234 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
4238 XtSetArg(args[j], XtNfromVert, edit); j++;
4239 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4240 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4241 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4242 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4244 XtCreateManagedWidget(_("ok"), commandWidgetClass, form, args, j);
4245 XtAddCallback(b_ok, XtNcallback, callback, (XtPointer) 0);
4248 XtSetArg(args[j], XtNfromVert, edit); j++;
4249 XtSetArg(args[j], XtNfromHoriz, b_ok); j++;
4250 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4251 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4252 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4253 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4255 XtCreateManagedWidget(_("cancel"), commandWidgetClass, form, args, j);
4256 XtAddCallback(b_cancel, XtNcallback, callback, (XtPointer) 0);
4259 XtSetArg(args[j], XtNfromVert, edit); j++;
4260 XtSetArg(args[j], XtNfromHoriz, b_cancel); j++;
4261 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4262 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4263 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4264 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4266 XtCreateManagedWidget(_("clear"), commandWidgetClass, form, args, j);
4267 XtAddCallback(b_clear, XtNcallback, callback, (XtPointer) 0);
4270 XtSetArg(args[j], XtNfromVert, edit); j++;
4271 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4272 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4273 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4274 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4276 XtCreateManagedWidget(_("close"), commandWidgetClass, form, args, j);
4277 XtAddCallback(b_close, XtNcallback, callback, (XtPointer) 0);
4280 XtSetArg(args[j], XtNfromVert, edit); j++;
4281 XtSetArg(args[j], XtNfromHoriz, b_close); j++;
4282 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4283 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4284 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4285 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4287 XtCreateManagedWidget(_("edit"), commandWidgetClass, form, args, j);
4288 XtAddCallback(b_edit, XtNcallback, callback, (XtPointer) 0);
4291 XtRealizeWidget(shell);
4293 if (commentX == -1) {
4296 Dimension pw_height;
4297 Dimension ew_height;
4300 XtSetArg(args[j], XtNheight, &ew_height); j++;
4301 XtGetValues(edit, args, j);
4304 XtSetArg(args[j], XtNheight, &pw_height); j++;
4305 XtGetValues(shell, args, j);
4306 commentH = pw_height + (lines - 1) * ew_height;
4307 commentW = bw_width - 16;
4309 XSync(xDisplay, False);
4311 /* This code seems to tickle an X bug if it is executed too soon
4312 after xboard starts up. The coordinates get transformed as if
4313 the main window was positioned at (0, 0).
4315 XtTranslateCoords(shellWidget,
4316 (bw_width - commentW) / 2, 0 - commentH / 2,
4317 &commentX, &commentY);
4319 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
4320 RootWindowOfScreen(XtScreen(shellWidget)),
4321 (bw_width - commentW) / 2, 0 - commentH / 2,
4326 if (commentY < 0) commentY = 0; /*avoid positioning top offscreen*/
4329 XtSetArg(args[j], XtNheight, commentH); j++;
4330 XtSetArg(args[j], XtNwidth, commentW); j++;
4331 XtSetArg(args[j], XtNx, commentX); j++;
4332 XtSetArg(args[j], XtNy, commentY); j++;
4333 XtSetValues(shell, args, j);
4334 XtSetKeyboardFocus(shell, edit);
4339 /* Used for analysis window and ICS input window */
4340 Widget MiscCreate(name, text, mutable, callback, lines)
4342 int /*Boolean*/ mutable;
4343 XtCallbackProc callback;
4347 Widget shell, layout, form, edit;
4349 Dimension bw_width, pw_height, ew_height, w, h;
4355 XtSetArg(args[j], XtNresizable, True); j++;
4358 XtCreatePopupShell(name, topLevelShellWidgetClass,
4359 shellWidget, args, j);
4362 XtCreatePopupShell(name, transientShellWidgetClass,
4363 shellWidget, args, j);
4366 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
4367 layoutArgs, XtNumber(layoutArgs));
4369 XtCreateManagedWidget("form", formWidgetClass, layout,
4370 formArgs, XtNumber(formArgs));
4374 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
4375 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
4377 XtSetArg(args[j], XtNstring, text); j++;
4378 XtSetArg(args[j], XtNtop, XtChainTop); j++;
4379 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4380 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4381 XtSetArg(args[j], XtNright, XtChainRight); j++;
4382 XtSetArg(args[j], XtNresizable, True); j++;
4383 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
4384 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
4385 XtSetArg(args[j], XtNautoFill, True); j++;
4386 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
4388 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
4390 XtRealizeWidget(shell);
4393 XtSetArg(args[j], XtNwidth, &bw_width); j++;
4394 XtGetValues(boardWidget, args, j);
4397 XtSetArg(args[j], XtNheight, &ew_height); j++;
4398 XtGetValues(edit, args, j);
4401 XtSetArg(args[j], XtNheight, &pw_height); j++;
4402 XtGetValues(shell, args, j);
4403 h = pw_height + (lines - 1) * ew_height;
4406 XSync(xDisplay, False);
4408 /* This code seems to tickle an X bug if it is executed too soon
4409 after xboard starts up. The coordinates get transformed as if
4410 the main window was positioned at (0, 0).
4412 XtTranslateCoords(shellWidget, (bw_width - w) / 2, 0 - h / 2, &x, &y);
4414 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
4415 RootWindowOfScreen(XtScreen(shellWidget)),
4416 (bw_width - w) / 2, 0 - h / 2, &xx, &yy, &junk);
4420 if (y < 0) y = 0; /*avoid positioning top offscreen*/
4423 XtSetArg(args[j], XtNheight, h); j++;
4424 XtSetArg(args[j], XtNwidth, w); j++;
4425 XtSetArg(args[j], XtNx, x); j++;
4426 XtSetArg(args[j], XtNy, y); j++;
4427 XtSetValues(shell, args, j);
4433 static int savedIndex; /* gross that this is global */
4435 void EditCommentPopUp(index, title, text)
4444 if (text == NULL) text = "";
4446 if (editShell == NULL) {
4448 CommentCreate(title, text, True, EditCommentCallback, 4);
4449 XtRealizeWidget(editShell);
4450 CatchDeleteWindow(editShell, "EditCommentPopDown");
4452 edit = XtNameToWidget(editShell, "*form.text");
4454 XtSetArg(args[j], XtNstring, text); j++;
4455 XtSetValues(edit, args, j);
4457 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4458 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4459 XtSetValues(editShell, args, j);
4462 XtPopup(editShell, XtGrabNone);
4466 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
4467 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
4471 void EditCommentCallback(w, client_data, call_data)
4473 XtPointer client_data, call_data;
4481 XtSetArg(args[j], XtNlabel, &name); j++;
4482 XtGetValues(w, args, j);
4484 if (strcmp(name, _("ok")) == 0) {
4485 edit = XtNameToWidget(editShell, "*form.text");
4487 XtSetArg(args[j], XtNstring, &val); j++;
4488 XtGetValues(edit, args, j);
4489 ReplaceComment(savedIndex, val);
4490 EditCommentPopDown();
4491 } else if (strcmp(name, _("cancel")) == 0) {
4492 EditCommentPopDown();
4493 } else if (strcmp(name, _("clear")) == 0) {
4494 edit = XtNameToWidget(editShell, "*form.text");
4495 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
4496 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
4500 void EditCommentPopDown()
4505 if (!editUp) return;
4507 XtSetArg(args[j], XtNx, &commentX); j++;
4508 XtSetArg(args[j], XtNy, &commentY); j++;
4509 XtSetArg(args[j], XtNheight, &commentH); j++;
4510 XtSetArg(args[j], XtNwidth, &commentW); j++;
4511 XtGetValues(editShell, args, j);
4512 XtPopdown(editShell);
4515 XtSetArg(args[j], XtNleftBitmap, None); j++;
4516 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
4520 void ICSInputBoxPopUp()
4525 char *title = _("ICS Input");
4528 if (ICSInputShell == NULL) {
4529 ICSInputShell = MiscCreate(title, "", True, NULL, 1);
4530 tr = XtParseTranslationTable(ICSInputTranslations);
4531 edit = XtNameToWidget(ICSInputShell, "*form.text");
4532 XtOverrideTranslations(edit, tr);
4533 XtRealizeWidget(ICSInputShell);
4534 CatchDeleteWindow(ICSInputShell, "ICSInputBoxPopDown");
4537 edit = XtNameToWidget(ICSInputShell, "*form.text");
4539 XtSetArg(args[j], XtNstring, ""); j++;
4540 XtSetValues(edit, args, j);
4542 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4543 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4544 XtSetValues(ICSInputShell, args, j);
4547 XtPopup(ICSInputShell, XtGrabNone);
4548 XtSetKeyboardFocus(ICSInputShell, edit);
4550 ICSInputBoxUp = True;
4552 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
4553 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
4557 void ICSInputSendText()
4564 edit = XtNameToWidget(ICSInputShell, "*form.text");
4566 XtSetArg(args[j], XtNstring, &val); j++;
4567 XtGetValues(edit, args, j);
4568 SendMultiLineToICS(val);
4569 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
4570 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
4573 void ICSInputBoxPopDown()
4578 if (!ICSInputBoxUp) return;
4580 XtPopdown(ICSInputShell);
4581 ICSInputBoxUp = False;
4583 XtSetArg(args[j], XtNleftBitmap, None); j++;
4584 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
4588 void CommentPopUp(title, text)
4595 if (commentShell == NULL) {
4597 CommentCreate(title, text, False, CommentCallback, 4);
4598 XtRealizeWidget(commentShell);
4599 CatchDeleteWindow(commentShell, "CommentPopDown");
4601 edit = XtNameToWidget(commentShell, "*form.text");
4603 XtSetArg(args[j], XtNstring, text); j++;
4604 XtSetValues(edit, args, j);
4606 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4607 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4608 XtSetValues(commentShell, args, j);
4611 XtPopup(commentShell, XtGrabNone);
4612 XSync(xDisplay, False);
4617 void AnalysisPopUp(title, text)
4624 if (analysisShell == NULL) {
4625 analysisShell = MiscCreate(title, text, False, NULL, 4);
4626 XtRealizeWidget(analysisShell);
4627 CatchDeleteWindow(analysisShell, "AnalysisPopDown");
4630 edit = XtNameToWidget(analysisShell, "*form.text");
4632 XtSetArg(args[j], XtNstring, text); j++;
4633 XtSetValues(edit, args, j);
4635 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4636 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4637 XtSetValues(analysisShell, args, j);
4641 XtPopup(analysisShell, XtGrabNone);
4643 XSync(xDisplay, False);
4648 void CommentCallback(w, client_data, call_data)
4650 XtPointer client_data, call_data;
4657 XtSetArg(args[j], XtNlabel, &name); j++;
4658 XtGetValues(w, args, j);
4660 if (strcmp(name, _("close")) == 0) {
4662 } else if (strcmp(name, _("edit")) == 0) {
4669 void CommentPopDown()
4674 if (!commentUp) return;
4676 XtSetArg(args[j], XtNx, &commentX); j++;
4677 XtSetArg(args[j], XtNy, &commentY); j++;
4678 XtSetArg(args[j], XtNwidth, &commentW); j++;
4679 XtSetArg(args[j], XtNheight, &commentH); j++;
4680 XtGetValues(commentShell, args, j);
4681 XtPopdown(commentShell);
4682 XSync(xDisplay, False);
4686 void AnalysisPopDown()
4688 if (!analysisUp) return;
4689 XtPopdown(analysisShell);
4690 XSync(xDisplay, False);
4692 if (appData.icsEngineAnalyze) ExitAnalyzeMode(); /* [DM] icsEngineAnalyze */
4696 void FileNamePopUp(label, def, proc, openMode)
4703 Widget popup, layout, dialog, edit;
4709 fileProc = proc; /* I can't see a way not */
4710 fileOpenMode = openMode; /* to use globals here */
4713 XtSetArg(args[i], XtNresizable, True); i++;
4714 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
4715 XtSetArg(args[i], XtNtitle, XtNewString(_("File name prompt"))); i++;
4716 fileNameShell = popup =
4717 XtCreatePopupShell("File name prompt", transientShellWidgetClass,
4718 shellWidget, args, i);
4721 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
4722 layoutArgs, XtNumber(layoutArgs));
4725 XtSetArg(args[i], XtNlabel, label); i++;
4726 XtSetArg(args[i], XtNvalue, def); i++;
4727 XtSetArg(args[i], XtNborderWidth, 0); i++;
4728 dialog = XtCreateManagedWidget("fileName", dialogWidgetClass,
4731 XawDialogAddButton(dialog, _("ok"), FileNameCallback, (XtPointer) dialog);
4732 XawDialogAddButton(dialog, _("cancel"), FileNameCallback,
4733 (XtPointer) dialog);
4735 XtRealizeWidget(popup);
4736 CatchDeleteWindow(popup, "FileNamePopDown");
4738 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
4739 &x, &y, &win_x, &win_y, &mask);
4741 XtSetArg(args[0], XtNx, x - 10);
4742 XtSetArg(args[1], XtNy, y - 30);
4743 XtSetValues(popup, args, 2);
4745 XtPopup(popup, XtGrabExclusive);
4748 edit = XtNameToWidget(dialog, "*value");
4749 XtSetKeyboardFocus(popup, edit);
4752 void FileNamePopDown()
4754 if (!filenameUp) return;
4755 XtPopdown(fileNameShell);
4756 XtDestroyWidget(fileNameShell);
4761 void FileNameCallback(w, client_data, call_data)
4763 XtPointer client_data, call_data;
4768 XtSetArg(args[0], XtNlabel, &name);
4769 XtGetValues(w, args, 1);
4771 if (strcmp(name, _("cancel")) == 0) {
4776 FileNameAction(w, NULL, NULL, NULL);
4779 void FileNameAction(w, event, prms, nprms)
4791 name = XawDialogGetValueString(w = XtParent(w));
4793 if ((name != NULL) && (*name != NULLCHAR)) {
4795 XtPopdown(w = XtParent(XtParent(w)));
4799 p = strrchr(buf, ' ');
4806 fullname = ExpandPathName(buf);
4808 ErrorPopUp(_("Error"), _("Can't open file"), FALSE);
4811 f = fopen(fullname, fileOpenMode);
4813 DisplayError(_("Failed to open file"), errno);
4815 (void) (*fileProc)(f, index, buf);
4822 XtPopdown(w = XtParent(XtParent(w)));
4828 void PromotionPopUp()
4831 Widget dialog, layout;
4833 Dimension bw_width, pw_width;
4837 XtSetArg(args[j], XtNwidth, &bw_width); j++;
4838 XtGetValues(boardWidget, args, j);
4841 XtSetArg(args[j], XtNresizable, True); j++;
4842 XtSetArg(args[j], XtNtitle, XtNewString(_("Promotion"))); j++;
4844 XtCreatePopupShell("Promotion", transientShellWidgetClass,
4845 shellWidget, args, j);
4847 XtCreateManagedWidget(layoutName, formWidgetClass, promotionShell,
4848 layoutArgs, XtNumber(layoutArgs));
4851 XtSetArg(args[j], XtNlabel, _("Promote to what?")); j++;
4852 XtSetArg(args[j], XtNborderWidth, 0); j++;
4853 dialog = XtCreateManagedWidget("promotion", dialogWidgetClass,
4856 if(gameInfo.variant != VariantShogi) {
4857 XawDialogAddButton(dialog, _("Queen"), PromotionCallback,
4858 (XtPointer) dialog);
4859 XawDialogAddButton(dialog, _("Rook"), PromotionCallback,
4860 (XtPointer) dialog);
4861 XawDialogAddButton(dialog, _("Bishop"), PromotionCallback,
4862 (XtPointer) dialog);
4863 XawDialogAddButton(dialog, _("Knight"), PromotionCallback,
4864 (XtPointer) dialog);
4865 if (!appData.testLegality || gameInfo.variant == VariantSuicide ||
4866 gameInfo.variant == VariantGiveaway) {
4867 XawDialogAddButton(dialog, _("King"), PromotionCallback,
4868 (XtPointer) dialog);
4870 if(gameInfo.variant == VariantCapablanca ||
4871 gameInfo.variant == VariantGothic ||
4872 gameInfo.variant == VariantCapaRandom) {
4873 XawDialogAddButton(dialog, _("Archbishop"), PromotionCallback,
4874 (XtPointer) dialog);
4875 XawDialogAddButton(dialog, _("Chancellor"), PromotionCallback,
4876 (XtPointer) dialog);
4878 } else // [HGM] shogi
4880 XawDialogAddButton(dialog, _("Promote"), PromotionCallback,
4881 (XtPointer) dialog);
4882 XawDialogAddButton(dialog, _("Defer"), PromotionCallback,
4883 (XtPointer) dialog);
4885 XawDialogAddButton(dialog, _("cancel"), PromotionCallback,
4886 (XtPointer) dialog);
4888 XtRealizeWidget(promotionShell);
4889 CatchDeleteWindow(promotionShell, "PromotionPopDown");
4892 XtSetArg(args[j], XtNwidth, &pw_width); j++;
4893 XtGetValues(promotionShell, args, j);
4895 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
4896 lineGap + squareSize/3 +
4897 ((toY == BOARD_HEIGHT-1) ^ (flipView) ?
4898 0 : 6*(squareSize + lineGap)), &x, &y);
4901 XtSetArg(args[j], XtNx, x); j++;
4902 XtSetArg(args[j], XtNy, y); j++;
4903 XtSetValues(promotionShell, args, j);
4905 XtPopup(promotionShell, XtGrabNone);
4910 void PromotionPopDown()
4912 if (!promotionUp) return;
4913 XtPopdown(promotionShell);
4914 XtDestroyWidget(promotionShell);
4915 promotionUp = False;
4918 void PromotionCallback(w, client_data, call_data)
4920 XtPointer client_data, call_data;
4926 XtSetArg(args[0], XtNlabel, &name);
4927 XtGetValues(w, args, 1);
4931 if (fromX == -1) return;
4933 if (strcmp(name, _("cancel")) == 0) {
4937 } else if (strcmp(name, _("Knight")) == 0) {
4939 } else if (strcmp(name, _("Promote")) == 0) {
4941 } else if (strcmp(name, _("Defer")) == 0) {
4944 promoChar = ToLower(name[0]);
4947 FinishMove(NormalMove, fromX, fromY, toX, toY, promoChar);
4949 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
4950 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
4955 void ErrorCallback(w, client_data, call_data)
4957 XtPointer client_data, call_data;
4960 XtPopdown(w = XtParent(XtParent(XtParent(w))));
4962 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
4968 if (!errorUp) return;
4972 gtk_widget_destroy(GTK_WIDGET(GUI_Error));
4974 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
4979 void ErrorPopUp(title, label, modal)
4980 char *title, *label;
4983 GUI_Error = gtk_message_dialog_new(GTK_WINDOW(GUI_Window),
4984 GTK_DIALOG_DESTROY_WITH_PARENT,
4989 gtk_window_set_title(GTK_WINDOW(GUI_Error),(gchar *) title);
4992 gtk_dialog_run(GTK_DIALOG(GUI_Error));
4993 gtk_widget_destroy(GTK_WIDGET(GUI_Error));
4997 g_signal_connect_swapped (GUI_Error, "response",
4998 G_CALLBACK (ErrorPopDownProc),
5001 gtk_widget_show(GTK_WIDGET(GUI_Error));
5007 /* Disable all user input other than deleting the window */
5008 static int frozen = 0;
5012 /* Grab by a widget that doesn't accept input */
5013 // XtAddGrab(messageWidget, TRUE, FALSE);
5017 /* Undo a FreezeUI */
5020 if (!frozen) return;
5021 // XtRemoveGrab(messageWidget);
5025 char *ModeToWidgetName(mode)
5029 case BeginningOfGame:
5030 if (appData.icsActive)
5031 return "menuMode.ICS Client";
5032 else if (appData.noChessProgram ||
5033 *appData.cmailGameName != NULLCHAR)
5034 return "menuMode.Edit Game";
5036 return "menuMode.Machine Black";
5037 case MachinePlaysBlack:
5038 return "menuMode.Machine Black";
5039 case MachinePlaysWhite:
5040 return "menuMode.Machine White";
5042 return "menuMode.Analysis Mode";
5044 return "menuMode.Analyze File";
5045 case TwoMachinesPlay:
5046 return "menuMode.Two Machines";
5048 return "menuMode.Edit Game";
5049 case PlayFromGameFile:
5050 return "menuFile.Load Game";
5052 return "menuMode.Edit Position";
5054 return "menuMode.Training";
5055 case IcsPlayingWhite:
5056 case IcsPlayingBlack:
5060 return "menuMode.ICS Client";
5067 void ModeHighlight()
5069 static int oldPausing = FALSE;
5070 static GameMode oldmode = (GameMode) -1;
5073 // todo this toggling of the pause button doesn't seem to work?
5074 // e.g. select pause from buttonbar doesn't activate menumode.pause
5076 // if (!boardWidget || !XtIsRealized(boardWidget)) return;
5078 if (pausing != oldPausing) {
5079 oldPausing = pausing;
5080 gtk_button_set_relief(GTK_BUTTON (gtk_builder_get_object (builder, "menuMode.Pause")),pausing?GTK_RELIEF_NORMAL:GTK_RELIEF_NONE);
5081 /* toggle background color in showbuttonbar */
5082 if (appData.showButtonBar) {
5084 gtk_button_pressed(GTK_BUTTON (gtk_builder_get_object (builder, "buttonbar.Pause")));
5086 gtk_button_released(GTK_BUTTON (gtk_builder_get_object (builder, "buttonbar.Pause")));
5091 wname = ModeToWidgetName(oldmode);
5093 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, wname)),True);
5097 /* Maybe all the enables should be handled here, not just this one */
5098 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuMode.Training")),
5099 gameMode == Training || gameMode == PlayFromGameFile);
5104 * Button/menu procedures
5107 int LoadGamePopUp(f, gameNumber, title)
5112 cmailMsgLoaded = FALSE;
5114 if (gameNumber == 0)
5116 int error = GameListBuild(f);
5120 DisplayError(_("Cannot build game list"), error);
5122 else if (!ListEmpty(&gameList)
5123 && ((ListGame *) gameList.tailPred)->number > 1)
5125 GameListPopUp(f, title);
5133 return LoadGame(f, gameNumber, title, FALSE);
5136 void LoadPositionProc(w, event, prms, nprms)
5142 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
5145 FileNamePopUp(_("Load position file name?"), "", LoadPosition, "rb");
5148 void SaveGameProc(w, event, prms, nprms)
5154 FileNamePopUp(_("Save game file name?"),
5155 DefaultFileName(appData.oldSaveStyle ? "game" : "pgn"),
5159 void SavePositionProc(w, event, prms, nprms)
5165 FileNamePopUp(_("Save position file name?"),
5166 DefaultFileName(appData.oldSaveStyle ? "pos" : "fen"),
5170 void ReloadCmailMsgProc(w, event, prms, nprms)
5176 ReloadCmailMsgEvent(FALSE);
5179 void MailMoveProc(w, event, prms, nprms)
5188 /* this variable is shared between CopyPositionProc and SendPositionSelection */
5189 static char *selected_fen_position=NULL;
5192 SendPositionSelection(Widget w, Atom *selection, Atom *target,
5193 Atom *type_return, XtPointer *value_return,
5194 unsigned long *length_return, int *format_return)
5196 char *selection_tmp;
5198 if (!selected_fen_position) return False; /* should never happen */
5199 if (*target == XA_STRING){
5200 /* note: since no XtSelectionDoneProc was registered, Xt will
5201 * automatically call XtFree on the value returned. So have to
5202 * make a copy of it allocated with XtMalloc */
5203 selection_tmp= XtMalloc(strlen(selected_fen_position)+16);
5204 strcpy(selection_tmp, selected_fen_position);
5206 *value_return=selection_tmp;
5207 *length_return=strlen(selection_tmp);
5208 *type_return=XA_STRING;
5209 *format_return = 8; /* bits per byte */
5216 /* note: when called from menu all parameters are NULL, so no clue what the
5217 * Widget which was clicked on was, or what the click event was
5219 void CopyPositionProc(w, event, prms, nprms)
5227 if (selected_fen_position) free(selected_fen_position);
5228 selected_fen_position = (char *)PositionToFEN(currentMove, NULL);
5229 if (!selected_fen_position) return;
5230 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
5232 SendPositionSelection,
5233 NULL/* lose_ownership_proc */ ,
5234 NULL/* transfer_done_proc */);
5236 free(selected_fen_position);
5237 selected_fen_position=NULL;
5241 /* function called when the data to Paste is ready */
5243 PastePositionCB(Widget w, XtPointer client_data, Atom *selection,
5244 Atom *type, XtPointer value, unsigned long *len, int *format)
5247 if (value==NULL || *len==0) return; /* nothing had been selected to copy */
5248 fenstr[*len]='\0'; /* normally this string is terminated, but be safe */
5249 EditPositionPasteFEN(fenstr);
5253 /* called when Paste Position button is pressed,
5254 * all parameters will be NULL */
5255 void PastePositionProc(w, event, prms, nprms)
5261 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
5262 /* (XtSelectionCallbackProc) */ PastePositionCB,
5263 NULL, /* client_data passed to PastePositionCB */
5265 /* better to use the time field from the event that triggered the
5266 * call to this function, but that isn't trivial to get
5274 SendGameSelection(Widget w, Atom *selection, Atom *target,
5275 Atom *type_return, XtPointer *value_return,
5276 unsigned long *length_return, int *format_return)
5278 char *selection_tmp;
5280 if (*target == XA_STRING){
5281 FILE* f = fopen(gameCopyFilename, "r");
5284 if (f == NULL) return False;
5288 selection_tmp = XtMalloc(len + 1);
5289 count = fread(selection_tmp, 1, len, f);
5291 XtFree(selection_tmp);
5294 selection_tmp[len] = NULLCHAR;
5295 *value_return = selection_tmp;
5296 *length_return = len;
5297 *type_return = XA_STRING;
5298 *format_return = 8; /* bits per byte */
5305 /* note: when called from menu all parameters are NULL, so no clue what the
5306 * Widget which was clicked on was, or what the click event was
5308 void CopyGameProc(w, event, prms, nprms)
5316 ret = SaveGameToFile(gameCopyFilename, FALSE);
5319 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
5322 NULL/* lose_ownership_proc */ ,
5323 NULL/* transfer_done_proc */);
5326 /* function called when the data to Paste is ready */
5328 PasteGameCB(Widget w, XtPointer client_data, Atom *selection,
5329 Atom *type, XtPointer value, unsigned long *len, int *format)
5332 if (value == NULL || *len == 0) {
5333 return; /* nothing had been selected to copy */
5335 f = fopen(gamePasteFilename, "w");
5337 DisplayError(_("Can't open temp file"), errno);
5340 fwrite(value, 1, *len, f);
5343 LoadGameFromFile(gamePasteFilename, 0, gamePasteFilename, TRUE);
5346 /* called when Paste Game button is pressed,
5347 * all parameters will be NULL */
5348 void PasteGameProc(w, event, prms, nprms)
5354 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
5355 /* (XtSelectionCallbackProc) */ PasteGameCB,
5356 NULL, /* client_data passed to PasteGameCB */
5358 /* better to use the time field from the event that triggered the
5359 * call to this function, but that isn't trivial to get
5369 SaveGameProc(NULL, NULL, NULL, NULL);
5372 void AnalyzeModeProc(w, event, prms, nprms)
5380 if (!first.analysisSupport) {
5381 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
5382 DisplayError(buf, 0);
5385 /* [DM] icsEngineAnalyze [HGM] This is horrible code; reverse the gameMode and isEngineAnalyze tests! */
5386 if (appData.icsActive) {
5387 if (gameMode != IcsObserving) {
5388 sprintf(buf,_("You are not observing a game"));
5389 DisplayError(buf, 0);
5391 if (appData.icsEngineAnalyze) {
5392 if (appData.debugMode)
5393 fprintf(debugFP, _("Found unexpected active ICS engine analyze \n"));
5399 /* if enable, use want disable icsEngineAnalyze */
5400 if (appData.icsEngineAnalyze) {
5405 appData.icsEngineAnalyze = TRUE;
5406 if (appData.debugMode)
5407 fprintf(debugFP, _("ICS engine analyze starting... \n"));
5409 if (!appData.showThinking)
5410 ShowThinkingProc(NULL,NULL);
5415 void AnalyzeFileProc(w, event, prms, nprms)
5421 if (!first.analysisSupport) {
5423 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
5424 DisplayError(buf, 0);
5429 if (!appData.showThinking)
5430 ShowThinkingProc(NULL,NULL);
5433 FileNamePopUp(_("File to analyze"), "", LoadGamePopUp, "rb");
5434 AnalysisPeriodicEvent(1);
5438 void EditGameProc(w, event, prms, nprms)
5447 void EditPositionProc(w, event, prms, nprms)
5453 EditPositionEvent();
5456 void TrainingProc(w, event, prms, nprms)
5465 void EditCommentProc(w, event, prms, nprms)
5472 EditCommentPopDown();
5478 void IcsInputBoxProc(w, event, prms, nprms)
5484 if (ICSInputBoxUp) {
5485 ICSInputBoxPopDown();
5492 void EnterKeyProc(w, event, prms, nprms)
5498 if (ICSInputBoxUp == True)
5502 void AlwaysQueenProc(w, event, prms, nprms)
5510 appData.alwaysPromoteToQueen = !appData.alwaysPromoteToQueen;
5512 if (appData.alwaysPromoteToQueen) {
5513 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5515 XtSetArg(args[0], XtNleftBitmap, None);
5517 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
5521 void AnimateDraggingProc(w, event, prms, nprms)
5529 appData.animateDragging = !appData.animateDragging;
5531 if (appData.animateDragging) {
5532 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5535 XtSetArg(args[0], XtNleftBitmap, None);
5537 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Dragging"),
5541 void AnimateMovingProc(w, event, prms, nprms)
5549 appData.animate = !appData.animate;
5551 if (appData.animate) {
5552 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5555 XtSetArg(args[0], XtNleftBitmap, None);
5557 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
5561 void AutobsProc(w, event, prms, nprms)
5569 appData.autoObserve = !appData.autoObserve;
5571 if (appData.autoObserve) {
5572 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5574 XtSetArg(args[0], XtNleftBitmap, None);
5576 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
5580 void AutoraiseProc(w, event, prms, nprms)
5588 appData.autoRaiseBoard = !appData.autoRaiseBoard;
5590 if (appData.autoRaiseBoard) {
5591 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5593 XtSetArg(args[0], XtNleftBitmap, None);
5595 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Raise Board"),
5599 void AutosaveProc(w, event, prms, nprms)
5607 appData.autoSaveGames = !appData.autoSaveGames;
5609 if (appData.autoSaveGames) {
5610 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5612 XtSetArg(args[0], XtNleftBitmap, None);
5614 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
5618 void BlindfoldProc(w, event, prms, nprms)
5626 appData.blindfold = !appData.blindfold;
5628 if (appData.blindfold) {
5629 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5631 XtSetArg(args[0], XtNleftBitmap, None);
5633 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Blindfold"),
5636 DrawPosition(True, NULL);
5639 void TestLegalityProc(w, event, prms, nprms)
5647 appData.testLegality = !appData.testLegality;
5649 if (appData.testLegality) {
5650 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5652 XtSetArg(args[0], XtNleftBitmap, None);
5654 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Test Legality"),
5659 void FlashMovesProc(w, event, prms, nprms)
5667 if (appData.flashCount == 0) {
5668 appData.flashCount = 3;
5670 appData.flashCount = -appData.flashCount;
5673 if (appData.flashCount > 0) {
5674 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5676 XtSetArg(args[0], XtNleftBitmap, None);
5678 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flash Moves"),
5683 void HighlightDraggingProc(w, event, prms, nprms)
5691 appData.highlightDragging = !appData.highlightDragging;
5693 if (appData.highlightDragging) {
5694 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5696 XtSetArg(args[0], XtNleftBitmap, None);
5698 XtSetValues(XtNameToWidget(menuBarWidget,
5699 "menuOptions.Highlight Dragging"), args, 1);
5703 void HighlightLastMoveProc(w, event, prms, nprms)
5711 appData.highlightLastMove = !appData.highlightLastMove;
5713 if (appData.highlightLastMove) {
5714 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5716 XtSetArg(args[0], XtNleftBitmap, None);
5718 XtSetValues(XtNameToWidget(menuBarWidget,
5719 "menuOptions.Highlight Last Move"), args, 1);
5722 void IcsAlarmProc(w, event, prms, nprms)
5730 appData.icsAlarm = !appData.icsAlarm;
5732 if (appData.icsAlarm) {
5733 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5735 XtSetArg(args[0], XtNleftBitmap, None);
5737 XtSetValues(XtNameToWidget(menuBarWidget,
5738 "menuOptions.ICS Alarm"), args, 1);
5741 void MoveSoundProc(w, event, prms, nprms)
5749 appData.ringBellAfterMoves = !appData.ringBellAfterMoves;
5751 if (appData.ringBellAfterMoves) {
5752 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5754 XtSetArg(args[0], XtNleftBitmap, None);
5756 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
5761 void OldSaveStyleProc(w, event, prms, nprms)
5769 appData.oldSaveStyle = !appData.oldSaveStyle;
5771 if (appData.oldSaveStyle) {
5772 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5774 XtSetArg(args[0], XtNleftBitmap, None);
5776 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Old Save Style"),
5780 void PeriodicUpdatesProc(w, event, prms, nprms)
5788 PeriodicUpdatesEvent(!appData.periodicUpdates);
5790 if (appData.periodicUpdates) {
5791 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5793 XtSetArg(args[0], XtNleftBitmap, None);
5795 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Periodic Updates"),
5799 void PonderNextMoveProc(w, event, prms, nprms)
5807 PonderNextMoveEvent(!appData.ponderNextMove);
5809 if (appData.ponderNextMove) {
5810 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5812 XtSetArg(args[0], XtNleftBitmap, None);
5814 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Ponder Next Move"),
5818 void PopupExitMessageProc(w, event, prms, nprms)
5826 appData.popupExitMessage = !appData.popupExitMessage;
5828 if (appData.popupExitMessage) {
5829 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5831 XtSetArg(args[0], XtNleftBitmap, None);
5833 XtSetValues(XtNameToWidget(menuBarWidget,
5834 "menuOptions.Popup Exit Message"), args, 1);
5837 void PopupMoveErrorsProc(w, event, prms, nprms)
5845 appData.popupMoveErrors = !appData.popupMoveErrors;
5847 if (appData.popupMoveErrors) {
5848 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5850 XtSetArg(args[0], XtNleftBitmap, None);
5852 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Popup Move Errors"),
5856 void PremoveProc(w, event, prms, nprms)
5864 appData.premove = !appData.premove;
5866 if (appData.premove) {
5867 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5869 XtSetArg(args[0], XtNleftBitmap, None);
5871 XtSetValues(XtNameToWidget(menuBarWidget,
5872 "menuOptions.Premove"), args, 1);
5875 void QuietPlayProc(w, event, prms, nprms)
5883 appData.quietPlay = !appData.quietPlay;
5885 if (appData.quietPlay) {
5886 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5888 XtSetArg(args[0], XtNleftBitmap, None);
5890 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Quiet Play"),
5894 void DebugProc(w, event, prms, nprms)
5900 appData.debugMode = !appData.debugMode;
5903 void AboutGameProc(w, event, prms, nprms)
5912 void NothingProc(w, event, prms, nprms)
5921 void Iconify(w, event, prms, nprms)
5930 XtSetArg(args[0], XtNiconic, True);
5931 XtSetValues(shellWidget, args, 1);
5934 void DisplayMessage(message, extMessage)
5935 gchar *message, *extMessage;
5942 snprintf(buf, sizeof(buf), "%s %s", message, extMessage);
5945 message = extMessage;
5948 gtk_label_set_text( GTK_LABEL(gtk_builder_get_object (builder, "Messages")),message);
5953 void DisplayTitle(text)
5956 gchar title[MSG_SIZ];
5958 if (text == NULL) text = "";
5960 if (appData.titleInWindow)
5965 if (*text != NULLCHAR)
5967 strcpy(title, text);
5969 else if (appData.icsActive)
5971 snprintf(title, sizeof(title), "%s: %s", programName, appData.icsHost);
5973 else if (appData.cmailGameName[0] != NULLCHAR)
5975 snprintf(title,sizeof(title), "%s: %s", programName, "CMail");
5977 // [HGM] license: This stuff should really be done in back-end, but WinBoard already had a pop-up for it
5979 else if (gameInfo.variant == VariantGothic)
5981 strcpy(title, GOTHIC);
5985 else if (gameInfo.variant == VariantFalcon)
5987 strcpy(title, FALCON);
5990 else if (appData.noChessProgram)
5992 strcpy(title, programName);
5996 snprintf(title,sizeof(title), "%s: %s", programName, first.tidy);
5998 gtk_window_set_title(GTK_WINDOW(GUI_Window),title);
6004 void DisplayError(message, error)
6011 if (appData.debugMode || appData.matchMode) {
6012 fprintf(stderr, "%s: %s\n", programName, message);
6015 if (appData.debugMode || appData.matchMode) {
6016 fprintf(stderr, "%s: %s: %s\n",
6017 programName, message, strerror(error));
6019 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
6022 ErrorPopUp(_("Error"), message, FALSE);
6026 void DisplayMoveError(message)
6031 DrawPosition(FALSE, NULL);
6032 if (appData.debugMode || appData.matchMode) {
6033 fprintf(stderr, "%s: %s\n", programName, message);
6035 if (appData.popupMoveErrors) {
6036 ErrorPopUp(_("Error"), message, FALSE);
6038 DisplayMessage(message, "");
6043 void DisplayFatalError(message, error, status)
6049 errorExitStatus = status;
6051 fprintf(stderr, "%s: %s\n", programName, message);
6053 fprintf(stderr, "%s: %s: %s\n",
6054 programName, message, strerror(error));
6055 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
6058 if (appData.popupExitMessage && boardWidget && XtIsRealized(boardWidget)) {
6059 ErrorPopUp(status ? _("Fatal Error") : _("Exiting"), message, TRUE);
6065 void DisplayInformation(message)
6069 ErrorPopUp(_("Information"), message, TRUE);
6072 void DisplayNote(message)
6076 ErrorPopUp(_("Note"), message, FALSE);
6080 NullXErrorCheck(dpy, error_event)
6082 XErrorEvent *error_event;
6087 void DisplayIcsInteractionTitle(message)
6090 if (oldICSInteractionTitle == NULL) {
6091 /* Magic to find the old window title, adapted from vim */
6092 char *wina = getenv("WINDOWID");
6094 Window win = (Window) atoi(wina);
6095 Window root, parent, *children;
6096 unsigned int nchildren;
6097 int (*oldHandler)() = XSetErrorHandler(NullXErrorCheck);
6099 if (XFetchName(xDisplay, win, &oldICSInteractionTitle)) break;
6100 if (!XQueryTree(xDisplay, win, &root, &parent,
6101 &children, &nchildren)) break;
6102 if (children) XFree((void *)children);
6103 if (parent == root || parent == 0) break;
6106 XSetErrorHandler(oldHandler);
6108 if (oldICSInteractionTitle == NULL) {
6109 oldICSInteractionTitle = "xterm";
6112 printf("\033]0;%s\007", message);
6116 char pendingReplyPrefix[MSG_SIZ];
6117 ProcRef pendingReplyPR;
6119 void AskQuestionProc(w, event, prms, nprms)
6126 fprintf(stderr, _("AskQuestionProc needed 4 parameters, got %d\n"),
6130 AskQuestionEvent(prms[0], prms[1], prms[2], prms[3]);
6133 void AskQuestionPopDown()
6135 if (!askQuestionUp) return;
6136 XtPopdown(askQuestionShell);
6137 XtDestroyWidget(askQuestionShell);
6138 askQuestionUp = False;
6141 void AskQuestionReplyAction(w, event, prms, nprms)
6151 reply = XawDialogGetValueString(w = XtParent(w));
6152 strcpy(buf, pendingReplyPrefix);
6153 if (*buf) strcat(buf, " ");
6156 OutputToProcess(pendingReplyPR, buf, strlen(buf), &err);
6157 AskQuestionPopDown();
6159 if (err) DisplayFatalError(_("Error writing to chess program"), err, 0);
6162 void AskQuestionCallback(w, client_data, call_data)
6164 XtPointer client_data, call_data;
6169 XtSetArg(args[0], XtNlabel, &name);
6170 XtGetValues(w, args, 1);
6172 if (strcmp(name, _("cancel")) == 0) {
6173 AskQuestionPopDown();
6175 AskQuestionReplyAction(w, NULL, NULL, NULL);
6179 void AskQuestion(title, question, replyPrefix, pr)
6180 char *title, *question, *replyPrefix;
6184 Widget popup, layout, dialog, edit;
6190 strcpy(pendingReplyPrefix, replyPrefix);
6191 pendingReplyPR = pr;
6194 XtSetArg(args[i], XtNresizable, True); i++;
6195 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
6196 askQuestionShell = popup =
6197 XtCreatePopupShell(title, transientShellWidgetClass,
6198 shellWidget, args, i);
6201 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
6202 layoutArgs, XtNumber(layoutArgs));
6205 XtSetArg(args[i], XtNlabel, question); i++;
6206 XtSetArg(args[i], XtNvalue, ""); i++;
6207 XtSetArg(args[i], XtNborderWidth, 0); i++;
6208 dialog = XtCreateManagedWidget("question", dialogWidgetClass,
6211 XawDialogAddButton(dialog, _("enter"), AskQuestionCallback,
6212 (XtPointer) dialog);
6213 XawDialogAddButton(dialog, _("cancel"), AskQuestionCallback,
6214 (XtPointer) dialog);
6216 XtRealizeWidget(popup);
6217 CatchDeleteWindow(popup, "AskQuestionPopDown");
6219 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
6220 &x, &y, &win_x, &win_y, &mask);
6222 XtSetArg(args[0], XtNx, x - 10);
6223 XtSetArg(args[1], XtNy, y - 30);
6224 XtSetValues(popup, args, 2);
6226 XtPopup(popup, XtGrabExclusive);
6227 askQuestionUp = True;
6229 edit = XtNameToWidget(dialog, "*value");
6230 XtSetKeyboardFocus(popup, edit);
6238 if (*name == NULLCHAR) {
6240 } else if (strcmp(name, "$") == 0) {
6241 putc(BELLCHAR, stderr);
6244 snprintf(buf, sizeof(buf), "%s '%s' &", appData.soundProgram, name);
6252 PlaySound(appData.soundMove);
6258 PlaySound(appData.soundIcsWin);
6264 PlaySound(appData.soundIcsLoss);
6270 PlaySound(appData.soundIcsDraw);
6274 PlayIcsUnfinishedSound()
6276 PlaySound(appData.soundIcsUnfinished);
6282 PlaySound(appData.soundIcsAlarm);
6288 system("stty echo");
6294 system("stty -echo");
6298 Colorize(cc, continuation)
6303 int count, outCount, error;
6305 if (textColors[(int)cc].bg > 0) {
6306 if (textColors[(int)cc].fg > 0) {
6307 sprintf(buf, "\033[0;%d;%d;%dm", textColors[(int)cc].attr,
6308 textColors[(int)cc].fg, textColors[(int)cc].bg);
6310 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
6311 textColors[(int)cc].bg);
6314 if (textColors[(int)cc].fg > 0) {
6315 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
6316 textColors[(int)cc].fg);
6318 sprintf(buf, "\033[0;%dm", textColors[(int)cc].attr);
6321 count = strlen(buf);
6322 outCount = OutputToProcess(NoProc, buf, count, &error);
6323 if (outCount < count) {
6324 DisplayFatalError(_("Error writing to display"), error, 1);
6327 if (continuation) return;
6330 PlaySound(appData.soundShout);
6333 PlaySound(appData.soundSShout);
6336 PlaySound(appData.soundChannel1);
6339 PlaySound(appData.soundChannel);
6342 PlaySound(appData.soundKibitz);
6345 PlaySound(appData.soundTell);
6347 case ColorChallenge:
6348 PlaySound(appData.soundChallenge);
6351 PlaySound(appData.soundRequest);
6354 PlaySound(appData.soundSeek);
6365 return getpwuid(getuid())->pw_name;
6368 static char *ExpandPathName(path)
6371 static char static_buf[2000];
6372 char *d, *s, buf[2000];
6378 while (*s && isspace(*s))
6387 if (*(s+1) == '/') {
6388 strcpy(d, getpwuid(getuid())->pw_dir);
6393 *strchr(buf, '/') = 0;
6394 pwd = getpwnam(buf);
6397 fprintf(stderr, _("ERROR: Unknown user %s (in path %s)\n"),
6401 strcpy(d, pwd->pw_dir);
6402 strcat(d, strchr(s+1, '/'));
6413 static char host_name[MSG_SIZ];
6415 #if HAVE_GETHOSTNAME
6416 gethostname(host_name, MSG_SIZ);
6418 #else /* not HAVE_GETHOSTNAME */
6419 # if HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H
6420 sysinfo(SI_HOSTNAME, host_name, MSG_SIZ);
6422 # else /* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
6424 # endif/* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
6425 #endif /* not HAVE_GETHOSTNAME */
6428 guint delayedEventTimerTag = 0;
6429 DelayedEventCallback delayedEventCallback = 0;
6432 FireDelayedEvent(data)
6436 g_source_remove(delayedEventTimerTag);
6437 delayedEventTimerTag = 0;
6440 delayedEventCallback();
6446 ScheduleDelayedEvent(cb, millisec)
6447 DelayedEventCallback cb; guint millisec;
6449 if(delayedEventTimerTag && delayedEventCallback == cb)
6450 // [HGM] alive: replace, rather than add or flush identical event
6451 g_source_remove(delayedEventTimerTag);
6452 delayedEventCallback = cb;
6453 delayedEventTimerTag = g_timeout_add(millisec,(GSourceFunc) FireDelayedEvent, NULL);
6457 DelayedEventCallback
6460 if (delayedEventTimerTag)
6462 return delayedEventCallback;
6471 CancelDelayedEvent()
6473 if (delayedEventTimerTag)
6475 g_source_remove(delayedEventTimerTag);
6476 delayedEventTimerTag = 0;
6482 guint loadGameTimerTag = 0;
6484 int LoadGameTimerRunning()
6486 return loadGameTimerTag != 0;
6489 int StopLoadGameTimer()
6491 if (loadGameTimerTag != 0) {
6492 g_source_remove(loadGameTimerTag);
6493 loadGameTimerTag = 0;
6501 LoadGameTimerCallback(data)
6505 g_source_remove(loadGameTimerTag);
6506 loadGameTimerTag = 0;
6513 StartLoadGameTimer(millisec)
6517 g_timeout_add( millisec, (GSourceFunc) LoadGameTimerCallback, NULL);
6521 guint analysisClockTag = 0;
6524 AnalysisClockCallback(data)
6527 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile
6528 || appData.icsEngineAnalyze)
6530 AnalysisPeriodicEvent(0);
6531 return 1; /* keep on going */
6533 return 0; /* stop timer */
6537 StartAnalysisClock()
6540 g_timeout_add( 2000,(GSourceFunc) AnalysisClockCallback, NULL);
6544 guint clockTimerTag = 0;
6546 int ClockTimerRunning()
6548 return clockTimerTag != 0;
6551 int StopClockTimer()
6553 if (clockTimerTag != 0)
6555 g_source_remove(clockTimerTag);
6566 ClockTimerCallback(data)
6570 g_source_remove(clockTimerTag);
6578 StartClockTimer(millisec)
6581 clockTimerTag = g_timeout_add(millisec,(GSourceFunc) ClockTimerCallback,NULL);
6586 DisplayTimerLabel(w, color, timer, highlight)
6595 if (appData.clockMode) {
6596 sprintf(buf, "%s: %s", color, TimeString(timer));
6598 sprintf(buf, "%s ", color);
6600 gtk_label_set_text(GTK_LABEL(w),buf);
6602 /* check for low time warning */
6603 // Pixel foregroundOrWarningColor = timerForegroundPixel;
6606 // appData.lowTimeWarning &&
6607 // (timer / 1000) < appData.icsAlarmTime)
6608 // foregroundOrWarningColor = lowTimeWarningColor;
6610 // if (appData.clockMode) {
6611 // sprintf(buf, "%s: %s", color, TimeString(timer));
6612 // XtSetArg(args[0], XtNlabel, buf);
6614 // sprintf(buf, "%s ", color);
6615 // XtSetArg(args[0], XtNlabel, buf);
6620 // XtSetArg(args[1], XtNbackground, foregroundOrWarningColor);
6621 // XtSetArg(args[2], XtNforeground, timerBackgroundPixel);
6623 // XtSetArg(args[1], XtNbackground, timerBackgroundPixel);
6624 // XtSetArg(args[2], XtNforeground, foregroundOrWarningColor);
6627 // XtSetValues(w, args, 3);
6632 DisplayWhiteClock(timeRemaining, highlight)
6636 if(appData.noGUI) return;
6638 DisplayTimerLabel(GUI_Whiteclock, _("White"), timeRemaining, highlight);
6639 if (highlight && WindowIcon == BlackIcon)
6641 WindowIcon = WhiteIcon;
6642 gtk_window_set_icon(GTK_WINDOW(GUI_Window),WindowIcon);
6647 DisplayBlackClock(timeRemaining, highlight)
6651 if(appData.noGUI) return;
6653 DisplayTimerLabel(GUI_Blackclock, _("Black"), timeRemaining, highlight);
6654 if (highlight && WindowIcon == WhiteIcon)
6656 WindowIcon = BlackIcon;
6657 gtk_window_set_icon(GTK_WINDOW(GUI_Window),WindowIcon);
6675 int StartChildProcess(cmdLine, dir, pr)
6682 int to_prog[2], from_prog[2];
6686 if (appData.debugMode) {
6687 fprintf(stderr, "StartChildProcess (dir=\"%s\") %s\n",dir, cmdLine);
6690 /* We do NOT feed the cmdLine to the shell; we just
6691 parse it into blank-separated arguments in the
6692 most simple-minded way possible.
6695 strcpy(buf, cmdLine);
6700 if (p == NULL) break;
6705 SetUpChildIO(to_prog, from_prog);
6707 if ((pid = fork()) == 0) {
6709 // [HGM] PSWBTM: made order resistant against case where fd of created pipe was 0 or 1
6710 close(to_prog[1]); // first close the unused pipe ends
6711 close(from_prog[0]);
6712 dup2(to_prog[0], 0); // to_prog was created first, nd is the only one to use 0 or 1
6713 dup2(from_prog[1], 1);
6714 if(to_prog[0] >= 2) close(to_prog[0]); // if 0 or 1, the dup2 already cosed the original
6715 close(from_prog[1]); // and closing again loses one of the pipes!
6716 if(fileno(stderr) >= 2) // better safe than sorry...
6717 dup2(1, fileno(stderr)); /* force stderr to the pipe */
6719 if (dir[0] != NULLCHAR && chdir(dir) != 0) {
6724 nice(appData.niceEngines); // [HGM] nice: adjust priority of engine proc
6726 execvp(argv[0], argv);
6728 /* If we get here, exec failed */
6733 /* Parent process */
6735 close(from_prog[1]);
6737 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
6740 cp->fdFrom = from_prog[0];
6741 cp->fdTo = to_prog[1];
6746 // [HGM] kill: implement the 'hard killing' of AS's Winboard_x
6747 static RETSIGTYPE AlarmCallBack(int n)
6753 DestroyChildProcess(pr, signalType)
6757 ChildProc *cp = (ChildProc *) pr;
6759 if (cp->kind != CPReal) return;
6761 if (signalType == 10) { // [HGM] kill: if it does not terminate in 3 sec, kill
6762 signal(SIGALRM, AlarmCallBack);
6764 if(wait((int *) 0) == -1) { // process does not terminate on its own accord
6765 kill(cp->pid, SIGKILL); // kill it forcefully
6766 wait((int *) 0); // and wait again
6770 kill(cp->pid, signalType == 9 ? SIGKILL : SIGTERM); // [HGM] kill: use hard kill if so requested
6772 /* Process is exiting either because of the kill or because of
6773 a quit command sent by the backend; either way, wait for it to die.
6782 InterruptChildProcess(pr)
6785 ChildProc *cp = (ChildProc *) pr;
6787 if (cp->kind != CPReal) return;
6788 (void) kill(cp->pid, SIGINT); /* stop it thinking */
6791 int OpenTelnet(host, port, pr)
6796 char cmdLine[MSG_SIZ];
6798 if (port[0] == NULLCHAR) {
6799 snprintf(cmdLine, sizeof(cmdLine), "%s %s", appData.telnetProgram, host);
6801 snprintf(cmdLine, sizeof(cmdLine), "%s %s %s", appData.telnetProgram, host, port);
6803 return StartChildProcess(cmdLine, "", pr);
6806 int OpenTCP(host, port, pr)
6812 DisplayFatalError(_("Socket support is not configured in"), 0, 2);
6813 #else /* !OMIT_SOCKETS */
6815 struct sockaddr_in sa;
6817 unsigned short uport;
6820 if ((s = socket(AF_INET, SOCK_STREAM, 6)) < 0) {
6824 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
6825 sa.sin_family = AF_INET;
6826 sa.sin_addr.s_addr = INADDR_ANY;
6827 uport = (unsigned short) 0;
6828 sa.sin_port = htons(uport);
6829 if (bind(s, (struct sockaddr *) &sa, sizeof(struct sockaddr_in)) < 0) {
6833 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
6834 if (!(hp = gethostbyname(host))) {
6836 if (sscanf(host, "%d.%d.%d.%d", &b0, &b1, &b2, &b3) == 4) {
6837 hp = (struct hostent *) calloc(1, sizeof(struct hostent));
6838 hp->h_addrtype = AF_INET;
6840 hp->h_addr_list = (char **) calloc(2, sizeof(char *));
6841 hp->h_addr_list[0] = (char *) malloc(4);
6842 hp->h_addr_list[0][0] = b0;
6843 hp->h_addr_list[0][1] = b1;
6844 hp->h_addr_list[0][2] = b2;
6845 hp->h_addr_list[0][3] = b3;
6850 sa.sin_family = hp->h_addrtype;
6851 uport = (unsigned short) atoi(port);
6852 sa.sin_port = htons(uport);
6853 memcpy((char *) &sa.sin_addr, hp->h_addr, hp->h_length);
6855 if (connect(s, (struct sockaddr *) &sa,
6856 sizeof(struct sockaddr_in)) < 0) {
6860 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
6867 #endif /* !OMIT_SOCKETS */
6872 int OpenCommPort(name, pr)
6879 fd = open(name, 2, 0);
6880 if (fd < 0) return errno;
6882 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
6892 int OpenLoopback(pr)
6898 SetUpChildIO(to, from);
6900 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
6903 cp->fdFrom = to[0]; /* note not from[0]; we are doing a loopback */
6910 int OpenRcmd(host, user, cmd, pr)
6911 char *host, *user, *cmd;
6914 DisplayFatalError(_("internal rcmd not implemented for Unix"), 0, 1);
6918 #define INPUT_SOURCE_BUF_SIZE 8192
6927 char buf[INPUT_SOURCE_BUF_SIZE];
6932 DoInputCallback(io,cond,data)
6937 /* read input from one of the input source (for example a chess program, ICS, etc).
6938 * and call a function that will handle the input
6941 int count; /* how many bytes did we read */
6945 /* All information (callback function, file descriptor, etc) is
6946 * saved in an InputSource structure
6948 InputSource *is = (InputSource *) data;
6952 count = read(is->fd, is->unused,
6953 INPUT_SOURCE_BUF_SIZE - (is->unused - is->buf));
6957 (is->func)(is, is->closure, is->buf, count, count ? errno : 0);
6960 is->unused += count;
6962 /* break input into lines and call the callback function on each
6965 while (p < is->unused)
6967 q = memchr(p, '\n', is->unused - p);
6968 if (q == NULL) break;
6970 (is->func)(is, is->closure, p, q - p, 0);
6973 /* remember not yet used part of the buffer */
6975 while (p < is->unused)
6983 /* read maximum length of input buffer and send the whole buffer
6984 * to the callback function
6986 count = read(is->fd, is->buf, INPUT_SOURCE_BUF_SIZE);
6991 (is->func)(is, is->closure, is->buf, count, error);
6997 InputSourceRef AddInputSource(pr, lineByLine, func, closure)
7004 GIOChannel *channel;
7005 ChildProc *cp = (ChildProc *) pr;
7007 is = (InputSource *) calloc(1, sizeof(InputSource));
7008 is->lineByLine = lineByLine;
7012 is->fd = fileno(stdin);
7014 is->kind = cp->kind;
7015 is->fd = cp->fdFrom;
7018 is->unused = is->buf;
7022 // is->xid = XtAppAddInput(appContext, is->fd,
7023 // (XtPointer) (XtInputReadMask),
7024 // (XtInputCallbackProc) DoInputCallback,
7028 /* TODO: will this work on windows?*/
7029 printf("DEBUG: fd=%d %d\n",is->fd,is);
7031 channel = g_io_channel_unix_new(is->fd);
7032 g_io_channel_set_close_on_unref (channel, TRUE);
7033 is->sid = g_io_add_watch(channel, G_IO_IN,(GIOFunc) DoInputCallback, is);
7034 is->closure = closure;
7035 return (InputSourceRef) is;
7039 RemoveInputSource(isr)
7042 InputSource *is = (InputSource *) isr;
7044 if (is->sid == 0) return;
7045 g_source_remove(is->sid);
7050 int OutputToProcess(pr, message, count, outError)
7056 ChildProc *cp = (ChildProc *) pr;
7060 outCount = fwrite(message, 1, count, stdout);
7062 outCount = write(cp->fdTo, message, count);
7072 /* Output message to process, with "ms" milliseconds of delay
7073 between each character. This is needed when sending the logon
7074 script to ICC, which for some reason doesn't like the
7075 instantaneous send. */
7076 int OutputToProcessDelayed(pr, message, count, outError, msdelay)
7083 ChildProc *cp = (ChildProc *) pr;
7088 r = write(cp->fdTo, message++, 1);
7101 /**** Animation code by Hugh Fisher, DCS, ANU.
7103 Known problem: if a window overlapping the board is
7104 moved away while a piece is being animated underneath,
7105 the newly exposed area won't be updated properly.
7106 I can live with this.
7108 Known problem: if you look carefully at the animation
7109 of pieces in mono mode, they are being drawn as solid
7110 shapes without interior detail while moving. Fixing
7111 this would be a major complication for minimal return.
7114 /* Masks for XPM pieces. Black and white pieces can have
7115 different shapes, but in the interest of retaining my
7116 sanity pieces must have the same outline on both light
7117 and dark squares, and all pieces must use the same
7118 background square colors/images. */
7120 static int xpmDone = 0;
7123 CreateAnimMasks (pieceDepth)
7130 unsigned long plane;
7133 /* just return for gtk at the moment */
7136 /* Need a bitmap just to get a GC with right depth */
7137 buf = XCreatePixmap(xDisplay, xBoardWindow,
7139 values.foreground = 1;
7140 values.background = 0;
7141 /* Don't use XtGetGC, not read only */
7142 maskGC = XCreateGC(xDisplay, buf,
7143 GCForeground | GCBackground, &values);
7144 XFreePixmap(xDisplay, buf);
7146 buf = XCreatePixmap(xDisplay, xBoardWindow,
7147 squareSize, squareSize, pieceDepth);
7148 values.foreground = XBlackPixel(xDisplay, xScreen);
7149 values.background = XWhitePixel(xDisplay, xScreen);
7150 bufGC = XCreateGC(xDisplay, buf,
7151 GCForeground | GCBackground, &values);
7153 for (piece = WhitePawn; piece <= BlackKing; piece++) {
7154 /* Begin with empty mask */
7155 if(!xpmDone) // [HGM] pieces: keep using existing
7156 xpmMask[piece] = XCreatePixmap(xDisplay, xBoardWindow,
7157 squareSize, squareSize, 1);
7158 XSetFunction(xDisplay, maskGC, GXclear);
7159 XFillRectangle(xDisplay, xpmMask[piece], maskGC,
7160 0, 0, squareSize, squareSize);
7162 /* Take a copy of the piece */
7167 XSetFunction(xDisplay, bufGC, GXcopy);
7168 XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % (int)BlackPawn],
7170 0, 0, squareSize, squareSize, 0, 0);
7172 /* XOR the background (light) over the piece */
7173 XSetFunction(xDisplay, bufGC, GXxor);
7175 XCopyArea(xDisplay, xpmLightSquare, buf, bufGC,
7176 0, 0, squareSize, squareSize, 0, 0);
7178 XSetForeground(xDisplay, bufGC, lightSquareColor);
7179 XFillRectangle(xDisplay, buf, bufGC, 0, 0, squareSize, squareSize);
7182 /* We now have an inverted piece image with the background
7183 erased. Construct mask by just selecting all the non-zero
7184 pixels - no need to reconstruct the original image. */
7185 XSetFunction(xDisplay, maskGC, GXor);
7187 /* Might be quicker to download an XImage and create bitmap
7188 data from it rather than this N copies per piece, but it
7189 only takes a fraction of a second and there is a much
7190 longer delay for loading the pieces. */
7191 for (n = 0; n < pieceDepth; n ++) {
7192 XCopyPlane(xDisplay, buf, xpmMask[piece], maskGC,
7193 0, 0, squareSize, squareSize,
7199 XFreePixmap(xDisplay, buf);
7200 XFreeGC(xDisplay, bufGC);
7201 XFreeGC(xDisplay, maskGC);
7205 InitAnimState (anim, info)
7207 XWindowAttributes * info;
7212 /* Each buffer is square size, same depth as window */
7213 // anim->saveBuf = XCreatePixmap(xDisplay, xBoardWindow,
7214 // squareSize, squareSize, info->depth);
7215 // anim->newBuf = XCreatePixmap(xDisplay, xBoardWindow,
7216 // squareSize, squareSize, info->depth);
7218 // /* Create a plain GC for blitting */
7219 // mask = GCForeground | GCBackground | GCFunction |
7220 // GCPlaneMask | GCGraphicsExposures;
7221 // values.foreground = XBlackPixel(xDisplay, xScreen);
7222 // values.background = XWhitePixel(xDisplay, xScreen);
7223 // values.function = GXcopy;
7224 // values.plane_mask = AllPlanes;
7225 // values.graphics_exposures = False;
7226 // anim->blitGC = XCreateGC(xDisplay, xBoardWindow, mask, &values);
7228 // /* Piece will be copied from an existing context at
7229 // the start of each new animation/drag. */
7230 // anim->pieceGC = XCreateGC(xDisplay, xBoardWindow, 0, &values);
7232 // /* Outline will be a read-only copy of an existing */
7233 // anim->outlineGC = None;
7239 static VariantClass old = (VariantClass) -1; // [HGM] pieces: redo every time variant changes
7240 XWindowAttributes info;
7242 /* for gtk at the moment just ... */
7245 if (xpmDone && gameInfo.variant == old) return;
7246 if(xpmDone) old = gameInfo.variant; // first time pieces might not be created yet
7247 // XGetWindowAttributes(xDisplay, xBoardWindow, &info);
7249 // InitAnimState(&game, &info);
7250 // InitAnimState(&player, &info);
7252 /* For XPM pieces, we need bitmaps to use as masks. */
7254 // CreateAnimMasks(info.depth);
7260 static Boolean frameWaiting;
7262 static RETSIGTYPE FrameAlarm (sig)
7265 frameWaiting = False;
7266 /* In case System-V style signals. Needed?? */
7267 signal(SIGALRM, FrameAlarm);
7274 struct itimerval delay;
7276 XSync(xDisplay, False);
7279 frameWaiting = True;
7280 signal(SIGALRM, FrameAlarm);
7281 delay.it_interval.tv_sec =
7282 delay.it_value.tv_sec = time / 1000;
7283 delay.it_interval.tv_usec =
7284 delay.it_value.tv_usec = (time % 1000) * 1000;
7285 setitimer(ITIMER_REAL, &delay, NULL);
7286 while (frameWaiting) pause();
7287 delay.it_interval.tv_sec = delay.it_value.tv_sec = 0;
7288 delay.it_interval.tv_usec = delay.it_value.tv_usec = 0;
7289 setitimer(ITIMER_REAL, &delay, NULL);
7299 // XSync(xDisplay, False);
7301 usleep(time * 1000);
7306 /* Convert board position to corner of screen rect and color */
7309 ScreenSquare(column, row, pt, color)
7310 int column; int row; XPoint * pt; int * color;
7313 pt->x = lineGap + ((BOARD_WIDTH-1)-column) * (squareSize + lineGap);
7314 pt->y = lineGap + row * (squareSize + lineGap);
7316 pt->x = lineGap + column * (squareSize + lineGap);
7317 pt->y = lineGap + ((BOARD_HEIGHT-1)-row) * (squareSize + lineGap);
7319 *color = SquareColor(row, column);
7322 /* Convert window coords to square */
7325 BoardSquare(x, y, column, row)
7326 int x; int y; int * column; int * row;
7328 *column = EventToSquare(x, BOARD_WIDTH);
7329 if (flipView && *column >= 0)
7330 *column = BOARD_WIDTH - 1 - *column;
7331 *row = EventToSquare(y, BOARD_HEIGHT);
7332 if (!flipView && *row >= 0)
7333 *row = BOARD_HEIGHT - 1 - *row;
7338 #undef Max /* just in case */
7340 #define Max(a, b) ((a) > (b) ? (a) : (b))
7341 #define Min(a, b) ((a) < (b) ? (a) : (b))
7344 SetRect(rect, x, y, width, height)
7345 XRectangle * rect; int x; int y; int width; int height;
7349 rect->width = width;
7350 rect->height = height;
7353 /* Test if two frames overlap. If they do, return
7354 intersection rect within old and location of
7355 that rect within new. */
7358 Intersect(old, new, size, area, pt)
7359 XPoint * old; XPoint * new;
7360 int size; XRectangle * area; XPoint * pt;
7362 if (old->x > new->x + size || new->x > old->x + size ||
7363 old->y > new->y + size || new->y > old->y + size) {
7366 SetRect(area, Max(new->x - old->x, 0), Max(new->y - old->y, 0),
7367 size - abs(old->x - new->x), size - abs(old->y - new->y));
7368 pt->x = Max(old->x - new->x, 0);
7369 pt->y = Max(old->y - new->y, 0);
7374 /* For two overlapping frames, return the rect(s)
7375 in the old that do not intersect with the new. */
7378 CalcUpdateRects(old, new, size, update, nUpdates)
7379 XPoint * old; XPoint * new; int size;
7380 XRectangle update[]; int * nUpdates;
7384 /* If old = new (shouldn't happen) then nothing to draw */
7385 if (old->x == new->x && old->y == new->y) {
7389 /* Work out what bits overlap. Since we know the rects
7390 are the same size we don't need a full intersect calc. */
7392 /* Top or bottom edge? */
7393 if (new->y > old->y) {
7394 SetRect(&(update[count]), old->x, old->y, size, new->y - old->y);
7396 } else if (old->y > new->y) {
7397 SetRect(&(update[count]), old->x, old->y + size - (old->y - new->y),
7398 size, old->y - new->y);
7401 /* Left or right edge - don't overlap any update calculated above. */
7402 if (new->x > old->x) {
7403 SetRect(&(update[count]), old->x, Max(new->y, old->y),
7404 new->x - old->x, size - abs(new->y - old->y));
7406 } else if (old->x > new->x) {
7407 SetRect(&(update[count]), new->x + size, Max(new->y, old->y),
7408 old->x - new->x, size - abs(new->y - old->y));
7415 /* Generate a series of frame coords from start->mid->finish.
7416 The movement rate doubles until the half way point is
7417 reached, then halves back down to the final destination,
7418 which gives a nice slow in/out effect. The algorithmn
7419 may seem to generate too many intermediates for short
7420 moves, but remember that the purpose is to attract the
7421 viewers attention to the piece about to be moved and
7422 then to where it ends up. Too few frames would be less
7426 Tween(start, mid, finish, factor, frames, nFrames)
7427 XPoint * start; XPoint * mid;
7428 XPoint * finish; int factor;
7429 XPoint frames[]; int * nFrames;
7431 int fraction, n, count;
7435 /* Slow in, stepping 1/16th, then 1/8th, ... */
7437 for (n = 0; n < factor; n++)
7439 for (n = 0; n < factor; n++) {
7440 frames[count].x = start->x + (mid->x - start->x) / fraction;
7441 frames[count].y = start->y + (mid->y - start->y) / fraction;
7443 fraction = fraction / 2;
7447 frames[count] = *mid;
7450 /* Slow out, stepping 1/2, then 1/4, ... */
7452 for (n = 0; n < factor; n++) {
7453 frames[count].x = finish->x - (finish->x - mid->x) / fraction;
7454 frames[count].y = finish->y - (finish->y - mid->y) / fraction;
7456 fraction = fraction * 2;
7461 /* Draw a piece on the screen without disturbing what's there */
7464 SelectGCMask(piece, clip, outline, mask)
7465 ChessSquare piece; GC * clip; GC * outline; Pixmap * mask;
7469 /* Bitmap for piece being moved. */
7470 if (appData.monoMode) {
7471 *mask = *pieceToSolid(piece);
7472 } else if (useImages) {
7474 *mask = xpmMask[piece];
7476 *mask = ximMaskPm[piece];
7479 *mask = *pieceToSolid(piece);
7482 /* GC for piece being moved. Square color doesn't matter, but
7483 since it gets modified we make a copy of the original. */
7485 if (appData.monoMode)
7490 if (appData.monoMode)
7495 // XCopyGC(xDisplay, source, 0xFFFFFFFF, *clip);
7497 /* Outline only used in mono mode and is not modified */
7499 *outline = bwPieceGC;
7501 *outline = wbPieceGC;
7505 OverlayPiece(piece, clip, outline, dest)
7506 ChessSquare piece; GC clip; GC outline; Drawable dest;
7511 /* Draw solid rectangle which will be clipped to shape of piece */
7512 // XFillRectangle(xDisplay, dest, clip,
7513 // 0, 0, squareSize, squareSize)
7515 if (appData.monoMode)
7516 /* Also draw outline in contrasting color for black
7517 on black / white on white cases */
7518 // XCopyPlane(xDisplay, *pieceToOutline(piece), dest, outline,
7519 // 0, 0, squareSize, squareSize, 0, 0, 1)
7522 /* Copy the piece */
7527 // XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
7529 // 0, 0, squareSize, squareSize,
7534 /* Animate the movement of a single piece */
7537 BeginAnimation(anim, piece, startColor, start)
7545 /* The old buffer is initialised with the start square (empty) */
7546 BlankSquare(0, 0, startColor, EmptySquare, anim->saveBuf);
7547 anim->prevFrame = *start;
7549 /* The piece will be drawn using its own bitmap as a matte */
7550 // SelectGCMask(piece, &anim->pieceGC, &anim->outlineGC, &mask);
7551 // XSetClipMask(xDisplay, anim->pieceGC, mask);
7555 AnimationFrame(anim, frame, piece)
7560 XRectangle updates[4];
7565 /* Save what we are about to draw into the new buffer */
7566 // XCopyArea(xDisplay, xBoardWindow, anim->newBuf, anim->blitGC,
7567 // frame->x, frame->y, squareSize, squareSize,
7570 /* Erase bits of the previous frame */
7571 if (Intersect(&anim->prevFrame, frame, squareSize, &overlap, &pt)) {
7572 /* Where the new frame overlapped the previous,
7573 the contents in newBuf are wrong. */
7574 // XCopyArea(xDisplay, anim->saveBuf, anim->newBuf, anim->blitGC,
7575 // overlap.x, overlap.y,
7576 // overlap.width, overlap.height,
7578 /* Repaint the areas in the old that don't overlap new */
7579 CalcUpdateRects(&anim->prevFrame, frame, squareSize, updates, &count);
7580 for (i = 0; i < count; i++)
7581 // XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
7582 // updates[i].x - anim->prevFrame.x,
7583 // updates[i].y - anim->prevFrame.y,
7584 // updates[i].width, updates[i].height,
7585 // updates[i].x, updates[i].y)
7588 /* Easy when no overlap */
7589 // XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
7590 // 0, 0, squareSize, squareSize,
7591 // anim->prevFrame.x, anim->prevFrame.y);
7594 /* Save this frame for next time round */
7595 // XCopyArea(xDisplay, anim->newBuf, anim->saveBuf, anim->blitGC,
7596 // 0, 0, squareSize, squareSize,
7598 anim->prevFrame = *frame;
7600 /* Draw piece over original screen contents, not current,
7601 and copy entire rect. Wipes out overlapping piece images. */
7602 OverlayPiece(piece, anim->pieceGC, anim->outlineGC, anim->newBuf);
7603 // XCopyArea(xDisplay, anim->newBuf, xBoardWindow, anim->blitGC,
7604 // 0, 0, squareSize, squareSize,
7605 // frame->x, frame->y);
7609 EndAnimation (anim, finish)
7613 XRectangle updates[4];
7618 /* The main code will redraw the final square, so we
7619 only need to erase the bits that don't overlap. */
7620 if (Intersect(&anim->prevFrame, finish, squareSize, &overlap, &pt)) {
7621 CalcUpdateRects(&anim->prevFrame, finish, squareSize, updates, &count);
7622 for (i = 0; i < count; i++)
7623 // XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
7624 // updates[i].x - anim->prevFrame.x,
7625 // updates[i].y - anim->prevFrame.y,
7626 // updates[i].width, updates[i].height,
7627 // updates[i].x, updates[i].y)
7630 // XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
7631 // 0, 0, squareSize, squareSize,
7632 // anim->prevFrame.x, anim->prevFrame.y);
7637 FrameSequence(anim, piece, startColor, start, finish, frames, nFrames)
7639 ChessSquare piece; int startColor;
7640 XPoint * start; XPoint * finish;
7641 XPoint frames[]; int nFrames;
7645 BeginAnimation(anim, piece, startColor, start);
7646 for (n = 0; n < nFrames; n++) {
7647 AnimationFrame(anim, &(frames[n]), piece);
7648 FrameDelay(appData.animSpeed);
7650 EndAnimation(anim, finish);
7653 /* Main control logic for deciding what to animate and how */
7656 AnimateMove(board, fromX, fromY, toX, toY)
7665 XPoint start, finish, mid;
7666 XPoint frames[kFactor * 2 + 1];
7667 int nFrames, startColor, endColor;
7669 /* Are we animating? */
7670 if (!appData.animate || appData.blindfold)
7673 if(board[toY][toX] == WhiteRook && board[fromY][fromX] == WhiteKing ||
7674 board[toY][toX] == BlackRook && board[fromY][fromX] == BlackKing)
7675 return; // [HGM] FRC: no animtion of FRC castlings, as to-square is not true to-square
7677 if (fromY < 0 || fromX < 0 || toX < 0 || toY < 0) return;
7678 piece = board[fromY][fromX];
7679 if (piece >= EmptySquare) return;
7684 hop = (piece == WhiteKnight || piece == BlackKnight);
7687 if (appData.debugMode) {
7688 fprintf(debugFP, hop ? _("AnimateMove: piece %d hops from %d,%d to %d,%d \n") :
7689 _("AnimateMove: piece %d slides from %d,%d to %d,%d \n"),
7690 piece, fromX, fromY, toX, toY); }
7692 ScreenSquare(fromX, fromY, &start, &startColor);
7693 ScreenSquare(toX, toY, &finish, &endColor);
7696 /* Knight: make diagonal movement then straight */
7697 if (abs(toY - fromY) < abs(toX - fromX)) {
7698 mid.x = start.x + (finish.x - start.x) / 2;
7702 mid.y = start.y + (finish.y - start.y) / 2;
7705 mid.x = start.x + (finish.x - start.x) / 2;
7706 mid.y = start.y + (finish.y - start.y) / 2;
7709 /* Don't use as many frames for very short moves */
7710 if (abs(toY - fromY) + abs(toX - fromX) <= 2)
7711 Tween(&start, &mid, &finish, kFactor - 1, frames, &nFrames);
7713 Tween(&start, &mid, &finish, kFactor, frames, &nFrames);
7714 FrameSequence(&game, piece, startColor, &start, &finish, frames, nFrames);
7716 /* Be sure end square is redrawn */
7717 damage[toY][toX] = True;
7721 DragPieceBegin(x, y)
7724 int boardX, boardY, color;
7727 /* Are we animating? */
7728 if (!appData.animateDragging || appData.blindfold)
7731 /* Figure out which square we start in and the
7732 mouse position relative to top left corner. */
7733 BoardSquare(x, y, &boardX, &boardY);
7734 player.startBoardX = boardX;
7735 player.startBoardY = boardY;
7736 ScreenSquare(boardX, boardY, &corner, &color);
7737 player.startSquare = corner;
7738 player.startColor = color;
7739 /* As soon as we start dragging, the piece will jump slightly to
7740 be centered over the mouse pointer. */
7741 player.mouseDelta.x = squareSize/2;
7742 player.mouseDelta.y = squareSize/2;
7743 /* Initialise animation */
7744 player.dragPiece = PieceForSquare(boardX, boardY);
7746 if (player.dragPiece >= 0 && player.dragPiece < EmptySquare) {
7747 player.dragActive = True;
7748 BeginAnimation(&player, player.dragPiece, color, &corner);
7749 /* Mark this square as needing to be redrawn. Note that
7750 we don't remove the piece though, since logically (ie
7751 as seen by opponent) the move hasn't been made yet. */
7752 if(boardX == BOARD_RGHT+1 && PieceForSquare(boardX-1, boardY) > 1 ||
7753 boardX == BOARD_LEFT-2 && PieceForSquare(boardX+1, boardY) > 1)
7754 // XCopyArea(xDisplay, xBoardWindow, player.saveBuf, player.blitGC,
7755 // corner.x, corner.y, squareSize, squareSize,
7756 // 0, 0); // [HGM] zh: unstack in stead of grab
7757 damage[boardY][boardX] = True;
7759 player.dragActive = False;
7769 /* Are we animating? */
7770 if (!appData.animateDragging || appData.blindfold)
7774 if (! player.dragActive)
7776 /* Move piece, maintaining same relative position
7777 of mouse within square */
7778 corner.x = x - player.mouseDelta.x;
7779 corner.y = y - player.mouseDelta.y;
7780 AnimationFrame(&player, &corner, player.dragPiece);
7782 if (appData.highlightDragging) {
7784 BoardSquare(x, y, &boardX, &boardY);
7785 SetHighlights(fromX, fromY, boardX, boardY);
7794 int boardX, boardY, color;
7797 /* Are we animating? */
7798 if (!appData.animateDragging || appData.blindfold)
7802 if (! player.dragActive)
7804 /* Last frame in sequence is square piece is
7805 placed on, which may not match mouse exactly. */
7806 BoardSquare(x, y, &boardX, &boardY);
7807 ScreenSquare(boardX, boardY, &corner, &color);
7808 EndAnimation(&player, &corner);
7810 /* Be sure end square is redrawn */
7811 damage[boardY][boardX] = True;
7813 /* This prevents weird things happening with fast successive
7814 clicks which on my Sun at least can cause motion events
7815 without corresponding press/release. */
7816 player.dragActive = False;
7819 /* Handle expose event while piece being dragged */
7824 if (!player.dragActive || appData.blindfold)
7827 /* What we're doing: logically, the move hasn't been made yet,
7828 so the piece is still in it's original square. But visually
7829 it's being dragged around the board. So we erase the square
7830 that the piece is on and draw it at the last known drag point. */
7831 BlankSquare(player.startSquare.x, player.startSquare.y,
7832 player.startColor, EmptySquare, xBoardWindow);
7833 AnimationFrame(&player, &player.prevFrame, player.dragPiece);
7834 damage[player.startBoardY][player.startBoardX] = TRUE;
7838 SetProgramStats( FrontEndProgramStats * stats )
7841 // [HGM] done, but perhaps backend should call this directly?
7842 EngineOutputUpdate( stats );