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_Aspect = GTK_WIDGET (gtk_builder_get_object (builder, "Aspectframe"));
2202 if(!GUI_Aspect) printf("Error: gtk_builder didn't work!\n");
2204 GUI_History = GTK_WIDGET (gtk_builder_get_object (builder, "MoveHistory"));
2205 if(!GUI_History) printf("Error: gtk_builder didn't work!\n");
2207 GUI_Menubar = GTK_WIDGET (gtk_builder_get_object (builder, "MenuBar"));
2208 if(!GUI_Menubar) printf("Error: gtk_builder didn't work!\n");
2209 GUI_Timer = GTK_WIDGET (gtk_builder_get_object (builder, "Timer"));
2210 if(!GUI_Timer) printf("Error: gtk_builder didn't work!\n");
2211 GUI_Buttonbar = GTK_WIDGET (gtk_builder_get_object (builder, "ButtonBar"));
2212 if(!GUI_Buttonbar) printf("Error: gtk_builder didn't work!\n");
2213 GUI_Board = GTK_WIDGET (gtk_builder_get_object (builder, "Board"));
2214 if(!GUI_Board) printf("Error: gtk_builder didn't work!\n");
2216 GUI_Whiteclock = GTK_WIDGET (gtk_builder_get_object (builder, "WhiteClock"));
2217 if(!GUI_Whiteclock) printf("Error: gtk_builder didn't work!\n");
2219 GUI_Blackclock = GTK_WIDGET (gtk_builder_get_object (builder, "BlackClock"));
2220 if(!GUI_Blackclock) printf("Error: gtk_builder didn't work!\n");
2222 LIST_MoveHistory = GTK_LIST_STORE (gtk_builder_get_object (builder, "MoveHistoryStore"));
2223 if(!LIST_MoveHistory) printf("Error: gtk_builder didn't work!\n");
2226 gtk_builder_connect_signals (builder, NULL);
2228 // don't unref the builder, since we use it to get references to widgets
2229 // g_object_unref (G_OBJECT (builder));
2231 /* end parse glade file */
2235 fprintf(stderr, _("%s: unrecognized argument %s\n"),
2236 programName, argv[1]);
2238 fprintf(stderr, "Recognized options:\n");
2239 for(i = 0; i < XtNumber(shellOptions); i++)
2241 /* print first column */
2242 j = fprintf(stderr, " %s%s", shellOptions[i].option,
2243 (shellOptions[i].argKind == XrmoptionSepArg
2245 /* print second column and end line */
2246 if (++i < XtNumber(shellOptions))
2248 fprintf(stderr, "%*c%s%s\n", 40 - j, ' ',
2249 shellOptions[i].option,
2250 (shellOptions[i].argKind == XrmoptionSepArg
2255 fprintf(stderr, "\n");
2262 if (p == NULL) p = "/tmp";
2263 i = strlen(p) + strlen("/.xboardXXXXXx.pgn") + 1;
2264 gameCopyFilename = (char*) malloc(i);
2265 gamePasteFilename = (char*) malloc(i);
2266 snprintf(gameCopyFilename,i, "%s/.xboard%05uc.pgn", p, getpid());
2267 snprintf(gamePasteFilename,i, "%s/.xboard%05up.pgn", p, getpid());
2269 XtGetApplicationResources(shellWidget, (XtPointer) &appData,
2270 clientResources, XtNumber(clientResources),
2273 { // [HGM] initstring: kludge to fix bad bug. expand '\n' characters in init string and computer string.
2274 static char buf[MSG_SIZ];
2275 EscapeExpand(buf, appData.initString);
2276 appData.initString = strdup(buf);
2277 EscapeExpand(buf, appData.secondInitString);
2278 appData.secondInitString = strdup(buf);
2279 EscapeExpand(buf, appData.firstComputerString);
2280 appData.firstComputerString = strdup(buf);
2281 EscapeExpand(buf, appData.secondComputerString);
2282 appData.secondComputerString = strdup(buf);
2285 if ((chessDir = (char *) getenv("CHESSDIR")) == NULL) {
2288 if (chdir(chessDir) != 0) {
2289 fprintf(stderr, _("%s: can't cd to CHESSDIR: "), programName);
2295 if (appData.debugMode && appData.nameOfDebugFile && strcmp(appData.nameOfDebugFile, "stderr")) {
2296 /* [DM] debug info to file [HGM] make the filename a command-line option, and allow it to remain stderr */
2297 if ((debugFP = fopen(appData.nameOfDebugFile, "w")) == NULL) {
2298 printf(_("Failed to open file '%s'\n"), appData.nameOfDebugFile);
2301 setbuf(debugFP, NULL);
2304 /* [HGM,HR] make sure board size is acceptable */
2305 if(appData.NrFiles > BOARD_SIZE ||
2306 appData.NrRanks > BOARD_SIZE )
2307 DisplayFatalError(_("Recompile with BOARD_SIZE > 12, to support this size"), 0, 2);
2310 /* This feature does not work; animation needs a rewrite */
2311 appData.highlightDragging = FALSE;
2315 xDisplay = XtDisplay(shellWidget);
2316 xScreen = DefaultScreen(xDisplay);
2317 wm_delete_window = XInternAtom(xDisplay, "WM_DELETE_WINDOW", True);
2319 gameInfo.variant = StringToVariant(appData.variant);
2320 InitPosition(FALSE);
2322 /* calc board size */
2323 if (isdigit(appData.boardSize[0]))
2325 i = sscanf(appData.boardSize, "%d,%d,%d,%d,%d,%d,%d", &squareSize,
2326 &lineGap, &clockFontPxlSize, &coordFontPxlSize,
2327 &fontPxlSize, &smallLayout, &tinyLayout);
2330 fprintf(stderr, _("%s: bad boardSize syntax %s\n"),
2331 programName, appData.boardSize);
2336 /* Find some defaults; use the nearest known size */
2337 SizeDefaults *szd, *nearest;
2338 int distance = 99999;
2339 nearest = szd = sizeDefaults;
2340 while (szd->name != NULL)
2342 if (abs(szd->squareSize - squareSize) < distance)
2345 distance = abs(szd->squareSize - squareSize);
2346 if (distance == 0) break;
2350 if (i < 2) lineGap = nearest->lineGap;
2351 if (i < 3) clockFontPxlSize = nearest->clockFontPxlSize;
2352 if (i < 4) coordFontPxlSize = nearest->coordFontPxlSize;
2353 if (i < 5) fontPxlSize = nearest->fontPxlSize;
2354 if (i < 6) smallLayout = nearest->smallLayout;
2355 if (i < 7) tinyLayout = nearest->tinyLayout;
2360 SizeDefaults *szd = sizeDefaults;
2361 if (*appData.boardSize == NULLCHAR)
2363 while (DisplayWidth(xDisplay, xScreen) < szd->minScreenSize
2364 || DisplayHeight(xDisplay, xScreen) < szd->minScreenSize)
2368 if (szd->name == NULL) szd--;
2372 while (szd->name != NULL
2373 && StrCaseCmp(szd->name, appData.boardSize) != 0)
2375 if (szd->name == NULL)
2377 fprintf(stderr, _("%s: unrecognized boardSize name %s\n"),
2378 programName, appData.boardSize);
2382 squareSize = szd->squareSize;
2383 lineGap = szd->lineGap;
2384 clockFontPxlSize = szd->clockFontPxlSize;
2385 coordFontPxlSize = szd->coordFontPxlSize;
2386 fontPxlSize = szd->fontPxlSize;
2387 smallLayout = szd->smallLayout;
2388 tinyLayout = szd->tinyLayout;
2390 /* end figuring out what size to use */
2392 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2393 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2396 * Determine what fonts to use.
2398 appData.clockFont = FindFont(appData.clockFont, clockFontPxlSize);
2399 clockFontID = XLoadFont(xDisplay, appData.clockFont);
2400 clockFontStruct = XQueryFont(xDisplay, clockFontID);
2401 appData.coordFont = FindFont(appData.coordFont, coordFontPxlSize);
2402 coordFontID = XLoadFont(xDisplay, appData.coordFont);
2403 coordFontStruct = XQueryFont(xDisplay, coordFontID);
2404 appData.font = FindFont(appData.font, fontPxlSize);
2405 countFontID = XLoadFont(xDisplay, appData.coordFont); // [HGM] holdings
2406 countFontStruct = XQueryFont(xDisplay, countFontID);
2407 // appData.font = FindFont(appData.font, fontPxlSize);
2409 xdb = XtDatabase(xDisplay);
2410 XrmPutStringResource(&xdb, "*font", appData.font);
2413 * Detect if there are not enough colors available and adapt.
2415 if (DefaultDepth(xDisplay, xScreen) <= 2) {
2416 appData.monoMode = True;
2419 if (!appData.monoMode) {
2420 vFrom.addr = (caddr_t) appData.lightSquareColor;
2421 vFrom.size = strlen(appData.lightSquareColor);
2422 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2423 if (vTo.addr == NULL) {
2424 appData.monoMode = True;
2427 lightSquareColor = *(Pixel *) vTo.addr;
2430 if (!appData.monoMode) {
2431 vFrom.addr = (caddr_t) appData.darkSquareColor;
2432 vFrom.size = strlen(appData.darkSquareColor);
2433 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2434 if (vTo.addr == NULL) {
2435 appData.monoMode = True;
2438 darkSquareColor = *(Pixel *) vTo.addr;
2441 if (!appData.monoMode) {
2442 vFrom.addr = (caddr_t) appData.whitePieceColor;
2443 vFrom.size = strlen(appData.whitePieceColor);
2444 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2445 if (vTo.addr == NULL) {
2446 appData.monoMode = True;
2449 whitePieceColor = *(Pixel *) vTo.addr;
2452 if (!appData.monoMode) {
2453 vFrom.addr = (caddr_t) appData.blackPieceColor;
2454 vFrom.size = strlen(appData.blackPieceColor);
2455 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2456 if (vTo.addr == NULL) {
2457 appData.monoMode = True;
2460 blackPieceColor = *(Pixel *) vTo.addr;
2464 if (!appData.monoMode) {
2465 vFrom.addr = (caddr_t) appData.highlightSquareColor;
2466 vFrom.size = strlen(appData.highlightSquareColor);
2467 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2468 if (vTo.addr == NULL) {
2469 appData.monoMode = True;
2472 highlightSquareColor = *(Pixel *) vTo.addr;
2476 if (!appData.monoMode) {
2477 vFrom.addr = (caddr_t) appData.premoveHighlightColor;
2478 vFrom.size = strlen(appData.premoveHighlightColor);
2479 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2480 if (vTo.addr == NULL) {
2481 appData.monoMode = True;
2484 premoveHighlightColor = *(Pixel *) vTo.addr;
2489 fprintf(stderr, _("%s: too few colors available; trying monochrome mode\n"),
2492 if (appData.bitmapDirectory == NULL ||
2493 appData.bitmapDirectory[0] == NULLCHAR)
2494 appData.bitmapDirectory = DEF_BITMAP_DIR;
2497 if (appData.lowTimeWarning && !appData.monoMode) {
2498 vFrom.addr = (caddr_t) appData.lowTimeWarningColor;
2499 vFrom.size = strlen(appData.lowTimeWarningColor);
2500 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2501 if (vTo.addr == NULL)
2502 appData.monoMode = True;
2504 lowTimeWarningColor = *(Pixel *) vTo.addr;
2507 if (appData.monoMode && appData.debugMode) {
2508 fprintf(stderr, _("white pixel = 0x%lx, black pixel = 0x%lx\n"),
2509 (unsigned long) XWhitePixel(xDisplay, xScreen),
2510 (unsigned long) XBlackPixel(xDisplay, xScreen));
2513 if (parse_cpair(ColorShout, appData.colorShout) < 0 ||
2514 parse_cpair(ColorSShout, appData.colorSShout) < 0 ||
2515 parse_cpair(ColorChannel1, appData.colorChannel1) < 0 ||
2516 parse_cpair(ColorChannel, appData.colorChannel) < 0 ||
2517 parse_cpair(ColorKibitz, appData.colorKibitz) < 0 ||
2518 parse_cpair(ColorTell, appData.colorTell) < 0 ||
2519 parse_cpair(ColorChallenge, appData.colorChallenge) < 0 ||
2520 parse_cpair(ColorRequest, appData.colorRequest) < 0 ||
2521 parse_cpair(ColorSeek, appData.colorSeek) < 0 ||
2522 parse_cpair(ColorNormal, appData.colorNormal) < 0)
2524 if (appData.colorize) {
2526 _("%s: can't parse color names; disabling colorization\n"),
2529 appData.colorize = FALSE;
2531 textColors[ColorNone].fg = textColors[ColorNone].bg = -1;
2532 textColors[ColorNone].attr = 0;
2534 // XtAppAddActions(appContext, boardActions, XtNumber(boardActions));
2540 layoutName = "tinyLayout";
2541 } else if (smallLayout) {
2542 layoutName = "smallLayout";
2544 layoutName = "normalLayout";
2547 if (appData.titleInWindow) {
2548 /* todo check what this appdata does */
2551 if (appData.showButtonBar) {
2552 /* TODO hide button bar if requested */
2556 if (appData.titleInWindow)
2561 if (appData.showButtonBar)
2568 if (appData.showButtonBar)
2578 /* set some checkboxes in the menu according to appData */
2580 if (appData.alwaysPromoteToQueen)
2581 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Always Queen")),TRUE);
2583 if (appData.animateDragging)
2584 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Animate Dragging")),TRUE);
2586 if (appData.animate)
2587 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Animate Moving")),TRUE);
2589 if (appData.autoComment)
2590 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Comment")),TRUE);
2592 if (appData.autoCallFlag)
2593 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Flag")),TRUE);
2595 if (appData.autoFlipView)
2596 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Flip View")),TRUE);
2598 if (appData.autoObserve)
2599 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Observe")),TRUE);
2601 if (appData.autoRaiseBoard)
2602 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Raise Board")),TRUE);
2604 if (appData.autoSaveGames)
2605 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Save")),TRUE);
2607 if (appData.saveGameFile[0] != NULLCHAR)
2609 /* Can't turn this off from menu */
2610 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Save")),TRUE);
2611 gtk_action_set_sensitive(GTK_ACTION (gtk_builder_get_object (builder, "menuOptions.Auto Save")),FALSE);
2614 if (appData.blindfold)
2615 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Blindfold")),TRUE);
2617 if (appData.flashCount > 0)
2618 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Flash Moves")),TRUE);
2620 if (appData.getMoveList)
2621 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Get Move List")),TRUE);
2624 if (appData.highlightDragging)
2625 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Highlight Dragging")),TRUE);
2628 if (appData.highlightLastMove)
2629 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Highlight Last Move")),TRUE);
2631 if (appData.icsAlarm)
2632 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.ICS Alarm")),TRUE);
2634 if (appData.ringBellAfterMoves)
2635 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Move Sound")),TRUE);
2637 if (appData.oldSaveStyle)
2638 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Old Save Style")),TRUE);
2640 if (appData.periodicUpdates)
2641 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Periodic Updates")),TRUE);
2643 if (appData.ponderNextMove)
2644 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Ponder Next Move")),TRUE);
2646 if (appData.popupExitMessage)
2647 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Popup Exit Message")),TRUE);
2649 if (appData.popupMoveErrors)
2650 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Popup Move Errors")),TRUE);
2652 if (appData.premove)
2653 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Premove")),TRUE);
2655 if (appData.quietPlay)
2656 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Quit Play")),TRUE);
2658 if (appData.showCoords)
2659 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Show Coords")),TRUE);
2661 if (appData.showThinking)
2662 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Show Thinking")),TRUE);
2664 if (appData.testLegality)
2665 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Test Legality")),TRUE);
2667 /* end setting check boxes */
2669 /* load square colors */
2670 SVGLightSquare = load_pixbuf("svg/LightSquare.svg",squareSize);
2671 SVGDarkSquare = load_pixbuf("svg/DarkSquare.svg",squareSize);
2672 SVGNeutralSquare = load_pixbuf("svg/NeutralSquare.svg",squareSize);
2674 /* use two icons to indicate if it is white's or black's turn */
2675 WhiteIcon = load_pixbuf("svg/icon_white.svg",0);
2676 BlackIcon = load_pixbuf("svg/icon_black.svg",0);
2677 WindowIcon = WhiteIcon;
2678 gtk_window_set_icon(GTK_WINDOW(GUI_Window),WindowIcon);
2681 /* realize window */
2682 gtk_widget_show (GUI_Window);
2684 /* recalc boardsize */
2689 if (appData.animate || appData.animateDragging)
2694 if (errorExitStatus == -1) {
2695 if (appData.icsActive) {
2696 /* We now wait until we see "login:" from the ICS before
2697 sending the logon script (problems with timestamp otherwise) */
2698 /*ICSInitScript();*/
2699 if (appData.icsInputBox) ICSInputBoxPopUp();
2702 signal(SIGINT, IntSigHandler);
2703 signal(SIGTERM, IntSigHandler);
2704 if (*appData.cmailGameName != NULLCHAR) {
2705 signal(SIGUSR1, CmailSigHandler);
2708 gameInfo.boardWidth = 0; // [HGM] pieces: kludge to ensure InitPosition() calls InitDrawingSizes()
2712 * Create a cursor for the board widget.
2713 * (This needs to be called after the window has been created to have access to board-window)
2716 BoardCursor = gdk_cursor_new(GDK_HAND2);
2717 gdk_window_set_cursor(GUI_Board->window, BoardCursor);
2718 gdk_cursor_destroy(BoardCursor);
2723 if (appData.debugMode) fclose(debugFP); // [DM] debug
2730 if (appData.icsActive && oldICSInteractionTitle != NULL) {
2731 DisplayIcsInteractionTitle(oldICSInteractionTitle);
2733 unlink(gameCopyFilename);
2734 unlink(gamePasteFilename);
2737 RETSIGTYPE TermSizeSigHandler(int sig)
2750 CmailSigHandler(sig)
2756 signal(SIGUSR1, SIG_IGN); /* suspend handler */
2758 /* Activate call-back function CmailSigHandlerCallBack() */
2759 OutputToProcess(cmailPR, (char *)(&dummy), sizeof(int), &error);
2761 signal(SIGUSR1, CmailSigHandler); /* re-activate handler */
2765 CmailSigHandlerCallBack(isr, closure, message, count, error)
2773 ReloadCmailMsgEvent(TRUE); /* Reload cmail msg */
2775 /**** end signal code ****/
2785 f = fopen(appData.icsLogon, "r");
2791 strcat(buf, appData.icsLogon);
2792 f = fopen(buf, "r");
2796 ProcessICSInitScript(f);
2803 EditCommentPopDown();
2809 SetMenuEnables(enab)
2814 if (!builder) return;
2815 while (enab->name != NULL) {
2816 o = gtk_builder_get_object(builder, enab->name);
2817 if(GTK_IS_WIDGET(o))
2818 gtk_widget_set_sensitive(GTK_WIDGET (o),enab->value);
2821 if(GTK_IS_ACTION(o))
2822 gtk_action_set_sensitive(GTK_ACTION (o),enab->value);
2824 DisplayError(enab->name, 0);
2832 SetMenuEnables(icsEnables);
2835 if (appData.zippyPlay && !appData.noChessProgram) /* [DM] icsEngineAnalyze */
2836 {}; // XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Analysis Mode"), True);
2843 SetMenuEnables(ncpEnables);
2849 SetMenuEnables(gnuEnables);
2855 SetMenuEnables(cmailEnables);
2861 SetMenuEnables(trainingOnEnables);
2862 if (appData.showButtonBar) {
2863 // XtSetSensitive(buttonBarWidget, False);
2869 SetTrainingModeOff()
2871 SetMenuEnables(trainingOffEnables);
2872 if (appData.showButtonBar) {
2873 // XtSetSensitive(buttonBarWidget, True);
2878 SetUserThinkingEnables()
2880 if (appData.noChessProgram) return;
2881 SetMenuEnables(userThinkingEnables);
2885 SetMachineThinkingEnables()
2887 if (appData.noChessProgram) return;
2888 SetMenuEnables(machineThinkingEnables);
2890 case MachinePlaysBlack:
2891 case MachinePlaysWhite:
2892 case TwoMachinesPlay:
2893 // XtSetSensitive(XtNameToWidget(menuBarWidget,
2894 // ModeToWidgetName(gameMode)), True);
2901 #define Abs(n) ((n)<0 ? -(n) : (n))
2904 * Find a font that matches "pattern" that is as close as
2905 * possible to the targetPxlSize. Prefer fonts that are k
2906 * pixels smaller to fonts that are k pixels larger. The
2907 * pattern must be in the X Consortium standard format,
2908 * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".
2909 * The return value should be freed with XtFree when no
2912 char *FindFont(pattern, targetPxlSize)
2916 char **fonts, *p, *best, *scalable, *scalableTail;
2917 int i, j, nfonts, minerr, err, pxlSize;
2920 char **missing_list;
2922 char *def_string, *base_fnt_lst, strInt[3];
2924 XFontStruct **fnt_list;
2926 base_fnt_lst = calloc(1, strlen(pattern) + 3);
2927 sprintf(strInt, "%d", targetPxlSize);
2928 p = strstr(pattern, "--");
2929 strncpy(base_fnt_lst, pattern, p - pattern + 2);
2930 strcat(base_fnt_lst, strInt);
2931 strcat(base_fnt_lst, strchr(p + 2, '-'));
2933 if ((fntSet = XCreateFontSet(xDisplay,
2937 &def_string)) == NULL) {
2939 fprintf(stderr, _("Unable to create font set.\n"));
2943 nfonts = XFontsOfFontSet(fntSet, &fnt_list, &fonts);
2945 fonts = XListFonts(xDisplay, pattern, 999999, &nfonts);
2947 fprintf(stderr, _("%s: no fonts match pattern %s\n"),
2948 programName, pattern);
2956 for (i=0; i<nfonts; i++) {
2959 if (*p != '-') continue;
2961 if (*p == NULLCHAR) break;
2962 if (*p++ == '-') j++;
2964 if (j < 7) continue;
2967 scalable = fonts[i];
2970 err = pxlSize - targetPxlSize;
2971 if (Abs(err) < Abs(minerr) ||
2972 (minerr > 0 && err < 0 && -err == minerr)) {
2978 if (scalable && Abs(minerr) > appData.fontSizeTolerance) {
2979 /* If the error is too big and there is a scalable font,
2980 use the scalable font. */
2981 int headlen = scalableTail - scalable;
2982 p = (char *) XtMalloc(strlen(scalable) + 10);
2983 while (isdigit(*scalableTail)) scalableTail++;
2984 sprintf(p, "%.*s%d%s", headlen, scalable, targetPxlSize, scalableTail);
2986 p = (char *) XtMalloc(strlen(best) + 1);
2989 if (appData.debugMode) {
2990 fprintf(debugFP, _("resolved %s at pixel size %d\n to %s\n"),
2991 pattern, targetPxlSize, p);
2994 if (missing_count > 0)
2995 XFreeStringList(missing_list);
2996 XFreeFontSet(xDisplay, fntSet);
2998 XFreeFontNames(fonts);
3005 /* 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*/
3007 XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
3008 | GCBackground | GCFunction | GCPlaneMask;
3009 XGCValues gc_values;
3012 gc_values.plane_mask = AllPlanes;
3013 gc_values.line_width = lineGap;
3014 gc_values.line_style = LineSolid;
3015 gc_values.function = GXcopy;
3017 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3018 gc_values.background = XWhitePixel(xDisplay, xScreen);
3019 coordGC = XtGetGC(shellWidget, value_mask, &gc_values);
3020 XSetFont(xDisplay, coordGC, coordFontID);
3022 if (appData.monoMode) {
3023 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3024 gc_values.background = XBlackPixel(xDisplay, xScreen);
3025 lightSquareGC = wbPieceGC
3026 = XtGetGC(shellWidget, value_mask, &gc_values);
3028 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3029 gc_values.background = XWhitePixel(xDisplay, xScreen);
3030 darkSquareGC = bwPieceGC
3031 = XtGetGC(shellWidget, value_mask, &gc_values);
3033 if (DefaultDepth(xDisplay, xScreen) == 1) {
3034 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
3035 gc_values.function = GXcopyInverted;
3036 copyInvertedGC = XtGetGC(shellWidget, value_mask, &gc_values);
3037 gc_values.function = GXcopy;
3038 if (XBlackPixel(xDisplay, xScreen) == 1) {
3039 bwPieceGC = darkSquareGC;
3040 wbPieceGC = copyInvertedGC;
3042 bwPieceGC = copyInvertedGC;
3043 wbPieceGC = lightSquareGC;
3047 gc_values.foreground = lightSquareColor;
3048 gc_values.background = darkSquareColor;
3049 lightSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3051 gc_values.foreground = darkSquareColor;
3052 gc_values.background = lightSquareColor;
3053 darkSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3055 gc_values.foreground = jailSquareColor;
3056 gc_values.background = jailSquareColor;
3057 jailSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3059 gc_values.foreground = whitePieceColor;
3060 gc_values.background = darkSquareColor;
3061 wdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3063 gc_values.foreground = whitePieceColor;
3064 gc_values.background = lightSquareColor;
3065 wlPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3067 gc_values.foreground = whitePieceColor;
3068 gc_values.background = jailSquareColor;
3069 wjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3071 gc_values.foreground = blackPieceColor;
3072 gc_values.background = darkSquareColor;
3073 bdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3075 gc_values.foreground = blackPieceColor;
3076 gc_values.background = lightSquareColor;
3077 blPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3079 gc_values.foreground = blackPieceColor;
3080 gc_values.background = jailSquareColor;
3081 bjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3090 for(i=0;i<MAXPIECES;i++)
3094 g_free(SVGpieces[i]);
3101 SVGLightSquare = load_pixbuf("svg/LightSquare.svg",squareSize);
3102 SVGDarkSquare = load_pixbuf("svg/DarkSquare.svg",squareSize);
3103 SVGNeutralSquare = load_pixbuf("svg/NeutralSquare.svg",squareSize);
3106 /* get some defaults going */
3107 for(i=WhitePawn; i<DemotePiece+1; i++)
3108 SVGpieces[i] = load_pixbuf("svg/NeutralSquare.svg",squareSize);
3110 SVGpieces[WhitePawn] = load_pixbuf("svg/WhitePawn.svg",squareSize);
3111 SVGpieces[WhiteKnight] = load_pixbuf("svg/WhiteKnight.svg",squareSize);
3112 SVGpieces[WhiteBishop] = load_pixbuf("svg/WhiteBishop.svg",squareSize);
3113 SVGpieces[WhiteRook] = load_pixbuf("svg/WhiteRook.svg",squareSize);
3114 SVGpieces[WhiteQueen] = load_pixbuf("svg/WhiteQueen.svg",squareSize);
3115 SVGpieces[WhiteKing] = load_pixbuf("svg/WhiteKing.svg",squareSize);
3117 SVGpieces[BlackPawn] = load_pixbuf("svg/BlackPawn.svg",squareSize);
3118 SVGpieces[BlackKnight] = load_pixbuf("svg/BlackKnight.svg",squareSize);
3119 SVGpieces[BlackBishop] = load_pixbuf("svg/BlackBishop.svg",squareSize);
3120 SVGpieces[BlackRook] = load_pixbuf("svg/BlackRook.svg",squareSize);
3121 SVGpieces[BlackQueen] = load_pixbuf("svg/BlackQueen.svg",squareSize);
3122 SVGpieces[BlackKing] = load_pixbuf("svg/BlackKing.svg",squareSize);
3128 static void MenuBarSelect(w, addr, index)
3133 XtActionProc proc = (XtActionProc) addr;
3135 (proc)(NULL, NULL, NULL, NULL);
3138 void CreateMenuBarPopup(parent, name, mb)
3148 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3151 XtSetArg(args[j], XtNleftMargin, 20); j++;
3152 XtSetArg(args[j], XtNrightMargin, 20); j++;
3154 while (mi->string != NULL) {
3155 if (strcmp(mi->string, "----") == 0) {
3156 entry = XtCreateManagedWidget(mi->string, smeLineObjectClass,
3159 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string)));
3160 entry = XtCreateManagedWidget(mi->string, smeBSBObjectClass,
3162 XtAddCallback(entry, XtNcallback,
3163 (XtCallbackProc) MenuBarSelect,
3164 (caddr_t) mi->proc);
3170 Widget CreateMenuBar(mb)
3174 Widget anchor, menuBar;
3176 char menuName[MSG_SIZ];
3179 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
3180 XtSetArg(args[j], XtNvSpace, 0); j++;
3181 XtSetArg(args[j], XtNborderWidth, 0); j++;
3182 menuBar = XtCreateWidget("menuBar", boxWidgetClass,
3183 formWidget, args, j);
3185 while (mb->name != NULL) {
3186 strcpy(menuName, "menu");
3187 strcat(menuName, mb->name);
3189 XtSetArg(args[j], XtNmenuName, XtNewString(menuName)); j++;
3192 shortName[0] = _(mb->name)[0];
3193 shortName[1] = NULLCHAR;
3194 XtSetArg(args[j], XtNlabel, XtNewString(shortName)); j++;
3197 XtSetArg(args[j], XtNlabel, XtNewString(_(mb->name))); j++;
3200 XtSetArg(args[j], XtNborderWidth, 0); j++;
3201 anchor = XtCreateManagedWidget(mb->name, menuButtonWidgetClass,
3203 CreateMenuBarPopup(menuBar, menuName, mb);
3211 CreatePieceMenu(name, color)
3218 ChessSquare selection;
3220 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3221 boardWidget, args, 0);
3223 for (i = 0; i < PIECE_MENU_SIZE; i++) {
3224 String item = pieceMenuStrings[color][i];
3226 if (strcmp(item, "----") == 0) {
3227 entry = XtCreateManagedWidget(item, smeLineObjectClass,
3230 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
3231 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3233 selection = pieceMenuTranslation[color][i];
3234 XtAddCallback(entry, XtNcallback,
3235 (XtCallbackProc) PieceMenuSelect,
3236 (caddr_t) selection);
3237 if (selection == WhitePawn || selection == BlackPawn) {
3238 XtSetArg(args[0], XtNpopupOnEntry, entry);
3239 XtSetValues(menu, args, 1);
3252 ChessSquare selection;
3254 // whitePieceMenu = CreatePieceMenu("menuW", 0);
3255 // blackPieceMenu = CreatePieceMenu("menuB", 1);
3257 // XtRegisterGrabAction(PieceMenuPopup, True,
3258 // (unsigned)(ButtonPressMask|ButtonReleaseMask),
3259 // GrabModeAsync, GrabModeAsync);
3261 // XtSetArg(args[0], XtNlabel, _("Drop"));
3262 // dropMenu = XtCreatePopupShell("menuD", simpleMenuWidgetClass,
3263 // boardWidget, args, 1);
3264 // for (i = 0; i < DROP_MENU_SIZE; i++) {
3265 // String item = dropMenuStrings[i];
3267 // if (strcmp(item, "----") == 0) {
3268 // entry = XtCreateManagedWidget(item, smeLineObjectClass,
3269 // dropMenu, NULL, 0);
3271 // XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
3272 // entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3273 // dropMenu, args, 1);
3274 // selection = dropMenuTranslation[i];
3275 // XtAddCallback(entry, XtNcallback,
3276 // (XtCallbackProc) DropMenuSelect,
3277 // (caddr_t) selection);
3282 void SetupDropMenu()
3290 for (i=0; i<sizeof(dmEnables)/sizeof(DropMenuEnables); i++) {
3291 entry = XtNameToWidget(dropMenu, dmEnables[i].widget);
3292 p = strchr(gameMode == IcsPlayingWhite ? white_holding : black_holding,
3293 dmEnables[i].piece);
3294 XtSetSensitive(entry, p != NULL || !appData.testLegality
3295 /*!!temp:*/ || (gameInfo.variant == VariantCrazyhouse
3296 && !appData.icsActive));
3298 while (p && *p++ == dmEnables[i].piece) count++;
3299 snprintf(label, sizeof(label), "%s %d", dmEnables[i].widget, count);
3301 XtSetArg(args[j], XtNlabel, label); j++;
3302 XtSetValues(entry, args, j);
3306 void PieceMenuPopup(w, event, params, num_params)
3310 Cardinal *num_params;
3313 if (event->type != ButtonPress) return;
3314 if (errorUp) ErrorPopDown();
3318 whichMenu = params[0];
3320 case IcsPlayingWhite:
3321 case IcsPlayingBlack:
3323 case MachinePlaysWhite:
3324 case MachinePlaysBlack:
3325 if (appData.testLegality &&
3326 gameInfo.variant != VariantBughouse &&
3327 gameInfo.variant != VariantCrazyhouse) return;
3329 whichMenu = "menuD";
3335 if (((pmFromX = EventToSquare(event->xbutton.x, BOARD_WIDTH)) < 0) ||
3336 ((pmFromY = EventToSquare(event->xbutton.y, BOARD_HEIGHT)) < 0)) {
3337 pmFromX = pmFromY = -1;
3341 pmFromX = BOARD_WIDTH - 1 - pmFromX;
3343 pmFromY = BOARD_HEIGHT - 1 - pmFromY;
3345 XtPopupSpringLoaded(XtNameToWidget(boardWidget, whichMenu));
3348 static void PieceMenuSelect(w, piece, junk)
3353 if (pmFromX < 0 || pmFromY < 0) return;
3354 EditPositionMenuEvent(piece, pmFromX, pmFromY);
3357 static void DropMenuSelect(w, piece, junk)
3362 if (pmFromX < 0 || pmFromY < 0) return;
3363 DropMenuEvent(piece, pmFromX, pmFromY);
3367 * If the user selects on a border boundary, return -1; if off the board,
3368 * return -2. Otherwise map the event coordinate to the square.
3370 int EventToSquare(x, limit)
3378 if ((x % (squareSize + lineGap)) >= squareSize)
3380 x /= (squareSize + lineGap);
3386 static void do_flash_delay(msec)
3392 static void drawHighlight(file, rank, line_type)
3393 int file, rank, line_type;
3398 if (lineGap == 0 || appData.blindfold) return;
3402 x = lineGap/2 + ((BOARD_WIDTH-1)-file) *
3403 (squareSize + lineGap);
3404 y = lineGap/2 + rank * (squareSize + lineGap);
3408 x = lineGap/2 + file * (squareSize + lineGap);
3409 y = lineGap/2 + ((BOARD_HEIGHT-1)-rank) *
3410 (squareSize + lineGap);
3414 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
3416 /* draw the highlight */
3417 cairo_move_to (cr, x, y);
3418 cairo_rel_line_to (cr, 0,squareSize+lineGap);
3419 cairo_rel_line_to (cr, squareSize+lineGap,0);
3420 cairo_rel_line_to (cr, 0,-squareSize-lineGap);
3421 cairo_close_path (cr);
3423 cairo_set_line_width (cr, lineGap);
3426 /* TODO: use appdata colors */
3427 case LINE_TYPE_HIGHLIGHT:
3428 cairo_set_source_rgba (cr, 1, 1, 0, 1.0);
3431 cairo_set_source_rgba (cr, 1, 0, 0, 1.0);
3433 case LINE_TYPE_NORMAL:
3435 cairo_set_source_rgba (cr, 0, 1, 0, 1.0);
3446 int hi1X = -1, hi1Y = -1, hi2X = -1, hi2Y = -1;
3447 int pm1X = -1, pm1Y = -1, pm2X = -1, pm2Y = -1;
3450 SetHighlights(fromX, fromY, toX, toY)
3451 int fromX, fromY, toX, toY;
3453 if (hi1X != fromX || hi1Y != fromY)
3455 if (hi1X >= 0 && hi1Y >= 0)
3457 drawHighlight(hi1X, hi1Y, LINE_TYPE_NORMAL);
3459 if (fromX >= 0 && fromY >= 0)
3461 drawHighlight(fromX, fromY, LINE_TYPE_HIGHLIGHT);
3464 if (hi2X != toX || hi2Y != toY)
3466 if (hi2X >= 0 && hi2Y >= 0)
3468 drawHighlight(hi2X, hi2Y, LINE_TYPE_NORMAL);
3470 if (toX >= 0 && toY >= 0)
3472 drawHighlight(toX, toY, LINE_TYPE_HIGHLIGHT);
3486 SetHighlights(-1, -1, -1, -1);
3491 SetPremoveHighlights(fromX, fromY, toX, toY)
3492 int fromX, fromY, toX, toY;
3494 if (pm1X != fromX || pm1Y != fromY)
3496 if (pm1X >= 0 && pm1Y >= 0)
3498 drawHighlight(pm1X, pm1Y, LINE_TYPE_NORMAL);
3500 if (fromX >= 0 && fromY >= 0)
3502 drawHighlight(fromX, fromY, LINE_TYPE_PRE);
3505 if (pm2X != toX || pm2Y != toY)
3507 if (pm2X >= 0 && pm2Y >= 0)
3509 drawHighlight(pm2X, pm2Y, LINE_TYPE_NORMAL);
3511 if (toX >= 0 && toY >= 0)
3513 drawHighlight(toX, toY, LINE_TYPE_PRE);
3526 ClearPremoveHighlights()
3528 SetPremoveHighlights(-1, -1, -1, -1);
3531 static void BlankSquare(x, y, color, piece, dest)
3544 pb = SVGLightSquare;
3546 case 2: /* neutral */
3548 pb = SVGNeutralSquare;
3551 gdk_draw_pixbuf(GDK_WINDOW(GUI_Board->window),NULL,pb,0,0,x,y,-1,-1, GDK_RGB_DITHER_NORMAL, 0, 0);
3555 static void DrawPiece(piece, square_color, x, y, dest)
3557 int square_color, x, y;
3560 /* redraw background, since piece might be transparent in some areas */
3561 BlankSquare(x,y,square_color,piece,dest);
3564 gdk_draw_pixbuf(GDK_WINDOW(GUI_Board->window),NULL,
3565 GDK_PIXBUF(SVGpieces[piece]),0,0,x,y,-1,-1,
3566 GDK_RGB_DITHER_NORMAL, 0, 0);
3570 /* [HR] determine square color depending on chess variant. */
3571 static int SquareColor(row, column)
3576 if (gameInfo.variant == VariantXiangqi) {
3577 if (column >= 3 && column <= 5 && row >= 0 && row <= 2) {
3579 } else if (column >= 3 && column <= 5 && row >= 7 && row <= 9) {
3581 } else if (row <= 4) {
3587 square_color = ((column + row) % 2) == 1;
3590 /* [hgm] holdings: next line makes all holdings squares light */
3591 if(column < BOARD_LEFT || column >= BOARD_RGHT) square_color = 1;
3593 return square_color;
3596 void DrawSquare(row, column, piece, do_flash)
3597 int row, column, do_flash;
3600 int square_color, x, y;
3605 /* Calculate delay in milliseconds (2-delays per complete flash) */
3606 flash_delay = 500 / appData.flashRate;
3608 /* calculate x and y coordinates from row and column */
3611 x = lineGap + ((BOARD_WIDTH-1)-column) *
3612 (squareSize + lineGap);
3613 y = lineGap + row * (squareSize + lineGap);
3617 x = lineGap + column * (squareSize + lineGap);
3618 y = lineGap + ((BOARD_HEIGHT-1)-row) *
3619 (squareSize + lineGap);
3622 square_color = SquareColor(row, column);
3624 // [HGM] holdings: blank out area between board and holdings
3625 if ( column == BOARD_LEFT-1 || column == BOARD_RGHT
3626 || (column == BOARD_LEFT-2 && row < BOARD_HEIGHT-gameInfo.holdingsSize)
3627 || (column == BOARD_RGHT+1 && row >= gameInfo.holdingsSize) )
3629 BlankSquare(x, y, 2, EmptySquare, xBoardWindow);
3631 // [HGM] print piece counts next to holdings
3632 string[1] = NULLCHAR;
3635 cairo_text_extents_t extents;
3640 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
3642 string[0] = '0' + piece;
3644 /* TODO this has to go into the font-selection */
3645 cairo_select_font_face (cr, "Sans",
3646 CAIRO_FONT_SLANT_NORMAL,
3647 CAIRO_FONT_WEIGHT_NORMAL);
3649 cairo_set_font_size (cr, 12.0);
3650 cairo_text_extents (cr, string, &extents);
3652 if (column == (flipView ? BOARD_LEFT-1 : BOARD_RGHT) )
3654 xpos= x + squareSize - extents.width - 2;
3655 ypos= y + extents.y_bearing + 1;
3657 if (column == (flipView ? BOARD_RGHT : BOARD_LEFT-1) && piece > 1)
3660 ypos = y + extents.y_bearing + 1;
3663 /* TODO mono mode? */
3664 cairo_move_to (cr, xpos, ypos);
3665 cairo_text_path (cr, string);
3666 cairo_set_source_rgb (cr, 1.0, 1.0, 1);
3667 cairo_fill_preserve (cr);
3668 cairo_set_source_rgb (cr, 0, 0, 0);
3669 cairo_set_line_width (cr, 0.1);
3678 /* square on the board */
3679 if (piece == EmptySquare || appData.blindfold)
3681 BlankSquare(x, y, square_color, piece, xBoardWindow);
3685 if (do_flash && appData.flashCount > 0)
3687 for (i=0; i<appData.flashCount; ++i)
3690 DrawPiece(piece, square_color, x, y, xBoardWindow);
3691 do_flash_delay(flash_delay);
3693 BlankSquare(x, y, square_color, piece, xBoardWindow);
3694 do_flash_delay(flash_delay);
3697 DrawPiece(piece, square_color, x, y, xBoardWindow);
3701 /* show coordinates if necessary */
3702 if(appData.showCoords)
3704 cairo_text_extents_t extents;
3708 /* TODO this has to go into the font-selection */
3709 cairo_select_font_face (cr, "Sans",
3710 CAIRO_FONT_SLANT_NORMAL,
3711 CAIRO_FONT_WEIGHT_NORMAL);
3712 cairo_set_font_size (cr, 12.0);
3714 string[1] = NULLCHAR;
3717 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
3719 if (row == (flipView ? BOARD_HEIGHT-1 : 0) &&
3720 column >= BOARD_LEFT && column < BOARD_RGHT)
3722 string[0] = 'a' + column - BOARD_LEFT;
3723 cairo_text_extents (cr, string, &extents);
3725 xpos = x + squareSize - extents.width - 2;
3726 ypos = y + squareSize - extents.height - extents.y_bearing - 1;
3728 if (appData.monoMode)
3735 cairo_move_to (cr, xpos, ypos);
3736 cairo_text_path (cr, string);
3737 cairo_set_source_rgb (cr, 0.0, 0.0, 0);
3738 cairo_fill_preserve (cr);
3739 cairo_set_source_rgb (cr, 0, 1.0, 0);
3740 cairo_set_line_width (cr, 0.1);
3743 if ( column == (flipView ? BOARD_RGHT-1 : BOARD_LEFT))
3746 string[0] = ONE + row;
3747 cairo_text_extents (cr, string, &extents);
3750 ypos = y + extents.height + 1;
3752 if (appData.monoMode)
3759 cairo_move_to (cr, xpos, ypos);
3760 cairo_text_path (cr, string);
3761 cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
3762 cairo_fill_preserve (cr);
3763 cairo_set_source_rgb (cr, 0, 0, 1.0);
3764 cairo_set_line_width (cr, 0.1);
3776 /* Returns 1 if there are "too many" differences between b1 and b2
3777 (i.e. more than 1 move was made) */
3778 static int too_many_diffs(b1, b2)
3784 for (i=0; i<BOARD_HEIGHT; ++i) {
3785 for (j=0; j<BOARD_WIDTH; ++j) {
3786 if (b1[i][j] != b2[i][j]) {
3787 if (++c > 4) /* Castling causes 4 diffs */
3796 /* Matrix describing castling maneuvers */
3797 /* Row, ColRookFrom, ColKingFrom, ColRookTo, ColKingTo */
3798 static int castling_matrix[4][5] = {
3799 { 0, 0, 4, 3, 2 }, /* 0-0-0, white */
3800 { 0, 7, 4, 5, 6 }, /* 0-0, white */
3801 { 7, 0, 4, 3, 2 }, /* 0-0-0, black */
3802 { 7, 7, 4, 5, 6 } /* 0-0, black */
3805 /* Checks whether castling occurred. If it did, *rrow and *rcol
3806 are set to the destination (row,col) of the rook that moved.
3808 Returns 1 if castling occurred, 0 if not.
3810 Note: Only handles a max of 1 castling move, so be sure
3811 to call too_many_diffs() first.
3813 static int check_castle_draw(newb, oldb, rrow, rcol)
3820 /* For each type of castling... */
3821 for (i=0; i<4; ++i) {
3822 r = castling_matrix[i];
3824 /* Check the 4 squares involved in the castling move */
3826 for (j=1; j<=4; ++j) {
3827 if (newb[r[0]][r[j]] == oldb[r[0]][r[j]]) {
3834 /* All 4 changed, so it must be a castling move */
3843 static int damage[BOARD_SIZE][BOARD_SIZE];
3846 * event handler for redrawing the board
3848 void DrawPosition( repaint, board)
3849 /*Boolean*/int repaint;
3853 static int lastFlipView = 0;
3854 static int lastBoardValid = 0;
3855 static Board lastBoard;
3858 if (board == NULL) {
3859 if (!lastBoardValid) return;
3862 if (!lastBoardValid || lastFlipView != flipView) {
3863 // XtSetArg(args[0], XtNleftBitmap, (flipView ? xMarkPixmap : None));
3864 // XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flip View"),
3869 * It would be simpler to clear the window with XClearWindow()
3870 * but this causes a very distracting flicker.
3873 if (!repaint && lastBoardValid && lastFlipView == flipView)
3875 /* If too much changes (begin observing new game, etc.), don't
3877 do_flash = too_many_diffs(board, lastBoard) ? 0 : 1;
3879 /* Special check for castling so we don't flash both the king
3880 and the rook (just flash the king). */
3883 if (check_castle_draw(board, lastBoard, &rrow, &rcol))
3885 /* Draw rook with NO flashing. King will be drawn flashing later */
3886 DrawSquare(rrow, rcol, board[rrow][rcol], 0);
3887 lastBoard[rrow][rcol] = board[rrow][rcol];
3891 /* First pass -- Draw (newly) empty squares and repair damage.
3892 This prevents you from having a piece show up twice while it
3893 is flashing on its new square */
3894 for (i = 0; i < BOARD_HEIGHT; i++)
3895 for (j = 0; j < BOARD_WIDTH; j++)
3896 if ((board[i][j] != lastBoard[i][j] && board[i][j] == EmptySquare)
3899 DrawSquare(i, j, board[i][j], 0);
3900 damage[i][j] = False;
3903 /* Second pass -- Draw piece(s) in new position and flash them */
3904 for (i = 0; i < BOARD_HEIGHT; i++)
3905 for (j = 0; j < BOARD_WIDTH; j++)
3906 if (board[i][j] != lastBoard[i][j])
3908 DrawSquare(i, j, board[i][j], do_flash);
3920 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
3922 cairo_set_line_width (cr, lineGap);
3924 /* TODO: use appdata colors */
3925 cairo_set_source_rgba (cr, 0, 1, 0, 1.0);
3929 for (i = 0; i < BOARD_HEIGHT + 1; i++)
3932 x2 = lineGap + BOARD_WIDTH * (squareSize + lineGap);
3933 y1 = y2 = lineGap / 2 + (i * (squareSize + lineGap));
3935 cairo_move_to (cr, x1, y1);
3936 cairo_rel_line_to (cr, x2,0);
3940 for (j = 0; j < BOARD_WIDTH + 1; j++)
3943 y2 = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
3944 x1 = x2 = lineGap / 2 + (j * (squareSize + lineGap));
3946 cairo_move_to (cr, x1, y1);
3947 cairo_rel_line_to (cr, 0, y2);
3956 for (i = 0; i < BOARD_HEIGHT; i++)
3957 for (j = 0; j < BOARD_WIDTH; j++)
3959 DrawSquare(i, j, board[i][j], 0);
3960 damage[i][j] = False;
3964 CopyBoard(lastBoard, board);
3966 lastFlipView = flipView;
3968 /* Draw highlights */
3969 if (pm1X >= 0 && pm1Y >= 0)
3971 drawHighlight(pm1X, pm1Y, LINE_TYPE_PRE);
3973 if (pm2X >= 0 && pm2Y >= 0)
3975 drawHighlight(pm2X, pm2Y, LINE_TYPE_PRE);
3977 if (hi1X >= 0 && hi1Y >= 0)
3979 drawHighlight(hi1X, hi1Y, LINE_TYPE_HIGHLIGHT);
3981 if (hi2X >= 0 && hi2Y >= 0)
3983 drawHighlight(hi2X, hi2Y, LINE_TYPE_HIGHLIGHT);
3986 /* If piece being dragged around board, must redraw that too */
3993 * event handler for parsing user moves
3995 // [HGM] This routine will need quite some reworking. Although the backend still supports the old
3996 // way of doing things, by calling UserMoveEvent() to test the legality of the move and then perform
3997 // it at the end, and doing all kind of preliminary tests here (e.g. to weed out self-captures), it
3998 // should be made to use the new way, of calling UserMoveTest early to determine the legality of the
3999 // move, (which will weed out the illegal selfcaptures and moves into the holdings, and flag promotions),
4000 // and at the end FinishMove() to perform the move after optional promotion popups.
4001 // For now I patched it to allow self-capture with King, and suppress clicks between board and holdings.
4002 void HandleUserMove(w, event, prms, nprms)
4009 Boolean saveAnimate;
4010 static int second = 0, promotionChoice = 0;
4013 if (w != boardWidget || errorExitStatus != -1) return;
4015 x = EventToSquare(event->xbutton.x, BOARD_WIDTH);
4016 y = EventToSquare(event->xbutton.y, BOARD_HEIGHT);
4017 if (!flipView && y >= 0) {
4018 y = BOARD_HEIGHT - 1 - y;
4020 if (flipView && x >= 0) {
4021 x = BOARD_WIDTH - 1 - x;
4024 if(promotionChoice) { // we are waiting for a click to indicate promotion piece
4025 if(event->type == ButtonRelease) return; // ignore upclick of click-click destination
4026 promotionChoice = FALSE; // only one chance: if click not OK it is interpreted as cancel
4027 if(appData.debugMode) fprintf(debugFP, "promotion click, x=%d, y=%d\n", x, y);
4028 if(gameInfo.holdingsWidth &&
4029 (WhiteOnMove(currentMove)
4030 ? x == BOARD_WIDTH-1 && y < gameInfo.holdingsSize && y > 0
4031 : x == 0 && y >= BOARD_HEIGHT - gameInfo.holdingsSize && y < BOARD_HEIGHT-1) ) {
4032 // click in right holdings, for determining promotion piece
4033 ChessSquare p = boards[currentMove][y][x];
4034 if(appData.debugMode) fprintf(debugFP, "square contains %d\n", (int)p);
4035 if(p != EmptySquare) {
4036 FinishMove(NormalMove, fromX, fromY, toX, toY, ToLower(PieceToChar(p)));
4041 DrawPosition(FALSE, boards[currentMove]);
4044 if (event->type == ButtonPress) ErrorPopDown();
4047 if (event->type == ButtonPress) {
4048 // XtPopdown(promotionShell);
4049 // XtDestroyWidget(promotionShell);
4050 promotionUp = False;
4058 /* [HGM] holdings: next 5 lines: ignore all clicks between board and holdings */
4059 if(event->type == ButtonPress
4060 && ( x == BOARD_LEFT-1 ||
4062 (x == BOARD_LEFT-2 && y < BOARD_HEIGHT-gameInfo.holdingsSize ) ||
4063 (x == BOARD_RGHT+1 && y >= gameInfo.holdingsSize)) )
4067 if (event->type == ButtonPress) {
4068 /* First square, prepare to drag */
4069 if (OKToStartUserMove(x, y)) {
4073 DragPieceBegin(event->xbutton.x, event->xbutton.y);
4074 if (appData.highlightDragging) {
4075 SetHighlights(x, y, -1, -1);
4083 if (event->type == ButtonRelease && x == fromX && y == fromY) {
4084 /* Click on single square in stead of drag-drop */
4085 DragPieceEnd(event->xbutton.x, event->xbutton.y);
4086 if (appData.animateDragging) {
4087 /* Undo animation damage if any */
4088 DrawPosition(FALSE, NULL);
4091 /* Second up/down in same square; just abort move */
4096 ClearPremoveHighlights();
4098 /* First upclick in same square; start click-click mode */
4099 SetHighlights(x, y, -1, -1);
4104 moveType = UserMoveTest(fromX, fromY, x, y, NULLCHAR, event->type == ButtonRelease);
4106 if (moveType == Comment) { // kludge for indicating capture-own on Press
4107 /* Clicked again on same color piece -- changed his mind */
4108 /* note that re-clicking same square always hits same color piece */
4109 second = (x == fromX && y == fromY);
4110 if (appData.highlightDragging) {
4111 SetHighlights(x, y, -1, -1);
4115 if (OKToStartUserMove(x, y)) {
4118 DragPieceBegin(event->xbutton.x, event->xbutton.y);
4123 if(moveType == AmbiguousMove) { // kludge to indicate edit-position move
4126 DragPieceEnd(event->xbutton.x, event->xbutton.y);
4127 DrawPosition(FALSE, boards[currentMove]);
4131 /* Complete move; (x,y) is now different from (fromX, fromY) on both Press and Release */
4134 saveAnimate = appData.animate;
4135 if (event->type == ButtonPress) {
4136 /* Finish clickclick move */
4137 if (appData.animate || appData.highlightLastMove) {
4138 SetHighlights(fromX, fromY, toX, toY);
4143 /* Finish drag move */
4144 if (appData.highlightLastMove) {
4145 SetHighlights(fromX, fromY, toX, toY);
4149 DragPieceEnd(event->xbutton.x, event->xbutton.y);
4150 /* Don't animate move and drag both */
4151 appData.animate = FALSE;
4153 if (moveType == WhitePromotionKnight || moveType == BlackPromotionKnight ||
4154 (moveType == WhitePromotionQueen || moveType == BlackPromotionQueen) &&
4155 appData.alwaysPromoteToQueen) { // promotion, but no choice
4156 FinishMove(moveType, fromX, fromY, toX, toY, 'q');
4158 if (moveType == WhitePromotionQueen || moveType == BlackPromotionQueen ) {
4159 SetHighlights(fromX, fromY, toX, toY);
4160 if(gameInfo.variant == VariantSuper || gameInfo.variant == VariantGreat) {
4161 // [HGM] super: promotion to captured piece selected from holdings
4162 ChessSquare p = boards[currentMove][fromY][fromX], q = boards[currentMove][toY][toX];
4163 promotionChoice = TRUE;
4164 // kludge follows to temporarily execute move on display, without promoting yet
4165 boards[currentMove][fromY][fromX] = EmptySquare; // move Pawn to 8th rank
4166 boards[currentMove][toY][toX] = p;
4167 DrawPosition(FALSE, boards[currentMove]);
4168 boards[currentMove][fromY][fromX] = p; // take back, but display stays
4169 boards[currentMove][toY][toX] = q;
4170 DisplayMessage("Click in holdings to choose piece", "");
4174 goto skipClearingFrom; // the skipped stuff is done asynchronously by PromotionCallback
4176 if(moveType != ImpossibleMove) { // valid move, but no promotion
4177 FinishMove(moveType, fromX, fromY, toX, toY, NULLCHAR);
4178 } else { // invalid move; could have set premove
4181 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
4182 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
4185 appData.animate = saveAnimate;
4186 if (appData.animate || appData.animateDragging) {
4187 /* Undo animation damage if needed */
4188 DrawPosition(FALSE, NULL);
4192 void AnimateUserMove (Widget w, XEvent * event,
4193 String * params, Cardinal * nParams)
4195 DragPieceMove(event->xmotion.x, event->xmotion.y);
4198 Widget CommentCreate(name, text, mutable, callback, lines)
4200 int /*Boolean*/ mutable;
4201 XtCallbackProc callback;
4205 Widget shell, layout, form, edit, b_ok, b_cancel, b_clear, b_close, b_edit;
4210 XtSetArg(args[j], XtNwidth, &bw_width); j++;
4211 XtGetValues(boardWidget, args, j);
4214 XtSetArg(args[j], XtNresizable, True); j++;
4217 XtCreatePopupShell(name, topLevelShellWidgetClass,
4218 shellWidget, args, j);
4221 XtCreatePopupShell(name, transientShellWidgetClass,
4222 shellWidget, args, j);
4225 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
4226 layoutArgs, XtNumber(layoutArgs));
4228 XtCreateManagedWidget("form", formWidgetClass, layout,
4229 formArgs, XtNumber(formArgs));
4233 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
4234 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
4236 XtSetArg(args[j], XtNstring, text); j++;
4237 XtSetArg(args[j], XtNtop, XtChainTop); j++;
4238 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4239 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4240 XtSetArg(args[j], XtNright, XtChainRight); j++;
4241 XtSetArg(args[j], XtNresizable, True); j++;
4242 XtSetArg(args[j], XtNwidth, bw_width); j++; /*force wider than buttons*/
4243 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
4244 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
4245 XtSetArg(args[j], XtNautoFill, True); j++;
4246 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
4248 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
4252 XtSetArg(args[j], XtNfromVert, edit); j++;
4253 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4254 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4255 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4256 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4258 XtCreateManagedWidget(_("ok"), commandWidgetClass, form, args, j);
4259 XtAddCallback(b_ok, XtNcallback, callback, (XtPointer) 0);
4262 XtSetArg(args[j], XtNfromVert, edit); j++;
4263 XtSetArg(args[j], XtNfromHoriz, b_ok); j++;
4264 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4265 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4266 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4267 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4269 XtCreateManagedWidget(_("cancel"), commandWidgetClass, form, args, j);
4270 XtAddCallback(b_cancel, XtNcallback, callback, (XtPointer) 0);
4273 XtSetArg(args[j], XtNfromVert, edit); j++;
4274 XtSetArg(args[j], XtNfromHoriz, b_cancel); j++;
4275 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4276 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4277 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4278 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4280 XtCreateManagedWidget(_("clear"), commandWidgetClass, form, args, j);
4281 XtAddCallback(b_clear, XtNcallback, callback, (XtPointer) 0);
4284 XtSetArg(args[j], XtNfromVert, edit); j++;
4285 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4286 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4287 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4288 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4290 XtCreateManagedWidget(_("close"), commandWidgetClass, form, args, j);
4291 XtAddCallback(b_close, XtNcallback, callback, (XtPointer) 0);
4294 XtSetArg(args[j], XtNfromVert, edit); j++;
4295 XtSetArg(args[j], XtNfromHoriz, b_close); j++;
4296 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4297 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4298 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4299 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4301 XtCreateManagedWidget(_("edit"), commandWidgetClass, form, args, j);
4302 XtAddCallback(b_edit, XtNcallback, callback, (XtPointer) 0);
4305 XtRealizeWidget(shell);
4307 if (commentX == -1) {
4310 Dimension pw_height;
4311 Dimension ew_height;
4314 XtSetArg(args[j], XtNheight, &ew_height); j++;
4315 XtGetValues(edit, args, j);
4318 XtSetArg(args[j], XtNheight, &pw_height); j++;
4319 XtGetValues(shell, args, j);
4320 commentH = pw_height + (lines - 1) * ew_height;
4321 commentW = bw_width - 16;
4323 XSync(xDisplay, False);
4325 /* This code seems to tickle an X bug if it is executed too soon
4326 after xboard starts up. The coordinates get transformed as if
4327 the main window was positioned at (0, 0).
4329 XtTranslateCoords(shellWidget,
4330 (bw_width - commentW) / 2, 0 - commentH / 2,
4331 &commentX, &commentY);
4333 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
4334 RootWindowOfScreen(XtScreen(shellWidget)),
4335 (bw_width - commentW) / 2, 0 - commentH / 2,
4340 if (commentY < 0) commentY = 0; /*avoid positioning top offscreen*/
4343 XtSetArg(args[j], XtNheight, commentH); j++;
4344 XtSetArg(args[j], XtNwidth, commentW); j++;
4345 XtSetArg(args[j], XtNx, commentX); j++;
4346 XtSetArg(args[j], XtNy, commentY); j++;
4347 XtSetValues(shell, args, j);
4348 XtSetKeyboardFocus(shell, edit);
4353 /* Used for analysis window and ICS input window */
4354 Widget MiscCreate(name, text, mutable, callback, lines)
4356 int /*Boolean*/ mutable;
4357 XtCallbackProc callback;
4361 Widget shell, layout, form, edit;
4363 Dimension bw_width, pw_height, ew_height, w, h;
4369 XtSetArg(args[j], XtNresizable, True); j++;
4372 XtCreatePopupShell(name, topLevelShellWidgetClass,
4373 shellWidget, args, j);
4376 XtCreatePopupShell(name, transientShellWidgetClass,
4377 shellWidget, args, j);
4380 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
4381 layoutArgs, XtNumber(layoutArgs));
4383 XtCreateManagedWidget("form", formWidgetClass, layout,
4384 formArgs, XtNumber(formArgs));
4388 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
4389 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
4391 XtSetArg(args[j], XtNstring, text); j++;
4392 XtSetArg(args[j], XtNtop, XtChainTop); j++;
4393 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4394 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4395 XtSetArg(args[j], XtNright, XtChainRight); j++;
4396 XtSetArg(args[j], XtNresizable, True); j++;
4397 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
4398 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
4399 XtSetArg(args[j], XtNautoFill, True); j++;
4400 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
4402 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
4404 XtRealizeWidget(shell);
4407 XtSetArg(args[j], XtNwidth, &bw_width); j++;
4408 XtGetValues(boardWidget, args, j);
4411 XtSetArg(args[j], XtNheight, &ew_height); j++;
4412 XtGetValues(edit, args, j);
4415 XtSetArg(args[j], XtNheight, &pw_height); j++;
4416 XtGetValues(shell, args, j);
4417 h = pw_height + (lines - 1) * ew_height;
4420 XSync(xDisplay, False);
4422 /* This code seems to tickle an X bug if it is executed too soon
4423 after xboard starts up. The coordinates get transformed as if
4424 the main window was positioned at (0, 0).
4426 XtTranslateCoords(shellWidget, (bw_width - w) / 2, 0 - h / 2, &x, &y);
4428 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
4429 RootWindowOfScreen(XtScreen(shellWidget)),
4430 (bw_width - w) / 2, 0 - h / 2, &xx, &yy, &junk);
4434 if (y < 0) y = 0; /*avoid positioning top offscreen*/
4437 XtSetArg(args[j], XtNheight, h); j++;
4438 XtSetArg(args[j], XtNwidth, w); j++;
4439 XtSetArg(args[j], XtNx, x); j++;
4440 XtSetArg(args[j], XtNy, y); j++;
4441 XtSetValues(shell, args, j);
4447 static int savedIndex; /* gross that this is global */
4449 void EditCommentPopUp(index, title, text)
4458 if (text == NULL) text = "";
4460 if (editShell == NULL) {
4462 CommentCreate(title, text, True, EditCommentCallback, 4);
4463 XtRealizeWidget(editShell);
4464 CatchDeleteWindow(editShell, "EditCommentPopDown");
4466 edit = XtNameToWidget(editShell, "*form.text");
4468 XtSetArg(args[j], XtNstring, text); j++;
4469 XtSetValues(edit, args, j);
4471 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4472 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4473 XtSetValues(editShell, args, j);
4476 XtPopup(editShell, XtGrabNone);
4480 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
4481 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
4485 void EditCommentCallback(w, client_data, call_data)
4487 XtPointer client_data, call_data;
4495 XtSetArg(args[j], XtNlabel, &name); j++;
4496 XtGetValues(w, args, j);
4498 if (strcmp(name, _("ok")) == 0) {
4499 edit = XtNameToWidget(editShell, "*form.text");
4501 XtSetArg(args[j], XtNstring, &val); j++;
4502 XtGetValues(edit, args, j);
4503 ReplaceComment(savedIndex, val);
4504 EditCommentPopDown();
4505 } else if (strcmp(name, _("cancel")) == 0) {
4506 EditCommentPopDown();
4507 } else if (strcmp(name, _("clear")) == 0) {
4508 edit = XtNameToWidget(editShell, "*form.text");
4509 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
4510 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
4514 void EditCommentPopDown()
4519 if (!editUp) return;
4521 XtSetArg(args[j], XtNx, &commentX); j++;
4522 XtSetArg(args[j], XtNy, &commentY); j++;
4523 XtSetArg(args[j], XtNheight, &commentH); j++;
4524 XtSetArg(args[j], XtNwidth, &commentW); j++;
4525 XtGetValues(editShell, args, j);
4526 XtPopdown(editShell);
4529 XtSetArg(args[j], XtNleftBitmap, None); j++;
4530 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
4534 void ICSInputBoxPopUp()
4539 char *title = _("ICS Input");
4542 if (ICSInputShell == NULL) {
4543 ICSInputShell = MiscCreate(title, "", True, NULL, 1);
4544 tr = XtParseTranslationTable(ICSInputTranslations);
4545 edit = XtNameToWidget(ICSInputShell, "*form.text");
4546 XtOverrideTranslations(edit, tr);
4547 XtRealizeWidget(ICSInputShell);
4548 CatchDeleteWindow(ICSInputShell, "ICSInputBoxPopDown");
4551 edit = XtNameToWidget(ICSInputShell, "*form.text");
4553 XtSetArg(args[j], XtNstring, ""); j++;
4554 XtSetValues(edit, args, j);
4556 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4557 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4558 XtSetValues(ICSInputShell, args, j);
4561 XtPopup(ICSInputShell, XtGrabNone);
4562 XtSetKeyboardFocus(ICSInputShell, edit);
4564 ICSInputBoxUp = True;
4566 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
4567 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
4571 void ICSInputSendText()
4578 edit = XtNameToWidget(ICSInputShell, "*form.text");
4580 XtSetArg(args[j], XtNstring, &val); j++;
4581 XtGetValues(edit, args, j);
4582 SendMultiLineToICS(val);
4583 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
4584 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
4587 void ICSInputBoxPopDown()
4592 if (!ICSInputBoxUp) return;
4594 XtPopdown(ICSInputShell);
4595 ICSInputBoxUp = False;
4597 XtSetArg(args[j], XtNleftBitmap, None); j++;
4598 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
4602 void CommentPopUp(title, text)
4609 if (commentShell == NULL) {
4611 CommentCreate(title, text, False, CommentCallback, 4);
4612 XtRealizeWidget(commentShell);
4613 CatchDeleteWindow(commentShell, "CommentPopDown");
4615 edit = XtNameToWidget(commentShell, "*form.text");
4617 XtSetArg(args[j], XtNstring, text); j++;
4618 XtSetValues(edit, args, j);
4620 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4621 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4622 XtSetValues(commentShell, args, j);
4625 XtPopup(commentShell, XtGrabNone);
4626 XSync(xDisplay, False);
4631 void CommentCallback(w, client_data, call_data)
4633 XtPointer client_data, call_data;
4640 XtSetArg(args[j], XtNlabel, &name); j++;
4641 XtGetValues(w, args, j);
4643 if (strcmp(name, _("close")) == 0) {
4645 } else if (strcmp(name, _("edit")) == 0) {
4652 void CommentPopDown()
4657 if (!commentUp) return;
4659 XtSetArg(args[j], XtNx, &commentX); j++;
4660 XtSetArg(args[j], XtNy, &commentY); j++;
4661 XtSetArg(args[j], XtNwidth, &commentW); j++;
4662 XtSetArg(args[j], XtNheight, &commentH); j++;
4663 XtGetValues(commentShell, args, j);
4664 XtPopdown(commentShell);
4665 XSync(xDisplay, False);
4669 void FileNamePopUp(label, def, proc, openMode)
4676 Widget popup, layout, dialog, edit;
4682 fileProc = proc; /* I can't see a way not */
4683 fileOpenMode = openMode; /* to use globals here */
4686 XtSetArg(args[i], XtNresizable, True); i++;
4687 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
4688 XtSetArg(args[i], XtNtitle, XtNewString(_("File name prompt"))); i++;
4689 fileNameShell = popup =
4690 XtCreatePopupShell("File name prompt", transientShellWidgetClass,
4691 shellWidget, args, i);
4694 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
4695 layoutArgs, XtNumber(layoutArgs));
4698 XtSetArg(args[i], XtNlabel, label); i++;
4699 XtSetArg(args[i], XtNvalue, def); i++;
4700 XtSetArg(args[i], XtNborderWidth, 0); i++;
4701 dialog = XtCreateManagedWidget("fileName", dialogWidgetClass,
4704 XawDialogAddButton(dialog, _("ok"), FileNameCallback, (XtPointer) dialog);
4705 XawDialogAddButton(dialog, _("cancel"), FileNameCallback,
4706 (XtPointer) dialog);
4708 XtRealizeWidget(popup);
4709 CatchDeleteWindow(popup, "FileNamePopDown");
4711 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
4712 &x, &y, &win_x, &win_y, &mask);
4714 XtSetArg(args[0], XtNx, x - 10);
4715 XtSetArg(args[1], XtNy, y - 30);
4716 XtSetValues(popup, args, 2);
4718 XtPopup(popup, XtGrabExclusive);
4721 edit = XtNameToWidget(dialog, "*value");
4722 XtSetKeyboardFocus(popup, edit);
4725 void FileNamePopDown()
4727 if (!filenameUp) return;
4728 XtPopdown(fileNameShell);
4729 XtDestroyWidget(fileNameShell);
4734 void FileNameCallback(w, client_data, call_data)
4736 XtPointer client_data, call_data;
4741 XtSetArg(args[0], XtNlabel, &name);
4742 XtGetValues(w, args, 1);
4744 if (strcmp(name, _("cancel")) == 0) {
4749 FileNameAction(w, NULL, NULL, NULL);
4752 void FileNameAction(w, event, prms, nprms)
4764 name = XawDialogGetValueString(w = XtParent(w));
4766 if ((name != NULL) && (*name != NULLCHAR)) {
4768 XtPopdown(w = XtParent(XtParent(w)));
4772 p = strrchr(buf, ' ');
4779 fullname = ExpandPathName(buf);
4781 ErrorPopUp(_("Error"), _("Can't open file"), FALSE);
4784 f = fopen(fullname, fileOpenMode);
4786 DisplayError(_("Failed to open file"), errno);
4788 (void) (*fileProc)(f, index, buf);
4795 XtPopdown(w = XtParent(XtParent(w)));
4801 void PromotionPopUp()
4804 Widget dialog, layout;
4806 Dimension bw_width, pw_width;
4810 XtSetArg(args[j], XtNwidth, &bw_width); j++;
4811 XtGetValues(boardWidget, args, j);
4814 XtSetArg(args[j], XtNresizable, True); j++;
4815 XtSetArg(args[j], XtNtitle, XtNewString(_("Promotion"))); j++;
4817 XtCreatePopupShell("Promotion", transientShellWidgetClass,
4818 shellWidget, args, j);
4820 XtCreateManagedWidget(layoutName, formWidgetClass, promotionShell,
4821 layoutArgs, XtNumber(layoutArgs));
4824 XtSetArg(args[j], XtNlabel, _("Promote to what?")); j++;
4825 XtSetArg(args[j], XtNborderWidth, 0); j++;
4826 dialog = XtCreateManagedWidget("promotion", dialogWidgetClass,
4829 if(gameInfo.variant != VariantShogi) {
4830 XawDialogAddButton(dialog, _("Queen"), PromotionCallback,
4831 (XtPointer) dialog);
4832 XawDialogAddButton(dialog, _("Rook"), PromotionCallback,
4833 (XtPointer) dialog);
4834 XawDialogAddButton(dialog, _("Bishop"), PromotionCallback,
4835 (XtPointer) dialog);
4836 XawDialogAddButton(dialog, _("Knight"), PromotionCallback,
4837 (XtPointer) dialog);
4838 if (!appData.testLegality || gameInfo.variant == VariantSuicide ||
4839 gameInfo.variant == VariantGiveaway) {
4840 XawDialogAddButton(dialog, _("King"), PromotionCallback,
4841 (XtPointer) dialog);
4843 if(gameInfo.variant == VariantCapablanca ||
4844 gameInfo.variant == VariantGothic ||
4845 gameInfo.variant == VariantCapaRandom) {
4846 XawDialogAddButton(dialog, _("Archbishop"), PromotionCallback,
4847 (XtPointer) dialog);
4848 XawDialogAddButton(dialog, _("Chancellor"), PromotionCallback,
4849 (XtPointer) dialog);
4851 } else // [HGM] shogi
4853 XawDialogAddButton(dialog, _("Promote"), PromotionCallback,
4854 (XtPointer) dialog);
4855 XawDialogAddButton(dialog, _("Defer"), PromotionCallback,
4856 (XtPointer) dialog);
4858 XawDialogAddButton(dialog, _("cancel"), PromotionCallback,
4859 (XtPointer) dialog);
4861 XtRealizeWidget(promotionShell);
4862 CatchDeleteWindow(promotionShell, "PromotionPopDown");
4865 XtSetArg(args[j], XtNwidth, &pw_width); j++;
4866 XtGetValues(promotionShell, args, j);
4868 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
4869 lineGap + squareSize/3 +
4870 ((toY == BOARD_HEIGHT-1) ^ (flipView) ?
4871 0 : 6*(squareSize + lineGap)), &x, &y);
4874 XtSetArg(args[j], XtNx, x); j++;
4875 XtSetArg(args[j], XtNy, y); j++;
4876 XtSetValues(promotionShell, args, j);
4878 XtPopup(promotionShell, XtGrabNone);
4883 void PromotionPopDown()
4885 if (!promotionUp) return;
4886 XtPopdown(promotionShell);
4887 XtDestroyWidget(promotionShell);
4888 promotionUp = False;
4891 void PromotionCallback(w, client_data, call_data)
4893 XtPointer client_data, call_data;
4899 XtSetArg(args[0], XtNlabel, &name);
4900 XtGetValues(w, args, 1);
4904 if (fromX == -1) return;
4906 if (strcmp(name, _("cancel")) == 0) {
4910 } else if (strcmp(name, _("Knight")) == 0) {
4912 } else if (strcmp(name, _("Promote")) == 0) {
4914 } else if (strcmp(name, _("Defer")) == 0) {
4917 promoChar = ToLower(name[0]);
4920 FinishMove(NormalMove, fromX, fromY, toX, toY, promoChar);
4922 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
4923 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
4928 void ErrorCallback(w, client_data, call_data)
4930 XtPointer client_data, call_data;
4933 XtPopdown(w = XtParent(XtParent(XtParent(w))));
4935 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
4941 if (!errorUp) return;
4945 gtk_widget_destroy(GTK_WIDGET(GUI_Error));
4947 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
4952 void ErrorPopUp(title, label, modal)
4953 char *title, *label;
4956 GUI_Error = gtk_message_dialog_new(GTK_WINDOW(GUI_Window),
4957 GTK_DIALOG_DESTROY_WITH_PARENT,
4962 gtk_window_set_title(GTK_WINDOW(GUI_Error),(gchar *) title);
4965 gtk_dialog_run(GTK_DIALOG(GUI_Error));
4966 gtk_widget_destroy(GTK_WIDGET(GUI_Error));
4970 g_signal_connect_swapped (GUI_Error, "response",
4971 G_CALLBACK (ErrorPopDownProc),
4974 gtk_widget_show(GTK_WIDGET(GUI_Error));
4980 /* Disable all user input other than deleting the window */
4981 static int frozen = 0;
4985 /* Grab by a widget that doesn't accept input */
4986 // XtAddGrab(messageWidget, TRUE, FALSE);
4990 /* Undo a FreezeUI */
4993 if (!frozen) return;
4994 // XtRemoveGrab(messageWidget);
4998 char *ModeToWidgetName(mode)
5002 case BeginningOfGame:
5003 if (appData.icsActive)
5004 return "menuMode.ICS Client";
5005 else if (appData.noChessProgram ||
5006 *appData.cmailGameName != NULLCHAR)
5007 return "menuMode.Edit Game";
5009 return "menuMode.Machine Black";
5010 case MachinePlaysBlack:
5011 return "menuMode.Machine Black";
5012 case MachinePlaysWhite:
5013 return "menuMode.Machine White";
5015 return "menuMode.Analysis Mode";
5017 return "menuMode.Analyze File";
5018 case TwoMachinesPlay:
5019 return "menuMode.Two Machines";
5021 return "menuMode.Edit Game";
5022 case PlayFromGameFile:
5023 return "menuFile.Load Game";
5025 return "menuMode.Edit Position";
5027 return "menuMode.Training";
5028 case IcsPlayingWhite:
5029 case IcsPlayingBlack:
5033 return "menuMode.ICS Client";
5040 void ModeHighlight()
5042 static int oldPausing = FALSE;
5043 static GameMode oldmode = (GameMode) -1;
5046 // todo this toggling of the pause button doesn't seem to work?
5047 // e.g. select pause from buttonbar doesn't activate menumode.pause
5049 // if (!boardWidget || !XtIsRealized(boardWidget)) return;
5051 if (pausing != oldPausing) {
5052 oldPausing = pausing;
5053 gtk_button_set_relief(GTK_BUTTON (gtk_builder_get_object (builder, "menuMode.Pause")),pausing?GTK_RELIEF_NORMAL:GTK_RELIEF_NONE);
5054 /* toggle background color in showbuttonbar */
5055 if (appData.showButtonBar) {
5057 gtk_button_pressed(GTK_BUTTON (gtk_builder_get_object (builder, "buttonbar.Pause")));
5059 gtk_button_released(GTK_BUTTON (gtk_builder_get_object (builder, "buttonbar.Pause")));
5064 wname = ModeToWidgetName(oldmode);
5066 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, wname)),True);
5070 /* Maybe all the enables should be handled here, not just this one */
5071 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuMode.Training")),
5072 gameMode == Training || gameMode == PlayFromGameFile);
5077 * Button/menu procedures
5080 int LoadGamePopUp(f, gameNumber, title)
5085 cmailMsgLoaded = FALSE;
5087 if (gameNumber == 0)
5089 int error = GameListBuild(f);
5093 DisplayError(_("Cannot build game list"), error);
5095 else if (!ListEmpty(&gameList)
5096 && ((ListGame *) gameList.tailPred)->number > 1)
5098 GameListPopUp(f, title);
5106 return LoadGame(f, gameNumber, title, FALSE);
5109 void LoadPositionProc(w, event, prms, nprms)
5115 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
5118 FileNamePopUp(_("Load position file name?"), "", LoadPosition, "rb");
5121 void SaveGameProc(w, event, prms, nprms)
5127 FileNamePopUp(_("Save game file name?"),
5128 DefaultFileName(appData.oldSaveStyle ? "game" : "pgn"),
5132 void SavePositionProc(w, event, prms, nprms)
5138 FileNamePopUp(_("Save position file name?"),
5139 DefaultFileName(appData.oldSaveStyle ? "pos" : "fen"),
5143 void ReloadCmailMsgProc(w, event, prms, nprms)
5149 ReloadCmailMsgEvent(FALSE);
5152 void MailMoveProc(w, event, prms, nprms)
5161 /* this variable is shared between CopyPositionProc and SendPositionSelection */
5162 static char *selected_fen_position=NULL;
5165 SendPositionSelection(Widget w, Atom *selection, Atom *target,
5166 Atom *type_return, XtPointer *value_return,
5167 unsigned long *length_return, int *format_return)
5169 char *selection_tmp;
5171 if (!selected_fen_position) return False; /* should never happen */
5172 if (*target == XA_STRING){
5173 /* note: since no XtSelectionDoneProc was registered, Xt will
5174 * automatically call XtFree on the value returned. So have to
5175 * make a copy of it allocated with XtMalloc */
5176 selection_tmp= XtMalloc(strlen(selected_fen_position)+16);
5177 strcpy(selection_tmp, selected_fen_position);
5179 *value_return=selection_tmp;
5180 *length_return=strlen(selection_tmp);
5181 *type_return=XA_STRING;
5182 *format_return = 8; /* bits per byte */
5189 /* note: when called from menu all parameters are NULL, so no clue what the
5190 * Widget which was clicked on was, or what the click event was
5192 void CopyPositionProc(w, event, prms, nprms)
5200 if (selected_fen_position) free(selected_fen_position);
5201 selected_fen_position = (char *)PositionToFEN(currentMove, NULL);
5202 if (!selected_fen_position) return;
5203 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
5205 SendPositionSelection,
5206 NULL/* lose_ownership_proc */ ,
5207 NULL/* transfer_done_proc */);
5209 free(selected_fen_position);
5210 selected_fen_position=NULL;
5214 /* function called when the data to Paste is ready */
5216 PastePositionCB(Widget w, XtPointer client_data, Atom *selection,
5217 Atom *type, XtPointer value, unsigned long *len, int *format)
5220 if (value==NULL || *len==0) return; /* nothing had been selected to copy */
5221 fenstr[*len]='\0'; /* normally this string is terminated, but be safe */
5222 EditPositionPasteFEN(fenstr);
5226 /* called when Paste Position button is pressed,
5227 * all parameters will be NULL */
5228 void PastePositionProc(w, event, prms, nprms)
5234 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
5235 /* (XtSelectionCallbackProc) */ PastePositionCB,
5236 NULL, /* client_data passed to PastePositionCB */
5238 /* better to use the time field from the event that triggered the
5239 * call to this function, but that isn't trivial to get
5247 SendGameSelection(Widget w, Atom *selection, Atom *target,
5248 Atom *type_return, XtPointer *value_return,
5249 unsigned long *length_return, int *format_return)
5251 char *selection_tmp;
5253 if (*target == XA_STRING){
5254 FILE* f = fopen(gameCopyFilename, "r");
5257 if (f == NULL) return False;
5261 selection_tmp = XtMalloc(len + 1);
5262 count = fread(selection_tmp, 1, len, f);
5264 XtFree(selection_tmp);
5267 selection_tmp[len] = NULLCHAR;
5268 *value_return = selection_tmp;
5269 *length_return = len;
5270 *type_return = XA_STRING;
5271 *format_return = 8; /* bits per byte */
5278 /* note: when called from menu all parameters are NULL, so no clue what the
5279 * Widget which was clicked on was, or what the click event was
5281 void CopyGameProc(w, event, prms, nprms)
5289 ret = SaveGameToFile(gameCopyFilename, FALSE);
5292 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
5295 NULL/* lose_ownership_proc */ ,
5296 NULL/* transfer_done_proc */);
5299 /* function called when the data to Paste is ready */
5301 PasteGameCB(Widget w, XtPointer client_data, Atom *selection,
5302 Atom *type, XtPointer value, unsigned long *len, int *format)
5305 if (value == NULL || *len == 0) {
5306 return; /* nothing had been selected to copy */
5308 f = fopen(gamePasteFilename, "w");
5310 DisplayError(_("Can't open temp file"), errno);
5313 fwrite(value, 1, *len, f);
5316 LoadGameFromFile(gamePasteFilename, 0, gamePasteFilename, TRUE);
5319 /* called when Paste Game button is pressed,
5320 * all parameters will be NULL */
5321 void PasteGameProc(w, event, prms, nprms)
5327 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
5328 /* (XtSelectionCallbackProc) */ PasteGameCB,
5329 NULL, /* client_data passed to PasteGameCB */
5331 /* better to use the time field from the event that triggered the
5332 * call to this function, but that isn't trivial to get
5342 SaveGameProc(NULL, NULL, NULL, NULL);
5345 void AnalyzeModeProc(w, event, prms, nprms)
5353 if (!first.analysisSupport) {
5354 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
5355 DisplayError(buf, 0);
5358 /* [DM] icsEngineAnalyze [HGM] This is horrible code; reverse the gameMode and isEngineAnalyze tests! */
5359 if (appData.icsActive) {
5360 if (gameMode != IcsObserving) {
5361 sprintf(buf,_("You are not observing a game"));
5362 DisplayError(buf, 0);
5364 if (appData.icsEngineAnalyze) {
5365 if (appData.debugMode)
5366 fprintf(debugFP, _("Found unexpected active ICS engine analyze \n"));
5372 /* if enable, use want disable icsEngineAnalyze */
5373 if (appData.icsEngineAnalyze) {
5378 appData.icsEngineAnalyze = TRUE;
5379 if (appData.debugMode)
5380 fprintf(debugFP, _("ICS engine analyze starting... \n"));
5382 if (!appData.showThinking)
5383 ShowThinkingProc(NULL,NULL);
5388 void AnalyzeFileProc(w, event, prms, nprms)
5394 if (!first.analysisSupport) {
5396 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
5397 DisplayError(buf, 0);
5402 if (!appData.showThinking)
5403 ShowThinkingProc(NULL,NULL);
5406 FileNamePopUp(_("File to analyze"), "", LoadGamePopUp, "rb");
5407 AnalysisPeriodicEvent(1);
5411 void EditGameProc(w, event, prms, nprms)
5420 void EditPositionProc(w, event, prms, nprms)
5426 EditPositionEvent();
5429 void TrainingProc(w, event, prms, nprms)
5438 void EditCommentProc(w, event, prms, nprms)
5445 EditCommentPopDown();
5451 void IcsInputBoxProc(w, event, prms, nprms)
5457 if (ICSInputBoxUp) {
5458 ICSInputBoxPopDown();
5465 void EnterKeyProc(w, event, prms, nprms)
5471 if (ICSInputBoxUp == True)
5475 void AlwaysQueenProc(w, event, prms, nprms)
5483 appData.alwaysPromoteToQueen = !appData.alwaysPromoteToQueen;
5485 if (appData.alwaysPromoteToQueen) {
5486 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5488 XtSetArg(args[0], XtNleftBitmap, None);
5490 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
5494 void AnimateDraggingProc(w, event, prms, nprms)
5502 appData.animateDragging = !appData.animateDragging;
5504 if (appData.animateDragging) {
5505 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5508 XtSetArg(args[0], XtNleftBitmap, None);
5510 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Dragging"),
5514 void AnimateMovingProc(w, event, prms, nprms)
5522 appData.animate = !appData.animate;
5524 if (appData.animate) {
5525 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5528 XtSetArg(args[0], XtNleftBitmap, None);
5530 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
5534 void AutobsProc(w, event, prms, nprms)
5542 appData.autoObserve = !appData.autoObserve;
5544 if (appData.autoObserve) {
5545 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5547 XtSetArg(args[0], XtNleftBitmap, None);
5549 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
5553 void AutoraiseProc(w, event, prms, nprms)
5561 appData.autoRaiseBoard = !appData.autoRaiseBoard;
5563 if (appData.autoRaiseBoard) {
5564 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5566 XtSetArg(args[0], XtNleftBitmap, None);
5568 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Raise Board"),
5572 void AutosaveProc(w, event, prms, nprms)
5580 appData.autoSaveGames = !appData.autoSaveGames;
5582 if (appData.autoSaveGames) {
5583 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5585 XtSetArg(args[0], XtNleftBitmap, None);
5587 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
5591 void BlindfoldProc(w, event, prms, nprms)
5599 appData.blindfold = !appData.blindfold;
5601 if (appData.blindfold) {
5602 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5604 XtSetArg(args[0], XtNleftBitmap, None);
5606 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Blindfold"),
5609 DrawPosition(True, NULL);
5612 void TestLegalityProc(w, event, prms, nprms)
5620 appData.testLegality = !appData.testLegality;
5622 if (appData.testLegality) {
5623 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5625 XtSetArg(args[0], XtNleftBitmap, None);
5627 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Test Legality"),
5632 void FlashMovesProc(w, event, prms, nprms)
5640 if (appData.flashCount == 0) {
5641 appData.flashCount = 3;
5643 appData.flashCount = -appData.flashCount;
5646 if (appData.flashCount > 0) {
5647 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5649 XtSetArg(args[0], XtNleftBitmap, None);
5651 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flash Moves"),
5656 void HighlightDraggingProc(w, event, prms, nprms)
5664 appData.highlightDragging = !appData.highlightDragging;
5666 if (appData.highlightDragging) {
5667 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5669 XtSetArg(args[0], XtNleftBitmap, None);
5671 XtSetValues(XtNameToWidget(menuBarWidget,
5672 "menuOptions.Highlight Dragging"), args, 1);
5676 void HighlightLastMoveProc(w, event, prms, nprms)
5684 appData.highlightLastMove = !appData.highlightLastMove;
5686 if (appData.highlightLastMove) {
5687 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5689 XtSetArg(args[0], XtNleftBitmap, None);
5691 XtSetValues(XtNameToWidget(menuBarWidget,
5692 "menuOptions.Highlight Last Move"), args, 1);
5695 void IcsAlarmProc(w, event, prms, nprms)
5703 appData.icsAlarm = !appData.icsAlarm;
5705 if (appData.icsAlarm) {
5706 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5708 XtSetArg(args[0], XtNleftBitmap, None);
5710 XtSetValues(XtNameToWidget(menuBarWidget,
5711 "menuOptions.ICS Alarm"), args, 1);
5714 void MoveSoundProc(w, event, prms, nprms)
5722 appData.ringBellAfterMoves = !appData.ringBellAfterMoves;
5724 if (appData.ringBellAfterMoves) {
5725 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5727 XtSetArg(args[0], XtNleftBitmap, None);
5729 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
5734 void OldSaveStyleProc(w, event, prms, nprms)
5742 appData.oldSaveStyle = !appData.oldSaveStyle;
5744 if (appData.oldSaveStyle) {
5745 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5747 XtSetArg(args[0], XtNleftBitmap, None);
5749 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Old Save Style"),
5753 void PeriodicUpdatesProc(w, event, prms, nprms)
5761 PeriodicUpdatesEvent(!appData.periodicUpdates);
5763 if (appData.periodicUpdates) {
5764 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5766 XtSetArg(args[0], XtNleftBitmap, None);
5768 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Periodic Updates"),
5772 void PonderNextMoveProc(w, event, prms, nprms)
5780 PonderNextMoveEvent(!appData.ponderNextMove);
5782 if (appData.ponderNextMove) {
5783 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5785 XtSetArg(args[0], XtNleftBitmap, None);
5787 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Ponder Next Move"),
5791 void PopupExitMessageProc(w, event, prms, nprms)
5799 appData.popupExitMessage = !appData.popupExitMessage;
5801 if (appData.popupExitMessage) {
5802 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5804 XtSetArg(args[0], XtNleftBitmap, None);
5806 XtSetValues(XtNameToWidget(menuBarWidget,
5807 "menuOptions.Popup Exit Message"), args, 1);
5810 void PopupMoveErrorsProc(w, event, prms, nprms)
5818 appData.popupMoveErrors = !appData.popupMoveErrors;
5820 if (appData.popupMoveErrors) {
5821 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5823 XtSetArg(args[0], XtNleftBitmap, None);
5825 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Popup Move Errors"),
5829 void PremoveProc(w, event, prms, nprms)
5837 appData.premove = !appData.premove;
5839 if (appData.premove) {
5840 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5842 XtSetArg(args[0], XtNleftBitmap, None);
5844 XtSetValues(XtNameToWidget(menuBarWidget,
5845 "menuOptions.Premove"), args, 1);
5848 void QuietPlayProc(w, event, prms, nprms)
5856 appData.quietPlay = !appData.quietPlay;
5858 if (appData.quietPlay) {
5859 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5861 XtSetArg(args[0], XtNleftBitmap, None);
5863 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Quiet Play"),
5867 void DebugProc(w, event, prms, nprms)
5873 appData.debugMode = !appData.debugMode;
5876 void AboutGameProc(w, event, prms, nprms)
5885 void NothingProc(w, event, prms, nprms)
5894 void Iconify(w, event, prms, nprms)
5903 XtSetArg(args[0], XtNiconic, True);
5904 XtSetValues(shellWidget, args, 1);
5907 void DisplayMessage(message, extMessage)
5908 gchar *message, *extMessage;
5915 snprintf(buf, sizeof(buf), "%s %s", message, extMessage);
5918 message = extMessage;
5921 gtk_label_set_text( GTK_LABEL(gtk_builder_get_object (builder, "Messages")),message);
5926 void DisplayTitle(text)
5929 gchar title[MSG_SIZ];
5931 if (text == NULL) text = "";
5933 if (appData.titleInWindow)
5938 if (*text != NULLCHAR)
5940 strcpy(title, text);
5942 else if (appData.icsActive)
5944 snprintf(title, sizeof(title), "%s: %s", programName, appData.icsHost);
5946 else if (appData.cmailGameName[0] != NULLCHAR)
5948 snprintf(title,sizeof(title), "%s: %s", programName, "CMail");
5950 // [HGM] license: This stuff should really be done in back-end, but WinBoard already had a pop-up for it
5952 else if (gameInfo.variant == VariantGothic)
5954 strcpy(title, GOTHIC);
5958 else if (gameInfo.variant == VariantFalcon)
5960 strcpy(title, FALCON);
5963 else if (appData.noChessProgram)
5965 strcpy(title, programName);
5969 snprintf(title,sizeof(title), "%s: %s", programName, first.tidy);
5971 gtk_window_set_title(GTK_WINDOW(GUI_Window),title);
5977 void DisplayError(message, error)
5984 if (appData.debugMode || appData.matchMode) {
5985 fprintf(stderr, "%s: %s\n", programName, message);
5988 if (appData.debugMode || appData.matchMode) {
5989 fprintf(stderr, "%s: %s: %s\n",
5990 programName, message, strerror(error));
5992 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
5995 ErrorPopUp(_("Error"), message, FALSE);
5999 void DisplayMoveError(message)
6004 DrawPosition(FALSE, NULL);
6005 if (appData.debugMode || appData.matchMode) {
6006 fprintf(stderr, "%s: %s\n", programName, message);
6008 if (appData.popupMoveErrors) {
6009 ErrorPopUp(_("Error"), message, FALSE);
6011 DisplayMessage(message, "");
6016 void DisplayFatalError(message, error, status)
6022 errorExitStatus = status;
6024 fprintf(stderr, "%s: %s\n", programName, message);
6026 fprintf(stderr, "%s: %s: %s\n",
6027 programName, message, strerror(error));
6028 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
6031 if (appData.popupExitMessage && boardWidget && XtIsRealized(boardWidget)) {
6032 ErrorPopUp(status ? _("Fatal Error") : _("Exiting"), message, TRUE);
6038 void DisplayInformation(message)
6042 ErrorPopUp(_("Information"), message, TRUE);
6045 void DisplayNote(message)
6049 ErrorPopUp(_("Note"), message, FALSE);
6053 NullXErrorCheck(dpy, error_event)
6055 XErrorEvent *error_event;
6060 void DisplayIcsInteractionTitle(message)
6063 if (oldICSInteractionTitle == NULL) {
6064 /* Magic to find the old window title, adapted from vim */
6065 char *wina = getenv("WINDOWID");
6067 Window win = (Window) atoi(wina);
6068 Window root, parent, *children;
6069 unsigned int nchildren;
6070 int (*oldHandler)() = XSetErrorHandler(NullXErrorCheck);
6072 if (XFetchName(xDisplay, win, &oldICSInteractionTitle)) break;
6073 if (!XQueryTree(xDisplay, win, &root, &parent,
6074 &children, &nchildren)) break;
6075 if (children) XFree((void *)children);
6076 if (parent == root || parent == 0) break;
6079 XSetErrorHandler(oldHandler);
6081 if (oldICSInteractionTitle == NULL) {
6082 oldICSInteractionTitle = "xterm";
6085 printf("\033]0;%s\007", message);
6089 char pendingReplyPrefix[MSG_SIZ];
6090 ProcRef pendingReplyPR;
6092 void AskQuestionProc(w, event, prms, nprms)
6099 fprintf(stderr, _("AskQuestionProc needed 4 parameters, got %d\n"),
6103 AskQuestionEvent(prms[0], prms[1], prms[2], prms[3]);
6106 void AskQuestionPopDown()
6108 if (!askQuestionUp) return;
6109 XtPopdown(askQuestionShell);
6110 XtDestroyWidget(askQuestionShell);
6111 askQuestionUp = False;
6114 void AskQuestionReplyAction(w, event, prms, nprms)
6124 reply = XawDialogGetValueString(w = XtParent(w));
6125 strcpy(buf, pendingReplyPrefix);
6126 if (*buf) strcat(buf, " ");
6129 OutputToProcess(pendingReplyPR, buf, strlen(buf), &err);
6130 AskQuestionPopDown();
6132 if (err) DisplayFatalError(_("Error writing to chess program"), err, 0);
6135 void AskQuestionCallback(w, client_data, call_data)
6137 XtPointer client_data, call_data;
6142 XtSetArg(args[0], XtNlabel, &name);
6143 XtGetValues(w, args, 1);
6145 if (strcmp(name, _("cancel")) == 0) {
6146 AskQuestionPopDown();
6148 AskQuestionReplyAction(w, NULL, NULL, NULL);
6152 void AskQuestion(title, question, replyPrefix, pr)
6153 char *title, *question, *replyPrefix;
6157 Widget popup, layout, dialog, edit;
6163 strcpy(pendingReplyPrefix, replyPrefix);
6164 pendingReplyPR = pr;
6167 XtSetArg(args[i], XtNresizable, True); i++;
6168 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
6169 askQuestionShell = popup =
6170 XtCreatePopupShell(title, transientShellWidgetClass,
6171 shellWidget, args, i);
6174 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
6175 layoutArgs, XtNumber(layoutArgs));
6178 XtSetArg(args[i], XtNlabel, question); i++;
6179 XtSetArg(args[i], XtNvalue, ""); i++;
6180 XtSetArg(args[i], XtNborderWidth, 0); i++;
6181 dialog = XtCreateManagedWidget("question", dialogWidgetClass,
6184 XawDialogAddButton(dialog, _("enter"), AskQuestionCallback,
6185 (XtPointer) dialog);
6186 XawDialogAddButton(dialog, _("cancel"), AskQuestionCallback,
6187 (XtPointer) dialog);
6189 XtRealizeWidget(popup);
6190 CatchDeleteWindow(popup, "AskQuestionPopDown");
6192 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
6193 &x, &y, &win_x, &win_y, &mask);
6195 XtSetArg(args[0], XtNx, x - 10);
6196 XtSetArg(args[1], XtNy, y - 30);
6197 XtSetValues(popup, args, 2);
6199 XtPopup(popup, XtGrabExclusive);
6200 askQuestionUp = True;
6202 edit = XtNameToWidget(dialog, "*value");
6203 XtSetKeyboardFocus(popup, edit);
6211 if (*name == NULLCHAR) {
6213 } else if (strcmp(name, "$") == 0) {
6214 putc(BELLCHAR, stderr);
6217 snprintf(buf, sizeof(buf), "%s '%s' &", appData.soundProgram, name);
6225 PlaySound(appData.soundMove);
6231 PlaySound(appData.soundIcsWin);
6237 PlaySound(appData.soundIcsLoss);
6243 PlaySound(appData.soundIcsDraw);
6247 PlayIcsUnfinishedSound()
6249 PlaySound(appData.soundIcsUnfinished);
6255 PlaySound(appData.soundIcsAlarm);
6261 system("stty echo");
6267 system("stty -echo");
6271 Colorize(cc, continuation)
6276 int count, outCount, error;
6278 if (textColors[(int)cc].bg > 0) {
6279 if (textColors[(int)cc].fg > 0) {
6280 sprintf(buf, "\033[0;%d;%d;%dm", textColors[(int)cc].attr,
6281 textColors[(int)cc].fg, textColors[(int)cc].bg);
6283 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
6284 textColors[(int)cc].bg);
6287 if (textColors[(int)cc].fg > 0) {
6288 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
6289 textColors[(int)cc].fg);
6291 sprintf(buf, "\033[0;%dm", textColors[(int)cc].attr);
6294 count = strlen(buf);
6295 outCount = OutputToProcess(NoProc, buf, count, &error);
6296 if (outCount < count) {
6297 DisplayFatalError(_("Error writing to display"), error, 1);
6300 if (continuation) return;
6303 PlaySound(appData.soundShout);
6306 PlaySound(appData.soundSShout);
6309 PlaySound(appData.soundChannel1);
6312 PlaySound(appData.soundChannel);
6315 PlaySound(appData.soundKibitz);
6318 PlaySound(appData.soundTell);
6320 case ColorChallenge:
6321 PlaySound(appData.soundChallenge);
6324 PlaySound(appData.soundRequest);
6327 PlaySound(appData.soundSeek);
6338 return getpwuid(getuid())->pw_name;
6341 static char *ExpandPathName(path)
6344 static char static_buf[2000];
6345 char *d, *s, buf[2000];
6351 while (*s && isspace(*s))
6360 if (*(s+1) == '/') {
6361 strcpy(d, getpwuid(getuid())->pw_dir);
6366 *strchr(buf, '/') = 0;
6367 pwd = getpwnam(buf);
6370 fprintf(stderr, _("ERROR: Unknown user %s (in path %s)\n"),
6374 strcpy(d, pwd->pw_dir);
6375 strcat(d, strchr(s+1, '/'));
6386 static char host_name[MSG_SIZ];
6388 #if HAVE_GETHOSTNAME
6389 gethostname(host_name, MSG_SIZ);
6391 #else /* not HAVE_GETHOSTNAME */
6392 # if HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H
6393 sysinfo(SI_HOSTNAME, host_name, MSG_SIZ);
6395 # else /* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
6397 # endif/* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
6398 #endif /* not HAVE_GETHOSTNAME */
6401 guint delayedEventTimerTag = 0;
6402 DelayedEventCallback delayedEventCallback = 0;
6405 FireDelayedEvent(data)
6409 g_source_remove(delayedEventTimerTag);
6410 delayedEventTimerTag = 0;
6413 delayedEventCallback();
6419 ScheduleDelayedEvent(cb, millisec)
6420 DelayedEventCallback cb; guint millisec;
6422 if(delayedEventTimerTag && delayedEventCallback == cb)
6423 // [HGM] alive: replace, rather than add or flush identical event
6424 g_source_remove(delayedEventTimerTag);
6425 delayedEventCallback = cb;
6426 delayedEventTimerTag = g_timeout_add(millisec,(GSourceFunc) FireDelayedEvent, NULL);
6430 DelayedEventCallback
6433 if (delayedEventTimerTag)
6435 return delayedEventCallback;
6444 CancelDelayedEvent()
6446 if (delayedEventTimerTag)
6448 g_source_remove(delayedEventTimerTag);
6449 delayedEventTimerTag = 0;
6455 guint loadGameTimerTag = 0;
6457 int LoadGameTimerRunning()
6459 return loadGameTimerTag != 0;
6462 int StopLoadGameTimer()
6464 if (loadGameTimerTag != 0) {
6465 g_source_remove(loadGameTimerTag);
6466 loadGameTimerTag = 0;
6474 LoadGameTimerCallback(data)
6478 g_source_remove(loadGameTimerTag);
6479 loadGameTimerTag = 0;
6486 StartLoadGameTimer(millisec)
6490 g_timeout_add( millisec, (GSourceFunc) LoadGameTimerCallback, NULL);
6494 guint analysisClockTag = 0;
6497 AnalysisClockCallback(data)
6500 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile
6501 || appData.icsEngineAnalyze)
6503 AnalysisPeriodicEvent(0);
6504 return 1; /* keep on going */
6506 return 0; /* stop timer */
6510 StartAnalysisClock()
6513 g_timeout_add( 2000,(GSourceFunc) AnalysisClockCallback, NULL);
6517 guint clockTimerTag = 0;
6519 int ClockTimerRunning()
6521 return clockTimerTag != 0;
6524 int StopClockTimer()
6526 if (clockTimerTag != 0)
6528 g_source_remove(clockTimerTag);
6539 ClockTimerCallback(data)
6543 g_source_remove(clockTimerTag);
6551 StartClockTimer(millisec)
6554 clockTimerTag = g_timeout_add(millisec,(GSourceFunc) ClockTimerCallback,NULL);
6559 DisplayTimerLabel(w, color, timer, highlight)
6568 if (appData.clockMode) {
6569 sprintf(buf, "%s: %s", color, TimeString(timer));
6571 sprintf(buf, "%s ", color);
6573 gtk_label_set_text(GTK_LABEL(w),buf);
6575 /* check for low time warning */
6576 // Pixel foregroundOrWarningColor = timerForegroundPixel;
6579 // appData.lowTimeWarning &&
6580 // (timer / 1000) < appData.icsAlarmTime)
6581 // foregroundOrWarningColor = lowTimeWarningColor;
6583 // if (appData.clockMode) {
6584 // sprintf(buf, "%s: %s", color, TimeString(timer));
6585 // XtSetArg(args[0], XtNlabel, buf);
6587 // sprintf(buf, "%s ", color);
6588 // XtSetArg(args[0], XtNlabel, buf);
6593 // XtSetArg(args[1], XtNbackground, foregroundOrWarningColor);
6594 // XtSetArg(args[2], XtNforeground, timerBackgroundPixel);
6596 // XtSetArg(args[1], XtNbackground, timerBackgroundPixel);
6597 // XtSetArg(args[2], XtNforeground, foregroundOrWarningColor);
6600 // XtSetValues(w, args, 3);
6605 DisplayWhiteClock(timeRemaining, highlight)
6609 if(appData.noGUI) return;
6611 DisplayTimerLabel(GUI_Whiteclock, _("White"), timeRemaining, highlight);
6612 if (highlight && WindowIcon == BlackIcon)
6614 WindowIcon = WhiteIcon;
6615 gtk_window_set_icon(GTK_WINDOW(GUI_Window),WindowIcon);
6620 DisplayBlackClock(timeRemaining, highlight)
6624 if(appData.noGUI) return;
6626 DisplayTimerLabel(GUI_Blackclock, _("Black"), timeRemaining, highlight);
6627 if (highlight && WindowIcon == WhiteIcon)
6629 WindowIcon = BlackIcon;
6630 gtk_window_set_icon(GTK_WINDOW(GUI_Window),WindowIcon);
6648 int StartChildProcess(cmdLine, dir, pr)
6655 int to_prog[2], from_prog[2];
6659 if (appData.debugMode) {
6660 fprintf(stderr, "StartChildProcess (dir=\"%s\") %s\n",dir, cmdLine);
6663 /* We do NOT feed the cmdLine to the shell; we just
6664 parse it into blank-separated arguments in the
6665 most simple-minded way possible.
6668 strcpy(buf, cmdLine);
6673 if (p == NULL) break;
6678 SetUpChildIO(to_prog, from_prog);
6681 signal(SIGWINCH, TermSizeSigHandler);
6684 if ((pid = fork()) == 0) {
6686 // [HGM] PSWBTM: made order resistant against case where fd of created pipe was 0 or 1
6687 close(to_prog[1]); // first close the unused pipe ends
6688 close(from_prog[0]);
6689 dup2(to_prog[0], 0); // to_prog was created first, nd is the only one to use 0 or 1
6690 dup2(from_prog[1], 1);
6691 if(to_prog[0] >= 2) close(to_prog[0]); // if 0 or 1, the dup2 already cosed the original
6692 close(from_prog[1]); // and closing again loses one of the pipes!
6693 if(fileno(stderr) >= 2) // better safe than sorry...
6694 dup2(1, fileno(stderr)); /* force stderr to the pipe */
6696 if (dir[0] != NULLCHAR && chdir(dir) != 0) {
6701 nice(appData.niceEngines); // [HGM] nice: adjust priority of engine proc
6703 execvp(argv[0], argv);
6705 /* If we get here, exec failed */
6710 /* Parent process */
6712 close(from_prog[1]);
6714 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
6717 cp->fdFrom = from_prog[0];
6718 cp->fdTo = to_prog[1];
6723 // [HGM] kill: implement the 'hard killing' of AS's Winboard_x
6724 static RETSIGTYPE AlarmCallBack(int n)
6730 DestroyChildProcess(pr, signalType)
6734 ChildProc *cp = (ChildProc *) pr;
6736 if (cp->kind != CPReal) return;
6738 if (signalType == 10) { // [HGM] kill: if it does not terminate in 3 sec, kill
6739 signal(SIGALRM, AlarmCallBack);
6741 if(wait((int *) 0) == -1) { // process does not terminate on its own accord
6742 kill(cp->pid, SIGKILL); // kill it forcefully
6743 wait((int *) 0); // and wait again
6747 kill(cp->pid, signalType == 9 ? SIGKILL : SIGTERM); // [HGM] kill: use hard kill if so requested
6749 /* Process is exiting either because of the kill or because of
6750 a quit command sent by the backend; either way, wait for it to die.
6759 InterruptChildProcess(pr)
6762 ChildProc *cp = (ChildProc *) pr;
6764 if (cp->kind != CPReal) return;
6765 (void) kill(cp->pid, SIGINT); /* stop it thinking */
6768 int OpenTelnet(host, port, pr)
6773 char cmdLine[MSG_SIZ];
6775 if (port[0] == NULLCHAR) {
6776 snprintf(cmdLine, sizeof(cmdLine), "%s %s", appData.telnetProgram, host);
6778 snprintf(cmdLine, sizeof(cmdLine), "%s %s %s", appData.telnetProgram, host, port);
6780 return StartChildProcess(cmdLine, "", pr);
6783 int OpenTCP(host, port, pr)
6789 DisplayFatalError(_("Socket support is not configured in"), 0, 2);
6790 #else /* !OMIT_SOCKETS */
6792 struct sockaddr_in sa;
6794 unsigned short uport;
6797 if ((s = socket(AF_INET, SOCK_STREAM, 6)) < 0) {
6801 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
6802 sa.sin_family = AF_INET;
6803 sa.sin_addr.s_addr = INADDR_ANY;
6804 uport = (unsigned short) 0;
6805 sa.sin_port = htons(uport);
6806 if (bind(s, (struct sockaddr *) &sa, sizeof(struct sockaddr_in)) < 0) {
6810 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
6811 if (!(hp = gethostbyname(host))) {
6813 if (sscanf(host, "%d.%d.%d.%d", &b0, &b1, &b2, &b3) == 4) {
6814 hp = (struct hostent *) calloc(1, sizeof(struct hostent));
6815 hp->h_addrtype = AF_INET;
6817 hp->h_addr_list = (char **) calloc(2, sizeof(char *));
6818 hp->h_addr_list[0] = (char *) malloc(4);
6819 hp->h_addr_list[0][0] = b0;
6820 hp->h_addr_list[0][1] = b1;
6821 hp->h_addr_list[0][2] = b2;
6822 hp->h_addr_list[0][3] = b3;
6827 sa.sin_family = hp->h_addrtype;
6828 uport = (unsigned short) atoi(port);
6829 sa.sin_port = htons(uport);
6830 memcpy((char *) &sa.sin_addr, hp->h_addr, hp->h_length);
6832 if (connect(s, (struct sockaddr *) &sa,
6833 sizeof(struct sockaddr_in)) < 0) {
6837 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
6844 #endif /* !OMIT_SOCKETS */
6849 int OpenCommPort(name, pr)
6856 fd = open(name, 2, 0);
6857 if (fd < 0) return errno;
6859 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
6869 int OpenLoopback(pr)
6875 SetUpChildIO(to, from);
6877 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
6880 cp->fdFrom = to[0]; /* note not from[0]; we are doing a loopback */
6887 int OpenRcmd(host, user, cmd, pr)
6888 char *host, *user, *cmd;
6891 DisplayFatalError(_("internal rcmd not implemented for Unix"), 0, 1);
6895 #define INPUT_SOURCE_BUF_SIZE 8192
6904 char buf[INPUT_SOURCE_BUF_SIZE];
6909 DoInputCallback(io,cond,data)
6914 /* read input from one of the input source (for example a chess program, ICS, etc).
6915 * and call a function that will handle the input
6918 int count; /* how many bytes did we read */
6922 /* All information (callback function, file descriptor, etc) is
6923 * saved in an InputSource structure
6925 InputSource *is = (InputSource *) data;
6929 count = read(is->fd, is->unused,
6930 INPUT_SOURCE_BUF_SIZE - (is->unused - is->buf));
6934 (is->func)(is, is->closure, is->buf, count, count ? errno : 0);
6937 is->unused += count;
6939 /* break input into lines and call the callback function on each
6942 while (p < is->unused)
6944 q = memchr(p, '\n', is->unused - p);
6945 if (q == NULL) break;
6947 (is->func)(is, is->closure, p, q - p, 0);
6950 /* remember not yet used part of the buffer */
6952 while (p < is->unused)
6960 /* read maximum length of input buffer and send the whole buffer
6961 * to the callback function
6963 count = read(is->fd, is->buf, INPUT_SOURCE_BUF_SIZE);
6968 (is->func)(is, is->closure, is->buf, count, error);
6974 InputSourceRef AddInputSource(pr, lineByLine, func, closure)
6981 GIOChannel *channel;
6982 ChildProc *cp = (ChildProc *) pr;
6984 is = (InputSource *) calloc(1, sizeof(InputSource));
6985 is->lineByLine = lineByLine;
6989 is->fd = fileno(stdin);
6991 is->kind = cp->kind;
6992 is->fd = cp->fdFrom;
6995 is->unused = is->buf;
6999 // is->xid = XtAppAddInput(appContext, is->fd,
7000 // (XtPointer) (XtInputReadMask),
7001 // (XtInputCallbackProc) DoInputCallback,
7005 /* TODO: will this work on windows?*/
7006 printf("DEBUG: fd=%d %d\n",is->fd,is);
7008 channel = g_io_channel_unix_new(is->fd);
7009 g_io_channel_set_close_on_unref (channel, TRUE);
7010 is->sid = g_io_add_watch(channel, G_IO_IN,(GIOFunc) DoInputCallback, is);
7011 is->closure = closure;
7012 return (InputSourceRef) is;
7016 RemoveInputSource(isr)
7019 InputSource *is = (InputSource *) isr;
7021 if (is->sid == 0) return;
7022 g_source_remove(is->sid);
7027 int OutputToProcess(pr, message, count, outError)
7033 ChildProc *cp = (ChildProc *) pr;
7037 outCount = fwrite(message, 1, count, stdout);
7039 outCount = write(cp->fdTo, message, count);
7049 /* Output message to process, with "ms" milliseconds of delay
7050 between each character. This is needed when sending the logon
7051 script to ICC, which for some reason doesn't like the
7052 instantaneous send. */
7053 int OutputToProcessDelayed(pr, message, count, outError, msdelay)
7060 ChildProc *cp = (ChildProc *) pr;
7065 r = write(cp->fdTo, message++, 1);
7078 /**** Animation code by Hugh Fisher, DCS, ANU.
7080 Known problem: if a window overlapping the board is
7081 moved away while a piece is being animated underneath,
7082 the newly exposed area won't be updated properly.
7083 I can live with this.
7085 Known problem: if you look carefully at the animation
7086 of pieces in mono mode, they are being drawn as solid
7087 shapes without interior detail while moving. Fixing
7088 this would be a major complication for minimal return.
7091 /* Masks for XPM pieces. Black and white pieces can have
7092 different shapes, but in the interest of retaining my
7093 sanity pieces must have the same outline on both light
7094 and dark squares, and all pieces must use the same
7095 background square colors/images. */
7097 static int xpmDone = 0;
7100 CreateAnimMasks (pieceDepth)
7107 unsigned long plane;
7110 /* just return for gtk at the moment */
7113 /* Need a bitmap just to get a GC with right depth */
7114 buf = XCreatePixmap(xDisplay, xBoardWindow,
7116 values.foreground = 1;
7117 values.background = 0;
7118 /* Don't use XtGetGC, not read only */
7119 maskGC = XCreateGC(xDisplay, buf,
7120 GCForeground | GCBackground, &values);
7121 XFreePixmap(xDisplay, buf);
7123 buf = XCreatePixmap(xDisplay, xBoardWindow,
7124 squareSize, squareSize, pieceDepth);
7125 values.foreground = XBlackPixel(xDisplay, xScreen);
7126 values.background = XWhitePixel(xDisplay, xScreen);
7127 bufGC = XCreateGC(xDisplay, buf,
7128 GCForeground | GCBackground, &values);
7130 for (piece = WhitePawn; piece <= BlackKing; piece++) {
7131 /* Begin with empty mask */
7132 if(!xpmDone) // [HGM] pieces: keep using existing
7133 xpmMask[piece] = XCreatePixmap(xDisplay, xBoardWindow,
7134 squareSize, squareSize, 1);
7135 XSetFunction(xDisplay, maskGC, GXclear);
7136 XFillRectangle(xDisplay, xpmMask[piece], maskGC,
7137 0, 0, squareSize, squareSize);
7139 /* Take a copy of the piece */
7144 XSetFunction(xDisplay, bufGC, GXcopy);
7145 XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % (int)BlackPawn],
7147 0, 0, squareSize, squareSize, 0, 0);
7149 /* XOR the background (light) over the piece */
7150 XSetFunction(xDisplay, bufGC, GXxor);
7152 XCopyArea(xDisplay, xpmLightSquare, buf, bufGC,
7153 0, 0, squareSize, squareSize, 0, 0);
7155 XSetForeground(xDisplay, bufGC, lightSquareColor);
7156 XFillRectangle(xDisplay, buf, bufGC, 0, 0, squareSize, squareSize);
7159 /* We now have an inverted piece image with the background
7160 erased. Construct mask by just selecting all the non-zero
7161 pixels - no need to reconstruct the original image. */
7162 XSetFunction(xDisplay, maskGC, GXor);
7164 /* Might be quicker to download an XImage and create bitmap
7165 data from it rather than this N copies per piece, but it
7166 only takes a fraction of a second and there is a much
7167 longer delay for loading the pieces. */
7168 for (n = 0; n < pieceDepth; n ++) {
7169 XCopyPlane(xDisplay, buf, xpmMask[piece], maskGC,
7170 0, 0, squareSize, squareSize,
7176 XFreePixmap(xDisplay, buf);
7177 XFreeGC(xDisplay, bufGC);
7178 XFreeGC(xDisplay, maskGC);
7182 InitAnimState (anim, info)
7184 XWindowAttributes * info;
7189 /* Each buffer is square size, same depth as window */
7190 // anim->saveBuf = XCreatePixmap(xDisplay, xBoardWindow,
7191 // squareSize, squareSize, info->depth);
7192 // anim->newBuf = XCreatePixmap(xDisplay, xBoardWindow,
7193 // squareSize, squareSize, info->depth);
7195 // /* Create a plain GC for blitting */
7196 // mask = GCForeground | GCBackground | GCFunction |
7197 // GCPlaneMask | GCGraphicsExposures;
7198 // values.foreground = XBlackPixel(xDisplay, xScreen);
7199 // values.background = XWhitePixel(xDisplay, xScreen);
7200 // values.function = GXcopy;
7201 // values.plane_mask = AllPlanes;
7202 // values.graphics_exposures = False;
7203 // anim->blitGC = XCreateGC(xDisplay, xBoardWindow, mask, &values);
7205 // /* Piece will be copied from an existing context at
7206 // the start of each new animation/drag. */
7207 // anim->pieceGC = XCreateGC(xDisplay, xBoardWindow, 0, &values);
7209 // /* Outline will be a read-only copy of an existing */
7210 // anim->outlineGC = None;
7216 static VariantClass old = (VariantClass) -1; // [HGM] pieces: redo every time variant changes
7217 XWindowAttributes info;
7219 /* for gtk at the moment just ... */
7222 if (xpmDone && gameInfo.variant == old) return;
7223 if(xpmDone) old = gameInfo.variant; // first time pieces might not be created yet
7224 // XGetWindowAttributes(xDisplay, xBoardWindow, &info);
7226 // InitAnimState(&game, &info);
7227 // InitAnimState(&player, &info);
7229 /* For XPM pieces, we need bitmaps to use as masks. */
7231 // CreateAnimMasks(info.depth);
7237 static Boolean frameWaiting;
7239 static RETSIGTYPE FrameAlarm (sig)
7242 frameWaiting = False;
7243 /* In case System-V style signals. Needed?? */
7244 signal(SIGALRM, FrameAlarm);
7251 struct itimerval delay;
7253 XSync(xDisplay, False);
7256 frameWaiting = True;
7257 signal(SIGALRM, FrameAlarm);
7258 delay.it_interval.tv_sec =
7259 delay.it_value.tv_sec = time / 1000;
7260 delay.it_interval.tv_usec =
7261 delay.it_value.tv_usec = (time % 1000) * 1000;
7262 setitimer(ITIMER_REAL, &delay, NULL);
7263 while (frameWaiting) pause();
7264 delay.it_interval.tv_sec = delay.it_value.tv_sec = 0;
7265 delay.it_interval.tv_usec = delay.it_value.tv_usec = 0;
7266 setitimer(ITIMER_REAL, &delay, NULL);
7276 // XSync(xDisplay, False);
7278 usleep(time * 1000);
7283 /* Convert board position to corner of screen rect and color */
7286 ScreenSquare(column, row, pt, color)
7287 int column; int row; XPoint * pt; int * color;
7290 pt->x = lineGap + ((BOARD_WIDTH-1)-column) * (squareSize + lineGap);
7291 pt->y = lineGap + row * (squareSize + lineGap);
7293 pt->x = lineGap + column * (squareSize + lineGap);
7294 pt->y = lineGap + ((BOARD_HEIGHT-1)-row) * (squareSize + lineGap);
7296 *color = SquareColor(row, column);
7299 /* Convert window coords to square */
7302 BoardSquare(x, y, column, row)
7303 int x; int y; int * column; int * row;
7305 *column = EventToSquare(x, BOARD_WIDTH);
7306 if (flipView && *column >= 0)
7307 *column = BOARD_WIDTH - 1 - *column;
7308 *row = EventToSquare(y, BOARD_HEIGHT);
7309 if (!flipView && *row >= 0)
7310 *row = BOARD_HEIGHT - 1 - *row;
7315 #undef Max /* just in case */
7317 #define Max(a, b) ((a) > (b) ? (a) : (b))
7318 #define Min(a, b) ((a) < (b) ? (a) : (b))
7321 SetRect(rect, x, y, width, height)
7322 XRectangle * rect; int x; int y; int width; int height;
7326 rect->width = width;
7327 rect->height = height;
7330 /* Test if two frames overlap. If they do, return
7331 intersection rect within old and location of
7332 that rect within new. */
7335 Intersect(old, new, size, area, pt)
7336 XPoint * old; XPoint * new;
7337 int size; XRectangle * area; XPoint * pt;
7339 if (old->x > new->x + size || new->x > old->x + size ||
7340 old->y > new->y + size || new->y > old->y + size) {
7343 SetRect(area, Max(new->x - old->x, 0), Max(new->y - old->y, 0),
7344 size - abs(old->x - new->x), size - abs(old->y - new->y));
7345 pt->x = Max(old->x - new->x, 0);
7346 pt->y = Max(old->y - new->y, 0);
7351 /* For two overlapping frames, return the rect(s)
7352 in the old that do not intersect with the new. */
7355 CalcUpdateRects(old, new, size, update, nUpdates)
7356 XPoint * old; XPoint * new; int size;
7357 XRectangle update[]; int * nUpdates;
7361 /* If old = new (shouldn't happen) then nothing to draw */
7362 if (old->x == new->x && old->y == new->y) {
7366 /* Work out what bits overlap. Since we know the rects
7367 are the same size we don't need a full intersect calc. */
7369 /* Top or bottom edge? */
7370 if (new->y > old->y) {
7371 SetRect(&(update[count]), old->x, old->y, size, new->y - old->y);
7373 } else if (old->y > new->y) {
7374 SetRect(&(update[count]), old->x, old->y + size - (old->y - new->y),
7375 size, old->y - new->y);
7378 /* Left or right edge - don't overlap any update calculated above. */
7379 if (new->x > old->x) {
7380 SetRect(&(update[count]), old->x, Max(new->y, old->y),
7381 new->x - old->x, size - abs(new->y - old->y));
7383 } else if (old->x > new->x) {
7384 SetRect(&(update[count]), new->x + size, Max(new->y, old->y),
7385 old->x - new->x, size - abs(new->y - old->y));
7392 /* Generate a series of frame coords from start->mid->finish.
7393 The movement rate doubles until the half way point is
7394 reached, then halves back down to the final destination,
7395 which gives a nice slow in/out effect. The algorithmn
7396 may seem to generate too many intermediates for short
7397 moves, but remember that the purpose is to attract the
7398 viewers attention to the piece about to be moved and
7399 then to where it ends up. Too few frames would be less
7403 Tween(start, mid, finish, factor, frames, nFrames)
7404 XPoint * start; XPoint * mid;
7405 XPoint * finish; int factor;
7406 XPoint frames[]; int * nFrames;
7408 int fraction, n, count;
7412 /* Slow in, stepping 1/16th, then 1/8th, ... */
7414 for (n = 0; n < factor; n++)
7416 for (n = 0; n < factor; n++) {
7417 frames[count].x = start->x + (mid->x - start->x) / fraction;
7418 frames[count].y = start->y + (mid->y - start->y) / fraction;
7420 fraction = fraction / 2;
7424 frames[count] = *mid;
7427 /* Slow out, stepping 1/2, then 1/4, ... */
7429 for (n = 0; n < factor; n++) {
7430 frames[count].x = finish->x - (finish->x - mid->x) / fraction;
7431 frames[count].y = finish->y - (finish->y - mid->y) / fraction;
7433 fraction = fraction * 2;
7438 /* Draw a piece on the screen without disturbing what's there */
7441 SelectGCMask(piece, clip, outline, mask)
7442 ChessSquare piece; GC * clip; GC * outline; Pixmap * mask;
7446 /* Bitmap for piece being moved. */
7447 if (appData.monoMode) {
7448 *mask = *pieceToSolid(piece);
7449 } else if (useImages) {
7451 *mask = xpmMask[piece];
7453 *mask = ximMaskPm[piece];
7456 *mask = *pieceToSolid(piece);
7459 /* GC for piece being moved. Square color doesn't matter, but
7460 since it gets modified we make a copy of the original. */
7462 if (appData.monoMode)
7467 if (appData.monoMode)
7472 // XCopyGC(xDisplay, source, 0xFFFFFFFF, *clip);
7474 /* Outline only used in mono mode and is not modified */
7476 *outline = bwPieceGC;
7478 *outline = wbPieceGC;
7482 OverlayPiece(piece, clip, outline, dest)
7483 ChessSquare piece; GC clip; GC outline; Drawable dest;
7488 /* Draw solid rectangle which will be clipped to shape of piece */
7489 // XFillRectangle(xDisplay, dest, clip,
7490 // 0, 0, squareSize, squareSize)
7492 if (appData.monoMode)
7493 /* Also draw outline in contrasting color for black
7494 on black / white on white cases */
7495 // XCopyPlane(xDisplay, *pieceToOutline(piece), dest, outline,
7496 // 0, 0, squareSize, squareSize, 0, 0, 1)
7499 /* Copy the piece */
7504 // XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
7506 // 0, 0, squareSize, squareSize,
7511 /* Animate the movement of a single piece */
7514 BeginAnimation(anim, piece, startColor, start)
7522 /* The old buffer is initialised with the start square (empty) */
7523 BlankSquare(0, 0, startColor, EmptySquare, anim->saveBuf);
7524 anim->prevFrame = *start;
7526 /* The piece will be drawn using its own bitmap as a matte */
7527 // SelectGCMask(piece, &anim->pieceGC, &anim->outlineGC, &mask);
7528 // XSetClipMask(xDisplay, anim->pieceGC, mask);
7532 AnimationFrame(anim, frame, piece)
7537 XRectangle updates[4];
7542 /* Save what we are about to draw into the new buffer */
7543 // XCopyArea(xDisplay, xBoardWindow, anim->newBuf, anim->blitGC,
7544 // frame->x, frame->y, squareSize, squareSize,
7547 /* Erase bits of the previous frame */
7548 if (Intersect(&anim->prevFrame, frame, squareSize, &overlap, &pt)) {
7549 /* Where the new frame overlapped the previous,
7550 the contents in newBuf are wrong. */
7551 // XCopyArea(xDisplay, anim->saveBuf, anim->newBuf, anim->blitGC,
7552 // overlap.x, overlap.y,
7553 // overlap.width, overlap.height,
7555 /* Repaint the areas in the old that don't overlap new */
7556 CalcUpdateRects(&anim->prevFrame, frame, squareSize, updates, &count);
7557 for (i = 0; i < count; i++)
7558 // XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
7559 // updates[i].x - anim->prevFrame.x,
7560 // updates[i].y - anim->prevFrame.y,
7561 // updates[i].width, updates[i].height,
7562 // updates[i].x, updates[i].y)
7565 /* Easy when no overlap */
7566 // XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
7567 // 0, 0, squareSize, squareSize,
7568 // anim->prevFrame.x, anim->prevFrame.y);
7571 /* Save this frame for next time round */
7572 // XCopyArea(xDisplay, anim->newBuf, anim->saveBuf, anim->blitGC,
7573 // 0, 0, squareSize, squareSize,
7575 anim->prevFrame = *frame;
7577 /* Draw piece over original screen contents, not current,
7578 and copy entire rect. Wipes out overlapping piece images. */
7579 OverlayPiece(piece, anim->pieceGC, anim->outlineGC, anim->newBuf);
7580 // XCopyArea(xDisplay, anim->newBuf, xBoardWindow, anim->blitGC,
7581 // 0, 0, squareSize, squareSize,
7582 // frame->x, frame->y);
7586 EndAnimation (anim, finish)
7590 XRectangle updates[4];
7595 /* The main code will redraw the final square, so we
7596 only need to erase the bits that don't overlap. */
7597 if (Intersect(&anim->prevFrame, finish, squareSize, &overlap, &pt)) {
7598 CalcUpdateRects(&anim->prevFrame, finish, squareSize, updates, &count);
7599 for (i = 0; i < count; i++)
7600 // XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
7601 // updates[i].x - anim->prevFrame.x,
7602 // updates[i].y - anim->prevFrame.y,
7603 // updates[i].width, updates[i].height,
7604 // updates[i].x, updates[i].y)
7607 // XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
7608 // 0, 0, squareSize, squareSize,
7609 // anim->prevFrame.x, anim->prevFrame.y);
7614 FrameSequence(anim, piece, startColor, start, finish, frames, nFrames)
7616 ChessSquare piece; int startColor;
7617 XPoint * start; XPoint * finish;
7618 XPoint frames[]; int nFrames;
7622 BeginAnimation(anim, piece, startColor, start);
7623 for (n = 0; n < nFrames; n++) {
7624 AnimationFrame(anim, &(frames[n]), piece);
7625 FrameDelay(appData.animSpeed);
7627 EndAnimation(anim, finish);
7630 /* Main control logic for deciding what to animate and how */
7633 AnimateMove(board, fromX, fromY, toX, toY)
7642 XPoint start, finish, mid;
7643 XPoint frames[kFactor * 2 + 1];
7644 int nFrames, startColor, endColor;
7646 /* Are we animating? */
7647 if (!appData.animate || appData.blindfold)
7650 if(board[toY][toX] == WhiteRook && board[fromY][fromX] == WhiteKing ||
7651 board[toY][toX] == BlackRook && board[fromY][fromX] == BlackKing)
7652 return; // [HGM] FRC: no animtion of FRC castlings, as to-square is not true to-square
7654 if (fromY < 0 || fromX < 0 || toX < 0 || toY < 0) return;
7655 piece = board[fromY][fromX];
7656 if (piece >= EmptySquare) return;
7661 hop = (piece == WhiteKnight || piece == BlackKnight);
7664 if (appData.debugMode) {
7665 fprintf(debugFP, hop ? _("AnimateMove: piece %d hops from %d,%d to %d,%d \n") :
7666 _("AnimateMove: piece %d slides from %d,%d to %d,%d \n"),
7667 piece, fromX, fromY, toX, toY); }
7669 ScreenSquare(fromX, fromY, &start, &startColor);
7670 ScreenSquare(toX, toY, &finish, &endColor);
7673 /* Knight: make diagonal movement then straight */
7674 if (abs(toY - fromY) < abs(toX - fromX)) {
7675 mid.x = start.x + (finish.x - start.x) / 2;
7679 mid.y = start.y + (finish.y - start.y) / 2;
7682 mid.x = start.x + (finish.x - start.x) / 2;
7683 mid.y = start.y + (finish.y - start.y) / 2;
7686 /* Don't use as many frames for very short moves */
7687 if (abs(toY - fromY) + abs(toX - fromX) <= 2)
7688 Tween(&start, &mid, &finish, kFactor - 1, frames, &nFrames);
7690 Tween(&start, &mid, &finish, kFactor, frames, &nFrames);
7691 FrameSequence(&game, piece, startColor, &start, &finish, frames, nFrames);
7693 /* Be sure end square is redrawn */
7694 damage[toY][toX] = True;
7698 DragPieceBegin(x, y)
7701 int boardX, boardY, color;
7704 /* Are we animating? */
7705 if (!appData.animateDragging || appData.blindfold)
7708 /* Figure out which square we start in and the
7709 mouse position relative to top left corner. */
7710 BoardSquare(x, y, &boardX, &boardY);
7711 player.startBoardX = boardX;
7712 player.startBoardY = boardY;
7713 ScreenSquare(boardX, boardY, &corner, &color);
7714 player.startSquare = corner;
7715 player.startColor = color;
7716 /* As soon as we start dragging, the piece will jump slightly to
7717 be centered over the mouse pointer. */
7718 player.mouseDelta.x = squareSize/2;
7719 player.mouseDelta.y = squareSize/2;
7720 /* Initialise animation */
7721 player.dragPiece = PieceForSquare(boardX, boardY);
7723 if (player.dragPiece >= 0 && player.dragPiece < EmptySquare) {
7724 player.dragActive = True;
7725 BeginAnimation(&player, player.dragPiece, color, &corner);
7726 /* Mark this square as needing to be redrawn. Note that
7727 we don't remove the piece though, since logically (ie
7728 as seen by opponent) the move hasn't been made yet. */
7729 if(boardX == BOARD_RGHT+1 && PieceForSquare(boardX-1, boardY) > 1 ||
7730 boardX == BOARD_LEFT-2 && PieceForSquare(boardX+1, boardY) > 1)
7731 // XCopyArea(xDisplay, xBoardWindow, player.saveBuf, player.blitGC,
7732 // corner.x, corner.y, squareSize, squareSize,
7733 // 0, 0); // [HGM] zh: unstack in stead of grab
7734 damage[boardY][boardX] = True;
7736 player.dragActive = False;
7746 /* Are we animating? */
7747 if (!appData.animateDragging || appData.blindfold)
7751 if (! player.dragActive)
7753 /* Move piece, maintaining same relative position
7754 of mouse within square */
7755 corner.x = x - player.mouseDelta.x;
7756 corner.y = y - player.mouseDelta.y;
7757 AnimationFrame(&player, &corner, player.dragPiece);
7759 if (appData.highlightDragging) {
7761 BoardSquare(x, y, &boardX, &boardY);
7762 SetHighlights(fromX, fromY, boardX, boardY);
7771 int boardX, boardY, color;
7774 /* Are we animating? */
7775 if (!appData.animateDragging || appData.blindfold)
7779 if (! player.dragActive)
7781 /* Last frame in sequence is square piece is
7782 placed on, which may not match mouse exactly. */
7783 BoardSquare(x, y, &boardX, &boardY);
7784 ScreenSquare(boardX, boardY, &corner, &color);
7785 EndAnimation(&player, &corner);
7787 /* Be sure end square is redrawn */
7788 damage[boardY][boardX] = True;
7790 /* This prevents weird things happening with fast successive
7791 clicks which on my Sun at least can cause motion events
7792 without corresponding press/release. */
7793 player.dragActive = False;
7796 /* Handle expose event while piece being dragged */
7801 if (!player.dragActive || appData.blindfold)
7804 /* What we're doing: logically, the move hasn't been made yet,
7805 so the piece is still in it's original square. But visually
7806 it's being dragged around the board. So we erase the square
7807 that the piece is on and draw it at the last known drag point. */
7808 BlankSquare(player.startSquare.x, player.startSquare.y,
7809 player.startColor, EmptySquare, xBoardWindow);
7810 AnimationFrame(&player, &player.prevFrame, player.dragPiece);
7811 damage[player.startBoardY][player.startBoardX] = TRUE;
7815 SetProgramStats( FrontEndProgramStats * stats )
7818 // [HGM] done, but perhaps backend should call this directly?
7819 EngineOutputUpdate( stats );
7822 #include <sys/ioctl.h>
7823 int get_term_width()
7825 int fd, default_width;
7828 default_width = 79; // this is FICS default anyway...
7830 #if !defined(TIOCGWINSZ) && defined(TIOCGSIZE)
7832 if (!ioctl(fd, TIOCGSIZE, &win))
7833 default_width = win.ts_cols;
7834 #elif defined(TIOCGWINSZ)
7836 if (!ioctl(fd, TIOCGWINSZ, &win))
7837 default_width = win.ws_col;
7839 return default_width;
7842 void update_ics_width()
7844 static int old_width = 0;
7845 int new_width = get_term_width();
7847 if (old_width != new_width)
7848 ics_printf("set width %d\n", new_width);
7849 old_width = new_width;
7852 void NotifyFrontendLogin()