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 RETSIGTYPE TermSizeSigHandler P((int sig));
249 void CreateGCs P((void));
250 void CreateXIMPieces P((void));
251 void CreateXPMPieces P((void));
252 void CreatePieces P((void));
253 void CreatePieceMenus P((void));
254 Widget CreateMenuBar P((Menu *mb));
255 char *FindFont P((char *pattern, int targetPxlSize));
256 void PieceMenuPopup P((Widget w, XEvent *event,
257 String *params, Cardinal *num_params));
258 static void PieceMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
259 static void DropMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
260 int EventToSquare P((int x, int limit));
261 void DrawSquare P((int row, int column, ChessSquare piece, int do_flash));
262 void HandleUserMove P((Widget w, XEvent *event,
263 String *prms, Cardinal *nprms));
264 void AnimateUserMove P((Widget w, XEvent * event,
265 String * params, Cardinal * nParams));
266 void CommentPopUp P((char *title, char *label));
267 void CommentPopDown P((void));
268 void CommentCallback P((Widget w, XtPointer client_data,
269 XtPointer call_data));
270 void ICSInputBoxPopUp P((void));
271 void ICSInputBoxPopDown P((void));
272 void AskQuestionReplyAction P((Widget w, XEvent *event,
273 String *prms, Cardinal *nprms));
274 void AskQuestionProc P((Widget w, XEvent *event,
275 String *prms, Cardinal *nprms));
276 void AskQuestionPopDown P((void));
277 void PromotionPopUp P((void));
278 void PromotionPopDown P((void));
279 void PromotionCallback P((Widget w, XtPointer client_data,
280 XtPointer call_data));
281 void EditCommentPopDown P((void));
282 void EditCommentCallback P((Widget w, XtPointer client_data,
283 XtPointer call_data));
284 void SelectCommand P((Widget w, XtPointer client_data, XtPointer call_data));
285 void CopyPositionProc P((Widget w, XEvent *event, String *prms,
287 void PastePositionProc P((Widget w, XEvent *event, String *prms,
289 void CopyGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
290 void PasteGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
291 void MailMoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
292 void ReloadCmailMsgProc P((Widget w, XEvent *event, String *prms,
294 void AnalyzeModeProc P((Widget w, XEvent *event,
295 String *prms, Cardinal *nprms));
296 void EditGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
297 void EditPositionProc P((Widget w, XEvent *event,
298 String *prms, Cardinal *nprms));
299 void TrainingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
300 void EditCommentProc P((Widget w, XEvent *event,
301 String *prms, Cardinal *nprms));
302 void IcsInputBoxProc P((Widget w, XEvent *event,
303 String *prms, Cardinal *nprms));
304 void EnterKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
305 void AlwaysQueenProc P((Widget w, XEvent *event, String *prms,
307 void AnimateDraggingProc P((Widget w, XEvent *event, String *prms,
309 void AnimateMovingProc P((Widget w, XEvent *event, String *prms,
311 void AutobsProc P((Widget w, XEvent *event, String *prms,
313 void AutoraiseProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
314 void AutosaveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
315 void BlindfoldProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
316 void FlashMovesProc P((Widget w, XEvent *event, String *prms,
318 void HighlightDraggingProc P((Widget w, XEvent *event, String *prms,
320 void HighlightLastMoveProc P((Widget w, XEvent *event, String *prms,
322 void MoveSoundProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
323 void IcsAlarmProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
324 void OldSaveStyleProc P((Widget w, XEvent *event, String *prms,
326 void PeriodicUpdatesProc P((Widget w, XEvent *event, String *prms,
328 void PonderNextMoveProc P((Widget w, XEvent *event, String *prms,
330 void PopupMoveErrorsProc P((Widget w, XEvent *event, String *prms,
332 void PopupExitMessageProc P((Widget w, XEvent *event, String *prms,
334 void PremoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
335 void QuietPlayProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
336 void TestLegalityProc P((Widget w, XEvent *event, String *prms,
338 void AboutGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
339 void DebugProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
340 void NothingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
341 void Iconify P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
342 void DisplayMove P((int moveNumber));
343 void DisplayTitle P((char *title));
344 void ICSInitScript P((void));
345 int LoadGamePopUp P((FILE *f, int gameNumber, char *title));
346 void ErrorPopUp P((char *title, char *text, int modal));
347 void ErrorPopDown P((void));
348 static char *ExpandPathName P((char *path));
349 static void CreateAnimVars P((void));
350 void DragPieceBegin P((int x, int y));
351 static void DragPieceMove P((int x, int y));
352 void DragPieceEnd P((int x, int y));
353 static void DrawDragPiece P((void));
354 char *ModeToWidgetName P((GameMode mode));
355 void EngineOutputUpdate( FrontEndProgramStats * stats );
356 void ShuffleMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
357 void EngineMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
358 void UciMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
359 void TimeControlProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
360 void NewVariantProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
361 void FirstSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
362 void SecondSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
363 void ShufflePopDown P(());
364 void EnginePopDown P(());
365 void UciPopDown P(());
366 void TimeControlPopDown P(());
367 void NewVariantPopDown P(());
368 void SettingsPopDown P(());
369 void SetMenuEnables P((Enables *enab));
370 void update_ics_width P(());
371 int get_term_width P(());
373 * XBoard depends on Xt R4 or higher
375 int xtVersion = XtSpecificationRelease;
380 Pixel lightSquareColor, darkSquareColor, whitePieceColor, blackPieceColor,
381 jailSquareColor, highlightSquareColor, premoveHighlightColor;
382 Pixel lowTimeWarningColor;
384 #define LINE_TYPE_NORMAL 0
385 #define LINE_TYPE_HIGHLIGHT 1
386 #define LINE_TYPE_PRE 2
389 GC lightSquareGC, darkSquareGC, jailSquareGC, wdPieceGC, wlPieceGC,
390 bdPieceGC, blPieceGC, wbPieceGC, bwPieceGC, coordGC,
391 wjPieceGC, bjPieceGC;
392 Pixmap iconPixmap, wIconPixmap, bIconPixmap, xMarkPixmap;
393 Widget shellWidget, layoutWidget, formWidget, boardWidget, messageWidget,
394 whiteTimerWidget, blackTimerWidget, titleWidget, widgetList[16],
395 commentShell, promotionShell, whitePieceMenu, blackPieceMenu, dropMenu,
396 menuBarWidget, editShell, errorShell, analysisShell,
397 ICSInputShell, fileNameShell, askQuestionShell;
398 Font clockFontID, coordFontID, countFontID;
399 XFontStruct *clockFontStruct, *coordFontStruct, *countFontStruct;
400 XtAppContext appContext;
402 char *oldICSInteractionTitle;
406 char installDir[] = "."; // [HGM] UCI: needed for UCI; probably needs run-time initializtion
408 Position commentX = -1, commentY = -1;
409 Dimension commentW, commentH;
411 int squareSize, smallLayout = 0, tinyLayout = 0,
412 marginW, marginH, // [HGM] for run-time resizing
413 fromX = -1, fromY = -1, toX, toY, commentUp = False, analysisUp = False,
414 ICSInputBoxUp = False, askQuestionUp = False,
415 filenameUp = False, promotionUp = False, pmFromX = -1, pmFromY = -1,
416 editUp = False, errorUp = False, errorExitStatus = -1, lineGap;
417 Pixel timerForegroundPixel, timerBackgroundPixel;
418 Pixel buttonForegroundPixel, buttonBackgroundPixel;
419 char *chessDir, *programName, *programVersion,
420 *gameCopyFilename, *gamePasteFilename;
424 Pixmap pieceBitmap[2][(int)BlackPawn];
425 Pixmap pieceBitmap2[2][(int)BlackPawn+4]; /* [HGM] pieces */
426 Pixmap xpmPieceBitmap[4][(int)BlackPawn]; /* LL, LD, DL, DD actually used*/
427 Pixmap xpmPieceBitmap2[4][(int)BlackPawn+4]; /* LL, LD, DL, DD set to select from */
428 Pixmap xpmLightSquare, xpmDarkSquare, xpmJailSquare;
429 int useImages=0, useImageSqs;
430 XImage *ximPieceBitmap[4][(int)BlackPawn+4]; /* LL, LD, DL, DD */
431 Pixmap ximMaskPm[(int)BlackPawn]; /* clipmasks, used for XIM pieces */
432 Pixmap ximMaskPm2[(int)BlackPawn+4]; /* clipmasks, used for XIM pieces */
433 XImage *ximLightSquare, *ximDarkSquare;
436 #define pieceToSolid(piece) &pieceBitmap[SOLID][(piece) % (int)BlackPawn]
437 #define pieceToOutline(piece) &pieceBitmap[OUTLINE][(piece) % (int)BlackPawn]
439 #define White(piece) ((int)(piece) < (int)BlackPawn)
441 /* Variables for doing smooth animation. This whole thing
442 would be much easier if the board was double-buffered,
443 but that would require a fairly major rewrite. */
448 GC blitGC, pieceGC, outlineGC;
449 XPoint startSquare, prevFrame, mouseDelta;
453 int startBoardX, startBoardY;
456 /* There can be two pieces being animated at once: a player
457 can begin dragging a piece before the remote opponent has moved. */
459 static AnimState game, player;
461 /* Bitmaps for use as masks when drawing XPM pieces.
462 Need one for each black and white piece. */
463 static Pixmap xpmMask[BlackKing + 1];
465 /* This magic number is the number of intermediate frames used
466 in each half of the animation. For short moves it's reduced
467 by 1. The total number of frames will be factor * 2 + 1. */
470 SizeDefaults sizeDefaults[] = SIZE_DEFAULTS;
472 Enables icsEnables[] = {
473 { "menuFile.Mail Move", False },
474 { "menuFile.Reload CMail Message", False },
475 { "menuMode.Machine Black", False },
476 { "menuMode.Machine White", False },
477 { "menuMode.Analysis Mode", False },
478 { "menuMode.Analyze File", False },
479 { "menuMode.Two Machines", False },
481 { "menuHelp.Hint", False },
482 { "menuHelp.Book", False },
483 { "menuStep.Move Now", False },
484 { "menuOptions.Periodic Updates", False },
485 { "menuOptions.Hide Thinking", False },
486 { "menuOptions.Ponder Next Move", False },
491 Enables ncpEnables[] = {
492 { "menuFile.Mail Move", False },
493 { "menuFile.Reload CMail Message", False },
494 { "menuMode.Machine White", False },
495 { "menuMode.Machine Black", False },
496 { "menuMode.Analysis Mode", False },
497 { "menuMode.Analyze File", False },
498 { "menuMode.Two Machines", False },
499 { "menuMode.ICS Client", False },
500 { "menuMode.ICS Input Box", False },
502 { "menuStep.Revert", False },
503 { "menuStep.Move Now", False },
504 { "menuStep.Retract Move", False },
505 { "menuOptions.Auto Comment", False },
506 { "menuOptions.Auto Flag", False },
507 { "menuOptions.Auto Flip View", False },
508 { "menuOptions.Auto Observe", False },
509 { "menuOptions.Auto Raise Board", False },
510 { "menuOptions.Get Move List", False },
511 { "menuOptions.ICS Alarm", False },
512 { "menuOptions.Move Sound", False },
513 { "menuOptions.Quiet Play", False },
514 { "menuOptions.Hide Thinking", False },
515 { "menuOptions.Periodic Updates", False },
516 { "menuOptions.Ponder Next Move", False },
517 { "menuHelp.Hint", False },
518 { "menuHelp.Book", False },
522 Enables gnuEnables[] = {
523 { "menuMode.ICS Client", False },
524 { "menuMode.ICS Input Box", False },
525 { "menuAction.Accept", False },
526 { "menuAction.Decline", False },
527 { "menuAction.Rematch", False },
528 { "menuAction.Adjourn", False },
529 { "menuAction.Stop Examining", False },
530 { "menuAction.Stop Observing", False },
531 { "menuStep.Revert", False },
532 { "menuOptions.Auto Comment", False },
533 { "menuOptions.Auto Observe", False },
534 { "menuOptions.Auto Raise Board", False },
535 { "menuOptions.Get Move List", False },
536 { "menuOptions.Premove", False },
537 { "menuOptions.Quiet Play", False },
539 /* The next two options rely on SetCmailMode being called *after* */
540 /* SetGNUMode so that when GNU is being used to give hints these */
541 /* menu options are still available */
543 { "menuFile.Mail Move", False },
544 { "menuFile.Reload CMail Message", False },
548 Enables cmailEnables[] = {
550 { "menuAction.Call Flag", False },
551 { "menuAction.Draw", True },
552 { "menuAction.Adjourn", False },
553 { "menuAction.Abort", False },
554 { "menuAction.Stop Observing", False },
555 { "menuAction.Stop Examining", False },
556 { "menuFile.Mail Move", True },
557 { "menuFile.Reload CMail Message", True },
561 Enables trainingOnEnables[] = {
562 { "menuMode.Edit Comment", False },
563 { "menuMode.Pause", False },
564 { "menuStep.Forward", False },
565 { "menuStep.Backward", False },
566 { "menuStep.Forward to End", False },
567 { "menuStep.Back to Start", False },
568 { "menuStep.Move Now", False },
569 { "menuStep.Truncate Game", False },
573 Enables trainingOffEnables[] = {
574 { "menuMode.Edit Comment", True },
575 { "menuMode.Pause", True },
576 { "menuStep.Forward", True },
577 { "menuStep.Backward", True },
578 { "menuStep.Forward to End", True },
579 { "menuStep.Back to Start", True },
580 { "menuStep.Move Now", True },
581 { "menuStep.Truncate Game", True },
585 Enables machineThinkingEnables[] = {
586 { "menuFile.Load Game", False },
587 { "menuFile.Load Next Game", False },
588 { "menuFile.Load Previous Game", False },
589 { "menuFile.Reload Same Game", False },
590 { "menuFile.Paste Game", False },
591 { "menuFile.Load Position", False },
592 { "menuFile.Load Next Position", False },
593 { "menuFile.Load Previous Position", False },
594 { "menuFile.Reload Same Position", False },
595 { "menuFile.Paste Position", False },
596 { "menuMode.Machine White", False },
597 { "menuMode.Machine Black", False },
598 { "menuMode.Two Machines", False },
599 { "menuStep.Retract Move", False },
603 Enables userThinkingEnables[] = {
604 { "menuFile.Load Game", True },
605 { "menuFile.Load Next Game", True },
606 { "menuFile.Load Previous Game", True },
607 { "menuFile.Reload Same Game", True },
608 { "menuFile.Paste Game", True },
609 { "menuFile.Load Position", True },
610 { "menuFile.Load Next Position", True },
611 { "menuFile.Load Previous Position", True },
612 { "menuFile.Reload Same Position", True },
613 { "menuFile.Paste Position", True },
614 { "menuMode.Machine White", True },
615 { "menuMode.Machine Black", True },
616 { "menuMode.Two Machines", True },
617 { "menuStep.Retract Move", True },
623 MenuItem fileMenu[] = {
624 {N_("New Shuffle Game ..."), ShuffleMenuProc},
625 {N_("New Variant ..."), NewVariantProc}, // [HGM] variant: not functional yet
626 // {"----", NothingProc},
627 // {N_("Save Game"), SaveGameProc},
628 // {"----", NothingProc},
629 {N_("Copy Game"), CopyGameProc},
630 {N_("Paste Game"), PasteGameProc},
631 // {"----", NothingProc},
632 // {N_("Load Position"), LoadPositionProc},
633 // {N_("Load Next Position"), LoadNextPositionProc},
634 // {N_("Load Previous Position"), LoadPrevPositionProc},
635 // {N_("Reload Same Position"), ReloadPositionProc},
636 // {N_("Save Position"), SavePositionProc},
637 // {"----", NothingProc},
638 {N_("Copy Position"), CopyPositionProc},
639 {N_("Paste Position"), PastePositionProc},
640 // {"----", NothingProc},
641 {N_("Mail Move"), MailMoveProc},
642 {N_("Reload CMail Message"), ReloadCmailMsgProc},
643 // {"----", NothingProc},
647 MenuItem modeMenu[] = {
648 // {N_("Machine White"), MachineWhiteProc},
649 // {N_("Machine Black"), MachineBlackProc},
650 // {N_("Two Machines"), TwoMachinesProc},
651 {N_("Analysis Mode"), AnalyzeModeProc},
652 // {N_("Analyze File"), AnalyzeFileProc },
653 // {N_("ICS Client"), IcsClientProc},
654 {N_("Edit Game"), EditGameProc},
655 {N_("Edit Position"), EditPositionProc},
656 {N_("Training"), TrainingProc},
657 {"----", NothingProc},
658 {N_("Show Engine Output"), EngineOutputProc},
659 {N_("Show Evaluation Graph"), NothingProc}, // [HGM] evalgr: not functional yet
660 {N_("Show Game List"), ShowGameListProc},
661 // {"Show Move History", HistoryShowProc}, // [HGM] hist: activate 4.2.7 code
662 {"----", NothingProc},
663 {N_("Edit Tags"), EditTagsProc},
664 {N_("Edit Comment"), EditCommentProc},
665 {N_("ICS Input Box"), IcsInputBoxProc},
669 MenuItem optionsMenu[] = {
670 // {N_("Flip View"), FlipViewProc},
671 // {"----", NothingProc},
672 {N_("Adjudications ..."), EngineMenuProc},
673 {N_("General Settings ..."), UciMenuProc},
674 {N_("Engine #1 Settings ..."), FirstSettingsProc},
675 {N_("Engine #2 Settings ..."), SecondSettingsProc},
676 {N_("Time Control ..."), TimeControlProc},
677 {"----", NothingProc},
678 {N_("Always Queen"), AlwaysQueenProc},
679 {N_("Animate Dragging"), AnimateDraggingProc},
680 {N_("Animate Moving"), AnimateMovingProc},
681 // {N_("Auto Comment"), AutocommProc},
682 // {N_("Auto Flag"), AutoflagProc},
683 // {N_("Auto Flip View"), AutoflipProc},
684 {N_("Auto Observe"), AutobsProc},
685 {N_("Auto Raise Board"), AutoraiseProc},
686 {N_("Auto Save"), AutosaveProc},
687 {N_("Blindfold"), BlindfoldProc},
688 {N_("Flash Moves"), FlashMovesProc},
689 // {N_("Get Move List"), GetMoveListProc},
691 {N_("Highlight Dragging"), HighlightDraggingProc},
693 {N_("Highlight Last Move"), HighlightLastMoveProc},
694 {N_("Move Sound"), MoveSoundProc},
695 {N_("ICS Alarm"), IcsAlarmProc},
696 {N_("Old Save Style"), OldSaveStyleProc},
697 {N_("Periodic Updates"), PeriodicUpdatesProc},
698 {N_("Ponder Next Move"), PonderNextMoveProc},
699 {N_("Popup Exit Message"), PopupExitMessageProc},
700 {N_("Popup Move Errors"), PopupMoveErrorsProc},
701 {N_("Premove"), PremoveProc},
702 {N_("Quiet Play"), QuietPlayProc},
703 // {N_("Hide Thinking"), HideThinkingProc},
704 {N_("Test Legality"), TestLegalityProc},
709 {N_("File"), fileMenu},
710 {N_("Mode"), modeMenu},
711 {N_("Options"), optionsMenu},
715 #define PIECE_MENU_SIZE 18
716 String pieceMenuStrings[2][PIECE_MENU_SIZE] = {
717 { N_("White"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
718 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
719 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
720 N_("Empty square"), N_("Clear board") },
721 { N_("Black"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
722 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
723 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
724 N_("Empty square"), N_("Clear board") }
726 /* must be in same order as PieceMenuStrings! */
727 ChessSquare pieceMenuTranslation[2][PIECE_MENU_SIZE] = {
728 { WhitePlay, (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
729 WhiteRook, WhiteQueen, WhiteKing, (ChessSquare) 0, WhiteAlfil,
730 WhiteCannon, WhiteAngel, WhiteMarshall, (ChessSquare) 0,
731 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
732 { BlackPlay, (ChessSquare) 0, BlackPawn, BlackKnight, BlackBishop,
733 BlackRook, BlackQueen, BlackKing, (ChessSquare) 0, BlackAlfil,
734 BlackCannon, BlackAngel, BlackMarshall, (ChessSquare) 0,
735 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
738 #define DROP_MENU_SIZE 6
739 String dropMenuStrings[DROP_MENU_SIZE] = {
740 "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"), N_("Queen")
742 /* must be in same order as PieceMenuStrings! */
743 ChessSquare dropMenuTranslation[DROP_MENU_SIZE] = {
744 (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
745 WhiteRook, WhiteQueen
753 DropMenuEnables dmEnables[] = {
762 { XtNborderWidth, 0 },
763 { XtNdefaultDistance, 0 },
767 { XtNborderWidth, 0 },
768 { XtNresizable, (XtArgVal) True },
772 { XtNborderWidth, 0 },
777 XtResource clientResources[] = {
778 { "whitePieceColor", "whitePieceColor", XtRString, sizeof(String),
779 XtOffset(AppDataPtr, whitePieceColor), XtRString,
781 { "blackPieceColor", "blackPieceColor", XtRString, sizeof(String),
782 XtOffset(AppDataPtr, blackPieceColor), XtRString,
784 { "lightSquareColor", "lightSquareColor", XtRString,
785 sizeof(String), XtOffset(AppDataPtr, lightSquareColor),
786 XtRString, LIGHT_SQUARE_COLOR },
787 { "darkSquareColor", "darkSquareColor", XtRString, sizeof(String),
788 XtOffset(AppDataPtr, darkSquareColor), XtRString,
790 { "highlightSquareColor", "highlightSquareColor", XtRString,
791 sizeof(String), XtOffset(AppDataPtr, highlightSquareColor),
792 XtRString, HIGHLIGHT_SQUARE_COLOR },
793 { "premoveHighlightColor", "premoveHighlightColor", XtRString,
794 sizeof(String), XtOffset(AppDataPtr, premoveHighlightColor),
795 XtRString, PREMOVE_HIGHLIGHT_COLOR },
796 { "movesPerSession", "movesPerSession", XtRInt, sizeof(int),
797 XtOffset(AppDataPtr, movesPerSession), XtRImmediate,
798 (XtPointer) MOVES_PER_SESSION },
799 { "timeIncrement", "timeIncrement", XtRInt, sizeof(int),
800 XtOffset(AppDataPtr, timeIncrement), XtRImmediate,
801 (XtPointer) TIME_INCREMENT },
802 { "initString", "initString", XtRString, sizeof(String),
803 XtOffset(AppDataPtr, initString), XtRString, INIT_STRING },
804 { "secondInitString", "secondInitString", XtRString, sizeof(String),
805 XtOffset(AppDataPtr, secondInitString), XtRString, INIT_STRING },
806 { "firstComputerString", "firstComputerString", XtRString,
807 sizeof(String), XtOffset(AppDataPtr, firstComputerString), XtRString,
809 { "secondComputerString", "secondComputerString", XtRString,
810 sizeof(String), XtOffset(AppDataPtr, secondComputerString), XtRString,
812 { "firstChessProgram", "firstChessProgram", XtRString,
813 sizeof(String), XtOffset(AppDataPtr, firstChessProgram),
814 XtRString, FIRST_CHESS_PROGRAM },
815 { "secondChessProgram", "secondChessProgram", XtRString,
816 sizeof(String), XtOffset(AppDataPtr, secondChessProgram),
817 XtRString, SECOND_CHESS_PROGRAM },
818 { "firstPlaysBlack", "firstPlaysBlack", XtRBoolean,
819 sizeof(Boolean), XtOffset(AppDataPtr, firstPlaysBlack),
820 XtRImmediate, (XtPointer) False },
821 { "noChessProgram", "noChessProgram", XtRBoolean,
822 sizeof(Boolean), XtOffset(AppDataPtr, noChessProgram),
823 XtRImmediate, (XtPointer) False },
824 { "firstHost", "firstHost", XtRString, sizeof(String),
825 XtOffset(AppDataPtr, firstHost), XtRString, FIRST_HOST },
826 { "secondHost", "secondHost", XtRString, sizeof(String),
827 XtOffset(AppDataPtr, secondHost), XtRString, SECOND_HOST },
828 { "firstDirectory", "firstDirectory", XtRString, sizeof(String),
829 XtOffset(AppDataPtr, firstDirectory), XtRString, "." },
830 { "secondDirectory", "secondDirectory", XtRString, sizeof(String),
831 XtOffset(AppDataPtr, secondDirectory), XtRString, "." },
832 { "bitmapDirectory", "bitmapDirectory", XtRString,
833 sizeof(String), XtOffset(AppDataPtr, bitmapDirectory),
835 { "remoteShell", "remoteShell", XtRString, sizeof(String),
836 XtOffset(AppDataPtr, remoteShell), XtRString, REMOTE_SHELL },
837 { "remoteUser", "remoteUser", XtRString, sizeof(String),
838 XtOffset(AppDataPtr, remoteUser), XtRString, "" },
839 { "timeDelay", "timeDelay", XtRFloat, sizeof(float),
840 XtOffset(AppDataPtr, timeDelay), XtRString,
841 (XtPointer) TIME_DELAY_QUOTE },
842 { "timeControl", "timeControl", XtRString, sizeof(String),
843 XtOffset(AppDataPtr, timeControl), XtRString,
844 (XtPointer) TIME_CONTROL },
845 { "internetChessServerMode", "internetChessServerMode",
846 XtRBoolean, sizeof(Boolean),
847 XtOffset(AppDataPtr, icsActive), XtRImmediate,
849 { "internetChessServerHost", "internetChessServerHost",
850 XtRString, sizeof(String),
851 XtOffset(AppDataPtr, icsHost),
852 XtRString, (XtPointer) ICS_HOST },
853 { "internetChessServerPort", "internetChessServerPort",
854 XtRString, sizeof(String),
855 XtOffset(AppDataPtr, icsPort), XtRString,
856 (XtPointer) ICS_PORT },
857 { "internetChessServerCommPort", "internetChessServerCommPort",
858 XtRString, sizeof(String),
859 XtOffset(AppDataPtr, icsCommPort), XtRString,
861 { "internetChessServerLogonScript", "internetChessServerLogonScript",
862 XtRString, sizeof(String),
863 XtOffset(AppDataPtr, icsLogon), XtRString,
865 { "internetChessServerHelper", "internetChessServerHelper",
866 XtRString, sizeof(String),
867 XtOffset(AppDataPtr, icsHelper), XtRString, "" },
868 { "internetChessServerInputBox", "internetChessServerInputBox",
869 XtRBoolean, sizeof(Boolean),
870 XtOffset(AppDataPtr, icsInputBox), XtRImmediate,
872 { "icsAlarm", "icsAlarm",
873 XtRBoolean, sizeof(Boolean),
874 XtOffset(AppDataPtr, icsAlarm), XtRImmediate,
876 { "icsAlarmTime", "icsAlarmTime",
878 XtOffset(AppDataPtr, icsAlarmTime), XtRImmediate,
880 { "useTelnet", "useTelnet", XtRBoolean, sizeof(Boolean),
881 XtOffset(AppDataPtr, useTelnet), XtRImmediate,
883 { "telnetProgram", "telnetProgram", XtRString, sizeof(String),
884 XtOffset(AppDataPtr, telnetProgram), XtRString, TELNET_PROGRAM },
885 { "gateway", "gateway", XtRString, sizeof(String),
886 XtOffset(AppDataPtr, gateway), XtRString, "" },
887 { "loadGameFile", "loadGameFile", XtRString, sizeof(String),
888 XtOffset(AppDataPtr, loadGameFile), XtRString, "" },
889 { "loadGameIndex", "loadGameIndex",
891 XtOffset(AppDataPtr, loadGameIndex), XtRImmediate,
893 { "saveGameFile", "saveGameFile", XtRString, sizeof(String),
894 XtOffset(AppDataPtr, saveGameFile), XtRString, "" },
895 { "autoRaiseBoard", "autoRaiseBoard", XtRBoolean,
896 sizeof(Boolean), XtOffset(AppDataPtr, autoRaiseBoard),
897 XtRImmediate, (XtPointer) True },
898 { "autoSaveGames", "autoSaveGames", XtRBoolean,
899 sizeof(Boolean), XtOffset(AppDataPtr, autoSaveGames),
900 XtRImmediate, (XtPointer) False },
901 { "blindfold", "blindfold", XtRBoolean,
902 sizeof(Boolean), XtOffset(AppDataPtr, blindfold),
903 XtRImmediate, (XtPointer) False },
904 { "loadPositionFile", "loadPositionFile", XtRString,
905 sizeof(String), XtOffset(AppDataPtr, loadPositionFile),
907 { "loadPositionIndex", "loadPositionIndex",
909 XtOffset(AppDataPtr, loadPositionIndex), XtRImmediate,
911 { "savePositionFile", "savePositionFile", XtRString,
912 sizeof(String), XtOffset(AppDataPtr, savePositionFile),
914 { "matchMode", "matchMode", XtRBoolean, sizeof(Boolean),
915 XtOffset(AppDataPtr, matchMode), XtRImmediate, (XtPointer) False },
916 { "matchGames", "matchGames", XtRInt, sizeof(int),
917 XtOffset(AppDataPtr, matchGames), XtRImmediate,
919 { "monoMode", "monoMode", XtRBoolean, sizeof(Boolean),
920 XtOffset(AppDataPtr, monoMode), XtRImmediate,
922 { "debugMode", "debugMode", XtRBoolean, sizeof(Boolean),
923 XtOffset(AppDataPtr, debugMode), XtRImmediate,
925 { "clockMode", "clockMode", XtRBoolean, sizeof(Boolean),
926 XtOffset(AppDataPtr, clockMode), XtRImmediate,
928 { "boardSize", "boardSize", XtRString, sizeof(String),
929 XtOffset(AppDataPtr, boardSize), XtRString, "" },
930 { "searchTime", "searchTime", XtRString, sizeof(String),
931 XtOffset(AppDataPtr, searchTime), XtRString,
933 { "searchDepth", "searchDepth", XtRInt, sizeof(int),
934 XtOffset(AppDataPtr, searchDepth), XtRImmediate,
936 { "showCoords", "showCoords", XtRBoolean, sizeof(Boolean),
937 XtOffset(AppDataPtr, showCoords), XtRImmediate,
939 { "showJail", "showJail", XtRInt, sizeof(int),
940 XtOffset(AppDataPtr, showJail), XtRImmediate,
942 { "showThinking", "showThinking", XtRBoolean, sizeof(Boolean),
943 XtOffset(AppDataPtr, showThinking), XtRImmediate,
945 { "ponderNextMove", "ponderNextMove", XtRBoolean, sizeof(Boolean),
946 XtOffset(AppDataPtr, ponderNextMove), XtRImmediate,
948 { "periodicUpdates", "periodicUpdates", XtRBoolean, sizeof(Boolean),
949 XtOffset(AppDataPtr, periodicUpdates), XtRImmediate,
951 { "clockFont", "clockFont", XtRString, sizeof(String),
952 XtOffset(AppDataPtr, clockFont), XtRString, CLOCK_FONT },
953 { "coordFont", "coordFont", XtRString, sizeof(String),
954 XtOffset(AppDataPtr, coordFont), XtRString, COORD_FONT },
955 { "font", "font", XtRString, sizeof(String),
956 XtOffset(AppDataPtr, font), XtRString, DEFAULT_FONT },
957 { "ringBellAfterMoves", "ringBellAfterMoves",
958 XtRBoolean, sizeof(Boolean),
959 XtOffset(AppDataPtr, ringBellAfterMoves),
960 XtRImmediate, (XtPointer) False },
961 { "autoCallFlag", "autoCallFlag", XtRBoolean,
962 sizeof(Boolean), XtOffset(AppDataPtr, autoCallFlag),
963 XtRImmediate, (XtPointer) False },
964 { "autoFlipView", "autoFlipView", XtRBoolean,
965 sizeof(Boolean), XtOffset(AppDataPtr, autoFlipView),
966 XtRImmediate, (XtPointer) True },
967 { "autoObserve", "autoObserve", XtRBoolean,
968 sizeof(Boolean), XtOffset(AppDataPtr, autoObserve),
969 XtRImmediate, (XtPointer) False },
970 { "autoComment", "autoComment", XtRBoolean,
971 sizeof(Boolean), XtOffset(AppDataPtr, autoComment),
972 XtRImmediate, (XtPointer) False },
973 { "getMoveList", "getMoveList", XtRBoolean,
974 sizeof(Boolean), XtOffset(AppDataPtr, getMoveList),
975 XtRImmediate, (XtPointer) True },
977 { "highlightDragging", "highlightDragging", XtRBoolean,
978 sizeof(Boolean), XtOffset(AppDataPtr, highlightDragging),
979 XtRImmediate, (XtPointer) False },
981 { "highlightLastMove", "highlightLastMove", XtRBoolean,
982 sizeof(Boolean), XtOffset(AppDataPtr, highlightLastMove),
983 XtRImmediate, (XtPointer) False },
984 { "premove", "premove", XtRBoolean,
985 sizeof(Boolean), XtOffset(AppDataPtr, premove),
986 XtRImmediate, (XtPointer) True },
987 { "testLegality", "testLegality", XtRBoolean,
988 sizeof(Boolean), XtOffset(AppDataPtr, testLegality),
989 XtRImmediate, (XtPointer) True },
990 { "flipView", "flipView", XtRBoolean,
991 sizeof(Boolean), XtOffset(AppDataPtr, flipView),
992 XtRImmediate, (XtPointer) False },
993 { "cmail", "cmailGameName", XtRString, sizeof(String),
994 XtOffset(AppDataPtr, cmailGameName), XtRString, "" },
995 { "alwaysPromoteToQueen", "alwaysPromoteToQueen", XtRBoolean,
996 sizeof(Boolean), XtOffset(AppDataPtr, alwaysPromoteToQueen),
997 XtRImmediate, (XtPointer) False },
998 { "oldSaveStyle", "oldSaveStyle", XtRBoolean,
999 sizeof(Boolean), XtOffset(AppDataPtr, oldSaveStyle),
1000 XtRImmediate, (XtPointer) False },
1001 { "quietPlay", "quietPlay", XtRBoolean,
1002 sizeof(Boolean), XtOffset(AppDataPtr, quietPlay),
1003 XtRImmediate, (XtPointer) False },
1004 { "titleInWindow", "titleInWindow", XtRBoolean,
1005 sizeof(Boolean), XtOffset(AppDataPtr, titleInWindow),
1006 XtRImmediate, (XtPointer) False },
1007 { "localLineEditing", "localLineEditing", XtRBoolean,
1008 sizeof(Boolean), XtOffset(AppDataPtr, localLineEditing),
1009 XtRImmediate, (XtPointer) True }, /* not implemented, must be True */
1011 { "zippyTalk", "zippyTalk", XtRBoolean,
1012 sizeof(Boolean), XtOffset(AppDataPtr, zippyTalk),
1013 XtRImmediate, (XtPointer) ZIPPY_TALK },
1014 { "zippyPlay", "zippyPlay", XtRBoolean,
1015 sizeof(Boolean), XtOffset(AppDataPtr, zippyPlay),
1016 XtRImmediate, (XtPointer) ZIPPY_PLAY },
1017 { "zippyLines", "zippyLines", XtRString, sizeof(String),
1018 XtOffset(AppDataPtr, zippyLines), XtRString, ZIPPY_LINES },
1019 { "zippyPinhead", "zippyPinhead", XtRString, sizeof(String),
1020 XtOffset(AppDataPtr, zippyPinhead), XtRString, ZIPPY_PINHEAD },
1021 { "zippyPassword", "zippyPassword", XtRString, sizeof(String),
1022 XtOffset(AppDataPtr, zippyPassword), XtRString, ZIPPY_PASSWORD },
1023 { "zippyPassword2", "zippyPassword2", XtRString, sizeof(String),
1024 XtOffset(AppDataPtr, zippyPassword2), XtRString, ZIPPY_PASSWORD2 },
1025 { "zippyWrongPassword", "zippyWrongPassword", XtRString, sizeof(String),
1026 XtOffset(AppDataPtr, zippyWrongPassword), XtRString,
1027 ZIPPY_WRONG_PASSWORD },
1028 { "zippyAcceptOnly", "zippyAcceptOnly", XtRString, sizeof(String),
1029 XtOffset(AppDataPtr, zippyAcceptOnly), XtRString, ZIPPY_ACCEPT_ONLY },
1030 { "zippyUseI", "zippyUseI", XtRBoolean,
1031 sizeof(Boolean), XtOffset(AppDataPtr, zippyUseI),
1032 XtRImmediate, (XtPointer) ZIPPY_USE_I },
1033 { "zippyBughouse", "zippyBughouse", XtRInt,
1034 sizeof(int), XtOffset(AppDataPtr, zippyBughouse),
1035 XtRImmediate, (XtPointer) ZIPPY_BUGHOUSE },
1036 { "zippyNoplayCrafty", "zippyNoplayCrafty", XtRBoolean,
1037 sizeof(Boolean), XtOffset(AppDataPtr, zippyNoplayCrafty),
1038 XtRImmediate, (XtPointer) ZIPPY_NOPLAY_CRAFTY },
1039 { "zippyGameEnd", "zippyGameEnd", XtRString, sizeof(String),
1040 XtOffset(AppDataPtr, zippyGameEnd), XtRString, ZIPPY_GAME_END },
1041 { "zippyGameStart", "zippyGameStart", XtRString, sizeof(String),
1042 XtOffset(AppDataPtr, zippyGameStart), XtRString, ZIPPY_GAME_START },
1043 { "zippyAdjourn", "zippyAdjourn", XtRBoolean,
1044 sizeof(Boolean), XtOffset(AppDataPtr, zippyAdjourn),
1045 XtRImmediate, (XtPointer) ZIPPY_ADJOURN },
1046 { "zippyAbort", "zippyAbort", XtRBoolean,
1047 sizeof(Boolean), XtOffset(AppDataPtr, zippyAbort),
1048 XtRImmediate, (XtPointer) ZIPPY_ABORT },
1049 { "zippyVariants", "zippyVariants", XtRString, sizeof(String),
1050 XtOffset(AppDataPtr, zippyVariants), XtRString, ZIPPY_VARIANTS },
1051 { "zippyMaxGames", "zippyMaxGames", XtRInt, sizeof(int),
1052 XtOffset(AppDataPtr, zippyMaxGames), XtRImmediate,
1053 (XtPointer) ZIPPY_MAX_GAMES },
1054 { "zippyReplayTimeout", "zippyReplayTimeout", XtRInt, sizeof(int),
1055 XtOffset(AppDataPtr, zippyReplayTimeout), XtRImmediate,
1056 (XtPointer) ZIPPY_REPLAY_TIMEOUT },
1057 { "zippyShortGame", "zippyShortGame", XtRInt, sizeof(int),
1058 XtOffset(AppDataPtr, zippyShortGame), XtRImmediate,
1061 { "flashCount", "flashCount", XtRInt, sizeof(int),
1062 XtOffset(AppDataPtr, flashCount), XtRImmediate,
1063 (XtPointer) FLASH_COUNT },
1064 { "flashRate", "flashRate", XtRInt, sizeof(int),
1065 XtOffset(AppDataPtr, flashRate), XtRImmediate,
1066 (XtPointer) FLASH_RATE },
1067 { "pixmapDirectory", "pixmapDirectory", XtRString,
1068 sizeof(String), XtOffset(AppDataPtr, pixmapDirectory),
1070 { "msLoginDelay", "msLoginDelay", XtRInt, sizeof(int),
1071 XtOffset(AppDataPtr, msLoginDelay), XtRImmediate,
1072 (XtPointer) MS_LOGIN_DELAY },
1073 { "colorizeMessages", "colorizeMessages", XtRBoolean,
1074 sizeof(Boolean), XtOffset(AppDataPtr, colorize),
1075 XtRImmediate, (XtPointer) False },
1076 { "colorShout", "colorShout", XtRString,
1077 sizeof(String), XtOffset(AppDataPtr, colorShout),
1078 XtRString, COLOR_SHOUT },
1079 { "colorSShout", "colorSShout", XtRString,
1080 sizeof(String), XtOffset(AppDataPtr, colorSShout),
1081 XtRString, COLOR_SSHOUT },
1082 { "colorChannel1", "colorChannel1", XtRString,
1083 sizeof(String), XtOffset(AppDataPtr, colorChannel1),
1084 XtRString, COLOR_CHANNEL1 },
1085 { "colorChannel", "colorChannel", XtRString,
1086 sizeof(String), XtOffset(AppDataPtr, colorChannel),
1087 XtRString, COLOR_CHANNEL },
1088 { "colorKibitz", "colorKibitz", XtRString,
1089 sizeof(String), XtOffset(AppDataPtr, colorKibitz),
1090 XtRString, COLOR_KIBITZ },
1091 { "colorTell", "colorTell", XtRString,
1092 sizeof(String), XtOffset(AppDataPtr, colorTell),
1093 XtRString, COLOR_TELL },
1094 { "colorChallenge", "colorChallenge", XtRString,
1095 sizeof(String), XtOffset(AppDataPtr, colorChallenge),
1096 XtRString, COLOR_CHALLENGE },
1097 { "colorRequest", "colorRequest", XtRString,
1098 sizeof(String), XtOffset(AppDataPtr, colorRequest),
1099 XtRString, COLOR_REQUEST },
1100 { "colorSeek", "colorSeek", XtRString,
1101 sizeof(String), XtOffset(AppDataPtr, colorSeek),
1102 XtRString, COLOR_SEEK },
1103 { "colorNormal", "colorNormal", XtRString,
1104 sizeof(String), XtOffset(AppDataPtr, colorNormal),
1105 XtRString, COLOR_NORMAL },
1106 { "soundProgram", "soundProgram", XtRString,
1107 sizeof(String), XtOffset(AppDataPtr, soundProgram),
1108 XtRString, "play" },
1109 { "soundShout", "soundShout", XtRString,
1110 sizeof(String), XtOffset(AppDataPtr, soundShout),
1112 { "soundSShout", "soundSShout", XtRString,
1113 sizeof(String), XtOffset(AppDataPtr, soundSShout),
1115 { "soundChannel1", "soundChannel1", XtRString,
1116 sizeof(String), XtOffset(AppDataPtr, soundChannel1),
1118 { "soundChannel", "soundChannel", XtRString,
1119 sizeof(String), XtOffset(AppDataPtr, soundChannel),
1121 { "soundKibitz", "soundKibitz", XtRString,
1122 sizeof(String), XtOffset(AppDataPtr, soundKibitz),
1124 { "soundTell", "soundTell", XtRString,
1125 sizeof(String), XtOffset(AppDataPtr, soundTell),
1127 { "soundChallenge", "soundChallenge", XtRString,
1128 sizeof(String), XtOffset(AppDataPtr, soundChallenge),
1130 { "soundRequest", "soundRequest", XtRString,
1131 sizeof(String), XtOffset(AppDataPtr, soundRequest),
1133 { "soundSeek", "soundSeek", XtRString,
1134 sizeof(String), XtOffset(AppDataPtr, soundSeek),
1136 { "soundMove", "soundMove", XtRString,
1137 sizeof(String), XtOffset(AppDataPtr, soundMove),
1139 { "soundIcsWin", "soundIcsWin", XtRString,
1140 sizeof(String), XtOffset(AppDataPtr, soundIcsWin),
1142 { "soundIcsLoss", "soundIcsLoss", XtRString,
1143 sizeof(String), XtOffset(AppDataPtr, soundIcsLoss),
1145 { "soundIcsDraw", "soundIcsDraw", XtRString,
1146 sizeof(String), XtOffset(AppDataPtr, soundIcsDraw),
1148 { "soundIcsUnfinished", "soundIcsUnfinished", XtRString,
1149 sizeof(String), XtOffset(AppDataPtr, soundIcsUnfinished),
1151 { "soundIcsAlarm", "soundIcsAlarm", XtRString,
1152 sizeof(String), XtOffset(AppDataPtr, soundIcsAlarm),
1154 { "reuseFirst", "reuseFirst", XtRBoolean,
1155 sizeof(Boolean), XtOffset(AppDataPtr, reuseFirst),
1156 XtRImmediate, (XtPointer) True },
1157 { "reuseSecond", "reuseSecond", XtRBoolean,
1158 sizeof(Boolean), XtOffset(AppDataPtr, reuseSecond),
1159 XtRImmediate, (XtPointer) True },
1160 { "animateDragging", "animateDragging", XtRBoolean,
1161 sizeof(Boolean), XtOffset(AppDataPtr, animateDragging),
1162 XtRImmediate, (XtPointer) True },
1163 { "animateMoving", "animateMoving", XtRBoolean,
1164 sizeof(Boolean), XtOffset(AppDataPtr, animate),
1165 XtRImmediate, (XtPointer) True },
1166 { "animateSpeed", "animateSpeed", XtRInt,
1167 sizeof(int), XtOffset(AppDataPtr, animSpeed),
1168 XtRImmediate, (XtPointer)10 },
1169 { "popupExitMessage", "popupExitMessage", XtRBoolean,
1170 sizeof(Boolean), XtOffset(AppDataPtr, popupExitMessage),
1171 XtRImmediate, (XtPointer) True },
1172 { "popupMoveErrors", "popupMoveErrors", XtRBoolean,
1173 sizeof(Boolean), XtOffset(AppDataPtr, popupMoveErrors),
1174 XtRImmediate, (XtPointer) False },
1175 { "fontSizeTolerance", "fontSizeTolerance", XtRInt,
1176 sizeof(int), XtOffset(AppDataPtr, fontSizeTolerance),
1177 XtRImmediate, (XtPointer)4 },
1178 { "initialMode", "initialMode", XtRString,
1179 sizeof(String), XtOffset(AppDataPtr, initialMode),
1180 XtRImmediate, (XtPointer) "" },
1181 { "variant", "variant", XtRString,
1182 sizeof(String), XtOffset(AppDataPtr, variant),
1183 XtRImmediate, (XtPointer) "normal" },
1184 { "firstProtocolVersion", "firstProtocolVersion", XtRInt,
1185 sizeof(int), XtOffset(AppDataPtr, firstProtocolVersion),
1186 XtRImmediate, (XtPointer)PROTOVER },
1187 { "secondProtocolVersion", "secondProtocolVersion", XtRInt,
1188 sizeof(int), XtOffset(AppDataPtr, secondProtocolVersion),
1189 XtRImmediate, (XtPointer)PROTOVER },
1190 { "showButtonBar", "showButtonBar", XtRBoolean,
1191 sizeof(Boolean), XtOffset(AppDataPtr, showButtonBar),
1192 XtRImmediate, (XtPointer) True },
1193 { "lowTimeWarningColor", "lowTimeWarningColor", XtRString,
1194 sizeof(String), XtOffset(AppDataPtr, lowTimeWarningColor),
1195 XtRString, COLOR_LOWTIMEWARNING },
1196 { "lowTimeWarning", "lowTimeWarning", XtRBoolean,
1197 sizeof(Boolean), XtOffset(AppDataPtr, lowTimeWarning),
1198 XtRImmediate, (XtPointer) False },
1199 {"icsEngineAnalyze", "icsEngineAnalyze", XtRBoolean, /* [DM] icsEngineAnalyze */
1200 sizeof(Boolean), XtOffset(AppDataPtr, icsEngineAnalyze),
1201 XtRImmediate, (XtPointer) False },
1202 { "firstScoreAbs", "firstScoreAbs", XtRBoolean,
1203 sizeof(Boolean), XtOffset(AppDataPtr, firstScoreIsAbsolute),
1204 XtRImmediate, (XtPointer) False },
1205 { "secondScoreAbs", "secondScoreAbs", XtRBoolean,
1206 sizeof(Boolean), XtOffset(AppDataPtr, secondScoreIsAbsolute),
1207 XtRImmediate, (XtPointer) False },
1208 { "pgnExtendedInfo", "pgnExtendedInfo", XtRBoolean,
1209 sizeof(Boolean), XtOffset(AppDataPtr, saveExtendedInfoInPGN),
1210 XtRImmediate, (XtPointer) False },
1211 { "hideThinkingFromHuman", "hideThinkingFromHuman", XtRBoolean,
1212 sizeof(Boolean), XtOffset(AppDataPtr, hideThinkingFromHuman),
1213 XtRImmediate, (XtPointer) True },
1214 { "adjudicateLossThreshold", "adjudicateLossThreshold", XtRInt,
1215 sizeof(int), XtOffset(AppDataPtr, adjudicateLossThreshold),
1216 XtRImmediate, (XtPointer) 0},
1217 { "adjudicateDrawMoves", "adjudicateDrawMoves", XtRInt,
1218 sizeof(int), XtOffset(AppDataPtr, adjudicateDrawMoves),
1219 XtRImmediate, (XtPointer) 0},
1220 { "pgnEventHeader", "pgnEventHeader", XtRString,
1221 sizeof(String), XtOffset(AppDataPtr, pgnEventHeader),
1222 XtRImmediate, (XtPointer) "Computer Chess Game" },
1223 { "defaultFrcPosition", "defaultFrcPositon", XtRInt,
1224 sizeof(int), XtOffset(AppDataPtr, defaultFrcPosition),
1225 XtRImmediate, (XtPointer) -1},
1226 { "gameListTags", "gameListTags", XtRString,
1227 sizeof(String), XtOffset(AppDataPtr, gameListTags),
1228 XtRImmediate, (XtPointer) GLT_DEFAULT_TAGS },
1230 // [HGM] 4.3.xx options
1231 { "boardWidth", "boardWidth", XtRInt,
1232 sizeof(int), XtOffset(AppDataPtr, NrFiles),
1233 XtRImmediate, (XtPointer) -1},
1234 { "boardHeight", "boardHeight", XtRInt,
1235 sizeof(int), XtOffset(AppDataPtr, NrRanks),
1236 XtRImmediate, (XtPointer) -1},
1237 { "matchPause", "matchPause", XtRInt,
1238 sizeof(int), XtOffset(AppDataPtr, matchPause),
1239 XtRImmediate, (XtPointer) 10000},
1240 { "holdingsSize", "holdingsSize", XtRInt,
1241 sizeof(int), XtOffset(AppDataPtr, holdingsSize),
1242 XtRImmediate, (XtPointer) -1},
1243 { "flipBlack", "flipBlack", XtRBoolean,
1244 sizeof(Boolean), XtOffset(AppDataPtr, upsideDown),
1245 XtRImmediate, (XtPointer) False},
1246 { "allWhite", "allWhite", XtRBoolean,
1247 sizeof(Boolean), XtOffset(AppDataPtr, allWhite),
1248 XtRImmediate, (XtPointer) False},
1249 { "pieceToCharTable", "pieceToCharTable", XtRString,
1250 sizeof(String), XtOffset(AppDataPtr, pieceToCharTable),
1251 XtRImmediate, (XtPointer) 0},
1252 { "alphaRank", "alphaRank", XtRBoolean,
1253 sizeof(Boolean), XtOffset(AppDataPtr, alphaRank),
1254 XtRImmediate, (XtPointer) False},
1255 { "testClaims", "testClaims", XtRBoolean,
1256 sizeof(Boolean), XtOffset(AppDataPtr, testClaims),
1257 XtRImmediate, (XtPointer) True},
1258 { "checkMates", "checkMates", XtRBoolean,
1259 sizeof(Boolean), XtOffset(AppDataPtr, checkMates),
1260 XtRImmediate, (XtPointer) True},
1261 { "materialDraws", "materialDraws", XtRBoolean,
1262 sizeof(Boolean), XtOffset(AppDataPtr, materialDraws),
1263 XtRImmediate, (XtPointer) True},
1264 { "trivialDraws", "trivialDraws", XtRBoolean,
1265 sizeof(Boolean), XtOffset(AppDataPtr, trivialDraws),
1266 XtRImmediate, (XtPointer) False},
1267 { "ruleMoves", "ruleMoves", XtRInt,
1268 sizeof(int), XtOffset(AppDataPtr, ruleMoves),
1269 XtRImmediate, (XtPointer) 51},
1270 { "repeatsToDraw", "repeatsToDraw", XtRInt,
1271 sizeof(int), XtOffset(AppDataPtr, drawRepeats),
1272 XtRImmediate, (XtPointer) 6},
1273 { "engineDebugOutput", "engineDebugOutput", XtRInt,
1274 sizeof(int), XtOffset(AppDataPtr, engineComments),
1275 XtRImmediate, (XtPointer) 1},
1276 { "userName", "userName", XtRString,
1277 sizeof(int), XtOffset(AppDataPtr, userName),
1278 XtRImmediate, (XtPointer) 0},
1279 { "autoKibitz", "autoKibitz", XtRBoolean,
1280 sizeof(Boolean), XtOffset(AppDataPtr, autoKibitz),
1281 XtRImmediate, (XtPointer) False},
1282 { "firstTimeOdds", "firstTimeOdds", XtRInt,
1283 sizeof(int), XtOffset(AppDataPtr, firstTimeOdds),
1284 XtRImmediate, (XtPointer) 1},
1285 { "secondTimeOdds", "secondTimeOdds", XtRInt,
1286 sizeof(int), XtOffset(AppDataPtr, secondTimeOdds),
1287 XtRImmediate, (XtPointer) 1},
1288 { "timeOddsMode", "timeOddsMode", XtRInt,
1289 sizeof(int), XtOffset(AppDataPtr, timeOddsMode),
1290 XtRImmediate, (XtPointer) 0},
1291 { "firstAccumulateTC", "firstAccumulateTC", XtRInt,
1292 sizeof(int), XtOffset(AppDataPtr, firstAccumulateTC),
1293 XtRImmediate, (XtPointer) 1},
1294 { "secondAccumulateTC", "secondAccumulateTC", XtRInt,
1295 sizeof(int), XtOffset(AppDataPtr, secondAccumulateTC),
1296 XtRImmediate, (XtPointer) 1},
1297 { "firstNPS", "firstNPS", XtRInt,
1298 sizeof(int), XtOffset(AppDataPtr, firstNPS),
1299 XtRImmediate, (XtPointer) -1},
1300 { "secondNPS", "secondNPS", XtRInt,
1301 sizeof(int), XtOffset(AppDataPtr, secondNPS),
1302 XtRImmediate, (XtPointer) -1},
1303 { "serverMoves", "serverMoves", XtRString,
1304 sizeof(String), XtOffset(AppDataPtr, serverMovesName),
1305 XtRImmediate, (XtPointer) 0},
1306 { "serverPause", "serverPause", XtRInt,
1307 sizeof(int), XtOffset(AppDataPtr, serverPause),
1308 XtRImmediate, (XtPointer) 0},
1309 { "suppressLoadMoves", "suppressLoadMoves", XtRBoolean,
1310 sizeof(Boolean), XtOffset(AppDataPtr, suppressLoadMoves),
1311 XtRImmediate, (XtPointer) False},
1312 { "userName", "userName", XtRString,
1313 sizeof(String), XtOffset(AppDataPtr, userName),
1314 XtRImmediate, (XtPointer) 0},
1315 { "egtFormats", "egtFormats", XtRString,
1316 sizeof(String), XtOffset(AppDataPtr, egtFormats),
1317 XtRImmediate, (XtPointer) 0},
1318 { "rewindIndex", "rewindIndex", XtRInt,
1319 sizeof(int), XtOffset(AppDataPtr, rewindIndex),
1320 XtRImmediate, (XtPointer) 0},
1321 { "sameColorGames", "sameColorGames", XtRInt,
1322 sizeof(int), XtOffset(AppDataPtr, sameColorGames),
1323 XtRImmediate, (XtPointer) 0},
1324 { "smpCores", "smpCores", XtRInt,
1325 sizeof(int), XtOffset(AppDataPtr, smpCores),
1326 XtRImmediate, (XtPointer) 1},
1327 { "niceEngines", "niceEngines", XtRInt,
1328 sizeof(int), XtOffset(AppDataPtr, niceEngines),
1329 XtRImmediate, (XtPointer) 0},
1330 { "nameOfDebugFile", "nameOfDebugFile", XtRString,
1331 sizeof(String), XtOffset(AppDataPtr, nameOfDebugFile),
1332 XtRImmediate, (XtPointer) "xboard.debug"},
1333 { "engineDebugOutput", "engineDebugOutput", XtRInt,
1334 sizeof(int), XtOffset(AppDataPtr, engineComments),
1335 XtRImmediate, (XtPointer) 1},
1336 { "noGUI", "noGUI", XtRBoolean,
1337 sizeof(Boolean), XtOffset(AppDataPtr, noGUI),
1338 XtRImmediate, (XtPointer) 0},
1339 { "firstOptions", "firstOptions", XtRString,
1340 sizeof(String), XtOffset(AppDataPtr, firstOptions),
1341 XtRImmediate, (XtPointer) "" },
1342 { "secondOptions", "secondOptions", XtRString,
1343 sizeof(String), XtOffset(AppDataPtr, secondOptions),
1344 XtRImmediate, (XtPointer) "" },
1345 { "firstNeedsNoncompliantFEN", "firstNeedsNoncompliantFEN", XtRString,
1346 sizeof(String), XtOffset(AppDataPtr, fenOverride1),
1347 XtRImmediate, (XtPointer) 0 },
1348 { "secondNeedsNoncompliantFEN", "secondNeedsNoncompliantFEN", XtRString,
1349 sizeof(String), XtOffset(AppDataPtr, fenOverride2),
1350 XtRImmediate, (XtPointer) 0 },
1352 // [HGM] Winboard_x UCI options
1353 { "firstIsUCI", "firstIsUCI", XtRBoolean,
1354 sizeof(Boolean), XtOffset(AppDataPtr, firstIsUCI),
1355 XtRImmediate, (XtPointer) False},
1356 { "secondIsUCI", "secondIsUCI", XtRBoolean,
1357 sizeof(Boolean), XtOffset(AppDataPtr, secondIsUCI),
1358 XtRImmediate, (XtPointer) False},
1359 { "firstHasOwnBookUCI", "firstHasOwnBookUCI", XtRBoolean,
1360 sizeof(Boolean), XtOffset(AppDataPtr, firstHasOwnBookUCI),
1361 XtRImmediate, (XtPointer) True},
1362 { "secondHasOwnBookUCI", "secondHasOwnBookUCI", XtRBoolean,
1363 sizeof(Boolean), XtOffset(AppDataPtr, secondHasOwnBookUCI),
1364 XtRImmediate, (XtPointer) True},
1365 { "usePolyglotBook", "usePolyglotBook", XtRBoolean,
1366 sizeof(Boolean), XtOffset(AppDataPtr, usePolyglotBook),
1367 XtRImmediate, (XtPointer) False},
1368 { "defaultHashSize", "defaultHashSize", XtRInt,
1369 sizeof(int), XtOffset(AppDataPtr, defaultHashSize),
1370 XtRImmediate, (XtPointer) 64},
1371 { "defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XtRInt,
1372 sizeof(int), XtOffset(AppDataPtr, defaultCacheSizeEGTB),
1373 XtRImmediate, (XtPointer) 4},
1374 { "polyglotDir", "polyglotDir", XtRString,
1375 sizeof(String), XtOffset(AppDataPtr, polyglotDir),
1376 XtRImmediate, (XtPointer) "." },
1377 { "polyglotBook", "polyglotBook", XtRString,
1378 sizeof(String), XtOffset(AppDataPtr, polyglotBook),
1379 XtRImmediate, (XtPointer) "" },
1380 { "defaultPathEGTB", "defaultPathEGTB", XtRString,
1381 sizeof(String), XtOffset(AppDataPtr, defaultPathEGTB),
1382 XtRImmediate, (XtPointer) "/usr/local/share/egtb"},
1383 { "delayBeforeQuit", "delayBeforeQuit", XtRInt,
1384 sizeof(int), XtOffset(AppDataPtr, delayBeforeQuit),
1385 XtRImmediate, (XtPointer) 0},
1386 { "delayAfterQuit", "delayAfterQuit", XtRInt,
1387 sizeof(int), XtOffset(AppDataPtr, delayAfterQuit),
1388 XtRImmediate, (XtPointer) 0},
1389 { "keepAlive", "keepAlive", XtRInt,
1390 sizeof(int), XtOffset(AppDataPtr, keepAlive),
1391 XtRImmediate, (XtPointer) 0},
1392 { "forceIllegalMoves", "forceIllegalMoves", XtRBoolean,
1393 sizeof(Boolean), XtOffset(AppDataPtr, forceIllegal),
1394 XtRImmediate, (XtPointer) False},
1395 { "keepLineBreaksICS", "keepLineBreaksICS", XtRBoolean,
1396 sizeof(Boolean), XtOffset(AppDataPtr, noJoin),
1397 XtRImmediate, (XtPointer) True},
1400 XrmOptionDescRec shellOptions[] = {
1401 { "-whitePieceColor", "whitePieceColor", XrmoptionSepArg, NULL },
1402 { "-blackPieceColor", "blackPieceColor", XrmoptionSepArg, NULL },
1403 { "-lightSquareColor", "lightSquareColor", XrmoptionSepArg, NULL },
1404 { "-darkSquareColor", "darkSquareColor", XrmoptionSepArg, NULL },
1405 { "-highlightSquareColor", "highlightSquareColor", XrmoptionSepArg, NULL },
1406 { "-premoveHighlightColor", "premoveHighlightColor", XrmoptionSepArg,NULL},
1407 { "-movesPerSession", "movesPerSession", XrmoptionSepArg, NULL },
1408 { "-mps", "movesPerSession", XrmoptionSepArg, NULL },
1409 { "-timeIncrement", "timeIncrement", XrmoptionSepArg, NULL },
1410 { "-inc", "timeIncrement", XrmoptionSepArg, NULL },
1411 { "-initString", "initString", XrmoptionSepArg, NULL },
1412 { "-firstInitString", "initString", XrmoptionSepArg, NULL },
1413 { "-secondInitString", "secondInitString", XrmoptionSepArg, NULL },
1414 { "-firstComputerString", "firstComputerString", XrmoptionSepArg, NULL },
1415 { "-secondComputerString", "secondComputerString", XrmoptionSepArg, NULL },
1416 { "-firstChessProgram", "firstChessProgram", XrmoptionSepArg, NULL },
1417 { "-fcp", "firstChessProgram", XrmoptionSepArg, NULL },
1418 { "-secondChessProgram", "secondChessProgram", XrmoptionSepArg, NULL },
1419 { "-scp", "secondChessProgram", XrmoptionSepArg, NULL },
1420 { "-firstPlaysBlack", "firstPlaysBlack", XrmoptionSepArg, NULL },
1421 { "-fb", "firstPlaysBlack", XrmoptionNoArg, "True" },
1422 { "-xfb", "firstPlaysBlack", XrmoptionNoArg, "False" },
1423 { "-noChessProgram", "noChessProgram", XrmoptionSepArg, NULL },
1424 { "-ncp", "noChessProgram", XrmoptionNoArg, "True" },
1425 { "-xncp", "noChessProgram", XrmoptionNoArg, "False" },
1426 { "-firstHost", "firstHost", XrmoptionSepArg, NULL },
1427 { "-fh", "firstHost", XrmoptionSepArg, NULL },
1428 { "-secondHost", "secondHost", XrmoptionSepArg, NULL },
1429 { "-sh", "secondHost", XrmoptionSepArg, NULL },
1430 { "-firstDirectory", "firstDirectory", XrmoptionSepArg, NULL },
1431 { "-fd", "firstDirectory", XrmoptionSepArg, NULL },
1432 { "-secondDirectory", "secondDirectory", XrmoptionSepArg, NULL },
1433 { "-sd", "secondDirectory", XrmoptionSepArg, NULL },
1434 { "-bitmapDirectory", "bitmapDirectory", XrmoptionSepArg, NULL },
1435 { "-bm", "bitmapDirectory", XrmoptionSepArg, NULL },
1436 { "-remoteShell", "remoteShell", XrmoptionSepArg, NULL },
1437 { "-rsh", "remoteShell", XrmoptionSepArg, NULL },
1438 { "-remoteUser", "remoteUser", XrmoptionSepArg, NULL },
1439 { "-ruser", "remoteUser", XrmoptionSepArg, NULL },
1440 { "-timeDelay", "timeDelay", XrmoptionSepArg, NULL },
1441 { "-td", "timeDelay", XrmoptionSepArg, NULL },
1442 { "-timeControl", "timeControl", XrmoptionSepArg, NULL },
1443 { "-tc", "timeControl", XrmoptionSepArg, NULL },
1444 { "-internetChessServerMode", "internetChessServerMode",
1445 XrmoptionSepArg, NULL },
1446 { "-ics", "internetChessServerMode", XrmoptionNoArg, "True" },
1447 { "-xics", "internetChessServerMode", XrmoptionNoArg, "False" },
1448 { "-internetChessServerHost", "internetChessServerHost",
1449 XrmoptionSepArg, NULL },
1450 { "-icshost", "internetChessServerHost", XrmoptionSepArg, NULL },
1451 { "-internetChessServerPort", "internetChessServerPort",
1452 XrmoptionSepArg, NULL },
1453 { "-icsport", "internetChessServerPort", XrmoptionSepArg, NULL },
1454 { "-internetChessServerCommPort", "internetChessServerCommPort",
1455 XrmoptionSepArg, NULL },
1456 { "-icscomm", "internetChessServerCommPort", XrmoptionSepArg, NULL },
1457 { "-internetChessServerLogonScript", "internetChessServerLogonScript",
1458 XrmoptionSepArg, NULL },
1459 { "-icslogon", "internetChessServerLogonScript", XrmoptionSepArg, NULL },
1460 { "-internetChessServerHelper", "internetChessServerHelper",
1461 XrmoptionSepArg, NULL },
1462 { "-icshelper", "internetChessServerHelper", XrmoptionSepArg, NULL },
1463 { "-internetChessServerInputBox", "internetChessServerInputBox",
1464 XrmoptionSepArg, NULL },
1465 { "-icsinput", "internetChessServerInputBox", XrmoptionNoArg, "True" },
1466 { "-xicsinput", "internetChessServerInputBox", XrmoptionNoArg, "False" },
1467 { "-icsAlarm", "icsAlarm", XrmoptionSepArg, NULL },
1468 { "-alarm", "icsAlarm", XrmoptionNoArg, "True" },
1469 { "-xalarm", "icsAlarm", XrmoptionNoArg, "False" },
1470 { "-icsAlarmTime", "icsAlarmTime", XrmoptionSepArg, NULL },
1471 { "-useTelnet", "useTelnet", XrmoptionSepArg, NULL },
1472 { "-telnet", "useTelnet", XrmoptionNoArg, "True" },
1473 { "-xtelnet", "useTelnet", XrmoptionNoArg, "False" },
1474 { "-telnetProgram", "telnetProgram", XrmoptionSepArg, NULL },
1475 { "-gateway", "gateway", XrmoptionSepArg, NULL },
1476 { "-loadGameFile", "loadGameFile", XrmoptionSepArg, NULL },
1477 { "-lgf", "loadGameFile", XrmoptionSepArg, NULL },
1478 { "-loadGameIndex", "loadGameIndex", XrmoptionSepArg, NULL },
1479 { "-lgi", "loadGameIndex", XrmoptionSepArg, NULL },
1480 { "-saveGameFile", "saveGameFile", XrmoptionSepArg, NULL },
1481 { "-sgf", "saveGameFile", XrmoptionSepArg, NULL },
1482 { "-autoSaveGames", "autoSaveGames", XrmoptionSepArg, NULL },
1483 { "-autosave", "autoSaveGames", XrmoptionNoArg, "True" },
1484 { "-xautosave", "autoSaveGames", XrmoptionNoArg, "False" },
1485 { "-autoRaiseBoard", "autoRaiseBoard", XrmoptionSepArg, NULL },
1486 { "-autoraise", "autoRaiseBoard", XrmoptionNoArg, "True" },
1487 { "-xautoraise", "autoRaiseBoard", XrmoptionNoArg, "False" },
1488 { "-blindfold", "blindfold", XrmoptionSepArg, NULL },
1489 { "-blind", "blindfold", XrmoptionNoArg, "True" },
1490 { "-xblind", "blindfold", XrmoptionNoArg, "False" },
1491 { "-loadPositionFile", "loadPositionFile", XrmoptionSepArg, NULL },
1492 { "-lpf", "loadPositionFile", XrmoptionSepArg, NULL },
1493 { "-loadPositionIndex", "loadPositionIndex", XrmoptionSepArg, NULL },
1494 { "-lpi", "loadPositionIndex", XrmoptionSepArg, NULL },
1495 { "-savePositionFile", "savePositionFile", XrmoptionSepArg, NULL },
1496 { "-spf", "savePositionFile", XrmoptionSepArg, NULL },
1497 { "-matchMode", "matchMode", XrmoptionSepArg, NULL },
1498 { "-mm", "matchMode", XrmoptionNoArg, "True" },
1499 { "-xmm", "matchMode", XrmoptionNoArg, "False" },
1500 { "-matchGames", "matchGames", XrmoptionSepArg, NULL },
1501 { "-mg", "matchGames", XrmoptionSepArg, NULL },
1502 { "-monoMode", "monoMode", XrmoptionSepArg, NULL },
1503 { "-mono", "monoMode", XrmoptionNoArg, "True" },
1504 { "-xmono", "monoMode", XrmoptionNoArg, "False" },
1505 { "-debugMode", "debugMode", XrmoptionSepArg, NULL },
1506 { "-debug", "debugMode", XrmoptionNoArg, "True" },
1507 { "-xdebug", "debugMode", XrmoptionNoArg, "False" },
1508 { "-clockMode", "clockMode", XrmoptionSepArg, NULL },
1509 { "-clock", "clockMode", XrmoptionNoArg, "True" },
1510 { "-xclock", "clockMode", XrmoptionNoArg, "False" },
1511 { "-boardSize", "boardSize", XrmoptionSepArg, NULL },
1512 { "-size", "boardSize", XrmoptionSepArg, NULL },
1513 { "-searchTime", "searchTime", XrmoptionSepArg, NULL },
1514 { "-st", "searchTime", XrmoptionSepArg, NULL },
1515 { "-searchDepth", "searchDepth", XrmoptionSepArg, NULL },
1516 { "-depth", "searchDepth", XrmoptionSepArg, NULL },
1517 { "-showCoords", "showCoords", XrmoptionSepArg, NULL },
1518 { "-coords", "showCoords", XrmoptionNoArg, "True" },
1519 { "-xcoords", "showCoords", XrmoptionNoArg, "False" },
1521 { "-showJail", "showJail", XrmoptionSepArg, NULL },
1522 { "-jail", "showJail", XrmoptionNoArg, "1" },
1523 { "-sidejail", "showJail", XrmoptionNoArg, "2" },
1524 { "-xjail", "showJail", XrmoptionNoArg, "0" },
1526 { "-showThinking", "showThinking", XrmoptionSepArg, NULL },
1527 { "-thinking", "showThinking", XrmoptionNoArg, "True" },
1528 { "-xthinking", "showThinking", XrmoptionNoArg, "False" },
1529 { "-ponderNextMove", "ponderNextMove", XrmoptionSepArg, NULL },
1530 { "-ponder", "ponderNextMove", XrmoptionNoArg, "True" },
1531 { "-xponder", "ponderNextMove", XrmoptionNoArg, "False" },
1532 { "-periodicUpdates", "periodicUpdates", XrmoptionSepArg, NULL },
1533 { "-periodic", "periodicUpdates", XrmoptionNoArg, "True" },
1534 { "-xperiodic", "periodicUpdates", XrmoptionNoArg, "False" },
1535 { "-clockFont", "clockFont", XrmoptionSepArg, NULL },
1536 { "-coordFont", "coordFont", XrmoptionSepArg, NULL },
1537 { "-font", "font", XrmoptionSepArg, NULL },
1538 { "-ringBellAfterMoves", "ringBellAfterMoves", XrmoptionSepArg, NULL },
1539 { "-bell", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1540 { "-xbell", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1541 { "-movesound", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1542 { "-xmovesound", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1543 { "-autoCallFlag", "autoCallFlag", XrmoptionSepArg, NULL },
1544 { "-autoflag", "autoCallFlag", XrmoptionNoArg, "True" },
1545 { "-xautoflag", "autoCallFlag", XrmoptionNoArg, "False" },
1546 { "-autoFlipView", "autoFlipView", XrmoptionSepArg, NULL },
1547 { "-autoflip", "autoFlipView", XrmoptionNoArg, "True" },
1548 { "-xautoflip", "autoFlipView", XrmoptionNoArg, "False" },
1549 { "-autoObserve", "autoObserve", XrmoptionSepArg, NULL },
1550 { "-autobs", "autoObserve", XrmoptionNoArg, "True" },
1551 { "-xautobs", "autoObserve", XrmoptionNoArg, "False" },
1552 { "-autoComment", "autoComment", XrmoptionSepArg, NULL },
1553 { "-autocomm", "autoComment", XrmoptionNoArg, "True" },
1554 { "-xautocomm", "autoComment", XrmoptionNoArg, "False" },
1555 { "-getMoveList", "getMoveList", XrmoptionSepArg, NULL },
1556 { "-moves", "getMoveList", XrmoptionNoArg, "True" },
1557 { "-xmoves", "getMoveList", XrmoptionNoArg, "False" },
1559 { "-highlightDragging", "highlightDragging", XrmoptionSepArg, NULL },
1560 { "-highdrag", "highlightDragging", XrmoptionNoArg, "True" },
1561 { "-xhighdrag", "highlightDragging", XrmoptionNoArg, "False" },
1563 { "-highlightLastMove", "highlightLastMove", XrmoptionSepArg, NULL },
1564 { "-highlight", "highlightLastMove", XrmoptionNoArg, "True" },
1565 { "-xhighlight", "highlightLastMove", XrmoptionNoArg, "False" },
1566 { "-premove", "premove", XrmoptionSepArg, NULL },
1567 { "-pre", "premove", XrmoptionNoArg, "True" },
1568 { "-xpre", "premove", XrmoptionNoArg, "False" },
1569 { "-testLegality", "testLegality", XrmoptionSepArg, NULL },
1570 { "-legal", "testLegality", XrmoptionNoArg, "True" },
1571 { "-xlegal", "testLegality", XrmoptionNoArg, "False" },
1572 { "-flipView", "flipView", XrmoptionSepArg, NULL },
1573 { "-flip", "flipView", XrmoptionNoArg, "True" },
1574 { "-xflip", "flipView", XrmoptionNoArg, "False" },
1575 { "-cmail", "cmailGameName", XrmoptionSepArg, NULL },
1576 { "-alwaysPromoteToQueen", "alwaysPromoteToQueen",
1577 XrmoptionSepArg, NULL },
1578 { "-queen", "alwaysPromoteToQueen", XrmoptionNoArg, "True" },
1579 { "-xqueen", "alwaysPromoteToQueen", XrmoptionNoArg, "False" },
1580 { "-oldSaveStyle", "oldSaveStyle", XrmoptionSepArg, NULL },
1581 { "-oldsave", "oldSaveStyle", XrmoptionNoArg, "True" },
1582 { "-xoldsave", "oldSaveStyle", XrmoptionNoArg, "False" },
1583 { "-quietPlay", "quietPlay", XrmoptionSepArg, NULL },
1584 { "-quiet", "quietPlay", XrmoptionNoArg, "True" },
1585 { "-xquiet", "quietPlay", XrmoptionNoArg, "False" },
1586 { "-titleInWindow", "titleInWindow", XrmoptionSepArg, NULL },
1587 { "-title", "titleInWindow", XrmoptionNoArg, "True" },
1588 { "-xtitle", "titleInWindow", XrmoptionNoArg, "False" },
1590 { "-zippyTalk", "zippyTalk", XrmoptionSepArg, NULL },
1591 { "-zt", "zippyTalk", XrmoptionNoArg, "True" },
1592 { "-xzt", "zippyTalk", XrmoptionNoArg, "False" },
1593 { "-zippyPlay", "zippyPlay", XrmoptionSepArg, NULL },
1594 { "-zp", "zippyPlay", XrmoptionNoArg, "True" },
1595 { "-xzp", "zippyPlay", XrmoptionNoArg, "False" },
1596 { "-zippyLines", "zippyLines", XrmoptionSepArg, NULL },
1597 { "-zippyPinhead", "zippyPinhead", XrmoptionSepArg, NULL },
1598 { "-zippyPassword", "zippyPassword", XrmoptionSepArg, NULL },
1599 { "-zippyPassword2", "zippyPassword2", XrmoptionSepArg, NULL },
1600 { "-zippyWrongPassword", "zippyWrongPassword", XrmoptionSepArg, NULL },
1601 { "-zippyAcceptOnly", "zippyAcceptOnly", XrmoptionSepArg, NULL },
1602 { "-zippyUseI", "zippyUseI", XrmoptionSepArg, NULL },
1603 { "-zui", "zippyUseI", XrmoptionNoArg, "True" },
1604 { "-xzui", "zippyUseI", XrmoptionNoArg, "False" },
1605 { "-zippyBughouse", "zippyBughouse", XrmoptionSepArg, NULL },
1606 { "-zippyNoplayCrafty", "zippyNoplayCrafty", XrmoptionSepArg, NULL },
1607 { "-znc", "zippyNoplayCrafty", XrmoptionNoArg, "True" },
1608 { "-xznc", "zippyNoplayCrafty", XrmoptionNoArg, "False" },
1609 { "-zippyGameEnd", "zippyGameEnd", XrmoptionSepArg, NULL },
1610 { "-zippyGameStart", "zippyGameStart", XrmoptionSepArg, NULL },
1611 { "-zippyAdjourn", "zippyAdjourn", XrmoptionSepArg, NULL },
1612 { "-zadj", "zippyAdjourn", XrmoptionNoArg, "True" },
1613 { "-xzadj", "zippyAdjourn", XrmoptionNoArg, "False" },
1614 { "-zippyAbort", "zippyAbort", XrmoptionSepArg, NULL },
1615 { "-zab", "zippyAbort", XrmoptionNoArg, "True" },
1616 { "-xzab", "zippyAbort", XrmoptionNoArg, "False" },
1617 { "-zippyVariants", "zippyVariants", XrmoptionSepArg, NULL },
1618 { "-zippyMaxGames", "zippyMaxGames", XrmoptionSepArg, NULL },
1619 { "-zippyReplayTimeout", "zippyReplayTimeout", XrmoptionSepArg, NULL },
1620 { "-zippyShortGame", "zippyShortGame", XrmoptionSepArg, NULL },
1622 { "-flashCount", "flashCount", XrmoptionSepArg, NULL },
1623 { "-flash", "flashCount", XrmoptionNoArg, "3" },
1624 { "-xflash", "flashCount", XrmoptionNoArg, "0" },
1625 { "-flashRate", "flashRate", XrmoptionSepArg, NULL },
1626 { "-pixmapDirectory", "pixmapDirectory", XrmoptionSepArg, NULL },
1627 { "-msLoginDelay", "msLoginDelay", XrmoptionSepArg, NULL },
1628 { "-pixmap", "pixmapDirectory", XrmoptionSepArg, NULL },
1629 { "-colorizeMessages", "colorizeMessages", XrmoptionSepArg, NULL },
1630 { "-colorize", "colorizeMessages", XrmoptionNoArg, "True" },
1631 { "-xcolorize", "colorizeMessages", XrmoptionNoArg, "False" },
1632 { "-colorShout", "colorShout", XrmoptionSepArg, NULL },
1633 { "-colorSShout", "colorSShout", XrmoptionSepArg, NULL },
1634 { "-colorCShout", "colorSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1635 { "-colorChannel1", "colorChannel1", XrmoptionSepArg, NULL },
1636 { "-colorChannel", "colorChannel", XrmoptionSepArg, NULL },
1637 { "-colorKibitz", "colorKibitz", XrmoptionSepArg, NULL },
1638 { "-colorTell", "colorTell", XrmoptionSepArg, NULL },
1639 { "-colorChallenge", "colorChallenge", XrmoptionSepArg, NULL },
1640 { "-colorRequest", "colorRequest", XrmoptionSepArg, NULL },
1641 { "-colorSeek", "colorSeek", XrmoptionSepArg, NULL },
1642 { "-colorNormal", "colorNormal", XrmoptionSepArg, NULL },
1643 { "-soundProgram", "soundProgram", XrmoptionSepArg, NULL },
1644 { "-soundShout", "soundShout", XrmoptionSepArg, NULL },
1645 { "-soundSShout", "soundSShout", XrmoptionSepArg, NULL },
1646 { "-soundCShout", "soundSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1647 { "-soundChannel1", "soundChannel1", XrmoptionSepArg, NULL },
1648 { "-soundChannel", "soundChannel", XrmoptionSepArg, NULL },
1649 { "-soundKibitz", "soundKibitz", XrmoptionSepArg, NULL },
1650 { "-soundTell", "soundTell", XrmoptionSepArg, NULL },
1651 { "-soundChallenge", "soundChallenge", XrmoptionSepArg, NULL },
1652 { "-soundRequest", "soundRequest", XrmoptionSepArg, NULL },
1653 { "-soundSeek", "soundSeek", XrmoptionSepArg, NULL },
1654 { "-soundMove", "soundMove", XrmoptionSepArg, NULL },
1655 { "-soundIcsWin", "soundIcsWin", XrmoptionSepArg, NULL },
1656 { "-soundIcsLoss", "soundIcsLoss", XrmoptionSepArg, NULL },
1657 { "-soundIcsDraw", "soundIcsDraw", XrmoptionSepArg, NULL },
1658 { "-soundIcsUnfinished", "soundIcsUnfinished", XrmoptionSepArg, NULL },
1659 { "-soundIcsAlarm", "soundIcsAlarm", XrmoptionSepArg, NULL },
1660 { "-reuseFirst", "reuseFirst", XrmoptionSepArg, NULL },
1661 { "-reuseChessPrograms", "reuseFirst", XrmoptionSepArg, NULL }, /*compat*/
1662 { "-reuse", "reuseFirst", XrmoptionNoArg, "True" },
1663 { "-xreuse", "reuseFirst", XrmoptionNoArg, "False" },
1664 { "-reuseSecond", "reuseSecond", XrmoptionSepArg, NULL },
1665 { "-reuse2", "reuseSecond", XrmoptionNoArg, "True" },
1666 { "-xreuse2", "reuseSecond", XrmoptionNoArg, "False" },
1667 { "-animateMoving", "animateMoving", XrmoptionSepArg, NULL },
1668 { "-animate", "animateMoving", XrmoptionNoArg, "True" },
1669 { "-xanimate", "animateMoving", XrmoptionNoArg, "False" },
1670 { "-animateDragging", "animateDragging", XrmoptionSepArg, NULL },
1671 { "-drag", "animateDragging", XrmoptionNoArg, "True" },
1672 { "-xdrag", "animateDragging", XrmoptionNoArg, "False" },
1673 { "-animateSpeed", "animateSpeed", XrmoptionSepArg, NULL },
1674 { "-popupExitMessage", "popupExitMessage", XrmoptionSepArg, NULL },
1675 { "-exit", "popupExitMessage", XrmoptionNoArg, "True" },
1676 { "-xexit", "popupExitMessage", XrmoptionNoArg, "False" },
1677 { "-popupMoveErrors", "popupMoveErrors", XrmoptionSepArg, NULL },
1678 { "-popup", "popupMoveErrors", XrmoptionNoArg, "True" },
1679 { "-xpopup", "popupMoveErrors", XrmoptionNoArg, "False" },
1680 { "-fontSizeTolerance", "fontSizeTolerance", XrmoptionSepArg, NULL },
1681 { "-initialMode", "initialMode", XrmoptionSepArg, NULL },
1682 { "-mode", "initialMode", XrmoptionSepArg, NULL },
1683 { "-variant", "variant", XrmoptionSepArg, NULL },
1684 { "-firstProtocolVersion", "firstProtocolVersion", XrmoptionSepArg, NULL },
1685 { "-secondProtocolVersion","secondProtocolVersion",XrmoptionSepArg, NULL },
1686 { "-showButtonBar", "showButtonBar", XrmoptionSepArg, NULL },
1687 { "-buttons", "showButtonBar", XrmoptionNoArg, "True" },
1688 { "-xbuttons", "showButtonBar", XrmoptionNoArg, "False" },
1689 { "-lowTimeWarningColor", "lowTimeWarningColor", XrmoptionSepArg, NULL },
1690 { "-lowTimeWarning", "lowTimeWarning", XrmoptionSepArg, NULL },
1691 /* [AS,HR] New features */
1692 { "-firstScoreAbs", "firstScoreAbs", XrmoptionSepArg, NULL },
1693 { "-secondScoreAbs", "secondScoreAbs", XrmoptionSepArg, NULL },
1694 { "-pgnExtendedInfo", "pgnExtendedInfo", XrmoptionSepArg, NULL },
1695 { "-hideThinkingFromHuman", "hideThinkingFromHuman", XrmoptionSepArg, NULL },
1696 { "-adjudicateLossThreshold", "adjudicateLossThreshold", XrmoptionSepArg, NULL },
1697 { "-adjudicateDrawMoves", "adjudicateDrawMoves", XrmoptionSepArg, NULL },
1698 { "-pgnEventHeader", "pgnEventHeader", XrmoptionSepArg, NULL },
1699 { "-firstIsUCI", "firstIsUCI", XrmoptionSepArg, NULL },
1700 { "-secondIsUCI", "secondIsUCI", XrmoptionSepArg, NULL },
1701 { "-fUCI", "firstIsUCI", XrmoptionNoArg, "True" },
1702 { "-sUCI", "secondIsUCI", XrmoptionNoArg, "True" },
1703 { "-firstHasOwnBookUCI", "firstHasOwnBookUCI", XrmoptionSepArg, NULL },
1704 { "-secondHasOwnBookUCI", "secondHasOwnBookUCI", XrmoptionSepArg, NULL },
1705 { "-fNoOwnBookUCI", "firstHasOwnBookUCI", XrmoptionNoArg, "False" },
1706 { "-sNoOwnBookUCI", "secondHasOwnBookUCI", XrmoptionNoArg, "False" },
1707 { "-firstXBook", "firstHasOwnBookUCI", XrmoptionNoArg, "False" },
1708 { "-secondXBook", "secondHasOwnBookUCI", XrmoptionNoArg, "False" },
1709 { "-polyglotDir", "polyglotDir", XrmoptionSepArg, NULL },
1710 { "-usePolyglotBook", "usePolyglotBook", XrmoptionSepArg, NULL },
1711 { "-polyglotBook", "polyglotBook", XrmoptionSepArg, NULL },
1712 { "-defaultHashSize", "defaultHashSize", XrmoptionSepArg, NULL },
1713 { "-defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XrmoptionSepArg, NULL },
1714 { "-defaultPathEGTB", "defaultPathEGTB", XrmoptionSepArg, NULL },
1715 { "-defaultFrcPosition", "defaultFrcPosition", XrmoptionSepArg, NULL },
1716 { "-gameListTags", "gameListTags", XrmoptionSepArg, NULL },
1717 // [HGM] I am sure AS added many more options, but we have to fish them out, from the list in winboard.c
1719 /* [HGM,HR] User-selectable board size */
1720 { "-boardWidth", "boardWidth", XrmoptionSepArg, NULL },
1721 { "-boardHeight", "boardHeight", XrmoptionSepArg, NULL },
1722 { "-matchPause", "matchPause", XrmoptionSepArg, NULL },
1724 /* [HGM] new arguments of 4.3.xx. All except first three are back-end options, which should work immediately */
1725 { "-holdingsSize", "holdingsSize", XrmoptionSepArg, NULL }, // requires extensive front-end changes to work
1726 { "-flipBlack", "flipBlack", XrmoptionSepArg, NULL }, // requires front-end changes to work
1727 { "-allWhite", "allWhite", XrmoptionSepArg, NULL }, // requires front-end changes to work
1728 { "-pieceToCharTable", "pieceToCharTable", XrmoptionSepArg, NULL },
1729 { "-alphaRank", "alphaRank", XrmoptionSepArg, NULL },
1730 { "-testClaims", "testClaims", XrmoptionSepArg, NULL },
1731 { "-checkMates", "checkMates", XrmoptionSepArg, NULL },
1732 { "-materialDraws", "materialDraws", XrmoptionSepArg, NULL },
1733 { "-trivialDraws", "trivialDraws", XrmoptionSepArg, NULL },
1734 { "-ruleMoves", "ruleMoves", XrmoptionSepArg, NULL },
1735 { "-repeatsToDraw", "repeatsToDraw", XrmoptionSepArg, NULL },
1736 { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL },
1737 { "-userName", "userName", XrmoptionSepArg, NULL },
1738 { "-autoKibitz", "autoKibitz", XrmoptionNoArg, "True" },
1739 { "-firstTimeOdds", "firstTimeOdds", XrmoptionSepArg, NULL },
1740 { "-secondTimeOdds", "secondTimeOdds", XrmoptionSepArg, NULL },
1741 { "-timeOddsMode", "timeOddsMode", XrmoptionSepArg, NULL },
1742 { "-firstAccumulateTC", "firstAccumulateTC", XrmoptionSepArg, NULL },
1743 { "-secondAccumulateTC", "secondAccumulateTC", XrmoptionSepArg, NULL },
1744 { "-firstNPS", "firstNPS", XrmoptionSepArg, NULL },
1745 { "-secondNPS", "secondNPS", XrmoptionSepArg, NULL },
1746 { "-serverMoves", "serverMoves", XrmoptionSepArg, NULL },
1747 { "-serverPause", "serverPause", XrmoptionSepArg, NULL },
1748 { "-suppressLoadMoves", "suppressLoadMoves", XrmoptionSepArg, NULL },
1749 { "-egtFormats", "egtFormats", XrmoptionSepArg, NULL },
1750 { "-userName", "userName", XrmoptionSepArg, NULL },
1751 { "-smpCores", "smpCores", XrmoptionSepArg, NULL },
1752 { "-sameColorGames", "sameColorGames", XrmoptionSepArg, NULL },
1753 { "-rewindIndex", "rewindIndex", XrmoptionSepArg, NULL },
1754 { "-niceEngines", "niceEngines", XrmoptionSepArg, NULL },
1755 { "-delayBeforeQuit", "delayBeforeQuit", XrmoptionSepArg, NULL },
1756 { "-delayAfterQuit", "delayAfterQuit", XrmoptionSepArg, NULL },
1757 { "-nameOfDebugFile", "nameOfDebugFile", XrmoptionSepArg, NULL },
1758 { "-debugFile", "nameOfDebugFile", XrmoptionSepArg, NULL },
1759 { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL },
1760 { "-noGUI", "noGUI", XrmoptionNoArg, "True" },
1761 { "-firstOptions", "firstOptions", XrmoptionSepArg, NULL },
1762 { "-secondOptions", "secondOptions", XrmoptionSepArg, NULL },
1763 { "-firstNeedsNoncompliantFEN", "firstNeedsNoncompliantFEN", XrmoptionSepArg, NULL },
1764 { "-secondNeedsNoncompliantFEN", "secondNeedsNoncompliantFEN", XrmoptionSepArg, NULL },
1765 { "-keepAlive", "keepAlive", XrmoptionSepArg, NULL },
1766 { "-forceIllegalMoves", "forceIllegalMoves", XrmoptionNoArg, "True" },
1767 { "-keepLineBreaksICS", "keepLineBreaksICS", XrmoptionSepArg, NULL },
1771 XtActionsRec boardActions[] = {
1772 { "HandleUserMove", HandleUserMove },
1773 { "AnimateUserMove", AnimateUserMove },
1774 // { "FileNameAction", FileNameAction },
1775 { "AskQuestionProc", AskQuestionProc },
1776 { "AskQuestionReplyAction", AskQuestionReplyAction },
1777 { "PieceMenuPopup", PieceMenuPopup },
1778 // { "WhiteClock", WhiteClock },
1779 // { "BlackClock", BlackClock },
1780 { "Iconify", Iconify },
1781 { "LoadSelectedProc", LoadSelectedProc },
1782 // { "LoadPositionProc", LoadPositionProc },
1783 // { "LoadNextPositionProc", LoadNextPositionProc },
1784 // { "LoadPrevPositionProc", LoadPrevPositionProc },
1785 // { "ReloadPositionProc", ReloadPositionProc },
1786 { "CopyPositionProc", CopyPositionProc },
1787 { "PastePositionProc", PastePositionProc },
1788 { "CopyGameProc", CopyGameProc },
1789 { "PasteGameProc", PasteGameProc },
1790 // { "SaveGameProc", SaveGameProc },
1791 // { "SavePositionProc", SavePositionProc },
1792 { "MailMoveProc", MailMoveProc },
1793 { "ReloadCmailMsgProc", ReloadCmailMsgProc },
1794 // { "MachineWhiteProc", MachineWhiteProc },
1795 // { "MachineBlackProc", MachineBlackProc },
1796 { "AnalysisModeProc", AnalyzeModeProc },
1797 // { "AnalyzeFileProc", AnalyzeFileProc },
1798 // { "TwoMachinesProc", TwoMachinesProc },
1799 // { "IcsClientProc", IcsClientProc },
1800 { "EditGameProc", EditGameProc },
1801 { "EditPositionProc", EditPositionProc },
1802 { "TrainingProc", EditPositionProc },
1803 { "EngineOutputProc", EngineOutputProc}, // [HGM] Winboard_x engine-output window
1804 { "ShowGameListProc", ShowGameListProc },
1805 // { "ShowMoveListProc", HistoryShowProc},
1806 { "EditTagsProc", EditCommentProc },
1807 { "EditCommentProc", EditCommentProc },
1808 { "IcsAlarmProc", IcsAlarmProc },
1809 { "IcsInputBoxProc", IcsInputBoxProc },
1810 // { "AcceptProc", AcceptProc },
1811 // { "DeclineProc", DeclineProc },
1812 // { "RematchProc", RematchProc },
1813 // { "CallFlagProc", CallFlagProc },
1814 // { "DrawProc", DrawProc },
1815 // { "AdjournProc", AdjournProc },
1816 // { "AbortProc", AbortProc },
1817 // { "ResignProc", ResignProc },
1818 // { "AdjuWhiteProc", AdjuWhiteProc },
1819 // { "AdjuBlackProc", AdjuBlackProc },
1820 // { "AdjuDrawProc", AdjuDrawProc },
1821 { "EnterKeyProc", EnterKeyProc },
1822 // { "StopObservingProc", StopObservingProc },
1823 // { "StopExaminingProc", StopExaminingProc },
1824 // { "BackwardProc", BackwardProc },
1825 // { "ForwardProc", ForwardProc },
1826 // { "ToStartProc", ToStartProc },
1827 // { "ToEndProc", ToEndProc },
1828 // { "RevertProc", RevertProc },
1829 // { "TruncateGameProc", TruncateGameProc },
1830 // { "MoveNowProc", MoveNowProc },
1831 // { "RetractMoveProc", RetractMoveProc },
1832 { "AlwaysQueenProc", AlwaysQueenProc },
1833 { "AnimateDraggingProc", AnimateDraggingProc },
1834 { "AnimateMovingProc", AnimateMovingProc },
1835 // { "AutoflagProc", AutoflagProc },
1836 // { "AutoflipProc", AutoflipProc },
1837 { "AutobsProc", AutobsProc },
1838 { "AutoraiseProc", AutoraiseProc },
1839 { "AutosaveProc", AutosaveProc },
1840 { "BlindfoldProc", BlindfoldProc },
1841 { "FlashMovesProc", FlashMovesProc },
1842 // { "FlipViewProc", FlipViewProc },
1843 // { "GetMoveListProc", GetMoveListProc },
1845 { "HighlightDraggingProc", HighlightDraggingProc },
1847 { "HighlightLastMoveProc", HighlightLastMoveProc },
1848 { "IcsAlarmProc", IcsAlarmProc },
1849 { "MoveSoundProc", MoveSoundProc },
1850 { "OldSaveStyleProc", OldSaveStyleProc },
1851 { "PeriodicUpdatesProc", PeriodicUpdatesProc },
1852 { "PonderNextMoveProc", PonderNextMoveProc },
1853 { "PopupExitMessageProc", PopupExitMessageProc },
1854 { "PopupMoveErrorsProc", PopupMoveErrorsProc },
1855 { "PremoveProc", PremoveProc },
1856 { "QuietPlayProc", QuietPlayProc },
1857 // { "ShowThinkingProc", ShowThinkingProc },
1858 // { "HideThinkingProc", HideThinkingProc },
1859 { "TestLegalityProc", TestLegalityProc },
1860 // { "InfoProc", InfoProc },
1861 // { "ManProc", ManProc },
1862 // { "HintProc", HintProc },
1863 // { "BookProc", BookProc },
1864 { "AboutGameProc", AboutGameProc },
1865 { "DebugProc", DebugProc },
1866 { "NothingProc", NothingProc },
1867 { "CommentPopDown", (XtActionProc) CommentPopDown },
1868 { "EditCommentPopDown", (XtActionProc) EditCommentPopDown },
1869 { "TagsPopDown", (XtActionProc) TagsPopDown },
1870 { "ErrorPopDown", (XtActionProc) ErrorPopDown },
1871 { "ICSInputBoxPopDown", (XtActionProc) ICSInputBoxPopDown },
1872 { "EngineOutputPopDown", (XtActionProc) EngineOutputPopDown },
1873 // { "FileNamePopDown", (XtActionProc) FileNamePopDown },
1874 { "AskQuestionPopDown", (XtActionProc) AskQuestionPopDown },
1875 { "GameListPopDown", (XtActionProc) GameListPopDown },
1876 { "PromotionPopDown", (XtActionProc) PromotionPopDown },
1877 // { "HistoryPopDown", (XtActionProc) HistoryPopDown },
1878 { "EngineOutputPopDown", (XtActionProc) EngineOutputPopDown },
1879 { "ShufflePopDown", (XtActionProc) ShufflePopDown },
1880 { "EnginePopDown", (XtActionProc) EnginePopDown },
1881 { "UciPopDown", (XtActionProc) UciPopDown },
1882 { "TimeControlPopDown", (XtActionProc) TimeControlPopDown },
1883 { "NewVariantPopDown", (XtActionProc) NewVariantPopDown },
1884 { "SettingsPopDown", (XtActionProc) SettingsPopDown },
1888 char ICSInputTranslations[] =
1889 "<Key>Return: EnterKeyProc() \n";
1891 String xboardResources[] = {
1892 // "*fileName*value.translations: #override\\n <Key>Return: FileNameAction()",
1893 "*question*value.translations: #override\\n <Key>Return: AskQuestionReplyAction()",
1894 "*errorpopup*translations: #override\\n <Key>Return: ErrorPopDown()",
1898 static char *cnames[9] = { "black", "red", "green", "yellow", "blue",
1899 "magenta", "cyan", "white" };
1903 TextColors textColors[(int)NColorClasses];
1905 /* String is: "fg, bg, attr". Which is 0, 1, 2 */
1907 parse_color(str, which)
1911 char *p, buf[100], *d;
1914 if (strlen(str) > 99) /* watch bounds on buf */
1919 for (i=0; i<which; ++i) {
1926 /* Could be looking at something like:
1928 .. in which case we want to stop on a comma also */
1929 while (*p && *p != ',' && !isalpha(*p) && !isdigit(*p))
1933 return -1; /* Use default for empty field */
1936 if (which == 2 || isdigit(*p))
1939 while (*p && isalpha(*p))
1944 for (i=0; i<8; ++i) {
1945 if (!StrCaseCmp(buf, cnames[i]))
1946 return which? (i+40) : (i+30);
1948 if (!StrCaseCmp(buf, "default")) return -1;
1950 fprintf(stderr, _("%s: unrecognized color %s\n"), programName, buf);
1955 parse_cpair(cc, str)
1959 if ((textColors[(int)cc].fg=parse_color(str, 0)) == -2) {
1960 fprintf(stderr, _("%s: can't parse foreground color in `%s'\n"),
1965 /* bg and attr are optional */
1966 textColors[(int)cc].bg = parse_color(str, 1);
1967 if ((textColors[(int)cc].attr = parse_color(str, 2)) < 0) {
1968 textColors[(int)cc].attr = 0;
1974 /* Arrange to catch delete-window events */
1975 Atom wm_delete_window;
1977 CatchDeleteWindow(Widget w, String procname)
1980 XSetWMProtocols(xDisplay, XtWindow(w), &wm_delete_window, 1);
1981 snprintf(buf, sizeof(buf), "<Message>WM_PROTOCOLS: %s() \n", procname);
1982 XtAugmentTranslations(w, XtParseTranslationTable(buf));
1988 /* this should raise the board to the top */
1989 gtk_window_present(GTK_WINDOW(GUI_Window));
1993 #define BoardSize int
1994 void InitDrawingSizes(BoardSize boardSize, int flags)
1995 { // [HGM] resize is functional now, but for board format changes only (nr of ranks, files)
1996 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
1998 XtGeometryResult gres;
2001 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2002 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2004 timerWidth = (boardWidth - sep) / 2;
2006 if (appData.titleInWindow)
2011 w = boardWidth - 2*bor;
2015 w = boardWidth - w - sep - 2*bor - 2; // WIDTH_FUDGE
2019 if(!formWidget) return;
2022 * Inhibit shell resizing.
2025 // [HGM] pieces: tailor piece bitmaps to needs of specific variant
2028 for(i=0; i<4; i++) {
2030 for(p=0; p<=(int)WhiteKing; p++)
2031 xpmPieceBitmap[i][p] = xpmPieceBitmap2[i][p]; // defaults
2032 if(gameInfo.variant == VariantShogi) {
2033 xpmPieceBitmap[i][(int)WhiteCannon] = xpmPieceBitmap2[i][(int)WhiteKing+1];
2034 xpmPieceBitmap[i][(int)WhiteNightrider] = xpmPieceBitmap2[i][(int)WhiteKing+2];
2035 xpmPieceBitmap[i][(int)WhiteSilver] = xpmPieceBitmap2[i][(int)WhiteKing+3];
2036 xpmPieceBitmap[i][(int)WhiteGrasshopper] = xpmPieceBitmap2[i][(int)WhiteKing+4];
2037 xpmPieceBitmap[i][(int)WhiteQueen] = xpmPieceBitmap2[i][(int)WhiteLance];
2040 if(gameInfo.variant == VariantGothic) {
2041 xpmPieceBitmap[i][(int)WhiteMarshall] = xpmPieceBitmap2[i][(int)WhiteSilver];
2045 // [HGM] why are thee ximMasks used at all? the ximPieceBitmaps seem to be never used!
2046 for(p=0; p<=(int)WhiteKing; p++)
2047 ximMaskPm[p] = ximMaskPm2[p]; // defaults
2048 if(gameInfo.variant == VariantShogi) {
2049 ximMaskPm[(int)WhiteCannon] = ximMaskPm2[(int)WhiteKing+1];
2050 ximMaskPm[(int)WhiteNightrider] = ximMaskPm2[(int)WhiteKing+2];
2051 ximMaskPm[(int)WhiteSilver] = ximMaskPm2[(int)WhiteKing+3];
2052 ximMaskPm[(int)WhiteGrasshopper] = ximMaskPm2[(int)WhiteKing+4];
2053 ximMaskPm[(int)WhiteQueen] = ximMaskPm2[(int)WhiteLance];
2056 if(gameInfo.variant == VariantGothic) {
2057 ximMaskPm[(int)WhiteMarshall] = ximMaskPm2[(int)WhiteSilver];
2063 for(i=0; i<2; i++) {
2065 for(p=0; p<=(int)WhiteKing; p++)
2066 pieceBitmap[i][p] = pieceBitmap2[i][p]; // defaults
2067 if(gameInfo.variant == VariantShogi) {
2068 pieceBitmap[i][(int)WhiteCannon] = pieceBitmap2[i][(int)WhiteKing+1];
2069 pieceBitmap[i][(int)WhiteNightrider] = pieceBitmap2[i][(int)WhiteKing+2];
2070 pieceBitmap[i][(int)WhiteSilver] = pieceBitmap2[i][(int)WhiteKing+3];
2071 pieceBitmap[i][(int)WhiteGrasshopper] = pieceBitmap2[i][(int)WhiteKing+4];
2072 pieceBitmap[i][(int)WhiteQueen] = pieceBitmap2[i][(int)WhiteLance];
2075 if(gameInfo.variant == VariantGothic) {
2076 pieceBitmap[i][(int)WhiteMarshall] = pieceBitmap2[i][(int)WhiteSilver];
2086 void EscapeExpand(char *p, char *q)
2087 { // [HGM] initstring: routine to shape up string arguments
2088 while(*p++ = *q++) if(p[-1] == '\\')
2090 case 'n': p[-1] = '\n'; break;
2091 case 'r': p[-1] = '\r'; break;
2092 case 't': p[-1] = '\t'; break;
2093 case '\\': p[-1] = '\\'; break;
2094 case 0: *p = 0; return;
2095 default: p[-1] = q[-1]; break;
2104 int i, j, clockFontPxlSize, coordFontPxlSize, fontPxlSize;
2105 XSetWindowAttributes window_attributes;
2107 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
2108 XrmValue vFrom, vTo;
2109 XtGeometryResult gres;
2112 int forceMono = False;
2116 // [HGM] before anything else, expand any indirection files amongst options
2117 char *argvCopy[1000]; // 1000 seems enough
2118 char newArgs[10000]; // holds actual characters
2121 srandom(time(0)); // [HGM] book: make random truly random
2124 for(i=0; i<argc; i++) {
2125 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2126 //fprintf(stderr, "arg %s\n", argv[i]);
2127 if(argv[i][0] != '@') argvCopy[j++] = argv[i]; else {
2129 FILE *f = fopen(argv[i]+1, "rb");
2130 if(f == NULL) { fprintf(stderr, _("ignore %s\n"), argv[i]); continue; } // do not expand non-existing
2131 argvCopy[j++] = newArgs + k; // get ready for first argument from file
2132 while((c = fgetc(f)) != EOF) { // each line of file inserts 1 argument in the list
2134 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2135 newArgs[k++] = 0; // terminate current arg
2136 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2137 argvCopy[j++] = newArgs + k; // get ready for next
2139 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2153 setbuf(stdout, NULL);
2154 setbuf(stderr, NULL);
2157 programName = strrchr(argv[0], '/');
2158 if (programName == NULL)
2159 programName = argv[0];
2164 XtSetLanguageProc(NULL, NULL, NULL);
2165 bindtextdomain(PACKAGE, LOCALEDIR);
2166 textdomain(PACKAGE);
2170 XtAppInitialize(&appContext, "XBoard", shellOptions,
2171 XtNumber(shellOptions),
2172 &argc, argv, xboardResources, NULL, 0);
2175 gtk_init (&argc, &argv);
2177 /* parse glade file to build widgets */
2179 builder = gtk_builder_new ();
2180 gtk_builder_add_from_file (builder, "gtk-interface.xml", NULL);
2182 /* test if everything worked ok */
2184 GUI_Window = GTK_WIDGET (gtk_builder_get_object (builder, "MainWindow"));
2185 if(!GUI_Window) printf("Error: gtk_builder didn't work!\n");
2187 GUI_Aspect = GTK_WIDGET (gtk_builder_get_object (builder, "Aspectframe"));
2188 if(!GUI_Aspect) printf("Error: gtk_builder didn't work!\n");
2190 GUI_History = GTK_WIDGET (gtk_builder_get_object (builder, "MoveHistory"));
2191 if(!GUI_History) printf("Error: gtk_builder didn't work!\n");
2193 GUI_Menubar = GTK_WIDGET (gtk_builder_get_object (builder, "MenuBar"));
2194 if(!GUI_Menubar) printf("Error: gtk_builder didn't work!\n");
2195 GUI_Timer = GTK_WIDGET (gtk_builder_get_object (builder, "Timer"));
2196 if(!GUI_Timer) printf("Error: gtk_builder didn't work!\n");
2197 GUI_Buttonbar = GTK_WIDGET (gtk_builder_get_object (builder, "ButtonBar"));
2198 if(!GUI_Buttonbar) printf("Error: gtk_builder didn't work!\n");
2199 GUI_Board = GTK_WIDGET (gtk_builder_get_object (builder, "Board"));
2200 if(!GUI_Board) printf("Error: gtk_builder didn't work!\n");
2202 GUI_Whiteclock = GTK_WIDGET (gtk_builder_get_object (builder, "WhiteClock"));
2203 if(!GUI_Whiteclock) printf("Error: gtk_builder didn't work!\n");
2205 GUI_Blackclock = GTK_WIDGET (gtk_builder_get_object (builder, "BlackClock"));
2206 if(!GUI_Blackclock) printf("Error: gtk_builder didn't work!\n");
2208 LIST_MoveHistory = GTK_LIST_STORE (gtk_builder_get_object (builder, "MoveHistoryStore"));
2209 if(!LIST_MoveHistory) printf("Error: gtk_builder didn't work!\n");
2212 gtk_builder_connect_signals (builder, NULL);
2214 // don't unref the builder, since we use it to get references to widgets
2215 // g_object_unref (G_OBJECT (builder));
2217 /* end parse glade file */
2221 fprintf(stderr, _("%s: unrecognized argument %s\n"),
2222 programName, argv[1]);
2224 fprintf(stderr, "Recognized options:\n");
2225 for(i = 0; i < XtNumber(shellOptions); i++)
2227 /* print first column */
2228 j = fprintf(stderr, " %s%s", shellOptions[i].option,
2229 (shellOptions[i].argKind == XrmoptionSepArg
2231 /* print second column and end line */
2232 if (++i < XtNumber(shellOptions))
2234 fprintf(stderr, "%*c%s%s\n", 40 - j, ' ',
2235 shellOptions[i].option,
2236 (shellOptions[i].argKind == XrmoptionSepArg
2241 fprintf(stderr, "\n");
2248 if (p == NULL) p = "/tmp";
2249 i = strlen(p) + strlen("/.xboardXXXXXx.pgn") + 1;
2250 gameCopyFilename = (char*) malloc(i);
2251 gamePasteFilename = (char*) malloc(i);
2252 snprintf(gameCopyFilename,i, "%s/.xboard%05uc.pgn", p, getpid());
2253 snprintf(gamePasteFilename,i, "%s/.xboard%05up.pgn", p, getpid());
2255 XtGetApplicationResources(shellWidget, (XtPointer) &appData,
2256 clientResources, XtNumber(clientResources),
2259 { // [HGM] initstring: kludge to fix bad bug. expand '\n' characters in init string and computer string.
2260 static char buf[MSG_SIZ];
2261 EscapeExpand(buf, appData.initString);
2262 appData.initString = strdup(buf);
2263 EscapeExpand(buf, appData.secondInitString);
2264 appData.secondInitString = strdup(buf);
2265 EscapeExpand(buf, appData.firstComputerString);
2266 appData.firstComputerString = strdup(buf);
2267 EscapeExpand(buf, appData.secondComputerString);
2268 appData.secondComputerString = strdup(buf);
2271 if ((chessDir = (char *) getenv("CHESSDIR")) == NULL) {
2274 if (chdir(chessDir) != 0) {
2275 fprintf(stderr, _("%s: can't cd to CHESSDIR: "), programName);
2281 if (appData.debugMode && appData.nameOfDebugFile && strcmp(appData.nameOfDebugFile, "stderr")) {
2282 /* [DM] debug info to file [HGM] make the filename a command-line option, and allow it to remain stderr */
2283 if ((debugFP = fopen(appData.nameOfDebugFile, "w")) == NULL) {
2284 printf(_("Failed to open file '%s'\n"), appData.nameOfDebugFile);
2287 setbuf(debugFP, NULL);
2290 /* [HGM,HR] make sure board size is acceptable */
2291 if(appData.NrFiles > BOARD_SIZE ||
2292 appData.NrRanks > BOARD_SIZE )
2293 DisplayFatalError(_("Recompile with BOARD_SIZE > 12, to support this size"), 0, 2);
2296 /* This feature does not work; animation needs a rewrite */
2297 appData.highlightDragging = FALSE;
2301 xDisplay = XtDisplay(shellWidget);
2302 xScreen = DefaultScreen(xDisplay);
2303 wm_delete_window = XInternAtom(xDisplay, "WM_DELETE_WINDOW", True);
2305 gameInfo.variant = StringToVariant(appData.variant);
2306 InitPosition(FALSE);
2308 /* calc board size */
2309 if (isdigit(appData.boardSize[0]))
2311 i = sscanf(appData.boardSize, "%d,%d,%d,%d,%d,%d,%d", &squareSize,
2312 &lineGap, &clockFontPxlSize, &coordFontPxlSize,
2313 &fontPxlSize, &smallLayout, &tinyLayout);
2316 fprintf(stderr, _("%s: bad boardSize syntax %s\n"),
2317 programName, appData.boardSize);
2322 /* Find some defaults; use the nearest known size */
2323 SizeDefaults *szd, *nearest;
2324 int distance = 99999;
2325 nearest = szd = sizeDefaults;
2326 while (szd->name != NULL)
2328 if (abs(szd->squareSize - squareSize) < distance)
2331 distance = abs(szd->squareSize - squareSize);
2332 if (distance == 0) break;
2336 if (i < 2) lineGap = nearest->lineGap;
2337 if (i < 3) clockFontPxlSize = nearest->clockFontPxlSize;
2338 if (i < 4) coordFontPxlSize = nearest->coordFontPxlSize;
2339 if (i < 5) fontPxlSize = nearest->fontPxlSize;
2340 if (i < 6) smallLayout = nearest->smallLayout;
2341 if (i < 7) tinyLayout = nearest->tinyLayout;
2346 SizeDefaults *szd = sizeDefaults;
2347 if (*appData.boardSize == NULLCHAR)
2349 while (DisplayWidth(xDisplay, xScreen) < szd->minScreenSize
2350 || DisplayHeight(xDisplay, xScreen) < szd->minScreenSize)
2354 if (szd->name == NULL) szd--;
2358 while (szd->name != NULL
2359 && StrCaseCmp(szd->name, appData.boardSize) != 0)
2361 if (szd->name == NULL)
2363 fprintf(stderr, _("%s: unrecognized boardSize name %s\n"),
2364 programName, appData.boardSize);
2368 squareSize = szd->squareSize;
2369 lineGap = szd->lineGap;
2370 clockFontPxlSize = szd->clockFontPxlSize;
2371 coordFontPxlSize = szd->coordFontPxlSize;
2372 fontPxlSize = szd->fontPxlSize;
2373 smallLayout = szd->smallLayout;
2374 tinyLayout = szd->tinyLayout;
2376 /* end figuring out what size to use */
2378 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2379 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2382 * Determine what fonts to use.
2384 appData.clockFont = FindFont(appData.clockFont, clockFontPxlSize);
2385 clockFontID = XLoadFont(xDisplay, appData.clockFont);
2386 clockFontStruct = XQueryFont(xDisplay, clockFontID);
2387 appData.coordFont = FindFont(appData.coordFont, coordFontPxlSize);
2388 coordFontID = XLoadFont(xDisplay, appData.coordFont);
2389 coordFontStruct = XQueryFont(xDisplay, coordFontID);
2390 appData.font = FindFont(appData.font, fontPxlSize);
2391 countFontID = XLoadFont(xDisplay, appData.coordFont); // [HGM] holdings
2392 countFontStruct = XQueryFont(xDisplay, countFontID);
2393 // appData.font = FindFont(appData.font, fontPxlSize);
2395 xdb = XtDatabase(xDisplay);
2396 XrmPutStringResource(&xdb, "*font", appData.font);
2399 * Detect if there are not enough colors available and adapt.
2401 if (DefaultDepth(xDisplay, xScreen) <= 2) {
2402 appData.monoMode = True;
2405 if (!appData.monoMode) {
2406 vFrom.addr = (caddr_t) appData.lightSquareColor;
2407 vFrom.size = strlen(appData.lightSquareColor);
2408 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2409 if (vTo.addr == NULL) {
2410 appData.monoMode = True;
2413 lightSquareColor = *(Pixel *) vTo.addr;
2416 if (!appData.monoMode) {
2417 vFrom.addr = (caddr_t) appData.darkSquareColor;
2418 vFrom.size = strlen(appData.darkSquareColor);
2419 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2420 if (vTo.addr == NULL) {
2421 appData.monoMode = True;
2424 darkSquareColor = *(Pixel *) vTo.addr;
2427 if (!appData.monoMode) {
2428 vFrom.addr = (caddr_t) appData.whitePieceColor;
2429 vFrom.size = strlen(appData.whitePieceColor);
2430 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2431 if (vTo.addr == NULL) {
2432 appData.monoMode = True;
2435 whitePieceColor = *(Pixel *) vTo.addr;
2438 if (!appData.monoMode) {
2439 vFrom.addr = (caddr_t) appData.blackPieceColor;
2440 vFrom.size = strlen(appData.blackPieceColor);
2441 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2442 if (vTo.addr == NULL) {
2443 appData.monoMode = True;
2446 blackPieceColor = *(Pixel *) vTo.addr;
2450 if (!appData.monoMode) {
2451 vFrom.addr = (caddr_t) appData.highlightSquareColor;
2452 vFrom.size = strlen(appData.highlightSquareColor);
2453 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2454 if (vTo.addr == NULL) {
2455 appData.monoMode = True;
2458 highlightSquareColor = *(Pixel *) vTo.addr;
2462 if (!appData.monoMode) {
2463 vFrom.addr = (caddr_t) appData.premoveHighlightColor;
2464 vFrom.size = strlen(appData.premoveHighlightColor);
2465 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2466 if (vTo.addr == NULL) {
2467 appData.monoMode = True;
2470 premoveHighlightColor = *(Pixel *) vTo.addr;
2475 fprintf(stderr, _("%s: too few colors available; trying monochrome mode\n"),
2478 if (appData.bitmapDirectory == NULL ||
2479 appData.bitmapDirectory[0] == NULLCHAR)
2480 appData.bitmapDirectory = DEF_BITMAP_DIR;
2483 if (appData.lowTimeWarning && !appData.monoMode) {
2484 vFrom.addr = (caddr_t) appData.lowTimeWarningColor;
2485 vFrom.size = strlen(appData.lowTimeWarningColor);
2486 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2487 if (vTo.addr == NULL)
2488 appData.monoMode = True;
2490 lowTimeWarningColor = *(Pixel *) vTo.addr;
2493 if (appData.monoMode && appData.debugMode) {
2494 fprintf(stderr, _("white pixel = 0x%lx, black pixel = 0x%lx\n"),
2495 (unsigned long) XWhitePixel(xDisplay, xScreen),
2496 (unsigned long) XBlackPixel(xDisplay, xScreen));
2499 if (parse_cpair(ColorShout, appData.colorShout) < 0 ||
2500 parse_cpair(ColorSShout, appData.colorSShout) < 0 ||
2501 parse_cpair(ColorChannel1, appData.colorChannel1) < 0 ||
2502 parse_cpair(ColorChannel, appData.colorChannel) < 0 ||
2503 parse_cpair(ColorKibitz, appData.colorKibitz) < 0 ||
2504 parse_cpair(ColorTell, appData.colorTell) < 0 ||
2505 parse_cpair(ColorChallenge, appData.colorChallenge) < 0 ||
2506 parse_cpair(ColorRequest, appData.colorRequest) < 0 ||
2507 parse_cpair(ColorSeek, appData.colorSeek) < 0 ||
2508 parse_cpair(ColorNormal, appData.colorNormal) < 0)
2510 if (appData.colorize) {
2512 _("%s: can't parse color names; disabling colorization\n"),
2515 appData.colorize = FALSE;
2517 textColors[ColorNone].fg = textColors[ColorNone].bg = -1;
2518 textColors[ColorNone].attr = 0;
2520 // XtAppAddActions(appContext, boardActions, XtNumber(boardActions));
2526 layoutName = "tinyLayout";
2527 } else if (smallLayout) {
2528 layoutName = "smallLayout";
2530 layoutName = "normalLayout";
2533 if (appData.titleInWindow) {
2534 /* todo check what this appdata does */
2537 if (appData.showButtonBar) {
2538 /* TODO hide button bar if requested */
2542 if (appData.titleInWindow)
2547 if (appData.showButtonBar)
2554 if (appData.showButtonBar)
2564 /* set some checkboxes in the menu according to appData */
2566 if (appData.alwaysPromoteToQueen)
2567 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Always Queen")),TRUE);
2569 if (appData.animateDragging)
2570 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Animate Dragging")),TRUE);
2572 if (appData.animate)
2573 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Animate Moving")),TRUE);
2575 if (appData.autoComment)
2576 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Comment")),TRUE);
2578 if (appData.autoCallFlag)
2579 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Flag")),TRUE);
2581 if (appData.autoFlipView)
2582 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Flip View")),TRUE);
2584 if (appData.autoObserve)
2585 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Observe")),TRUE);
2587 if (appData.autoRaiseBoard)
2588 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Raise Board")),TRUE);
2590 if (appData.autoSaveGames)
2591 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Save")),TRUE);
2593 if (appData.saveGameFile[0] != NULLCHAR)
2595 /* Can't turn this off from menu */
2596 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Save")),TRUE);
2597 gtk_action_set_sensitive(GTK_ACTION (gtk_builder_get_object (builder, "menuOptions.Auto Save")),FALSE);
2600 if (appData.blindfold)
2601 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Blindfold")),TRUE);
2603 if (appData.flashCount > 0)
2604 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Flash Moves")),TRUE);
2606 if (appData.getMoveList)
2607 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Get Move List")),TRUE);
2610 if (appData.highlightDragging)
2611 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Highlight Dragging")),TRUE);
2614 if (appData.highlightLastMove)
2615 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Highlight Last Move")),TRUE);
2617 if (appData.icsAlarm)
2618 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.ICS Alarm")),TRUE);
2620 if (appData.ringBellAfterMoves)
2621 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Move Sound")),TRUE);
2623 if (appData.oldSaveStyle)
2624 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Old Save Style")),TRUE);
2626 if (appData.periodicUpdates)
2627 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Periodic Updates")),TRUE);
2629 if (appData.ponderNextMove)
2630 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Ponder Next Move")),TRUE);
2632 if (appData.popupExitMessage)
2633 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Popup Exit Message")),TRUE);
2635 if (appData.popupMoveErrors)
2636 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Popup Move Errors")),TRUE);
2638 if (appData.premove)
2639 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Premove")),TRUE);
2641 if (appData.quietPlay)
2642 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Quit Play")),TRUE);
2644 if (appData.showCoords)
2645 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Show Coords")),TRUE);
2647 if (appData.showThinking)
2648 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Show Thinking")),TRUE);
2650 if (appData.testLegality)
2651 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Test Legality")),TRUE);
2653 /* end setting check boxes */
2655 /* load square colors */
2656 SVGLightSquare = load_pixbuf("svg/LightSquare.svg",squareSize);
2657 SVGDarkSquare = load_pixbuf("svg/DarkSquare.svg",squareSize);
2658 SVGNeutralSquare = load_pixbuf("svg/NeutralSquare.svg",squareSize);
2660 /* use two icons to indicate if it is white's or black's turn */
2661 WhiteIcon = load_pixbuf("svg/icon_white.svg",0);
2662 BlackIcon = load_pixbuf("svg/icon_black.svg",0);
2663 WindowIcon = WhiteIcon;
2664 gtk_window_set_icon(GTK_WINDOW(GUI_Window),WindowIcon);
2667 /* realize window */
2668 gtk_widget_show (GUI_Window);
2670 /* recalc boardsize */
2675 if (appData.animate || appData.animateDragging)
2680 if (errorExitStatus == -1) {
2681 if (appData.icsActive) {
2682 /* We now wait until we see "login:" from the ICS before
2683 sending the logon script (problems with timestamp otherwise) */
2684 /*ICSInitScript();*/
2685 if (appData.icsInputBox) ICSInputBoxPopUp();
2688 signal(SIGINT, IntSigHandler);
2689 signal(SIGTERM, IntSigHandler);
2690 if (*appData.cmailGameName != NULLCHAR) {
2691 signal(SIGUSR1, CmailSigHandler);
2694 gameInfo.boardWidth = 0; // [HGM] pieces: kludge to ensure InitPosition() calls InitDrawingSizes()
2698 * Create a cursor for the board widget.
2699 * (This needs to be called after the window has been created to have access to board-window)
2702 BoardCursor = gdk_cursor_new(GDK_HAND2);
2703 gdk_window_set_cursor(GUI_Board->window, BoardCursor);
2704 gdk_cursor_destroy(BoardCursor);
2709 if (appData.debugMode) fclose(debugFP); // [DM] debug
2716 if (appData.icsActive && oldICSInteractionTitle != NULL) {
2717 DisplayIcsInteractionTitle(oldICSInteractionTitle);
2719 unlink(gameCopyFilename);
2720 unlink(gamePasteFilename);
2723 RETSIGTYPE TermSizeSigHandler(int sig)
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 CommentCallback(w, client_data, call_data)
4619 XtPointer client_data, call_data;
4626 XtSetArg(args[j], XtNlabel, &name); j++;
4627 XtGetValues(w, args, j);
4629 if (strcmp(name, _("close")) == 0) {
4631 } else if (strcmp(name, _("edit")) == 0) {
4638 void CommentPopDown()
4643 if (!commentUp) return;
4645 XtSetArg(args[j], XtNx, &commentX); j++;
4646 XtSetArg(args[j], XtNy, &commentY); j++;
4647 XtSetArg(args[j], XtNwidth, &commentW); j++;
4648 XtSetArg(args[j], XtNheight, &commentH); j++;
4649 XtGetValues(commentShell, args, j);
4650 XtPopdown(commentShell);
4651 XSync(xDisplay, False);
4655 void PromotionPopUp()
4658 Widget dialog, layout;
4660 Dimension bw_width, pw_width;
4664 XtSetArg(args[j], XtNwidth, &bw_width); j++;
4665 XtGetValues(boardWidget, args, j);
4668 XtSetArg(args[j], XtNresizable, True); j++;
4669 XtSetArg(args[j], XtNtitle, XtNewString(_("Promotion"))); j++;
4671 XtCreatePopupShell("Promotion", transientShellWidgetClass,
4672 shellWidget, args, j);
4674 XtCreateManagedWidget(layoutName, formWidgetClass, promotionShell,
4675 layoutArgs, XtNumber(layoutArgs));
4678 XtSetArg(args[j], XtNlabel, _("Promote to what?")); j++;
4679 XtSetArg(args[j], XtNborderWidth, 0); j++;
4680 dialog = XtCreateManagedWidget("promotion", dialogWidgetClass,
4683 if(gameInfo.variant != VariantShogi) {
4684 XawDialogAddButton(dialog, _("Queen"), PromotionCallback,
4685 (XtPointer) dialog);
4686 XawDialogAddButton(dialog, _("Rook"), PromotionCallback,
4687 (XtPointer) dialog);
4688 XawDialogAddButton(dialog, _("Bishop"), PromotionCallback,
4689 (XtPointer) dialog);
4690 XawDialogAddButton(dialog, _("Knight"), PromotionCallback,
4691 (XtPointer) dialog);
4692 if (!appData.testLegality || gameInfo.variant == VariantSuicide ||
4693 gameInfo.variant == VariantGiveaway) {
4694 XawDialogAddButton(dialog, _("King"), PromotionCallback,
4695 (XtPointer) dialog);
4697 if(gameInfo.variant == VariantCapablanca ||
4698 gameInfo.variant == VariantGothic ||
4699 gameInfo.variant == VariantCapaRandom) {
4700 XawDialogAddButton(dialog, _("Archbishop"), PromotionCallback,
4701 (XtPointer) dialog);
4702 XawDialogAddButton(dialog, _("Chancellor"), PromotionCallback,
4703 (XtPointer) dialog);
4705 } else // [HGM] shogi
4707 XawDialogAddButton(dialog, _("Promote"), PromotionCallback,
4708 (XtPointer) dialog);
4709 XawDialogAddButton(dialog, _("Defer"), PromotionCallback,
4710 (XtPointer) dialog);
4712 XawDialogAddButton(dialog, _("cancel"), PromotionCallback,
4713 (XtPointer) dialog);
4715 XtRealizeWidget(promotionShell);
4716 CatchDeleteWindow(promotionShell, "PromotionPopDown");
4719 XtSetArg(args[j], XtNwidth, &pw_width); j++;
4720 XtGetValues(promotionShell, args, j);
4722 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
4723 lineGap + squareSize/3 +
4724 ((toY == BOARD_HEIGHT-1) ^ (flipView) ?
4725 0 : 6*(squareSize + lineGap)), &x, &y);
4728 XtSetArg(args[j], XtNx, x); j++;
4729 XtSetArg(args[j], XtNy, y); j++;
4730 XtSetValues(promotionShell, args, j);
4732 XtPopup(promotionShell, XtGrabNone);
4737 void PromotionPopDown()
4739 if (!promotionUp) return;
4740 XtPopdown(promotionShell);
4741 XtDestroyWidget(promotionShell);
4742 promotionUp = False;
4745 void PromotionCallback(w, client_data, call_data)
4747 XtPointer client_data, call_data;
4753 XtSetArg(args[0], XtNlabel, &name);
4754 XtGetValues(w, args, 1);
4758 if (fromX == -1) return;
4760 if (strcmp(name, _("cancel")) == 0) {
4764 } else if (strcmp(name, _("Knight")) == 0) {
4766 } else if (strcmp(name, _("Promote")) == 0) {
4768 } else if (strcmp(name, _("Defer")) == 0) {
4771 promoChar = ToLower(name[0]);
4774 FinishMove(NormalMove, fromX, fromY, toX, toY, promoChar);
4776 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
4777 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
4782 void ErrorCallback(w, client_data, call_data)
4784 XtPointer client_data, call_data;
4787 XtPopdown(w = XtParent(XtParent(XtParent(w))));
4789 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
4795 if (!errorUp) return;
4799 gtk_widget_destroy(GTK_WIDGET(GUI_Error));
4801 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
4806 void ErrorPopUp(title, label, modal)
4807 char *title, *label;
4810 GUI_Error = gtk_message_dialog_new(GTK_WINDOW(GUI_Window),
4811 GTK_DIALOG_DESTROY_WITH_PARENT,
4816 gtk_window_set_title(GTK_WINDOW(GUI_Error),(gchar *) title);
4819 gtk_dialog_run(GTK_DIALOG(GUI_Error));
4820 gtk_widget_destroy(GTK_WIDGET(GUI_Error));
4824 g_signal_connect_swapped (GUI_Error, "response",
4825 G_CALLBACK (ErrorPopDownProc),
4828 gtk_widget_show(GTK_WIDGET(GUI_Error));
4834 /* Disable all user input other than deleting the window */
4835 static int frozen = 0;
4839 /* Grab by a widget that doesn't accept input */
4840 // XtAddGrab(messageWidget, TRUE, FALSE);
4844 /* Undo a FreezeUI */
4847 if (!frozen) return;
4848 // XtRemoveGrab(messageWidget);
4852 char *ModeToWidgetName(mode)
4856 case BeginningOfGame:
4857 if (appData.icsActive)
4858 return "menuMode.ICS Client";
4859 else if (appData.noChessProgram ||
4860 *appData.cmailGameName != NULLCHAR)
4861 return "menuMode.Edit Game";
4863 return "menuMode.Machine Black";
4864 case MachinePlaysBlack:
4865 return "menuMode.Machine Black";
4866 case MachinePlaysWhite:
4867 return "menuMode.Machine White";
4869 return "menuMode.Analysis Mode";
4871 return "menuMode.Analyze File";
4872 case TwoMachinesPlay:
4873 return "menuMode.Two Machines";
4875 return "menuMode.Edit Game";
4876 case PlayFromGameFile:
4877 return "menuFile.Load Game";
4879 return "menuMode.Edit Position";
4881 return "menuMode.Training";
4882 case IcsPlayingWhite:
4883 case IcsPlayingBlack:
4887 return "menuMode.ICS Client";
4894 void ModeHighlight()
4896 static int oldPausing = FALSE;
4897 static GameMode oldmode = (GameMode) -1;
4900 // todo this toggling of the pause button doesn't seem to work?
4901 // e.g. select pause from buttonbar doesn't activate menumode.pause
4903 // if (!boardWidget || !XtIsRealized(boardWidget)) return;
4905 if (pausing != oldPausing) {
4906 oldPausing = pausing;
4907 gtk_button_set_relief(GTK_BUTTON (gtk_builder_get_object (builder, "menuMode.Pause")),pausing?GTK_RELIEF_NORMAL:GTK_RELIEF_NONE);
4908 /* toggle background color in showbuttonbar */
4909 if (appData.showButtonBar) {
4911 gtk_button_pressed(GTK_BUTTON (gtk_builder_get_object (builder, "buttonbar.Pause")));
4913 gtk_button_released(GTK_BUTTON (gtk_builder_get_object (builder, "buttonbar.Pause")));
4918 wname = ModeToWidgetName(oldmode);
4920 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, wname)),True);
4924 /* Maybe all the enables should be handled here, not just this one */
4925 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuMode.Training")),
4926 gameMode == Training || gameMode == PlayFromGameFile);
4931 * Button/menu procedures
4934 int LoadGamePopUp(f, gameNumber, title)
4939 cmailMsgLoaded = FALSE;
4941 if (gameNumber == 0)
4943 int error = GameListBuild(f);
4947 DisplayError(_("Cannot build game list"), error);
4949 else if (!ListEmpty(&gameList)
4950 && ((ListGame *) gameList.tailPred)->number > 1)
4952 // TODO convert to GTK
4953 // GameListPopUp(f, title);
4961 return LoadGame(f, gameNumber, title, FALSE);
4964 void ReloadCmailMsgProc(w, event, prms, nprms)
4970 ReloadCmailMsgEvent(FALSE);
4973 void MailMoveProc(w, event, prms, nprms)
4982 /* this variable is shared between CopyPositionProc and SendPositionSelection */
4983 static char *selected_fen_position=NULL;
4986 SendPositionSelection(Widget w, Atom *selection, Atom *target,
4987 Atom *type_return, XtPointer *value_return,
4988 unsigned long *length_return, int *format_return)
4990 char *selection_tmp;
4992 if (!selected_fen_position) return False; /* should never happen */
4993 if (*target == XA_STRING){
4994 /* note: since no XtSelectionDoneProc was registered, Xt will
4995 * automatically call XtFree on the value returned. So have to
4996 * make a copy of it allocated with XtMalloc */
4997 selection_tmp= XtMalloc(strlen(selected_fen_position)+16);
4998 strcpy(selection_tmp, selected_fen_position);
5000 *value_return=selection_tmp;
5001 *length_return=strlen(selection_tmp);
5002 *type_return=XA_STRING;
5003 *format_return = 8; /* bits per byte */
5010 /* note: when called from menu all parameters are NULL, so no clue what the
5011 * Widget which was clicked on was, or what the click event was
5013 void CopyPositionProc(w, event, prms, nprms)
5021 if (selected_fen_position) free(selected_fen_position);
5022 selected_fen_position = (char *)PositionToFEN(currentMove, NULL);
5023 if (!selected_fen_position) return;
5024 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
5026 SendPositionSelection,
5027 NULL/* lose_ownership_proc */ ,
5028 NULL/* transfer_done_proc */);
5030 free(selected_fen_position);
5031 selected_fen_position=NULL;
5035 /* function called when the data to Paste is ready */
5037 PastePositionCB(Widget w, XtPointer client_data, Atom *selection,
5038 Atom *type, XtPointer value, unsigned long *len, int *format)
5041 if (value==NULL || *len==0) return; /* nothing had been selected to copy */
5042 fenstr[*len]='\0'; /* normally this string is terminated, but be safe */
5043 EditPositionPasteFEN(fenstr);
5047 /* called when Paste Position button is pressed,
5048 * all parameters will be NULL */
5049 void PastePositionProc(w, event, prms, nprms)
5055 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
5056 /* (XtSelectionCallbackProc) */ PastePositionCB,
5057 NULL, /* client_data passed to PastePositionCB */
5059 /* better to use the time field from the event that triggered the
5060 * call to this function, but that isn't trivial to get
5068 SendGameSelection(Widget w, Atom *selection, Atom *target,
5069 Atom *type_return, XtPointer *value_return,
5070 unsigned long *length_return, int *format_return)
5072 char *selection_tmp;
5074 if (*target == XA_STRING){
5075 FILE* f = fopen(gameCopyFilename, "r");
5078 if (f == NULL) return False;
5082 selection_tmp = XtMalloc(len + 1);
5083 count = fread(selection_tmp, 1, len, f);
5085 XtFree(selection_tmp);
5088 selection_tmp[len] = NULLCHAR;
5089 *value_return = selection_tmp;
5090 *length_return = len;
5091 *type_return = XA_STRING;
5092 *format_return = 8; /* bits per byte */
5099 /* note: when called from menu all parameters are NULL, so no clue what the
5100 * Widget which was clicked on was, or what the click event was
5102 void CopyGameProc(w, event, prms, nprms)
5110 ret = SaveGameToFile(gameCopyFilename, FALSE);
5113 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
5116 NULL/* lose_ownership_proc */ ,
5117 NULL/* transfer_done_proc */);
5120 /* function called when the data to Paste is ready */
5122 PasteGameCB(Widget w, XtPointer client_data, Atom *selection,
5123 Atom *type, XtPointer value, unsigned long *len, int *format)
5126 if (value == NULL || *len == 0) {
5127 return; /* nothing had been selected to copy */
5129 f = fopen(gamePasteFilename, "w");
5131 DisplayError(_("Can't open temp file"), errno);
5134 fwrite(value, 1, *len, f);
5137 LoadGameFromFile(gamePasteFilename, 0, gamePasteFilename, TRUE);
5140 /* called when Paste Game button is pressed,
5141 * all parameters will be NULL */
5142 void PasteGameProc(w, event, prms, nprms)
5148 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
5149 /* (XtSelectionCallbackProc) */ PasteGameCB,
5150 NULL, /* client_data passed to PasteGameCB */
5152 /* better to use the time field from the event that triggered the
5153 * call to this function, but that isn't trivial to get
5163 SaveGameProc(NULL, NULL);
5167 void AnalyzeModeProc(w, event, prms, nprms)
5175 if (!first.analysisSupport) {
5176 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
5177 DisplayError(buf, 0);
5180 /* [DM] icsEngineAnalyze [HGM] This is horrible code; reverse the gameMode and isEngineAnalyze tests! */
5181 if (appData.icsActive) {
5182 if (gameMode != IcsObserving) {
5183 sprintf(buf,_("You are not observing a game"));
5184 DisplayError(buf, 0);
5186 if (appData.icsEngineAnalyze) {
5187 if (appData.debugMode)
5188 fprintf(debugFP, _("Found unexpected active ICS engine analyze \n"));
5194 /* if enable, use want disable icsEngineAnalyze */
5195 if (appData.icsEngineAnalyze) {
5200 appData.icsEngineAnalyze = TRUE;
5201 if (appData.debugMode)
5202 fprintf(debugFP, _("ICS engine analyze starting... \n"));
5204 if (!appData.showThinking)
5205 ShowThinkingProc(NULL,NULL);
5210 void EditGameProc(w, event, prms, nprms)
5219 void EditPositionProc(w, event, prms, nprms)
5225 EditPositionEvent();
5228 void TrainingProc(w, event, prms, nprms)
5237 void EditCommentProc(w, event, prms, nprms)
5244 EditCommentPopDown();
5250 void IcsInputBoxProc(w, event, prms, nprms)
5256 if (ICSInputBoxUp) {
5257 ICSInputBoxPopDown();
5264 void EnterKeyProc(w, event, prms, nprms)
5270 if (ICSInputBoxUp == True)
5274 void AlwaysQueenProc(w, event, prms, nprms)
5282 appData.alwaysPromoteToQueen = !appData.alwaysPromoteToQueen;
5284 if (appData.alwaysPromoteToQueen) {
5285 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5287 XtSetArg(args[0], XtNleftBitmap, None);
5289 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
5293 void AnimateDraggingProc(w, event, prms, nprms)
5301 appData.animateDragging = !appData.animateDragging;
5303 if (appData.animateDragging) {
5304 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5307 XtSetArg(args[0], XtNleftBitmap, None);
5309 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Dragging"),
5313 void AnimateMovingProc(w, event, prms, nprms)
5321 appData.animate = !appData.animate;
5323 if (appData.animate) {
5324 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5327 XtSetArg(args[0], XtNleftBitmap, None);
5329 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
5333 void AutobsProc(w, event, prms, nprms)
5341 appData.autoObserve = !appData.autoObserve;
5343 if (appData.autoObserve) {
5344 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5346 XtSetArg(args[0], XtNleftBitmap, None);
5348 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
5352 void AutoraiseProc(w, event, prms, nprms)
5360 appData.autoRaiseBoard = !appData.autoRaiseBoard;
5362 if (appData.autoRaiseBoard) {
5363 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5365 XtSetArg(args[0], XtNleftBitmap, None);
5367 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Raise Board"),
5371 void AutosaveProc(w, event, prms, nprms)
5379 appData.autoSaveGames = !appData.autoSaveGames;
5381 if (appData.autoSaveGames) {
5382 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5384 XtSetArg(args[0], XtNleftBitmap, None);
5386 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
5390 void BlindfoldProc(w, event, prms, nprms)
5398 appData.blindfold = !appData.blindfold;
5400 if (appData.blindfold) {
5401 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5403 XtSetArg(args[0], XtNleftBitmap, None);
5405 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Blindfold"),
5408 DrawPosition(True, NULL);
5411 void TestLegalityProc(w, event, prms, nprms)
5419 appData.testLegality = !appData.testLegality;
5421 if (appData.testLegality) {
5422 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5424 XtSetArg(args[0], XtNleftBitmap, None);
5426 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Test Legality"),
5431 void FlashMovesProc(w, event, prms, nprms)
5439 if (appData.flashCount == 0) {
5440 appData.flashCount = 3;
5442 appData.flashCount = -appData.flashCount;
5445 if (appData.flashCount > 0) {
5446 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5448 XtSetArg(args[0], XtNleftBitmap, None);
5450 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flash Moves"),
5455 void HighlightDraggingProc(w, event, prms, nprms)
5463 appData.highlightDragging = !appData.highlightDragging;
5465 if (appData.highlightDragging) {
5466 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5468 XtSetArg(args[0], XtNleftBitmap, None);
5470 XtSetValues(XtNameToWidget(menuBarWidget,
5471 "menuOptions.Highlight Dragging"), args, 1);
5475 void HighlightLastMoveProc(w, event, prms, nprms)
5483 appData.highlightLastMove = !appData.highlightLastMove;
5485 if (appData.highlightLastMove) {
5486 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5488 XtSetArg(args[0], XtNleftBitmap, None);
5490 XtSetValues(XtNameToWidget(menuBarWidget,
5491 "menuOptions.Highlight Last Move"), args, 1);
5494 void IcsAlarmProc(w, event, prms, nprms)
5502 appData.icsAlarm = !appData.icsAlarm;
5504 if (appData.icsAlarm) {
5505 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5507 XtSetArg(args[0], XtNleftBitmap, None);
5509 XtSetValues(XtNameToWidget(menuBarWidget,
5510 "menuOptions.ICS Alarm"), args, 1);
5513 void MoveSoundProc(w, event, prms, nprms)
5521 appData.ringBellAfterMoves = !appData.ringBellAfterMoves;
5523 if (appData.ringBellAfterMoves) {
5524 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5526 XtSetArg(args[0], XtNleftBitmap, None);
5528 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
5533 void OldSaveStyleProc(w, event, prms, nprms)
5541 appData.oldSaveStyle = !appData.oldSaveStyle;
5543 if (appData.oldSaveStyle) {
5544 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5546 XtSetArg(args[0], XtNleftBitmap, None);
5548 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Old Save Style"),
5552 void PeriodicUpdatesProc(w, event, prms, nprms)
5560 PeriodicUpdatesEvent(!appData.periodicUpdates);
5562 if (appData.periodicUpdates) {
5563 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5565 XtSetArg(args[0], XtNleftBitmap, None);
5567 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Periodic Updates"),
5571 void PonderNextMoveProc(w, event, prms, nprms)
5579 PonderNextMoveEvent(!appData.ponderNextMove);
5581 if (appData.ponderNextMove) {
5582 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5584 XtSetArg(args[0], XtNleftBitmap, None);
5586 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Ponder Next Move"),
5590 void PopupExitMessageProc(w, event, prms, nprms)
5598 appData.popupExitMessage = !appData.popupExitMessage;
5600 if (appData.popupExitMessage) {
5601 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5603 XtSetArg(args[0], XtNleftBitmap, None);
5605 XtSetValues(XtNameToWidget(menuBarWidget,
5606 "menuOptions.Popup Exit Message"), args, 1);
5609 void PopupMoveErrorsProc(w, event, prms, nprms)
5617 appData.popupMoveErrors = !appData.popupMoveErrors;
5619 if (appData.popupMoveErrors) {
5620 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5622 XtSetArg(args[0], XtNleftBitmap, None);
5624 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Popup Move Errors"),
5628 void PremoveProc(w, event, prms, nprms)
5636 appData.premove = !appData.premove;
5638 if (appData.premove) {
5639 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5641 XtSetArg(args[0], XtNleftBitmap, None);
5643 XtSetValues(XtNameToWidget(menuBarWidget,
5644 "menuOptions.Premove"), args, 1);
5647 void QuietPlayProc(w, event, prms, nprms)
5655 appData.quietPlay = !appData.quietPlay;
5657 if (appData.quietPlay) {
5658 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5660 XtSetArg(args[0], XtNleftBitmap, None);
5662 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Quiet Play"),
5666 void DebugProc(w, event, prms, nprms)
5672 appData.debugMode = !appData.debugMode;
5675 void AboutGameProc(w, event, prms, nprms)
5684 void NothingProc(w, event, prms, nprms)
5693 void Iconify(w, event, prms, nprms)
5702 XtSetArg(args[0], XtNiconic, True);
5703 XtSetValues(shellWidget, args, 1);
5706 void DisplayMessage(message, extMessage)
5707 gchar *message, *extMessage;
5714 snprintf(buf, sizeof(buf), "%s %s", message, extMessage);
5717 message = extMessage;
5720 gtk_label_set_text( GTK_LABEL(gtk_builder_get_object (builder, "Messages")),message);
5725 void DisplayTitle(text)
5728 gchar title[MSG_SIZ];
5730 if (text == NULL) text = "";
5732 if (appData.titleInWindow)
5737 if (*text != NULLCHAR)
5739 strcpy(title, text);
5741 else if (appData.icsActive)
5743 snprintf(title, sizeof(title), "%s: %s", programName, appData.icsHost);
5745 else if (appData.cmailGameName[0] != NULLCHAR)
5747 snprintf(title,sizeof(title), "%s: %s", programName, "CMail");
5749 // [HGM] license: This stuff should really be done in back-end, but WinBoard already had a pop-up for it
5751 else if (gameInfo.variant == VariantGothic)
5753 strcpy(title, GOTHIC);
5757 else if (gameInfo.variant == VariantFalcon)
5759 strcpy(title, FALCON);
5762 else if (appData.noChessProgram)
5764 strcpy(title, programName);
5768 snprintf(title,sizeof(title), "%s: %s", programName, first.tidy);
5770 gtk_window_set_title(GTK_WINDOW(GUI_Window),title);
5776 void DisplayError(message, error)
5783 if (appData.debugMode || appData.matchMode) {
5784 fprintf(stderr, "%s: %s\n", programName, message);
5787 if (appData.debugMode || appData.matchMode) {
5788 fprintf(stderr, "%s: %s: %s\n",
5789 programName, message, strerror(error));
5791 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
5794 ErrorPopUp(_("Error"), message, FALSE);
5798 void DisplayMoveError(message)
5803 DrawPosition(FALSE, NULL);
5804 if (appData.debugMode || appData.matchMode) {
5805 fprintf(stderr, "%s: %s\n", programName, message);
5807 if (appData.popupMoveErrors) {
5808 ErrorPopUp(_("Error"), message, FALSE);
5810 DisplayMessage(message, "");
5815 void DisplayFatalError(message, error, status)
5821 errorExitStatus = status;
5823 fprintf(stderr, "%s: %s\n", programName, message);
5825 fprintf(stderr, "%s: %s: %s\n",
5826 programName, message, strerror(error));
5827 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
5830 if (appData.popupExitMessage && boardWidget && XtIsRealized(boardWidget)) {
5831 ErrorPopUp(status ? _("Fatal Error") : _("Exiting"), message, TRUE);
5837 void DisplayInformation(message)
5841 ErrorPopUp(_("Information"), message, TRUE);
5844 void DisplayNote(message)
5848 ErrorPopUp(_("Note"), message, FALSE);
5852 NullXErrorCheck(dpy, error_event)
5854 XErrorEvent *error_event;
5859 void DisplayIcsInteractionTitle(message)
5862 if (oldICSInteractionTitle == NULL) {
5863 /* Magic to find the old window title, adapted from vim */
5864 char *wina = getenv("WINDOWID");
5866 Window win = (Window) atoi(wina);
5867 Window root, parent, *children;
5868 unsigned int nchildren;
5869 int (*oldHandler)() = XSetErrorHandler(NullXErrorCheck);
5871 if (XFetchName(xDisplay, win, &oldICSInteractionTitle)) break;
5872 if (!XQueryTree(xDisplay, win, &root, &parent,
5873 &children, &nchildren)) break;
5874 if (children) XFree((void *)children);
5875 if (parent == root || parent == 0) break;
5878 XSetErrorHandler(oldHandler);
5880 if (oldICSInteractionTitle == NULL) {
5881 oldICSInteractionTitle = "xterm";
5884 printf("\033]0;%s\007", message);
5888 char pendingReplyPrefix[MSG_SIZ];
5889 ProcRef pendingReplyPR;
5891 void AskQuestionProc(w, event, prms, nprms)
5898 fprintf(stderr, _("AskQuestionProc needed 4 parameters, got %d\n"),
5902 AskQuestionEvent(prms[0], prms[1], prms[2], prms[3]);
5905 void AskQuestionPopDown()
5907 if (!askQuestionUp) return;
5908 XtPopdown(askQuestionShell);
5909 XtDestroyWidget(askQuestionShell);
5910 askQuestionUp = False;
5913 void AskQuestionReplyAction(w, event, prms, nprms)
5923 reply = XawDialogGetValueString(w = XtParent(w));
5924 strcpy(buf, pendingReplyPrefix);
5925 if (*buf) strcat(buf, " ");
5928 OutputToProcess(pendingReplyPR, buf, strlen(buf), &err);
5929 AskQuestionPopDown();
5931 if (err) DisplayFatalError(_("Error writing to chess program"), err, 0);
5934 void AskQuestionCallback(w, client_data, call_data)
5936 XtPointer client_data, call_data;
5941 XtSetArg(args[0], XtNlabel, &name);
5942 XtGetValues(w, args, 1);
5944 if (strcmp(name, _("cancel")) == 0) {
5945 AskQuestionPopDown();
5947 AskQuestionReplyAction(w, NULL, NULL, NULL);
5951 void AskQuestion(title, question, replyPrefix, pr)
5952 char *title, *question, *replyPrefix;
5956 Widget popup, layout, dialog, edit;
5962 strcpy(pendingReplyPrefix, replyPrefix);
5963 pendingReplyPR = pr;
5966 XtSetArg(args[i], XtNresizable, True); i++;
5967 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
5968 askQuestionShell = popup =
5969 XtCreatePopupShell(title, transientShellWidgetClass,
5970 shellWidget, args, i);
5973 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
5974 layoutArgs, XtNumber(layoutArgs));
5977 XtSetArg(args[i], XtNlabel, question); i++;
5978 XtSetArg(args[i], XtNvalue, ""); i++;
5979 XtSetArg(args[i], XtNborderWidth, 0); i++;
5980 dialog = XtCreateManagedWidget("question", dialogWidgetClass,
5983 XawDialogAddButton(dialog, _("enter"), AskQuestionCallback,
5984 (XtPointer) dialog);
5985 XawDialogAddButton(dialog, _("cancel"), AskQuestionCallback,
5986 (XtPointer) dialog);
5988 XtRealizeWidget(popup);
5989 CatchDeleteWindow(popup, "AskQuestionPopDown");
5991 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
5992 &x, &y, &win_x, &win_y, &mask);
5994 XtSetArg(args[0], XtNx, x - 10);
5995 XtSetArg(args[1], XtNy, y - 30);
5996 XtSetValues(popup, args, 2);
5998 XtPopup(popup, XtGrabExclusive);
5999 askQuestionUp = True;
6001 edit = XtNameToWidget(dialog, "*value");
6002 XtSetKeyboardFocus(popup, edit);
6010 if (*name == NULLCHAR) {
6012 } else if (strcmp(name, "$") == 0) {
6013 putc(BELLCHAR, stderr);
6016 snprintf(buf, sizeof(buf), "%s '%s' &", appData.soundProgram, name);
6024 PlaySound(appData.soundMove);
6030 PlaySound(appData.soundIcsWin);
6036 PlaySound(appData.soundIcsLoss);
6042 PlaySound(appData.soundIcsDraw);
6046 PlayIcsUnfinishedSound()
6048 PlaySound(appData.soundIcsUnfinished);
6054 PlaySound(appData.soundIcsAlarm);
6060 system("stty echo");
6066 system("stty -echo");
6070 Colorize(cc, continuation)
6075 int count, outCount, error;
6077 if (textColors[(int)cc].bg > 0) {
6078 if (textColors[(int)cc].fg > 0) {
6079 sprintf(buf, "\033[0;%d;%d;%dm", textColors[(int)cc].attr,
6080 textColors[(int)cc].fg, textColors[(int)cc].bg);
6082 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
6083 textColors[(int)cc].bg);
6086 if (textColors[(int)cc].fg > 0) {
6087 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
6088 textColors[(int)cc].fg);
6090 sprintf(buf, "\033[0;%dm", textColors[(int)cc].attr);
6093 count = strlen(buf);
6094 outCount = OutputToProcess(NoProc, buf, count, &error);
6095 if (outCount < count) {
6096 DisplayFatalError(_("Error writing to display"), error, 1);
6099 if (continuation) return;
6102 PlaySound(appData.soundShout);
6105 PlaySound(appData.soundSShout);
6108 PlaySound(appData.soundChannel1);
6111 PlaySound(appData.soundChannel);
6114 PlaySound(appData.soundKibitz);
6117 PlaySound(appData.soundTell);
6119 case ColorChallenge:
6120 PlaySound(appData.soundChallenge);
6123 PlaySound(appData.soundRequest);
6126 PlaySound(appData.soundSeek);
6137 return getpwuid(getuid())->pw_name;
6140 static char *ExpandPathName(path)
6143 static char static_buf[2000];
6144 char *d, *s, buf[2000];
6150 while (*s && isspace(*s))
6159 if (*(s+1) == '/') {
6160 strcpy(d, getpwuid(getuid())->pw_dir);
6165 *strchr(buf, '/') = 0;
6166 pwd = getpwnam(buf);
6169 fprintf(stderr, _("ERROR: Unknown user %s (in path %s)\n"),
6173 strcpy(d, pwd->pw_dir);
6174 strcat(d, strchr(s+1, '/'));
6185 static char host_name[MSG_SIZ];
6187 #if HAVE_GETHOSTNAME
6188 gethostname(host_name, MSG_SIZ);
6190 #else /* not HAVE_GETHOSTNAME */
6191 # if HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H
6192 sysinfo(SI_HOSTNAME, host_name, MSG_SIZ);
6194 # else /* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
6196 # endif/* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
6197 #endif /* not HAVE_GETHOSTNAME */
6200 guint delayedEventTimerTag = 0;
6201 DelayedEventCallback delayedEventCallback = 0;
6204 FireDelayedEvent(data)
6208 g_source_remove(delayedEventTimerTag);
6209 delayedEventTimerTag = 0;
6212 delayedEventCallback();
6218 ScheduleDelayedEvent(cb, millisec)
6219 DelayedEventCallback cb; guint millisec;
6221 if(delayedEventTimerTag && delayedEventCallback == cb)
6222 // [HGM] alive: replace, rather than add or flush identical event
6223 g_source_remove(delayedEventTimerTag);
6224 delayedEventCallback = cb;
6225 delayedEventTimerTag = g_timeout_add(millisec,(GSourceFunc) FireDelayedEvent, NULL);
6229 DelayedEventCallback
6232 if (delayedEventTimerTag)
6234 return delayedEventCallback;
6243 CancelDelayedEvent()
6245 if (delayedEventTimerTag)
6247 g_source_remove(delayedEventTimerTag);
6248 delayedEventTimerTag = 0;
6254 guint loadGameTimerTag = 0;
6256 int LoadGameTimerRunning()
6258 return loadGameTimerTag != 0;
6261 int StopLoadGameTimer()
6263 if (loadGameTimerTag != 0) {
6264 g_source_remove(loadGameTimerTag);
6265 loadGameTimerTag = 0;
6273 LoadGameTimerCallback(data)
6277 g_source_remove(loadGameTimerTag);
6278 loadGameTimerTag = 0;
6285 StartLoadGameTimer(millisec)
6289 g_timeout_add( millisec, (GSourceFunc) LoadGameTimerCallback, NULL);
6293 guint analysisClockTag = 0;
6296 AnalysisClockCallback(data)
6299 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile
6300 || appData.icsEngineAnalyze)
6302 AnalysisPeriodicEvent(0);
6303 return 1; /* keep on going */
6305 return 0; /* stop timer */
6309 StartAnalysisClock()
6312 g_timeout_add( 2000,(GSourceFunc) AnalysisClockCallback, NULL);
6316 guint clockTimerTag = 0;
6318 int ClockTimerRunning()
6320 return clockTimerTag != 0;
6323 int StopClockTimer()
6325 if (clockTimerTag != 0)
6327 g_source_remove(clockTimerTag);
6338 ClockTimerCallback(data)
6342 g_source_remove(clockTimerTag);
6350 StartClockTimer(millisec)
6353 clockTimerTag = g_timeout_add(millisec,(GSourceFunc) ClockTimerCallback,NULL);
6358 DisplayTimerLabel(w, color, timer, highlight)
6367 if (appData.clockMode) {
6368 sprintf(buf, "%s: %s", color, TimeString(timer));
6370 sprintf(buf, "%s ", color);
6372 gtk_label_set_text(GTK_LABEL(w),buf);
6374 /* check for low time warning */
6375 // Pixel foregroundOrWarningColor = timerForegroundPixel;
6378 // appData.lowTimeWarning &&
6379 // (timer / 1000) < appData.icsAlarmTime)
6380 // foregroundOrWarningColor = lowTimeWarningColor;
6382 // if (appData.clockMode) {
6383 // sprintf(buf, "%s: %s", color, TimeString(timer));
6384 // XtSetArg(args[0], XtNlabel, buf);
6386 // sprintf(buf, "%s ", color);
6387 // XtSetArg(args[0], XtNlabel, buf);
6392 // XtSetArg(args[1], XtNbackground, foregroundOrWarningColor);
6393 // XtSetArg(args[2], XtNforeground, timerBackgroundPixel);
6395 // XtSetArg(args[1], XtNbackground, timerBackgroundPixel);
6396 // XtSetArg(args[2], XtNforeground, foregroundOrWarningColor);
6399 // XtSetValues(w, args, 3);
6404 DisplayWhiteClock(timeRemaining, highlight)
6408 if(appData.noGUI) return;
6410 DisplayTimerLabel(GUI_Whiteclock, _("White"), timeRemaining, highlight);
6411 if (highlight && WindowIcon == BlackIcon)
6413 WindowIcon = WhiteIcon;
6414 gtk_window_set_icon(GTK_WINDOW(GUI_Window),WindowIcon);
6419 DisplayBlackClock(timeRemaining, highlight)
6423 if(appData.noGUI) return;
6425 DisplayTimerLabel(GUI_Blackclock, _("Black"), timeRemaining, highlight);
6426 if (highlight && WindowIcon == WhiteIcon)
6428 WindowIcon = BlackIcon;
6429 gtk_window_set_icon(GTK_WINDOW(GUI_Window),WindowIcon);
6447 int StartChildProcess(cmdLine, dir, pr)
6454 int to_prog[2], from_prog[2];
6458 if (appData.debugMode) {
6459 fprintf(stderr, "StartChildProcess (dir=\"%s\") %s\n",dir, cmdLine);
6462 /* We do NOT feed the cmdLine to the shell; we just
6463 parse it into blank-separated arguments in the
6464 most simple-minded way possible.
6467 strcpy(buf, cmdLine);
6472 if (p == NULL) break;
6477 SetUpChildIO(to_prog, from_prog);
6480 signal(SIGWINCH, TermSizeSigHandler);
6483 if ((pid = fork()) == 0) {
6485 // [HGM] PSWBTM: made order resistant against case where fd of created pipe was 0 or 1
6486 close(to_prog[1]); // first close the unused pipe ends
6487 close(from_prog[0]);
6488 dup2(to_prog[0], 0); // to_prog was created first, nd is the only one to use 0 or 1
6489 dup2(from_prog[1], 1);
6490 if(to_prog[0] >= 2) close(to_prog[0]); // if 0 or 1, the dup2 already cosed the original
6491 close(from_prog[1]); // and closing again loses one of the pipes!
6492 if(fileno(stderr) >= 2) // better safe than sorry...
6493 dup2(1, fileno(stderr)); /* force stderr to the pipe */
6495 if (dir[0] != NULLCHAR && chdir(dir) != 0) {
6500 nice(appData.niceEngines); // [HGM] nice: adjust priority of engine proc
6502 execvp(argv[0], argv);
6504 /* If we get here, exec failed */
6509 /* Parent process */
6511 close(from_prog[1]);
6513 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
6516 cp->fdFrom = from_prog[0];
6517 cp->fdTo = to_prog[1];
6522 // [HGM] kill: implement the 'hard killing' of AS's Winboard_x
6523 static RETSIGTYPE AlarmCallBack(int n)
6529 DestroyChildProcess(pr, signalType)
6533 ChildProc *cp = (ChildProc *) pr;
6535 if (cp->kind != CPReal) return;
6537 if (signalType == 10) { // [HGM] kill: if it does not terminate in 3 sec, kill
6538 signal(SIGALRM, AlarmCallBack);
6540 if(wait((int *) 0) == -1) { // process does not terminate on its own accord
6541 kill(cp->pid, SIGKILL); // kill it forcefully
6542 wait((int *) 0); // and wait again
6546 kill(cp->pid, signalType == 9 ? SIGKILL : SIGTERM); // [HGM] kill: use hard kill if so requested
6548 /* Process is exiting either because of the kill or because of
6549 a quit command sent by the backend; either way, wait for it to die.
6558 InterruptChildProcess(pr)
6561 ChildProc *cp = (ChildProc *) pr;
6563 if (cp->kind != CPReal) return;
6564 (void) kill(cp->pid, SIGINT); /* stop it thinking */
6567 int OpenTelnet(host, port, pr)
6572 char cmdLine[MSG_SIZ];
6574 if (port[0] == NULLCHAR) {
6575 snprintf(cmdLine, sizeof(cmdLine), "%s %s", appData.telnetProgram, host);
6577 snprintf(cmdLine, sizeof(cmdLine), "%s %s %s", appData.telnetProgram, host, port);
6579 return StartChildProcess(cmdLine, "", pr);
6582 int OpenTCP(host, port, pr)
6588 DisplayFatalError(_("Socket support is not configured in"), 0, 2);
6589 #else /* !OMIT_SOCKETS */
6591 struct sockaddr_in sa;
6593 unsigned short uport;
6596 if ((s = socket(AF_INET, SOCK_STREAM, 6)) < 0) {
6600 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
6601 sa.sin_family = AF_INET;
6602 sa.sin_addr.s_addr = INADDR_ANY;
6603 uport = (unsigned short) 0;
6604 sa.sin_port = htons(uport);
6605 if (bind(s, (struct sockaddr *) &sa, sizeof(struct sockaddr_in)) < 0) {
6609 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
6610 if (!(hp = gethostbyname(host))) {
6612 if (sscanf(host, "%d.%d.%d.%d", &b0, &b1, &b2, &b3) == 4) {
6613 hp = (struct hostent *) calloc(1, sizeof(struct hostent));
6614 hp->h_addrtype = AF_INET;
6616 hp->h_addr_list = (char **) calloc(2, sizeof(char *));
6617 hp->h_addr_list[0] = (char *) malloc(4);
6618 hp->h_addr_list[0][0] = b0;
6619 hp->h_addr_list[0][1] = b1;
6620 hp->h_addr_list[0][2] = b2;
6621 hp->h_addr_list[0][3] = b3;
6626 sa.sin_family = hp->h_addrtype;
6627 uport = (unsigned short) atoi(port);
6628 sa.sin_port = htons(uport);
6629 memcpy((char *) &sa.sin_addr, hp->h_addr, hp->h_length);
6631 if (connect(s, (struct sockaddr *) &sa,
6632 sizeof(struct sockaddr_in)) < 0) {
6636 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
6643 #endif /* !OMIT_SOCKETS */
6648 int OpenCommPort(name, pr)
6655 fd = open(name, 2, 0);
6656 if (fd < 0) return errno;
6658 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
6668 int OpenLoopback(pr)
6674 SetUpChildIO(to, from);
6676 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
6679 cp->fdFrom = to[0]; /* note not from[0]; we are doing a loopback */
6686 int OpenRcmd(host, user, cmd, pr)
6687 char *host, *user, *cmd;
6690 DisplayFatalError(_("internal rcmd not implemented for Unix"), 0, 1);
6694 #define INPUT_SOURCE_BUF_SIZE 8192
6703 char buf[INPUT_SOURCE_BUF_SIZE];
6708 DoInputCallback(io,cond,data)
6713 /* read input from one of the input source (for example a chess program, ICS, etc).
6714 * and call a function that will handle the input
6717 int count; /* how many bytes did we read */
6721 /* All information (callback function, file descriptor, etc) is
6722 * saved in an InputSource structure
6724 InputSource *is = (InputSource *) data;
6728 count = read(is->fd, is->unused,
6729 INPUT_SOURCE_BUF_SIZE - (is->unused - is->buf));
6733 (is->func)(is, is->closure, is->buf, count, count ? errno : 0);
6736 is->unused += count;
6738 /* break input into lines and call the callback function on each
6741 while (p < is->unused)
6743 q = memchr(p, '\n', is->unused - p);
6744 if (q == NULL) break;
6746 (is->func)(is, is->closure, p, q - p, 0);
6749 /* remember not yet used part of the buffer */
6751 while (p < is->unused)
6759 /* read maximum length of input buffer and send the whole buffer
6760 * to the callback function
6762 count = read(is->fd, is->buf, INPUT_SOURCE_BUF_SIZE);
6767 (is->func)(is, is->closure, is->buf, count, error);
6773 InputSourceRef AddInputSource(pr, lineByLine, func, closure)
6780 GIOChannel *channel;
6781 ChildProc *cp = (ChildProc *) pr;
6783 is = (InputSource *) calloc(1, sizeof(InputSource));
6784 is->lineByLine = lineByLine;
6788 is->fd = fileno(stdin);
6790 is->kind = cp->kind;
6791 is->fd = cp->fdFrom;
6794 is->unused = is->buf;
6798 // is->xid = XtAppAddInput(appContext, is->fd,
6799 // (XtPointer) (XtInputReadMask),
6800 // (XtInputCallbackProc) DoInputCallback,
6804 /* TODO: will this work on windows?*/
6805 printf("DEBUG: fd=%d %d\n",is->fd,is);
6807 channel = g_io_channel_unix_new(is->fd);
6808 g_io_channel_set_close_on_unref (channel, TRUE);
6809 is->sid = g_io_add_watch(channel, G_IO_IN,(GIOFunc) DoInputCallback, is);
6810 is->closure = closure;
6811 return (InputSourceRef) is;
6815 RemoveInputSource(isr)
6818 InputSource *is = (InputSource *) isr;
6820 if (is->sid == 0) return;
6821 g_source_remove(is->sid);
6826 int OutputToProcess(pr, message, count, outError)
6832 ChildProc *cp = (ChildProc *) pr;
6836 outCount = fwrite(message, 1, count, stdout);
6838 outCount = write(cp->fdTo, message, count);
6848 /* Output message to process, with "ms" milliseconds of delay
6849 between each character. This is needed when sending the logon
6850 script to ICC, which for some reason doesn't like the
6851 instantaneous send. */
6852 int OutputToProcessDelayed(pr, message, count, outError, msdelay)
6859 ChildProc *cp = (ChildProc *) pr;
6864 r = write(cp->fdTo, message++, 1);
6877 /**** Animation code by Hugh Fisher, DCS, ANU.
6879 Known problem: if a window overlapping the board is
6880 moved away while a piece is being animated underneath,
6881 the newly exposed area won't be updated properly.
6882 I can live with this.
6884 Known problem: if you look carefully at the animation
6885 of pieces in mono mode, they are being drawn as solid
6886 shapes without interior detail while moving. Fixing
6887 this would be a major complication for minimal return.
6890 /* Masks for XPM pieces. Black and white pieces can have
6891 different shapes, but in the interest of retaining my
6892 sanity pieces must have the same outline on both light
6893 and dark squares, and all pieces must use the same
6894 background square colors/images. */
6896 static int xpmDone = 0;
6899 CreateAnimMasks (pieceDepth)
6906 unsigned long plane;
6909 /* just return for gtk at the moment */
6912 /* Need a bitmap just to get a GC with right depth */
6913 buf = XCreatePixmap(xDisplay, xBoardWindow,
6915 values.foreground = 1;
6916 values.background = 0;
6917 /* Don't use XtGetGC, not read only */
6918 maskGC = XCreateGC(xDisplay, buf,
6919 GCForeground | GCBackground, &values);
6920 XFreePixmap(xDisplay, buf);
6922 buf = XCreatePixmap(xDisplay, xBoardWindow,
6923 squareSize, squareSize, pieceDepth);
6924 values.foreground = XBlackPixel(xDisplay, xScreen);
6925 values.background = XWhitePixel(xDisplay, xScreen);
6926 bufGC = XCreateGC(xDisplay, buf,
6927 GCForeground | GCBackground, &values);
6929 for (piece = WhitePawn; piece <= BlackKing; piece++) {
6930 /* Begin with empty mask */
6931 if(!xpmDone) // [HGM] pieces: keep using existing
6932 xpmMask[piece] = XCreatePixmap(xDisplay, xBoardWindow,
6933 squareSize, squareSize, 1);
6934 XSetFunction(xDisplay, maskGC, GXclear);
6935 XFillRectangle(xDisplay, xpmMask[piece], maskGC,
6936 0, 0, squareSize, squareSize);
6938 /* Take a copy of the piece */
6943 XSetFunction(xDisplay, bufGC, GXcopy);
6944 XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % (int)BlackPawn],
6946 0, 0, squareSize, squareSize, 0, 0);
6948 /* XOR the background (light) over the piece */
6949 XSetFunction(xDisplay, bufGC, GXxor);
6951 XCopyArea(xDisplay, xpmLightSquare, buf, bufGC,
6952 0, 0, squareSize, squareSize, 0, 0);
6954 XSetForeground(xDisplay, bufGC, lightSquareColor);
6955 XFillRectangle(xDisplay, buf, bufGC, 0, 0, squareSize, squareSize);
6958 /* We now have an inverted piece image with the background
6959 erased. Construct mask by just selecting all the non-zero
6960 pixels - no need to reconstruct the original image. */
6961 XSetFunction(xDisplay, maskGC, GXor);
6963 /* Might be quicker to download an XImage and create bitmap
6964 data from it rather than this N copies per piece, but it
6965 only takes a fraction of a second and there is a much
6966 longer delay for loading the pieces. */
6967 for (n = 0; n < pieceDepth; n ++) {
6968 XCopyPlane(xDisplay, buf, xpmMask[piece], maskGC,
6969 0, 0, squareSize, squareSize,
6975 XFreePixmap(xDisplay, buf);
6976 XFreeGC(xDisplay, bufGC);
6977 XFreeGC(xDisplay, maskGC);
6981 InitAnimState (anim, info)
6983 XWindowAttributes * info;
6988 /* Each buffer is square size, same depth as window */
6989 // anim->saveBuf = XCreatePixmap(xDisplay, xBoardWindow,
6990 // squareSize, squareSize, info->depth);
6991 // anim->newBuf = XCreatePixmap(xDisplay, xBoardWindow,
6992 // squareSize, squareSize, info->depth);
6994 // /* Create a plain GC for blitting */
6995 // mask = GCForeground | GCBackground | GCFunction |
6996 // GCPlaneMask | GCGraphicsExposures;
6997 // values.foreground = XBlackPixel(xDisplay, xScreen);
6998 // values.background = XWhitePixel(xDisplay, xScreen);
6999 // values.function = GXcopy;
7000 // values.plane_mask = AllPlanes;
7001 // values.graphics_exposures = False;
7002 // anim->blitGC = XCreateGC(xDisplay, xBoardWindow, mask, &values);
7004 // /* Piece will be copied from an existing context at
7005 // the start of each new animation/drag. */
7006 // anim->pieceGC = XCreateGC(xDisplay, xBoardWindow, 0, &values);
7008 // /* Outline will be a read-only copy of an existing */
7009 // anim->outlineGC = None;
7015 static VariantClass old = (VariantClass) -1; // [HGM] pieces: redo every time variant changes
7016 XWindowAttributes info;
7018 /* for gtk at the moment just ... */
7021 if (xpmDone && gameInfo.variant == old) return;
7022 if(xpmDone) old = gameInfo.variant; // first time pieces might not be created yet
7023 // XGetWindowAttributes(xDisplay, xBoardWindow, &info);
7025 // InitAnimState(&game, &info);
7026 // InitAnimState(&player, &info);
7028 /* For XPM pieces, we need bitmaps to use as masks. */
7030 // CreateAnimMasks(info.depth);
7036 static Boolean frameWaiting;
7038 static RETSIGTYPE FrameAlarm (sig)
7041 frameWaiting = False;
7042 /* In case System-V style signals. Needed?? */
7043 signal(SIGALRM, FrameAlarm);
7050 struct itimerval delay;
7052 XSync(xDisplay, False);
7055 frameWaiting = True;
7056 signal(SIGALRM, FrameAlarm);
7057 delay.it_interval.tv_sec =
7058 delay.it_value.tv_sec = time / 1000;
7059 delay.it_interval.tv_usec =
7060 delay.it_value.tv_usec = (time % 1000) * 1000;
7061 setitimer(ITIMER_REAL, &delay, NULL);
7062 while (frameWaiting) pause();
7063 delay.it_interval.tv_sec = delay.it_value.tv_sec = 0;
7064 delay.it_interval.tv_usec = delay.it_value.tv_usec = 0;
7065 setitimer(ITIMER_REAL, &delay, NULL);
7075 // XSync(xDisplay, False);
7077 usleep(time * 1000);
7082 /* Convert board position to corner of screen rect and color */
7085 ScreenSquare(column, row, pt, color)
7086 int column; int row; XPoint * pt; int * color;
7089 pt->x = lineGap + ((BOARD_WIDTH-1)-column) * (squareSize + lineGap);
7090 pt->y = lineGap + row * (squareSize + lineGap);
7092 pt->x = lineGap + column * (squareSize + lineGap);
7093 pt->y = lineGap + ((BOARD_HEIGHT-1)-row) * (squareSize + lineGap);
7095 *color = SquareColor(row, column);
7098 /* Convert window coords to square */
7101 BoardSquare(x, y, column, row)
7102 int x; int y; int * column; int * row;
7104 *column = EventToSquare(x, BOARD_WIDTH);
7105 if (flipView && *column >= 0)
7106 *column = BOARD_WIDTH - 1 - *column;
7107 *row = EventToSquare(y, BOARD_HEIGHT);
7108 if (!flipView && *row >= 0)
7109 *row = BOARD_HEIGHT - 1 - *row;
7114 #undef Max /* just in case */
7116 #define Max(a, b) ((a) > (b) ? (a) : (b))
7117 #define Min(a, b) ((a) < (b) ? (a) : (b))
7120 SetRect(rect, x, y, width, height)
7121 XRectangle * rect; int x; int y; int width; int height;
7125 rect->width = width;
7126 rect->height = height;
7129 /* Test if two frames overlap. If they do, return
7130 intersection rect within old and location of
7131 that rect within new. */
7134 Intersect(old, new, size, area, pt)
7135 XPoint * old; XPoint * new;
7136 int size; XRectangle * area; XPoint * pt;
7138 if (old->x > new->x + size || new->x > old->x + size ||
7139 old->y > new->y + size || new->y > old->y + size) {
7142 SetRect(area, Max(new->x - old->x, 0), Max(new->y - old->y, 0),
7143 size - abs(old->x - new->x), size - abs(old->y - new->y));
7144 pt->x = Max(old->x - new->x, 0);
7145 pt->y = Max(old->y - new->y, 0);
7150 /* For two overlapping frames, return the rect(s)
7151 in the old that do not intersect with the new. */
7154 CalcUpdateRects(old, new, size, update, nUpdates)
7155 XPoint * old; XPoint * new; int size;
7156 XRectangle update[]; int * nUpdates;
7160 /* If old = new (shouldn't happen) then nothing to draw */
7161 if (old->x == new->x && old->y == new->y) {
7165 /* Work out what bits overlap. Since we know the rects
7166 are the same size we don't need a full intersect calc. */
7168 /* Top or bottom edge? */
7169 if (new->y > old->y) {
7170 SetRect(&(update[count]), old->x, old->y, size, new->y - old->y);
7172 } else if (old->y > new->y) {
7173 SetRect(&(update[count]), old->x, old->y + size - (old->y - new->y),
7174 size, old->y - new->y);
7177 /* Left or right edge - don't overlap any update calculated above. */
7178 if (new->x > old->x) {
7179 SetRect(&(update[count]), old->x, Max(new->y, old->y),
7180 new->x - old->x, size - abs(new->y - old->y));
7182 } else if (old->x > new->x) {
7183 SetRect(&(update[count]), new->x + size, Max(new->y, old->y),
7184 old->x - new->x, size - abs(new->y - old->y));
7191 /* Generate a series of frame coords from start->mid->finish.
7192 The movement rate doubles until the half way point is
7193 reached, then halves back down to the final destination,
7194 which gives a nice slow in/out effect. The algorithmn
7195 may seem to generate too many intermediates for short
7196 moves, but remember that the purpose is to attract the
7197 viewers attention to the piece about to be moved and
7198 then to where it ends up. Too few frames would be less
7202 Tween(start, mid, finish, factor, frames, nFrames)
7203 XPoint * start; XPoint * mid;
7204 XPoint * finish; int factor;
7205 XPoint frames[]; int * nFrames;
7207 int fraction, n, count;
7211 /* Slow in, stepping 1/16th, then 1/8th, ... */
7213 for (n = 0; n < factor; n++)
7215 for (n = 0; n < factor; n++) {
7216 frames[count].x = start->x + (mid->x - start->x) / fraction;
7217 frames[count].y = start->y + (mid->y - start->y) / fraction;
7219 fraction = fraction / 2;
7223 frames[count] = *mid;
7226 /* Slow out, stepping 1/2, then 1/4, ... */
7228 for (n = 0; n < factor; n++) {
7229 frames[count].x = finish->x - (finish->x - mid->x) / fraction;
7230 frames[count].y = finish->y - (finish->y - mid->y) / fraction;
7232 fraction = fraction * 2;
7237 /* Draw a piece on the screen without disturbing what's there */
7240 SelectGCMask(piece, clip, outline, mask)
7241 ChessSquare piece; GC * clip; GC * outline; Pixmap * mask;
7245 /* Bitmap for piece being moved. */
7246 if (appData.monoMode) {
7247 *mask = *pieceToSolid(piece);
7248 } else if (useImages) {
7250 *mask = xpmMask[piece];
7252 *mask = ximMaskPm[piece];
7255 *mask = *pieceToSolid(piece);
7258 /* GC for piece being moved. Square color doesn't matter, but
7259 since it gets modified we make a copy of the original. */
7261 if (appData.monoMode)
7266 if (appData.monoMode)
7271 // XCopyGC(xDisplay, source, 0xFFFFFFFF, *clip);
7273 /* Outline only used in mono mode and is not modified */
7275 *outline = bwPieceGC;
7277 *outline = wbPieceGC;
7281 OverlayPiece(piece, clip, outline, dest)
7282 ChessSquare piece; GC clip; GC outline; Drawable dest;
7287 /* Draw solid rectangle which will be clipped to shape of piece */
7288 // XFillRectangle(xDisplay, dest, clip,
7289 // 0, 0, squareSize, squareSize)
7291 if (appData.monoMode)
7292 /* Also draw outline in contrasting color for black
7293 on black / white on white cases */
7294 // XCopyPlane(xDisplay, *pieceToOutline(piece), dest, outline,
7295 // 0, 0, squareSize, squareSize, 0, 0, 1)
7298 /* Copy the piece */
7303 // XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
7305 // 0, 0, squareSize, squareSize,
7310 /* Animate the movement of a single piece */
7313 BeginAnimation(anim, piece, startColor, start)
7321 /* The old buffer is initialised with the start square (empty) */
7322 BlankSquare(0, 0, startColor, EmptySquare, anim->saveBuf);
7323 anim->prevFrame = *start;
7325 /* The piece will be drawn using its own bitmap as a matte */
7326 // SelectGCMask(piece, &anim->pieceGC, &anim->outlineGC, &mask);
7327 // XSetClipMask(xDisplay, anim->pieceGC, mask);
7331 AnimationFrame(anim, frame, piece)
7336 XRectangle updates[4];
7341 /* Save what we are about to draw into the new buffer */
7342 // XCopyArea(xDisplay, xBoardWindow, anim->newBuf, anim->blitGC,
7343 // frame->x, frame->y, squareSize, squareSize,
7346 /* Erase bits of the previous frame */
7347 if (Intersect(&anim->prevFrame, frame, squareSize, &overlap, &pt)) {
7348 /* Where the new frame overlapped the previous,
7349 the contents in newBuf are wrong. */
7350 // XCopyArea(xDisplay, anim->saveBuf, anim->newBuf, anim->blitGC,
7351 // overlap.x, overlap.y,
7352 // overlap.width, overlap.height,
7354 /* Repaint the areas in the old that don't overlap new */
7355 CalcUpdateRects(&anim->prevFrame, frame, squareSize, updates, &count);
7356 for (i = 0; i < count; i++)
7357 // XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
7358 // updates[i].x - anim->prevFrame.x,
7359 // updates[i].y - anim->prevFrame.y,
7360 // updates[i].width, updates[i].height,
7361 // updates[i].x, updates[i].y)
7364 /* Easy when no overlap */
7365 // XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
7366 // 0, 0, squareSize, squareSize,
7367 // anim->prevFrame.x, anim->prevFrame.y);
7370 /* Save this frame for next time round */
7371 // XCopyArea(xDisplay, anim->newBuf, anim->saveBuf, anim->blitGC,
7372 // 0, 0, squareSize, squareSize,
7374 anim->prevFrame = *frame;
7376 /* Draw piece over original screen contents, not current,
7377 and copy entire rect. Wipes out overlapping piece images. */
7378 OverlayPiece(piece, anim->pieceGC, anim->outlineGC, anim->newBuf);
7379 // XCopyArea(xDisplay, anim->newBuf, xBoardWindow, anim->blitGC,
7380 // 0, 0, squareSize, squareSize,
7381 // frame->x, frame->y);
7385 EndAnimation (anim, finish)
7389 XRectangle updates[4];
7394 /* The main code will redraw the final square, so we
7395 only need to erase the bits that don't overlap. */
7396 if (Intersect(&anim->prevFrame, finish, squareSize, &overlap, &pt)) {
7397 CalcUpdateRects(&anim->prevFrame, finish, squareSize, updates, &count);
7398 for (i = 0; i < count; i++)
7399 // XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
7400 // updates[i].x - anim->prevFrame.x,
7401 // updates[i].y - anim->prevFrame.y,
7402 // updates[i].width, updates[i].height,
7403 // updates[i].x, updates[i].y)
7406 // XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
7407 // 0, 0, squareSize, squareSize,
7408 // anim->prevFrame.x, anim->prevFrame.y);
7413 FrameSequence(anim, piece, startColor, start, finish, frames, nFrames)
7415 ChessSquare piece; int startColor;
7416 XPoint * start; XPoint * finish;
7417 XPoint frames[]; int nFrames;
7421 BeginAnimation(anim, piece, startColor, start);
7422 for (n = 0; n < nFrames; n++) {
7423 AnimationFrame(anim, &(frames[n]), piece);
7424 FrameDelay(appData.animSpeed);
7426 EndAnimation(anim, finish);
7429 /* Main control logic for deciding what to animate and how */
7432 AnimateMove(board, fromX, fromY, toX, toY)
7441 XPoint start, finish, mid;
7442 XPoint frames[kFactor * 2 + 1];
7443 int nFrames, startColor, endColor;
7445 /* Are we animating? */
7446 if (!appData.animate || appData.blindfold)
7449 if(board[toY][toX] == WhiteRook && board[fromY][fromX] == WhiteKing ||
7450 board[toY][toX] == BlackRook && board[fromY][fromX] == BlackKing)
7451 return; // [HGM] FRC: no animtion of FRC castlings, as to-square is not true to-square
7453 if (fromY < 0 || fromX < 0 || toX < 0 || toY < 0) return;
7454 piece = board[fromY][fromX];
7455 if (piece >= EmptySquare) return;
7460 hop = (piece == WhiteKnight || piece == BlackKnight);
7463 if (appData.debugMode) {
7464 fprintf(debugFP, hop ? _("AnimateMove: piece %d hops from %d,%d to %d,%d \n") :
7465 _("AnimateMove: piece %d slides from %d,%d to %d,%d \n"),
7466 piece, fromX, fromY, toX, toY); }
7468 ScreenSquare(fromX, fromY, &start, &startColor);
7469 ScreenSquare(toX, toY, &finish, &endColor);
7472 /* Knight: make diagonal movement then straight */
7473 if (abs(toY - fromY) < abs(toX - fromX)) {
7474 mid.x = start.x + (finish.x - start.x) / 2;
7478 mid.y = start.y + (finish.y - start.y) / 2;
7481 mid.x = start.x + (finish.x - start.x) / 2;
7482 mid.y = start.y + (finish.y - start.y) / 2;
7485 /* Don't use as many frames for very short moves */
7486 if (abs(toY - fromY) + abs(toX - fromX) <= 2)
7487 Tween(&start, &mid, &finish, kFactor - 1, frames, &nFrames);
7489 Tween(&start, &mid, &finish, kFactor, frames, &nFrames);
7490 FrameSequence(&game, piece, startColor, &start, &finish, frames, nFrames);
7492 /* Be sure end square is redrawn */
7493 damage[toY][toX] = True;
7497 DragPieceBegin(x, y)
7500 int boardX, boardY, color;
7503 /* Are we animating? */
7504 if (!appData.animateDragging || appData.blindfold)
7507 /* Figure out which square we start in and the
7508 mouse position relative to top left corner. */
7509 BoardSquare(x, y, &boardX, &boardY);
7510 player.startBoardX = boardX;
7511 player.startBoardY = boardY;
7512 ScreenSquare(boardX, boardY, &corner, &color);
7513 player.startSquare = corner;
7514 player.startColor = color;
7515 /* As soon as we start dragging, the piece will jump slightly to
7516 be centered over the mouse pointer. */
7517 player.mouseDelta.x = squareSize/2;
7518 player.mouseDelta.y = squareSize/2;
7519 /* Initialise animation */
7520 player.dragPiece = PieceForSquare(boardX, boardY);
7522 if (player.dragPiece >= 0 && player.dragPiece < EmptySquare) {
7523 player.dragActive = True;
7524 BeginAnimation(&player, player.dragPiece, color, &corner);
7525 /* Mark this square as needing to be redrawn. Note that
7526 we don't remove the piece though, since logically (ie
7527 as seen by opponent) the move hasn't been made yet. */
7528 if(boardX == BOARD_RGHT+1 && PieceForSquare(boardX-1, boardY) > 1 ||
7529 boardX == BOARD_LEFT-2 && PieceForSquare(boardX+1, boardY) > 1)
7530 // XCopyArea(xDisplay, xBoardWindow, player.saveBuf, player.blitGC,
7531 // corner.x, corner.y, squareSize, squareSize,
7532 // 0, 0); // [HGM] zh: unstack in stead of grab
7533 damage[boardY][boardX] = True;
7535 player.dragActive = False;
7545 /* Are we animating? */
7546 if (!appData.animateDragging || appData.blindfold)
7550 if (! player.dragActive)
7552 /* Move piece, maintaining same relative position
7553 of mouse within square */
7554 corner.x = x - player.mouseDelta.x;
7555 corner.y = y - player.mouseDelta.y;
7556 AnimationFrame(&player, &corner, player.dragPiece);
7558 if (appData.highlightDragging) {
7560 BoardSquare(x, y, &boardX, &boardY);
7561 SetHighlights(fromX, fromY, boardX, boardY);
7570 int boardX, boardY, color;
7573 /* Are we animating? */
7574 if (!appData.animateDragging || appData.blindfold)
7578 if (! player.dragActive)
7580 /* Last frame in sequence is square piece is
7581 placed on, which may not match mouse exactly. */
7582 BoardSquare(x, y, &boardX, &boardY);
7583 ScreenSquare(boardX, boardY, &corner, &color);
7584 EndAnimation(&player, &corner);
7586 /* Be sure end square is redrawn */
7587 damage[boardY][boardX] = True;
7589 /* This prevents weird things happening with fast successive
7590 clicks which on my Sun at least can cause motion events
7591 without corresponding press/release. */
7592 player.dragActive = False;
7595 /* Handle expose event while piece being dragged */
7600 if (!player.dragActive || appData.blindfold)
7603 /* What we're doing: logically, the move hasn't been made yet,
7604 so the piece is still in it's original square. But visually
7605 it's being dragged around the board. So we erase the square
7606 that the piece is on and draw it at the last known drag point. */
7607 BlankSquare(player.startSquare.x, player.startSquare.y,
7608 player.startColor, EmptySquare, xBoardWindow);
7609 AnimationFrame(&player, &player.prevFrame, player.dragPiece);
7610 damage[player.startBoardY][player.startBoardX] = TRUE;
7614 SetProgramStats( FrontEndProgramStats * stats )
7617 // [HGM] done, but perhaps backend should call this directly?
7618 EngineOutputUpdate( stats );
7621 #include <sys/ioctl.h>
7622 int get_term_width()
7624 int fd, default_width;
7627 default_width = 79; // this is FICS default anyway...
7629 #if !defined(TIOCGWINSZ) && defined(TIOCGSIZE)
7631 if (!ioctl(fd, TIOCGSIZE, &win))
7632 default_width = win.ts_cols;
7633 #elif defined(TIOCGWINSZ)
7635 if (!ioctl(fd, TIOCGWINSZ, &win))
7636 default_width = win.ws_col;
7638 return default_width;
7641 void update_ics_width()
7643 static int old_width = 0;
7644 int new_width = get_term_width();
7646 if (old_width != new_width)
7647 ics_printf("set width %d\n", new_width);
7648 old_width = new_width;
7651 void NotifyFrontendLogin()