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 FileNamePopUp P((char *label, char *def,
273 FileProc proc, char *openMode));
274 void FileNamePopDown P((void));
275 void FileNameCallback P((Widget w, XtPointer client_data,
276 XtPointer call_data));
277 void FileNameAction P((Widget w, XEvent *event,
278 String *prms, Cardinal *nprms));
279 void AskQuestionReplyAction P((Widget w, XEvent *event,
280 String *prms, Cardinal *nprms));
281 void AskQuestionProc P((Widget w, XEvent *event,
282 String *prms, Cardinal *nprms));
283 void AskQuestionPopDown P((void));
284 void PromotionPopUp P((void));
285 void PromotionPopDown P((void));
286 void PromotionCallback P((Widget w, XtPointer client_data,
287 XtPointer call_data));
288 void EditCommentPopDown P((void));
289 void EditCommentCallback P((Widget w, XtPointer client_data,
290 XtPointer call_data));
291 void SelectCommand P((Widget w, XtPointer client_data, XtPointer call_data));
292 void LoadPositionProc P((Widget w, XEvent *event,
293 String *prms, Cardinal *nprms));
294 void CopyPositionProc P((Widget w, XEvent *event, String *prms,
296 void PastePositionProc P((Widget w, XEvent *event, String *prms,
298 void CopyGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
299 void PasteGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
300 void SaveGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
301 void SavePositionProc P((Widget w, XEvent *event,
302 String *prms, Cardinal *nprms));
303 void MailMoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
304 void ReloadCmailMsgProc P((Widget w, XEvent *event, String *prms,
306 void AnalyzeModeProc P((Widget w, XEvent *event,
307 String *prms, Cardinal *nprms));
308 void AnalyzeFileProc P((Widget w, XEvent *event,
309 String *prms, Cardinal *nprms));
310 void EditGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
311 void EditPositionProc P((Widget w, XEvent *event,
312 String *prms, Cardinal *nprms));
313 void TrainingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
314 void EditCommentProc P((Widget w, XEvent *event,
315 String *prms, Cardinal *nprms));
316 void IcsInputBoxProc P((Widget w, XEvent *event,
317 String *prms, Cardinal *nprms));
318 void EnterKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
319 void AlwaysQueenProc P((Widget w, XEvent *event, String *prms,
321 void AnimateDraggingProc P((Widget w, XEvent *event, String *prms,
323 void AnimateMovingProc P((Widget w, XEvent *event, String *prms,
325 void AutobsProc P((Widget w, XEvent *event, String *prms,
327 void AutoraiseProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
328 void AutosaveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
329 void BlindfoldProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
330 void FlashMovesProc P((Widget w, XEvent *event, String *prms,
332 void HighlightDraggingProc P((Widget w, XEvent *event, String *prms,
334 void HighlightLastMoveProc P((Widget w, XEvent *event, String *prms,
336 void MoveSoundProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
337 void IcsAlarmProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
338 void OldSaveStyleProc P((Widget w, XEvent *event, String *prms,
340 void PeriodicUpdatesProc P((Widget w, XEvent *event, String *prms,
342 void PonderNextMoveProc P((Widget w, XEvent *event, String *prms,
344 void PopupMoveErrorsProc P((Widget w, XEvent *event, String *prms,
346 void PopupExitMessageProc P((Widget w, XEvent *event, String *prms,
348 void PremoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
349 void QuietPlayProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
350 void TestLegalityProc P((Widget w, XEvent *event, String *prms,
352 void AboutGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
353 void DebugProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
354 void NothingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
355 void Iconify P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
356 void DisplayMove P((int moveNumber));
357 void DisplayTitle P((char *title));
358 void ICSInitScript P((void));
359 int LoadGamePopUp P((FILE *f, int gameNumber, char *title));
360 void ErrorPopUp P((char *title, char *text, int modal));
361 void ErrorPopDown P((void));
362 static char *ExpandPathName P((char *path));
363 static void CreateAnimVars P((void));
364 void DragPieceBegin P((int x, int y));
365 static void DragPieceMove P((int x, int y));
366 void DragPieceEnd P((int x, int y));
367 static void DrawDragPiece P((void));
368 char *ModeToWidgetName P((GameMode mode));
369 void EngineOutputUpdate( FrontEndProgramStats * stats );
370 void ShuffleMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
371 void EngineMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
372 void UciMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
373 void TimeControlProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
374 void NewVariantProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
375 void FirstSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
376 void SecondSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
377 void ShufflePopDown P(());
378 void EnginePopDown P(());
379 void UciPopDown P(());
380 void TimeControlPopDown P(());
381 void NewVariantPopDown P(());
382 void SettingsPopDown P(());
383 void SetMenuEnables P((Enables *enab));
384 void update_ics_width P(());
385 int get_term_width P(());
387 * XBoard depends on Xt R4 or higher
389 int xtVersion = XtSpecificationRelease;
394 Pixel lightSquareColor, darkSquareColor, whitePieceColor, blackPieceColor,
395 jailSquareColor, highlightSquareColor, premoveHighlightColor;
396 Pixel lowTimeWarningColor;
398 #define LINE_TYPE_NORMAL 0
399 #define LINE_TYPE_HIGHLIGHT 1
400 #define LINE_TYPE_PRE 2
403 GC lightSquareGC, darkSquareGC, jailSquareGC, wdPieceGC, wlPieceGC,
404 bdPieceGC, blPieceGC, wbPieceGC, bwPieceGC, coordGC,
405 wjPieceGC, bjPieceGC;
406 Pixmap iconPixmap, wIconPixmap, bIconPixmap, xMarkPixmap;
407 Widget shellWidget, layoutWidget, formWidget, boardWidget, messageWidget,
408 whiteTimerWidget, blackTimerWidget, titleWidget, widgetList[16],
409 commentShell, promotionShell, whitePieceMenu, blackPieceMenu, dropMenu,
410 menuBarWidget, editShell, errorShell, analysisShell,
411 ICSInputShell, fileNameShell, askQuestionShell;
412 Font clockFontID, coordFontID, countFontID;
413 XFontStruct *clockFontStruct, *coordFontStruct, *countFontStruct;
414 XtAppContext appContext;
416 char *oldICSInteractionTitle;
420 char installDir[] = "."; // [HGM] UCI: needed for UCI; probably needs run-time initializtion
422 Position commentX = -1, commentY = -1;
423 Dimension commentW, commentH;
425 int squareSize, smallLayout = 0, tinyLayout = 0,
426 marginW, marginH, // [HGM] for run-time resizing
427 fromX = -1, fromY = -1, toX, toY, commentUp = False, analysisUp = False,
428 ICSInputBoxUp = False, askQuestionUp = False,
429 filenameUp = False, promotionUp = False, pmFromX = -1, pmFromY = -1,
430 editUp = False, errorUp = False, errorExitStatus = -1, lineGap;
431 Pixel timerForegroundPixel, timerBackgroundPixel;
432 Pixel buttonForegroundPixel, buttonBackgroundPixel;
433 char *chessDir, *programName, *programVersion,
434 *gameCopyFilename, *gamePasteFilename;
438 Pixmap pieceBitmap[2][(int)BlackPawn];
439 Pixmap pieceBitmap2[2][(int)BlackPawn+4]; /* [HGM] pieces */
440 Pixmap xpmPieceBitmap[4][(int)BlackPawn]; /* LL, LD, DL, DD actually used*/
441 Pixmap xpmPieceBitmap2[4][(int)BlackPawn+4]; /* LL, LD, DL, DD set to select from */
442 Pixmap xpmLightSquare, xpmDarkSquare, xpmJailSquare;
443 int useImages=0, useImageSqs;
444 XImage *ximPieceBitmap[4][(int)BlackPawn+4]; /* LL, LD, DL, DD */
445 Pixmap ximMaskPm[(int)BlackPawn]; /* clipmasks, used for XIM pieces */
446 Pixmap ximMaskPm2[(int)BlackPawn+4]; /* clipmasks, used for XIM pieces */
447 XImage *ximLightSquare, *ximDarkSquare;
450 #define pieceToSolid(piece) &pieceBitmap[SOLID][(piece) % (int)BlackPawn]
451 #define pieceToOutline(piece) &pieceBitmap[OUTLINE][(piece) % (int)BlackPawn]
453 #define White(piece) ((int)(piece) < (int)BlackPawn)
455 /* Variables for doing smooth animation. This whole thing
456 would be much easier if the board was double-buffered,
457 but that would require a fairly major rewrite. */
462 GC blitGC, pieceGC, outlineGC;
463 XPoint startSquare, prevFrame, mouseDelta;
467 int startBoardX, startBoardY;
470 /* There can be two pieces being animated at once: a player
471 can begin dragging a piece before the remote opponent has moved. */
473 static AnimState game, player;
475 /* Bitmaps for use as masks when drawing XPM pieces.
476 Need one for each black and white piece. */
477 static Pixmap xpmMask[BlackKing + 1];
479 /* This magic number is the number of intermediate frames used
480 in each half of the animation. For short moves it's reduced
481 by 1. The total number of frames will be factor * 2 + 1. */
484 SizeDefaults sizeDefaults[] = SIZE_DEFAULTS;
486 Enables icsEnables[] = {
487 { "menuFile.Mail Move", False },
488 { "menuFile.Reload CMail Message", False },
489 { "menuMode.Machine Black", False },
490 { "menuMode.Machine White", False },
491 { "menuMode.Analysis Mode", False },
492 { "menuMode.Analyze File", False },
493 { "menuMode.Two Machines", False },
495 { "menuHelp.Hint", False },
496 { "menuHelp.Book", False },
497 { "menuStep.Move Now", False },
498 { "menuOptions.Periodic Updates", False },
499 { "menuOptions.Hide Thinking", False },
500 { "menuOptions.Ponder Next Move", False },
505 Enables ncpEnables[] = {
506 { "menuFile.Mail Move", False },
507 { "menuFile.Reload CMail Message", False },
508 { "menuMode.Machine White", False },
509 { "menuMode.Machine Black", False },
510 { "menuMode.Analysis Mode", False },
511 { "menuMode.Analyze File", False },
512 { "menuMode.Two Machines", False },
513 { "menuMode.ICS Client", False },
514 { "menuMode.ICS Input Box", False },
516 { "menuStep.Revert", False },
517 { "menuStep.Move Now", False },
518 { "menuStep.Retract Move", False },
519 { "menuOptions.Auto Comment", False },
520 { "menuOptions.Auto Flag", False },
521 { "menuOptions.Auto Flip View", False },
522 { "menuOptions.Auto Observe", False },
523 { "menuOptions.Auto Raise Board", False },
524 { "menuOptions.Get Move List", False },
525 { "menuOptions.ICS Alarm", False },
526 { "menuOptions.Move Sound", False },
527 { "menuOptions.Quiet Play", False },
528 { "menuOptions.Hide Thinking", False },
529 { "menuOptions.Periodic Updates", False },
530 { "menuOptions.Ponder Next Move", False },
531 { "menuHelp.Hint", False },
532 { "menuHelp.Book", False },
536 Enables gnuEnables[] = {
537 { "menuMode.ICS Client", False },
538 { "menuMode.ICS Input Box", False },
539 { "menuAction.Accept", False },
540 { "menuAction.Decline", False },
541 { "menuAction.Rematch", False },
542 { "menuAction.Adjourn", False },
543 { "menuAction.Stop Examining", False },
544 { "menuAction.Stop Observing", False },
545 { "menuStep.Revert", False },
546 { "menuOptions.Auto Comment", False },
547 { "menuOptions.Auto Observe", False },
548 { "menuOptions.Auto Raise Board", False },
549 { "menuOptions.Get Move List", False },
550 { "menuOptions.Premove", False },
551 { "menuOptions.Quiet Play", False },
553 /* The next two options rely on SetCmailMode being called *after* */
554 /* SetGNUMode so that when GNU is being used to give hints these */
555 /* menu options are still available */
557 { "menuFile.Mail Move", False },
558 { "menuFile.Reload CMail Message", False },
562 Enables cmailEnables[] = {
564 { "menuAction.Call Flag", False },
565 { "menuAction.Draw", True },
566 { "menuAction.Adjourn", False },
567 { "menuAction.Abort", False },
568 { "menuAction.Stop Observing", False },
569 { "menuAction.Stop Examining", False },
570 { "menuFile.Mail Move", True },
571 { "menuFile.Reload CMail Message", True },
575 Enables trainingOnEnables[] = {
576 { "menuMode.Edit Comment", False },
577 { "menuMode.Pause", False },
578 { "menuStep.Forward", False },
579 { "menuStep.Backward", False },
580 { "menuStep.Forward to End", False },
581 { "menuStep.Back to Start", False },
582 { "menuStep.Move Now", False },
583 { "menuStep.Truncate Game", False },
587 Enables trainingOffEnables[] = {
588 { "menuMode.Edit Comment", True },
589 { "menuMode.Pause", True },
590 { "menuStep.Forward", True },
591 { "menuStep.Backward", True },
592 { "menuStep.Forward to End", True },
593 { "menuStep.Back to Start", True },
594 { "menuStep.Move Now", True },
595 { "menuStep.Truncate Game", True },
599 Enables machineThinkingEnables[] = {
600 { "menuFile.Load Game", False },
601 { "menuFile.Load Next Game", False },
602 { "menuFile.Load Previous Game", False },
603 { "menuFile.Reload Same Game", False },
604 { "menuFile.Paste Game", False },
605 { "menuFile.Load Position", False },
606 { "menuFile.Load Next Position", False },
607 { "menuFile.Load Previous Position", False },
608 { "menuFile.Reload Same Position", False },
609 { "menuFile.Paste Position", False },
610 { "menuMode.Machine White", False },
611 { "menuMode.Machine Black", False },
612 { "menuMode.Two Machines", False },
613 { "menuStep.Retract Move", False },
617 Enables userThinkingEnables[] = {
618 { "menuFile.Load Game", True },
619 { "menuFile.Load Next Game", True },
620 { "menuFile.Load Previous Game", True },
621 { "menuFile.Reload Same Game", True },
622 { "menuFile.Paste Game", True },
623 { "menuFile.Load Position", True },
624 { "menuFile.Load Next Position", True },
625 { "menuFile.Load Previous Position", True },
626 { "menuFile.Reload Same Position", True },
627 { "menuFile.Paste Position", True },
628 { "menuMode.Machine White", True },
629 { "menuMode.Machine Black", True },
630 { "menuMode.Two Machines", True },
631 { "menuStep.Retract Move", True },
637 MenuItem fileMenu[] = {
638 {N_("New Shuffle Game ..."), ShuffleMenuProc},
639 {N_("New Variant ..."), NewVariantProc}, // [HGM] variant: not functional yet
640 {"----", NothingProc},
641 {N_("Save Game"), SaveGameProc},
642 {"----", NothingProc},
643 {N_("Copy Game"), CopyGameProc},
644 {N_("Paste Game"), PasteGameProc},
645 {"----", NothingProc},
646 {N_("Load Position"), LoadPositionProc},
647 // {N_("Load Next Position"), LoadNextPositionProc},
648 // {N_("Load Previous Position"), LoadPrevPositionProc},
649 // {N_("Reload Same Position"), ReloadPositionProc},
650 {N_("Save Position"), SavePositionProc},
651 {"----", NothingProc},
652 {N_("Copy Position"), CopyPositionProc},
653 {N_("Paste Position"), PastePositionProc},
654 {"----", NothingProc},
655 {N_("Mail Move"), MailMoveProc},
656 {N_("Reload CMail Message"), ReloadCmailMsgProc},
657 {"----", NothingProc},
661 MenuItem modeMenu[] = {
662 // {N_("Machine White"), MachineWhiteProc},
663 // {N_("Machine Black"), MachineBlackProc},
664 // {N_("Two Machines"), TwoMachinesProc},
665 {N_("Analysis Mode"), AnalyzeModeProc},
666 {N_("Analyze File"), AnalyzeFileProc },
667 // {N_("ICS Client"), IcsClientProc},
668 {N_("Edit Game"), EditGameProc},
669 {N_("Edit Position"), EditPositionProc},
670 {N_("Training"), TrainingProc},
671 {"----", NothingProc},
672 {N_("Show Engine Output"), EngineOutputProc},
673 {N_("Show Evaluation Graph"), NothingProc}, // [HGM] evalgr: not functional yet
674 {N_("Show Game List"), ShowGameListProc},
675 // {"Show Move History", HistoryShowProc}, // [HGM] hist: activate 4.2.7 code
676 {"----", NothingProc},
677 {N_("Edit Tags"), EditTagsProc},
678 {N_("Edit Comment"), EditCommentProc},
679 {N_("ICS Input Box"), IcsInputBoxProc},
683 MenuItem optionsMenu[] = {
684 // {N_("Flip View"), FlipViewProc},
685 // {"----", NothingProc},
686 {N_("Adjudications ..."), EngineMenuProc},
687 {N_("General Settings ..."), UciMenuProc},
688 {N_("Engine #1 Settings ..."), FirstSettingsProc},
689 {N_("Engine #2 Settings ..."), SecondSettingsProc},
690 {N_("Time Control ..."), TimeControlProc},
691 {"----", NothingProc},
692 {N_("Always Queen"), AlwaysQueenProc},
693 {N_("Animate Dragging"), AnimateDraggingProc},
694 {N_("Animate Moving"), AnimateMovingProc},
695 // {N_("Auto Comment"), AutocommProc},
696 // {N_("Auto Flag"), AutoflagProc},
697 // {N_("Auto Flip View"), AutoflipProc},
698 {N_("Auto Observe"), AutobsProc},
699 {N_("Auto Raise Board"), AutoraiseProc},
700 {N_("Auto Save"), AutosaveProc},
701 {N_("Blindfold"), BlindfoldProc},
702 {N_("Flash Moves"), FlashMovesProc},
703 // {N_("Get Move List"), GetMoveListProc},
705 {N_("Highlight Dragging"), HighlightDraggingProc},
707 {N_("Highlight Last Move"), HighlightLastMoveProc},
708 {N_("Move Sound"), MoveSoundProc},
709 {N_("ICS Alarm"), IcsAlarmProc},
710 {N_("Old Save Style"), OldSaveStyleProc},
711 {N_("Periodic Updates"), PeriodicUpdatesProc},
712 {N_("Ponder Next Move"), PonderNextMoveProc},
713 {N_("Popup Exit Message"), PopupExitMessageProc},
714 {N_("Popup Move Errors"), PopupMoveErrorsProc},
715 {N_("Premove"), PremoveProc},
716 {N_("Quiet Play"), QuietPlayProc},
717 // {N_("Hide Thinking"), HideThinkingProc},
718 {N_("Test Legality"), TestLegalityProc},
723 {N_("File"), fileMenu},
724 {N_("Mode"), modeMenu},
725 {N_("Options"), optionsMenu},
729 #define PIECE_MENU_SIZE 18
730 String pieceMenuStrings[2][PIECE_MENU_SIZE] = {
731 { N_("White"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
732 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
733 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
734 N_("Empty square"), N_("Clear board") },
735 { N_("Black"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
736 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
737 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
738 N_("Empty square"), N_("Clear board") }
740 /* must be in same order as PieceMenuStrings! */
741 ChessSquare pieceMenuTranslation[2][PIECE_MENU_SIZE] = {
742 { WhitePlay, (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
743 WhiteRook, WhiteQueen, WhiteKing, (ChessSquare) 0, WhiteAlfil,
744 WhiteCannon, WhiteAngel, WhiteMarshall, (ChessSquare) 0,
745 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
746 { BlackPlay, (ChessSquare) 0, BlackPawn, BlackKnight, BlackBishop,
747 BlackRook, BlackQueen, BlackKing, (ChessSquare) 0, BlackAlfil,
748 BlackCannon, BlackAngel, BlackMarshall, (ChessSquare) 0,
749 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
752 #define DROP_MENU_SIZE 6
753 String dropMenuStrings[DROP_MENU_SIZE] = {
754 "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"), N_("Queen")
756 /* must be in same order as PieceMenuStrings! */
757 ChessSquare dropMenuTranslation[DROP_MENU_SIZE] = {
758 (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
759 WhiteRook, WhiteQueen
767 DropMenuEnables dmEnables[] = {
776 { XtNborderWidth, 0 },
777 { XtNdefaultDistance, 0 },
781 { XtNborderWidth, 0 },
782 { XtNresizable, (XtArgVal) True },
786 { XtNborderWidth, 0 },
791 XtResource clientResources[] = {
792 { "whitePieceColor", "whitePieceColor", XtRString, sizeof(String),
793 XtOffset(AppDataPtr, whitePieceColor), XtRString,
795 { "blackPieceColor", "blackPieceColor", XtRString, sizeof(String),
796 XtOffset(AppDataPtr, blackPieceColor), XtRString,
798 { "lightSquareColor", "lightSquareColor", XtRString,
799 sizeof(String), XtOffset(AppDataPtr, lightSquareColor),
800 XtRString, LIGHT_SQUARE_COLOR },
801 { "darkSquareColor", "darkSquareColor", XtRString, sizeof(String),
802 XtOffset(AppDataPtr, darkSquareColor), XtRString,
804 { "highlightSquareColor", "highlightSquareColor", XtRString,
805 sizeof(String), XtOffset(AppDataPtr, highlightSquareColor),
806 XtRString, HIGHLIGHT_SQUARE_COLOR },
807 { "premoveHighlightColor", "premoveHighlightColor", XtRString,
808 sizeof(String), XtOffset(AppDataPtr, premoveHighlightColor),
809 XtRString, PREMOVE_HIGHLIGHT_COLOR },
810 { "movesPerSession", "movesPerSession", XtRInt, sizeof(int),
811 XtOffset(AppDataPtr, movesPerSession), XtRImmediate,
812 (XtPointer) MOVES_PER_SESSION },
813 { "timeIncrement", "timeIncrement", XtRInt, sizeof(int),
814 XtOffset(AppDataPtr, timeIncrement), XtRImmediate,
815 (XtPointer) TIME_INCREMENT },
816 { "initString", "initString", XtRString, sizeof(String),
817 XtOffset(AppDataPtr, initString), XtRString, INIT_STRING },
818 { "secondInitString", "secondInitString", XtRString, sizeof(String),
819 XtOffset(AppDataPtr, secondInitString), XtRString, INIT_STRING },
820 { "firstComputerString", "firstComputerString", XtRString,
821 sizeof(String), XtOffset(AppDataPtr, firstComputerString), XtRString,
823 { "secondComputerString", "secondComputerString", XtRString,
824 sizeof(String), XtOffset(AppDataPtr, secondComputerString), XtRString,
826 { "firstChessProgram", "firstChessProgram", XtRString,
827 sizeof(String), XtOffset(AppDataPtr, firstChessProgram),
828 XtRString, FIRST_CHESS_PROGRAM },
829 { "secondChessProgram", "secondChessProgram", XtRString,
830 sizeof(String), XtOffset(AppDataPtr, secondChessProgram),
831 XtRString, SECOND_CHESS_PROGRAM },
832 { "firstPlaysBlack", "firstPlaysBlack", XtRBoolean,
833 sizeof(Boolean), XtOffset(AppDataPtr, firstPlaysBlack),
834 XtRImmediate, (XtPointer) False },
835 { "noChessProgram", "noChessProgram", XtRBoolean,
836 sizeof(Boolean), XtOffset(AppDataPtr, noChessProgram),
837 XtRImmediate, (XtPointer) False },
838 { "firstHost", "firstHost", XtRString, sizeof(String),
839 XtOffset(AppDataPtr, firstHost), XtRString, FIRST_HOST },
840 { "secondHost", "secondHost", XtRString, sizeof(String),
841 XtOffset(AppDataPtr, secondHost), XtRString, SECOND_HOST },
842 { "firstDirectory", "firstDirectory", XtRString, sizeof(String),
843 XtOffset(AppDataPtr, firstDirectory), XtRString, "." },
844 { "secondDirectory", "secondDirectory", XtRString, sizeof(String),
845 XtOffset(AppDataPtr, secondDirectory), XtRString, "." },
846 { "bitmapDirectory", "bitmapDirectory", XtRString,
847 sizeof(String), XtOffset(AppDataPtr, bitmapDirectory),
849 { "remoteShell", "remoteShell", XtRString, sizeof(String),
850 XtOffset(AppDataPtr, remoteShell), XtRString, REMOTE_SHELL },
851 { "remoteUser", "remoteUser", XtRString, sizeof(String),
852 XtOffset(AppDataPtr, remoteUser), XtRString, "" },
853 { "timeDelay", "timeDelay", XtRFloat, sizeof(float),
854 XtOffset(AppDataPtr, timeDelay), XtRString,
855 (XtPointer) TIME_DELAY_QUOTE },
856 { "timeControl", "timeControl", XtRString, sizeof(String),
857 XtOffset(AppDataPtr, timeControl), XtRString,
858 (XtPointer) TIME_CONTROL },
859 { "internetChessServerMode", "internetChessServerMode",
860 XtRBoolean, sizeof(Boolean),
861 XtOffset(AppDataPtr, icsActive), XtRImmediate,
863 { "internetChessServerHost", "internetChessServerHost",
864 XtRString, sizeof(String),
865 XtOffset(AppDataPtr, icsHost),
866 XtRString, (XtPointer) ICS_HOST },
867 { "internetChessServerPort", "internetChessServerPort",
868 XtRString, sizeof(String),
869 XtOffset(AppDataPtr, icsPort), XtRString,
870 (XtPointer) ICS_PORT },
871 { "internetChessServerCommPort", "internetChessServerCommPort",
872 XtRString, sizeof(String),
873 XtOffset(AppDataPtr, icsCommPort), XtRString,
875 { "internetChessServerLogonScript", "internetChessServerLogonScript",
876 XtRString, sizeof(String),
877 XtOffset(AppDataPtr, icsLogon), XtRString,
879 { "internetChessServerHelper", "internetChessServerHelper",
880 XtRString, sizeof(String),
881 XtOffset(AppDataPtr, icsHelper), XtRString, "" },
882 { "internetChessServerInputBox", "internetChessServerInputBox",
883 XtRBoolean, sizeof(Boolean),
884 XtOffset(AppDataPtr, icsInputBox), XtRImmediate,
886 { "icsAlarm", "icsAlarm",
887 XtRBoolean, sizeof(Boolean),
888 XtOffset(AppDataPtr, icsAlarm), XtRImmediate,
890 { "icsAlarmTime", "icsAlarmTime",
892 XtOffset(AppDataPtr, icsAlarmTime), XtRImmediate,
894 { "useTelnet", "useTelnet", XtRBoolean, sizeof(Boolean),
895 XtOffset(AppDataPtr, useTelnet), XtRImmediate,
897 { "telnetProgram", "telnetProgram", XtRString, sizeof(String),
898 XtOffset(AppDataPtr, telnetProgram), XtRString, TELNET_PROGRAM },
899 { "gateway", "gateway", XtRString, sizeof(String),
900 XtOffset(AppDataPtr, gateway), XtRString, "" },
901 { "loadGameFile", "loadGameFile", XtRString, sizeof(String),
902 XtOffset(AppDataPtr, loadGameFile), XtRString, "" },
903 { "loadGameIndex", "loadGameIndex",
905 XtOffset(AppDataPtr, loadGameIndex), XtRImmediate,
907 { "saveGameFile", "saveGameFile", XtRString, sizeof(String),
908 XtOffset(AppDataPtr, saveGameFile), XtRString, "" },
909 { "autoRaiseBoard", "autoRaiseBoard", XtRBoolean,
910 sizeof(Boolean), XtOffset(AppDataPtr, autoRaiseBoard),
911 XtRImmediate, (XtPointer) True },
912 { "autoSaveGames", "autoSaveGames", XtRBoolean,
913 sizeof(Boolean), XtOffset(AppDataPtr, autoSaveGames),
914 XtRImmediate, (XtPointer) False },
915 { "blindfold", "blindfold", XtRBoolean,
916 sizeof(Boolean), XtOffset(AppDataPtr, blindfold),
917 XtRImmediate, (XtPointer) False },
918 { "loadPositionFile", "loadPositionFile", XtRString,
919 sizeof(String), XtOffset(AppDataPtr, loadPositionFile),
921 { "loadPositionIndex", "loadPositionIndex",
923 XtOffset(AppDataPtr, loadPositionIndex), XtRImmediate,
925 { "savePositionFile", "savePositionFile", XtRString,
926 sizeof(String), XtOffset(AppDataPtr, savePositionFile),
928 { "matchMode", "matchMode", XtRBoolean, sizeof(Boolean),
929 XtOffset(AppDataPtr, matchMode), XtRImmediate, (XtPointer) False },
930 { "matchGames", "matchGames", XtRInt, sizeof(int),
931 XtOffset(AppDataPtr, matchGames), XtRImmediate,
933 { "monoMode", "monoMode", XtRBoolean, sizeof(Boolean),
934 XtOffset(AppDataPtr, monoMode), XtRImmediate,
936 { "debugMode", "debugMode", XtRBoolean, sizeof(Boolean),
937 XtOffset(AppDataPtr, debugMode), XtRImmediate,
939 { "clockMode", "clockMode", XtRBoolean, sizeof(Boolean),
940 XtOffset(AppDataPtr, clockMode), XtRImmediate,
942 { "boardSize", "boardSize", XtRString, sizeof(String),
943 XtOffset(AppDataPtr, boardSize), XtRString, "" },
944 { "searchTime", "searchTime", XtRString, sizeof(String),
945 XtOffset(AppDataPtr, searchTime), XtRString,
947 { "searchDepth", "searchDepth", XtRInt, sizeof(int),
948 XtOffset(AppDataPtr, searchDepth), XtRImmediate,
950 { "showCoords", "showCoords", XtRBoolean, sizeof(Boolean),
951 XtOffset(AppDataPtr, showCoords), XtRImmediate,
953 { "showJail", "showJail", XtRInt, sizeof(int),
954 XtOffset(AppDataPtr, showJail), XtRImmediate,
956 { "showThinking", "showThinking", XtRBoolean, sizeof(Boolean),
957 XtOffset(AppDataPtr, showThinking), XtRImmediate,
959 { "ponderNextMove", "ponderNextMove", XtRBoolean, sizeof(Boolean),
960 XtOffset(AppDataPtr, ponderNextMove), XtRImmediate,
962 { "periodicUpdates", "periodicUpdates", XtRBoolean, sizeof(Boolean),
963 XtOffset(AppDataPtr, periodicUpdates), XtRImmediate,
965 { "clockFont", "clockFont", XtRString, sizeof(String),
966 XtOffset(AppDataPtr, clockFont), XtRString, CLOCK_FONT },
967 { "coordFont", "coordFont", XtRString, sizeof(String),
968 XtOffset(AppDataPtr, coordFont), XtRString, COORD_FONT },
969 { "font", "font", XtRString, sizeof(String),
970 XtOffset(AppDataPtr, font), XtRString, DEFAULT_FONT },
971 { "ringBellAfterMoves", "ringBellAfterMoves",
972 XtRBoolean, sizeof(Boolean),
973 XtOffset(AppDataPtr, ringBellAfterMoves),
974 XtRImmediate, (XtPointer) False },
975 { "autoCallFlag", "autoCallFlag", XtRBoolean,
976 sizeof(Boolean), XtOffset(AppDataPtr, autoCallFlag),
977 XtRImmediate, (XtPointer) False },
978 { "autoFlipView", "autoFlipView", XtRBoolean,
979 sizeof(Boolean), XtOffset(AppDataPtr, autoFlipView),
980 XtRImmediate, (XtPointer) True },
981 { "autoObserve", "autoObserve", XtRBoolean,
982 sizeof(Boolean), XtOffset(AppDataPtr, autoObserve),
983 XtRImmediate, (XtPointer) False },
984 { "autoComment", "autoComment", XtRBoolean,
985 sizeof(Boolean), XtOffset(AppDataPtr, autoComment),
986 XtRImmediate, (XtPointer) False },
987 { "getMoveList", "getMoveList", XtRBoolean,
988 sizeof(Boolean), XtOffset(AppDataPtr, getMoveList),
989 XtRImmediate, (XtPointer) True },
991 { "highlightDragging", "highlightDragging", XtRBoolean,
992 sizeof(Boolean), XtOffset(AppDataPtr, highlightDragging),
993 XtRImmediate, (XtPointer) False },
995 { "highlightLastMove", "highlightLastMove", XtRBoolean,
996 sizeof(Boolean), XtOffset(AppDataPtr, highlightLastMove),
997 XtRImmediate, (XtPointer) False },
998 { "premove", "premove", XtRBoolean,
999 sizeof(Boolean), XtOffset(AppDataPtr, premove),
1000 XtRImmediate, (XtPointer) True },
1001 { "testLegality", "testLegality", XtRBoolean,
1002 sizeof(Boolean), XtOffset(AppDataPtr, testLegality),
1003 XtRImmediate, (XtPointer) True },
1004 { "flipView", "flipView", XtRBoolean,
1005 sizeof(Boolean), XtOffset(AppDataPtr, flipView),
1006 XtRImmediate, (XtPointer) False },
1007 { "cmail", "cmailGameName", XtRString, sizeof(String),
1008 XtOffset(AppDataPtr, cmailGameName), XtRString, "" },
1009 { "alwaysPromoteToQueen", "alwaysPromoteToQueen", XtRBoolean,
1010 sizeof(Boolean), XtOffset(AppDataPtr, alwaysPromoteToQueen),
1011 XtRImmediate, (XtPointer) False },
1012 { "oldSaveStyle", "oldSaveStyle", XtRBoolean,
1013 sizeof(Boolean), XtOffset(AppDataPtr, oldSaveStyle),
1014 XtRImmediate, (XtPointer) False },
1015 { "quietPlay", "quietPlay", XtRBoolean,
1016 sizeof(Boolean), XtOffset(AppDataPtr, quietPlay),
1017 XtRImmediate, (XtPointer) False },
1018 { "titleInWindow", "titleInWindow", XtRBoolean,
1019 sizeof(Boolean), XtOffset(AppDataPtr, titleInWindow),
1020 XtRImmediate, (XtPointer) False },
1021 { "localLineEditing", "localLineEditing", XtRBoolean,
1022 sizeof(Boolean), XtOffset(AppDataPtr, localLineEditing),
1023 XtRImmediate, (XtPointer) True }, /* not implemented, must be True */
1025 { "zippyTalk", "zippyTalk", XtRBoolean,
1026 sizeof(Boolean), XtOffset(AppDataPtr, zippyTalk),
1027 XtRImmediate, (XtPointer) ZIPPY_TALK },
1028 { "zippyPlay", "zippyPlay", XtRBoolean,
1029 sizeof(Boolean), XtOffset(AppDataPtr, zippyPlay),
1030 XtRImmediate, (XtPointer) ZIPPY_PLAY },
1031 { "zippyLines", "zippyLines", XtRString, sizeof(String),
1032 XtOffset(AppDataPtr, zippyLines), XtRString, ZIPPY_LINES },
1033 { "zippyPinhead", "zippyPinhead", XtRString, sizeof(String),
1034 XtOffset(AppDataPtr, zippyPinhead), XtRString, ZIPPY_PINHEAD },
1035 { "zippyPassword", "zippyPassword", XtRString, sizeof(String),
1036 XtOffset(AppDataPtr, zippyPassword), XtRString, ZIPPY_PASSWORD },
1037 { "zippyPassword2", "zippyPassword2", XtRString, sizeof(String),
1038 XtOffset(AppDataPtr, zippyPassword2), XtRString, ZIPPY_PASSWORD2 },
1039 { "zippyWrongPassword", "zippyWrongPassword", XtRString, sizeof(String),
1040 XtOffset(AppDataPtr, zippyWrongPassword), XtRString,
1041 ZIPPY_WRONG_PASSWORD },
1042 { "zippyAcceptOnly", "zippyAcceptOnly", XtRString, sizeof(String),
1043 XtOffset(AppDataPtr, zippyAcceptOnly), XtRString, ZIPPY_ACCEPT_ONLY },
1044 { "zippyUseI", "zippyUseI", XtRBoolean,
1045 sizeof(Boolean), XtOffset(AppDataPtr, zippyUseI),
1046 XtRImmediate, (XtPointer) ZIPPY_USE_I },
1047 { "zippyBughouse", "zippyBughouse", XtRInt,
1048 sizeof(int), XtOffset(AppDataPtr, zippyBughouse),
1049 XtRImmediate, (XtPointer) ZIPPY_BUGHOUSE },
1050 { "zippyNoplayCrafty", "zippyNoplayCrafty", XtRBoolean,
1051 sizeof(Boolean), XtOffset(AppDataPtr, zippyNoplayCrafty),
1052 XtRImmediate, (XtPointer) ZIPPY_NOPLAY_CRAFTY },
1053 { "zippyGameEnd", "zippyGameEnd", XtRString, sizeof(String),
1054 XtOffset(AppDataPtr, zippyGameEnd), XtRString, ZIPPY_GAME_END },
1055 { "zippyGameStart", "zippyGameStart", XtRString, sizeof(String),
1056 XtOffset(AppDataPtr, zippyGameStart), XtRString, ZIPPY_GAME_START },
1057 { "zippyAdjourn", "zippyAdjourn", XtRBoolean,
1058 sizeof(Boolean), XtOffset(AppDataPtr, zippyAdjourn),
1059 XtRImmediate, (XtPointer) ZIPPY_ADJOURN },
1060 { "zippyAbort", "zippyAbort", XtRBoolean,
1061 sizeof(Boolean), XtOffset(AppDataPtr, zippyAbort),
1062 XtRImmediate, (XtPointer) ZIPPY_ABORT },
1063 { "zippyVariants", "zippyVariants", XtRString, sizeof(String),
1064 XtOffset(AppDataPtr, zippyVariants), XtRString, ZIPPY_VARIANTS },
1065 { "zippyMaxGames", "zippyMaxGames", XtRInt, sizeof(int),
1066 XtOffset(AppDataPtr, zippyMaxGames), XtRImmediate,
1067 (XtPointer) ZIPPY_MAX_GAMES },
1068 { "zippyReplayTimeout", "zippyReplayTimeout", XtRInt, sizeof(int),
1069 XtOffset(AppDataPtr, zippyReplayTimeout), XtRImmediate,
1070 (XtPointer) ZIPPY_REPLAY_TIMEOUT },
1071 { "zippyShortGame", "zippyShortGame", XtRInt, sizeof(int),
1072 XtOffset(AppDataPtr, zippyShortGame), XtRImmediate,
1075 { "flashCount", "flashCount", XtRInt, sizeof(int),
1076 XtOffset(AppDataPtr, flashCount), XtRImmediate,
1077 (XtPointer) FLASH_COUNT },
1078 { "flashRate", "flashRate", XtRInt, sizeof(int),
1079 XtOffset(AppDataPtr, flashRate), XtRImmediate,
1080 (XtPointer) FLASH_RATE },
1081 { "pixmapDirectory", "pixmapDirectory", XtRString,
1082 sizeof(String), XtOffset(AppDataPtr, pixmapDirectory),
1084 { "msLoginDelay", "msLoginDelay", XtRInt, sizeof(int),
1085 XtOffset(AppDataPtr, msLoginDelay), XtRImmediate,
1086 (XtPointer) MS_LOGIN_DELAY },
1087 { "colorizeMessages", "colorizeMessages", XtRBoolean,
1088 sizeof(Boolean), XtOffset(AppDataPtr, colorize),
1089 XtRImmediate, (XtPointer) False },
1090 { "colorShout", "colorShout", XtRString,
1091 sizeof(String), XtOffset(AppDataPtr, colorShout),
1092 XtRString, COLOR_SHOUT },
1093 { "colorSShout", "colorSShout", XtRString,
1094 sizeof(String), XtOffset(AppDataPtr, colorSShout),
1095 XtRString, COLOR_SSHOUT },
1096 { "colorChannel1", "colorChannel1", XtRString,
1097 sizeof(String), XtOffset(AppDataPtr, colorChannel1),
1098 XtRString, COLOR_CHANNEL1 },
1099 { "colorChannel", "colorChannel", XtRString,
1100 sizeof(String), XtOffset(AppDataPtr, colorChannel),
1101 XtRString, COLOR_CHANNEL },
1102 { "colorKibitz", "colorKibitz", XtRString,
1103 sizeof(String), XtOffset(AppDataPtr, colorKibitz),
1104 XtRString, COLOR_KIBITZ },
1105 { "colorTell", "colorTell", XtRString,
1106 sizeof(String), XtOffset(AppDataPtr, colorTell),
1107 XtRString, COLOR_TELL },
1108 { "colorChallenge", "colorChallenge", XtRString,
1109 sizeof(String), XtOffset(AppDataPtr, colorChallenge),
1110 XtRString, COLOR_CHALLENGE },
1111 { "colorRequest", "colorRequest", XtRString,
1112 sizeof(String), XtOffset(AppDataPtr, colorRequest),
1113 XtRString, COLOR_REQUEST },
1114 { "colorSeek", "colorSeek", XtRString,
1115 sizeof(String), XtOffset(AppDataPtr, colorSeek),
1116 XtRString, COLOR_SEEK },
1117 { "colorNormal", "colorNormal", XtRString,
1118 sizeof(String), XtOffset(AppDataPtr, colorNormal),
1119 XtRString, COLOR_NORMAL },
1120 { "soundProgram", "soundProgram", XtRString,
1121 sizeof(String), XtOffset(AppDataPtr, soundProgram),
1122 XtRString, "play" },
1123 { "soundShout", "soundShout", XtRString,
1124 sizeof(String), XtOffset(AppDataPtr, soundShout),
1126 { "soundSShout", "soundSShout", XtRString,
1127 sizeof(String), XtOffset(AppDataPtr, soundSShout),
1129 { "soundChannel1", "soundChannel1", XtRString,
1130 sizeof(String), XtOffset(AppDataPtr, soundChannel1),
1132 { "soundChannel", "soundChannel", XtRString,
1133 sizeof(String), XtOffset(AppDataPtr, soundChannel),
1135 { "soundKibitz", "soundKibitz", XtRString,
1136 sizeof(String), XtOffset(AppDataPtr, soundKibitz),
1138 { "soundTell", "soundTell", XtRString,
1139 sizeof(String), XtOffset(AppDataPtr, soundTell),
1141 { "soundChallenge", "soundChallenge", XtRString,
1142 sizeof(String), XtOffset(AppDataPtr, soundChallenge),
1144 { "soundRequest", "soundRequest", XtRString,
1145 sizeof(String), XtOffset(AppDataPtr, soundRequest),
1147 { "soundSeek", "soundSeek", XtRString,
1148 sizeof(String), XtOffset(AppDataPtr, soundSeek),
1150 { "soundMove", "soundMove", XtRString,
1151 sizeof(String), XtOffset(AppDataPtr, soundMove),
1153 { "soundIcsWin", "soundIcsWin", XtRString,
1154 sizeof(String), XtOffset(AppDataPtr, soundIcsWin),
1156 { "soundIcsLoss", "soundIcsLoss", XtRString,
1157 sizeof(String), XtOffset(AppDataPtr, soundIcsLoss),
1159 { "soundIcsDraw", "soundIcsDraw", XtRString,
1160 sizeof(String), XtOffset(AppDataPtr, soundIcsDraw),
1162 { "soundIcsUnfinished", "soundIcsUnfinished", XtRString,
1163 sizeof(String), XtOffset(AppDataPtr, soundIcsUnfinished),
1165 { "soundIcsAlarm", "soundIcsAlarm", XtRString,
1166 sizeof(String), XtOffset(AppDataPtr, soundIcsAlarm),
1168 { "reuseFirst", "reuseFirst", XtRBoolean,
1169 sizeof(Boolean), XtOffset(AppDataPtr, reuseFirst),
1170 XtRImmediate, (XtPointer) True },
1171 { "reuseSecond", "reuseSecond", XtRBoolean,
1172 sizeof(Boolean), XtOffset(AppDataPtr, reuseSecond),
1173 XtRImmediate, (XtPointer) True },
1174 { "animateDragging", "animateDragging", XtRBoolean,
1175 sizeof(Boolean), XtOffset(AppDataPtr, animateDragging),
1176 XtRImmediate, (XtPointer) True },
1177 { "animateMoving", "animateMoving", XtRBoolean,
1178 sizeof(Boolean), XtOffset(AppDataPtr, animate),
1179 XtRImmediate, (XtPointer) True },
1180 { "animateSpeed", "animateSpeed", XtRInt,
1181 sizeof(int), XtOffset(AppDataPtr, animSpeed),
1182 XtRImmediate, (XtPointer)10 },
1183 { "popupExitMessage", "popupExitMessage", XtRBoolean,
1184 sizeof(Boolean), XtOffset(AppDataPtr, popupExitMessage),
1185 XtRImmediate, (XtPointer) True },
1186 { "popupMoveErrors", "popupMoveErrors", XtRBoolean,
1187 sizeof(Boolean), XtOffset(AppDataPtr, popupMoveErrors),
1188 XtRImmediate, (XtPointer) False },
1189 { "fontSizeTolerance", "fontSizeTolerance", XtRInt,
1190 sizeof(int), XtOffset(AppDataPtr, fontSizeTolerance),
1191 XtRImmediate, (XtPointer)4 },
1192 { "initialMode", "initialMode", XtRString,
1193 sizeof(String), XtOffset(AppDataPtr, initialMode),
1194 XtRImmediate, (XtPointer) "" },
1195 { "variant", "variant", XtRString,
1196 sizeof(String), XtOffset(AppDataPtr, variant),
1197 XtRImmediate, (XtPointer) "normal" },
1198 { "firstProtocolVersion", "firstProtocolVersion", XtRInt,
1199 sizeof(int), XtOffset(AppDataPtr, firstProtocolVersion),
1200 XtRImmediate, (XtPointer)PROTOVER },
1201 { "secondProtocolVersion", "secondProtocolVersion", XtRInt,
1202 sizeof(int), XtOffset(AppDataPtr, secondProtocolVersion),
1203 XtRImmediate, (XtPointer)PROTOVER },
1204 { "showButtonBar", "showButtonBar", XtRBoolean,
1205 sizeof(Boolean), XtOffset(AppDataPtr, showButtonBar),
1206 XtRImmediate, (XtPointer) True },
1207 { "lowTimeWarningColor", "lowTimeWarningColor", XtRString,
1208 sizeof(String), XtOffset(AppDataPtr, lowTimeWarningColor),
1209 XtRString, COLOR_LOWTIMEWARNING },
1210 { "lowTimeWarning", "lowTimeWarning", XtRBoolean,
1211 sizeof(Boolean), XtOffset(AppDataPtr, lowTimeWarning),
1212 XtRImmediate, (XtPointer) False },
1213 {"icsEngineAnalyze", "icsEngineAnalyze", XtRBoolean, /* [DM] icsEngineAnalyze */
1214 sizeof(Boolean), XtOffset(AppDataPtr, icsEngineAnalyze),
1215 XtRImmediate, (XtPointer) False },
1216 { "firstScoreAbs", "firstScoreAbs", XtRBoolean,
1217 sizeof(Boolean), XtOffset(AppDataPtr, firstScoreIsAbsolute),
1218 XtRImmediate, (XtPointer) False },
1219 { "secondScoreAbs", "secondScoreAbs", XtRBoolean,
1220 sizeof(Boolean), XtOffset(AppDataPtr, secondScoreIsAbsolute),
1221 XtRImmediate, (XtPointer) False },
1222 { "pgnExtendedInfo", "pgnExtendedInfo", XtRBoolean,
1223 sizeof(Boolean), XtOffset(AppDataPtr, saveExtendedInfoInPGN),
1224 XtRImmediate, (XtPointer) False },
1225 { "hideThinkingFromHuman", "hideThinkingFromHuman", XtRBoolean,
1226 sizeof(Boolean), XtOffset(AppDataPtr, hideThinkingFromHuman),
1227 XtRImmediate, (XtPointer) True },
1228 { "adjudicateLossThreshold", "adjudicateLossThreshold", XtRInt,
1229 sizeof(int), XtOffset(AppDataPtr, adjudicateLossThreshold),
1230 XtRImmediate, (XtPointer) 0},
1231 { "adjudicateDrawMoves", "adjudicateDrawMoves", XtRInt,
1232 sizeof(int), XtOffset(AppDataPtr, adjudicateDrawMoves),
1233 XtRImmediate, (XtPointer) 0},
1234 { "pgnEventHeader", "pgnEventHeader", XtRString,
1235 sizeof(String), XtOffset(AppDataPtr, pgnEventHeader),
1236 XtRImmediate, (XtPointer) "Computer Chess Game" },
1237 { "defaultFrcPosition", "defaultFrcPositon", XtRInt,
1238 sizeof(int), XtOffset(AppDataPtr, defaultFrcPosition),
1239 XtRImmediate, (XtPointer) -1},
1240 { "gameListTags", "gameListTags", XtRString,
1241 sizeof(String), XtOffset(AppDataPtr, gameListTags),
1242 XtRImmediate, (XtPointer) GLT_DEFAULT_TAGS },
1244 // [HGM] 4.3.xx options
1245 { "boardWidth", "boardWidth", XtRInt,
1246 sizeof(int), XtOffset(AppDataPtr, NrFiles),
1247 XtRImmediate, (XtPointer) -1},
1248 { "boardHeight", "boardHeight", XtRInt,
1249 sizeof(int), XtOffset(AppDataPtr, NrRanks),
1250 XtRImmediate, (XtPointer) -1},
1251 { "matchPause", "matchPause", XtRInt,
1252 sizeof(int), XtOffset(AppDataPtr, matchPause),
1253 XtRImmediate, (XtPointer) 10000},
1254 { "holdingsSize", "holdingsSize", XtRInt,
1255 sizeof(int), XtOffset(AppDataPtr, holdingsSize),
1256 XtRImmediate, (XtPointer) -1},
1257 { "flipBlack", "flipBlack", XtRBoolean,
1258 sizeof(Boolean), XtOffset(AppDataPtr, upsideDown),
1259 XtRImmediate, (XtPointer) False},
1260 { "allWhite", "allWhite", XtRBoolean,
1261 sizeof(Boolean), XtOffset(AppDataPtr, allWhite),
1262 XtRImmediate, (XtPointer) False},
1263 { "pieceToCharTable", "pieceToCharTable", XtRString,
1264 sizeof(String), XtOffset(AppDataPtr, pieceToCharTable),
1265 XtRImmediate, (XtPointer) 0},
1266 { "alphaRank", "alphaRank", XtRBoolean,
1267 sizeof(Boolean), XtOffset(AppDataPtr, alphaRank),
1268 XtRImmediate, (XtPointer) False},
1269 { "testClaims", "testClaims", XtRBoolean,
1270 sizeof(Boolean), XtOffset(AppDataPtr, testClaims),
1271 XtRImmediate, (XtPointer) True},
1272 { "checkMates", "checkMates", XtRBoolean,
1273 sizeof(Boolean), XtOffset(AppDataPtr, checkMates),
1274 XtRImmediate, (XtPointer) True},
1275 { "materialDraws", "materialDraws", XtRBoolean,
1276 sizeof(Boolean), XtOffset(AppDataPtr, materialDraws),
1277 XtRImmediate, (XtPointer) True},
1278 { "trivialDraws", "trivialDraws", XtRBoolean,
1279 sizeof(Boolean), XtOffset(AppDataPtr, trivialDraws),
1280 XtRImmediate, (XtPointer) False},
1281 { "ruleMoves", "ruleMoves", XtRInt,
1282 sizeof(int), XtOffset(AppDataPtr, ruleMoves),
1283 XtRImmediate, (XtPointer) 51},
1284 { "repeatsToDraw", "repeatsToDraw", XtRInt,
1285 sizeof(int), XtOffset(AppDataPtr, drawRepeats),
1286 XtRImmediate, (XtPointer) 6},
1287 { "engineDebugOutput", "engineDebugOutput", XtRInt,
1288 sizeof(int), XtOffset(AppDataPtr, engineComments),
1289 XtRImmediate, (XtPointer) 1},
1290 { "userName", "userName", XtRString,
1291 sizeof(int), XtOffset(AppDataPtr, userName),
1292 XtRImmediate, (XtPointer) 0},
1293 { "autoKibitz", "autoKibitz", XtRBoolean,
1294 sizeof(Boolean), XtOffset(AppDataPtr, autoKibitz),
1295 XtRImmediate, (XtPointer) False},
1296 { "firstTimeOdds", "firstTimeOdds", XtRInt,
1297 sizeof(int), XtOffset(AppDataPtr, firstTimeOdds),
1298 XtRImmediate, (XtPointer) 1},
1299 { "secondTimeOdds", "secondTimeOdds", XtRInt,
1300 sizeof(int), XtOffset(AppDataPtr, secondTimeOdds),
1301 XtRImmediate, (XtPointer) 1},
1302 { "timeOddsMode", "timeOddsMode", XtRInt,
1303 sizeof(int), XtOffset(AppDataPtr, timeOddsMode),
1304 XtRImmediate, (XtPointer) 0},
1305 { "firstAccumulateTC", "firstAccumulateTC", XtRInt,
1306 sizeof(int), XtOffset(AppDataPtr, firstAccumulateTC),
1307 XtRImmediate, (XtPointer) 1},
1308 { "secondAccumulateTC", "secondAccumulateTC", XtRInt,
1309 sizeof(int), XtOffset(AppDataPtr, secondAccumulateTC),
1310 XtRImmediate, (XtPointer) 1},
1311 { "firstNPS", "firstNPS", XtRInt,
1312 sizeof(int), XtOffset(AppDataPtr, firstNPS),
1313 XtRImmediate, (XtPointer) -1},
1314 { "secondNPS", "secondNPS", XtRInt,
1315 sizeof(int), XtOffset(AppDataPtr, secondNPS),
1316 XtRImmediate, (XtPointer) -1},
1317 { "serverMoves", "serverMoves", XtRString,
1318 sizeof(String), XtOffset(AppDataPtr, serverMovesName),
1319 XtRImmediate, (XtPointer) 0},
1320 { "serverPause", "serverPause", XtRInt,
1321 sizeof(int), XtOffset(AppDataPtr, serverPause),
1322 XtRImmediate, (XtPointer) 0},
1323 { "suppressLoadMoves", "suppressLoadMoves", XtRBoolean,
1324 sizeof(Boolean), XtOffset(AppDataPtr, suppressLoadMoves),
1325 XtRImmediate, (XtPointer) False},
1326 { "userName", "userName", XtRString,
1327 sizeof(String), XtOffset(AppDataPtr, userName),
1328 XtRImmediate, (XtPointer) 0},
1329 { "egtFormats", "egtFormats", XtRString,
1330 sizeof(String), XtOffset(AppDataPtr, egtFormats),
1331 XtRImmediate, (XtPointer) 0},
1332 { "rewindIndex", "rewindIndex", XtRInt,
1333 sizeof(int), XtOffset(AppDataPtr, rewindIndex),
1334 XtRImmediate, (XtPointer) 0},
1335 { "sameColorGames", "sameColorGames", XtRInt,
1336 sizeof(int), XtOffset(AppDataPtr, sameColorGames),
1337 XtRImmediate, (XtPointer) 0},
1338 { "smpCores", "smpCores", XtRInt,
1339 sizeof(int), XtOffset(AppDataPtr, smpCores),
1340 XtRImmediate, (XtPointer) 1},
1341 { "niceEngines", "niceEngines", XtRInt,
1342 sizeof(int), XtOffset(AppDataPtr, niceEngines),
1343 XtRImmediate, (XtPointer) 0},
1344 { "nameOfDebugFile", "nameOfDebugFile", XtRString,
1345 sizeof(String), XtOffset(AppDataPtr, nameOfDebugFile),
1346 XtRImmediate, (XtPointer) "xboard.debug"},
1347 { "engineDebugOutput", "engineDebugOutput", XtRInt,
1348 sizeof(int), XtOffset(AppDataPtr, engineComments),
1349 XtRImmediate, (XtPointer) 1},
1350 { "noGUI", "noGUI", XtRBoolean,
1351 sizeof(Boolean), XtOffset(AppDataPtr, noGUI),
1352 XtRImmediate, (XtPointer) 0},
1353 { "firstOptions", "firstOptions", XtRString,
1354 sizeof(String), XtOffset(AppDataPtr, firstOptions),
1355 XtRImmediate, (XtPointer) "" },
1356 { "secondOptions", "secondOptions", XtRString,
1357 sizeof(String), XtOffset(AppDataPtr, secondOptions),
1358 XtRImmediate, (XtPointer) "" },
1359 { "firstNeedsNoncompliantFEN", "firstNeedsNoncompliantFEN", XtRString,
1360 sizeof(String), XtOffset(AppDataPtr, fenOverride1),
1361 XtRImmediate, (XtPointer) 0 },
1362 { "secondNeedsNoncompliantFEN", "secondNeedsNoncompliantFEN", XtRString,
1363 sizeof(String), XtOffset(AppDataPtr, fenOverride2),
1364 XtRImmediate, (XtPointer) 0 },
1366 // [HGM] Winboard_x UCI options
1367 { "firstIsUCI", "firstIsUCI", XtRBoolean,
1368 sizeof(Boolean), XtOffset(AppDataPtr, firstIsUCI),
1369 XtRImmediate, (XtPointer) False},
1370 { "secondIsUCI", "secondIsUCI", XtRBoolean,
1371 sizeof(Boolean), XtOffset(AppDataPtr, secondIsUCI),
1372 XtRImmediate, (XtPointer) False},
1373 { "firstHasOwnBookUCI", "firstHasOwnBookUCI", XtRBoolean,
1374 sizeof(Boolean), XtOffset(AppDataPtr, firstHasOwnBookUCI),
1375 XtRImmediate, (XtPointer) True},
1376 { "secondHasOwnBookUCI", "secondHasOwnBookUCI", XtRBoolean,
1377 sizeof(Boolean), XtOffset(AppDataPtr, secondHasOwnBookUCI),
1378 XtRImmediate, (XtPointer) True},
1379 { "usePolyglotBook", "usePolyglotBook", XtRBoolean,
1380 sizeof(Boolean), XtOffset(AppDataPtr, usePolyglotBook),
1381 XtRImmediate, (XtPointer) False},
1382 { "defaultHashSize", "defaultHashSize", XtRInt,
1383 sizeof(int), XtOffset(AppDataPtr, defaultHashSize),
1384 XtRImmediate, (XtPointer) 64},
1385 { "defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XtRInt,
1386 sizeof(int), XtOffset(AppDataPtr, defaultCacheSizeEGTB),
1387 XtRImmediate, (XtPointer) 4},
1388 { "polyglotDir", "polyglotDir", XtRString,
1389 sizeof(String), XtOffset(AppDataPtr, polyglotDir),
1390 XtRImmediate, (XtPointer) "." },
1391 { "polyglotBook", "polyglotBook", XtRString,
1392 sizeof(String), XtOffset(AppDataPtr, polyglotBook),
1393 XtRImmediate, (XtPointer) "" },
1394 { "defaultPathEGTB", "defaultPathEGTB", XtRString,
1395 sizeof(String), XtOffset(AppDataPtr, defaultPathEGTB),
1396 XtRImmediate, (XtPointer) "/usr/local/share/egtb"},
1397 { "delayBeforeQuit", "delayBeforeQuit", XtRInt,
1398 sizeof(int), XtOffset(AppDataPtr, delayBeforeQuit),
1399 XtRImmediate, (XtPointer) 0},
1400 { "delayAfterQuit", "delayAfterQuit", XtRInt,
1401 sizeof(int), XtOffset(AppDataPtr, delayAfterQuit),
1402 XtRImmediate, (XtPointer) 0},
1403 { "keepAlive", "keepAlive", XtRInt,
1404 sizeof(int), XtOffset(AppDataPtr, keepAlive),
1405 XtRImmediate, (XtPointer) 0},
1406 { "forceIllegalMoves", "forceIllegalMoves", XtRBoolean,
1407 sizeof(Boolean), XtOffset(AppDataPtr, forceIllegal),
1408 XtRImmediate, (XtPointer) False},
1409 { "keepLineBreaksICS", "keepLineBreaksICS", XtRBoolean,
1410 sizeof(Boolean), XtOffset(AppDataPtr, noJoin),
1411 XtRImmediate, (XtPointer) True},
1414 XrmOptionDescRec shellOptions[] = {
1415 { "-whitePieceColor", "whitePieceColor", XrmoptionSepArg, NULL },
1416 { "-blackPieceColor", "blackPieceColor", XrmoptionSepArg, NULL },
1417 { "-lightSquareColor", "lightSquareColor", XrmoptionSepArg, NULL },
1418 { "-darkSquareColor", "darkSquareColor", XrmoptionSepArg, NULL },
1419 { "-highlightSquareColor", "highlightSquareColor", XrmoptionSepArg, NULL },
1420 { "-premoveHighlightColor", "premoveHighlightColor", XrmoptionSepArg,NULL},
1421 { "-movesPerSession", "movesPerSession", XrmoptionSepArg, NULL },
1422 { "-mps", "movesPerSession", XrmoptionSepArg, NULL },
1423 { "-timeIncrement", "timeIncrement", XrmoptionSepArg, NULL },
1424 { "-inc", "timeIncrement", XrmoptionSepArg, NULL },
1425 { "-initString", "initString", XrmoptionSepArg, NULL },
1426 { "-firstInitString", "initString", XrmoptionSepArg, NULL },
1427 { "-secondInitString", "secondInitString", XrmoptionSepArg, NULL },
1428 { "-firstComputerString", "firstComputerString", XrmoptionSepArg, NULL },
1429 { "-secondComputerString", "secondComputerString", XrmoptionSepArg, NULL },
1430 { "-firstChessProgram", "firstChessProgram", XrmoptionSepArg, NULL },
1431 { "-fcp", "firstChessProgram", XrmoptionSepArg, NULL },
1432 { "-secondChessProgram", "secondChessProgram", XrmoptionSepArg, NULL },
1433 { "-scp", "secondChessProgram", XrmoptionSepArg, NULL },
1434 { "-firstPlaysBlack", "firstPlaysBlack", XrmoptionSepArg, NULL },
1435 { "-fb", "firstPlaysBlack", XrmoptionNoArg, "True" },
1436 { "-xfb", "firstPlaysBlack", XrmoptionNoArg, "False" },
1437 { "-noChessProgram", "noChessProgram", XrmoptionSepArg, NULL },
1438 { "-ncp", "noChessProgram", XrmoptionNoArg, "True" },
1439 { "-xncp", "noChessProgram", XrmoptionNoArg, "False" },
1440 { "-firstHost", "firstHost", XrmoptionSepArg, NULL },
1441 { "-fh", "firstHost", XrmoptionSepArg, NULL },
1442 { "-secondHost", "secondHost", XrmoptionSepArg, NULL },
1443 { "-sh", "secondHost", XrmoptionSepArg, NULL },
1444 { "-firstDirectory", "firstDirectory", XrmoptionSepArg, NULL },
1445 { "-fd", "firstDirectory", XrmoptionSepArg, NULL },
1446 { "-secondDirectory", "secondDirectory", XrmoptionSepArg, NULL },
1447 { "-sd", "secondDirectory", XrmoptionSepArg, NULL },
1448 { "-bitmapDirectory", "bitmapDirectory", XrmoptionSepArg, NULL },
1449 { "-bm", "bitmapDirectory", XrmoptionSepArg, NULL },
1450 { "-remoteShell", "remoteShell", XrmoptionSepArg, NULL },
1451 { "-rsh", "remoteShell", XrmoptionSepArg, NULL },
1452 { "-remoteUser", "remoteUser", XrmoptionSepArg, NULL },
1453 { "-ruser", "remoteUser", XrmoptionSepArg, NULL },
1454 { "-timeDelay", "timeDelay", XrmoptionSepArg, NULL },
1455 { "-td", "timeDelay", XrmoptionSepArg, NULL },
1456 { "-timeControl", "timeControl", XrmoptionSepArg, NULL },
1457 { "-tc", "timeControl", XrmoptionSepArg, NULL },
1458 { "-internetChessServerMode", "internetChessServerMode",
1459 XrmoptionSepArg, NULL },
1460 { "-ics", "internetChessServerMode", XrmoptionNoArg, "True" },
1461 { "-xics", "internetChessServerMode", XrmoptionNoArg, "False" },
1462 { "-internetChessServerHost", "internetChessServerHost",
1463 XrmoptionSepArg, NULL },
1464 { "-icshost", "internetChessServerHost", XrmoptionSepArg, NULL },
1465 { "-internetChessServerPort", "internetChessServerPort",
1466 XrmoptionSepArg, NULL },
1467 { "-icsport", "internetChessServerPort", XrmoptionSepArg, NULL },
1468 { "-internetChessServerCommPort", "internetChessServerCommPort",
1469 XrmoptionSepArg, NULL },
1470 { "-icscomm", "internetChessServerCommPort", XrmoptionSepArg, NULL },
1471 { "-internetChessServerLogonScript", "internetChessServerLogonScript",
1472 XrmoptionSepArg, NULL },
1473 { "-icslogon", "internetChessServerLogonScript", XrmoptionSepArg, NULL },
1474 { "-internetChessServerHelper", "internetChessServerHelper",
1475 XrmoptionSepArg, NULL },
1476 { "-icshelper", "internetChessServerHelper", XrmoptionSepArg, NULL },
1477 { "-internetChessServerInputBox", "internetChessServerInputBox",
1478 XrmoptionSepArg, NULL },
1479 { "-icsinput", "internetChessServerInputBox", XrmoptionNoArg, "True" },
1480 { "-xicsinput", "internetChessServerInputBox", XrmoptionNoArg, "False" },
1481 { "-icsAlarm", "icsAlarm", XrmoptionSepArg, NULL },
1482 { "-alarm", "icsAlarm", XrmoptionNoArg, "True" },
1483 { "-xalarm", "icsAlarm", XrmoptionNoArg, "False" },
1484 { "-icsAlarmTime", "icsAlarmTime", XrmoptionSepArg, NULL },
1485 { "-useTelnet", "useTelnet", XrmoptionSepArg, NULL },
1486 { "-telnet", "useTelnet", XrmoptionNoArg, "True" },
1487 { "-xtelnet", "useTelnet", XrmoptionNoArg, "False" },
1488 { "-telnetProgram", "telnetProgram", XrmoptionSepArg, NULL },
1489 { "-gateway", "gateway", XrmoptionSepArg, NULL },
1490 { "-loadGameFile", "loadGameFile", XrmoptionSepArg, NULL },
1491 { "-lgf", "loadGameFile", XrmoptionSepArg, NULL },
1492 { "-loadGameIndex", "loadGameIndex", XrmoptionSepArg, NULL },
1493 { "-lgi", "loadGameIndex", XrmoptionSepArg, NULL },
1494 { "-saveGameFile", "saveGameFile", XrmoptionSepArg, NULL },
1495 { "-sgf", "saveGameFile", XrmoptionSepArg, NULL },
1496 { "-autoSaveGames", "autoSaveGames", XrmoptionSepArg, NULL },
1497 { "-autosave", "autoSaveGames", XrmoptionNoArg, "True" },
1498 { "-xautosave", "autoSaveGames", XrmoptionNoArg, "False" },
1499 { "-autoRaiseBoard", "autoRaiseBoard", XrmoptionSepArg, NULL },
1500 { "-autoraise", "autoRaiseBoard", XrmoptionNoArg, "True" },
1501 { "-xautoraise", "autoRaiseBoard", XrmoptionNoArg, "False" },
1502 { "-blindfold", "blindfold", XrmoptionSepArg, NULL },
1503 { "-blind", "blindfold", XrmoptionNoArg, "True" },
1504 { "-xblind", "blindfold", XrmoptionNoArg, "False" },
1505 { "-loadPositionFile", "loadPositionFile", XrmoptionSepArg, NULL },
1506 { "-lpf", "loadPositionFile", XrmoptionSepArg, NULL },
1507 { "-loadPositionIndex", "loadPositionIndex", XrmoptionSepArg, NULL },
1508 { "-lpi", "loadPositionIndex", XrmoptionSepArg, NULL },
1509 { "-savePositionFile", "savePositionFile", XrmoptionSepArg, NULL },
1510 { "-spf", "savePositionFile", XrmoptionSepArg, NULL },
1511 { "-matchMode", "matchMode", XrmoptionSepArg, NULL },
1512 { "-mm", "matchMode", XrmoptionNoArg, "True" },
1513 { "-xmm", "matchMode", XrmoptionNoArg, "False" },
1514 { "-matchGames", "matchGames", XrmoptionSepArg, NULL },
1515 { "-mg", "matchGames", XrmoptionSepArg, NULL },
1516 { "-monoMode", "monoMode", XrmoptionSepArg, NULL },
1517 { "-mono", "monoMode", XrmoptionNoArg, "True" },
1518 { "-xmono", "monoMode", XrmoptionNoArg, "False" },
1519 { "-debugMode", "debugMode", XrmoptionSepArg, NULL },
1520 { "-debug", "debugMode", XrmoptionNoArg, "True" },
1521 { "-xdebug", "debugMode", XrmoptionNoArg, "False" },
1522 { "-clockMode", "clockMode", XrmoptionSepArg, NULL },
1523 { "-clock", "clockMode", XrmoptionNoArg, "True" },
1524 { "-xclock", "clockMode", XrmoptionNoArg, "False" },
1525 { "-boardSize", "boardSize", XrmoptionSepArg, NULL },
1526 { "-size", "boardSize", XrmoptionSepArg, NULL },
1527 { "-searchTime", "searchTime", XrmoptionSepArg, NULL },
1528 { "-st", "searchTime", XrmoptionSepArg, NULL },
1529 { "-searchDepth", "searchDepth", XrmoptionSepArg, NULL },
1530 { "-depth", "searchDepth", XrmoptionSepArg, NULL },
1531 { "-showCoords", "showCoords", XrmoptionSepArg, NULL },
1532 { "-coords", "showCoords", XrmoptionNoArg, "True" },
1533 { "-xcoords", "showCoords", XrmoptionNoArg, "False" },
1535 { "-showJail", "showJail", XrmoptionSepArg, NULL },
1536 { "-jail", "showJail", XrmoptionNoArg, "1" },
1537 { "-sidejail", "showJail", XrmoptionNoArg, "2" },
1538 { "-xjail", "showJail", XrmoptionNoArg, "0" },
1540 { "-showThinking", "showThinking", XrmoptionSepArg, NULL },
1541 { "-thinking", "showThinking", XrmoptionNoArg, "True" },
1542 { "-xthinking", "showThinking", XrmoptionNoArg, "False" },
1543 { "-ponderNextMove", "ponderNextMove", XrmoptionSepArg, NULL },
1544 { "-ponder", "ponderNextMove", XrmoptionNoArg, "True" },
1545 { "-xponder", "ponderNextMove", XrmoptionNoArg, "False" },
1546 { "-periodicUpdates", "periodicUpdates", XrmoptionSepArg, NULL },
1547 { "-periodic", "periodicUpdates", XrmoptionNoArg, "True" },
1548 { "-xperiodic", "periodicUpdates", XrmoptionNoArg, "False" },
1549 { "-clockFont", "clockFont", XrmoptionSepArg, NULL },
1550 { "-coordFont", "coordFont", XrmoptionSepArg, NULL },
1551 { "-font", "font", XrmoptionSepArg, NULL },
1552 { "-ringBellAfterMoves", "ringBellAfterMoves", XrmoptionSepArg, NULL },
1553 { "-bell", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1554 { "-xbell", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1555 { "-movesound", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1556 { "-xmovesound", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1557 { "-autoCallFlag", "autoCallFlag", XrmoptionSepArg, NULL },
1558 { "-autoflag", "autoCallFlag", XrmoptionNoArg, "True" },
1559 { "-xautoflag", "autoCallFlag", XrmoptionNoArg, "False" },
1560 { "-autoFlipView", "autoFlipView", XrmoptionSepArg, NULL },
1561 { "-autoflip", "autoFlipView", XrmoptionNoArg, "True" },
1562 { "-xautoflip", "autoFlipView", XrmoptionNoArg, "False" },
1563 { "-autoObserve", "autoObserve", XrmoptionSepArg, NULL },
1564 { "-autobs", "autoObserve", XrmoptionNoArg, "True" },
1565 { "-xautobs", "autoObserve", XrmoptionNoArg, "False" },
1566 { "-autoComment", "autoComment", XrmoptionSepArg, NULL },
1567 { "-autocomm", "autoComment", XrmoptionNoArg, "True" },
1568 { "-xautocomm", "autoComment", XrmoptionNoArg, "False" },
1569 { "-getMoveList", "getMoveList", XrmoptionSepArg, NULL },
1570 { "-moves", "getMoveList", XrmoptionNoArg, "True" },
1571 { "-xmoves", "getMoveList", XrmoptionNoArg, "False" },
1573 { "-highlightDragging", "highlightDragging", XrmoptionSepArg, NULL },
1574 { "-highdrag", "highlightDragging", XrmoptionNoArg, "True" },
1575 { "-xhighdrag", "highlightDragging", XrmoptionNoArg, "False" },
1577 { "-highlightLastMove", "highlightLastMove", XrmoptionSepArg, NULL },
1578 { "-highlight", "highlightLastMove", XrmoptionNoArg, "True" },
1579 { "-xhighlight", "highlightLastMove", XrmoptionNoArg, "False" },
1580 { "-premove", "premove", XrmoptionSepArg, NULL },
1581 { "-pre", "premove", XrmoptionNoArg, "True" },
1582 { "-xpre", "premove", XrmoptionNoArg, "False" },
1583 { "-testLegality", "testLegality", XrmoptionSepArg, NULL },
1584 { "-legal", "testLegality", XrmoptionNoArg, "True" },
1585 { "-xlegal", "testLegality", XrmoptionNoArg, "False" },
1586 { "-flipView", "flipView", XrmoptionSepArg, NULL },
1587 { "-flip", "flipView", XrmoptionNoArg, "True" },
1588 { "-xflip", "flipView", XrmoptionNoArg, "False" },
1589 { "-cmail", "cmailGameName", XrmoptionSepArg, NULL },
1590 { "-alwaysPromoteToQueen", "alwaysPromoteToQueen",
1591 XrmoptionSepArg, NULL },
1592 { "-queen", "alwaysPromoteToQueen", XrmoptionNoArg, "True" },
1593 { "-xqueen", "alwaysPromoteToQueen", XrmoptionNoArg, "False" },
1594 { "-oldSaveStyle", "oldSaveStyle", XrmoptionSepArg, NULL },
1595 { "-oldsave", "oldSaveStyle", XrmoptionNoArg, "True" },
1596 { "-xoldsave", "oldSaveStyle", XrmoptionNoArg, "False" },
1597 { "-quietPlay", "quietPlay", XrmoptionSepArg, NULL },
1598 { "-quiet", "quietPlay", XrmoptionNoArg, "True" },
1599 { "-xquiet", "quietPlay", XrmoptionNoArg, "False" },
1600 { "-titleInWindow", "titleInWindow", XrmoptionSepArg, NULL },
1601 { "-title", "titleInWindow", XrmoptionNoArg, "True" },
1602 { "-xtitle", "titleInWindow", XrmoptionNoArg, "False" },
1604 { "-zippyTalk", "zippyTalk", XrmoptionSepArg, NULL },
1605 { "-zt", "zippyTalk", XrmoptionNoArg, "True" },
1606 { "-xzt", "zippyTalk", XrmoptionNoArg, "False" },
1607 { "-zippyPlay", "zippyPlay", XrmoptionSepArg, NULL },
1608 { "-zp", "zippyPlay", XrmoptionNoArg, "True" },
1609 { "-xzp", "zippyPlay", XrmoptionNoArg, "False" },
1610 { "-zippyLines", "zippyLines", XrmoptionSepArg, NULL },
1611 { "-zippyPinhead", "zippyPinhead", XrmoptionSepArg, NULL },
1612 { "-zippyPassword", "zippyPassword", XrmoptionSepArg, NULL },
1613 { "-zippyPassword2", "zippyPassword2", XrmoptionSepArg, NULL },
1614 { "-zippyWrongPassword", "zippyWrongPassword", XrmoptionSepArg, NULL },
1615 { "-zippyAcceptOnly", "zippyAcceptOnly", XrmoptionSepArg, NULL },
1616 { "-zippyUseI", "zippyUseI", XrmoptionSepArg, NULL },
1617 { "-zui", "zippyUseI", XrmoptionNoArg, "True" },
1618 { "-xzui", "zippyUseI", XrmoptionNoArg, "False" },
1619 { "-zippyBughouse", "zippyBughouse", XrmoptionSepArg, NULL },
1620 { "-zippyNoplayCrafty", "zippyNoplayCrafty", XrmoptionSepArg, NULL },
1621 { "-znc", "zippyNoplayCrafty", XrmoptionNoArg, "True" },
1622 { "-xznc", "zippyNoplayCrafty", XrmoptionNoArg, "False" },
1623 { "-zippyGameEnd", "zippyGameEnd", XrmoptionSepArg, NULL },
1624 { "-zippyGameStart", "zippyGameStart", XrmoptionSepArg, NULL },
1625 { "-zippyAdjourn", "zippyAdjourn", XrmoptionSepArg, NULL },
1626 { "-zadj", "zippyAdjourn", XrmoptionNoArg, "True" },
1627 { "-xzadj", "zippyAdjourn", XrmoptionNoArg, "False" },
1628 { "-zippyAbort", "zippyAbort", XrmoptionSepArg, NULL },
1629 { "-zab", "zippyAbort", XrmoptionNoArg, "True" },
1630 { "-xzab", "zippyAbort", XrmoptionNoArg, "False" },
1631 { "-zippyVariants", "zippyVariants", XrmoptionSepArg, NULL },
1632 { "-zippyMaxGames", "zippyMaxGames", XrmoptionSepArg, NULL },
1633 { "-zippyReplayTimeout", "zippyReplayTimeout", XrmoptionSepArg, NULL },
1634 { "-zippyShortGame", "zippyShortGame", XrmoptionSepArg, NULL },
1636 { "-flashCount", "flashCount", XrmoptionSepArg, NULL },
1637 { "-flash", "flashCount", XrmoptionNoArg, "3" },
1638 { "-xflash", "flashCount", XrmoptionNoArg, "0" },
1639 { "-flashRate", "flashRate", XrmoptionSepArg, NULL },
1640 { "-pixmapDirectory", "pixmapDirectory", XrmoptionSepArg, NULL },
1641 { "-msLoginDelay", "msLoginDelay", XrmoptionSepArg, NULL },
1642 { "-pixmap", "pixmapDirectory", XrmoptionSepArg, NULL },
1643 { "-colorizeMessages", "colorizeMessages", XrmoptionSepArg, NULL },
1644 { "-colorize", "colorizeMessages", XrmoptionNoArg, "True" },
1645 { "-xcolorize", "colorizeMessages", XrmoptionNoArg, "False" },
1646 { "-colorShout", "colorShout", XrmoptionSepArg, NULL },
1647 { "-colorSShout", "colorSShout", XrmoptionSepArg, NULL },
1648 { "-colorCShout", "colorSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1649 { "-colorChannel1", "colorChannel1", XrmoptionSepArg, NULL },
1650 { "-colorChannel", "colorChannel", XrmoptionSepArg, NULL },
1651 { "-colorKibitz", "colorKibitz", XrmoptionSepArg, NULL },
1652 { "-colorTell", "colorTell", XrmoptionSepArg, NULL },
1653 { "-colorChallenge", "colorChallenge", XrmoptionSepArg, NULL },
1654 { "-colorRequest", "colorRequest", XrmoptionSepArg, NULL },
1655 { "-colorSeek", "colorSeek", XrmoptionSepArg, NULL },
1656 { "-colorNormal", "colorNormal", XrmoptionSepArg, NULL },
1657 { "-soundProgram", "soundProgram", XrmoptionSepArg, NULL },
1658 { "-soundShout", "soundShout", XrmoptionSepArg, NULL },
1659 { "-soundSShout", "soundSShout", XrmoptionSepArg, NULL },
1660 { "-soundCShout", "soundSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1661 { "-soundChannel1", "soundChannel1", XrmoptionSepArg, NULL },
1662 { "-soundChannel", "soundChannel", XrmoptionSepArg, NULL },
1663 { "-soundKibitz", "soundKibitz", XrmoptionSepArg, NULL },
1664 { "-soundTell", "soundTell", XrmoptionSepArg, NULL },
1665 { "-soundChallenge", "soundChallenge", XrmoptionSepArg, NULL },
1666 { "-soundRequest", "soundRequest", XrmoptionSepArg, NULL },
1667 { "-soundSeek", "soundSeek", XrmoptionSepArg, NULL },
1668 { "-soundMove", "soundMove", XrmoptionSepArg, NULL },
1669 { "-soundIcsWin", "soundIcsWin", XrmoptionSepArg, NULL },
1670 { "-soundIcsLoss", "soundIcsLoss", XrmoptionSepArg, NULL },
1671 { "-soundIcsDraw", "soundIcsDraw", XrmoptionSepArg, NULL },
1672 { "-soundIcsUnfinished", "soundIcsUnfinished", XrmoptionSepArg, NULL },
1673 { "-soundIcsAlarm", "soundIcsAlarm", XrmoptionSepArg, NULL },
1674 { "-reuseFirst", "reuseFirst", XrmoptionSepArg, NULL },
1675 { "-reuseChessPrograms", "reuseFirst", XrmoptionSepArg, NULL }, /*compat*/
1676 { "-reuse", "reuseFirst", XrmoptionNoArg, "True" },
1677 { "-xreuse", "reuseFirst", XrmoptionNoArg, "False" },
1678 { "-reuseSecond", "reuseSecond", XrmoptionSepArg, NULL },
1679 { "-reuse2", "reuseSecond", XrmoptionNoArg, "True" },
1680 { "-xreuse2", "reuseSecond", XrmoptionNoArg, "False" },
1681 { "-animateMoving", "animateMoving", XrmoptionSepArg, NULL },
1682 { "-animate", "animateMoving", XrmoptionNoArg, "True" },
1683 { "-xanimate", "animateMoving", XrmoptionNoArg, "False" },
1684 { "-animateDragging", "animateDragging", XrmoptionSepArg, NULL },
1685 { "-drag", "animateDragging", XrmoptionNoArg, "True" },
1686 { "-xdrag", "animateDragging", XrmoptionNoArg, "False" },
1687 { "-animateSpeed", "animateSpeed", XrmoptionSepArg, NULL },
1688 { "-popupExitMessage", "popupExitMessage", XrmoptionSepArg, NULL },
1689 { "-exit", "popupExitMessage", XrmoptionNoArg, "True" },
1690 { "-xexit", "popupExitMessage", XrmoptionNoArg, "False" },
1691 { "-popupMoveErrors", "popupMoveErrors", XrmoptionSepArg, NULL },
1692 { "-popup", "popupMoveErrors", XrmoptionNoArg, "True" },
1693 { "-xpopup", "popupMoveErrors", XrmoptionNoArg, "False" },
1694 { "-fontSizeTolerance", "fontSizeTolerance", XrmoptionSepArg, NULL },
1695 { "-initialMode", "initialMode", XrmoptionSepArg, NULL },
1696 { "-mode", "initialMode", XrmoptionSepArg, NULL },
1697 { "-variant", "variant", XrmoptionSepArg, NULL },
1698 { "-firstProtocolVersion", "firstProtocolVersion", XrmoptionSepArg, NULL },
1699 { "-secondProtocolVersion","secondProtocolVersion",XrmoptionSepArg, NULL },
1700 { "-showButtonBar", "showButtonBar", XrmoptionSepArg, NULL },
1701 { "-buttons", "showButtonBar", XrmoptionNoArg, "True" },
1702 { "-xbuttons", "showButtonBar", XrmoptionNoArg, "False" },
1703 { "-lowTimeWarningColor", "lowTimeWarningColor", XrmoptionSepArg, NULL },
1704 { "-lowTimeWarning", "lowTimeWarning", XrmoptionSepArg, NULL },
1705 /* [AS,HR] New features */
1706 { "-firstScoreAbs", "firstScoreAbs", XrmoptionSepArg, NULL },
1707 { "-secondScoreAbs", "secondScoreAbs", XrmoptionSepArg, NULL },
1708 { "-pgnExtendedInfo", "pgnExtendedInfo", XrmoptionSepArg, NULL },
1709 { "-hideThinkingFromHuman", "hideThinkingFromHuman", XrmoptionSepArg, NULL },
1710 { "-adjudicateLossThreshold", "adjudicateLossThreshold", XrmoptionSepArg, NULL },
1711 { "-adjudicateDrawMoves", "adjudicateDrawMoves", XrmoptionSepArg, NULL },
1712 { "-pgnEventHeader", "pgnEventHeader", XrmoptionSepArg, NULL },
1713 { "-firstIsUCI", "firstIsUCI", XrmoptionSepArg, NULL },
1714 { "-secondIsUCI", "secondIsUCI", XrmoptionSepArg, NULL },
1715 { "-fUCI", "firstIsUCI", XrmoptionNoArg, "True" },
1716 { "-sUCI", "secondIsUCI", XrmoptionNoArg, "True" },
1717 { "-firstHasOwnBookUCI", "firstHasOwnBookUCI", XrmoptionSepArg, NULL },
1718 { "-secondHasOwnBookUCI", "secondHasOwnBookUCI", XrmoptionSepArg, NULL },
1719 { "-fNoOwnBookUCI", "firstHasOwnBookUCI", XrmoptionNoArg, "False" },
1720 { "-sNoOwnBookUCI", "secondHasOwnBookUCI", XrmoptionNoArg, "False" },
1721 { "-firstXBook", "firstHasOwnBookUCI", XrmoptionNoArg, "False" },
1722 { "-secondXBook", "secondHasOwnBookUCI", XrmoptionNoArg, "False" },
1723 { "-polyglotDir", "polyglotDir", XrmoptionSepArg, NULL },
1724 { "-usePolyglotBook", "usePolyglotBook", XrmoptionSepArg, NULL },
1725 { "-polyglotBook", "polyglotBook", XrmoptionSepArg, NULL },
1726 { "-defaultHashSize", "defaultHashSize", XrmoptionSepArg, NULL },
1727 { "-defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XrmoptionSepArg, NULL },
1728 { "-defaultPathEGTB", "defaultPathEGTB", XrmoptionSepArg, NULL },
1729 { "-defaultFrcPosition", "defaultFrcPosition", XrmoptionSepArg, NULL },
1730 { "-gameListTags", "gameListTags", XrmoptionSepArg, NULL },
1731 // [HGM] I am sure AS added many more options, but we have to fish them out, from the list in winboard.c
1733 /* [HGM,HR] User-selectable board size */
1734 { "-boardWidth", "boardWidth", XrmoptionSepArg, NULL },
1735 { "-boardHeight", "boardHeight", XrmoptionSepArg, NULL },
1736 { "-matchPause", "matchPause", XrmoptionSepArg, NULL },
1738 /* [HGM] new arguments of 4.3.xx. All except first three are back-end options, which should work immediately */
1739 { "-holdingsSize", "holdingsSize", XrmoptionSepArg, NULL }, // requires extensive front-end changes to work
1740 { "-flipBlack", "flipBlack", XrmoptionSepArg, NULL }, // requires front-end changes to work
1741 { "-allWhite", "allWhite", XrmoptionSepArg, NULL }, // requires front-end changes to work
1742 { "-pieceToCharTable", "pieceToCharTable", XrmoptionSepArg, NULL },
1743 { "-alphaRank", "alphaRank", XrmoptionSepArg, NULL },
1744 { "-testClaims", "testClaims", XrmoptionSepArg, NULL },
1745 { "-checkMates", "checkMates", XrmoptionSepArg, NULL },
1746 { "-materialDraws", "materialDraws", XrmoptionSepArg, NULL },
1747 { "-trivialDraws", "trivialDraws", XrmoptionSepArg, NULL },
1748 { "-ruleMoves", "ruleMoves", XrmoptionSepArg, NULL },
1749 { "-repeatsToDraw", "repeatsToDraw", XrmoptionSepArg, NULL },
1750 { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL },
1751 { "-userName", "userName", XrmoptionSepArg, NULL },
1752 { "-autoKibitz", "autoKibitz", XrmoptionNoArg, "True" },
1753 { "-firstTimeOdds", "firstTimeOdds", XrmoptionSepArg, NULL },
1754 { "-secondTimeOdds", "secondTimeOdds", XrmoptionSepArg, NULL },
1755 { "-timeOddsMode", "timeOddsMode", XrmoptionSepArg, NULL },
1756 { "-firstAccumulateTC", "firstAccumulateTC", XrmoptionSepArg, NULL },
1757 { "-secondAccumulateTC", "secondAccumulateTC", XrmoptionSepArg, NULL },
1758 { "-firstNPS", "firstNPS", XrmoptionSepArg, NULL },
1759 { "-secondNPS", "secondNPS", XrmoptionSepArg, NULL },
1760 { "-serverMoves", "serverMoves", XrmoptionSepArg, NULL },
1761 { "-serverPause", "serverPause", XrmoptionSepArg, NULL },
1762 { "-suppressLoadMoves", "suppressLoadMoves", XrmoptionSepArg, NULL },
1763 { "-egtFormats", "egtFormats", XrmoptionSepArg, NULL },
1764 { "-userName", "userName", XrmoptionSepArg, NULL },
1765 { "-smpCores", "smpCores", XrmoptionSepArg, NULL },
1766 { "-sameColorGames", "sameColorGames", XrmoptionSepArg, NULL },
1767 { "-rewindIndex", "rewindIndex", XrmoptionSepArg, NULL },
1768 { "-niceEngines", "niceEngines", XrmoptionSepArg, NULL },
1769 { "-delayBeforeQuit", "delayBeforeQuit", XrmoptionSepArg, NULL },
1770 { "-delayAfterQuit", "delayAfterQuit", XrmoptionSepArg, NULL },
1771 { "-nameOfDebugFile", "nameOfDebugFile", XrmoptionSepArg, NULL },
1772 { "-debugFile", "nameOfDebugFile", XrmoptionSepArg, NULL },
1773 { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL },
1774 { "-noGUI", "noGUI", XrmoptionNoArg, "True" },
1775 { "-firstOptions", "firstOptions", XrmoptionSepArg, NULL },
1776 { "-secondOptions", "secondOptions", XrmoptionSepArg, NULL },
1777 { "-firstNeedsNoncompliantFEN", "firstNeedsNoncompliantFEN", XrmoptionSepArg, NULL },
1778 { "-secondNeedsNoncompliantFEN", "secondNeedsNoncompliantFEN", XrmoptionSepArg, NULL },
1779 { "-keepAlive", "keepAlive", XrmoptionSepArg, NULL },
1780 { "-forceIllegalMoves", "forceIllegalMoves", XrmoptionNoArg, "True" },
1781 { "-keepLineBreaksICS", "keepLineBreaksICS", XrmoptionSepArg, NULL },
1785 XtActionsRec boardActions[] = {
1786 { "HandleUserMove", HandleUserMove },
1787 { "AnimateUserMove", AnimateUserMove },
1788 { "FileNameAction", FileNameAction },
1789 { "AskQuestionProc", AskQuestionProc },
1790 { "AskQuestionReplyAction", AskQuestionReplyAction },
1791 { "PieceMenuPopup", PieceMenuPopup },
1792 // { "WhiteClock", WhiteClock },
1793 // { "BlackClock", BlackClock },
1794 { "Iconify", Iconify },
1795 { "LoadSelectedProc", LoadSelectedProc },
1796 { "LoadPositionProc", LoadPositionProc },
1797 // { "LoadNextPositionProc", LoadNextPositionProc },
1798 // { "LoadPrevPositionProc", LoadPrevPositionProc },
1799 // { "ReloadPositionProc", ReloadPositionProc },
1800 { "CopyPositionProc", CopyPositionProc },
1801 { "PastePositionProc", PastePositionProc },
1802 { "CopyGameProc", CopyGameProc },
1803 { "PasteGameProc", PasteGameProc },
1804 { "SaveGameProc", SaveGameProc },
1805 { "SavePositionProc", SavePositionProc },
1806 { "MailMoveProc", MailMoveProc },
1807 { "ReloadCmailMsgProc", ReloadCmailMsgProc },
1808 // { "MachineWhiteProc", MachineWhiteProc },
1809 // { "MachineBlackProc", MachineBlackProc },
1810 { "AnalysisModeProc", AnalyzeModeProc },
1811 { "AnalyzeFileProc", AnalyzeFileProc },
1812 // { "TwoMachinesProc", TwoMachinesProc },
1813 // { "IcsClientProc", IcsClientProc },
1814 { "EditGameProc", EditGameProc },
1815 { "EditPositionProc", EditPositionProc },
1816 { "TrainingProc", EditPositionProc },
1817 { "EngineOutputProc", EngineOutputProc}, // [HGM] Winboard_x engine-output window
1818 { "ShowGameListProc", ShowGameListProc },
1819 // { "ShowMoveListProc", HistoryShowProc},
1820 { "EditTagsProc", EditCommentProc },
1821 { "EditCommentProc", EditCommentProc },
1822 { "IcsAlarmProc", IcsAlarmProc },
1823 { "IcsInputBoxProc", IcsInputBoxProc },
1824 // { "AcceptProc", AcceptProc },
1825 // { "DeclineProc", DeclineProc },
1826 // { "RematchProc", RematchProc },
1827 // { "CallFlagProc", CallFlagProc },
1828 // { "DrawProc", DrawProc },
1829 // { "AdjournProc", AdjournProc },
1830 // { "AbortProc", AbortProc },
1831 // { "ResignProc", ResignProc },
1832 // { "AdjuWhiteProc", AdjuWhiteProc },
1833 // { "AdjuBlackProc", AdjuBlackProc },
1834 // { "AdjuDrawProc", AdjuDrawProc },
1835 { "EnterKeyProc", EnterKeyProc },
1836 // { "StopObservingProc", StopObservingProc },
1837 // { "StopExaminingProc", StopExaminingProc },
1838 // { "BackwardProc", BackwardProc },
1839 // { "ForwardProc", ForwardProc },
1840 // { "ToStartProc", ToStartProc },
1841 // { "ToEndProc", ToEndProc },
1842 // { "RevertProc", RevertProc },
1843 // { "TruncateGameProc", TruncateGameProc },
1844 // { "MoveNowProc", MoveNowProc },
1845 // { "RetractMoveProc", RetractMoveProc },
1846 { "AlwaysQueenProc", AlwaysQueenProc },
1847 { "AnimateDraggingProc", AnimateDraggingProc },
1848 { "AnimateMovingProc", AnimateMovingProc },
1849 // { "AutoflagProc", AutoflagProc },
1850 // { "AutoflipProc", AutoflipProc },
1851 { "AutobsProc", AutobsProc },
1852 { "AutoraiseProc", AutoraiseProc },
1853 { "AutosaveProc", AutosaveProc },
1854 { "BlindfoldProc", BlindfoldProc },
1855 { "FlashMovesProc", FlashMovesProc },
1856 // { "FlipViewProc", FlipViewProc },
1857 // { "GetMoveListProc", GetMoveListProc },
1859 { "HighlightDraggingProc", HighlightDraggingProc },
1861 { "HighlightLastMoveProc", HighlightLastMoveProc },
1862 { "IcsAlarmProc", IcsAlarmProc },
1863 { "MoveSoundProc", MoveSoundProc },
1864 { "OldSaveStyleProc", OldSaveStyleProc },
1865 { "PeriodicUpdatesProc", PeriodicUpdatesProc },
1866 { "PonderNextMoveProc", PonderNextMoveProc },
1867 { "PopupExitMessageProc", PopupExitMessageProc },
1868 { "PopupMoveErrorsProc", PopupMoveErrorsProc },
1869 { "PremoveProc", PremoveProc },
1870 { "QuietPlayProc", QuietPlayProc },
1871 // { "ShowThinkingProc", ShowThinkingProc },
1872 // { "HideThinkingProc", HideThinkingProc },
1873 { "TestLegalityProc", TestLegalityProc },
1874 // { "InfoProc", InfoProc },
1875 // { "ManProc", ManProc },
1876 // { "HintProc", HintProc },
1877 // { "BookProc", BookProc },
1878 { "AboutGameProc", AboutGameProc },
1879 { "DebugProc", DebugProc },
1880 { "NothingProc", NothingProc },
1881 { "CommentPopDown", (XtActionProc) CommentPopDown },
1882 { "EditCommentPopDown", (XtActionProc) EditCommentPopDown },
1883 { "TagsPopDown", (XtActionProc) TagsPopDown },
1884 { "ErrorPopDown", (XtActionProc) ErrorPopDown },
1885 { "ICSInputBoxPopDown", (XtActionProc) ICSInputBoxPopDown },
1886 { "EngineOutputPopDown", (XtActionProc) EngineOutputPopDown },
1887 { "FileNamePopDown", (XtActionProc) FileNamePopDown },
1888 { "AskQuestionPopDown", (XtActionProc) AskQuestionPopDown },
1889 { "GameListPopDown", (XtActionProc) GameListPopDown },
1890 { "PromotionPopDown", (XtActionProc) PromotionPopDown },
1891 // { "HistoryPopDown", (XtActionProc) HistoryPopDown },
1892 { "EngineOutputPopDown", (XtActionProc) EngineOutputPopDown },
1893 { "ShufflePopDown", (XtActionProc) ShufflePopDown },
1894 { "EnginePopDown", (XtActionProc) EnginePopDown },
1895 { "UciPopDown", (XtActionProc) UciPopDown },
1896 { "TimeControlPopDown", (XtActionProc) TimeControlPopDown },
1897 { "NewVariantPopDown", (XtActionProc) NewVariantPopDown },
1898 { "SettingsPopDown", (XtActionProc) SettingsPopDown },
1902 char ICSInputTranslations[] =
1903 "<Key>Return: EnterKeyProc() \n";
1905 String xboardResources[] = {
1906 "*fileName*value.translations: #override\\n <Key>Return: FileNameAction()",
1907 "*question*value.translations: #override\\n <Key>Return: AskQuestionReplyAction()",
1908 "*errorpopup*translations: #override\\n <Key>Return: ErrorPopDown()",
1912 static char *cnames[9] = { "black", "red", "green", "yellow", "blue",
1913 "magenta", "cyan", "white" };
1917 TextColors textColors[(int)NColorClasses];
1919 /* String is: "fg, bg, attr". Which is 0, 1, 2 */
1921 parse_color(str, which)
1925 char *p, buf[100], *d;
1928 if (strlen(str) > 99) /* watch bounds on buf */
1933 for (i=0; i<which; ++i) {
1940 /* Could be looking at something like:
1942 .. in which case we want to stop on a comma also */
1943 while (*p && *p != ',' && !isalpha(*p) && !isdigit(*p))
1947 return -1; /* Use default for empty field */
1950 if (which == 2 || isdigit(*p))
1953 while (*p && isalpha(*p))
1958 for (i=0; i<8; ++i) {
1959 if (!StrCaseCmp(buf, cnames[i]))
1960 return which? (i+40) : (i+30);
1962 if (!StrCaseCmp(buf, "default")) return -1;
1964 fprintf(stderr, _("%s: unrecognized color %s\n"), programName, buf);
1969 parse_cpair(cc, str)
1973 if ((textColors[(int)cc].fg=parse_color(str, 0)) == -2) {
1974 fprintf(stderr, _("%s: can't parse foreground color in `%s'\n"),
1979 /* bg and attr are optional */
1980 textColors[(int)cc].bg = parse_color(str, 1);
1981 if ((textColors[(int)cc].attr = parse_color(str, 2)) < 0) {
1982 textColors[(int)cc].attr = 0;
1988 /* Arrange to catch delete-window events */
1989 Atom wm_delete_window;
1991 CatchDeleteWindow(Widget w, String procname)
1994 XSetWMProtocols(xDisplay, XtWindow(w), &wm_delete_window, 1);
1995 snprintf(buf, sizeof(buf), "<Message>WM_PROTOCOLS: %s() \n", procname);
1996 XtAugmentTranslations(w, XtParseTranslationTable(buf));
2002 /* this should raise the board to the top */
2003 gtk_window_present(GTK_WINDOW(GUI_Window));
2007 #define BoardSize int
2008 void InitDrawingSizes(BoardSize boardSize, int flags)
2009 { // [HGM] resize is functional now, but for board format changes only (nr of ranks, files)
2010 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
2012 XtGeometryResult gres;
2015 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2016 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2018 timerWidth = (boardWidth - sep) / 2;
2020 if (appData.titleInWindow)
2025 w = boardWidth - 2*bor;
2029 w = boardWidth - w - sep - 2*bor - 2; // WIDTH_FUDGE
2033 if(!formWidget) return;
2036 * Inhibit shell resizing.
2039 // [HGM] pieces: tailor piece bitmaps to needs of specific variant
2042 for(i=0; i<4; i++) {
2044 for(p=0; p<=(int)WhiteKing; p++)
2045 xpmPieceBitmap[i][p] = xpmPieceBitmap2[i][p]; // defaults
2046 if(gameInfo.variant == VariantShogi) {
2047 xpmPieceBitmap[i][(int)WhiteCannon] = xpmPieceBitmap2[i][(int)WhiteKing+1];
2048 xpmPieceBitmap[i][(int)WhiteNightrider] = xpmPieceBitmap2[i][(int)WhiteKing+2];
2049 xpmPieceBitmap[i][(int)WhiteSilver] = xpmPieceBitmap2[i][(int)WhiteKing+3];
2050 xpmPieceBitmap[i][(int)WhiteGrasshopper] = xpmPieceBitmap2[i][(int)WhiteKing+4];
2051 xpmPieceBitmap[i][(int)WhiteQueen] = xpmPieceBitmap2[i][(int)WhiteLance];
2054 if(gameInfo.variant == VariantGothic) {
2055 xpmPieceBitmap[i][(int)WhiteMarshall] = xpmPieceBitmap2[i][(int)WhiteSilver];
2059 // [HGM] why are thee ximMasks used at all? the ximPieceBitmaps seem to be never used!
2060 for(p=0; p<=(int)WhiteKing; p++)
2061 ximMaskPm[p] = ximMaskPm2[p]; // defaults
2062 if(gameInfo.variant == VariantShogi) {
2063 ximMaskPm[(int)WhiteCannon] = ximMaskPm2[(int)WhiteKing+1];
2064 ximMaskPm[(int)WhiteNightrider] = ximMaskPm2[(int)WhiteKing+2];
2065 ximMaskPm[(int)WhiteSilver] = ximMaskPm2[(int)WhiteKing+3];
2066 ximMaskPm[(int)WhiteGrasshopper] = ximMaskPm2[(int)WhiteKing+4];
2067 ximMaskPm[(int)WhiteQueen] = ximMaskPm2[(int)WhiteLance];
2070 if(gameInfo.variant == VariantGothic) {
2071 ximMaskPm[(int)WhiteMarshall] = ximMaskPm2[(int)WhiteSilver];
2077 for(i=0; i<2; i++) {
2079 for(p=0; p<=(int)WhiteKing; p++)
2080 pieceBitmap[i][p] = pieceBitmap2[i][p]; // defaults
2081 if(gameInfo.variant == VariantShogi) {
2082 pieceBitmap[i][(int)WhiteCannon] = pieceBitmap2[i][(int)WhiteKing+1];
2083 pieceBitmap[i][(int)WhiteNightrider] = pieceBitmap2[i][(int)WhiteKing+2];
2084 pieceBitmap[i][(int)WhiteSilver] = pieceBitmap2[i][(int)WhiteKing+3];
2085 pieceBitmap[i][(int)WhiteGrasshopper] = pieceBitmap2[i][(int)WhiteKing+4];
2086 pieceBitmap[i][(int)WhiteQueen] = pieceBitmap2[i][(int)WhiteLance];
2089 if(gameInfo.variant == VariantGothic) {
2090 pieceBitmap[i][(int)WhiteMarshall] = pieceBitmap2[i][(int)WhiteSilver];
2100 void EscapeExpand(char *p, char *q)
2101 { // [HGM] initstring: routine to shape up string arguments
2102 while(*p++ = *q++) if(p[-1] == '\\')
2104 case 'n': p[-1] = '\n'; break;
2105 case 'r': p[-1] = '\r'; break;
2106 case 't': p[-1] = '\t'; break;
2107 case '\\': p[-1] = '\\'; break;
2108 case 0: *p = 0; return;
2109 default: p[-1] = q[-1]; break;
2118 int i, j, clockFontPxlSize, coordFontPxlSize, fontPxlSize;
2119 XSetWindowAttributes window_attributes;
2121 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
2122 XrmValue vFrom, vTo;
2123 XtGeometryResult gres;
2126 int forceMono = False;
2130 // [HGM] before anything else, expand any indirection files amongst options
2131 char *argvCopy[1000]; // 1000 seems enough
2132 char newArgs[10000]; // holds actual characters
2135 srandom(time(0)); // [HGM] book: make random truly random
2138 for(i=0; i<argc; i++) {
2139 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2140 //fprintf(stderr, "arg %s\n", argv[i]);
2141 if(argv[i][0] != '@') argvCopy[j++] = argv[i]; else {
2143 FILE *f = fopen(argv[i]+1, "rb");
2144 if(f == NULL) { fprintf(stderr, _("ignore %s\n"), argv[i]); continue; } // do not expand non-existing
2145 argvCopy[j++] = newArgs + k; // get ready for first argument from file
2146 while((c = fgetc(f)) != EOF) { // each line of file inserts 1 argument in the list
2148 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2149 newArgs[k++] = 0; // terminate current arg
2150 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2151 argvCopy[j++] = newArgs + k; // get ready for next
2153 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2167 setbuf(stdout, NULL);
2168 setbuf(stderr, NULL);
2171 programName = strrchr(argv[0], '/');
2172 if (programName == NULL)
2173 programName = argv[0];
2178 XtSetLanguageProc(NULL, NULL, NULL);
2179 bindtextdomain(PACKAGE, LOCALEDIR);
2180 textdomain(PACKAGE);
2184 XtAppInitialize(&appContext, "XBoard", shellOptions,
2185 XtNumber(shellOptions),
2186 &argc, argv, xboardResources, NULL, 0);
2189 gtk_init (&argc, &argv);
2191 /* parse glade file to build widgets */
2193 builder = gtk_builder_new ();
2194 gtk_builder_add_from_file (builder, "gtk-interface.xml", NULL);
2196 /* test if everything worked ok */
2198 GUI_Window = GTK_WIDGET (gtk_builder_get_object (builder, "MainWindow"));
2199 if(!GUI_Window) printf("Error: gtk_builder didn't work!\n");
2201 GUI_History = GTK_WIDGET (gtk_builder_get_object (builder, "MoveHistory"));
2202 if(!GUI_History) printf("Error: gtk_builder didn't work!\n");
2204 GUI_Menubar = GTK_WIDGET (gtk_builder_get_object (builder, "MenuBar"));
2205 if(!GUI_Menubar) printf("Error: gtk_builder didn't work!\n");
2206 GUI_Timer = GTK_WIDGET (gtk_builder_get_object (builder, "Timer"));
2207 if(!GUI_Timer) printf("Error: gtk_builder didn't work!\n");
2208 GUI_Buttonbar = GTK_WIDGET (gtk_builder_get_object (builder, "ButtonBar"));
2209 if(!GUI_Buttonbar) printf("Error: gtk_builder didn't work!\n");
2210 GUI_Board = GTK_WIDGET (gtk_builder_get_object (builder, "Board"));
2211 if(!GUI_Board) printf("Error: gtk_builder didn't work!\n");
2213 GUI_Whiteclock = GTK_WIDGET (gtk_builder_get_object (builder, "WhiteClock"));
2214 if(!GUI_Whiteclock) printf("Error: gtk_builder didn't work!\n");
2216 GUI_Blackclock = GTK_WIDGET (gtk_builder_get_object (builder, "BlackClock"));
2217 if(!GUI_Blackclock) printf("Error: gtk_builder didn't work!\n");
2219 LIST_MoveHistory = GTK_LIST_STORE (gtk_builder_get_object (builder, "MoveHistoryStore"));
2220 if(!LIST_MoveHistory) printf("Error: gtk_builder didn't work!\n");
2223 gtk_builder_connect_signals (builder, NULL);
2225 // don't unref the builder, since we use it to get references to widgets
2226 // g_object_unref (G_OBJECT (builder));
2228 /* end parse glade file */
2232 fprintf(stderr, _("%s: unrecognized argument %s\n"),
2233 programName, argv[1]);
2235 fprintf(stderr, "Recognized options:\n");
2236 for(i = 0; i < XtNumber(shellOptions); i++)
2238 /* print first column */
2239 j = fprintf(stderr, " %s%s", shellOptions[i].option,
2240 (shellOptions[i].argKind == XrmoptionSepArg
2242 /* print second column and end line */
2243 if (++i < XtNumber(shellOptions))
2245 fprintf(stderr, "%*c%s%s\n", 40 - j, ' ',
2246 shellOptions[i].option,
2247 (shellOptions[i].argKind == XrmoptionSepArg
2252 fprintf(stderr, "\n");
2259 if (p == NULL) p = "/tmp";
2260 i = strlen(p) + strlen("/.xboardXXXXXx.pgn") + 1;
2261 gameCopyFilename = (char*) malloc(i);
2262 gamePasteFilename = (char*) malloc(i);
2263 snprintf(gameCopyFilename,i, "%s/.xboard%05uc.pgn", p, getpid());
2264 snprintf(gamePasteFilename,i, "%s/.xboard%05up.pgn", p, getpid());
2266 XtGetApplicationResources(shellWidget, (XtPointer) &appData,
2267 clientResources, XtNumber(clientResources),
2270 { // [HGM] initstring: kludge to fix bad bug. expand '\n' characters in init string and computer string.
2271 static char buf[MSG_SIZ];
2272 EscapeExpand(buf, appData.initString);
2273 appData.initString = strdup(buf);
2274 EscapeExpand(buf, appData.secondInitString);
2275 appData.secondInitString = strdup(buf);
2276 EscapeExpand(buf, appData.firstComputerString);
2277 appData.firstComputerString = strdup(buf);
2278 EscapeExpand(buf, appData.secondComputerString);
2279 appData.secondComputerString = strdup(buf);
2282 if ((chessDir = (char *) getenv("CHESSDIR")) == NULL) {
2285 if (chdir(chessDir) != 0) {
2286 fprintf(stderr, _("%s: can't cd to CHESSDIR: "), programName);
2292 if (appData.debugMode && appData.nameOfDebugFile && strcmp(appData.nameOfDebugFile, "stderr")) {
2293 /* [DM] debug info to file [HGM] make the filename a command-line option, and allow it to remain stderr */
2294 if ((debugFP = fopen(appData.nameOfDebugFile, "w")) == NULL) {
2295 printf(_("Failed to open file '%s'\n"), appData.nameOfDebugFile);
2298 setbuf(debugFP, NULL);
2301 /* [HGM,HR] make sure board size is acceptable */
2302 if(appData.NrFiles > BOARD_SIZE ||
2303 appData.NrRanks > BOARD_SIZE )
2304 DisplayFatalError(_("Recompile with BOARD_SIZE > 12, to support this size"), 0, 2);
2307 /* This feature does not work; animation needs a rewrite */
2308 appData.highlightDragging = FALSE;
2312 xDisplay = XtDisplay(shellWidget);
2313 xScreen = DefaultScreen(xDisplay);
2314 wm_delete_window = XInternAtom(xDisplay, "WM_DELETE_WINDOW", True);
2316 gameInfo.variant = StringToVariant(appData.variant);
2317 InitPosition(FALSE);
2319 /* calc board size */
2320 if (isdigit(appData.boardSize[0]))
2322 i = sscanf(appData.boardSize, "%d,%d,%d,%d,%d,%d,%d", &squareSize,
2323 &lineGap, &clockFontPxlSize, &coordFontPxlSize,
2324 &fontPxlSize, &smallLayout, &tinyLayout);
2327 fprintf(stderr, _("%s: bad boardSize syntax %s\n"),
2328 programName, appData.boardSize);
2333 /* Find some defaults; use the nearest known size */
2334 SizeDefaults *szd, *nearest;
2335 int distance = 99999;
2336 nearest = szd = sizeDefaults;
2337 while (szd->name != NULL)
2339 if (abs(szd->squareSize - squareSize) < distance)
2342 distance = abs(szd->squareSize - squareSize);
2343 if (distance == 0) break;
2347 if (i < 2) lineGap = nearest->lineGap;
2348 if (i < 3) clockFontPxlSize = nearest->clockFontPxlSize;
2349 if (i < 4) coordFontPxlSize = nearest->coordFontPxlSize;
2350 if (i < 5) fontPxlSize = nearest->fontPxlSize;
2351 if (i < 6) smallLayout = nearest->smallLayout;
2352 if (i < 7) tinyLayout = nearest->tinyLayout;
2357 SizeDefaults *szd = sizeDefaults;
2358 if (*appData.boardSize == NULLCHAR)
2360 while (DisplayWidth(xDisplay, xScreen) < szd->minScreenSize
2361 || DisplayHeight(xDisplay, xScreen) < szd->minScreenSize)
2365 if (szd->name == NULL) szd--;
2369 while (szd->name != NULL
2370 && StrCaseCmp(szd->name, appData.boardSize) != 0)
2372 if (szd->name == NULL)
2374 fprintf(stderr, _("%s: unrecognized boardSize name %s\n"),
2375 programName, appData.boardSize);
2379 squareSize = szd->squareSize;
2380 lineGap = szd->lineGap;
2381 clockFontPxlSize = szd->clockFontPxlSize;
2382 coordFontPxlSize = szd->coordFontPxlSize;
2383 fontPxlSize = szd->fontPxlSize;
2384 smallLayout = szd->smallLayout;
2385 tinyLayout = szd->tinyLayout;
2387 /* end figuring out what size to use */
2389 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2390 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2393 * Determine what fonts to use.
2395 appData.clockFont = FindFont(appData.clockFont, clockFontPxlSize);
2396 clockFontID = XLoadFont(xDisplay, appData.clockFont);
2397 clockFontStruct = XQueryFont(xDisplay, clockFontID);
2398 appData.coordFont = FindFont(appData.coordFont, coordFontPxlSize);
2399 coordFontID = XLoadFont(xDisplay, appData.coordFont);
2400 coordFontStruct = XQueryFont(xDisplay, coordFontID);
2401 appData.font = FindFont(appData.font, fontPxlSize);
2402 countFontID = XLoadFont(xDisplay, appData.coordFont); // [HGM] holdings
2403 countFontStruct = XQueryFont(xDisplay, countFontID);
2404 // appData.font = FindFont(appData.font, fontPxlSize);
2406 xdb = XtDatabase(xDisplay);
2407 XrmPutStringResource(&xdb, "*font", appData.font);
2410 * Detect if there are not enough colors available and adapt.
2412 if (DefaultDepth(xDisplay, xScreen) <= 2) {
2413 appData.monoMode = True;
2416 if (!appData.monoMode) {
2417 vFrom.addr = (caddr_t) appData.lightSquareColor;
2418 vFrom.size = strlen(appData.lightSquareColor);
2419 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2420 if (vTo.addr == NULL) {
2421 appData.monoMode = True;
2424 lightSquareColor = *(Pixel *) vTo.addr;
2427 if (!appData.monoMode) {
2428 vFrom.addr = (caddr_t) appData.darkSquareColor;
2429 vFrom.size = strlen(appData.darkSquareColor);
2430 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2431 if (vTo.addr == NULL) {
2432 appData.monoMode = True;
2435 darkSquareColor = *(Pixel *) vTo.addr;
2438 if (!appData.monoMode) {
2439 vFrom.addr = (caddr_t) appData.whitePieceColor;
2440 vFrom.size = strlen(appData.whitePieceColor);
2441 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2442 if (vTo.addr == NULL) {
2443 appData.monoMode = True;
2446 whitePieceColor = *(Pixel *) vTo.addr;
2449 if (!appData.monoMode) {
2450 vFrom.addr = (caddr_t) appData.blackPieceColor;
2451 vFrom.size = strlen(appData.blackPieceColor);
2452 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2453 if (vTo.addr == NULL) {
2454 appData.monoMode = True;
2457 blackPieceColor = *(Pixel *) vTo.addr;
2461 if (!appData.monoMode) {
2462 vFrom.addr = (caddr_t) appData.highlightSquareColor;
2463 vFrom.size = strlen(appData.highlightSquareColor);
2464 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2465 if (vTo.addr == NULL) {
2466 appData.monoMode = True;
2469 highlightSquareColor = *(Pixel *) vTo.addr;
2473 if (!appData.monoMode) {
2474 vFrom.addr = (caddr_t) appData.premoveHighlightColor;
2475 vFrom.size = strlen(appData.premoveHighlightColor);
2476 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2477 if (vTo.addr == NULL) {
2478 appData.monoMode = True;
2481 premoveHighlightColor = *(Pixel *) vTo.addr;
2486 fprintf(stderr, _("%s: too few colors available; trying monochrome mode\n"),
2489 if (appData.bitmapDirectory == NULL ||
2490 appData.bitmapDirectory[0] == NULLCHAR)
2491 appData.bitmapDirectory = DEF_BITMAP_DIR;
2494 if (appData.lowTimeWarning && !appData.monoMode) {
2495 vFrom.addr = (caddr_t) appData.lowTimeWarningColor;
2496 vFrom.size = strlen(appData.lowTimeWarningColor);
2497 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2498 if (vTo.addr == NULL)
2499 appData.monoMode = True;
2501 lowTimeWarningColor = *(Pixel *) vTo.addr;
2504 if (appData.monoMode && appData.debugMode) {
2505 fprintf(stderr, _("white pixel = 0x%lx, black pixel = 0x%lx\n"),
2506 (unsigned long) XWhitePixel(xDisplay, xScreen),
2507 (unsigned long) XBlackPixel(xDisplay, xScreen));
2510 if (parse_cpair(ColorShout, appData.colorShout) < 0 ||
2511 parse_cpair(ColorSShout, appData.colorSShout) < 0 ||
2512 parse_cpair(ColorChannel1, appData.colorChannel1) < 0 ||
2513 parse_cpair(ColorChannel, appData.colorChannel) < 0 ||
2514 parse_cpair(ColorKibitz, appData.colorKibitz) < 0 ||
2515 parse_cpair(ColorTell, appData.colorTell) < 0 ||
2516 parse_cpair(ColorChallenge, appData.colorChallenge) < 0 ||
2517 parse_cpair(ColorRequest, appData.colorRequest) < 0 ||
2518 parse_cpair(ColorSeek, appData.colorSeek) < 0 ||
2519 parse_cpair(ColorNormal, appData.colorNormal) < 0)
2521 if (appData.colorize) {
2523 _("%s: can't parse color names; disabling colorization\n"),
2526 appData.colorize = FALSE;
2528 textColors[ColorNone].fg = textColors[ColorNone].bg = -1;
2529 textColors[ColorNone].attr = 0;
2531 // XtAppAddActions(appContext, boardActions, XtNumber(boardActions));
2537 layoutName = "tinyLayout";
2538 } else if (smallLayout) {
2539 layoutName = "smallLayout";
2541 layoutName = "normalLayout";
2544 if (appData.titleInWindow) {
2545 /* todo check what this appdata does */
2548 if (appData.showButtonBar) {
2549 /* TODO hide button bar if requested */
2553 if (appData.titleInWindow)
2558 if (appData.showButtonBar)
2565 if (appData.showButtonBar)
2575 /* set some checkboxes in the menu according to appData */
2577 if (appData.alwaysPromoteToQueen)
2578 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Always Queen")),TRUE);
2580 if (appData.animateDragging)
2581 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Animate Dragging")),TRUE);
2583 if (appData.animate)
2584 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Animate Moving")),TRUE);
2586 if (appData.autoComment)
2587 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Comment")),TRUE);
2589 if (appData.autoCallFlag)
2590 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Flag")),TRUE);
2592 if (appData.autoFlipView)
2593 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Flip View")),TRUE);
2595 if (appData.autoObserve)
2596 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Observe")),TRUE);
2598 if (appData.autoRaiseBoard)
2599 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Raise Board")),TRUE);
2601 if (appData.autoSaveGames)
2602 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Save")),TRUE);
2604 if (appData.saveGameFile[0] != NULLCHAR)
2606 /* Can't turn this off from menu */
2607 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Save")),TRUE);
2608 gtk_action_set_sensitive(GTK_ACTION (gtk_builder_get_object (builder, "menuOptions.Auto Save")),FALSE);
2611 if (appData.blindfold)
2612 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Blindfold")),TRUE);
2614 if (appData.flashCount > 0)
2615 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Flash Moves")),TRUE);
2617 if (appData.getMoveList)
2618 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Get Move List")),TRUE);
2621 if (appData.highlightDragging)
2622 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Highlight Dragging")),TRUE);
2625 if (appData.highlightLastMove)
2626 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Highlight Last Move")),TRUE);
2628 if (appData.icsAlarm)
2629 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.ICS Alarm")),TRUE);
2631 if (appData.ringBellAfterMoves)
2632 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Move Sound")),TRUE);
2634 if (appData.oldSaveStyle)
2635 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Old Save Style")),TRUE);
2637 if (appData.periodicUpdates)
2638 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Periodic Updates")),TRUE);
2640 if (appData.ponderNextMove)
2641 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Ponder Next Move")),TRUE);
2643 if (appData.popupExitMessage)
2644 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Popup Exit Message")),TRUE);
2646 if (appData.popupMoveErrors)
2647 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Popup Move Errors")),TRUE);
2649 if (appData.premove)
2650 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Premove")),TRUE);
2652 if (appData.quietPlay)
2653 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Quit Play")),TRUE);
2655 if (appData.showCoords)
2656 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Show Coords")),TRUE);
2658 if (appData.showThinking)
2659 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Show Thinking")),TRUE);
2661 if (appData.testLegality)
2662 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Test Legality")),TRUE);
2664 /* end setting check boxes */
2666 /* load square colors */
2667 SVGLightSquare = load_pixbuf("svg/LightSquare.svg",squareSize);
2668 SVGDarkSquare = load_pixbuf("svg/DarkSquare.svg",squareSize);
2669 SVGNeutralSquare = load_pixbuf("svg/NeutralSquare.svg",squareSize);
2671 /* use two icons to indicate if it is white's or black's turn */
2672 WhiteIcon = load_pixbuf("svg/icon_white.svg",0);
2673 BlackIcon = load_pixbuf("svg/icon_black.svg",0);
2674 WindowIcon = WhiteIcon;
2675 gtk_window_set_icon(GTK_WINDOW(GUI_Window),WindowIcon);
2678 /* realize window */
2679 gtk_widget_show (GUI_Window);
2681 /* recalc boardsize */
2686 if (appData.animate || appData.animateDragging)
2691 if (errorExitStatus == -1) {
2692 if (appData.icsActive) {
2693 /* We now wait until we see "login:" from the ICS before
2694 sending the logon script (problems with timestamp otherwise) */
2695 /*ICSInitScript();*/
2696 if (appData.icsInputBox) ICSInputBoxPopUp();
2699 signal(SIGINT, IntSigHandler);
2700 signal(SIGTERM, IntSigHandler);
2701 if (*appData.cmailGameName != NULLCHAR) {
2702 signal(SIGUSR1, CmailSigHandler);
2705 gameInfo.boardWidth = 0; // [HGM] pieces: kludge to ensure InitPosition() calls InitDrawingSizes()
2709 * Create a cursor for the board widget.
2710 * (This needs to be called after the window has been created to have access to board-window)
2713 BoardCursor = gdk_cursor_new(GDK_HAND2);
2714 gdk_window_set_cursor(GUI_Board->window, BoardCursor);
2715 gdk_cursor_destroy(BoardCursor);
2720 if (appData.debugMode) fclose(debugFP); // [DM] debug
2727 if (appData.icsActive && oldICSInteractionTitle != NULL) {
2728 DisplayIcsInteractionTitle(oldICSInteractionTitle);
2730 unlink(gameCopyFilename);
2731 unlink(gamePasteFilename);
2734 RETSIGTYPE TermSizeSigHandler(int sig)
2747 CmailSigHandler(sig)
2753 signal(SIGUSR1, SIG_IGN); /* suspend handler */
2755 /* Activate call-back function CmailSigHandlerCallBack() */
2756 OutputToProcess(cmailPR, (char *)(&dummy), sizeof(int), &error);
2758 signal(SIGUSR1, CmailSigHandler); /* re-activate handler */
2762 CmailSigHandlerCallBack(isr, closure, message, count, error)
2770 ReloadCmailMsgEvent(TRUE); /* Reload cmail msg */
2772 /**** end signal code ****/
2782 f = fopen(appData.icsLogon, "r");
2788 strcat(buf, appData.icsLogon);
2789 f = fopen(buf, "r");
2793 ProcessICSInitScript(f);
2800 EditCommentPopDown();
2806 SetMenuEnables(enab)
2811 if (!builder) return;
2812 while (enab->name != NULL) {
2813 o = gtk_builder_get_object(builder, enab->name);
2814 if(GTK_IS_WIDGET(o))
2815 gtk_widget_set_sensitive(GTK_WIDGET (o),enab->value);
2818 if(GTK_IS_ACTION(o))
2819 gtk_action_set_sensitive(GTK_ACTION (o),enab->value);
2821 DisplayError(enab->name, 0);
2829 SetMenuEnables(icsEnables);
2832 if (appData.zippyPlay && !appData.noChessProgram) /* [DM] icsEngineAnalyze */
2833 {}; // XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Analysis Mode"), True);
2840 SetMenuEnables(ncpEnables);
2846 SetMenuEnables(gnuEnables);
2852 SetMenuEnables(cmailEnables);
2858 SetMenuEnables(trainingOnEnables);
2859 if (appData.showButtonBar) {
2860 // XtSetSensitive(buttonBarWidget, False);
2866 SetTrainingModeOff()
2868 SetMenuEnables(trainingOffEnables);
2869 if (appData.showButtonBar) {
2870 // XtSetSensitive(buttonBarWidget, True);
2875 SetUserThinkingEnables()
2877 if (appData.noChessProgram) return;
2878 SetMenuEnables(userThinkingEnables);
2882 SetMachineThinkingEnables()
2884 if (appData.noChessProgram) return;
2885 SetMenuEnables(machineThinkingEnables);
2887 case MachinePlaysBlack:
2888 case MachinePlaysWhite:
2889 case TwoMachinesPlay:
2890 // XtSetSensitive(XtNameToWidget(menuBarWidget,
2891 // ModeToWidgetName(gameMode)), True);
2898 #define Abs(n) ((n)<0 ? -(n) : (n))
2901 * Find a font that matches "pattern" that is as close as
2902 * possible to the targetPxlSize. Prefer fonts that are k
2903 * pixels smaller to fonts that are k pixels larger. The
2904 * pattern must be in the X Consortium standard format,
2905 * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".
2906 * The return value should be freed with XtFree when no
2909 char *FindFont(pattern, targetPxlSize)
2913 char **fonts, *p, *best, *scalable, *scalableTail;
2914 int i, j, nfonts, minerr, err, pxlSize;
2917 char **missing_list;
2919 char *def_string, *base_fnt_lst, strInt[3];
2921 XFontStruct **fnt_list;
2923 base_fnt_lst = calloc(1, strlen(pattern) + 3);
2924 sprintf(strInt, "%d", targetPxlSize);
2925 p = strstr(pattern, "--");
2926 strncpy(base_fnt_lst, pattern, p - pattern + 2);
2927 strcat(base_fnt_lst, strInt);
2928 strcat(base_fnt_lst, strchr(p + 2, '-'));
2930 if ((fntSet = XCreateFontSet(xDisplay,
2934 &def_string)) == NULL) {
2936 fprintf(stderr, _("Unable to create font set.\n"));
2940 nfonts = XFontsOfFontSet(fntSet, &fnt_list, &fonts);
2942 fonts = XListFonts(xDisplay, pattern, 999999, &nfonts);
2944 fprintf(stderr, _("%s: no fonts match pattern %s\n"),
2945 programName, pattern);
2953 for (i=0; i<nfonts; i++) {
2956 if (*p != '-') continue;
2958 if (*p == NULLCHAR) break;
2959 if (*p++ == '-') j++;
2961 if (j < 7) continue;
2964 scalable = fonts[i];
2967 err = pxlSize - targetPxlSize;
2968 if (Abs(err) < Abs(minerr) ||
2969 (minerr > 0 && err < 0 && -err == minerr)) {
2975 if (scalable && Abs(minerr) > appData.fontSizeTolerance) {
2976 /* If the error is too big and there is a scalable font,
2977 use the scalable font. */
2978 int headlen = scalableTail - scalable;
2979 p = (char *) XtMalloc(strlen(scalable) + 10);
2980 while (isdigit(*scalableTail)) scalableTail++;
2981 sprintf(p, "%.*s%d%s", headlen, scalable, targetPxlSize, scalableTail);
2983 p = (char *) XtMalloc(strlen(best) + 1);
2986 if (appData.debugMode) {
2987 fprintf(debugFP, _("resolved %s at pixel size %d\n to %s\n"),
2988 pattern, targetPxlSize, p);
2991 if (missing_count > 0)
2992 XFreeStringList(missing_list);
2993 XFreeFontSet(xDisplay, fntSet);
2995 XFreeFontNames(fonts);
3002 /* 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*/
3004 XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
3005 | GCBackground | GCFunction | GCPlaneMask;
3006 XGCValues gc_values;
3009 gc_values.plane_mask = AllPlanes;
3010 gc_values.line_width = lineGap;
3011 gc_values.line_style = LineSolid;
3012 gc_values.function = GXcopy;
3014 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3015 gc_values.background = XWhitePixel(xDisplay, xScreen);
3016 coordGC = XtGetGC(shellWidget, value_mask, &gc_values);
3017 XSetFont(xDisplay, coordGC, coordFontID);
3019 if (appData.monoMode) {
3020 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3021 gc_values.background = XBlackPixel(xDisplay, xScreen);
3022 lightSquareGC = wbPieceGC
3023 = XtGetGC(shellWidget, value_mask, &gc_values);
3025 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3026 gc_values.background = XWhitePixel(xDisplay, xScreen);
3027 darkSquareGC = bwPieceGC
3028 = XtGetGC(shellWidget, value_mask, &gc_values);
3030 if (DefaultDepth(xDisplay, xScreen) == 1) {
3031 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
3032 gc_values.function = GXcopyInverted;
3033 copyInvertedGC = XtGetGC(shellWidget, value_mask, &gc_values);
3034 gc_values.function = GXcopy;
3035 if (XBlackPixel(xDisplay, xScreen) == 1) {
3036 bwPieceGC = darkSquareGC;
3037 wbPieceGC = copyInvertedGC;
3039 bwPieceGC = copyInvertedGC;
3040 wbPieceGC = lightSquareGC;
3044 gc_values.foreground = lightSquareColor;
3045 gc_values.background = darkSquareColor;
3046 lightSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3048 gc_values.foreground = darkSquareColor;
3049 gc_values.background = lightSquareColor;
3050 darkSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3052 gc_values.foreground = jailSquareColor;
3053 gc_values.background = jailSquareColor;
3054 jailSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3056 gc_values.foreground = whitePieceColor;
3057 gc_values.background = darkSquareColor;
3058 wdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3060 gc_values.foreground = whitePieceColor;
3061 gc_values.background = lightSquareColor;
3062 wlPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3064 gc_values.foreground = whitePieceColor;
3065 gc_values.background = jailSquareColor;
3066 wjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3068 gc_values.foreground = blackPieceColor;
3069 gc_values.background = darkSquareColor;
3070 bdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3072 gc_values.foreground = blackPieceColor;
3073 gc_values.background = lightSquareColor;
3074 blPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3076 gc_values.foreground = blackPieceColor;
3077 gc_values.background = jailSquareColor;
3078 bjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3087 for(i=0;i<MAXPIECES;i++)
3091 g_free(SVGpieces[i]);
3098 SVGLightSquare = load_pixbuf("svg/LightSquare.svg",squareSize);
3099 SVGDarkSquare = load_pixbuf("svg/DarkSquare.svg",squareSize);
3100 SVGNeutralSquare = load_pixbuf("svg/NeutralSquare.svg",squareSize);
3103 /* get some defaults going */
3104 for(i=WhitePawn; i<DemotePiece+1; i++)
3105 SVGpieces[i] = load_pixbuf("svg/NeutralSquare.svg",squareSize);
3107 SVGpieces[WhitePawn] = load_pixbuf("svg/WhitePawn.svg",squareSize);
3108 SVGpieces[WhiteKnight] = load_pixbuf("svg/WhiteKnight.svg",squareSize);
3109 SVGpieces[WhiteBishop] = load_pixbuf("svg/WhiteBishop.svg",squareSize);
3110 SVGpieces[WhiteRook] = load_pixbuf("svg/WhiteRook.svg",squareSize);
3111 SVGpieces[WhiteQueen] = load_pixbuf("svg/WhiteQueen.svg",squareSize);
3112 SVGpieces[WhiteKing] = load_pixbuf("svg/WhiteKing.svg",squareSize);
3114 SVGpieces[BlackPawn] = load_pixbuf("svg/BlackPawn.svg",squareSize);
3115 SVGpieces[BlackKnight] = load_pixbuf("svg/BlackKnight.svg",squareSize);
3116 SVGpieces[BlackBishop] = load_pixbuf("svg/BlackBishop.svg",squareSize);
3117 SVGpieces[BlackRook] = load_pixbuf("svg/BlackRook.svg",squareSize);
3118 SVGpieces[BlackQueen] = load_pixbuf("svg/BlackQueen.svg",squareSize);
3119 SVGpieces[BlackKing] = load_pixbuf("svg/BlackKing.svg",squareSize);
3125 static void MenuBarSelect(w, addr, index)
3130 XtActionProc proc = (XtActionProc) addr;
3132 (proc)(NULL, NULL, NULL, NULL);
3135 void CreateMenuBarPopup(parent, name, mb)
3145 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3148 XtSetArg(args[j], XtNleftMargin, 20); j++;
3149 XtSetArg(args[j], XtNrightMargin, 20); j++;
3151 while (mi->string != NULL) {
3152 if (strcmp(mi->string, "----") == 0) {
3153 entry = XtCreateManagedWidget(mi->string, smeLineObjectClass,
3156 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string)));
3157 entry = XtCreateManagedWidget(mi->string, smeBSBObjectClass,
3159 XtAddCallback(entry, XtNcallback,
3160 (XtCallbackProc) MenuBarSelect,
3161 (caddr_t) mi->proc);
3167 Widget CreateMenuBar(mb)
3171 Widget anchor, menuBar;
3173 char menuName[MSG_SIZ];
3176 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
3177 XtSetArg(args[j], XtNvSpace, 0); j++;
3178 XtSetArg(args[j], XtNborderWidth, 0); j++;
3179 menuBar = XtCreateWidget("menuBar", boxWidgetClass,
3180 formWidget, args, j);
3182 while (mb->name != NULL) {
3183 strcpy(menuName, "menu");
3184 strcat(menuName, mb->name);
3186 XtSetArg(args[j], XtNmenuName, XtNewString(menuName)); j++;
3189 shortName[0] = _(mb->name)[0];
3190 shortName[1] = NULLCHAR;
3191 XtSetArg(args[j], XtNlabel, XtNewString(shortName)); j++;
3194 XtSetArg(args[j], XtNlabel, XtNewString(_(mb->name))); j++;
3197 XtSetArg(args[j], XtNborderWidth, 0); j++;
3198 anchor = XtCreateManagedWidget(mb->name, menuButtonWidgetClass,
3200 CreateMenuBarPopup(menuBar, menuName, mb);
3208 CreatePieceMenu(name, color)
3215 ChessSquare selection;
3217 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3218 boardWidget, args, 0);
3220 for (i = 0; i < PIECE_MENU_SIZE; i++) {
3221 String item = pieceMenuStrings[color][i];
3223 if (strcmp(item, "----") == 0) {
3224 entry = XtCreateManagedWidget(item, smeLineObjectClass,
3227 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
3228 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3230 selection = pieceMenuTranslation[color][i];
3231 XtAddCallback(entry, XtNcallback,
3232 (XtCallbackProc) PieceMenuSelect,
3233 (caddr_t) selection);
3234 if (selection == WhitePawn || selection == BlackPawn) {
3235 XtSetArg(args[0], XtNpopupOnEntry, entry);
3236 XtSetValues(menu, args, 1);
3249 ChessSquare selection;
3251 // whitePieceMenu = CreatePieceMenu("menuW", 0);
3252 // blackPieceMenu = CreatePieceMenu("menuB", 1);
3254 // XtRegisterGrabAction(PieceMenuPopup, True,
3255 // (unsigned)(ButtonPressMask|ButtonReleaseMask),
3256 // GrabModeAsync, GrabModeAsync);
3258 // XtSetArg(args[0], XtNlabel, _("Drop"));
3259 // dropMenu = XtCreatePopupShell("menuD", simpleMenuWidgetClass,
3260 // boardWidget, args, 1);
3261 // for (i = 0; i < DROP_MENU_SIZE; i++) {
3262 // String item = dropMenuStrings[i];
3264 // if (strcmp(item, "----") == 0) {
3265 // entry = XtCreateManagedWidget(item, smeLineObjectClass,
3266 // dropMenu, NULL, 0);
3268 // XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
3269 // entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3270 // dropMenu, args, 1);
3271 // selection = dropMenuTranslation[i];
3272 // XtAddCallback(entry, XtNcallback,
3273 // (XtCallbackProc) DropMenuSelect,
3274 // (caddr_t) selection);
3279 void SetupDropMenu()
3287 for (i=0; i<sizeof(dmEnables)/sizeof(DropMenuEnables); i++) {
3288 entry = XtNameToWidget(dropMenu, dmEnables[i].widget);
3289 p = strchr(gameMode == IcsPlayingWhite ? white_holding : black_holding,
3290 dmEnables[i].piece);
3291 XtSetSensitive(entry, p != NULL || !appData.testLegality
3292 /*!!temp:*/ || (gameInfo.variant == VariantCrazyhouse
3293 && !appData.icsActive));
3295 while (p && *p++ == dmEnables[i].piece) count++;
3296 snprintf(label, sizeof(label), "%s %d", dmEnables[i].widget, count);
3298 XtSetArg(args[j], XtNlabel, label); j++;
3299 XtSetValues(entry, args, j);
3303 void PieceMenuPopup(w, event, params, num_params)
3307 Cardinal *num_params;
3310 if (event->type != ButtonPress) return;
3311 if (errorUp) ErrorPopDown();
3315 whichMenu = params[0];
3317 case IcsPlayingWhite:
3318 case IcsPlayingBlack:
3320 case MachinePlaysWhite:
3321 case MachinePlaysBlack:
3322 if (appData.testLegality &&
3323 gameInfo.variant != VariantBughouse &&
3324 gameInfo.variant != VariantCrazyhouse) return;
3326 whichMenu = "menuD";
3332 if (((pmFromX = EventToSquare(event->xbutton.x, BOARD_WIDTH)) < 0) ||
3333 ((pmFromY = EventToSquare(event->xbutton.y, BOARD_HEIGHT)) < 0)) {
3334 pmFromX = pmFromY = -1;
3338 pmFromX = BOARD_WIDTH - 1 - pmFromX;
3340 pmFromY = BOARD_HEIGHT - 1 - pmFromY;
3342 XtPopupSpringLoaded(XtNameToWidget(boardWidget, whichMenu));
3345 static void PieceMenuSelect(w, piece, junk)
3350 if (pmFromX < 0 || pmFromY < 0) return;
3351 EditPositionMenuEvent(piece, pmFromX, pmFromY);
3354 static void DropMenuSelect(w, piece, junk)
3359 if (pmFromX < 0 || pmFromY < 0) return;
3360 DropMenuEvent(piece, pmFromX, pmFromY);
3364 * If the user selects on a border boundary, return -1; if off the board,
3365 * return -2. Otherwise map the event coordinate to the square.
3367 int EventToSquare(x, limit)
3375 if ((x % (squareSize + lineGap)) >= squareSize)
3377 x /= (squareSize + lineGap);
3383 static void do_flash_delay(msec)
3389 static void drawHighlight(file, rank, line_type)
3390 int file, rank, line_type;
3395 if (lineGap == 0 || appData.blindfold) return;
3399 x = lineGap/2 + ((BOARD_WIDTH-1)-file) *
3400 (squareSize + lineGap);
3401 y = lineGap/2 + rank * (squareSize + lineGap);
3405 x = lineGap/2 + file * (squareSize + lineGap);
3406 y = lineGap/2 + ((BOARD_HEIGHT-1)-rank) *
3407 (squareSize + lineGap);
3411 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
3413 /* draw the highlight */
3414 cairo_move_to (cr, x, y);
3415 cairo_rel_line_to (cr, 0,squareSize+lineGap);
3416 cairo_rel_line_to (cr, squareSize+lineGap,0);
3417 cairo_rel_line_to (cr, 0,-squareSize-lineGap);
3418 cairo_close_path (cr);
3420 cairo_set_line_width (cr, lineGap);
3423 /* TODO: use appdata colors */
3424 case LINE_TYPE_HIGHLIGHT:
3425 cairo_set_source_rgba (cr, 1, 1, 0, 1.0);
3428 cairo_set_source_rgba (cr, 1, 0, 0, 1.0);
3430 case LINE_TYPE_NORMAL:
3432 cairo_set_source_rgba (cr, 0, 1, 0, 1.0);
3443 int hi1X = -1, hi1Y = -1, hi2X = -1, hi2Y = -1;
3444 int pm1X = -1, pm1Y = -1, pm2X = -1, pm2Y = -1;
3447 SetHighlights(fromX, fromY, toX, toY)
3448 int fromX, fromY, toX, toY;
3450 if (hi1X != fromX || hi1Y != fromY)
3452 if (hi1X >= 0 && hi1Y >= 0)
3454 drawHighlight(hi1X, hi1Y, LINE_TYPE_NORMAL);
3456 if (fromX >= 0 && fromY >= 0)
3458 drawHighlight(fromX, fromY, LINE_TYPE_HIGHLIGHT);
3461 if (hi2X != toX || hi2Y != toY)
3463 if (hi2X >= 0 && hi2Y >= 0)
3465 drawHighlight(hi2X, hi2Y, LINE_TYPE_NORMAL);
3467 if (toX >= 0 && toY >= 0)
3469 drawHighlight(toX, toY, LINE_TYPE_HIGHLIGHT);
3483 SetHighlights(-1, -1, -1, -1);
3488 SetPremoveHighlights(fromX, fromY, toX, toY)
3489 int fromX, fromY, toX, toY;
3491 if (pm1X != fromX || pm1Y != fromY)
3493 if (pm1X >= 0 && pm1Y >= 0)
3495 drawHighlight(pm1X, pm1Y, LINE_TYPE_NORMAL);
3497 if (fromX >= 0 && fromY >= 0)
3499 drawHighlight(fromX, fromY, LINE_TYPE_PRE);
3502 if (pm2X != toX || pm2Y != toY)
3504 if (pm2X >= 0 && pm2Y >= 0)
3506 drawHighlight(pm2X, pm2Y, LINE_TYPE_NORMAL);
3508 if (toX >= 0 && toY >= 0)
3510 drawHighlight(toX, toY, LINE_TYPE_PRE);
3523 ClearPremoveHighlights()
3525 SetPremoveHighlights(-1, -1, -1, -1);
3528 static void BlankSquare(x, y, color, piece, dest)
3541 pb = SVGLightSquare;
3543 case 2: /* neutral */
3545 pb = SVGNeutralSquare;
3548 gdk_draw_pixbuf(GDK_WINDOW(GUI_Board->window),NULL,pb,0,0,x,y,-1,-1, GDK_RGB_DITHER_NORMAL, 0, 0);
3552 static void DrawPiece(piece, square_color, x, y, dest)
3554 int square_color, x, y;
3557 /* redraw background, since piece might be transparent in some areas */
3558 BlankSquare(x,y,square_color,piece,dest);
3561 gdk_draw_pixbuf(GDK_WINDOW(GUI_Board->window),NULL,
3562 GDK_PIXBUF(SVGpieces[piece]),0,0,x,y,-1,-1,
3563 GDK_RGB_DITHER_NORMAL, 0, 0);
3567 /* [HR] determine square color depending on chess variant. */
3568 static int SquareColor(row, column)
3573 if (gameInfo.variant == VariantXiangqi) {
3574 if (column >= 3 && column <= 5 && row >= 0 && row <= 2) {
3576 } else if (column >= 3 && column <= 5 && row >= 7 && row <= 9) {
3578 } else if (row <= 4) {
3584 square_color = ((column + row) % 2) == 1;
3587 /* [hgm] holdings: next line makes all holdings squares light */
3588 if(column < BOARD_LEFT || column >= BOARD_RGHT) square_color = 1;
3590 return square_color;
3593 void DrawSquare(row, column, piece, do_flash)
3594 int row, column, do_flash;
3597 int square_color, x, y;
3602 /* Calculate delay in milliseconds (2-delays per complete flash) */
3603 flash_delay = 500 / appData.flashRate;
3605 /* calculate x and y coordinates from row and column */
3608 x = lineGap + ((BOARD_WIDTH-1)-column) *
3609 (squareSize + lineGap);
3610 y = lineGap + row * (squareSize + lineGap);
3614 x = lineGap + column * (squareSize + lineGap);
3615 y = lineGap + ((BOARD_HEIGHT-1)-row) *
3616 (squareSize + lineGap);
3619 square_color = SquareColor(row, column);
3621 // [HGM] holdings: blank out area between board and holdings
3622 if ( column == BOARD_LEFT-1 || column == BOARD_RGHT
3623 || (column == BOARD_LEFT-2 && row < BOARD_HEIGHT-gameInfo.holdingsSize)
3624 || (column == BOARD_RGHT+1 && row >= gameInfo.holdingsSize) )
3626 BlankSquare(x, y, 2, EmptySquare, xBoardWindow);
3628 // [HGM] print piece counts next to holdings
3629 string[1] = NULLCHAR;
3632 cairo_text_extents_t extents;
3637 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
3639 string[0] = '0' + piece;
3641 /* TODO this has to go into the font-selection */
3642 cairo_select_font_face (cr, "Sans",
3643 CAIRO_FONT_SLANT_NORMAL,
3644 CAIRO_FONT_WEIGHT_NORMAL);
3646 cairo_set_font_size (cr, 12.0);
3647 cairo_text_extents (cr, string, &extents);
3649 if (column == (flipView ? BOARD_LEFT-1 : BOARD_RGHT) )
3651 xpos= x + squareSize - extents.width - 2;
3652 ypos= y + extents.y_bearing + 1;
3654 if (column == (flipView ? BOARD_RGHT : BOARD_LEFT-1) && piece > 1)
3657 ypos = y + extents.y_bearing + 1;
3660 /* TODO mono mode? */
3661 cairo_move_to (cr, xpos, ypos);
3662 cairo_text_path (cr, string);
3663 cairo_set_source_rgb (cr, 1.0, 1.0, 1);
3664 cairo_fill_preserve (cr);
3665 cairo_set_source_rgb (cr, 0, 0, 0);
3666 cairo_set_line_width (cr, 0.1);
3675 /* square on the board */
3676 if (piece == EmptySquare || appData.blindfold)
3678 BlankSquare(x, y, square_color, piece, xBoardWindow);
3682 if (do_flash && appData.flashCount > 0)
3684 for (i=0; i<appData.flashCount; ++i)
3687 DrawPiece(piece, square_color, x, y, xBoardWindow);
3688 do_flash_delay(flash_delay);
3690 BlankSquare(x, y, square_color, piece, xBoardWindow);
3691 do_flash_delay(flash_delay);
3694 DrawPiece(piece, square_color, x, y, xBoardWindow);
3698 /* show coordinates if necessary */
3699 if(appData.showCoords)
3701 cairo_text_extents_t extents;
3705 /* TODO this has to go into the font-selection */
3706 cairo_select_font_face (cr, "Sans",
3707 CAIRO_FONT_SLANT_NORMAL,
3708 CAIRO_FONT_WEIGHT_NORMAL);
3709 cairo_set_font_size (cr, 12.0);
3711 string[1] = NULLCHAR;
3714 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
3716 if (row == (flipView ? BOARD_HEIGHT-1 : 0) &&
3717 column >= BOARD_LEFT && column < BOARD_RGHT)
3719 string[0] = 'a' + column - BOARD_LEFT;
3720 cairo_text_extents (cr, string, &extents);
3722 xpos = x + squareSize - extents.width - 2;
3723 ypos = y + squareSize - extents.height - extents.y_bearing - 1;
3725 if (appData.monoMode)
3732 cairo_move_to (cr, xpos, ypos);
3733 cairo_text_path (cr, string);
3734 cairo_set_source_rgb (cr, 0.0, 0.0, 0);
3735 cairo_fill_preserve (cr);
3736 cairo_set_source_rgb (cr, 0, 1.0, 0);
3737 cairo_set_line_width (cr, 0.1);
3740 if ( column == (flipView ? BOARD_RGHT-1 : BOARD_LEFT))
3743 string[0] = ONE + row;
3744 cairo_text_extents (cr, string, &extents);
3747 ypos = y + extents.height + 1;
3749 if (appData.monoMode)
3756 cairo_move_to (cr, xpos, ypos);
3757 cairo_text_path (cr, string);
3758 cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
3759 cairo_fill_preserve (cr);
3760 cairo_set_source_rgb (cr, 0, 0, 1.0);
3761 cairo_set_line_width (cr, 0.1);
3773 /* Returns 1 if there are "too many" differences between b1 and b2
3774 (i.e. more than 1 move was made) */
3775 static int too_many_diffs(b1, b2)
3781 for (i=0; i<BOARD_HEIGHT; ++i) {
3782 for (j=0; j<BOARD_WIDTH; ++j) {
3783 if (b1[i][j] != b2[i][j]) {
3784 if (++c > 4) /* Castling causes 4 diffs */
3793 /* Matrix describing castling maneuvers */
3794 /* Row, ColRookFrom, ColKingFrom, ColRookTo, ColKingTo */
3795 static int castling_matrix[4][5] = {
3796 { 0, 0, 4, 3, 2 }, /* 0-0-0, white */
3797 { 0, 7, 4, 5, 6 }, /* 0-0, white */
3798 { 7, 0, 4, 3, 2 }, /* 0-0-0, black */
3799 { 7, 7, 4, 5, 6 } /* 0-0, black */
3802 /* Checks whether castling occurred. If it did, *rrow and *rcol
3803 are set to the destination (row,col) of the rook that moved.
3805 Returns 1 if castling occurred, 0 if not.
3807 Note: Only handles a max of 1 castling move, so be sure
3808 to call too_many_diffs() first.
3810 static int check_castle_draw(newb, oldb, rrow, rcol)
3817 /* For each type of castling... */
3818 for (i=0; i<4; ++i) {
3819 r = castling_matrix[i];
3821 /* Check the 4 squares involved in the castling move */
3823 for (j=1; j<=4; ++j) {
3824 if (newb[r[0]][r[j]] == oldb[r[0]][r[j]]) {
3831 /* All 4 changed, so it must be a castling move */
3840 static int damage[BOARD_SIZE][BOARD_SIZE];
3843 * event handler for redrawing the board
3845 void DrawPosition( repaint, board)
3846 /*Boolean*/int repaint;
3850 static int lastFlipView = 0;
3851 static int lastBoardValid = 0;
3852 static Board lastBoard;
3855 if (board == NULL) {
3856 if (!lastBoardValid) return;
3859 if (!lastBoardValid || lastFlipView != flipView) {
3860 // XtSetArg(args[0], XtNleftBitmap, (flipView ? xMarkPixmap : None));
3861 // XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flip View"),
3866 * It would be simpler to clear the window with XClearWindow()
3867 * but this causes a very distracting flicker.
3870 if (!repaint && lastBoardValid && lastFlipView == flipView)
3872 /* If too much changes (begin observing new game, etc.), don't
3874 do_flash = too_many_diffs(board, lastBoard) ? 0 : 1;
3876 /* Special check for castling so we don't flash both the king
3877 and the rook (just flash the king). */
3880 if (check_castle_draw(board, lastBoard, &rrow, &rcol))
3882 /* Draw rook with NO flashing. King will be drawn flashing later */
3883 DrawSquare(rrow, rcol, board[rrow][rcol], 0);
3884 lastBoard[rrow][rcol] = board[rrow][rcol];
3888 /* First pass -- Draw (newly) empty squares and repair damage.
3889 This prevents you from having a piece show up twice while it
3890 is flashing on its new square */
3891 for (i = 0; i < BOARD_HEIGHT; i++)
3892 for (j = 0; j < BOARD_WIDTH; j++)
3893 if ((board[i][j] != lastBoard[i][j] && board[i][j] == EmptySquare)
3896 DrawSquare(i, j, board[i][j], 0);
3897 damage[i][j] = False;
3900 /* Second pass -- Draw piece(s) in new position and flash them */
3901 for (i = 0; i < BOARD_HEIGHT; i++)
3902 for (j = 0; j < BOARD_WIDTH; j++)
3903 if (board[i][j] != lastBoard[i][j])
3905 DrawSquare(i, j, board[i][j], do_flash);
3917 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
3919 cairo_set_line_width (cr, lineGap);
3921 /* TODO: use appdata colors */
3922 cairo_set_source_rgba (cr, 0, 1, 0, 1.0);
3926 for (i = 0; i < BOARD_HEIGHT + 1; i++)
3929 x2 = lineGap + BOARD_WIDTH * (squareSize + lineGap);
3930 y1 = y2 = lineGap / 2 + (i * (squareSize + lineGap));
3932 cairo_move_to (cr, x1, y1);
3933 cairo_rel_line_to (cr, x2,0);
3937 for (j = 0; j < BOARD_WIDTH + 1; j++)
3940 y2 = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
3941 x1 = x2 = lineGap / 2 + (j * (squareSize + lineGap));
3943 cairo_move_to (cr, x1, y1);
3944 cairo_rel_line_to (cr, 0, y2);
3953 for (i = 0; i < BOARD_HEIGHT; i++)
3954 for (j = 0; j < BOARD_WIDTH; j++)
3956 DrawSquare(i, j, board[i][j], 0);
3957 damage[i][j] = False;
3961 CopyBoard(lastBoard, board);
3963 lastFlipView = flipView;
3965 /* Draw highlights */
3966 if (pm1X >= 0 && pm1Y >= 0)
3968 drawHighlight(pm1X, pm1Y, LINE_TYPE_PRE);
3970 if (pm2X >= 0 && pm2Y >= 0)
3972 drawHighlight(pm2X, pm2Y, LINE_TYPE_PRE);
3974 if (hi1X >= 0 && hi1Y >= 0)
3976 drawHighlight(hi1X, hi1Y, LINE_TYPE_HIGHLIGHT);
3978 if (hi2X >= 0 && hi2Y >= 0)
3980 drawHighlight(hi2X, hi2Y, LINE_TYPE_HIGHLIGHT);
3983 /* If piece being dragged around board, must redraw that too */
3990 * event handler for parsing user moves
3992 // [HGM] This routine will need quite some reworking. Although the backend still supports the old
3993 // way of doing things, by calling UserMoveEvent() to test the legality of the move and then perform
3994 // it at the end, and doing all kind of preliminary tests here (e.g. to weed out self-captures), it
3995 // should be made to use the new way, of calling UserMoveTest early to determine the legality of the
3996 // move, (which will weed out the illegal selfcaptures and moves into the holdings, and flag promotions),
3997 // and at the end FinishMove() to perform the move after optional promotion popups.
3998 // For now I patched it to allow self-capture with King, and suppress clicks between board and holdings.
3999 void HandleUserMove(w, event, prms, nprms)
4006 Boolean saveAnimate;
4007 static int second = 0, promotionChoice = 0;
4010 if (w != boardWidget || errorExitStatus != -1) return;
4012 x = EventToSquare(event->xbutton.x, BOARD_WIDTH);
4013 y = EventToSquare(event->xbutton.y, BOARD_HEIGHT);
4014 if (!flipView && y >= 0) {
4015 y = BOARD_HEIGHT - 1 - y;
4017 if (flipView && x >= 0) {
4018 x = BOARD_WIDTH - 1 - x;
4021 if(promotionChoice) { // we are waiting for a click to indicate promotion piece
4022 if(event->type == ButtonRelease) return; // ignore upclick of click-click destination
4023 promotionChoice = FALSE; // only one chance: if click not OK it is interpreted as cancel
4024 if(appData.debugMode) fprintf(debugFP, "promotion click, x=%d, y=%d\n", x, y);
4025 if(gameInfo.holdingsWidth &&
4026 (WhiteOnMove(currentMove)
4027 ? x == BOARD_WIDTH-1 && y < gameInfo.holdingsSize && y > 0
4028 : x == 0 && y >= BOARD_HEIGHT - gameInfo.holdingsSize && y < BOARD_HEIGHT-1) ) {
4029 // click in right holdings, for determining promotion piece
4030 ChessSquare p = boards[currentMove][y][x];
4031 if(appData.debugMode) fprintf(debugFP, "square contains %d\n", (int)p);
4032 if(p != EmptySquare) {
4033 FinishMove(NormalMove, fromX, fromY, toX, toY, ToLower(PieceToChar(p)));
4038 DrawPosition(FALSE, boards[currentMove]);
4041 if (event->type == ButtonPress) ErrorPopDown();
4044 if (event->type == ButtonPress) {
4045 // XtPopdown(promotionShell);
4046 // XtDestroyWidget(promotionShell);
4047 promotionUp = False;
4055 /* [HGM] holdings: next 5 lines: ignore all clicks between board and holdings */
4056 if(event->type == ButtonPress
4057 && ( x == BOARD_LEFT-1 ||
4059 (x == BOARD_LEFT-2 && y < BOARD_HEIGHT-gameInfo.holdingsSize ) ||
4060 (x == BOARD_RGHT+1 && y >= gameInfo.holdingsSize)) )
4064 if (event->type == ButtonPress) {
4065 /* First square, prepare to drag */
4066 if (OKToStartUserMove(x, y)) {
4070 DragPieceBegin(event->xbutton.x, event->xbutton.y);
4071 if (appData.highlightDragging) {
4072 SetHighlights(x, y, -1, -1);
4080 if (event->type == ButtonRelease && x == fromX && y == fromY) {
4081 /* Click on single square in stead of drag-drop */
4082 DragPieceEnd(event->xbutton.x, event->xbutton.y);
4083 if (appData.animateDragging) {
4084 /* Undo animation damage if any */
4085 DrawPosition(FALSE, NULL);
4088 /* Second up/down in same square; just abort move */
4093 ClearPremoveHighlights();
4095 /* First upclick in same square; start click-click mode */
4096 SetHighlights(x, y, -1, -1);
4101 moveType = UserMoveTest(fromX, fromY, x, y, NULLCHAR, event->type == ButtonRelease);
4103 if (moveType == Comment) { // kludge for indicating capture-own on Press
4104 /* Clicked again on same color piece -- changed his mind */
4105 /* note that re-clicking same square always hits same color piece */
4106 second = (x == fromX && y == fromY);
4107 if (appData.highlightDragging) {
4108 SetHighlights(x, y, -1, -1);
4112 if (OKToStartUserMove(x, y)) {
4115 DragPieceBegin(event->xbutton.x, event->xbutton.y);
4120 if(moveType == AmbiguousMove) { // kludge to indicate edit-position move
4123 DragPieceEnd(event->xbutton.x, event->xbutton.y);
4124 DrawPosition(FALSE, boards[currentMove]);
4128 /* Complete move; (x,y) is now different from (fromX, fromY) on both Press and Release */
4131 saveAnimate = appData.animate;
4132 if (event->type == ButtonPress) {
4133 /* Finish clickclick move */
4134 if (appData.animate || appData.highlightLastMove) {
4135 SetHighlights(fromX, fromY, toX, toY);
4140 /* Finish drag move */
4141 if (appData.highlightLastMove) {
4142 SetHighlights(fromX, fromY, toX, toY);
4146 DragPieceEnd(event->xbutton.x, event->xbutton.y);
4147 /* Don't animate move and drag both */
4148 appData.animate = FALSE;
4150 if (moveType == WhitePromotionKnight || moveType == BlackPromotionKnight ||
4151 (moveType == WhitePromotionQueen || moveType == BlackPromotionQueen) &&
4152 appData.alwaysPromoteToQueen) { // promotion, but no choice
4153 FinishMove(moveType, fromX, fromY, toX, toY, 'q');
4155 if (moveType == WhitePromotionQueen || moveType == BlackPromotionQueen ) {
4156 SetHighlights(fromX, fromY, toX, toY);
4157 if(gameInfo.variant == VariantSuper || gameInfo.variant == VariantGreat) {
4158 // [HGM] super: promotion to captured piece selected from holdings
4159 ChessSquare p = boards[currentMove][fromY][fromX], q = boards[currentMove][toY][toX];
4160 promotionChoice = TRUE;
4161 // kludge follows to temporarily execute move on display, without promoting yet
4162 boards[currentMove][fromY][fromX] = EmptySquare; // move Pawn to 8th rank
4163 boards[currentMove][toY][toX] = p;
4164 DrawPosition(FALSE, boards[currentMove]);
4165 boards[currentMove][fromY][fromX] = p; // take back, but display stays
4166 boards[currentMove][toY][toX] = q;
4167 DisplayMessage("Click in holdings to choose piece", "");
4171 goto skipClearingFrom; // the skipped stuff is done asynchronously by PromotionCallback
4173 if(moveType != ImpossibleMove) { // valid move, but no promotion
4174 FinishMove(moveType, fromX, fromY, toX, toY, NULLCHAR);
4175 } else { // invalid move; could have set premove
4178 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
4179 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
4182 appData.animate = saveAnimate;
4183 if (appData.animate || appData.animateDragging) {
4184 /* Undo animation damage if needed */
4185 DrawPosition(FALSE, NULL);
4189 void AnimateUserMove (Widget w, XEvent * event,
4190 String * params, Cardinal * nParams)
4192 DragPieceMove(event->xmotion.x, event->xmotion.y);
4195 Widget CommentCreate(name, text, mutable, callback, lines)
4197 int /*Boolean*/ mutable;
4198 XtCallbackProc callback;
4202 Widget shell, layout, form, edit, b_ok, b_cancel, b_clear, b_close, b_edit;
4207 XtSetArg(args[j], XtNwidth, &bw_width); j++;
4208 XtGetValues(boardWidget, args, j);
4211 XtSetArg(args[j], XtNresizable, True); j++;
4214 XtCreatePopupShell(name, topLevelShellWidgetClass,
4215 shellWidget, args, j);
4218 XtCreatePopupShell(name, transientShellWidgetClass,
4219 shellWidget, args, j);
4222 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
4223 layoutArgs, XtNumber(layoutArgs));
4225 XtCreateManagedWidget("form", formWidgetClass, layout,
4226 formArgs, XtNumber(formArgs));
4230 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
4231 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
4233 XtSetArg(args[j], XtNstring, text); j++;
4234 XtSetArg(args[j], XtNtop, XtChainTop); j++;
4235 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4236 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4237 XtSetArg(args[j], XtNright, XtChainRight); j++;
4238 XtSetArg(args[j], XtNresizable, True); j++;
4239 XtSetArg(args[j], XtNwidth, bw_width); j++; /*force wider than buttons*/
4240 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
4241 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
4242 XtSetArg(args[j], XtNautoFill, True); j++;
4243 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
4245 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
4249 XtSetArg(args[j], XtNfromVert, edit); 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(_("ok"), commandWidgetClass, form, args, j);
4256 XtAddCallback(b_ok, XtNcallback, callback, (XtPointer) 0);
4259 XtSetArg(args[j], XtNfromVert, edit); j++;
4260 XtSetArg(args[j], XtNfromHoriz, b_ok); 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(_("cancel"), commandWidgetClass, form, args, j);
4267 XtAddCallback(b_cancel, XtNcallback, callback, (XtPointer) 0);
4270 XtSetArg(args[j], XtNfromVert, edit); j++;
4271 XtSetArg(args[j], XtNfromHoriz, b_cancel); j++;
4272 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4273 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4274 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4275 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4277 XtCreateManagedWidget(_("clear"), commandWidgetClass, form, args, j);
4278 XtAddCallback(b_clear, XtNcallback, callback, (XtPointer) 0);
4281 XtSetArg(args[j], XtNfromVert, edit); 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(_("close"), commandWidgetClass, form, args, j);
4288 XtAddCallback(b_close, XtNcallback, callback, (XtPointer) 0);
4291 XtSetArg(args[j], XtNfromVert, edit); j++;
4292 XtSetArg(args[j], XtNfromHoriz, b_close); j++;
4293 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4294 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4295 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4296 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4298 XtCreateManagedWidget(_("edit"), commandWidgetClass, form, args, j);
4299 XtAddCallback(b_edit, XtNcallback, callback, (XtPointer) 0);
4302 XtRealizeWidget(shell);
4304 if (commentX == -1) {
4307 Dimension pw_height;
4308 Dimension ew_height;
4311 XtSetArg(args[j], XtNheight, &ew_height); j++;
4312 XtGetValues(edit, args, j);
4315 XtSetArg(args[j], XtNheight, &pw_height); j++;
4316 XtGetValues(shell, args, j);
4317 commentH = pw_height + (lines - 1) * ew_height;
4318 commentW = bw_width - 16;
4320 XSync(xDisplay, False);
4322 /* This code seems to tickle an X bug if it is executed too soon
4323 after xboard starts up. The coordinates get transformed as if
4324 the main window was positioned at (0, 0).
4326 XtTranslateCoords(shellWidget,
4327 (bw_width - commentW) / 2, 0 - commentH / 2,
4328 &commentX, &commentY);
4330 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
4331 RootWindowOfScreen(XtScreen(shellWidget)),
4332 (bw_width - commentW) / 2, 0 - commentH / 2,
4337 if (commentY < 0) commentY = 0; /*avoid positioning top offscreen*/
4340 XtSetArg(args[j], XtNheight, commentH); j++;
4341 XtSetArg(args[j], XtNwidth, commentW); j++;
4342 XtSetArg(args[j], XtNx, commentX); j++;
4343 XtSetArg(args[j], XtNy, commentY); j++;
4344 XtSetValues(shell, args, j);
4345 XtSetKeyboardFocus(shell, edit);
4350 /* Used for analysis window and ICS input window */
4351 Widget MiscCreate(name, text, mutable, callback, lines)
4353 int /*Boolean*/ mutable;
4354 XtCallbackProc callback;
4358 Widget shell, layout, form, edit;
4360 Dimension bw_width, pw_height, ew_height, w, h;
4366 XtSetArg(args[j], XtNresizable, True); j++;
4369 XtCreatePopupShell(name, topLevelShellWidgetClass,
4370 shellWidget, args, j);
4373 XtCreatePopupShell(name, transientShellWidgetClass,
4374 shellWidget, args, j);
4377 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
4378 layoutArgs, XtNumber(layoutArgs));
4380 XtCreateManagedWidget("form", formWidgetClass, layout,
4381 formArgs, XtNumber(formArgs));
4385 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
4386 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
4388 XtSetArg(args[j], XtNstring, text); j++;
4389 XtSetArg(args[j], XtNtop, XtChainTop); j++;
4390 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4391 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4392 XtSetArg(args[j], XtNright, XtChainRight); j++;
4393 XtSetArg(args[j], XtNresizable, True); j++;
4394 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
4395 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
4396 XtSetArg(args[j], XtNautoFill, True); j++;
4397 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
4399 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
4401 XtRealizeWidget(shell);
4404 XtSetArg(args[j], XtNwidth, &bw_width); j++;
4405 XtGetValues(boardWidget, args, j);
4408 XtSetArg(args[j], XtNheight, &ew_height); j++;
4409 XtGetValues(edit, args, j);
4412 XtSetArg(args[j], XtNheight, &pw_height); j++;
4413 XtGetValues(shell, args, j);
4414 h = pw_height + (lines - 1) * ew_height;
4417 XSync(xDisplay, False);
4419 /* This code seems to tickle an X bug if it is executed too soon
4420 after xboard starts up. The coordinates get transformed as if
4421 the main window was positioned at (0, 0).
4423 XtTranslateCoords(shellWidget, (bw_width - w) / 2, 0 - h / 2, &x, &y);
4425 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
4426 RootWindowOfScreen(XtScreen(shellWidget)),
4427 (bw_width - w) / 2, 0 - h / 2, &xx, &yy, &junk);
4431 if (y < 0) y = 0; /*avoid positioning top offscreen*/
4434 XtSetArg(args[j], XtNheight, h); j++;
4435 XtSetArg(args[j], XtNwidth, w); j++;
4436 XtSetArg(args[j], XtNx, x); j++;
4437 XtSetArg(args[j], XtNy, y); j++;
4438 XtSetValues(shell, args, j);
4444 static int savedIndex; /* gross that this is global */
4446 void EditCommentPopUp(index, title, text)
4455 if (text == NULL) text = "";
4457 if (editShell == NULL) {
4459 CommentCreate(title, text, True, EditCommentCallback, 4);
4460 XtRealizeWidget(editShell);
4461 CatchDeleteWindow(editShell, "EditCommentPopDown");
4463 edit = XtNameToWidget(editShell, "*form.text");
4465 XtSetArg(args[j], XtNstring, text); j++;
4466 XtSetValues(edit, args, j);
4468 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4469 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4470 XtSetValues(editShell, args, j);
4473 XtPopup(editShell, XtGrabNone);
4477 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
4478 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
4482 void EditCommentCallback(w, client_data, call_data)
4484 XtPointer client_data, call_data;
4492 XtSetArg(args[j], XtNlabel, &name); j++;
4493 XtGetValues(w, args, j);
4495 if (strcmp(name, _("ok")) == 0) {
4496 edit = XtNameToWidget(editShell, "*form.text");
4498 XtSetArg(args[j], XtNstring, &val); j++;
4499 XtGetValues(edit, args, j);
4500 ReplaceComment(savedIndex, val);
4501 EditCommentPopDown();
4502 } else if (strcmp(name, _("cancel")) == 0) {
4503 EditCommentPopDown();
4504 } else if (strcmp(name, _("clear")) == 0) {
4505 edit = XtNameToWidget(editShell, "*form.text");
4506 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
4507 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
4511 void EditCommentPopDown()
4516 if (!editUp) return;
4518 XtSetArg(args[j], XtNx, &commentX); j++;
4519 XtSetArg(args[j], XtNy, &commentY); j++;
4520 XtSetArg(args[j], XtNheight, &commentH); j++;
4521 XtSetArg(args[j], XtNwidth, &commentW); j++;
4522 XtGetValues(editShell, args, j);
4523 XtPopdown(editShell);
4526 XtSetArg(args[j], XtNleftBitmap, None); j++;
4527 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
4531 void ICSInputBoxPopUp()
4536 char *title = _("ICS Input");
4539 if (ICSInputShell == NULL) {
4540 ICSInputShell = MiscCreate(title, "", True, NULL, 1);
4541 tr = XtParseTranslationTable(ICSInputTranslations);
4542 edit = XtNameToWidget(ICSInputShell, "*form.text");
4543 XtOverrideTranslations(edit, tr);
4544 XtRealizeWidget(ICSInputShell);
4545 CatchDeleteWindow(ICSInputShell, "ICSInputBoxPopDown");
4548 edit = XtNameToWidget(ICSInputShell, "*form.text");
4550 XtSetArg(args[j], XtNstring, ""); j++;
4551 XtSetValues(edit, args, j);
4553 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4554 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4555 XtSetValues(ICSInputShell, args, j);
4558 XtPopup(ICSInputShell, XtGrabNone);
4559 XtSetKeyboardFocus(ICSInputShell, edit);
4561 ICSInputBoxUp = True;
4563 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
4564 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
4568 void ICSInputSendText()
4575 edit = XtNameToWidget(ICSInputShell, "*form.text");
4577 XtSetArg(args[j], XtNstring, &val); j++;
4578 XtGetValues(edit, args, j);
4579 SendMultiLineToICS(val);
4580 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
4581 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
4584 void ICSInputBoxPopDown()
4589 if (!ICSInputBoxUp) return;
4591 XtPopdown(ICSInputShell);
4592 ICSInputBoxUp = False;
4594 XtSetArg(args[j], XtNleftBitmap, None); j++;
4595 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
4599 void CommentPopUp(title, text)
4606 if (commentShell == NULL) {
4608 CommentCreate(title, text, False, CommentCallback, 4);
4609 XtRealizeWidget(commentShell);
4610 CatchDeleteWindow(commentShell, "CommentPopDown");
4612 edit = XtNameToWidget(commentShell, "*form.text");
4614 XtSetArg(args[j], XtNstring, text); j++;
4615 XtSetValues(edit, args, j);
4617 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4618 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4619 XtSetValues(commentShell, args, j);
4622 XtPopup(commentShell, XtGrabNone);
4623 XSync(xDisplay, False);
4628 void CommentCallback(w, client_data, call_data)
4630 XtPointer client_data, call_data;
4637 XtSetArg(args[j], XtNlabel, &name); j++;
4638 XtGetValues(w, args, j);
4640 if (strcmp(name, _("close")) == 0) {
4642 } else if (strcmp(name, _("edit")) == 0) {
4649 void CommentPopDown()
4654 if (!commentUp) return;
4656 XtSetArg(args[j], XtNx, &commentX); j++;
4657 XtSetArg(args[j], XtNy, &commentY); j++;
4658 XtSetArg(args[j], XtNwidth, &commentW); j++;
4659 XtSetArg(args[j], XtNheight, &commentH); j++;
4660 XtGetValues(commentShell, args, j);
4661 XtPopdown(commentShell);
4662 XSync(xDisplay, False);
4666 void FileNamePopUp(label, def, proc, openMode)
4673 Widget popup, layout, dialog, edit;
4679 fileProc = proc; /* I can't see a way not */
4680 fileOpenMode = openMode; /* to use globals here */
4683 XtSetArg(args[i], XtNresizable, True); i++;
4684 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
4685 XtSetArg(args[i], XtNtitle, XtNewString(_("File name prompt"))); i++;
4686 fileNameShell = popup =
4687 XtCreatePopupShell("File name prompt", transientShellWidgetClass,
4688 shellWidget, args, i);
4691 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
4692 layoutArgs, XtNumber(layoutArgs));
4695 XtSetArg(args[i], XtNlabel, label); i++;
4696 XtSetArg(args[i], XtNvalue, def); i++;
4697 XtSetArg(args[i], XtNborderWidth, 0); i++;
4698 dialog = XtCreateManagedWidget("fileName", dialogWidgetClass,
4701 XawDialogAddButton(dialog, _("ok"), FileNameCallback, (XtPointer) dialog);
4702 XawDialogAddButton(dialog, _("cancel"), FileNameCallback,
4703 (XtPointer) dialog);
4705 XtRealizeWidget(popup);
4706 CatchDeleteWindow(popup, "FileNamePopDown");
4708 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
4709 &x, &y, &win_x, &win_y, &mask);
4711 XtSetArg(args[0], XtNx, x - 10);
4712 XtSetArg(args[1], XtNy, y - 30);
4713 XtSetValues(popup, args, 2);
4715 XtPopup(popup, XtGrabExclusive);
4718 edit = XtNameToWidget(dialog, "*value");
4719 XtSetKeyboardFocus(popup, edit);
4722 void FileNamePopDown()
4724 if (!filenameUp) return;
4725 XtPopdown(fileNameShell);
4726 XtDestroyWidget(fileNameShell);
4731 void FileNameCallback(w, client_data, call_data)
4733 XtPointer client_data, call_data;
4738 XtSetArg(args[0], XtNlabel, &name);
4739 XtGetValues(w, args, 1);
4741 if (strcmp(name, _("cancel")) == 0) {
4746 FileNameAction(w, NULL, NULL, NULL);
4749 void FileNameAction(w, event, prms, nprms)
4761 name = XawDialogGetValueString(w = XtParent(w));
4763 if ((name != NULL) && (*name != NULLCHAR)) {
4765 XtPopdown(w = XtParent(XtParent(w)));
4769 p = strrchr(buf, ' ');
4776 fullname = ExpandPathName(buf);
4778 ErrorPopUp(_("Error"), _("Can't open file"), FALSE);
4781 f = fopen(fullname, fileOpenMode);
4783 DisplayError(_("Failed to open file"), errno);
4785 (void) (*fileProc)(f, index, buf);
4792 XtPopdown(w = XtParent(XtParent(w)));
4798 void PromotionPopUp()
4801 Widget dialog, layout;
4803 Dimension bw_width, pw_width;
4807 XtSetArg(args[j], XtNwidth, &bw_width); j++;
4808 XtGetValues(boardWidget, args, j);
4811 XtSetArg(args[j], XtNresizable, True); j++;
4812 XtSetArg(args[j], XtNtitle, XtNewString(_("Promotion"))); j++;
4814 XtCreatePopupShell("Promotion", transientShellWidgetClass,
4815 shellWidget, args, j);
4817 XtCreateManagedWidget(layoutName, formWidgetClass, promotionShell,
4818 layoutArgs, XtNumber(layoutArgs));
4821 XtSetArg(args[j], XtNlabel, _("Promote to what?")); j++;
4822 XtSetArg(args[j], XtNborderWidth, 0); j++;
4823 dialog = XtCreateManagedWidget("promotion", dialogWidgetClass,
4826 if(gameInfo.variant != VariantShogi) {
4827 XawDialogAddButton(dialog, _("Queen"), PromotionCallback,
4828 (XtPointer) dialog);
4829 XawDialogAddButton(dialog, _("Rook"), PromotionCallback,
4830 (XtPointer) dialog);
4831 XawDialogAddButton(dialog, _("Bishop"), PromotionCallback,
4832 (XtPointer) dialog);
4833 XawDialogAddButton(dialog, _("Knight"), PromotionCallback,
4834 (XtPointer) dialog);
4835 if (!appData.testLegality || gameInfo.variant == VariantSuicide ||
4836 gameInfo.variant == VariantGiveaway) {
4837 XawDialogAddButton(dialog, _("King"), PromotionCallback,
4838 (XtPointer) dialog);
4840 if(gameInfo.variant == VariantCapablanca ||
4841 gameInfo.variant == VariantGothic ||
4842 gameInfo.variant == VariantCapaRandom) {
4843 XawDialogAddButton(dialog, _("Archbishop"), PromotionCallback,
4844 (XtPointer) dialog);
4845 XawDialogAddButton(dialog, _("Chancellor"), PromotionCallback,
4846 (XtPointer) dialog);
4848 } else // [HGM] shogi
4850 XawDialogAddButton(dialog, _("Promote"), PromotionCallback,
4851 (XtPointer) dialog);
4852 XawDialogAddButton(dialog, _("Defer"), PromotionCallback,
4853 (XtPointer) dialog);
4855 XawDialogAddButton(dialog, _("cancel"), PromotionCallback,
4856 (XtPointer) dialog);
4858 XtRealizeWidget(promotionShell);
4859 CatchDeleteWindow(promotionShell, "PromotionPopDown");
4862 XtSetArg(args[j], XtNwidth, &pw_width); j++;
4863 XtGetValues(promotionShell, args, j);
4865 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
4866 lineGap + squareSize/3 +
4867 ((toY == BOARD_HEIGHT-1) ^ (flipView) ?
4868 0 : 6*(squareSize + lineGap)), &x, &y);
4871 XtSetArg(args[j], XtNx, x); j++;
4872 XtSetArg(args[j], XtNy, y); j++;
4873 XtSetValues(promotionShell, args, j);
4875 XtPopup(promotionShell, XtGrabNone);
4880 void PromotionPopDown()
4882 if (!promotionUp) return;
4883 XtPopdown(promotionShell);
4884 XtDestroyWidget(promotionShell);
4885 promotionUp = False;
4888 void PromotionCallback(w, client_data, call_data)
4890 XtPointer client_data, call_data;
4896 XtSetArg(args[0], XtNlabel, &name);
4897 XtGetValues(w, args, 1);
4901 if (fromX == -1) return;
4903 if (strcmp(name, _("cancel")) == 0) {
4907 } else if (strcmp(name, _("Knight")) == 0) {
4909 } else if (strcmp(name, _("Promote")) == 0) {
4911 } else if (strcmp(name, _("Defer")) == 0) {
4914 promoChar = ToLower(name[0]);
4917 FinishMove(NormalMove, fromX, fromY, toX, toY, promoChar);
4919 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
4920 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
4925 void ErrorCallback(w, client_data, call_data)
4927 XtPointer client_data, call_data;
4930 XtPopdown(w = XtParent(XtParent(XtParent(w))));
4932 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
4938 if (!errorUp) return;
4942 gtk_widget_destroy(GTK_WIDGET(GUI_Error));
4944 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
4949 void ErrorPopUp(title, label, modal)
4950 char *title, *label;
4953 GUI_Error = gtk_message_dialog_new(GTK_WINDOW(GUI_Window),
4954 GTK_DIALOG_DESTROY_WITH_PARENT,
4959 gtk_window_set_title(GTK_WINDOW(GUI_Error),(gchar *) title);
4962 gtk_dialog_run(GTK_DIALOG(GUI_Error));
4963 gtk_widget_destroy(GTK_WIDGET(GUI_Error));
4967 g_signal_connect_swapped (GUI_Error, "response",
4968 G_CALLBACK (ErrorPopDownProc),
4971 gtk_widget_show(GTK_WIDGET(GUI_Error));
4977 /* Disable all user input other than deleting the window */
4978 static int frozen = 0;
4982 /* Grab by a widget that doesn't accept input */
4983 // XtAddGrab(messageWidget, TRUE, FALSE);
4987 /* Undo a FreezeUI */
4990 if (!frozen) return;
4991 // XtRemoveGrab(messageWidget);
4995 char *ModeToWidgetName(mode)
4999 case BeginningOfGame:
5000 if (appData.icsActive)
5001 return "menuMode.ICS Client";
5002 else if (appData.noChessProgram ||
5003 *appData.cmailGameName != NULLCHAR)
5004 return "menuMode.Edit Game";
5006 return "menuMode.Machine Black";
5007 case MachinePlaysBlack:
5008 return "menuMode.Machine Black";
5009 case MachinePlaysWhite:
5010 return "menuMode.Machine White";
5012 return "menuMode.Analysis Mode";
5014 return "menuMode.Analyze File";
5015 case TwoMachinesPlay:
5016 return "menuMode.Two Machines";
5018 return "menuMode.Edit Game";
5019 case PlayFromGameFile:
5020 return "menuFile.Load Game";
5022 return "menuMode.Edit Position";
5024 return "menuMode.Training";
5025 case IcsPlayingWhite:
5026 case IcsPlayingBlack:
5030 return "menuMode.ICS Client";
5037 void ModeHighlight()
5039 static int oldPausing = FALSE;
5040 static GameMode oldmode = (GameMode) -1;
5043 // todo this toggling of the pause button doesn't seem to work?
5044 // e.g. select pause from buttonbar doesn't activate menumode.pause
5046 // if (!boardWidget || !XtIsRealized(boardWidget)) return;
5048 if (pausing != oldPausing) {
5049 oldPausing = pausing;
5050 gtk_button_set_relief(GTK_BUTTON (gtk_builder_get_object (builder, "menuMode.Pause")),pausing?GTK_RELIEF_NORMAL:GTK_RELIEF_NONE);
5051 /* toggle background color in showbuttonbar */
5052 if (appData.showButtonBar) {
5054 gtk_button_pressed(GTK_BUTTON (gtk_builder_get_object (builder, "buttonbar.Pause")));
5056 gtk_button_released(GTK_BUTTON (gtk_builder_get_object (builder, "buttonbar.Pause")));
5061 wname = ModeToWidgetName(oldmode);
5063 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, wname)),True);
5067 /* Maybe all the enables should be handled here, not just this one */
5068 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuMode.Training")),
5069 gameMode == Training || gameMode == PlayFromGameFile);
5074 * Button/menu procedures
5077 int LoadGamePopUp(f, gameNumber, title)
5082 cmailMsgLoaded = FALSE;
5084 if (gameNumber == 0)
5086 int error = GameListBuild(f);
5090 DisplayError(_("Cannot build game list"), error);
5092 else if (!ListEmpty(&gameList)
5093 && ((ListGame *) gameList.tailPred)->number > 1)
5095 GameListPopUp(f, title);
5103 return LoadGame(f, gameNumber, title, FALSE);
5106 void LoadPositionProc(w, event, prms, nprms)
5112 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
5115 FileNamePopUp(_("Load position file name?"), "", LoadPosition, "rb");
5118 void SaveGameProc(w, event, prms, nprms)
5124 FileNamePopUp(_("Save game file name?"),
5125 DefaultFileName(appData.oldSaveStyle ? "game" : "pgn"),
5129 void SavePositionProc(w, event, prms, nprms)
5135 FileNamePopUp(_("Save position file name?"),
5136 DefaultFileName(appData.oldSaveStyle ? "pos" : "fen"),
5140 void ReloadCmailMsgProc(w, event, prms, nprms)
5146 ReloadCmailMsgEvent(FALSE);
5149 void MailMoveProc(w, event, prms, nprms)
5158 /* this variable is shared between CopyPositionProc and SendPositionSelection */
5159 static char *selected_fen_position=NULL;
5162 SendPositionSelection(Widget w, Atom *selection, Atom *target,
5163 Atom *type_return, XtPointer *value_return,
5164 unsigned long *length_return, int *format_return)
5166 char *selection_tmp;
5168 if (!selected_fen_position) return False; /* should never happen */
5169 if (*target == XA_STRING){
5170 /* note: since no XtSelectionDoneProc was registered, Xt will
5171 * automatically call XtFree on the value returned. So have to
5172 * make a copy of it allocated with XtMalloc */
5173 selection_tmp= XtMalloc(strlen(selected_fen_position)+16);
5174 strcpy(selection_tmp, selected_fen_position);
5176 *value_return=selection_tmp;
5177 *length_return=strlen(selection_tmp);
5178 *type_return=XA_STRING;
5179 *format_return = 8; /* bits per byte */
5186 /* note: when called from menu all parameters are NULL, so no clue what the
5187 * Widget which was clicked on was, or what the click event was
5189 void CopyPositionProc(w, event, prms, nprms)
5197 if (selected_fen_position) free(selected_fen_position);
5198 selected_fen_position = (char *)PositionToFEN(currentMove, NULL);
5199 if (!selected_fen_position) return;
5200 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
5202 SendPositionSelection,
5203 NULL/* lose_ownership_proc */ ,
5204 NULL/* transfer_done_proc */);
5206 free(selected_fen_position);
5207 selected_fen_position=NULL;
5211 /* function called when the data to Paste is ready */
5213 PastePositionCB(Widget w, XtPointer client_data, Atom *selection,
5214 Atom *type, XtPointer value, unsigned long *len, int *format)
5217 if (value==NULL || *len==0) return; /* nothing had been selected to copy */
5218 fenstr[*len]='\0'; /* normally this string is terminated, but be safe */
5219 EditPositionPasteFEN(fenstr);
5223 /* called when Paste Position button is pressed,
5224 * all parameters will be NULL */
5225 void PastePositionProc(w, event, prms, nprms)
5231 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
5232 /* (XtSelectionCallbackProc) */ PastePositionCB,
5233 NULL, /* client_data passed to PastePositionCB */
5235 /* better to use the time field from the event that triggered the
5236 * call to this function, but that isn't trivial to get
5244 SendGameSelection(Widget w, Atom *selection, Atom *target,
5245 Atom *type_return, XtPointer *value_return,
5246 unsigned long *length_return, int *format_return)
5248 char *selection_tmp;
5250 if (*target == XA_STRING){
5251 FILE* f = fopen(gameCopyFilename, "r");
5254 if (f == NULL) return False;
5258 selection_tmp = XtMalloc(len + 1);
5259 count = fread(selection_tmp, 1, len, f);
5261 XtFree(selection_tmp);
5264 selection_tmp[len] = NULLCHAR;
5265 *value_return = selection_tmp;
5266 *length_return = len;
5267 *type_return = XA_STRING;
5268 *format_return = 8; /* bits per byte */
5275 /* note: when called from menu all parameters are NULL, so no clue what the
5276 * Widget which was clicked on was, or what the click event was
5278 void CopyGameProc(w, event, prms, nprms)
5286 ret = SaveGameToFile(gameCopyFilename, FALSE);
5289 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
5292 NULL/* lose_ownership_proc */ ,
5293 NULL/* transfer_done_proc */);
5296 /* function called when the data to Paste is ready */
5298 PasteGameCB(Widget w, XtPointer client_data, Atom *selection,
5299 Atom *type, XtPointer value, unsigned long *len, int *format)
5302 if (value == NULL || *len == 0) {
5303 return; /* nothing had been selected to copy */
5305 f = fopen(gamePasteFilename, "w");
5307 DisplayError(_("Can't open temp file"), errno);
5310 fwrite(value, 1, *len, f);
5313 LoadGameFromFile(gamePasteFilename, 0, gamePasteFilename, TRUE);
5316 /* called when Paste Game button is pressed,
5317 * all parameters will be NULL */
5318 void PasteGameProc(w, event, prms, nprms)
5324 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
5325 /* (XtSelectionCallbackProc) */ PasteGameCB,
5326 NULL, /* client_data passed to PasteGameCB */
5328 /* better to use the time field from the event that triggered the
5329 * call to this function, but that isn't trivial to get
5339 SaveGameProc(NULL, NULL, NULL, NULL);
5342 void AnalyzeModeProc(w, event, prms, nprms)
5350 if (!first.analysisSupport) {
5351 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
5352 DisplayError(buf, 0);
5355 /* [DM] icsEngineAnalyze [HGM] This is horrible code; reverse the gameMode and isEngineAnalyze tests! */
5356 if (appData.icsActive) {
5357 if (gameMode != IcsObserving) {
5358 sprintf(buf,_("You are not observing a game"));
5359 DisplayError(buf, 0);
5361 if (appData.icsEngineAnalyze) {
5362 if (appData.debugMode)
5363 fprintf(debugFP, _("Found unexpected active ICS engine analyze \n"));
5369 /* if enable, use want disable icsEngineAnalyze */
5370 if (appData.icsEngineAnalyze) {
5375 appData.icsEngineAnalyze = TRUE;
5376 if (appData.debugMode)
5377 fprintf(debugFP, _("ICS engine analyze starting... \n"));
5379 if (!appData.showThinking)
5380 ShowThinkingProc(NULL,NULL);
5385 void AnalyzeFileProc(w, event, prms, nprms)
5391 if (!first.analysisSupport) {
5393 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
5394 DisplayError(buf, 0);
5399 if (!appData.showThinking)
5400 ShowThinkingProc(NULL,NULL);
5403 FileNamePopUp(_("File to analyze"), "", LoadGamePopUp, "rb");
5404 AnalysisPeriodicEvent(1);
5408 void EditGameProc(w, event, prms, nprms)
5417 void EditPositionProc(w, event, prms, nprms)
5423 EditPositionEvent();
5426 void TrainingProc(w, event, prms, nprms)
5435 void EditCommentProc(w, event, prms, nprms)
5442 EditCommentPopDown();
5448 void IcsInputBoxProc(w, event, prms, nprms)
5454 if (ICSInputBoxUp) {
5455 ICSInputBoxPopDown();
5462 void EnterKeyProc(w, event, prms, nprms)
5468 if (ICSInputBoxUp == True)
5472 void AlwaysQueenProc(w, event, prms, nprms)
5480 appData.alwaysPromoteToQueen = !appData.alwaysPromoteToQueen;
5482 if (appData.alwaysPromoteToQueen) {
5483 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5485 XtSetArg(args[0], XtNleftBitmap, None);
5487 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
5491 void AnimateDraggingProc(w, event, prms, nprms)
5499 appData.animateDragging = !appData.animateDragging;
5501 if (appData.animateDragging) {
5502 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5505 XtSetArg(args[0], XtNleftBitmap, None);
5507 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Dragging"),
5511 void AnimateMovingProc(w, event, prms, nprms)
5519 appData.animate = !appData.animate;
5521 if (appData.animate) {
5522 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5525 XtSetArg(args[0], XtNleftBitmap, None);
5527 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
5531 void AutobsProc(w, event, prms, nprms)
5539 appData.autoObserve = !appData.autoObserve;
5541 if (appData.autoObserve) {
5542 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5544 XtSetArg(args[0], XtNleftBitmap, None);
5546 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
5550 void AutoraiseProc(w, event, prms, nprms)
5558 appData.autoRaiseBoard = !appData.autoRaiseBoard;
5560 if (appData.autoRaiseBoard) {
5561 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5563 XtSetArg(args[0], XtNleftBitmap, None);
5565 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Raise Board"),
5569 void AutosaveProc(w, event, prms, nprms)
5577 appData.autoSaveGames = !appData.autoSaveGames;
5579 if (appData.autoSaveGames) {
5580 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5582 XtSetArg(args[0], XtNleftBitmap, None);
5584 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
5588 void BlindfoldProc(w, event, prms, nprms)
5596 appData.blindfold = !appData.blindfold;
5598 if (appData.blindfold) {
5599 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5601 XtSetArg(args[0], XtNleftBitmap, None);
5603 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Blindfold"),
5606 DrawPosition(True, NULL);
5609 void TestLegalityProc(w, event, prms, nprms)
5617 appData.testLegality = !appData.testLegality;
5619 if (appData.testLegality) {
5620 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5622 XtSetArg(args[0], XtNleftBitmap, None);
5624 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Test Legality"),
5629 void FlashMovesProc(w, event, prms, nprms)
5637 if (appData.flashCount == 0) {
5638 appData.flashCount = 3;
5640 appData.flashCount = -appData.flashCount;
5643 if (appData.flashCount > 0) {
5644 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5646 XtSetArg(args[0], XtNleftBitmap, None);
5648 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flash Moves"),
5653 void HighlightDraggingProc(w, event, prms, nprms)
5661 appData.highlightDragging = !appData.highlightDragging;
5663 if (appData.highlightDragging) {
5664 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5666 XtSetArg(args[0], XtNleftBitmap, None);
5668 XtSetValues(XtNameToWidget(menuBarWidget,
5669 "menuOptions.Highlight Dragging"), args, 1);
5673 void HighlightLastMoveProc(w, event, prms, nprms)
5681 appData.highlightLastMove = !appData.highlightLastMove;
5683 if (appData.highlightLastMove) {
5684 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5686 XtSetArg(args[0], XtNleftBitmap, None);
5688 XtSetValues(XtNameToWidget(menuBarWidget,
5689 "menuOptions.Highlight Last Move"), args, 1);
5692 void IcsAlarmProc(w, event, prms, nprms)
5700 appData.icsAlarm = !appData.icsAlarm;
5702 if (appData.icsAlarm) {
5703 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5705 XtSetArg(args[0], XtNleftBitmap, None);
5707 XtSetValues(XtNameToWidget(menuBarWidget,
5708 "menuOptions.ICS Alarm"), args, 1);
5711 void MoveSoundProc(w, event, prms, nprms)
5719 appData.ringBellAfterMoves = !appData.ringBellAfterMoves;
5721 if (appData.ringBellAfterMoves) {
5722 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5724 XtSetArg(args[0], XtNleftBitmap, None);
5726 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
5731 void OldSaveStyleProc(w, event, prms, nprms)
5739 appData.oldSaveStyle = !appData.oldSaveStyle;
5741 if (appData.oldSaveStyle) {
5742 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5744 XtSetArg(args[0], XtNleftBitmap, None);
5746 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Old Save Style"),
5750 void PeriodicUpdatesProc(w, event, prms, nprms)
5758 PeriodicUpdatesEvent(!appData.periodicUpdates);
5760 if (appData.periodicUpdates) {
5761 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5763 XtSetArg(args[0], XtNleftBitmap, None);
5765 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Periodic Updates"),
5769 void PonderNextMoveProc(w, event, prms, nprms)
5777 PonderNextMoveEvent(!appData.ponderNextMove);
5779 if (appData.ponderNextMove) {
5780 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5782 XtSetArg(args[0], XtNleftBitmap, None);
5784 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Ponder Next Move"),
5788 void PopupExitMessageProc(w, event, prms, nprms)
5796 appData.popupExitMessage = !appData.popupExitMessage;
5798 if (appData.popupExitMessage) {
5799 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5801 XtSetArg(args[0], XtNleftBitmap, None);
5803 XtSetValues(XtNameToWidget(menuBarWidget,
5804 "menuOptions.Popup Exit Message"), args, 1);
5807 void PopupMoveErrorsProc(w, event, prms, nprms)
5815 appData.popupMoveErrors = !appData.popupMoveErrors;
5817 if (appData.popupMoveErrors) {
5818 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5820 XtSetArg(args[0], XtNleftBitmap, None);
5822 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Popup Move Errors"),
5826 void PremoveProc(w, event, prms, nprms)
5834 appData.premove = !appData.premove;
5836 if (appData.premove) {
5837 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5839 XtSetArg(args[0], XtNleftBitmap, None);
5841 XtSetValues(XtNameToWidget(menuBarWidget,
5842 "menuOptions.Premove"), args, 1);
5845 void QuietPlayProc(w, event, prms, nprms)
5853 appData.quietPlay = !appData.quietPlay;
5855 if (appData.quietPlay) {
5856 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5858 XtSetArg(args[0], XtNleftBitmap, None);
5860 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Quiet Play"),
5864 void DebugProc(w, event, prms, nprms)
5870 appData.debugMode = !appData.debugMode;
5873 void AboutGameProc(w, event, prms, nprms)
5882 void NothingProc(w, event, prms, nprms)
5891 void Iconify(w, event, prms, nprms)
5900 XtSetArg(args[0], XtNiconic, True);
5901 XtSetValues(shellWidget, args, 1);
5904 void DisplayMessage(message, extMessage)
5905 gchar *message, *extMessage;
5912 snprintf(buf, sizeof(buf), "%s %s", message, extMessage);
5915 message = extMessage;
5918 gtk_label_set_text( GTK_LABEL(gtk_builder_get_object (builder, "Messages")),message);
5923 void DisplayTitle(text)
5926 gchar title[MSG_SIZ];
5928 if (text == NULL) text = "";
5930 if (appData.titleInWindow)
5935 if (*text != NULLCHAR)
5937 strcpy(title, text);
5939 else if (appData.icsActive)
5941 snprintf(title, sizeof(title), "%s: %s", programName, appData.icsHost);
5943 else if (appData.cmailGameName[0] != NULLCHAR)
5945 snprintf(title,sizeof(title), "%s: %s", programName, "CMail");
5947 // [HGM] license: This stuff should really be done in back-end, but WinBoard already had a pop-up for it
5949 else if (gameInfo.variant == VariantGothic)
5951 strcpy(title, GOTHIC);
5955 else if (gameInfo.variant == VariantFalcon)
5957 strcpy(title, FALCON);
5960 else if (appData.noChessProgram)
5962 strcpy(title, programName);
5966 snprintf(title,sizeof(title), "%s: %s", programName, first.tidy);
5968 gtk_window_set_title(GTK_WINDOW(GUI_Window),title);
5974 void DisplayError(message, error)
5981 if (appData.debugMode || appData.matchMode) {
5982 fprintf(stderr, "%s: %s\n", programName, message);
5985 if (appData.debugMode || appData.matchMode) {
5986 fprintf(stderr, "%s: %s: %s\n",
5987 programName, message, strerror(error));
5989 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
5992 ErrorPopUp(_("Error"), message, FALSE);
5996 void DisplayMoveError(message)
6001 DrawPosition(FALSE, NULL);
6002 if (appData.debugMode || appData.matchMode) {
6003 fprintf(stderr, "%s: %s\n", programName, message);
6005 if (appData.popupMoveErrors) {
6006 ErrorPopUp(_("Error"), message, FALSE);
6008 DisplayMessage(message, "");
6013 void DisplayFatalError(message, error, status)
6019 errorExitStatus = status;
6021 fprintf(stderr, "%s: %s\n", programName, message);
6023 fprintf(stderr, "%s: %s: %s\n",
6024 programName, message, strerror(error));
6025 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
6028 if (appData.popupExitMessage && boardWidget && XtIsRealized(boardWidget)) {
6029 ErrorPopUp(status ? _("Fatal Error") : _("Exiting"), message, TRUE);
6035 void DisplayInformation(message)
6039 ErrorPopUp(_("Information"), message, TRUE);
6042 void DisplayNote(message)
6046 ErrorPopUp(_("Note"), message, FALSE);
6050 NullXErrorCheck(dpy, error_event)
6052 XErrorEvent *error_event;
6057 void DisplayIcsInteractionTitle(message)
6060 if (oldICSInteractionTitle == NULL) {
6061 /* Magic to find the old window title, adapted from vim */
6062 char *wina = getenv("WINDOWID");
6064 Window win = (Window) atoi(wina);
6065 Window root, parent, *children;
6066 unsigned int nchildren;
6067 int (*oldHandler)() = XSetErrorHandler(NullXErrorCheck);
6069 if (XFetchName(xDisplay, win, &oldICSInteractionTitle)) break;
6070 if (!XQueryTree(xDisplay, win, &root, &parent,
6071 &children, &nchildren)) break;
6072 if (children) XFree((void *)children);
6073 if (parent == root || parent == 0) break;
6076 XSetErrorHandler(oldHandler);
6078 if (oldICSInteractionTitle == NULL) {
6079 oldICSInteractionTitle = "xterm";
6082 printf("\033]0;%s\007", message);
6086 char pendingReplyPrefix[MSG_SIZ];
6087 ProcRef pendingReplyPR;
6089 void AskQuestionProc(w, event, prms, nprms)
6096 fprintf(stderr, _("AskQuestionProc needed 4 parameters, got %d\n"),
6100 AskQuestionEvent(prms[0], prms[1], prms[2], prms[3]);
6103 void AskQuestionPopDown()
6105 if (!askQuestionUp) return;
6106 XtPopdown(askQuestionShell);
6107 XtDestroyWidget(askQuestionShell);
6108 askQuestionUp = False;
6111 void AskQuestionReplyAction(w, event, prms, nprms)
6121 reply = XawDialogGetValueString(w = XtParent(w));
6122 strcpy(buf, pendingReplyPrefix);
6123 if (*buf) strcat(buf, " ");
6126 OutputToProcess(pendingReplyPR, buf, strlen(buf), &err);
6127 AskQuestionPopDown();
6129 if (err) DisplayFatalError(_("Error writing to chess program"), err, 0);
6132 void AskQuestionCallback(w, client_data, call_data)
6134 XtPointer client_data, call_data;
6139 XtSetArg(args[0], XtNlabel, &name);
6140 XtGetValues(w, args, 1);
6142 if (strcmp(name, _("cancel")) == 0) {
6143 AskQuestionPopDown();
6145 AskQuestionReplyAction(w, NULL, NULL, NULL);
6149 void AskQuestion(title, question, replyPrefix, pr)
6150 char *title, *question, *replyPrefix;
6154 Widget popup, layout, dialog, edit;
6160 strcpy(pendingReplyPrefix, replyPrefix);
6161 pendingReplyPR = pr;
6164 XtSetArg(args[i], XtNresizable, True); i++;
6165 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
6166 askQuestionShell = popup =
6167 XtCreatePopupShell(title, transientShellWidgetClass,
6168 shellWidget, args, i);
6171 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
6172 layoutArgs, XtNumber(layoutArgs));
6175 XtSetArg(args[i], XtNlabel, question); i++;
6176 XtSetArg(args[i], XtNvalue, ""); i++;
6177 XtSetArg(args[i], XtNborderWidth, 0); i++;
6178 dialog = XtCreateManagedWidget("question", dialogWidgetClass,
6181 XawDialogAddButton(dialog, _("enter"), AskQuestionCallback,
6182 (XtPointer) dialog);
6183 XawDialogAddButton(dialog, _("cancel"), AskQuestionCallback,
6184 (XtPointer) dialog);
6186 XtRealizeWidget(popup);
6187 CatchDeleteWindow(popup, "AskQuestionPopDown");
6189 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
6190 &x, &y, &win_x, &win_y, &mask);
6192 XtSetArg(args[0], XtNx, x - 10);
6193 XtSetArg(args[1], XtNy, y - 30);
6194 XtSetValues(popup, args, 2);
6196 XtPopup(popup, XtGrabExclusive);
6197 askQuestionUp = True;
6199 edit = XtNameToWidget(dialog, "*value");
6200 XtSetKeyboardFocus(popup, edit);
6208 if (*name == NULLCHAR) {
6210 } else if (strcmp(name, "$") == 0) {
6211 putc(BELLCHAR, stderr);
6214 snprintf(buf, sizeof(buf), "%s '%s' &", appData.soundProgram, name);
6222 PlaySound(appData.soundMove);
6228 PlaySound(appData.soundIcsWin);
6234 PlaySound(appData.soundIcsLoss);
6240 PlaySound(appData.soundIcsDraw);
6244 PlayIcsUnfinishedSound()
6246 PlaySound(appData.soundIcsUnfinished);
6252 PlaySound(appData.soundIcsAlarm);
6258 system("stty echo");
6264 system("stty -echo");
6268 Colorize(cc, continuation)
6273 int count, outCount, error;
6275 if (textColors[(int)cc].bg > 0) {
6276 if (textColors[(int)cc].fg > 0) {
6277 sprintf(buf, "\033[0;%d;%d;%dm", textColors[(int)cc].attr,
6278 textColors[(int)cc].fg, textColors[(int)cc].bg);
6280 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
6281 textColors[(int)cc].bg);
6284 if (textColors[(int)cc].fg > 0) {
6285 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
6286 textColors[(int)cc].fg);
6288 sprintf(buf, "\033[0;%dm", textColors[(int)cc].attr);
6291 count = strlen(buf);
6292 outCount = OutputToProcess(NoProc, buf, count, &error);
6293 if (outCount < count) {
6294 DisplayFatalError(_("Error writing to display"), error, 1);
6297 if (continuation) return;
6300 PlaySound(appData.soundShout);
6303 PlaySound(appData.soundSShout);
6306 PlaySound(appData.soundChannel1);
6309 PlaySound(appData.soundChannel);
6312 PlaySound(appData.soundKibitz);
6315 PlaySound(appData.soundTell);
6317 case ColorChallenge:
6318 PlaySound(appData.soundChallenge);
6321 PlaySound(appData.soundRequest);
6324 PlaySound(appData.soundSeek);
6335 return getpwuid(getuid())->pw_name;
6338 static char *ExpandPathName(path)
6341 static char static_buf[2000];
6342 char *d, *s, buf[2000];
6348 while (*s && isspace(*s))
6357 if (*(s+1) == '/') {
6358 strcpy(d, getpwuid(getuid())->pw_dir);
6363 *strchr(buf, '/') = 0;
6364 pwd = getpwnam(buf);
6367 fprintf(stderr, _("ERROR: Unknown user %s (in path %s)\n"),
6371 strcpy(d, pwd->pw_dir);
6372 strcat(d, strchr(s+1, '/'));
6383 static char host_name[MSG_SIZ];
6385 #if HAVE_GETHOSTNAME
6386 gethostname(host_name, MSG_SIZ);
6388 #else /* not HAVE_GETHOSTNAME */
6389 # if HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H
6390 sysinfo(SI_HOSTNAME, host_name, MSG_SIZ);
6392 # else /* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
6394 # endif/* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
6395 #endif /* not HAVE_GETHOSTNAME */
6398 guint delayedEventTimerTag = 0;
6399 DelayedEventCallback delayedEventCallback = 0;
6402 FireDelayedEvent(data)
6406 g_source_remove(delayedEventTimerTag);
6407 delayedEventTimerTag = 0;
6410 delayedEventCallback();
6416 ScheduleDelayedEvent(cb, millisec)
6417 DelayedEventCallback cb; guint millisec;
6419 if(delayedEventTimerTag && delayedEventCallback == cb)
6420 // [HGM] alive: replace, rather than add or flush identical event
6421 g_source_remove(delayedEventTimerTag);
6422 delayedEventCallback = cb;
6423 delayedEventTimerTag = g_timeout_add(millisec,(GSourceFunc) FireDelayedEvent, NULL);
6427 DelayedEventCallback
6430 if (delayedEventTimerTag)
6432 return delayedEventCallback;
6441 CancelDelayedEvent()
6443 if (delayedEventTimerTag)
6445 g_source_remove(delayedEventTimerTag);
6446 delayedEventTimerTag = 0;
6452 guint loadGameTimerTag = 0;
6454 int LoadGameTimerRunning()
6456 return loadGameTimerTag != 0;
6459 int StopLoadGameTimer()
6461 if (loadGameTimerTag != 0) {
6462 g_source_remove(loadGameTimerTag);
6463 loadGameTimerTag = 0;
6471 LoadGameTimerCallback(data)
6475 g_source_remove(loadGameTimerTag);
6476 loadGameTimerTag = 0;
6483 StartLoadGameTimer(millisec)
6487 g_timeout_add( millisec, (GSourceFunc) LoadGameTimerCallback, NULL);
6491 guint analysisClockTag = 0;
6494 AnalysisClockCallback(data)
6497 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile
6498 || appData.icsEngineAnalyze)
6500 AnalysisPeriodicEvent(0);
6501 return 1; /* keep on going */
6503 return 0; /* stop timer */
6507 StartAnalysisClock()
6510 g_timeout_add( 2000,(GSourceFunc) AnalysisClockCallback, NULL);
6514 guint clockTimerTag = 0;
6516 int ClockTimerRunning()
6518 return clockTimerTag != 0;
6521 int StopClockTimer()
6523 if (clockTimerTag != 0)
6525 g_source_remove(clockTimerTag);
6536 ClockTimerCallback(data)
6540 g_source_remove(clockTimerTag);
6548 StartClockTimer(millisec)
6551 clockTimerTag = g_timeout_add(millisec,(GSourceFunc) ClockTimerCallback,NULL);
6556 DisplayTimerLabel(w, color, timer, highlight)
6565 if (appData.clockMode) {
6566 sprintf(buf, "%s: %s", color, TimeString(timer));
6568 sprintf(buf, "%s ", color);
6570 gtk_label_set_text(GTK_LABEL(w),buf);
6572 /* check for low time warning */
6573 // Pixel foregroundOrWarningColor = timerForegroundPixel;
6576 // appData.lowTimeWarning &&
6577 // (timer / 1000) < appData.icsAlarmTime)
6578 // foregroundOrWarningColor = lowTimeWarningColor;
6580 // if (appData.clockMode) {
6581 // sprintf(buf, "%s: %s", color, TimeString(timer));
6582 // XtSetArg(args[0], XtNlabel, buf);
6584 // sprintf(buf, "%s ", color);
6585 // XtSetArg(args[0], XtNlabel, buf);
6590 // XtSetArg(args[1], XtNbackground, foregroundOrWarningColor);
6591 // XtSetArg(args[2], XtNforeground, timerBackgroundPixel);
6593 // XtSetArg(args[1], XtNbackground, timerBackgroundPixel);
6594 // XtSetArg(args[2], XtNforeground, foregroundOrWarningColor);
6597 // XtSetValues(w, args, 3);
6602 DisplayWhiteClock(timeRemaining, highlight)
6606 if(appData.noGUI) return;
6608 DisplayTimerLabel(GUI_Whiteclock, _("White"), timeRemaining, highlight);
6609 if (highlight && WindowIcon == BlackIcon)
6611 WindowIcon = WhiteIcon;
6612 gtk_window_set_icon(GTK_WINDOW(GUI_Window),WindowIcon);
6617 DisplayBlackClock(timeRemaining, highlight)
6621 if(appData.noGUI) return;
6623 DisplayTimerLabel(GUI_Blackclock, _("Black"), timeRemaining, highlight);
6624 if (highlight && WindowIcon == WhiteIcon)
6626 WindowIcon = BlackIcon;
6627 gtk_window_set_icon(GTK_WINDOW(GUI_Window),WindowIcon);
6645 int StartChildProcess(cmdLine, dir, pr)
6652 int to_prog[2], from_prog[2];
6656 if (appData.debugMode) {
6657 fprintf(stderr, "StartChildProcess (dir=\"%s\") %s\n",dir, cmdLine);
6660 /* We do NOT feed the cmdLine to the shell; we just
6661 parse it into blank-separated arguments in the
6662 most simple-minded way possible.
6665 strcpy(buf, cmdLine);
6670 if (p == NULL) break;
6675 SetUpChildIO(to_prog, from_prog);
6678 signal(SIGWINCH, TermSizeSigHandler);
6681 if ((pid = fork()) == 0) {
6683 // [HGM] PSWBTM: made order resistant against case where fd of created pipe was 0 or 1
6684 close(to_prog[1]); // first close the unused pipe ends
6685 close(from_prog[0]);
6686 dup2(to_prog[0], 0); // to_prog was created first, nd is the only one to use 0 or 1
6687 dup2(from_prog[1], 1);
6688 if(to_prog[0] >= 2) close(to_prog[0]); // if 0 or 1, the dup2 already cosed the original
6689 close(from_prog[1]); // and closing again loses one of the pipes!
6690 if(fileno(stderr) >= 2) // better safe than sorry...
6691 dup2(1, fileno(stderr)); /* force stderr to the pipe */
6693 if (dir[0] != NULLCHAR && chdir(dir) != 0) {
6698 nice(appData.niceEngines); // [HGM] nice: adjust priority of engine proc
6700 execvp(argv[0], argv);
6702 /* If we get here, exec failed */
6707 /* Parent process */
6709 close(from_prog[1]);
6711 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
6714 cp->fdFrom = from_prog[0];
6715 cp->fdTo = to_prog[1];
6720 // [HGM] kill: implement the 'hard killing' of AS's Winboard_x
6721 static RETSIGTYPE AlarmCallBack(int n)
6727 DestroyChildProcess(pr, signalType)
6731 ChildProc *cp = (ChildProc *) pr;
6733 if (cp->kind != CPReal) return;
6735 if (signalType == 10) { // [HGM] kill: if it does not terminate in 3 sec, kill
6736 signal(SIGALRM, AlarmCallBack);
6738 if(wait((int *) 0) == -1) { // process does not terminate on its own accord
6739 kill(cp->pid, SIGKILL); // kill it forcefully
6740 wait((int *) 0); // and wait again
6744 kill(cp->pid, signalType == 9 ? SIGKILL : SIGTERM); // [HGM] kill: use hard kill if so requested
6746 /* Process is exiting either because of the kill or because of
6747 a quit command sent by the backend; either way, wait for it to die.
6756 InterruptChildProcess(pr)
6759 ChildProc *cp = (ChildProc *) pr;
6761 if (cp->kind != CPReal) return;
6762 (void) kill(cp->pid, SIGINT); /* stop it thinking */
6765 int OpenTelnet(host, port, pr)
6770 char cmdLine[MSG_SIZ];
6772 if (port[0] == NULLCHAR) {
6773 snprintf(cmdLine, sizeof(cmdLine), "%s %s", appData.telnetProgram, host);
6775 snprintf(cmdLine, sizeof(cmdLine), "%s %s %s", appData.telnetProgram, host, port);
6777 return StartChildProcess(cmdLine, "", pr);
6780 int OpenTCP(host, port, pr)
6786 DisplayFatalError(_("Socket support is not configured in"), 0, 2);
6787 #else /* !OMIT_SOCKETS */
6789 struct sockaddr_in sa;
6791 unsigned short uport;
6794 if ((s = socket(AF_INET, SOCK_STREAM, 6)) < 0) {
6798 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
6799 sa.sin_family = AF_INET;
6800 sa.sin_addr.s_addr = INADDR_ANY;
6801 uport = (unsigned short) 0;
6802 sa.sin_port = htons(uport);
6803 if (bind(s, (struct sockaddr *) &sa, sizeof(struct sockaddr_in)) < 0) {
6807 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
6808 if (!(hp = gethostbyname(host))) {
6810 if (sscanf(host, "%d.%d.%d.%d", &b0, &b1, &b2, &b3) == 4) {
6811 hp = (struct hostent *) calloc(1, sizeof(struct hostent));
6812 hp->h_addrtype = AF_INET;
6814 hp->h_addr_list = (char **) calloc(2, sizeof(char *));
6815 hp->h_addr_list[0] = (char *) malloc(4);
6816 hp->h_addr_list[0][0] = b0;
6817 hp->h_addr_list[0][1] = b1;
6818 hp->h_addr_list[0][2] = b2;
6819 hp->h_addr_list[0][3] = b3;
6824 sa.sin_family = hp->h_addrtype;
6825 uport = (unsigned short) atoi(port);
6826 sa.sin_port = htons(uport);
6827 memcpy((char *) &sa.sin_addr, hp->h_addr, hp->h_length);
6829 if (connect(s, (struct sockaddr *) &sa,
6830 sizeof(struct sockaddr_in)) < 0) {
6834 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
6841 #endif /* !OMIT_SOCKETS */
6846 int OpenCommPort(name, pr)
6853 fd = open(name, 2, 0);
6854 if (fd < 0) return errno;
6856 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
6866 int OpenLoopback(pr)
6872 SetUpChildIO(to, from);
6874 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
6877 cp->fdFrom = to[0]; /* note not from[0]; we are doing a loopback */
6884 int OpenRcmd(host, user, cmd, pr)
6885 char *host, *user, *cmd;
6888 DisplayFatalError(_("internal rcmd not implemented for Unix"), 0, 1);
6892 #define INPUT_SOURCE_BUF_SIZE 8192
6901 char buf[INPUT_SOURCE_BUF_SIZE];
6906 DoInputCallback(io,cond,data)
6911 /* read input from one of the input source (for example a chess program, ICS, etc).
6912 * and call a function that will handle the input
6915 int count; /* how many bytes did we read */
6919 /* All information (callback function, file descriptor, etc) is
6920 * saved in an InputSource structure
6922 InputSource *is = (InputSource *) data;
6926 count = read(is->fd, is->unused,
6927 INPUT_SOURCE_BUF_SIZE - (is->unused - is->buf));
6931 (is->func)(is, is->closure, is->buf, count, count ? errno : 0);
6934 is->unused += count;
6936 /* break input into lines and call the callback function on each
6939 while (p < is->unused)
6941 q = memchr(p, '\n', is->unused - p);
6942 if (q == NULL) break;
6944 (is->func)(is, is->closure, p, q - p, 0);
6947 /* remember not yet used part of the buffer */
6949 while (p < is->unused)
6957 /* read maximum length of input buffer and send the whole buffer
6958 * to the callback function
6960 count = read(is->fd, is->buf, INPUT_SOURCE_BUF_SIZE);
6965 (is->func)(is, is->closure, is->buf, count, error);
6971 InputSourceRef AddInputSource(pr, lineByLine, func, closure)
6978 GIOChannel *channel;
6979 ChildProc *cp = (ChildProc *) pr;
6981 is = (InputSource *) calloc(1, sizeof(InputSource));
6982 is->lineByLine = lineByLine;
6986 is->fd = fileno(stdin);
6988 is->kind = cp->kind;
6989 is->fd = cp->fdFrom;
6992 is->unused = is->buf;
6996 // is->xid = XtAppAddInput(appContext, is->fd,
6997 // (XtPointer) (XtInputReadMask),
6998 // (XtInputCallbackProc) DoInputCallback,
7002 /* TODO: will this work on windows?*/
7003 printf("DEBUG: fd=%d %d\n",is->fd,is);
7005 channel = g_io_channel_unix_new(is->fd);
7006 g_io_channel_set_close_on_unref (channel, TRUE);
7007 is->sid = g_io_add_watch(channel, G_IO_IN,(GIOFunc) DoInputCallback, is);
7008 is->closure = closure;
7009 return (InputSourceRef) is;
7013 RemoveInputSource(isr)
7016 InputSource *is = (InputSource *) isr;
7018 if (is->sid == 0) return;
7019 g_source_remove(is->sid);
7024 int OutputToProcess(pr, message, count, outError)
7030 ChildProc *cp = (ChildProc *) pr;
7034 outCount = fwrite(message, 1, count, stdout);
7036 outCount = write(cp->fdTo, message, count);
7046 /* Output message to process, with "ms" milliseconds of delay
7047 between each character. This is needed when sending the logon
7048 script to ICC, which for some reason doesn't like the
7049 instantaneous send. */
7050 int OutputToProcessDelayed(pr, message, count, outError, msdelay)
7057 ChildProc *cp = (ChildProc *) pr;
7062 r = write(cp->fdTo, message++, 1);
7075 /**** Animation code by Hugh Fisher, DCS, ANU.
7077 Known problem: if a window overlapping the board is
7078 moved away while a piece is being animated underneath,
7079 the newly exposed area won't be updated properly.
7080 I can live with this.
7082 Known problem: if you look carefully at the animation
7083 of pieces in mono mode, they are being drawn as solid
7084 shapes without interior detail while moving. Fixing
7085 this would be a major complication for minimal return.
7088 /* Masks for XPM pieces. Black and white pieces can have
7089 different shapes, but in the interest of retaining my
7090 sanity pieces must have the same outline on both light
7091 and dark squares, and all pieces must use the same
7092 background square colors/images. */
7094 static int xpmDone = 0;
7097 CreateAnimMasks (pieceDepth)
7104 unsigned long plane;
7107 /* just return for gtk at the moment */
7110 /* Need a bitmap just to get a GC with right depth */
7111 buf = XCreatePixmap(xDisplay, xBoardWindow,
7113 values.foreground = 1;
7114 values.background = 0;
7115 /* Don't use XtGetGC, not read only */
7116 maskGC = XCreateGC(xDisplay, buf,
7117 GCForeground | GCBackground, &values);
7118 XFreePixmap(xDisplay, buf);
7120 buf = XCreatePixmap(xDisplay, xBoardWindow,
7121 squareSize, squareSize, pieceDepth);
7122 values.foreground = XBlackPixel(xDisplay, xScreen);
7123 values.background = XWhitePixel(xDisplay, xScreen);
7124 bufGC = XCreateGC(xDisplay, buf,
7125 GCForeground | GCBackground, &values);
7127 for (piece = WhitePawn; piece <= BlackKing; piece++) {
7128 /* Begin with empty mask */
7129 if(!xpmDone) // [HGM] pieces: keep using existing
7130 xpmMask[piece] = XCreatePixmap(xDisplay, xBoardWindow,
7131 squareSize, squareSize, 1);
7132 XSetFunction(xDisplay, maskGC, GXclear);
7133 XFillRectangle(xDisplay, xpmMask[piece], maskGC,
7134 0, 0, squareSize, squareSize);
7136 /* Take a copy of the piece */
7141 XSetFunction(xDisplay, bufGC, GXcopy);
7142 XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % (int)BlackPawn],
7144 0, 0, squareSize, squareSize, 0, 0);
7146 /* XOR the background (light) over the piece */
7147 XSetFunction(xDisplay, bufGC, GXxor);
7149 XCopyArea(xDisplay, xpmLightSquare, buf, bufGC,
7150 0, 0, squareSize, squareSize, 0, 0);
7152 XSetForeground(xDisplay, bufGC, lightSquareColor);
7153 XFillRectangle(xDisplay, buf, bufGC, 0, 0, squareSize, squareSize);
7156 /* We now have an inverted piece image with the background
7157 erased. Construct mask by just selecting all the non-zero
7158 pixels - no need to reconstruct the original image. */
7159 XSetFunction(xDisplay, maskGC, GXor);
7161 /* Might be quicker to download an XImage and create bitmap
7162 data from it rather than this N copies per piece, but it
7163 only takes a fraction of a second and there is a much
7164 longer delay for loading the pieces. */
7165 for (n = 0; n < pieceDepth; n ++) {
7166 XCopyPlane(xDisplay, buf, xpmMask[piece], maskGC,
7167 0, 0, squareSize, squareSize,
7173 XFreePixmap(xDisplay, buf);
7174 XFreeGC(xDisplay, bufGC);
7175 XFreeGC(xDisplay, maskGC);
7179 InitAnimState (anim, info)
7181 XWindowAttributes * info;
7186 /* Each buffer is square size, same depth as window */
7187 // anim->saveBuf = XCreatePixmap(xDisplay, xBoardWindow,
7188 // squareSize, squareSize, info->depth);
7189 // anim->newBuf = XCreatePixmap(xDisplay, xBoardWindow,
7190 // squareSize, squareSize, info->depth);
7192 // /* Create a plain GC for blitting */
7193 // mask = GCForeground | GCBackground | GCFunction |
7194 // GCPlaneMask | GCGraphicsExposures;
7195 // values.foreground = XBlackPixel(xDisplay, xScreen);
7196 // values.background = XWhitePixel(xDisplay, xScreen);
7197 // values.function = GXcopy;
7198 // values.plane_mask = AllPlanes;
7199 // values.graphics_exposures = False;
7200 // anim->blitGC = XCreateGC(xDisplay, xBoardWindow, mask, &values);
7202 // /* Piece will be copied from an existing context at
7203 // the start of each new animation/drag. */
7204 // anim->pieceGC = XCreateGC(xDisplay, xBoardWindow, 0, &values);
7206 // /* Outline will be a read-only copy of an existing */
7207 // anim->outlineGC = None;
7213 static VariantClass old = (VariantClass) -1; // [HGM] pieces: redo every time variant changes
7214 XWindowAttributes info;
7216 /* for gtk at the moment just ... */
7219 if (xpmDone && gameInfo.variant == old) return;
7220 if(xpmDone) old = gameInfo.variant; // first time pieces might not be created yet
7221 // XGetWindowAttributes(xDisplay, xBoardWindow, &info);
7223 // InitAnimState(&game, &info);
7224 // InitAnimState(&player, &info);
7226 /* For XPM pieces, we need bitmaps to use as masks. */
7228 // CreateAnimMasks(info.depth);
7234 static Boolean frameWaiting;
7236 static RETSIGTYPE FrameAlarm (sig)
7239 frameWaiting = False;
7240 /* In case System-V style signals. Needed?? */
7241 signal(SIGALRM, FrameAlarm);
7248 struct itimerval delay;
7250 XSync(xDisplay, False);
7253 frameWaiting = True;
7254 signal(SIGALRM, FrameAlarm);
7255 delay.it_interval.tv_sec =
7256 delay.it_value.tv_sec = time / 1000;
7257 delay.it_interval.tv_usec =
7258 delay.it_value.tv_usec = (time % 1000) * 1000;
7259 setitimer(ITIMER_REAL, &delay, NULL);
7260 while (frameWaiting) pause();
7261 delay.it_interval.tv_sec = delay.it_value.tv_sec = 0;
7262 delay.it_interval.tv_usec = delay.it_value.tv_usec = 0;
7263 setitimer(ITIMER_REAL, &delay, NULL);
7273 // XSync(xDisplay, False);
7275 usleep(time * 1000);
7280 /* Convert board position to corner of screen rect and color */
7283 ScreenSquare(column, row, pt, color)
7284 int column; int row; XPoint * pt; int * color;
7287 pt->x = lineGap + ((BOARD_WIDTH-1)-column) * (squareSize + lineGap);
7288 pt->y = lineGap + row * (squareSize + lineGap);
7290 pt->x = lineGap + column * (squareSize + lineGap);
7291 pt->y = lineGap + ((BOARD_HEIGHT-1)-row) * (squareSize + lineGap);
7293 *color = SquareColor(row, column);
7296 /* Convert window coords to square */
7299 BoardSquare(x, y, column, row)
7300 int x; int y; int * column; int * row;
7302 *column = EventToSquare(x, BOARD_WIDTH);
7303 if (flipView && *column >= 0)
7304 *column = BOARD_WIDTH - 1 - *column;
7305 *row = EventToSquare(y, BOARD_HEIGHT);
7306 if (!flipView && *row >= 0)
7307 *row = BOARD_HEIGHT - 1 - *row;
7312 #undef Max /* just in case */
7314 #define Max(a, b) ((a) > (b) ? (a) : (b))
7315 #define Min(a, b) ((a) < (b) ? (a) : (b))
7318 SetRect(rect, x, y, width, height)
7319 XRectangle * rect; int x; int y; int width; int height;
7323 rect->width = width;
7324 rect->height = height;
7327 /* Test if two frames overlap. If they do, return
7328 intersection rect within old and location of
7329 that rect within new. */
7332 Intersect(old, new, size, area, pt)
7333 XPoint * old; XPoint * new;
7334 int size; XRectangle * area; XPoint * pt;
7336 if (old->x > new->x + size || new->x > old->x + size ||
7337 old->y > new->y + size || new->y > old->y + size) {
7340 SetRect(area, Max(new->x - old->x, 0), Max(new->y - old->y, 0),
7341 size - abs(old->x - new->x), size - abs(old->y - new->y));
7342 pt->x = Max(old->x - new->x, 0);
7343 pt->y = Max(old->y - new->y, 0);
7348 /* For two overlapping frames, return the rect(s)
7349 in the old that do not intersect with the new. */
7352 CalcUpdateRects(old, new, size, update, nUpdates)
7353 XPoint * old; XPoint * new; int size;
7354 XRectangle update[]; int * nUpdates;
7358 /* If old = new (shouldn't happen) then nothing to draw */
7359 if (old->x == new->x && old->y == new->y) {
7363 /* Work out what bits overlap. Since we know the rects
7364 are the same size we don't need a full intersect calc. */
7366 /* Top or bottom edge? */
7367 if (new->y > old->y) {
7368 SetRect(&(update[count]), old->x, old->y, size, new->y - old->y);
7370 } else if (old->y > new->y) {
7371 SetRect(&(update[count]), old->x, old->y + size - (old->y - new->y),
7372 size, old->y - new->y);
7375 /* Left or right edge - don't overlap any update calculated above. */
7376 if (new->x > old->x) {
7377 SetRect(&(update[count]), old->x, Max(new->y, old->y),
7378 new->x - old->x, size - abs(new->y - old->y));
7380 } else if (old->x > new->x) {
7381 SetRect(&(update[count]), new->x + size, Max(new->y, old->y),
7382 old->x - new->x, size - abs(new->y - old->y));
7389 /* Generate a series of frame coords from start->mid->finish.
7390 The movement rate doubles until the half way point is
7391 reached, then halves back down to the final destination,
7392 which gives a nice slow in/out effect. The algorithmn
7393 may seem to generate too many intermediates for short
7394 moves, but remember that the purpose is to attract the
7395 viewers attention to the piece about to be moved and
7396 then to where it ends up. Too few frames would be less
7400 Tween(start, mid, finish, factor, frames, nFrames)
7401 XPoint * start; XPoint * mid;
7402 XPoint * finish; int factor;
7403 XPoint frames[]; int * nFrames;
7405 int fraction, n, count;
7409 /* Slow in, stepping 1/16th, then 1/8th, ... */
7411 for (n = 0; n < factor; n++)
7413 for (n = 0; n < factor; n++) {
7414 frames[count].x = start->x + (mid->x - start->x) / fraction;
7415 frames[count].y = start->y + (mid->y - start->y) / fraction;
7417 fraction = fraction / 2;
7421 frames[count] = *mid;
7424 /* Slow out, stepping 1/2, then 1/4, ... */
7426 for (n = 0; n < factor; n++) {
7427 frames[count].x = finish->x - (finish->x - mid->x) / fraction;
7428 frames[count].y = finish->y - (finish->y - mid->y) / fraction;
7430 fraction = fraction * 2;
7435 /* Draw a piece on the screen without disturbing what's there */
7438 SelectGCMask(piece, clip, outline, mask)
7439 ChessSquare piece; GC * clip; GC * outline; Pixmap * mask;
7443 /* Bitmap for piece being moved. */
7444 if (appData.monoMode) {
7445 *mask = *pieceToSolid(piece);
7446 } else if (useImages) {
7448 *mask = xpmMask[piece];
7450 *mask = ximMaskPm[piece];
7453 *mask = *pieceToSolid(piece);
7456 /* GC for piece being moved. Square color doesn't matter, but
7457 since it gets modified we make a copy of the original. */
7459 if (appData.monoMode)
7464 if (appData.monoMode)
7469 // XCopyGC(xDisplay, source, 0xFFFFFFFF, *clip);
7471 /* Outline only used in mono mode and is not modified */
7473 *outline = bwPieceGC;
7475 *outline = wbPieceGC;
7479 OverlayPiece(piece, clip, outline, dest)
7480 ChessSquare piece; GC clip; GC outline; Drawable dest;
7485 /* Draw solid rectangle which will be clipped to shape of piece */
7486 // XFillRectangle(xDisplay, dest, clip,
7487 // 0, 0, squareSize, squareSize)
7489 if (appData.monoMode)
7490 /* Also draw outline in contrasting color for black
7491 on black / white on white cases */
7492 // XCopyPlane(xDisplay, *pieceToOutline(piece), dest, outline,
7493 // 0, 0, squareSize, squareSize, 0, 0, 1)
7496 /* Copy the piece */
7501 // XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
7503 // 0, 0, squareSize, squareSize,
7508 /* Animate the movement of a single piece */
7511 BeginAnimation(anim, piece, startColor, start)
7519 /* The old buffer is initialised with the start square (empty) */
7520 BlankSquare(0, 0, startColor, EmptySquare, anim->saveBuf);
7521 anim->prevFrame = *start;
7523 /* The piece will be drawn using its own bitmap as a matte */
7524 // SelectGCMask(piece, &anim->pieceGC, &anim->outlineGC, &mask);
7525 // XSetClipMask(xDisplay, anim->pieceGC, mask);
7529 AnimationFrame(anim, frame, piece)
7534 XRectangle updates[4];
7539 /* Save what we are about to draw into the new buffer */
7540 // XCopyArea(xDisplay, xBoardWindow, anim->newBuf, anim->blitGC,
7541 // frame->x, frame->y, squareSize, squareSize,
7544 /* Erase bits of the previous frame */
7545 if (Intersect(&anim->prevFrame, frame, squareSize, &overlap, &pt)) {
7546 /* Where the new frame overlapped the previous,
7547 the contents in newBuf are wrong. */
7548 // XCopyArea(xDisplay, anim->saveBuf, anim->newBuf, anim->blitGC,
7549 // overlap.x, overlap.y,
7550 // overlap.width, overlap.height,
7552 /* Repaint the areas in the old that don't overlap new */
7553 CalcUpdateRects(&anim->prevFrame, frame, squareSize, updates, &count);
7554 for (i = 0; i < count; i++)
7555 // XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
7556 // updates[i].x - anim->prevFrame.x,
7557 // updates[i].y - anim->prevFrame.y,
7558 // updates[i].width, updates[i].height,
7559 // updates[i].x, updates[i].y)
7562 /* Easy when no overlap */
7563 // XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
7564 // 0, 0, squareSize, squareSize,
7565 // anim->prevFrame.x, anim->prevFrame.y);
7568 /* Save this frame for next time round */
7569 // XCopyArea(xDisplay, anim->newBuf, anim->saveBuf, anim->blitGC,
7570 // 0, 0, squareSize, squareSize,
7572 anim->prevFrame = *frame;
7574 /* Draw piece over original screen contents, not current,
7575 and copy entire rect. Wipes out overlapping piece images. */
7576 OverlayPiece(piece, anim->pieceGC, anim->outlineGC, anim->newBuf);
7577 // XCopyArea(xDisplay, anim->newBuf, xBoardWindow, anim->blitGC,
7578 // 0, 0, squareSize, squareSize,
7579 // frame->x, frame->y);
7583 EndAnimation (anim, finish)
7587 XRectangle updates[4];
7592 /* The main code will redraw the final square, so we
7593 only need to erase the bits that don't overlap. */
7594 if (Intersect(&anim->prevFrame, finish, squareSize, &overlap, &pt)) {
7595 CalcUpdateRects(&anim->prevFrame, finish, squareSize, updates, &count);
7596 for (i = 0; i < count; i++)
7597 // XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
7598 // updates[i].x - anim->prevFrame.x,
7599 // updates[i].y - anim->prevFrame.y,
7600 // updates[i].width, updates[i].height,
7601 // updates[i].x, updates[i].y)
7604 // XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
7605 // 0, 0, squareSize, squareSize,
7606 // anim->prevFrame.x, anim->prevFrame.y);
7611 FrameSequence(anim, piece, startColor, start, finish, frames, nFrames)
7613 ChessSquare piece; int startColor;
7614 XPoint * start; XPoint * finish;
7615 XPoint frames[]; int nFrames;
7619 BeginAnimation(anim, piece, startColor, start);
7620 for (n = 0; n < nFrames; n++) {
7621 AnimationFrame(anim, &(frames[n]), piece);
7622 FrameDelay(appData.animSpeed);
7624 EndAnimation(anim, finish);
7627 /* Main control logic for deciding what to animate and how */
7630 AnimateMove(board, fromX, fromY, toX, toY)
7639 XPoint start, finish, mid;
7640 XPoint frames[kFactor * 2 + 1];
7641 int nFrames, startColor, endColor;
7643 /* Are we animating? */
7644 if (!appData.animate || appData.blindfold)
7647 if(board[toY][toX] == WhiteRook && board[fromY][fromX] == WhiteKing ||
7648 board[toY][toX] == BlackRook && board[fromY][fromX] == BlackKing)
7649 return; // [HGM] FRC: no animtion of FRC castlings, as to-square is not true to-square
7651 if (fromY < 0 || fromX < 0 || toX < 0 || toY < 0) return;
7652 piece = board[fromY][fromX];
7653 if (piece >= EmptySquare) return;
7658 hop = (piece == WhiteKnight || piece == BlackKnight);
7661 if (appData.debugMode) {
7662 fprintf(debugFP, hop ? _("AnimateMove: piece %d hops from %d,%d to %d,%d \n") :
7663 _("AnimateMove: piece %d slides from %d,%d to %d,%d \n"),
7664 piece, fromX, fromY, toX, toY); }
7666 ScreenSquare(fromX, fromY, &start, &startColor);
7667 ScreenSquare(toX, toY, &finish, &endColor);
7670 /* Knight: make diagonal movement then straight */
7671 if (abs(toY - fromY) < abs(toX - fromX)) {
7672 mid.x = start.x + (finish.x - start.x) / 2;
7676 mid.y = start.y + (finish.y - start.y) / 2;
7679 mid.x = start.x + (finish.x - start.x) / 2;
7680 mid.y = start.y + (finish.y - start.y) / 2;
7683 /* Don't use as many frames for very short moves */
7684 if (abs(toY - fromY) + abs(toX - fromX) <= 2)
7685 Tween(&start, &mid, &finish, kFactor - 1, frames, &nFrames);
7687 Tween(&start, &mid, &finish, kFactor, frames, &nFrames);
7688 FrameSequence(&game, piece, startColor, &start, &finish, frames, nFrames);
7690 /* Be sure end square is redrawn */
7691 damage[toY][toX] = True;
7695 DragPieceBegin(x, y)
7698 int boardX, boardY, color;
7701 /* Are we animating? */
7702 if (!appData.animateDragging || appData.blindfold)
7705 /* Figure out which square we start in and the
7706 mouse position relative to top left corner. */
7707 BoardSquare(x, y, &boardX, &boardY);
7708 player.startBoardX = boardX;
7709 player.startBoardY = boardY;
7710 ScreenSquare(boardX, boardY, &corner, &color);
7711 player.startSquare = corner;
7712 player.startColor = color;
7713 /* As soon as we start dragging, the piece will jump slightly to
7714 be centered over the mouse pointer. */
7715 player.mouseDelta.x = squareSize/2;
7716 player.mouseDelta.y = squareSize/2;
7717 /* Initialise animation */
7718 player.dragPiece = PieceForSquare(boardX, boardY);
7720 if (player.dragPiece >= 0 && player.dragPiece < EmptySquare) {
7721 player.dragActive = True;
7722 BeginAnimation(&player, player.dragPiece, color, &corner);
7723 /* Mark this square as needing to be redrawn. Note that
7724 we don't remove the piece though, since logically (ie
7725 as seen by opponent) the move hasn't been made yet. */
7726 if(boardX == BOARD_RGHT+1 && PieceForSquare(boardX-1, boardY) > 1 ||
7727 boardX == BOARD_LEFT-2 && PieceForSquare(boardX+1, boardY) > 1)
7728 // XCopyArea(xDisplay, xBoardWindow, player.saveBuf, player.blitGC,
7729 // corner.x, corner.y, squareSize, squareSize,
7730 // 0, 0); // [HGM] zh: unstack in stead of grab
7731 damage[boardY][boardX] = True;
7733 player.dragActive = False;
7743 /* Are we animating? */
7744 if (!appData.animateDragging || appData.blindfold)
7748 if (! player.dragActive)
7750 /* Move piece, maintaining same relative position
7751 of mouse within square */
7752 corner.x = x - player.mouseDelta.x;
7753 corner.y = y - player.mouseDelta.y;
7754 AnimationFrame(&player, &corner, player.dragPiece);
7756 if (appData.highlightDragging) {
7758 BoardSquare(x, y, &boardX, &boardY);
7759 SetHighlights(fromX, fromY, boardX, boardY);
7768 int boardX, boardY, color;
7771 /* Are we animating? */
7772 if (!appData.animateDragging || appData.blindfold)
7776 if (! player.dragActive)
7778 /* Last frame in sequence is square piece is
7779 placed on, which may not match mouse exactly. */
7780 BoardSquare(x, y, &boardX, &boardY);
7781 ScreenSquare(boardX, boardY, &corner, &color);
7782 EndAnimation(&player, &corner);
7784 /* Be sure end square is redrawn */
7785 damage[boardY][boardX] = True;
7787 /* This prevents weird things happening with fast successive
7788 clicks which on my Sun at least can cause motion events
7789 without corresponding press/release. */
7790 player.dragActive = False;
7793 /* Handle expose event while piece being dragged */
7798 if (!player.dragActive || appData.blindfold)
7801 /* What we're doing: logically, the move hasn't been made yet,
7802 so the piece is still in it's original square. But visually
7803 it's being dragged around the board. So we erase the square
7804 that the piece is on and draw it at the last known drag point. */
7805 BlankSquare(player.startSquare.x, player.startSquare.y,
7806 player.startColor, EmptySquare, xBoardWindow);
7807 AnimationFrame(&player, &player.prevFrame, player.dragPiece);
7808 damage[player.startBoardY][player.startBoardX] = TRUE;
7812 SetProgramStats( FrontEndProgramStats * stats )
7815 // [HGM] done, but perhaps backend should call this directly?
7816 EngineOutputUpdate( stats );
7819 #include <sys/ioctl.h>
7820 int get_term_width()
7822 int fd, default_width;
7825 default_width = 79; // this is FICS default anyway...
7827 #if !defined(TIOCGWINSZ) && defined(TIOCGSIZE)
7829 if (!ioctl(fd, TIOCGSIZE, &win))
7830 default_width = win.ts_cols;
7831 #elif defined(TIOCGWINSZ)
7833 if (!ioctl(fd, TIOCGWINSZ, &win))
7834 default_width = win.ws_col;
7836 return default_width;
7839 void update_ics_width()
7841 static int old_width = 0;
7842 int new_width = get_term_width();
7844 if (old_width != new_width)
7845 ics_printf("set width %d\n", new_width);
7846 old_width = new_width;
7849 void NotifyFrontendLogin()