2 * xboard.c -- X front end for XBoard
4 * Copyright 1991 by Digital Equipment Corporation, Maynard,
7 * Enhancements Copyright 1992-2001, 2002, 2003, 2004, 2005, 2006,
8 * 2007, 2008, 2009 Free Software Foundation, Inc.
10 * The following terms apply to Digital Equipment Corporation's copyright
12 * ------------------------------------------------------------------------
15 * Permission to use, copy, modify, and distribute this software and its
16 * documentation for any purpose and without fee is hereby granted,
17 * provided that the above copyright notice appear in all copies and that
18 * both that copyright notice and this permission notice appear in
19 * supporting documentation, and that the name of Digital not be
20 * used in advertising or publicity pertaining to distribution of the
21 * software without specific, written prior permission.
23 * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
24 * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
25 * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
26 * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
27 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
28 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
30 * ------------------------------------------------------------------------
32 * The following terms apply to the enhanced version of XBoard
33 * distributed by the Free Software Foundation:
34 * ------------------------------------------------------------------------
36 * GNU XBoard is free software: you can redistribute it and/or modify
37 * it under the terms of the GNU General Public License as published by
38 * the Free Software Foundation, either version 3 of the License, or (at
39 * your option) any later version.
41 * GNU XBoard is distributed in the hope that it will be useful, but
42 * WITHOUT ANY WARRANTY; without even the implied warranty of
43 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
44 * General Public License for more details.
46 * You should have received a copy of the GNU General Public License
47 * along with this program. If not, see http://www.gnu.org/licenses/. *
49 *------------------------------------------------------------------------
50 ** See the file ChangeLog for a revision history. */
58 #include <sys/types.h>
63 # if HAVE_SYS_SOCKET_H
64 # include <sys/socket.h>
65 # include <netinet/in.h>
67 # else /* not HAVE_SYS_SOCKET_H */
68 # if HAVE_LAN_SOCKET_H
69 # include <lan/socket.h>
71 # include <lan/netdb.h>
72 # else /* not HAVE_LAN_SOCKET_H */
73 # define OMIT_SOCKETS 1
74 # endif /* not HAVE_LAN_SOCKET_H */
75 # endif /* not HAVE_SYS_SOCKET_H */
76 #endif /* !OMIT_SOCKETS */
81 #else /* not STDC_HEADERS */
82 extern char *getenv();
85 # else /* not HAVE_STRING_H */
87 # endif /* not HAVE_STRING_H */
88 #endif /* not STDC_HEADERS */
91 # include <sys/fcntl.h>
92 #else /* not HAVE_SYS_FCNTL_H */
95 # endif /* HAVE_FCNTL_H */
96 #endif /* not HAVE_SYS_FCNTL_H */
98 #if HAVE_SYS_SYSTEMINFO_H
99 # include <sys/systeminfo.h>
100 #endif /* HAVE_SYS_SYSTEMINFO_H */
102 #if TIME_WITH_SYS_TIME
103 # include <sys/time.h>
107 # include <sys/time.h>
118 # include <sys/wait.h>
123 # define NAMLEN(dirent) strlen((dirent)->d_name)
124 # define HAVE_DIR_STRUCT
126 # define dirent direct
127 # define NAMLEN(dirent) (dirent)->d_namlen
129 # include <sys/ndir.h>
130 # define HAVE_DIR_STRUCT
133 # include <sys/dir.h>
134 # define HAVE_DIR_STRUCT
138 # define HAVE_DIR_STRUCT
142 #include <X11/Intrinsic.h>
143 #include <X11/StringDefs.h>
144 #include <X11/Shell.h>
145 #include <X11/cursorfont.h>
146 #include <X11/Xatom.h>
148 #include <X11/Xaw3d/Dialog.h>
149 #include <X11/Xaw3d/Form.h>
150 #include <X11/Xaw3d/List.h>
151 #include <X11/Xaw3d/Label.h>
152 #include <X11/Xaw3d/SimpleMenu.h>
153 #include <X11/Xaw3d/SmeBSB.h>
154 #include <X11/Xaw3d/SmeLine.h>
155 #include <X11/Xaw3d/Box.h>
156 #include <X11/Xaw3d/MenuButton.h>
157 #include <X11/Xaw3d/Text.h>
158 #include <X11/Xaw3d/AsciiText.h>
160 #include <X11/Xaw/Dialog.h>
161 #include <X11/Xaw/Form.h>
162 #include <X11/Xaw/List.h>
163 #include <X11/Xaw/Label.h>
164 #include <X11/Xaw/SimpleMenu.h>
165 #include <X11/Xaw/SmeBSB.h>
166 #include <X11/Xaw/SmeLine.h>
167 #include <X11/Xaw/Box.h>
168 #include <X11/Xaw/MenuButton.h>
169 #include <X11/Xaw/Text.h>
170 #include <X11/Xaw/AsciiText.h>
173 // [HGM] bitmaps: put before incuding the bitmaps / pixmaps, to know how many piece types there are.
178 #include "pixmaps/pixmaps.h"
179 #define IMAGE_EXT "xpm"
181 #define IMAGE_EXT "xim"
182 #include "bitmaps/bitmaps.h"
187 #include <gdk-pixbuf/gdk-pixbuf.h>
189 #include "bitmaps/icon_white.bm"
190 #include "bitmaps/icon_black.bm"
191 #include "bitmaps/checkmark.bm"
193 #include "frontend.h"
198 #include "xgamelist.h"
199 #include "xhistory.h"
200 #include "xedittags.h"
202 #include "callback.h"
203 #include "interface.h"
205 // must be moved to xengineoutput.h
207 void EngineOutputProc P((Widget w, XEvent *event,
208 String *prms, Cardinal *nprms));
210 void EngineOutputPopDown();
217 #define usleep(t) _sleep2(((t)+500)/1000)
221 # define _(s) gettext (s)
222 # define N_(s) gettext_noop (s)
245 int main P((int argc, char **argv));
246 RETSIGTYPE CmailSigHandler P((int sig));
247 RETSIGTYPE IntSigHandler P((int sig));
248 RETSIGTYPE TermSizeSigHandler P((int sig));
249 void CreateGCs P((void));
250 void CreateXIMPieces P((void));
251 void CreateXPMPieces P((void));
252 void CreatePieces P((void));
253 void CreatePieceMenus P((void));
254 Widget CreateMenuBar P((Menu *mb));
255 char *FindFont P((char *pattern, int targetPxlSize));
256 void PieceMenuPopup P((Widget w, XEvent *event,
257 String *params, Cardinal *num_params));
258 static void PieceMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
259 static void DropMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
260 int EventToSquare P((int x, int limit));
261 void DrawSquare P((int row, int column, ChessSquare piece, int do_flash));
262 void HandleUserMove P((Widget w, XEvent *event,
263 String *prms, Cardinal *nprms));
264 void AnimateUserMove P((Widget w, XEvent * event,
265 String * params, Cardinal * nParams));
266 void CommentPopUp P((char *title, char *label));
267 void CommentPopDown P((void));
268 void CommentCallback P((Widget w, XtPointer client_data,
269 XtPointer call_data));
270 void ICSInputBoxPopUp P((void));
271 void ICSInputBoxPopDown P((void));
272 void AskQuestionReplyAction P((Widget w, XEvent *event,
273 String *prms, Cardinal *nprms));
274 void AskQuestionProc P((Widget w, XEvent *event,
275 String *prms, Cardinal *nprms));
276 void AskQuestionPopDown P((void));
277 void PromotionPopDown P((void));
278 void PromotionCallback P((Widget w, XtPointer client_data,
279 XtPointer call_data));
280 void EditCommentPopDown P((void));
281 void EditCommentCallback P((Widget w, XtPointer client_data,
282 XtPointer call_data));
283 void SelectCommand P((Widget w, XtPointer client_data, XtPointer call_data));
284 void CopyPositionProc P((Widget w, XEvent *event, String *prms,
286 void PastePositionProc P((Widget w, XEvent *event, String *prms,
288 void CopyGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
289 void PasteGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
290 void MailMoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
291 void ReloadCmailMsgProc P((Widget w, XEvent *event, String *prms,
293 void AnalyzeModeProc P((Widget w, XEvent *event,
294 String *prms, Cardinal *nprms));
295 void EditGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
296 void EditPositionProc P((Widget w, XEvent *event,
297 String *prms, Cardinal *nprms));
298 void TrainingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
299 void EditCommentProc P((Widget w, XEvent *event,
300 String *prms, Cardinal *nprms));
301 void IcsInputBoxProc P((Widget w, XEvent *event,
302 String *prms, Cardinal *nprms));
303 void EnterKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
304 void PonderNextMoveProc P((Widget w, XEvent *event, String *prms,
306 void PopupMoveErrorsProc P((Widget w, XEvent *event, String *prms,
308 void PopupExitMessageProc P((Widget w, XEvent *event, String *prms,
310 void PremoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
311 void QuietPlayProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
312 void AboutGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
313 void DebugProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
314 void NothingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
315 void Iconify P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
316 void DisplayMove P((int moveNumber));
317 void DisplayTitle P((char *title));
318 void ICSInitScript P((void));
319 int LoadGamePopUp P((FILE *f, int gameNumber, char *title));
320 void ErrorPopUp P((char *title, char *text, int modal));
321 void ErrorPopDown P((void));
322 static char *ExpandPathName P((char *path));
323 static void CreateAnimVars P((void));
324 static void DragPieceMove P((int x, int y));
325 static void DrawDragPiece P((void));
326 char *ModeToWidgetName P((GameMode mode));
327 void EngineOutputUpdate( FrontEndProgramStats * stats );
328 void ShuffleMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
329 void EngineMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
330 void UciMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
331 void TimeControlProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
332 void NewVariantProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
333 void FirstSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
334 void SecondSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
335 void ShufflePopDown P(());
336 void EnginePopDown P(());
337 void UciPopDown P(());
338 void TimeControlPopDown P(());
339 void NewVariantPopDown P(());
340 void SettingsPopDown P(());
341 void SetMenuEnables P((Enables *enab));
342 void update_ics_width P(());
343 int get_term_width P(());
345 * XBoard depends on Xt R4 or higher
347 int xtVersion = XtSpecificationRelease;
352 Pixel lightSquareColor, darkSquareColor, whitePieceColor, blackPieceColor,
353 jailSquareColor, highlightSquareColor, premoveHighlightColor;
354 Pixel lowTimeWarningColor;
356 #define LINE_TYPE_NORMAL 0
357 #define LINE_TYPE_HIGHLIGHT 1
358 #define LINE_TYPE_PRE 2
361 GC lightSquareGC, darkSquareGC, jailSquareGC, wdPieceGC, wlPieceGC,
362 bdPieceGC, blPieceGC, wbPieceGC, bwPieceGC, coordGC,
363 wjPieceGC, bjPieceGC;
364 Pixmap iconPixmap, wIconPixmap, bIconPixmap, xMarkPixmap;
365 Widget shellWidget, layoutWidget, formWidget, boardWidget, messageWidget,
366 whiteTimerWidget, blackTimerWidget, titleWidget, widgetList[16],
367 commentShell, promotionShell, whitePieceMenu, blackPieceMenu, dropMenu,
368 menuBarWidget, editShell, errorShell, analysisShell,
369 ICSInputShell, fileNameShell, askQuestionShell;
370 Font clockFontID, coordFontID, countFontID;
371 XFontStruct *clockFontStruct, *coordFontStruct, *countFontStruct;
372 XtAppContext appContext;
374 char *oldICSInteractionTitle;
378 char installDir[] = "."; // [HGM] UCI: needed for UCI; probably needs run-time initializtion
380 Position commentX = -1, commentY = -1;
381 Dimension commentW, commentH;
383 int squareSize, smallLayout = 0, tinyLayout = 0,
384 marginW, marginH, // [HGM] for run-time resizing
385 fromX = -1, fromY = -1, toX, toY, commentUp = False, analysisUp = False,
386 ICSInputBoxUp = False, askQuestionUp = False,
387 filenameUp = False, promotionUp = False, pmFromX = -1, pmFromY = -1,
388 editUp = False, errorUp = False, errorExitStatus = -1, lineGap;
389 Pixel timerForegroundPixel, timerBackgroundPixel;
390 Pixel buttonForegroundPixel, buttonBackgroundPixel;
391 char *chessDir, *programName, *programVersion,
392 *gameCopyFilename, *gamePasteFilename;
396 Pixmap pieceBitmap[2][(int)BlackPawn];
397 Pixmap pieceBitmap2[2][(int)BlackPawn+4]; /* [HGM] pieces */
398 Pixmap xpmPieceBitmap[4][(int)BlackPawn]; /* LL, LD, DL, DD actually used*/
399 Pixmap xpmPieceBitmap2[4][(int)BlackPawn+4]; /* LL, LD, DL, DD set to select from */
400 Pixmap xpmLightSquare, xpmDarkSquare, xpmJailSquare;
401 int useImages=0, useImageSqs;
402 XImage *ximPieceBitmap[4][(int)BlackPawn+4]; /* LL, LD, DL, DD */
403 Pixmap ximMaskPm[(int)BlackPawn]; /* clipmasks, used for XIM pieces */
404 Pixmap ximMaskPm2[(int)BlackPawn+4]; /* clipmasks, used for XIM pieces */
405 XImage *ximLightSquare, *ximDarkSquare;
408 #define pieceToSolid(piece) &pieceBitmap[SOLID][(piece) % (int)BlackPawn]
409 #define pieceToOutline(piece) &pieceBitmap[OUTLINE][(piece) % (int)BlackPawn]
411 #define White(piece) ((int)(piece) < (int)BlackPawn)
413 /* Variables for doing smooth animation. This whole thing
414 would be much easier if the board was double-buffered,
415 but that would require a fairly major rewrite. */
420 GC blitGC, pieceGC, outlineGC;
421 XPoint startSquare, prevFrame, mouseDelta;
425 int startBoardX, startBoardY;
428 /* There can be two pieces being animated at once: a player
429 can begin dragging a piece before the remote opponent has moved. */
431 static AnimState game, player;
433 /* Bitmaps for use as masks when drawing XPM pieces.
434 Need one for each black and white piece. */
435 static Pixmap xpmMask[BlackKing + 1];
437 /* This magic number is the number of intermediate frames used
438 in each half of the animation. For short moves it's reduced
439 by 1. The total number of frames will be factor * 2 + 1. */
442 SizeDefaults sizeDefaults[] = SIZE_DEFAULTS;
444 Enables icsEnables[] = {
445 { "menuFile.Mail Move", False },
446 { "menuFile.Reload CMail Message", False },
447 { "menuMode.Machine Black", False },
448 { "menuMode.Machine White", False },
449 { "menuMode.Analysis Mode", False },
450 { "menuMode.Analyze File", False },
451 { "menuMode.Two Machines", False },
453 { "menuHelp.Hint", False },
454 { "menuHelp.Book", False },
455 { "menuStep.Move Now", False },
456 { "menuOptions.Periodic Updates", False },
457 { "menuOptions.Hide Thinking", False },
458 { "menuOptions.Ponder Next Move", False },
463 Enables ncpEnables[] = {
464 { "menuFile.Mail Move", False },
465 { "menuFile.Reload CMail Message", False },
466 { "menuMode.Machine White", False },
467 { "menuMode.Machine Black", False },
468 { "menuMode.Analysis Mode", False },
469 { "menuMode.Analyze File", False },
470 { "menuMode.Two Machines", False },
471 { "menuMode.ICS Client", False },
472 { "menuMode.ICS Input Box", False },
474 { "menuStep.Revert", False },
475 { "menuStep.Move Now", False },
476 { "menuStep.Retract Move", False },
477 { "menuOptions.Auto Comment", False },
478 { "menuOptions.Auto Flag", False },
479 { "menuOptions.Auto Flip View", False },
480 { "menuOptions.Auto Observe", False },
481 { "menuOptions.Auto Raise Board", False },
482 { "menuOptions.Get Move List", False },
483 { "menuOptions.ICS Alarm", False },
484 { "menuOptions.Move Sound", False },
485 { "menuOptions.Quiet Play", False },
486 { "menuOptions.Hide Thinking", False },
487 { "menuOptions.Periodic Updates", False },
488 { "menuOptions.Ponder Next Move", False },
489 { "menuHelp.Hint", False },
490 { "menuHelp.Book", False },
494 Enables gnuEnables[] = {
495 { "menuMode.ICS Client", False },
496 { "menuMode.ICS Input Box", False },
497 { "menuAction.Accept", False },
498 { "menuAction.Decline", False },
499 { "menuAction.Rematch", False },
500 { "menuAction.Adjourn", False },
501 { "menuAction.Stop Examining", False },
502 { "menuAction.Stop Observing", False },
503 { "menuStep.Revert", False },
504 { "menuOptions.Auto Comment", False },
505 { "menuOptions.Auto Observe", False },
506 { "menuOptions.Auto Raise Board", False },
507 { "menuOptions.Get Move List", False },
508 { "menuOptions.Premove", False },
509 { "menuOptions.Quiet Play", False },
511 /* The next two options rely on SetCmailMode being called *after* */
512 /* SetGNUMode so that when GNU is being used to give hints these */
513 /* menu options are still available */
515 { "menuFile.Mail Move", False },
516 { "menuFile.Reload CMail Message", False },
520 Enables cmailEnables[] = {
522 { "menuAction.Call Flag", False },
523 { "menuAction.Draw", True },
524 { "menuAction.Adjourn", False },
525 { "menuAction.Abort", False },
526 { "menuAction.Stop Observing", False },
527 { "menuAction.Stop Examining", False },
528 { "menuFile.Mail Move", True },
529 { "menuFile.Reload CMail Message", True },
533 Enables trainingOnEnables[] = {
534 { "menuMode.Edit Comment", False },
535 { "menuMode.Pause", False },
536 { "menuStep.Forward", False },
537 { "menuStep.Backward", False },
538 { "menuStep.Forward to End", False },
539 { "menuStep.Back to Start", False },
540 { "menuStep.Move Now", False },
541 { "menuStep.Truncate Game", False },
545 Enables trainingOffEnables[] = {
546 { "menuMode.Edit Comment", True },
547 { "menuMode.Pause", True },
548 { "menuStep.Forward", True },
549 { "menuStep.Backward", True },
550 { "menuStep.Forward to End", True },
551 { "menuStep.Back to Start", True },
552 { "menuStep.Move Now", True },
553 { "menuStep.Truncate Game", True },
557 Enables machineThinkingEnables[] = {
558 { "menuFile.Load Game", False },
559 { "menuFile.Load Next Game", False },
560 { "menuFile.Load Previous Game", False },
561 { "menuFile.Reload Same Game", False },
562 { "menuFile.Paste Game", False },
563 { "menuFile.Load Position", False },
564 { "menuFile.Load Next Position", False },
565 { "menuFile.Load Previous Position", False },
566 { "menuFile.Reload Same Position", False },
567 { "menuFile.Paste Position", False },
568 { "menuMode.Machine White", False },
569 { "menuMode.Machine Black", False },
570 { "menuMode.Two Machines", False },
571 { "menuStep.Retract Move", False },
575 Enables userThinkingEnables[] = {
576 { "menuFile.Load Game", True },
577 { "menuFile.Load Next Game", True },
578 { "menuFile.Load Previous Game", True },
579 { "menuFile.Reload Same Game", True },
580 { "menuFile.Paste Game", True },
581 { "menuFile.Load Position", True },
582 { "menuFile.Load Next Position", True },
583 { "menuFile.Load Previous Position", True },
584 { "menuFile.Reload Same Position", True },
585 { "menuFile.Paste Position", True },
586 { "menuMode.Machine White", True },
587 { "menuMode.Machine Black", True },
588 { "menuMode.Two Machines", True },
589 { "menuStep.Retract Move", True },
595 MenuItem fileMenu[] = {
596 {N_("New Shuffle Game ..."), ShuffleMenuProc},
597 {N_("New Variant ..."), NewVariantProc}, // [HGM] variant: not functional yet
598 // {"----", NothingProc},
599 // {N_("Save Game"), SaveGameProc},
600 // {"----", NothingProc},
601 {N_("Copy Game"), CopyGameProc},
602 {N_("Paste Game"), PasteGameProc},
603 // {"----", NothingProc},
604 // {N_("Load Position"), LoadPositionProc},
605 // {N_("Load Next Position"), LoadNextPositionProc},
606 // {N_("Load Previous Position"), LoadPrevPositionProc},
607 // {N_("Reload Same Position"), ReloadPositionProc},
608 // {N_("Save Position"), SavePositionProc},
609 // {"----", NothingProc},
610 {N_("Copy Position"), CopyPositionProc},
611 {N_("Paste Position"), PastePositionProc},
612 // {"----", NothingProc},
613 {N_("Mail Move"), MailMoveProc},
614 {N_("Reload CMail Message"), ReloadCmailMsgProc},
615 // {"----", NothingProc},
619 MenuItem modeMenu[] = {
620 // {N_("Machine White"), MachineWhiteProc},
621 // {N_("Machine Black"), MachineBlackProc},
622 // {N_("Two Machines"), TwoMachinesProc},
623 {N_("Analysis Mode"), AnalyzeModeProc},
624 // {N_("Analyze File"), AnalyzeFileProc },
625 // {N_("ICS Client"), IcsClientProc},
626 {N_("Edit Game"), EditGameProc},
627 {N_("Edit Position"), EditPositionProc},
628 {N_("Training"), TrainingProc},
629 {"----", NothingProc},
630 {N_("Show Engine Output"), EngineOutputProc},
631 {N_("Show Evaluation Graph"), NothingProc}, // [HGM] evalgr: not functional yet
632 {N_("Show Game List"), ShowGameListProc},
633 // {"Show Move History", HistoryShowProc}, // [HGM] hist: activate 4.2.7 code
634 {"----", NothingProc},
635 // {N_("Edit Tags"), EditTagsProc},
636 {N_("Edit Comment"), EditCommentProc},
637 {N_("ICS Input Box"), IcsInputBoxProc},
641 MenuItem optionsMenu[] = {
642 // {N_("Flip View"), FlipViewProc},
643 // {"----", NothingProc},
644 {N_("Adjudications ..."), EngineMenuProc},
645 {N_("General Settings ..."), UciMenuProc},
646 {N_("Engine #1 Settings ..."), FirstSettingsProc},
647 {N_("Engine #2 Settings ..."), SecondSettingsProc},
648 {N_("Time Control ..."), TimeControlProc},
649 {"----", NothingProc},
650 // {N_("Always Queen"), AlwaysQueenProc},
651 // {N_("Animate Dragging"), AnimateDraggingProc},
652 // {N_("Animate Moving"), AnimateMovingProc},
653 // {N_("Auto Comment"), AutocommProc},
654 // {N_("Auto Flag"), AutoflagProc},
655 // {N_("Auto Flip View"), AutoflipProc},
656 // {N_("Auto Observe"), AutobsProc},
657 // {N_("Auto Raise Board"), AutoraiseProc},
658 // {N_("Auto Save"), AutosaveProc},
659 // {N_("Blindfold"), BlindfoldProc},
660 // {N_("Flash Moves"), FlashMovesProc},
661 // {N_("Get Move List"), GetMoveListProc},
663 // {N_("Highlight Dragging"), HighlightDraggingProc},
665 // {N_("Highlight Last Move"), HighlightLastMoveProc},
666 // {N_("Move Sound"), MoveSoundProc},
667 // {N_("ICS Alarm"), IcsAlarmProc},
668 // {N_("Old Save Style"), OldSaveStyleProc},
669 // {N_("Periodic Updates"), PeriodicUpdatesProc},
670 {N_("Ponder Next Move"), PonderNextMoveProc},
671 {N_("Popup Exit Message"), PopupExitMessageProc},
672 {N_("Popup Move Errors"), PopupMoveErrorsProc},
673 {N_("Premove"), PremoveProc},
674 {N_("Quiet Play"), QuietPlayProc},
675 // {N_("Hide Thinking"), HideThinkingProc},
676 // {N_("Test Legality"), TestLegalityProc},
681 {N_("File"), fileMenu},
682 {N_("Mode"), modeMenu},
683 {N_("Options"), optionsMenu},
687 #define PIECE_MENU_SIZE 18
688 String pieceMenuStrings[2][PIECE_MENU_SIZE] = {
689 { N_("White"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
690 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
691 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
692 N_("Empty square"), N_("Clear board") },
693 { N_("Black"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
694 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
695 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
696 N_("Empty square"), N_("Clear board") }
698 /* must be in same order as PieceMenuStrings! */
699 ChessSquare pieceMenuTranslation[2][PIECE_MENU_SIZE] = {
700 { WhitePlay, (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
701 WhiteRook, WhiteQueen, WhiteKing, (ChessSquare) 0, WhiteAlfil,
702 WhiteCannon, WhiteAngel, WhiteMarshall, (ChessSquare) 0,
703 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
704 { BlackPlay, (ChessSquare) 0, BlackPawn, BlackKnight, BlackBishop,
705 BlackRook, BlackQueen, BlackKing, (ChessSquare) 0, BlackAlfil,
706 BlackCannon, BlackAngel, BlackMarshall, (ChessSquare) 0,
707 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
710 #define DROP_MENU_SIZE 6
711 String dropMenuStrings[DROP_MENU_SIZE] = {
712 "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"), N_("Queen")
714 /* must be in same order as PieceMenuStrings! */
715 ChessSquare dropMenuTranslation[DROP_MENU_SIZE] = {
716 (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
717 WhiteRook, WhiteQueen
725 DropMenuEnables dmEnables[] = {
734 { XtNborderWidth, 0 },
735 { XtNdefaultDistance, 0 },
739 { XtNborderWidth, 0 },
740 { XtNresizable, (XtArgVal) True },
744 { XtNborderWidth, 0 },
749 XtResource clientResources[] = {
750 { "whitePieceColor", "whitePieceColor", XtRString, sizeof(String),
751 XtOffset(AppDataPtr, whitePieceColor), XtRString,
753 { "blackPieceColor", "blackPieceColor", XtRString, sizeof(String),
754 XtOffset(AppDataPtr, blackPieceColor), XtRString,
756 { "lightSquareColor", "lightSquareColor", XtRString,
757 sizeof(String), XtOffset(AppDataPtr, lightSquareColor),
758 XtRString, LIGHT_SQUARE_COLOR },
759 { "darkSquareColor", "darkSquareColor", XtRString, sizeof(String),
760 XtOffset(AppDataPtr, darkSquareColor), XtRString,
762 { "highlightSquareColor", "highlightSquareColor", XtRString,
763 sizeof(String), XtOffset(AppDataPtr, highlightSquareColor),
764 XtRString, HIGHLIGHT_SQUARE_COLOR },
765 { "premoveHighlightColor", "premoveHighlightColor", XtRString,
766 sizeof(String), XtOffset(AppDataPtr, premoveHighlightColor),
767 XtRString, PREMOVE_HIGHLIGHT_COLOR },
768 { "movesPerSession", "movesPerSession", XtRInt, sizeof(int),
769 XtOffset(AppDataPtr, movesPerSession), XtRImmediate,
770 (XtPointer) MOVES_PER_SESSION },
771 { "timeIncrement", "timeIncrement", XtRInt, sizeof(int),
772 XtOffset(AppDataPtr, timeIncrement), XtRImmediate,
773 (XtPointer) TIME_INCREMENT },
774 { "initString", "initString", XtRString, sizeof(String),
775 XtOffset(AppDataPtr, initString), XtRString, INIT_STRING },
776 { "secondInitString", "secondInitString", XtRString, sizeof(String),
777 XtOffset(AppDataPtr, secondInitString), XtRString, INIT_STRING },
778 { "firstComputerString", "firstComputerString", XtRString,
779 sizeof(String), XtOffset(AppDataPtr, firstComputerString), XtRString,
781 { "secondComputerString", "secondComputerString", XtRString,
782 sizeof(String), XtOffset(AppDataPtr, secondComputerString), XtRString,
784 { "firstChessProgram", "firstChessProgram", XtRString,
785 sizeof(String), XtOffset(AppDataPtr, firstChessProgram),
786 XtRString, FIRST_CHESS_PROGRAM },
787 { "secondChessProgram", "secondChessProgram", XtRString,
788 sizeof(String), XtOffset(AppDataPtr, secondChessProgram),
789 XtRString, SECOND_CHESS_PROGRAM },
790 { "firstPlaysBlack", "firstPlaysBlack", XtRBoolean,
791 sizeof(Boolean), XtOffset(AppDataPtr, firstPlaysBlack),
792 XtRImmediate, (XtPointer) False },
793 { "noChessProgram", "noChessProgram", XtRBoolean,
794 sizeof(Boolean), XtOffset(AppDataPtr, noChessProgram),
795 XtRImmediate, (XtPointer) False },
796 { "firstHost", "firstHost", XtRString, sizeof(String),
797 XtOffset(AppDataPtr, firstHost), XtRString, FIRST_HOST },
798 { "secondHost", "secondHost", XtRString, sizeof(String),
799 XtOffset(AppDataPtr, secondHost), XtRString, SECOND_HOST },
800 { "firstDirectory", "firstDirectory", XtRString, sizeof(String),
801 XtOffset(AppDataPtr, firstDirectory), XtRString, "." },
802 { "secondDirectory", "secondDirectory", XtRString, sizeof(String),
803 XtOffset(AppDataPtr, secondDirectory), XtRString, "." },
804 { "bitmapDirectory", "bitmapDirectory", XtRString,
805 sizeof(String), XtOffset(AppDataPtr, bitmapDirectory),
807 { "remoteShell", "remoteShell", XtRString, sizeof(String),
808 XtOffset(AppDataPtr, remoteShell), XtRString, REMOTE_SHELL },
809 { "remoteUser", "remoteUser", XtRString, sizeof(String),
810 XtOffset(AppDataPtr, remoteUser), XtRString, "" },
811 { "timeDelay", "timeDelay", XtRFloat, sizeof(float),
812 XtOffset(AppDataPtr, timeDelay), XtRString,
813 (XtPointer) TIME_DELAY_QUOTE },
814 { "timeControl", "timeControl", XtRString, sizeof(String),
815 XtOffset(AppDataPtr, timeControl), XtRString,
816 (XtPointer) TIME_CONTROL },
817 { "internetChessServerMode", "internetChessServerMode",
818 XtRBoolean, sizeof(Boolean),
819 XtOffset(AppDataPtr, icsActive), XtRImmediate,
821 { "internetChessServerHost", "internetChessServerHost",
822 XtRString, sizeof(String),
823 XtOffset(AppDataPtr, icsHost),
824 XtRString, (XtPointer) ICS_HOST },
825 { "internetChessServerPort", "internetChessServerPort",
826 XtRString, sizeof(String),
827 XtOffset(AppDataPtr, icsPort), XtRString,
828 (XtPointer) ICS_PORT },
829 { "internetChessServerCommPort", "internetChessServerCommPort",
830 XtRString, sizeof(String),
831 XtOffset(AppDataPtr, icsCommPort), XtRString,
833 { "internetChessServerLogonScript", "internetChessServerLogonScript",
834 XtRString, sizeof(String),
835 XtOffset(AppDataPtr, icsLogon), XtRString,
837 { "internetChessServerHelper", "internetChessServerHelper",
838 XtRString, sizeof(String),
839 XtOffset(AppDataPtr, icsHelper), XtRString, "" },
840 { "internetChessServerInputBox", "internetChessServerInputBox",
841 XtRBoolean, sizeof(Boolean),
842 XtOffset(AppDataPtr, icsInputBox), XtRImmediate,
844 { "icsAlarm", "icsAlarm",
845 XtRBoolean, sizeof(Boolean),
846 XtOffset(AppDataPtr, icsAlarm), XtRImmediate,
848 { "icsAlarmTime", "icsAlarmTime",
850 XtOffset(AppDataPtr, icsAlarmTime), XtRImmediate,
852 { "useTelnet", "useTelnet", XtRBoolean, sizeof(Boolean),
853 XtOffset(AppDataPtr, useTelnet), XtRImmediate,
855 { "telnetProgram", "telnetProgram", XtRString, sizeof(String),
856 XtOffset(AppDataPtr, telnetProgram), XtRString, TELNET_PROGRAM },
857 { "gateway", "gateway", XtRString, sizeof(String),
858 XtOffset(AppDataPtr, gateway), XtRString, "" },
859 { "loadGameFile", "loadGameFile", XtRString, sizeof(String),
860 XtOffset(AppDataPtr, loadGameFile), XtRString, "" },
861 { "loadGameIndex", "loadGameIndex",
863 XtOffset(AppDataPtr, loadGameIndex), XtRImmediate,
865 { "saveGameFile", "saveGameFile", XtRString, sizeof(String),
866 XtOffset(AppDataPtr, saveGameFile), XtRString, "" },
867 { "autoRaiseBoard", "autoRaiseBoard", XtRBoolean,
868 sizeof(Boolean), XtOffset(AppDataPtr, autoRaiseBoard),
869 XtRImmediate, (XtPointer) True },
870 { "autoSaveGames", "autoSaveGames", XtRBoolean,
871 sizeof(Boolean), XtOffset(AppDataPtr, autoSaveGames),
872 XtRImmediate, (XtPointer) False },
873 { "blindfold", "blindfold", XtRBoolean,
874 sizeof(Boolean), XtOffset(AppDataPtr, blindfold),
875 XtRImmediate, (XtPointer) False },
876 { "loadPositionFile", "loadPositionFile", XtRString,
877 sizeof(String), XtOffset(AppDataPtr, loadPositionFile),
879 { "loadPositionIndex", "loadPositionIndex",
881 XtOffset(AppDataPtr, loadPositionIndex), XtRImmediate,
883 { "savePositionFile", "savePositionFile", XtRString,
884 sizeof(String), XtOffset(AppDataPtr, savePositionFile),
886 { "matchMode", "matchMode", XtRBoolean, sizeof(Boolean),
887 XtOffset(AppDataPtr, matchMode), XtRImmediate, (XtPointer) False },
888 { "matchGames", "matchGames", XtRInt, sizeof(int),
889 XtOffset(AppDataPtr, matchGames), XtRImmediate,
891 { "monoMode", "monoMode", XtRBoolean, sizeof(Boolean),
892 XtOffset(AppDataPtr, monoMode), XtRImmediate,
894 { "debugMode", "debugMode", XtRBoolean, sizeof(Boolean),
895 XtOffset(AppDataPtr, debugMode), XtRImmediate,
897 { "clockMode", "clockMode", XtRBoolean, sizeof(Boolean),
898 XtOffset(AppDataPtr, clockMode), XtRImmediate,
900 { "boardSize", "boardSize", XtRString, sizeof(String),
901 XtOffset(AppDataPtr, boardSize), XtRString, "" },
902 { "searchTime", "searchTime", XtRString, sizeof(String),
903 XtOffset(AppDataPtr, searchTime), XtRString,
905 { "searchDepth", "searchDepth", XtRInt, sizeof(int),
906 XtOffset(AppDataPtr, searchDepth), XtRImmediate,
908 { "showCoords", "showCoords", XtRBoolean, sizeof(Boolean),
909 XtOffset(AppDataPtr, showCoords), XtRImmediate,
911 { "showJail", "showJail", XtRInt, sizeof(int),
912 XtOffset(AppDataPtr, showJail), XtRImmediate,
914 { "showThinking", "showThinking", XtRBoolean, sizeof(Boolean),
915 XtOffset(AppDataPtr, showThinking), XtRImmediate,
917 { "ponderNextMove", "ponderNextMove", XtRBoolean, sizeof(Boolean),
918 XtOffset(AppDataPtr, ponderNextMove), XtRImmediate,
920 { "periodicUpdates", "periodicUpdates", XtRBoolean, sizeof(Boolean),
921 XtOffset(AppDataPtr, periodicUpdates), XtRImmediate,
923 { "clockFont", "clockFont", XtRString, sizeof(String),
924 XtOffset(AppDataPtr, clockFont), XtRString, CLOCK_FONT },
925 { "coordFont", "coordFont", XtRString, sizeof(String),
926 XtOffset(AppDataPtr, coordFont), XtRString, COORD_FONT },
927 { "font", "font", XtRString, sizeof(String),
928 XtOffset(AppDataPtr, font), XtRString, DEFAULT_FONT },
929 { "ringBellAfterMoves", "ringBellAfterMoves",
930 XtRBoolean, sizeof(Boolean),
931 XtOffset(AppDataPtr, ringBellAfterMoves),
932 XtRImmediate, (XtPointer) False },
933 { "autoCallFlag", "autoCallFlag", XtRBoolean,
934 sizeof(Boolean), XtOffset(AppDataPtr, autoCallFlag),
935 XtRImmediate, (XtPointer) False },
936 { "autoFlipView", "autoFlipView", XtRBoolean,
937 sizeof(Boolean), XtOffset(AppDataPtr, autoFlipView),
938 XtRImmediate, (XtPointer) True },
939 { "autoObserve", "autoObserve", XtRBoolean,
940 sizeof(Boolean), XtOffset(AppDataPtr, autoObserve),
941 XtRImmediate, (XtPointer) False },
942 { "autoComment", "autoComment", XtRBoolean,
943 sizeof(Boolean), XtOffset(AppDataPtr, autoComment),
944 XtRImmediate, (XtPointer) False },
945 { "getMoveList", "getMoveList", XtRBoolean,
946 sizeof(Boolean), XtOffset(AppDataPtr, getMoveList),
947 XtRImmediate, (XtPointer) True },
949 { "highlightDragging", "highlightDragging", XtRBoolean,
950 sizeof(Boolean), XtOffset(AppDataPtr, highlightDragging),
951 XtRImmediate, (XtPointer) False },
953 { "highlightLastMove", "highlightLastMove", XtRBoolean,
954 sizeof(Boolean), XtOffset(AppDataPtr, highlightLastMove),
955 XtRImmediate, (XtPointer) False },
956 { "premove", "premove", XtRBoolean,
957 sizeof(Boolean), XtOffset(AppDataPtr, premove),
958 XtRImmediate, (XtPointer) True },
959 { "testLegality", "testLegality", XtRBoolean,
960 sizeof(Boolean), XtOffset(AppDataPtr, testLegality),
961 XtRImmediate, (XtPointer) True },
962 { "flipView", "flipView", XtRBoolean,
963 sizeof(Boolean), XtOffset(AppDataPtr, flipView),
964 XtRImmediate, (XtPointer) False },
965 { "cmail", "cmailGameName", XtRString, sizeof(String),
966 XtOffset(AppDataPtr, cmailGameName), XtRString, "" },
967 { "alwaysPromoteToQueen", "alwaysPromoteToQueen", XtRBoolean,
968 sizeof(Boolean), XtOffset(AppDataPtr, alwaysPromoteToQueen),
969 XtRImmediate, (XtPointer) False },
970 { "oldSaveStyle", "oldSaveStyle", XtRBoolean,
971 sizeof(Boolean), XtOffset(AppDataPtr, oldSaveStyle),
972 XtRImmediate, (XtPointer) False },
973 { "quietPlay", "quietPlay", XtRBoolean,
974 sizeof(Boolean), XtOffset(AppDataPtr, quietPlay),
975 XtRImmediate, (XtPointer) False },
976 { "titleInWindow", "titleInWindow", XtRBoolean,
977 sizeof(Boolean), XtOffset(AppDataPtr, titleInWindow),
978 XtRImmediate, (XtPointer) False },
979 { "localLineEditing", "localLineEditing", XtRBoolean,
980 sizeof(Boolean), XtOffset(AppDataPtr, localLineEditing),
981 XtRImmediate, (XtPointer) True }, /* not implemented, must be True */
983 { "zippyTalk", "zippyTalk", XtRBoolean,
984 sizeof(Boolean), XtOffset(AppDataPtr, zippyTalk),
985 XtRImmediate, (XtPointer) ZIPPY_TALK },
986 { "zippyPlay", "zippyPlay", XtRBoolean,
987 sizeof(Boolean), XtOffset(AppDataPtr, zippyPlay),
988 XtRImmediate, (XtPointer) ZIPPY_PLAY },
989 { "zippyLines", "zippyLines", XtRString, sizeof(String),
990 XtOffset(AppDataPtr, zippyLines), XtRString, ZIPPY_LINES },
991 { "zippyPinhead", "zippyPinhead", XtRString, sizeof(String),
992 XtOffset(AppDataPtr, zippyPinhead), XtRString, ZIPPY_PINHEAD },
993 { "zippyPassword", "zippyPassword", XtRString, sizeof(String),
994 XtOffset(AppDataPtr, zippyPassword), XtRString, ZIPPY_PASSWORD },
995 { "zippyPassword2", "zippyPassword2", XtRString, sizeof(String),
996 XtOffset(AppDataPtr, zippyPassword2), XtRString, ZIPPY_PASSWORD2 },
997 { "zippyWrongPassword", "zippyWrongPassword", XtRString, sizeof(String),
998 XtOffset(AppDataPtr, zippyWrongPassword), XtRString,
999 ZIPPY_WRONG_PASSWORD },
1000 { "zippyAcceptOnly", "zippyAcceptOnly", XtRString, sizeof(String),
1001 XtOffset(AppDataPtr, zippyAcceptOnly), XtRString, ZIPPY_ACCEPT_ONLY },
1002 { "zippyUseI", "zippyUseI", XtRBoolean,
1003 sizeof(Boolean), XtOffset(AppDataPtr, zippyUseI),
1004 XtRImmediate, (XtPointer) ZIPPY_USE_I },
1005 { "zippyBughouse", "zippyBughouse", XtRInt,
1006 sizeof(int), XtOffset(AppDataPtr, zippyBughouse),
1007 XtRImmediate, (XtPointer) ZIPPY_BUGHOUSE },
1008 { "zippyNoplayCrafty", "zippyNoplayCrafty", XtRBoolean,
1009 sizeof(Boolean), XtOffset(AppDataPtr, zippyNoplayCrafty),
1010 XtRImmediate, (XtPointer) ZIPPY_NOPLAY_CRAFTY },
1011 { "zippyGameEnd", "zippyGameEnd", XtRString, sizeof(String),
1012 XtOffset(AppDataPtr, zippyGameEnd), XtRString, ZIPPY_GAME_END },
1013 { "zippyGameStart", "zippyGameStart", XtRString, sizeof(String),
1014 XtOffset(AppDataPtr, zippyGameStart), XtRString, ZIPPY_GAME_START },
1015 { "zippyAdjourn", "zippyAdjourn", XtRBoolean,
1016 sizeof(Boolean), XtOffset(AppDataPtr, zippyAdjourn),
1017 XtRImmediate, (XtPointer) ZIPPY_ADJOURN },
1018 { "zippyAbort", "zippyAbort", XtRBoolean,
1019 sizeof(Boolean), XtOffset(AppDataPtr, zippyAbort),
1020 XtRImmediate, (XtPointer) ZIPPY_ABORT },
1021 { "zippyVariants", "zippyVariants", XtRString, sizeof(String),
1022 XtOffset(AppDataPtr, zippyVariants), XtRString, ZIPPY_VARIANTS },
1023 { "zippyMaxGames", "zippyMaxGames", XtRInt, sizeof(int),
1024 XtOffset(AppDataPtr, zippyMaxGames), XtRImmediate,
1025 (XtPointer) ZIPPY_MAX_GAMES },
1026 { "zippyReplayTimeout", "zippyReplayTimeout", XtRInt, sizeof(int),
1027 XtOffset(AppDataPtr, zippyReplayTimeout), XtRImmediate,
1028 (XtPointer) ZIPPY_REPLAY_TIMEOUT },
1029 { "zippyShortGame", "zippyShortGame", XtRInt, sizeof(int),
1030 XtOffset(AppDataPtr, zippyShortGame), XtRImmediate,
1033 { "flashCount", "flashCount", XtRInt, sizeof(int),
1034 XtOffset(AppDataPtr, flashCount), XtRImmediate,
1035 (XtPointer) FLASH_COUNT },
1036 { "flashRate", "flashRate", XtRInt, sizeof(int),
1037 XtOffset(AppDataPtr, flashRate), XtRImmediate,
1038 (XtPointer) FLASH_RATE },
1039 { "pixmapDirectory", "pixmapDirectory", XtRString,
1040 sizeof(String), XtOffset(AppDataPtr, pixmapDirectory),
1042 { "msLoginDelay", "msLoginDelay", XtRInt, sizeof(int),
1043 XtOffset(AppDataPtr, msLoginDelay), XtRImmediate,
1044 (XtPointer) MS_LOGIN_DELAY },
1045 { "colorizeMessages", "colorizeMessages", XtRBoolean,
1046 sizeof(Boolean), XtOffset(AppDataPtr, colorize),
1047 XtRImmediate, (XtPointer) False },
1048 { "colorShout", "colorShout", XtRString,
1049 sizeof(String), XtOffset(AppDataPtr, colorShout),
1050 XtRString, COLOR_SHOUT },
1051 { "colorSShout", "colorSShout", XtRString,
1052 sizeof(String), XtOffset(AppDataPtr, colorSShout),
1053 XtRString, COLOR_SSHOUT },
1054 { "colorChannel1", "colorChannel1", XtRString,
1055 sizeof(String), XtOffset(AppDataPtr, colorChannel1),
1056 XtRString, COLOR_CHANNEL1 },
1057 { "colorChannel", "colorChannel", XtRString,
1058 sizeof(String), XtOffset(AppDataPtr, colorChannel),
1059 XtRString, COLOR_CHANNEL },
1060 { "colorKibitz", "colorKibitz", XtRString,
1061 sizeof(String), XtOffset(AppDataPtr, colorKibitz),
1062 XtRString, COLOR_KIBITZ },
1063 { "colorTell", "colorTell", XtRString,
1064 sizeof(String), XtOffset(AppDataPtr, colorTell),
1065 XtRString, COLOR_TELL },
1066 { "colorChallenge", "colorChallenge", XtRString,
1067 sizeof(String), XtOffset(AppDataPtr, colorChallenge),
1068 XtRString, COLOR_CHALLENGE },
1069 { "colorRequest", "colorRequest", XtRString,
1070 sizeof(String), XtOffset(AppDataPtr, colorRequest),
1071 XtRString, COLOR_REQUEST },
1072 { "colorSeek", "colorSeek", XtRString,
1073 sizeof(String), XtOffset(AppDataPtr, colorSeek),
1074 XtRString, COLOR_SEEK },
1075 { "colorNormal", "colorNormal", XtRString,
1076 sizeof(String), XtOffset(AppDataPtr, colorNormal),
1077 XtRString, COLOR_NORMAL },
1078 { "soundProgram", "soundProgram", XtRString,
1079 sizeof(String), XtOffset(AppDataPtr, soundProgram),
1080 XtRString, "play" },
1081 { "soundShout", "soundShout", XtRString,
1082 sizeof(String), XtOffset(AppDataPtr, soundShout),
1084 { "soundSShout", "soundSShout", XtRString,
1085 sizeof(String), XtOffset(AppDataPtr, soundSShout),
1087 { "soundChannel1", "soundChannel1", XtRString,
1088 sizeof(String), XtOffset(AppDataPtr, soundChannel1),
1090 { "soundChannel", "soundChannel", XtRString,
1091 sizeof(String), XtOffset(AppDataPtr, soundChannel),
1093 { "soundKibitz", "soundKibitz", XtRString,
1094 sizeof(String), XtOffset(AppDataPtr, soundKibitz),
1096 { "soundTell", "soundTell", XtRString,
1097 sizeof(String), XtOffset(AppDataPtr, soundTell),
1099 { "soundChallenge", "soundChallenge", XtRString,
1100 sizeof(String), XtOffset(AppDataPtr, soundChallenge),
1102 { "soundRequest", "soundRequest", XtRString,
1103 sizeof(String), XtOffset(AppDataPtr, soundRequest),
1105 { "soundSeek", "soundSeek", XtRString,
1106 sizeof(String), XtOffset(AppDataPtr, soundSeek),
1108 { "soundMove", "soundMove", XtRString,
1109 sizeof(String), XtOffset(AppDataPtr, soundMove),
1111 { "soundIcsWin", "soundIcsWin", XtRString,
1112 sizeof(String), XtOffset(AppDataPtr, soundIcsWin),
1114 { "soundIcsLoss", "soundIcsLoss", XtRString,
1115 sizeof(String), XtOffset(AppDataPtr, soundIcsLoss),
1117 { "soundIcsDraw", "soundIcsDraw", XtRString,
1118 sizeof(String), XtOffset(AppDataPtr, soundIcsDraw),
1120 { "soundIcsUnfinished", "soundIcsUnfinished", XtRString,
1121 sizeof(String), XtOffset(AppDataPtr, soundIcsUnfinished),
1123 { "soundIcsAlarm", "soundIcsAlarm", XtRString,
1124 sizeof(String), XtOffset(AppDataPtr, soundIcsAlarm),
1126 { "reuseFirst", "reuseFirst", XtRBoolean,
1127 sizeof(Boolean), XtOffset(AppDataPtr, reuseFirst),
1128 XtRImmediate, (XtPointer) True },
1129 { "reuseSecond", "reuseSecond", XtRBoolean,
1130 sizeof(Boolean), XtOffset(AppDataPtr, reuseSecond),
1131 XtRImmediate, (XtPointer) True },
1132 { "animateDragging", "animateDragging", XtRBoolean,
1133 sizeof(Boolean), XtOffset(AppDataPtr, animateDragging),
1134 XtRImmediate, (XtPointer) True },
1135 { "animateMoving", "animateMoving", XtRBoolean,
1136 sizeof(Boolean), XtOffset(AppDataPtr, animate),
1137 XtRImmediate, (XtPointer) True },
1138 { "animateSpeed", "animateSpeed", XtRInt,
1139 sizeof(int), XtOffset(AppDataPtr, animSpeed),
1140 XtRImmediate, (XtPointer)10 },
1141 { "popupExitMessage", "popupExitMessage", XtRBoolean,
1142 sizeof(Boolean), XtOffset(AppDataPtr, popupExitMessage),
1143 XtRImmediate, (XtPointer) True },
1144 { "popupMoveErrors", "popupMoveErrors", XtRBoolean,
1145 sizeof(Boolean), XtOffset(AppDataPtr, popupMoveErrors),
1146 XtRImmediate, (XtPointer) False },
1147 { "fontSizeTolerance", "fontSizeTolerance", XtRInt,
1148 sizeof(int), XtOffset(AppDataPtr, fontSizeTolerance),
1149 XtRImmediate, (XtPointer)4 },
1150 { "initialMode", "initialMode", XtRString,
1151 sizeof(String), XtOffset(AppDataPtr, initialMode),
1152 XtRImmediate, (XtPointer) "" },
1153 { "variant", "variant", XtRString,
1154 sizeof(String), XtOffset(AppDataPtr, variant),
1155 XtRImmediate, (XtPointer) "normal" },
1156 { "firstProtocolVersion", "firstProtocolVersion", XtRInt,
1157 sizeof(int), XtOffset(AppDataPtr, firstProtocolVersion),
1158 XtRImmediate, (XtPointer)PROTOVER },
1159 { "secondProtocolVersion", "secondProtocolVersion", XtRInt,
1160 sizeof(int), XtOffset(AppDataPtr, secondProtocolVersion),
1161 XtRImmediate, (XtPointer)PROTOVER },
1162 { "showButtonBar", "showButtonBar", XtRBoolean,
1163 sizeof(Boolean), XtOffset(AppDataPtr, showButtonBar),
1164 XtRImmediate, (XtPointer) True },
1165 { "lowTimeWarningColor", "lowTimeWarningColor", XtRString,
1166 sizeof(String), XtOffset(AppDataPtr, lowTimeWarningColor),
1167 XtRString, COLOR_LOWTIMEWARNING },
1168 { "lowTimeWarning", "lowTimeWarning", XtRBoolean,
1169 sizeof(Boolean), XtOffset(AppDataPtr, lowTimeWarning),
1170 XtRImmediate, (XtPointer) False },
1171 {"icsEngineAnalyze", "icsEngineAnalyze", XtRBoolean, /* [DM] icsEngineAnalyze */
1172 sizeof(Boolean), XtOffset(AppDataPtr, icsEngineAnalyze),
1173 XtRImmediate, (XtPointer) False },
1174 { "firstScoreAbs", "firstScoreAbs", XtRBoolean,
1175 sizeof(Boolean), XtOffset(AppDataPtr, firstScoreIsAbsolute),
1176 XtRImmediate, (XtPointer) False },
1177 { "secondScoreAbs", "secondScoreAbs", XtRBoolean,
1178 sizeof(Boolean), XtOffset(AppDataPtr, secondScoreIsAbsolute),
1179 XtRImmediate, (XtPointer) False },
1180 { "pgnExtendedInfo", "pgnExtendedInfo", XtRBoolean,
1181 sizeof(Boolean), XtOffset(AppDataPtr, saveExtendedInfoInPGN),
1182 XtRImmediate, (XtPointer) False },
1183 { "hideThinkingFromHuman", "hideThinkingFromHuman", XtRBoolean,
1184 sizeof(Boolean), XtOffset(AppDataPtr, hideThinkingFromHuman),
1185 XtRImmediate, (XtPointer) True },
1186 { "adjudicateLossThreshold", "adjudicateLossThreshold", XtRInt,
1187 sizeof(int), XtOffset(AppDataPtr, adjudicateLossThreshold),
1188 XtRImmediate, (XtPointer) 0},
1189 { "adjudicateDrawMoves", "adjudicateDrawMoves", XtRInt,
1190 sizeof(int), XtOffset(AppDataPtr, adjudicateDrawMoves),
1191 XtRImmediate, (XtPointer) 0},
1192 { "pgnEventHeader", "pgnEventHeader", XtRString,
1193 sizeof(String), XtOffset(AppDataPtr, pgnEventHeader),
1194 XtRImmediate, (XtPointer) "Computer Chess Game" },
1195 { "defaultFrcPosition", "defaultFrcPositon", XtRInt,
1196 sizeof(int), XtOffset(AppDataPtr, defaultFrcPosition),
1197 XtRImmediate, (XtPointer) -1},
1198 { "gameListTags", "gameListTags", XtRString,
1199 sizeof(String), XtOffset(AppDataPtr, gameListTags),
1200 XtRImmediate, (XtPointer) GLT_DEFAULT_TAGS },
1202 // [HGM] 4.3.xx options
1203 { "boardWidth", "boardWidth", XtRInt,
1204 sizeof(int), XtOffset(AppDataPtr, NrFiles),
1205 XtRImmediate, (XtPointer) -1},
1206 { "boardHeight", "boardHeight", XtRInt,
1207 sizeof(int), XtOffset(AppDataPtr, NrRanks),
1208 XtRImmediate, (XtPointer) -1},
1209 { "matchPause", "matchPause", XtRInt,
1210 sizeof(int), XtOffset(AppDataPtr, matchPause),
1211 XtRImmediate, (XtPointer) 10000},
1212 { "holdingsSize", "holdingsSize", XtRInt,
1213 sizeof(int), XtOffset(AppDataPtr, holdingsSize),
1214 XtRImmediate, (XtPointer) -1},
1215 { "flipBlack", "flipBlack", XtRBoolean,
1216 sizeof(Boolean), XtOffset(AppDataPtr, upsideDown),
1217 XtRImmediate, (XtPointer) False},
1218 { "allWhite", "allWhite", XtRBoolean,
1219 sizeof(Boolean), XtOffset(AppDataPtr, allWhite),
1220 XtRImmediate, (XtPointer) False},
1221 { "pieceToCharTable", "pieceToCharTable", XtRString,
1222 sizeof(String), XtOffset(AppDataPtr, pieceToCharTable),
1223 XtRImmediate, (XtPointer) 0},
1224 { "alphaRank", "alphaRank", XtRBoolean,
1225 sizeof(Boolean), XtOffset(AppDataPtr, alphaRank),
1226 XtRImmediate, (XtPointer) False},
1227 { "testClaims", "testClaims", XtRBoolean,
1228 sizeof(Boolean), XtOffset(AppDataPtr, testClaims),
1229 XtRImmediate, (XtPointer) True},
1230 { "checkMates", "checkMates", XtRBoolean,
1231 sizeof(Boolean), XtOffset(AppDataPtr, checkMates),
1232 XtRImmediate, (XtPointer) True},
1233 { "materialDraws", "materialDraws", XtRBoolean,
1234 sizeof(Boolean), XtOffset(AppDataPtr, materialDraws),
1235 XtRImmediate, (XtPointer) True},
1236 { "trivialDraws", "trivialDraws", XtRBoolean,
1237 sizeof(Boolean), XtOffset(AppDataPtr, trivialDraws),
1238 XtRImmediate, (XtPointer) False},
1239 { "ruleMoves", "ruleMoves", XtRInt,
1240 sizeof(int), XtOffset(AppDataPtr, ruleMoves),
1241 XtRImmediate, (XtPointer) 51},
1242 { "repeatsToDraw", "repeatsToDraw", XtRInt,
1243 sizeof(int), XtOffset(AppDataPtr, drawRepeats),
1244 XtRImmediate, (XtPointer) 6},
1245 { "engineDebugOutput", "engineDebugOutput", XtRInt,
1246 sizeof(int), XtOffset(AppDataPtr, engineComments),
1247 XtRImmediate, (XtPointer) 1},
1248 { "userName", "userName", XtRString,
1249 sizeof(int), XtOffset(AppDataPtr, userName),
1250 XtRImmediate, (XtPointer) 0},
1251 { "autoKibitz", "autoKibitz", XtRBoolean,
1252 sizeof(Boolean), XtOffset(AppDataPtr, autoKibitz),
1253 XtRImmediate, (XtPointer) False},
1254 { "firstTimeOdds", "firstTimeOdds", XtRInt,
1255 sizeof(int), XtOffset(AppDataPtr, firstTimeOdds),
1256 XtRImmediate, (XtPointer) 1},
1257 { "secondTimeOdds", "secondTimeOdds", XtRInt,
1258 sizeof(int), XtOffset(AppDataPtr, secondTimeOdds),
1259 XtRImmediate, (XtPointer) 1},
1260 { "timeOddsMode", "timeOddsMode", XtRInt,
1261 sizeof(int), XtOffset(AppDataPtr, timeOddsMode),
1262 XtRImmediate, (XtPointer) 0},
1263 { "firstAccumulateTC", "firstAccumulateTC", XtRInt,
1264 sizeof(int), XtOffset(AppDataPtr, firstAccumulateTC),
1265 XtRImmediate, (XtPointer) 1},
1266 { "secondAccumulateTC", "secondAccumulateTC", XtRInt,
1267 sizeof(int), XtOffset(AppDataPtr, secondAccumulateTC),
1268 XtRImmediate, (XtPointer) 1},
1269 { "firstNPS", "firstNPS", XtRInt,
1270 sizeof(int), XtOffset(AppDataPtr, firstNPS),
1271 XtRImmediate, (XtPointer) -1},
1272 { "secondNPS", "secondNPS", XtRInt,
1273 sizeof(int), XtOffset(AppDataPtr, secondNPS),
1274 XtRImmediate, (XtPointer) -1},
1275 { "serverMoves", "serverMoves", XtRString,
1276 sizeof(String), XtOffset(AppDataPtr, serverMovesName),
1277 XtRImmediate, (XtPointer) 0},
1278 { "serverPause", "serverPause", XtRInt,
1279 sizeof(int), XtOffset(AppDataPtr, serverPause),
1280 XtRImmediate, (XtPointer) 0},
1281 { "suppressLoadMoves", "suppressLoadMoves", XtRBoolean,
1282 sizeof(Boolean), XtOffset(AppDataPtr, suppressLoadMoves),
1283 XtRImmediate, (XtPointer) False},
1284 { "userName", "userName", XtRString,
1285 sizeof(String), XtOffset(AppDataPtr, userName),
1286 XtRImmediate, (XtPointer) 0},
1287 { "egtFormats", "egtFormats", XtRString,
1288 sizeof(String), XtOffset(AppDataPtr, egtFormats),
1289 XtRImmediate, (XtPointer) 0},
1290 { "rewindIndex", "rewindIndex", XtRInt,
1291 sizeof(int), XtOffset(AppDataPtr, rewindIndex),
1292 XtRImmediate, (XtPointer) 0},
1293 { "sameColorGames", "sameColorGames", XtRInt,
1294 sizeof(int), XtOffset(AppDataPtr, sameColorGames),
1295 XtRImmediate, (XtPointer) 0},
1296 { "smpCores", "smpCores", XtRInt,
1297 sizeof(int), XtOffset(AppDataPtr, smpCores),
1298 XtRImmediate, (XtPointer) 1},
1299 { "niceEngines", "niceEngines", XtRInt,
1300 sizeof(int), XtOffset(AppDataPtr, niceEngines),
1301 XtRImmediate, (XtPointer) 0},
1302 { "nameOfDebugFile", "nameOfDebugFile", XtRString,
1303 sizeof(String), XtOffset(AppDataPtr, nameOfDebugFile),
1304 XtRImmediate, (XtPointer) "xboard.debug"},
1305 { "engineDebugOutput", "engineDebugOutput", XtRInt,
1306 sizeof(int), XtOffset(AppDataPtr, engineComments),
1307 XtRImmediate, (XtPointer) 1},
1308 { "noGUI", "noGUI", XtRBoolean,
1309 sizeof(Boolean), XtOffset(AppDataPtr, noGUI),
1310 XtRImmediate, (XtPointer) 0},
1311 { "firstOptions", "firstOptions", XtRString,
1312 sizeof(String), XtOffset(AppDataPtr, firstOptions),
1313 XtRImmediate, (XtPointer) "" },
1314 { "secondOptions", "secondOptions", XtRString,
1315 sizeof(String), XtOffset(AppDataPtr, secondOptions),
1316 XtRImmediate, (XtPointer) "" },
1317 { "firstNeedsNoncompliantFEN", "firstNeedsNoncompliantFEN", XtRString,
1318 sizeof(String), XtOffset(AppDataPtr, fenOverride1),
1319 XtRImmediate, (XtPointer) 0 },
1320 { "secondNeedsNoncompliantFEN", "secondNeedsNoncompliantFEN", XtRString,
1321 sizeof(String), XtOffset(AppDataPtr, fenOverride2),
1322 XtRImmediate, (XtPointer) 0 },
1324 // [HGM] Winboard_x UCI options
1325 { "firstIsUCI", "firstIsUCI", XtRBoolean,
1326 sizeof(Boolean), XtOffset(AppDataPtr, firstIsUCI),
1327 XtRImmediate, (XtPointer) False},
1328 { "secondIsUCI", "secondIsUCI", XtRBoolean,
1329 sizeof(Boolean), XtOffset(AppDataPtr, secondIsUCI),
1330 XtRImmediate, (XtPointer) False},
1331 { "firstHasOwnBookUCI", "firstHasOwnBookUCI", XtRBoolean,
1332 sizeof(Boolean), XtOffset(AppDataPtr, firstHasOwnBookUCI),
1333 XtRImmediate, (XtPointer) True},
1334 { "secondHasOwnBookUCI", "secondHasOwnBookUCI", XtRBoolean,
1335 sizeof(Boolean), XtOffset(AppDataPtr, secondHasOwnBookUCI),
1336 XtRImmediate, (XtPointer) True},
1337 { "usePolyglotBook", "usePolyglotBook", XtRBoolean,
1338 sizeof(Boolean), XtOffset(AppDataPtr, usePolyglotBook),
1339 XtRImmediate, (XtPointer) False},
1340 { "defaultHashSize", "defaultHashSize", XtRInt,
1341 sizeof(int), XtOffset(AppDataPtr, defaultHashSize),
1342 XtRImmediate, (XtPointer) 64},
1343 { "defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XtRInt,
1344 sizeof(int), XtOffset(AppDataPtr, defaultCacheSizeEGTB),
1345 XtRImmediate, (XtPointer) 4},
1346 { "polyglotDir", "polyglotDir", XtRString,
1347 sizeof(String), XtOffset(AppDataPtr, polyglotDir),
1348 XtRImmediate, (XtPointer) "." },
1349 { "polyglotBook", "polyglotBook", XtRString,
1350 sizeof(String), XtOffset(AppDataPtr, polyglotBook),
1351 XtRImmediate, (XtPointer) "" },
1352 { "defaultPathEGTB", "defaultPathEGTB", XtRString,
1353 sizeof(String), XtOffset(AppDataPtr, defaultPathEGTB),
1354 XtRImmediate, (XtPointer) "/usr/local/share/egtb"},
1355 { "delayBeforeQuit", "delayBeforeQuit", XtRInt,
1356 sizeof(int), XtOffset(AppDataPtr, delayBeforeQuit),
1357 XtRImmediate, (XtPointer) 0},
1358 { "delayAfterQuit", "delayAfterQuit", XtRInt,
1359 sizeof(int), XtOffset(AppDataPtr, delayAfterQuit),
1360 XtRImmediate, (XtPointer) 0},
1361 { "keepAlive", "keepAlive", XtRInt,
1362 sizeof(int), XtOffset(AppDataPtr, keepAlive),
1363 XtRImmediate, (XtPointer) 0},
1364 { "forceIllegalMoves", "forceIllegalMoves", XtRBoolean,
1365 sizeof(Boolean), XtOffset(AppDataPtr, forceIllegal),
1366 XtRImmediate, (XtPointer) False},
1367 { "keepLineBreaksICS", "keepLineBreaksICS", XtRBoolean,
1368 sizeof(Boolean), XtOffset(AppDataPtr, noJoin),
1369 XtRImmediate, (XtPointer) False},
1370 { "wrapContinuationSequence", "wrapContinuationSequence", XtRString,
1371 sizeof(String), XtOffset(AppDataPtr, wrapContSeq),
1373 { "useInternalWrap", "useInternalWrap", XtRBoolean,
1374 sizeof(Boolean), XtOffset(AppDataPtr, useInternalWrap),
1375 XtRImmediate, (XtPointer) True},
1378 XrmOptionDescRec shellOptions[] = {
1379 { "-whitePieceColor", "whitePieceColor", XrmoptionSepArg, NULL },
1380 { "-blackPieceColor", "blackPieceColor", XrmoptionSepArg, NULL },
1381 { "-lightSquareColor", "lightSquareColor", XrmoptionSepArg, NULL },
1382 { "-darkSquareColor", "darkSquareColor", XrmoptionSepArg, NULL },
1383 { "-highlightSquareColor", "highlightSquareColor", XrmoptionSepArg, NULL },
1384 { "-premoveHighlightColor", "premoveHighlightColor", XrmoptionSepArg,NULL},
1385 { "-movesPerSession", "movesPerSession", XrmoptionSepArg, NULL },
1386 { "-mps", "movesPerSession", XrmoptionSepArg, NULL },
1387 { "-timeIncrement", "timeIncrement", XrmoptionSepArg, NULL },
1388 { "-inc", "timeIncrement", XrmoptionSepArg, NULL },
1389 { "-initString", "initString", XrmoptionSepArg, NULL },
1390 { "-firstInitString", "initString", XrmoptionSepArg, NULL },
1391 { "-secondInitString", "secondInitString", XrmoptionSepArg, NULL },
1392 { "-firstComputerString", "firstComputerString", XrmoptionSepArg, NULL },
1393 { "-secondComputerString", "secondComputerString", XrmoptionSepArg, NULL },
1394 { "-firstChessProgram", "firstChessProgram", XrmoptionSepArg, NULL },
1395 { "-fcp", "firstChessProgram", XrmoptionSepArg, NULL },
1396 { "-secondChessProgram", "secondChessProgram", XrmoptionSepArg, NULL },
1397 { "-scp", "secondChessProgram", XrmoptionSepArg, NULL },
1398 { "-firstPlaysBlack", "firstPlaysBlack", XrmoptionSepArg, NULL },
1399 { "-fb", "firstPlaysBlack", XrmoptionNoArg, "True" },
1400 { "-xfb", "firstPlaysBlack", XrmoptionNoArg, "False" },
1401 { "-noChessProgram", "noChessProgram", XrmoptionSepArg, NULL },
1402 { "-ncp", "noChessProgram", XrmoptionNoArg, "True" },
1403 { "-xncp", "noChessProgram", XrmoptionNoArg, "False" },
1404 { "-firstHost", "firstHost", XrmoptionSepArg, NULL },
1405 { "-fh", "firstHost", XrmoptionSepArg, NULL },
1406 { "-secondHost", "secondHost", XrmoptionSepArg, NULL },
1407 { "-sh", "secondHost", XrmoptionSepArg, NULL },
1408 { "-firstDirectory", "firstDirectory", XrmoptionSepArg, NULL },
1409 { "-fd", "firstDirectory", XrmoptionSepArg, NULL },
1410 { "-secondDirectory", "secondDirectory", XrmoptionSepArg, NULL },
1411 { "-sd", "secondDirectory", XrmoptionSepArg, NULL },
1412 { "-bitmapDirectory", "bitmapDirectory", XrmoptionSepArg, NULL },
1413 { "-bm", "bitmapDirectory", XrmoptionSepArg, NULL },
1414 { "-remoteShell", "remoteShell", XrmoptionSepArg, NULL },
1415 { "-rsh", "remoteShell", XrmoptionSepArg, NULL },
1416 { "-remoteUser", "remoteUser", XrmoptionSepArg, NULL },
1417 { "-ruser", "remoteUser", XrmoptionSepArg, NULL },
1418 { "-timeDelay", "timeDelay", XrmoptionSepArg, NULL },
1419 { "-td", "timeDelay", XrmoptionSepArg, NULL },
1420 { "-timeControl", "timeControl", XrmoptionSepArg, NULL },
1421 { "-tc", "timeControl", XrmoptionSepArg, NULL },
1422 { "-internetChessServerMode", "internetChessServerMode",
1423 XrmoptionSepArg, NULL },
1424 { "-ics", "internetChessServerMode", XrmoptionNoArg, "True" },
1425 { "-xics", "internetChessServerMode", XrmoptionNoArg, "False" },
1426 { "-internetChessServerHost", "internetChessServerHost",
1427 XrmoptionSepArg, NULL },
1428 { "-icshost", "internetChessServerHost", XrmoptionSepArg, NULL },
1429 { "-internetChessServerPort", "internetChessServerPort",
1430 XrmoptionSepArg, NULL },
1431 { "-icsport", "internetChessServerPort", XrmoptionSepArg, NULL },
1432 { "-internetChessServerCommPort", "internetChessServerCommPort",
1433 XrmoptionSepArg, NULL },
1434 { "-icscomm", "internetChessServerCommPort", XrmoptionSepArg, NULL },
1435 { "-internetChessServerLogonScript", "internetChessServerLogonScript",
1436 XrmoptionSepArg, NULL },
1437 { "-icslogon", "internetChessServerLogonScript", XrmoptionSepArg, NULL },
1438 { "-internetChessServerHelper", "internetChessServerHelper",
1439 XrmoptionSepArg, NULL },
1440 { "-icshelper", "internetChessServerHelper", XrmoptionSepArg, NULL },
1441 { "-internetChessServerInputBox", "internetChessServerInputBox",
1442 XrmoptionSepArg, NULL },
1443 { "-icsinput", "internetChessServerInputBox", XrmoptionNoArg, "True" },
1444 { "-xicsinput", "internetChessServerInputBox", XrmoptionNoArg, "False" },
1445 { "-icsAlarm", "icsAlarm", XrmoptionSepArg, NULL },
1446 { "-alarm", "icsAlarm", XrmoptionNoArg, "True" },
1447 { "-xalarm", "icsAlarm", XrmoptionNoArg, "False" },
1448 { "-icsAlarmTime", "icsAlarmTime", XrmoptionSepArg, NULL },
1449 { "-useTelnet", "useTelnet", XrmoptionSepArg, NULL },
1450 { "-telnet", "useTelnet", XrmoptionNoArg, "True" },
1451 { "-xtelnet", "useTelnet", XrmoptionNoArg, "False" },
1452 { "-telnetProgram", "telnetProgram", XrmoptionSepArg, NULL },
1453 { "-gateway", "gateway", XrmoptionSepArg, NULL },
1454 { "-loadGameFile", "loadGameFile", XrmoptionSepArg, NULL },
1455 { "-lgf", "loadGameFile", XrmoptionSepArg, NULL },
1456 { "-loadGameIndex", "loadGameIndex", XrmoptionSepArg, NULL },
1457 { "-lgi", "loadGameIndex", XrmoptionSepArg, NULL },
1458 { "-saveGameFile", "saveGameFile", XrmoptionSepArg, NULL },
1459 { "-sgf", "saveGameFile", XrmoptionSepArg, NULL },
1460 { "-autoSaveGames", "autoSaveGames", XrmoptionSepArg, NULL },
1461 { "-autosave", "autoSaveGames", XrmoptionNoArg, "True" },
1462 { "-xautosave", "autoSaveGames", XrmoptionNoArg, "False" },
1463 { "-autoRaiseBoard", "autoRaiseBoard", XrmoptionSepArg, NULL },
1464 { "-autoraise", "autoRaiseBoard", XrmoptionNoArg, "True" },
1465 { "-xautoraise", "autoRaiseBoard", XrmoptionNoArg, "False" },
1466 { "-blindfold", "blindfold", XrmoptionSepArg, NULL },
1467 { "-blind", "blindfold", XrmoptionNoArg, "True" },
1468 { "-xblind", "blindfold", XrmoptionNoArg, "False" },
1469 { "-loadPositionFile", "loadPositionFile", XrmoptionSepArg, NULL },
1470 { "-lpf", "loadPositionFile", XrmoptionSepArg, NULL },
1471 { "-loadPositionIndex", "loadPositionIndex", XrmoptionSepArg, NULL },
1472 { "-lpi", "loadPositionIndex", XrmoptionSepArg, NULL },
1473 { "-savePositionFile", "savePositionFile", XrmoptionSepArg, NULL },
1474 { "-spf", "savePositionFile", XrmoptionSepArg, NULL },
1475 { "-matchMode", "matchMode", XrmoptionSepArg, NULL },
1476 { "-mm", "matchMode", XrmoptionNoArg, "True" },
1477 { "-xmm", "matchMode", XrmoptionNoArg, "False" },
1478 { "-matchGames", "matchGames", XrmoptionSepArg, NULL },
1479 { "-mg", "matchGames", XrmoptionSepArg, NULL },
1480 { "-monoMode", "monoMode", XrmoptionSepArg, NULL },
1481 { "-mono", "monoMode", XrmoptionNoArg, "True" },
1482 { "-xmono", "monoMode", XrmoptionNoArg, "False" },
1483 { "-debugMode", "debugMode", XrmoptionSepArg, NULL },
1484 { "-debug", "debugMode", XrmoptionNoArg, "True" },
1485 { "-xdebug", "debugMode", XrmoptionNoArg, "False" },
1486 { "-clockMode", "clockMode", XrmoptionSepArg, NULL },
1487 { "-clock", "clockMode", XrmoptionNoArg, "True" },
1488 { "-xclock", "clockMode", XrmoptionNoArg, "False" },
1489 { "-boardSize", "boardSize", XrmoptionSepArg, NULL },
1490 { "-size", "boardSize", XrmoptionSepArg, NULL },
1491 { "-searchTime", "searchTime", XrmoptionSepArg, NULL },
1492 { "-st", "searchTime", XrmoptionSepArg, NULL },
1493 { "-searchDepth", "searchDepth", XrmoptionSepArg, NULL },
1494 { "-depth", "searchDepth", XrmoptionSepArg, NULL },
1495 { "-showCoords", "showCoords", XrmoptionSepArg, NULL },
1496 { "-coords", "showCoords", XrmoptionNoArg, "True" },
1497 { "-xcoords", "showCoords", XrmoptionNoArg, "False" },
1499 { "-showJail", "showJail", XrmoptionSepArg, NULL },
1500 { "-jail", "showJail", XrmoptionNoArg, "1" },
1501 { "-sidejail", "showJail", XrmoptionNoArg, "2" },
1502 { "-xjail", "showJail", XrmoptionNoArg, "0" },
1504 { "-showThinking", "showThinking", XrmoptionSepArg, NULL },
1505 { "-thinking", "showThinking", XrmoptionNoArg, "True" },
1506 { "-xthinking", "showThinking", XrmoptionNoArg, "False" },
1507 { "-ponderNextMove", "ponderNextMove", XrmoptionSepArg, NULL },
1508 { "-ponder", "ponderNextMove", XrmoptionNoArg, "True" },
1509 { "-xponder", "ponderNextMove", XrmoptionNoArg, "False" },
1510 { "-periodicUpdates", "periodicUpdates", XrmoptionSepArg, NULL },
1511 { "-periodic", "periodicUpdates", XrmoptionNoArg, "True" },
1512 { "-xperiodic", "periodicUpdates", XrmoptionNoArg, "False" },
1513 { "-clockFont", "clockFont", XrmoptionSepArg, NULL },
1514 { "-coordFont", "coordFont", XrmoptionSepArg, NULL },
1515 { "-font", "font", XrmoptionSepArg, NULL },
1516 { "-ringBellAfterMoves", "ringBellAfterMoves", XrmoptionSepArg, NULL },
1517 { "-bell", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1518 { "-xbell", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1519 { "-movesound", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1520 { "-xmovesound", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1521 { "-autoCallFlag", "autoCallFlag", XrmoptionSepArg, NULL },
1522 { "-autoflag", "autoCallFlag", XrmoptionNoArg, "True" },
1523 { "-xautoflag", "autoCallFlag", XrmoptionNoArg, "False" },
1524 { "-autoFlipView", "autoFlipView", XrmoptionSepArg, NULL },
1525 { "-autoflip", "autoFlipView", XrmoptionNoArg, "True" },
1526 { "-xautoflip", "autoFlipView", XrmoptionNoArg, "False" },
1527 { "-autoObserve", "autoObserve", XrmoptionSepArg, NULL },
1528 { "-autobs", "autoObserve", XrmoptionNoArg, "True" },
1529 { "-xautobs", "autoObserve", XrmoptionNoArg, "False" },
1530 { "-autoComment", "autoComment", XrmoptionSepArg, NULL },
1531 { "-autocomm", "autoComment", XrmoptionNoArg, "True" },
1532 { "-xautocomm", "autoComment", XrmoptionNoArg, "False" },
1533 { "-getMoveList", "getMoveList", XrmoptionSepArg, NULL },
1534 { "-moves", "getMoveList", XrmoptionNoArg, "True" },
1535 { "-xmoves", "getMoveList", XrmoptionNoArg, "False" },
1537 { "-highlightDragging", "highlightDragging", XrmoptionSepArg, NULL },
1538 { "-highdrag", "highlightDragging", XrmoptionNoArg, "True" },
1539 { "-xhighdrag", "highlightDragging", XrmoptionNoArg, "False" },
1541 { "-highlightLastMove", "highlightLastMove", XrmoptionSepArg, NULL },
1542 { "-highlight", "highlightLastMove", XrmoptionNoArg, "True" },
1543 { "-xhighlight", "highlightLastMove", XrmoptionNoArg, "False" },
1544 { "-premove", "premove", XrmoptionSepArg, NULL },
1545 { "-pre", "premove", XrmoptionNoArg, "True" },
1546 { "-xpre", "premove", XrmoptionNoArg, "False" },
1547 { "-testLegality", "testLegality", XrmoptionSepArg, NULL },
1548 { "-legal", "testLegality", XrmoptionNoArg, "True" },
1549 { "-xlegal", "testLegality", XrmoptionNoArg, "False" },
1550 { "-flipView", "flipView", XrmoptionSepArg, NULL },
1551 { "-flip", "flipView", XrmoptionNoArg, "True" },
1552 { "-xflip", "flipView", XrmoptionNoArg, "False" },
1553 { "-cmail", "cmailGameName", XrmoptionSepArg, NULL },
1554 { "-alwaysPromoteToQueen", "alwaysPromoteToQueen",
1555 XrmoptionSepArg, NULL },
1556 { "-queen", "alwaysPromoteToQueen", XrmoptionNoArg, "True" },
1557 { "-xqueen", "alwaysPromoteToQueen", XrmoptionNoArg, "False" },
1558 { "-oldSaveStyle", "oldSaveStyle", XrmoptionSepArg, NULL },
1559 { "-oldsave", "oldSaveStyle", XrmoptionNoArg, "True" },
1560 { "-xoldsave", "oldSaveStyle", XrmoptionNoArg, "False" },
1561 { "-quietPlay", "quietPlay", XrmoptionSepArg, NULL },
1562 { "-quiet", "quietPlay", XrmoptionNoArg, "True" },
1563 { "-xquiet", "quietPlay", XrmoptionNoArg, "False" },
1564 { "-titleInWindow", "titleInWindow", XrmoptionSepArg, NULL },
1565 { "-title", "titleInWindow", XrmoptionNoArg, "True" },
1566 { "-xtitle", "titleInWindow", XrmoptionNoArg, "False" },
1568 { "-zippyTalk", "zippyTalk", XrmoptionSepArg, NULL },
1569 { "-zt", "zippyTalk", XrmoptionNoArg, "True" },
1570 { "-xzt", "zippyTalk", XrmoptionNoArg, "False" },
1571 { "-zippyPlay", "zippyPlay", XrmoptionSepArg, NULL },
1572 { "-zp", "zippyPlay", XrmoptionNoArg, "True" },
1573 { "-xzp", "zippyPlay", XrmoptionNoArg, "False" },
1574 { "-zippyLines", "zippyLines", XrmoptionSepArg, NULL },
1575 { "-zippyPinhead", "zippyPinhead", XrmoptionSepArg, NULL },
1576 { "-zippyPassword", "zippyPassword", XrmoptionSepArg, NULL },
1577 { "-zippyPassword2", "zippyPassword2", XrmoptionSepArg, NULL },
1578 { "-zippyWrongPassword", "zippyWrongPassword", XrmoptionSepArg, NULL },
1579 { "-zippyAcceptOnly", "zippyAcceptOnly", XrmoptionSepArg, NULL },
1580 { "-zippyUseI", "zippyUseI", XrmoptionSepArg, NULL },
1581 { "-zui", "zippyUseI", XrmoptionNoArg, "True" },
1582 { "-xzui", "zippyUseI", XrmoptionNoArg, "False" },
1583 { "-zippyBughouse", "zippyBughouse", XrmoptionSepArg, NULL },
1584 { "-zippyNoplayCrafty", "zippyNoplayCrafty", XrmoptionSepArg, NULL },
1585 { "-znc", "zippyNoplayCrafty", XrmoptionNoArg, "True" },
1586 { "-xznc", "zippyNoplayCrafty", XrmoptionNoArg, "False" },
1587 { "-zippyGameEnd", "zippyGameEnd", XrmoptionSepArg, NULL },
1588 { "-zippyGameStart", "zippyGameStart", XrmoptionSepArg, NULL },
1589 { "-zippyAdjourn", "zippyAdjourn", XrmoptionSepArg, NULL },
1590 { "-zadj", "zippyAdjourn", XrmoptionNoArg, "True" },
1591 { "-xzadj", "zippyAdjourn", XrmoptionNoArg, "False" },
1592 { "-zippyAbort", "zippyAbort", XrmoptionSepArg, NULL },
1593 { "-zab", "zippyAbort", XrmoptionNoArg, "True" },
1594 { "-xzab", "zippyAbort", XrmoptionNoArg, "False" },
1595 { "-zippyVariants", "zippyVariants", XrmoptionSepArg, NULL },
1596 { "-zippyMaxGames", "zippyMaxGames", XrmoptionSepArg, NULL },
1597 { "-zippyReplayTimeout", "zippyReplayTimeout", XrmoptionSepArg, NULL },
1598 { "-zippyShortGame", "zippyShortGame", XrmoptionSepArg, NULL },
1600 { "-flashCount", "flashCount", XrmoptionSepArg, NULL },
1601 { "-flash", "flashCount", XrmoptionNoArg, "3" },
1602 { "-xflash", "flashCount", XrmoptionNoArg, "0" },
1603 { "-flashRate", "flashRate", XrmoptionSepArg, NULL },
1604 { "-pixmapDirectory", "pixmapDirectory", XrmoptionSepArg, NULL },
1605 { "-msLoginDelay", "msLoginDelay", XrmoptionSepArg, NULL },
1606 { "-pixmap", "pixmapDirectory", XrmoptionSepArg, NULL },
1607 { "-colorizeMessages", "colorizeMessages", XrmoptionSepArg, NULL },
1608 { "-colorize", "colorizeMessages", XrmoptionNoArg, "True" },
1609 { "-xcolorize", "colorizeMessages", XrmoptionNoArg, "False" },
1610 { "-colorShout", "colorShout", XrmoptionSepArg, NULL },
1611 { "-colorSShout", "colorSShout", XrmoptionSepArg, NULL },
1612 { "-colorCShout", "colorSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1613 { "-colorChannel1", "colorChannel1", XrmoptionSepArg, NULL },
1614 { "-colorChannel", "colorChannel", XrmoptionSepArg, NULL },
1615 { "-colorKibitz", "colorKibitz", XrmoptionSepArg, NULL },
1616 { "-colorTell", "colorTell", XrmoptionSepArg, NULL },
1617 { "-colorChallenge", "colorChallenge", XrmoptionSepArg, NULL },
1618 { "-colorRequest", "colorRequest", XrmoptionSepArg, NULL },
1619 { "-colorSeek", "colorSeek", XrmoptionSepArg, NULL },
1620 { "-colorNormal", "colorNormal", XrmoptionSepArg, NULL },
1621 { "-soundProgram", "soundProgram", XrmoptionSepArg, NULL },
1622 { "-soundShout", "soundShout", XrmoptionSepArg, NULL },
1623 { "-soundSShout", "soundSShout", XrmoptionSepArg, NULL },
1624 { "-soundCShout", "soundSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1625 { "-soundChannel1", "soundChannel1", XrmoptionSepArg, NULL },
1626 { "-soundChannel", "soundChannel", XrmoptionSepArg, NULL },
1627 { "-soundKibitz", "soundKibitz", XrmoptionSepArg, NULL },
1628 { "-soundTell", "soundTell", XrmoptionSepArg, NULL },
1629 { "-soundChallenge", "soundChallenge", XrmoptionSepArg, NULL },
1630 { "-soundRequest", "soundRequest", XrmoptionSepArg, NULL },
1631 { "-soundSeek", "soundSeek", XrmoptionSepArg, NULL },
1632 { "-soundMove", "soundMove", XrmoptionSepArg, NULL },
1633 { "-soundIcsWin", "soundIcsWin", XrmoptionSepArg, NULL },
1634 { "-soundIcsLoss", "soundIcsLoss", XrmoptionSepArg, NULL },
1635 { "-soundIcsDraw", "soundIcsDraw", XrmoptionSepArg, NULL },
1636 { "-soundIcsUnfinished", "soundIcsUnfinished", XrmoptionSepArg, NULL },
1637 { "-soundIcsAlarm", "soundIcsAlarm", XrmoptionSepArg, NULL },
1638 { "-reuseFirst", "reuseFirst", XrmoptionSepArg, NULL },
1639 { "-reuseChessPrograms", "reuseFirst", XrmoptionSepArg, NULL }, /*compat*/
1640 { "-reuse", "reuseFirst", XrmoptionNoArg, "True" },
1641 { "-xreuse", "reuseFirst", XrmoptionNoArg, "False" },
1642 { "-reuseSecond", "reuseSecond", XrmoptionSepArg, NULL },
1643 { "-reuse2", "reuseSecond", XrmoptionNoArg, "True" },
1644 { "-xreuse2", "reuseSecond", XrmoptionNoArg, "False" },
1645 { "-animateMoving", "animateMoving", XrmoptionSepArg, NULL },
1646 { "-animate", "animateMoving", XrmoptionNoArg, "True" },
1647 { "-xanimate", "animateMoving", XrmoptionNoArg, "False" },
1648 { "-animateDragging", "animateDragging", XrmoptionSepArg, NULL },
1649 { "-drag", "animateDragging", XrmoptionNoArg, "True" },
1650 { "-xdrag", "animateDragging", XrmoptionNoArg, "False" },
1651 { "-animateSpeed", "animateSpeed", XrmoptionSepArg, NULL },
1652 { "-popupExitMessage", "popupExitMessage", XrmoptionSepArg, NULL },
1653 { "-exit", "popupExitMessage", XrmoptionNoArg, "True" },
1654 { "-xexit", "popupExitMessage", XrmoptionNoArg, "False" },
1655 { "-popupMoveErrors", "popupMoveErrors", XrmoptionSepArg, NULL },
1656 { "-popup", "popupMoveErrors", XrmoptionNoArg, "True" },
1657 { "-xpopup", "popupMoveErrors", XrmoptionNoArg, "False" },
1658 { "-fontSizeTolerance", "fontSizeTolerance", XrmoptionSepArg, NULL },
1659 { "-initialMode", "initialMode", XrmoptionSepArg, NULL },
1660 { "-mode", "initialMode", XrmoptionSepArg, NULL },
1661 { "-variant", "variant", XrmoptionSepArg, NULL },
1662 { "-firstProtocolVersion", "firstProtocolVersion", XrmoptionSepArg, NULL },
1663 { "-secondProtocolVersion","secondProtocolVersion",XrmoptionSepArg, NULL },
1664 { "-showButtonBar", "showButtonBar", XrmoptionSepArg, NULL },
1665 { "-buttons", "showButtonBar", XrmoptionNoArg, "True" },
1666 { "-xbuttons", "showButtonBar", XrmoptionNoArg, "False" },
1667 { "-lowTimeWarningColor", "lowTimeWarningColor", XrmoptionSepArg, NULL },
1668 { "-lowTimeWarning", "lowTimeWarning", XrmoptionSepArg, NULL },
1669 /* [AS,HR] New features */
1670 { "-firstScoreAbs", "firstScoreAbs", XrmoptionSepArg, NULL },
1671 { "-secondScoreAbs", "secondScoreAbs", XrmoptionSepArg, NULL },
1672 { "-pgnExtendedInfo", "pgnExtendedInfo", XrmoptionSepArg, NULL },
1673 { "-hideThinkingFromHuman", "hideThinkingFromHuman", XrmoptionSepArg, NULL },
1674 { "-adjudicateLossThreshold", "adjudicateLossThreshold", XrmoptionSepArg, NULL },
1675 { "-adjudicateDrawMoves", "adjudicateDrawMoves", XrmoptionSepArg, NULL },
1676 { "-pgnEventHeader", "pgnEventHeader", XrmoptionSepArg, NULL },
1677 { "-firstIsUCI", "firstIsUCI", XrmoptionSepArg, NULL },
1678 { "-secondIsUCI", "secondIsUCI", XrmoptionSepArg, NULL },
1679 { "-fUCI", "firstIsUCI", XrmoptionNoArg, "True" },
1680 { "-sUCI", "secondIsUCI", XrmoptionNoArg, "True" },
1681 { "-firstHasOwnBookUCI", "firstHasOwnBookUCI", XrmoptionSepArg, NULL },
1682 { "-secondHasOwnBookUCI", "secondHasOwnBookUCI", XrmoptionSepArg, NULL },
1683 { "-fNoOwnBookUCI", "firstHasOwnBookUCI", XrmoptionNoArg, "False" },
1684 { "-sNoOwnBookUCI", "secondHasOwnBookUCI", XrmoptionNoArg, "False" },
1685 { "-firstXBook", "firstHasOwnBookUCI", XrmoptionNoArg, "False" },
1686 { "-secondXBook", "secondHasOwnBookUCI", XrmoptionNoArg, "False" },
1687 { "-polyglotDir", "polyglotDir", XrmoptionSepArg, NULL },
1688 { "-usePolyglotBook", "usePolyglotBook", XrmoptionSepArg, NULL },
1689 { "-polyglotBook", "polyglotBook", XrmoptionSepArg, NULL },
1690 { "-defaultHashSize", "defaultHashSize", XrmoptionSepArg, NULL },
1691 { "-defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XrmoptionSepArg, NULL },
1692 { "-defaultPathEGTB", "defaultPathEGTB", XrmoptionSepArg, NULL },
1693 { "-defaultFrcPosition", "defaultFrcPosition", XrmoptionSepArg, NULL },
1694 { "-gameListTags", "gameListTags", XrmoptionSepArg, NULL },
1695 // [HGM] I am sure AS added many more options, but we have to fish them out, from the list in winboard.c
1697 /* [HGM,HR] User-selectable board size */
1698 { "-boardWidth", "boardWidth", XrmoptionSepArg, NULL },
1699 { "-boardHeight", "boardHeight", XrmoptionSepArg, NULL },
1700 { "-matchPause", "matchPause", XrmoptionSepArg, NULL },
1702 /* [HGM] new arguments of 4.3.xx. All except first three are back-end options, which should work immediately */
1703 { "-holdingsSize", "holdingsSize", XrmoptionSepArg, NULL }, // requires extensive front-end changes to work
1704 { "-flipBlack", "flipBlack", XrmoptionSepArg, NULL }, // requires front-end changes to work
1705 { "-allWhite", "allWhite", XrmoptionSepArg, NULL }, // requires front-end changes to work
1706 { "-pieceToCharTable", "pieceToCharTable", XrmoptionSepArg, NULL },
1707 { "-alphaRank", "alphaRank", XrmoptionSepArg, NULL },
1708 { "-testClaims", "testClaims", XrmoptionSepArg, NULL },
1709 { "-checkMates", "checkMates", XrmoptionSepArg, NULL },
1710 { "-materialDraws", "materialDraws", XrmoptionSepArg, NULL },
1711 { "-trivialDraws", "trivialDraws", XrmoptionSepArg, NULL },
1712 { "-ruleMoves", "ruleMoves", XrmoptionSepArg, NULL },
1713 { "-repeatsToDraw", "repeatsToDraw", XrmoptionSepArg, NULL },
1714 { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL },
1715 { "-userName", "userName", XrmoptionSepArg, NULL },
1716 { "-autoKibitz", "autoKibitz", XrmoptionNoArg, "True" },
1717 { "-firstTimeOdds", "firstTimeOdds", XrmoptionSepArg, NULL },
1718 { "-secondTimeOdds", "secondTimeOdds", XrmoptionSepArg, NULL },
1719 { "-timeOddsMode", "timeOddsMode", XrmoptionSepArg, NULL },
1720 { "-firstAccumulateTC", "firstAccumulateTC", XrmoptionSepArg, NULL },
1721 { "-secondAccumulateTC", "secondAccumulateTC", XrmoptionSepArg, NULL },
1722 { "-firstNPS", "firstNPS", XrmoptionSepArg, NULL },
1723 { "-secondNPS", "secondNPS", XrmoptionSepArg, NULL },
1724 { "-serverMoves", "serverMoves", XrmoptionSepArg, NULL },
1725 { "-serverPause", "serverPause", XrmoptionSepArg, NULL },
1726 { "-suppressLoadMoves", "suppressLoadMoves", XrmoptionSepArg, NULL },
1727 { "-egtFormats", "egtFormats", XrmoptionSepArg, NULL },
1728 { "-userName", "userName", XrmoptionSepArg, NULL },
1729 { "-smpCores", "smpCores", XrmoptionSepArg, NULL },
1730 { "-sameColorGames", "sameColorGames", XrmoptionSepArg, NULL },
1731 { "-rewindIndex", "rewindIndex", XrmoptionSepArg, NULL },
1732 { "-niceEngines", "niceEngines", XrmoptionSepArg, NULL },
1733 { "-delayBeforeQuit", "delayBeforeQuit", XrmoptionSepArg, NULL },
1734 { "-delayAfterQuit", "delayAfterQuit", XrmoptionSepArg, NULL },
1735 { "-nameOfDebugFile", "nameOfDebugFile", XrmoptionSepArg, NULL },
1736 { "-debugFile", "nameOfDebugFile", XrmoptionSepArg, NULL },
1737 { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL },
1738 { "-noGUI", "noGUI", XrmoptionNoArg, "True" },
1739 { "-firstOptions", "firstOptions", XrmoptionSepArg, NULL },
1740 { "-secondOptions", "secondOptions", XrmoptionSepArg, NULL },
1741 { "-firstNeedsNoncompliantFEN", "firstNeedsNoncompliantFEN", XrmoptionSepArg, NULL },
1742 { "-secondNeedsNoncompliantFEN", "secondNeedsNoncompliantFEN", XrmoptionSepArg, NULL },
1743 { "-keepAlive", "keepAlive", XrmoptionSepArg, NULL },
1744 { "-forceIllegalMoves", "forceIllegalMoves", XrmoptionNoArg, "True" },
1745 { "-keepLineBreaksICS", "keepLineBreaksICS", XrmoptionSepArg, NULL },
1746 { "-wrapContinuationSequence", "wrapContinuationSequence", XrmoptionSepArg, NULL },
1747 { "-useInternalWrap", "useInternalWrap", XrmoptionSepArg, NULL },
1750 XtActionsRec boardActions[] = {
1751 { "HandleUserMove", HandleUserMove },
1752 { "AnimateUserMove", AnimateUserMove },
1753 // { "FileNameAction", FileNameAction },
1754 { "AskQuestionProc", AskQuestionProc },
1755 { "AskQuestionReplyAction", AskQuestionReplyAction },
1756 { "PieceMenuPopup", PieceMenuPopup },
1757 // { "WhiteClock", WhiteClock },
1758 // { "BlackClock", BlackClock },
1759 { "Iconify", Iconify },
1760 { "LoadSelectedProc", LoadSelectedProc },
1761 // { "LoadPositionProc", LoadPositionProc },
1762 // { "LoadNextPositionProc", LoadNextPositionProc },
1763 // { "LoadPrevPositionProc", LoadPrevPositionProc },
1764 // { "ReloadPositionProc", ReloadPositionProc },
1765 { "CopyPositionProc", CopyPositionProc },
1766 { "PastePositionProc", PastePositionProc },
1767 { "CopyGameProc", CopyGameProc },
1768 { "PasteGameProc", PasteGameProc },
1769 // { "SaveGameProc", SaveGameProc },
1770 // { "SavePositionProc", SavePositionProc },
1771 { "MailMoveProc", MailMoveProc },
1772 { "ReloadCmailMsgProc", ReloadCmailMsgProc },
1773 // { "MachineWhiteProc", MachineWhiteProc },
1774 // { "MachineBlackProc", MachineBlackProc },
1775 { "AnalysisModeProc", AnalyzeModeProc },
1776 // { "AnalyzeFileProc", AnalyzeFileProc },
1777 // { "TwoMachinesProc", TwoMachinesProc },
1778 // { "IcsClientProc", IcsClientProc },
1779 { "EditGameProc", EditGameProc },
1780 { "EditPositionProc", EditPositionProc },
1781 { "TrainingProc", EditPositionProc },
1782 { "EngineOutputProc", EngineOutputProc}, // [HGM] Winboard_x engine-output window
1783 { "ShowGameListProc", ShowGameListProc },
1784 // { "ShowMoveListProc", HistoryShowProc},
1785 // { "EditTagsProc", EditCommentProc },
1786 { "EditCommentProc", EditCommentProc },
1787 // { "IcsAlarmProc", IcsAlarmProc },
1788 { "IcsInputBoxProc", IcsInputBoxProc },
1789 // { "AcceptProc", AcceptProc },
1790 // { "DeclineProc", DeclineProc },
1791 // { "RematchProc", RematchProc },
1792 // { "CallFlagProc", CallFlagProc },
1793 // { "DrawProc", DrawProc },
1794 // { "AdjournProc", AdjournProc },
1795 // { "AbortProc", AbortProc },
1796 // { "ResignProc", ResignProc },
1797 // { "AdjuWhiteProc", AdjuWhiteProc },
1798 // { "AdjuBlackProc", AdjuBlackProc },
1799 // { "AdjuDrawProc", AdjuDrawProc },
1800 { "EnterKeyProc", EnterKeyProc },
1801 // { "StopObservingProc", StopObservingProc },
1802 // { "StopExaminingProc", StopExaminingProc },
1803 // { "BackwardProc", BackwardProc },
1804 // { "ForwardProc", ForwardProc },
1805 // { "ToStartProc", ToStartProc },
1806 // { "ToEndProc", ToEndProc },
1807 // { "RevertProc", RevertProc },
1808 // { "TruncateGameProc", TruncateGameProc },
1809 // { "MoveNowProc", MoveNowProc },
1810 // { "RetractMoveProc", RetractMoveProc },
1811 // { "AlwaysQueenProc", AlwaysQueenProc },
1812 // { "AnimateDraggingProc", AnimateDraggingProc },
1813 // { "AnimateMovingProc", AnimateMovingProc },
1814 // { "AutoflagProc", AutoflagProc },
1815 // { "AutoflipProc", AutoflipProc },
1816 // { "AutobsProc", AutobsProc },
1817 // { "AutoraiseProc", AutoraiseProc },
1818 // { "AutosaveProc", AutosaveProc },
1819 // { "BlindfoldProc", BlindfoldProc },
1820 // { "FlashMovesProc", FlashMovesProc },
1821 // { "FlipViewProc", FlipViewProc },
1822 // { "GetMoveListProc", GetMoveListProc },
1824 // { "HighlightDraggingProc", HighlightDraggingProc },
1826 // { "HighlightLastMoveProc", HighlightLastMoveProc },
1827 // { "IcsAlarmProc", IcsAlarmProc },
1828 // { "MoveSoundProc", MoveSoundProc },
1829 // { "OldSaveStyleProc", OldSaveStyleProc },
1830 // { "PeriodicUpdatesProc", PeriodicUpdatesProc },
1831 { "PonderNextMoveProc", PonderNextMoveProc },
1832 { "PopupExitMessageProc", PopupExitMessageProc },
1833 { "PopupMoveErrorsProc", PopupMoveErrorsProc },
1834 { "PremoveProc", PremoveProc },
1835 { "QuietPlayProc", QuietPlayProc },
1836 // { "ShowThinkingProc", ShowThinkingProc },
1837 // { "HideThinkingProc", HideThinkingProc },
1838 { "TestLegalityProc", TestLegalityProc },
1839 // { "InfoProc", InfoProc },
1840 // { "ManProc", ManProc },
1841 // { "HintProc", HintProc },
1842 // { "BookProc", BookProc },
1843 { "AboutGameProc", AboutGameProc },
1844 { "DebugProc", DebugProc },
1845 { "NothingProc", NothingProc },
1846 { "CommentPopDown", (XtActionProc) CommentPopDown },
1847 { "EditCommentPopDown", (XtActionProc) EditCommentPopDown },
1848 { "TagsPopDown", (XtActionProc) TagsPopDown },
1849 { "ErrorPopDown", (XtActionProc) ErrorPopDown },
1850 { "ICSInputBoxPopDown", (XtActionProc) ICSInputBoxPopDown },
1851 // { "FileNamePopDown", (XtActionProc) FileNamePopDown },
1852 { "AskQuestionPopDown", (XtActionProc) AskQuestionPopDown },
1853 { "GameListPopDown", (XtActionProc) GameListPopDown },
1854 { "PromotionPopDown", (XtActionProc) PromotionPopDown },
1855 // { "HistoryPopDown", (XtActionProc) HistoryPopDown },
1856 { "EngineOutputPopDown", (XtActionProc) EngineOutputPopDown },
1857 { "ShufflePopDown", (XtActionProc) ShufflePopDown },
1858 { "EnginePopDown", (XtActionProc) EnginePopDown },
1859 { "UciPopDown", (XtActionProc) UciPopDown },
1860 { "TimeControlPopDown", (XtActionProc) TimeControlPopDown },
1861 { "NewVariantPopDown", (XtActionProc) NewVariantPopDown },
1862 { "SettingsPopDown", (XtActionProc) SettingsPopDown },
1866 char ICSInputTranslations[] =
1867 "<Key>Return: EnterKeyProc() \n";
1869 String xboardResources[] = {
1870 // "*fileName*value.translations: #override\\n <Key>Return: FileNameAction()",
1871 "*question*value.translations: #override\\n <Key>Return: AskQuestionReplyAction()",
1872 "*errorpopup*translations: #override\\n <Key>Return: ErrorPopDown()",
1876 static char *cnames[9] = { "black", "red", "green", "yellow", "blue",
1877 "magenta", "cyan", "white" };
1881 TextColors textColors[(int)NColorClasses];
1883 /* String is: "fg, bg, attr". Which is 0, 1, 2 */
1885 parse_color(str, which)
1889 char *p, buf[100], *d;
1892 if (strlen(str) > 99) /* watch bounds on buf */
1897 for (i=0; i<which; ++i) {
1904 /* Could be looking at something like:
1906 .. in which case we want to stop on a comma also */
1907 while (*p && *p != ',' && !isalpha(*p) && !isdigit(*p))
1911 return -1; /* Use default for empty field */
1914 if (which == 2 || isdigit(*p))
1917 while (*p && isalpha(*p))
1922 for (i=0; i<8; ++i) {
1923 if (!StrCaseCmp(buf, cnames[i]))
1924 return which? (i+40) : (i+30);
1926 if (!StrCaseCmp(buf, "default")) return -1;
1928 fprintf(stderr, _("%s: unrecognized color %s\n"), programName, buf);
1933 parse_cpair(cc, str)
1937 if ((textColors[(int)cc].fg=parse_color(str, 0)) == -2) {
1938 fprintf(stderr, _("%s: can't parse foreground color in `%s'\n"),
1943 /* bg and attr are optional */
1944 textColors[(int)cc].bg = parse_color(str, 1);
1945 if ((textColors[(int)cc].attr = parse_color(str, 2)) < 0) {
1946 textColors[(int)cc].attr = 0;
1952 /* Arrange to catch delete-window events */
1953 Atom wm_delete_window;
1955 CatchDeleteWindow(Widget w, String procname)
1958 XSetWMProtocols(xDisplay, XtWindow(w), &wm_delete_window, 1);
1959 snprintf(buf, sizeof(buf), "<Message>WM_PROTOCOLS: %s() \n", procname);
1960 XtAugmentTranslations(w, XtParseTranslationTable(buf));
1966 /* this should raise the board to the top */
1967 gtk_window_present(GTK_WINDOW(GUI_Window));
1971 #define BoardSize int
1972 void InitDrawingSizes(BoardSize boardSize, int flags)
1973 { // [HGM] resize is functional now, but for board format changes only (nr of ranks, files)
1974 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
1976 XtGeometryResult gres;
1979 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
1980 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
1982 timerWidth = (boardWidth - sep) / 2;
1984 if (appData.titleInWindow)
1989 w = boardWidth - 2*bor;
1993 w = boardWidth - w - sep - 2*bor - 2; // WIDTH_FUDGE
1997 if(!formWidget) return;
2000 * Inhibit shell resizing.
2003 // [HGM] pieces: tailor piece bitmaps to needs of specific variant
2006 for(i=0; i<4; i++) {
2008 for(p=0; p<=(int)WhiteKing; p++)
2009 xpmPieceBitmap[i][p] = xpmPieceBitmap2[i][p]; // defaults
2010 if(gameInfo.variant == VariantShogi) {
2011 xpmPieceBitmap[i][(int)WhiteCannon] = xpmPieceBitmap2[i][(int)WhiteKing+1];
2012 xpmPieceBitmap[i][(int)WhiteNightrider] = xpmPieceBitmap2[i][(int)WhiteKing+2];
2013 xpmPieceBitmap[i][(int)WhiteSilver] = xpmPieceBitmap2[i][(int)WhiteKing+3];
2014 xpmPieceBitmap[i][(int)WhiteGrasshopper] = xpmPieceBitmap2[i][(int)WhiteKing+4];
2015 xpmPieceBitmap[i][(int)WhiteQueen] = xpmPieceBitmap2[i][(int)WhiteLance];
2018 if(gameInfo.variant == VariantGothic) {
2019 xpmPieceBitmap[i][(int)WhiteMarshall] = xpmPieceBitmap2[i][(int)WhiteSilver];
2023 // [HGM] why are thee ximMasks used at all? the ximPieceBitmaps seem to be never used!
2024 for(p=0; p<=(int)WhiteKing; p++)
2025 ximMaskPm[p] = ximMaskPm2[p]; // defaults
2026 if(gameInfo.variant == VariantShogi) {
2027 ximMaskPm[(int)WhiteCannon] = ximMaskPm2[(int)WhiteKing+1];
2028 ximMaskPm[(int)WhiteNightrider] = ximMaskPm2[(int)WhiteKing+2];
2029 ximMaskPm[(int)WhiteSilver] = ximMaskPm2[(int)WhiteKing+3];
2030 ximMaskPm[(int)WhiteGrasshopper] = ximMaskPm2[(int)WhiteKing+4];
2031 ximMaskPm[(int)WhiteQueen] = ximMaskPm2[(int)WhiteLance];
2034 if(gameInfo.variant == VariantGothic) {
2035 ximMaskPm[(int)WhiteMarshall] = ximMaskPm2[(int)WhiteSilver];
2041 for(i=0; i<2; i++) {
2043 for(p=0; p<=(int)WhiteKing; p++)
2044 pieceBitmap[i][p] = pieceBitmap2[i][p]; // defaults
2045 if(gameInfo.variant == VariantShogi) {
2046 pieceBitmap[i][(int)WhiteCannon] = pieceBitmap2[i][(int)WhiteKing+1];
2047 pieceBitmap[i][(int)WhiteNightrider] = pieceBitmap2[i][(int)WhiteKing+2];
2048 pieceBitmap[i][(int)WhiteSilver] = pieceBitmap2[i][(int)WhiteKing+3];
2049 pieceBitmap[i][(int)WhiteGrasshopper] = pieceBitmap2[i][(int)WhiteKing+4];
2050 pieceBitmap[i][(int)WhiteQueen] = pieceBitmap2[i][(int)WhiteLance];
2053 if(gameInfo.variant == VariantGothic) {
2054 pieceBitmap[i][(int)WhiteMarshall] = pieceBitmap2[i][(int)WhiteSilver];
2064 void EscapeExpand(char *p, char *q)
2065 { // [HGM] initstring: routine to shape up string arguments
2066 while(*p++ = *q++) if(p[-1] == '\\')
2068 case 'n': p[-1] = '\n'; break;
2069 case 'r': p[-1] = '\r'; break;
2070 case 't': p[-1] = '\t'; break;
2071 case '\\': p[-1] = '\\'; break;
2072 case 0: *p = 0; return;
2073 default: p[-1] = q[-1]; break;
2082 int i, j, clockFontPxlSize, coordFontPxlSize, fontPxlSize;
2083 XSetWindowAttributes window_attributes;
2085 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
2086 XrmValue vFrom, vTo;
2087 XtGeometryResult gres;
2090 int forceMono = False;
2094 // [HGM] before anything else, expand any indirection files amongst options
2095 char *argvCopy[1000]; // 1000 seems enough
2096 char newArgs[10000]; // holds actual characters
2099 srandom(time(0)); // [HGM] book: make random truly random
2102 for(i=0; i<argc; i++) {
2103 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2104 //fprintf(stderr, "arg %s\n", argv[i]);
2105 if(argv[i][0] != '@') argvCopy[j++] = argv[i]; else {
2107 FILE *f = fopen(argv[i]+1, "rb");
2108 if(f == NULL) { fprintf(stderr, _("ignore %s\n"), argv[i]); continue; } // do not expand non-existing
2109 argvCopy[j++] = newArgs + k; // get ready for first argument from file
2110 while((c = fgetc(f)) != EOF) { // each line of file inserts 1 argument in the list
2112 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2113 newArgs[k++] = 0; // terminate current arg
2114 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2115 argvCopy[j++] = newArgs + k; // get ready for next
2117 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2131 setbuf(stdout, NULL);
2132 setbuf(stderr, NULL);
2135 programName = strrchr(argv[0], '/');
2136 if (programName == NULL)
2137 programName = argv[0];
2142 XtSetLanguageProc(NULL, NULL, NULL);
2143 bindtextdomain(PACKAGE, LOCALEDIR);
2144 textdomain(PACKAGE);
2148 XtAppInitialize(&appContext, "XBoard", shellOptions,
2149 XtNumber(shellOptions),
2150 &argc, argv, xboardResources, NULL, 0);
2153 gtk_init (&argc, &argv);
2155 /* parse glade file to build widgets */
2157 builder = gtk_builder_new ();
2158 gtk_builder_add_from_file (builder, "gtk-interface.xml", NULL);
2160 /* test if everything worked ok */
2162 GUI_Window = GTK_WIDGET (gtk_builder_get_object (builder, "MainWindow"));
2163 if(!GUI_Window) printf("Error: gtk_builder didn't work!\n");
2165 GUI_Aspect = GTK_WIDGET (gtk_builder_get_object (builder, "Aspectframe"));
2166 if(!GUI_Aspect) printf("Error: gtk_builder didn't work!\n");
2168 GUI_History = GTK_WIDGET (gtk_builder_get_object (builder, "MoveHistory"));
2169 if(!GUI_History) printf("Error: gtk_builder didn't work!\n");
2171 GUI_Menubar = GTK_WIDGET (gtk_builder_get_object (builder, "MenuBar"));
2172 if(!GUI_Menubar) printf("Error: gtk_builder didn't work!\n");
2173 GUI_Timer = GTK_WIDGET (gtk_builder_get_object (builder, "Timer"));
2174 if(!GUI_Timer) printf("Error: gtk_builder didn't work!\n");
2175 GUI_Buttonbar = GTK_WIDGET (gtk_builder_get_object (builder, "ButtonBar"));
2176 if(!GUI_Buttonbar) printf("Error: gtk_builder didn't work!\n");
2177 GUI_Board = GTK_WIDGET (gtk_builder_get_object (builder, "Board"));
2178 if(!GUI_Board) printf("Error: gtk_builder didn't work!\n");
2180 GUI_Whiteclock = GTK_WIDGET (gtk_builder_get_object (builder, "WhiteClock"));
2181 if(!GUI_Whiteclock) printf("Error: gtk_builder didn't work!\n");
2183 GUI_Blackclock = GTK_WIDGET (gtk_builder_get_object (builder, "BlackClock"));
2184 if(!GUI_Blackclock) printf("Error: gtk_builder didn't work!\n");
2186 LIST_MoveHistory = GTK_LIST_STORE (gtk_builder_get_object (builder, "MoveHistoryStore"));
2187 if(!LIST_MoveHistory) printf("Error: gtk_builder didn't work!\n");
2189 /* EditTags window */
2190 GUI_EditTags = GTK_WIDGET (gtk_builder_get_object (builder, "EditTags"));
2191 if(!GUI_EditTags) printf("Error: gtk_builder didn't work!\n");
2193 GUI_EditTagsTextArea = GTK_WIDGET (gtk_builder_get_object (builder, "EditTagsTextArea"));
2194 if(!GUI_EditTagsTextArea) printf("Error: gtk_builder didn't work!\n");
2197 gtk_builder_connect_signals (builder, NULL);
2199 // don't unref the builder, since we use it to get references to widgets
2200 // g_object_unref (G_OBJECT (builder));
2202 /* end parse glade file */
2206 fprintf(stderr, _("%s: unrecognized argument %s\n"),
2207 programName, argv[1]);
2209 fprintf(stderr, "Recognized options:\n");
2210 for(i = 0; i < XtNumber(shellOptions); i++)
2212 /* print first column */
2213 j = fprintf(stderr, " %s%s", shellOptions[i].option,
2214 (shellOptions[i].argKind == XrmoptionSepArg
2216 /* print second column and end line */
2217 if (++i < XtNumber(shellOptions))
2219 fprintf(stderr, "%*c%s%s\n", 40 - j, ' ',
2220 shellOptions[i].option,
2221 (shellOptions[i].argKind == XrmoptionSepArg
2226 fprintf(stderr, "\n");
2233 if (p == NULL) p = "/tmp";
2234 i = strlen(p) + strlen("/.xboardXXXXXx.pgn") + 1;
2235 gameCopyFilename = (char*) malloc(i);
2236 gamePasteFilename = (char*) malloc(i);
2237 snprintf(gameCopyFilename,i, "%s/.xboard%05uc.pgn", p, getpid());
2238 snprintf(gamePasteFilename,i, "%s/.xboard%05up.pgn", p, getpid());
2240 XtGetApplicationResources(shellWidget, (XtPointer) &appData,
2241 clientResources, XtNumber(clientResources),
2244 { // [HGM] initstring: kludge to fix bad bug. expand '\n' characters in init string and computer string.
2245 static char buf[MSG_SIZ];
2246 EscapeExpand(buf, appData.initString);
2247 appData.initString = strdup(buf);
2248 EscapeExpand(buf, appData.secondInitString);
2249 appData.secondInitString = strdup(buf);
2250 EscapeExpand(buf, appData.firstComputerString);
2251 appData.firstComputerString = strdup(buf);
2252 EscapeExpand(buf, appData.secondComputerString);
2253 appData.secondComputerString = strdup(buf);
2256 if ((chessDir = (char *) getenv("CHESSDIR")) == NULL) {
2259 if (chdir(chessDir) != 0) {
2260 fprintf(stderr, _("%s: can't cd to CHESSDIR: "), programName);
2266 if (appData.debugMode && appData.nameOfDebugFile && strcmp(appData.nameOfDebugFile, "stderr")) {
2267 /* [DM] debug info to file [HGM] make the filename a command-line option, and allow it to remain stderr */
2268 if ((debugFP = fopen(appData.nameOfDebugFile, "w")) == NULL) {
2269 printf(_("Failed to open file '%s'\n"), appData.nameOfDebugFile);
2272 setbuf(debugFP, NULL);
2275 /* [HGM,HR] make sure board size is acceptable */
2276 if(appData.NrFiles > BOARD_SIZE ||
2277 appData.NrRanks > BOARD_SIZE )
2278 DisplayFatalError(_("Recompile with BOARD_SIZE > 12, to support this size"), 0, 2);
2281 /* This feature does not work; animation needs a rewrite */
2282 appData.highlightDragging = FALSE;
2286 xDisplay = XtDisplay(shellWidget);
2287 xScreen = DefaultScreen(xDisplay);
2288 wm_delete_window = XInternAtom(xDisplay, "WM_DELETE_WINDOW", True);
2290 gameInfo.variant = StringToVariant(appData.variant);
2291 InitPosition(FALSE);
2293 /* calc board size */
2294 if (isdigit(appData.boardSize[0]))
2296 i = sscanf(appData.boardSize, "%d,%d,%d,%d,%d,%d,%d", &squareSize,
2297 &lineGap, &clockFontPxlSize, &coordFontPxlSize,
2298 &fontPxlSize, &smallLayout, &tinyLayout);
2301 fprintf(stderr, _("%s: bad boardSize syntax %s\n"),
2302 programName, appData.boardSize);
2307 /* Find some defaults; use the nearest known size */
2308 SizeDefaults *szd, *nearest;
2309 int distance = 99999;
2310 nearest = szd = sizeDefaults;
2311 while (szd->name != NULL)
2313 if (abs(szd->squareSize - squareSize) < distance)
2316 distance = abs(szd->squareSize - squareSize);
2317 if (distance == 0) break;
2321 if (i < 2) lineGap = nearest->lineGap;
2322 if (i < 3) clockFontPxlSize = nearest->clockFontPxlSize;
2323 if (i < 4) coordFontPxlSize = nearest->coordFontPxlSize;
2324 if (i < 5) fontPxlSize = nearest->fontPxlSize;
2325 if (i < 6) smallLayout = nearest->smallLayout;
2326 if (i < 7) tinyLayout = nearest->tinyLayout;
2331 SizeDefaults *szd = sizeDefaults;
2332 if (*appData.boardSize == NULLCHAR)
2334 while (DisplayWidth(xDisplay, xScreen) < szd->minScreenSize
2335 || DisplayHeight(xDisplay, xScreen) < szd->minScreenSize)
2339 if (szd->name == NULL) szd--;
2343 while (szd->name != NULL
2344 && StrCaseCmp(szd->name, appData.boardSize) != 0)
2346 if (szd->name == NULL)
2348 fprintf(stderr, _("%s: unrecognized boardSize name %s\n"),
2349 programName, appData.boardSize);
2353 squareSize = szd->squareSize;
2354 lineGap = szd->lineGap;
2355 clockFontPxlSize = szd->clockFontPxlSize;
2356 coordFontPxlSize = szd->coordFontPxlSize;
2357 fontPxlSize = szd->fontPxlSize;
2358 smallLayout = szd->smallLayout;
2359 tinyLayout = szd->tinyLayout;
2361 /* end figuring out what size to use */
2363 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2364 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2367 * Determine what fonts to use.
2369 appData.clockFont = FindFont(appData.clockFont, clockFontPxlSize);
2370 clockFontID = XLoadFont(xDisplay, appData.clockFont);
2371 clockFontStruct = XQueryFont(xDisplay, clockFontID);
2372 appData.coordFont = FindFont(appData.coordFont, coordFontPxlSize);
2373 coordFontID = XLoadFont(xDisplay, appData.coordFont);
2374 coordFontStruct = XQueryFont(xDisplay, coordFontID);
2375 appData.font = FindFont(appData.font, fontPxlSize);
2376 countFontID = XLoadFont(xDisplay, appData.coordFont); // [HGM] holdings
2377 countFontStruct = XQueryFont(xDisplay, countFontID);
2378 // appData.font = FindFont(appData.font, fontPxlSize);
2380 xdb = XtDatabase(xDisplay);
2381 XrmPutStringResource(&xdb, "*font", appData.font);
2384 * Detect if there are not enough colors available and adapt.
2386 if (DefaultDepth(xDisplay, xScreen) <= 2) {
2387 appData.monoMode = True;
2390 if (!appData.monoMode) {
2391 vFrom.addr = (caddr_t) appData.lightSquareColor;
2392 vFrom.size = strlen(appData.lightSquareColor);
2393 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2394 if (vTo.addr == NULL) {
2395 appData.monoMode = True;
2398 lightSquareColor = *(Pixel *) vTo.addr;
2401 if (!appData.monoMode) {
2402 vFrom.addr = (caddr_t) appData.darkSquareColor;
2403 vFrom.size = strlen(appData.darkSquareColor);
2404 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2405 if (vTo.addr == NULL) {
2406 appData.monoMode = True;
2409 darkSquareColor = *(Pixel *) vTo.addr;
2412 if (!appData.monoMode) {
2413 vFrom.addr = (caddr_t) appData.whitePieceColor;
2414 vFrom.size = strlen(appData.whitePieceColor);
2415 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2416 if (vTo.addr == NULL) {
2417 appData.monoMode = True;
2420 whitePieceColor = *(Pixel *) vTo.addr;
2423 if (!appData.monoMode) {
2424 vFrom.addr = (caddr_t) appData.blackPieceColor;
2425 vFrom.size = strlen(appData.blackPieceColor);
2426 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2427 if (vTo.addr == NULL) {
2428 appData.monoMode = True;
2431 blackPieceColor = *(Pixel *) vTo.addr;
2435 if (!appData.monoMode) {
2436 vFrom.addr = (caddr_t) appData.highlightSquareColor;
2437 vFrom.size = strlen(appData.highlightSquareColor);
2438 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2439 if (vTo.addr == NULL) {
2440 appData.monoMode = True;
2443 highlightSquareColor = *(Pixel *) vTo.addr;
2447 if (!appData.monoMode) {
2448 vFrom.addr = (caddr_t) appData.premoveHighlightColor;
2449 vFrom.size = strlen(appData.premoveHighlightColor);
2450 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2451 if (vTo.addr == NULL) {
2452 appData.monoMode = True;
2455 premoveHighlightColor = *(Pixel *) vTo.addr;
2460 fprintf(stderr, _("%s: too few colors available; trying monochrome mode\n"),
2463 if (appData.bitmapDirectory == NULL ||
2464 appData.bitmapDirectory[0] == NULLCHAR)
2465 appData.bitmapDirectory = DEF_BITMAP_DIR;
2468 if (appData.lowTimeWarning && !appData.monoMode) {
2469 vFrom.addr = (caddr_t) appData.lowTimeWarningColor;
2470 vFrom.size = strlen(appData.lowTimeWarningColor);
2471 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2472 if (vTo.addr == NULL)
2473 appData.monoMode = True;
2475 lowTimeWarningColor = *(Pixel *) vTo.addr;
2478 if (appData.monoMode && appData.debugMode) {
2479 fprintf(stderr, _("white pixel = 0x%lx, black pixel = 0x%lx\n"),
2480 (unsigned long) XWhitePixel(xDisplay, xScreen),
2481 (unsigned long) XBlackPixel(xDisplay, xScreen));
2484 if (parse_cpair(ColorShout, appData.colorShout) < 0 ||
2485 parse_cpair(ColorSShout, appData.colorSShout) < 0 ||
2486 parse_cpair(ColorChannel1, appData.colorChannel1) < 0 ||
2487 parse_cpair(ColorChannel, appData.colorChannel) < 0 ||
2488 parse_cpair(ColorKibitz, appData.colorKibitz) < 0 ||
2489 parse_cpair(ColorTell, appData.colorTell) < 0 ||
2490 parse_cpair(ColorChallenge, appData.colorChallenge) < 0 ||
2491 parse_cpair(ColorRequest, appData.colorRequest) < 0 ||
2492 parse_cpair(ColorSeek, appData.colorSeek) < 0 ||
2493 parse_cpair(ColorNormal, appData.colorNormal) < 0)
2495 if (appData.colorize) {
2497 _("%s: can't parse color names; disabling colorization\n"),
2500 appData.colorize = FALSE;
2502 textColors[ColorNone].fg = textColors[ColorNone].bg = -1;
2503 textColors[ColorNone].attr = 0;
2505 // XtAppAddActions(appContext, boardActions, XtNumber(boardActions));
2511 layoutName = "tinyLayout";
2512 } else if (smallLayout) {
2513 layoutName = "smallLayout";
2515 layoutName = "normalLayout";
2518 if (appData.titleInWindow) {
2519 /* todo check what this appdata does */
2522 if (appData.showButtonBar) {
2523 /* TODO hide button bar if requested */
2527 if (appData.titleInWindow)
2532 if (appData.showButtonBar)
2539 if (appData.showButtonBar)
2549 /* set some checkboxes in the menu according to appData */
2551 if (appData.alwaysPromoteToQueen)
2552 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Always Queen")),TRUE);
2554 if (appData.animateDragging)
2555 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Animate Dragging")),TRUE);
2557 if (appData.animate)
2558 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Animate Moving")),TRUE);
2560 if (appData.autoComment)
2561 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Comment")),TRUE);
2563 if (appData.autoCallFlag)
2564 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Flag")),TRUE);
2566 if (appData.autoFlipView)
2567 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Flip View")),TRUE);
2569 if (appData.autoObserve)
2570 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Observe")),TRUE);
2572 if (appData.autoRaiseBoard)
2573 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Raise Board")),TRUE);
2575 if (appData.autoSaveGames)
2576 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Save")),TRUE);
2578 if (appData.saveGameFile[0] != NULLCHAR)
2580 /* Can't turn this off from menu */
2581 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Save")),TRUE);
2582 gtk_action_set_sensitive(GTK_ACTION (gtk_builder_get_object (builder, "menuOptions.Auto Save")),FALSE);
2585 if (appData.blindfold)
2586 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Blindfold")),TRUE);
2588 if (appData.flashCount > 0)
2589 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Flash Moves")),TRUE);
2591 if (appData.getMoveList)
2592 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Get Move List")),TRUE);
2595 if (appData.highlightDragging)
2596 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Highlight Dragging")),TRUE);
2599 if (appData.highlightLastMove)
2600 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Highlight Last Move")),TRUE);
2602 if (appData.icsAlarm)
2603 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.ICS Alarm")),TRUE);
2605 if (appData.ringBellAfterMoves)
2606 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Move Sound")),TRUE);
2608 if (appData.oldSaveStyle)
2609 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Old Save Style")),TRUE);
2611 if (appData.periodicUpdates)
2612 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Periodic Updates")),TRUE);
2614 if (appData.ponderNextMove)
2615 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Ponder Next Move")),TRUE);
2617 if (appData.popupExitMessage)
2618 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Popup Exit Message")),TRUE);
2620 if (appData.popupMoveErrors)
2621 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Popup Move Errors")),TRUE);
2623 if (appData.premove)
2624 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Premove")),TRUE);
2626 if (appData.quietPlay)
2627 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Quit Play")),TRUE);
2629 if (appData.showCoords)
2630 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Show Coords")),TRUE);
2632 if (appData.showThinking)
2633 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Show Thinking")),TRUE);
2635 if (appData.testLegality)
2636 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Test Legality")),TRUE);
2638 /* end setting check boxes */
2640 /* load square colors */
2641 SVGLightSquare = load_pixbuf("svg/LightSquare.svg",squareSize);
2642 SVGDarkSquare = load_pixbuf("svg/DarkSquare.svg",squareSize);
2643 SVGNeutralSquare = load_pixbuf("svg/NeutralSquare.svg",squareSize);
2645 /* use two icons to indicate if it is white's or black's turn */
2646 WhiteIcon = load_pixbuf("svg/icon_white.svg",0);
2647 BlackIcon = load_pixbuf("svg/icon_black.svg",0);
2648 WindowIcon = WhiteIcon;
2649 gtk_window_set_icon(GTK_WINDOW(GUI_Window),WindowIcon);
2652 /* realize window */
2653 gtk_widget_show (GUI_Window);
2655 /* recalc boardsize */
2660 if (appData.animate || appData.animateDragging)
2665 if (errorExitStatus == -1) {
2666 if (appData.icsActive) {
2667 /* We now wait until we see "login:" from the ICS before
2668 sending the logon script (problems with timestamp otherwise) */
2669 /*ICSInitScript();*/
2670 if (appData.icsInputBox) ICSInputBoxPopUp();
2674 signal(SIGWINCH, TermSizeSigHandler);
2676 signal(SIGINT, IntSigHandler);
2677 signal(SIGTERM, IntSigHandler);
2678 if (*appData.cmailGameName != NULLCHAR) {
2679 signal(SIGUSR1, CmailSigHandler);
2682 gameInfo.boardWidth = 0; // [HGM] pieces: kludge to ensure InitPosition() calls InitDrawingSizes()
2686 * Create a cursor for the board widget.
2687 * (This needs to be called after the window has been created to have access to board-window)
2690 BoardCursor = gdk_cursor_new(GDK_HAND2);
2691 gdk_window_set_cursor(GUI_Board->window, BoardCursor);
2692 gdk_cursor_destroy(BoardCursor);
2697 if (appData.debugMode) fclose(debugFP); // [DM] debug
2704 if (appData.icsActive && oldICSInteractionTitle != NULL) {
2705 DisplayIcsInteractionTitle(oldICSInteractionTitle);
2707 unlink(gameCopyFilename);
2708 unlink(gamePasteFilename);
2711 RETSIGTYPE TermSizeSigHandler(int sig)
2724 CmailSigHandler(sig)
2730 signal(SIGUSR1, SIG_IGN); /* suspend handler */
2732 /* Activate call-back function CmailSigHandlerCallBack() */
2733 OutputToProcess(cmailPR, (char *)(&dummy), sizeof(int), &error);
2735 signal(SIGUSR1, CmailSigHandler); /* re-activate handler */
2739 CmailSigHandlerCallBack(isr, closure, message, count, error)
2747 ReloadCmailMsgEvent(TRUE); /* Reload cmail msg */
2749 /**** end signal code ****/
2759 f = fopen(appData.icsLogon, "r");
2765 strcat(buf, appData.icsLogon);
2766 f = fopen(buf, "r");
2770 ProcessICSInitScript(f);
2777 EditCommentPopDown();
2783 SetMenuEnables(enab)
2788 if (!builder) return;
2789 while (enab->name != NULL) {
2790 o = gtk_builder_get_object(builder, enab->name);
2791 if(GTK_IS_WIDGET(o))
2792 gtk_widget_set_sensitive(GTK_WIDGET (o),enab->value);
2795 if(GTK_IS_ACTION(o))
2796 gtk_action_set_sensitive(GTK_ACTION (o),enab->value);
2798 DisplayError(enab->name, 0);
2806 SetMenuEnables(icsEnables);
2809 if (appData.zippyPlay && !appData.noChessProgram) /* [DM] icsEngineAnalyze */
2810 {}; // XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Analysis Mode"), True);
2817 SetMenuEnables(ncpEnables);
2823 SetMenuEnables(gnuEnables);
2829 SetMenuEnables(cmailEnables);
2835 SetMenuEnables(trainingOnEnables);
2836 if (appData.showButtonBar) {
2837 // XtSetSensitive(buttonBarWidget, False);
2843 SetTrainingModeOff()
2845 SetMenuEnables(trainingOffEnables);
2846 if (appData.showButtonBar) {
2847 // XtSetSensitive(buttonBarWidget, True);
2852 SetUserThinkingEnables()
2854 if (appData.noChessProgram) return;
2855 SetMenuEnables(userThinkingEnables);
2859 SetMachineThinkingEnables()
2861 if (appData.noChessProgram) return;
2862 SetMenuEnables(machineThinkingEnables);
2864 case MachinePlaysBlack:
2865 case MachinePlaysWhite:
2866 case TwoMachinesPlay:
2867 // XtSetSensitive(XtNameToWidget(menuBarWidget,
2868 // ModeToWidgetName(gameMode)), True);
2875 #define Abs(n) ((n)<0 ? -(n) : (n))
2878 * Find a font that matches "pattern" that is as close as
2879 * possible to the targetPxlSize. Prefer fonts that are k
2880 * pixels smaller to fonts that are k pixels larger. The
2881 * pattern must be in the X Consortium standard format,
2882 * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".
2883 * The return value should be freed with XtFree when no
2886 char *FindFont(pattern, targetPxlSize)
2890 char **fonts, *p, *best, *scalable, *scalableTail;
2891 int i, j, nfonts, minerr, err, pxlSize;
2894 char **missing_list;
2896 char *def_string, *base_fnt_lst, strInt[3];
2898 XFontStruct **fnt_list;
2900 base_fnt_lst = calloc(1, strlen(pattern) + 3);
2901 sprintf(strInt, "%d", targetPxlSize);
2902 p = strstr(pattern, "--");
2903 strncpy(base_fnt_lst, pattern, p - pattern + 2);
2904 strcat(base_fnt_lst, strInt);
2905 strcat(base_fnt_lst, strchr(p + 2, '-'));
2907 if ((fntSet = XCreateFontSet(xDisplay,
2911 &def_string)) == NULL) {
2913 fprintf(stderr, _("Unable to create font set.\n"));
2917 nfonts = XFontsOfFontSet(fntSet, &fnt_list, &fonts);
2919 fonts = XListFonts(xDisplay, pattern, 999999, &nfonts);
2921 fprintf(stderr, _("%s: no fonts match pattern %s\n"),
2922 programName, pattern);
2930 for (i=0; i<nfonts; i++) {
2933 if (*p != '-') continue;
2935 if (*p == NULLCHAR) break;
2936 if (*p++ == '-') j++;
2938 if (j < 7) continue;
2941 scalable = fonts[i];
2944 err = pxlSize - targetPxlSize;
2945 if (Abs(err) < Abs(minerr) ||
2946 (minerr > 0 && err < 0 && -err == minerr)) {
2952 if (scalable && Abs(minerr) > appData.fontSizeTolerance) {
2953 /* If the error is too big and there is a scalable font,
2954 use the scalable font. */
2955 int headlen = scalableTail - scalable;
2956 p = (char *) XtMalloc(strlen(scalable) + 10);
2957 while (isdigit(*scalableTail)) scalableTail++;
2958 sprintf(p, "%.*s%d%s", headlen, scalable, targetPxlSize, scalableTail);
2960 p = (char *) XtMalloc(strlen(best) + 1);
2963 if (appData.debugMode) {
2964 fprintf(debugFP, _("resolved %s at pixel size %d\n to %s\n"),
2965 pattern, targetPxlSize, p);
2968 if (missing_count > 0)
2969 XFreeStringList(missing_list);
2970 XFreeFontSet(xDisplay, fntSet);
2972 XFreeFontNames(fonts);
2979 /* 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*/
2981 XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
2982 | GCBackground | GCFunction | GCPlaneMask;
2983 XGCValues gc_values;
2986 gc_values.plane_mask = AllPlanes;
2987 gc_values.line_width = lineGap;
2988 gc_values.line_style = LineSolid;
2989 gc_values.function = GXcopy;
2991 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
2992 gc_values.background = XWhitePixel(xDisplay, xScreen);
2993 coordGC = XtGetGC(shellWidget, value_mask, &gc_values);
2994 XSetFont(xDisplay, coordGC, coordFontID);
2996 if (appData.monoMode) {
2997 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
2998 gc_values.background = XBlackPixel(xDisplay, xScreen);
2999 lightSquareGC = wbPieceGC
3000 = XtGetGC(shellWidget, value_mask, &gc_values);
3002 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3003 gc_values.background = XWhitePixel(xDisplay, xScreen);
3004 darkSquareGC = bwPieceGC
3005 = XtGetGC(shellWidget, value_mask, &gc_values);
3007 if (DefaultDepth(xDisplay, xScreen) == 1) {
3008 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
3009 gc_values.function = GXcopyInverted;
3010 copyInvertedGC = XtGetGC(shellWidget, value_mask, &gc_values);
3011 gc_values.function = GXcopy;
3012 if (XBlackPixel(xDisplay, xScreen) == 1) {
3013 bwPieceGC = darkSquareGC;
3014 wbPieceGC = copyInvertedGC;
3016 bwPieceGC = copyInvertedGC;
3017 wbPieceGC = lightSquareGC;
3021 gc_values.foreground = lightSquareColor;
3022 gc_values.background = darkSquareColor;
3023 lightSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3025 gc_values.foreground = darkSquareColor;
3026 gc_values.background = lightSquareColor;
3027 darkSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3029 gc_values.foreground = jailSquareColor;
3030 gc_values.background = jailSquareColor;
3031 jailSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3033 gc_values.foreground = whitePieceColor;
3034 gc_values.background = darkSquareColor;
3035 wdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3037 gc_values.foreground = whitePieceColor;
3038 gc_values.background = lightSquareColor;
3039 wlPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3041 gc_values.foreground = whitePieceColor;
3042 gc_values.background = jailSquareColor;
3043 wjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3045 gc_values.foreground = blackPieceColor;
3046 gc_values.background = darkSquareColor;
3047 bdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3049 gc_values.foreground = blackPieceColor;
3050 gc_values.background = lightSquareColor;
3051 blPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3053 gc_values.foreground = blackPieceColor;
3054 gc_values.background = jailSquareColor;
3055 bjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3064 for(i=0;i<MAXPIECES;i++)
3068 g_free(SVGpieces[i]);
3075 SVGLightSquare = load_pixbuf("svg/LightSquare.svg",squareSize);
3076 SVGDarkSquare = load_pixbuf("svg/DarkSquare.svg",squareSize);
3077 SVGNeutralSquare = load_pixbuf("svg/NeutralSquare.svg",squareSize);
3080 /* get some defaults going */
3081 for(i=WhitePawn; i<DemotePiece+1; i++)
3082 SVGpieces[i] = load_pixbuf("svg/NeutralSquare.svg",squareSize);
3084 SVGpieces[WhitePawn] = load_pixbuf("svg/WhitePawn.svg",squareSize);
3085 SVGpieces[WhiteKnight] = load_pixbuf("svg/WhiteKnight.svg",squareSize);
3086 SVGpieces[WhiteBishop] = load_pixbuf("svg/WhiteBishop.svg",squareSize);
3087 SVGpieces[WhiteRook] = load_pixbuf("svg/WhiteRook.svg",squareSize);
3088 SVGpieces[WhiteQueen] = load_pixbuf("svg/WhiteQueen.svg",squareSize);
3089 SVGpieces[WhiteKing] = load_pixbuf("svg/WhiteKing.svg",squareSize);
3091 SVGpieces[BlackPawn] = load_pixbuf("svg/BlackPawn.svg",squareSize);
3092 SVGpieces[BlackKnight] = load_pixbuf("svg/BlackKnight.svg",squareSize);
3093 SVGpieces[BlackBishop] = load_pixbuf("svg/BlackBishop.svg",squareSize);
3094 SVGpieces[BlackRook] = load_pixbuf("svg/BlackRook.svg",squareSize);
3095 SVGpieces[BlackQueen] = load_pixbuf("svg/BlackQueen.svg",squareSize);
3096 SVGpieces[BlackKing] = load_pixbuf("svg/BlackKing.svg",squareSize);
3102 static void MenuBarSelect(w, addr, index)
3107 XtActionProc proc = (XtActionProc) addr;
3109 (proc)(NULL, NULL, NULL, NULL);
3112 void CreateMenuBarPopup(parent, name, mb)
3122 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3125 XtSetArg(args[j], XtNleftMargin, 20); j++;
3126 XtSetArg(args[j], XtNrightMargin, 20); j++;
3128 while (mi->string != NULL) {
3129 if (strcmp(mi->string, "----") == 0) {
3130 entry = XtCreateManagedWidget(mi->string, smeLineObjectClass,
3133 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string)));
3134 entry = XtCreateManagedWidget(mi->string, smeBSBObjectClass,
3136 XtAddCallback(entry, XtNcallback,
3137 (XtCallbackProc) MenuBarSelect,
3138 (caddr_t) mi->proc);
3144 Widget CreateMenuBar(mb)
3148 Widget anchor, menuBar;
3150 char menuName[MSG_SIZ];
3153 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
3154 XtSetArg(args[j], XtNvSpace, 0); j++;
3155 XtSetArg(args[j], XtNborderWidth, 0); j++;
3156 menuBar = XtCreateWidget("menuBar", boxWidgetClass,
3157 formWidget, args, j);
3159 while (mb->name != NULL) {
3160 strcpy(menuName, "menu");
3161 strcat(menuName, mb->name);
3163 XtSetArg(args[j], XtNmenuName, XtNewString(menuName)); j++;
3166 shortName[0] = _(mb->name)[0];
3167 shortName[1] = NULLCHAR;
3168 XtSetArg(args[j], XtNlabel, XtNewString(shortName)); j++;
3171 XtSetArg(args[j], XtNlabel, XtNewString(_(mb->name))); j++;
3174 XtSetArg(args[j], XtNborderWidth, 0); j++;
3175 anchor = XtCreateManagedWidget(mb->name, menuButtonWidgetClass,
3177 CreateMenuBarPopup(menuBar, menuName, mb);
3185 CreatePieceMenu(name, color)
3192 ChessSquare selection;
3194 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3195 boardWidget, args, 0);
3197 for (i = 0; i < PIECE_MENU_SIZE; i++) {
3198 String item = pieceMenuStrings[color][i];
3200 if (strcmp(item, "----") == 0) {
3201 entry = XtCreateManagedWidget(item, smeLineObjectClass,
3204 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
3205 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3207 selection = pieceMenuTranslation[color][i];
3208 XtAddCallback(entry, XtNcallback,
3209 (XtCallbackProc) PieceMenuSelect,
3210 (caddr_t) selection);
3211 if (selection == WhitePawn || selection == BlackPawn) {
3212 XtSetArg(args[0], XtNpopupOnEntry, entry);
3213 XtSetValues(menu, args, 1);
3226 ChessSquare selection;
3228 // whitePieceMenu = CreatePieceMenu("menuW", 0);
3229 // blackPieceMenu = CreatePieceMenu("menuB", 1);
3231 // XtRegisterGrabAction(PieceMenuPopup, True,
3232 // (unsigned)(ButtonPressMask|ButtonReleaseMask),
3233 // GrabModeAsync, GrabModeAsync);
3235 // XtSetArg(args[0], XtNlabel, _("Drop"));
3236 // dropMenu = XtCreatePopupShell("menuD", simpleMenuWidgetClass,
3237 // boardWidget, args, 1);
3238 // for (i = 0; i < DROP_MENU_SIZE; i++) {
3239 // String item = dropMenuStrings[i];
3241 // if (strcmp(item, "----") == 0) {
3242 // entry = XtCreateManagedWidget(item, smeLineObjectClass,
3243 // dropMenu, NULL, 0);
3245 // XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
3246 // entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3247 // dropMenu, args, 1);
3248 // selection = dropMenuTranslation[i];
3249 // XtAddCallback(entry, XtNcallback,
3250 // (XtCallbackProc) DropMenuSelect,
3251 // (caddr_t) selection);
3256 void SetupDropMenu()
3264 for (i=0; i<sizeof(dmEnables)/sizeof(DropMenuEnables); i++) {
3265 entry = XtNameToWidget(dropMenu, dmEnables[i].widget);
3266 p = strchr(gameMode == IcsPlayingWhite ? white_holding : black_holding,
3267 dmEnables[i].piece);
3268 XtSetSensitive(entry, p != NULL || !appData.testLegality
3269 /*!!temp:*/ || (gameInfo.variant == VariantCrazyhouse
3270 && !appData.icsActive));
3272 while (p && *p++ == dmEnables[i].piece) count++;
3273 snprintf(label, sizeof(label), "%s %d", dmEnables[i].widget, count);
3275 XtSetArg(args[j], XtNlabel, label); j++;
3276 XtSetValues(entry, args, j);
3280 void PieceMenuPopup(w, event, params, num_params)
3284 Cardinal *num_params;
3287 if (event->type != ButtonPress) return;
3288 if (errorUp) ErrorPopDown();
3292 whichMenu = params[0];
3294 case IcsPlayingWhite:
3295 case IcsPlayingBlack:
3297 case MachinePlaysWhite:
3298 case MachinePlaysBlack:
3299 if (appData.testLegality &&
3300 gameInfo.variant != VariantBughouse &&
3301 gameInfo.variant != VariantCrazyhouse) return;
3303 whichMenu = "menuD";
3309 if (((pmFromX = EventToSquare(event->xbutton.x, BOARD_WIDTH)) < 0) ||
3310 ((pmFromY = EventToSquare(event->xbutton.y, BOARD_HEIGHT)) < 0)) {
3311 pmFromX = pmFromY = -1;
3315 pmFromX = BOARD_WIDTH - 1 - pmFromX;
3317 pmFromY = BOARD_HEIGHT - 1 - pmFromY;
3319 XtPopupSpringLoaded(XtNameToWidget(boardWidget, whichMenu));
3322 static void PieceMenuSelect(w, piece, junk)
3327 if (pmFromX < 0 || pmFromY < 0) return;
3328 EditPositionMenuEvent(piece, pmFromX, pmFromY);
3331 static void DropMenuSelect(w, piece, junk)
3336 if (pmFromX < 0 || pmFromY < 0) return;
3337 DropMenuEvent(piece, pmFromX, pmFromY);
3341 * If the user selects on a border boundary, return -1; if off the board,
3342 * return -2. Otherwise map the event coordinate to the square.
3344 int EventToSquare(x, limit)
3352 if ((x % (squareSize + lineGap)) >= squareSize)
3354 x /= (squareSize + lineGap);
3360 static void do_flash_delay(msec)
3366 static void drawHighlight(file, rank, line_type)
3367 int file, rank, line_type;
3372 if (lineGap == 0 || appData.blindfold) return;
3376 x = lineGap/2 + ((BOARD_WIDTH-1)-file) *
3377 (squareSize + lineGap);
3378 y = lineGap/2 + rank * (squareSize + lineGap);
3382 x = lineGap/2 + file * (squareSize + lineGap);
3383 y = lineGap/2 + ((BOARD_HEIGHT-1)-rank) *
3384 (squareSize + lineGap);
3388 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
3390 /* draw the highlight */
3391 cairo_move_to (cr, x, y);
3392 cairo_rel_line_to (cr, 0,squareSize+lineGap);
3393 cairo_rel_line_to (cr, squareSize+lineGap,0);
3394 cairo_rel_line_to (cr, 0,-squareSize-lineGap);
3395 cairo_close_path (cr);
3397 cairo_set_line_width (cr, lineGap);
3400 /* TODO: use appdata colors */
3401 case LINE_TYPE_HIGHLIGHT:
3402 cairo_set_source_rgba (cr, 1, 1, 0, 1.0);
3405 cairo_set_source_rgba (cr, 1, 0, 0, 1.0);
3407 case LINE_TYPE_NORMAL:
3409 cairo_set_source_rgba (cr, 0, 1, 0, 1.0);
3420 int hi1X = -1, hi1Y = -1, hi2X = -1, hi2Y = -1;
3421 int pm1X = -1, pm1Y = -1, pm2X = -1, pm2Y = -1;
3424 SetHighlights(fromX, fromY, toX, toY)
3425 int fromX, fromY, toX, toY;
3427 if (hi1X != fromX || hi1Y != fromY)
3429 if (hi1X >= 0 && hi1Y >= 0)
3431 drawHighlight(hi1X, hi1Y, LINE_TYPE_NORMAL);
3433 if (fromX >= 0 && fromY >= 0)
3435 drawHighlight(fromX, fromY, LINE_TYPE_HIGHLIGHT);
3438 if (hi2X != toX || hi2Y != toY)
3440 if (hi2X >= 0 && hi2Y >= 0)
3442 drawHighlight(hi2X, hi2Y, LINE_TYPE_NORMAL);
3444 if (toX >= 0 && toY >= 0)
3446 drawHighlight(toX, toY, LINE_TYPE_HIGHLIGHT);
3460 SetHighlights(-1, -1, -1, -1);
3465 SetPremoveHighlights(fromX, fromY, toX, toY)
3466 int fromX, fromY, toX, toY;
3468 if (pm1X != fromX || pm1Y != fromY)
3470 if (pm1X >= 0 && pm1Y >= 0)
3472 drawHighlight(pm1X, pm1Y, LINE_TYPE_NORMAL);
3474 if (fromX >= 0 && fromY >= 0)
3476 drawHighlight(fromX, fromY, LINE_TYPE_PRE);
3479 if (pm2X != toX || pm2Y != toY)
3481 if (pm2X >= 0 && pm2Y >= 0)
3483 drawHighlight(pm2X, pm2Y, LINE_TYPE_NORMAL);
3485 if (toX >= 0 && toY >= 0)
3487 drawHighlight(toX, toY, LINE_TYPE_PRE);
3500 ClearPremoveHighlights()
3502 SetPremoveHighlights(-1, -1, -1, -1);
3505 static void BlankSquare(x, y, color, piece, dest)
3518 pb = SVGLightSquare;
3520 case 2: /* neutral */
3522 pb = SVGNeutralSquare;
3525 gdk_draw_pixbuf(GDK_WINDOW(GUI_Board->window),NULL,pb,0,0,x,y,-1,-1, GDK_RGB_DITHER_NORMAL, 0, 0);
3529 static void DrawPiece(piece, square_color, x, y, dest)
3531 int square_color, x, y;
3534 /* redraw background, since piece might be transparent in some areas */
3535 BlankSquare(x,y,square_color,piece,dest);
3538 gdk_draw_pixbuf(GDK_WINDOW(GUI_Board->window),NULL,
3539 GDK_PIXBUF(SVGpieces[piece]),0,0,x,y,-1,-1,
3540 GDK_RGB_DITHER_NORMAL, 0, 0);
3544 /* [HR] determine square color depending on chess variant. */
3545 static int SquareColor(row, column)
3550 if (gameInfo.variant == VariantXiangqi) {
3551 if (column >= 3 && column <= 5 && row >= 0 && row <= 2) {
3553 } else if (column >= 3 && column <= 5 && row >= 7 && row <= 9) {
3555 } else if (row <= 4) {
3561 square_color = ((column + row) % 2) == 1;
3564 /* [hgm] holdings: next line makes all holdings squares light */
3565 if(column < BOARD_LEFT || column >= BOARD_RGHT) square_color = 1;
3567 return square_color;
3570 void DrawSquare(row, column, piece, do_flash)
3571 int row, column, do_flash;
3574 int square_color, x, y;
3579 /* Calculate delay in milliseconds (2-delays per complete flash) */
3580 flash_delay = 500 / appData.flashRate;
3582 /* calculate x and y coordinates from row and column */
3585 x = lineGap + ((BOARD_WIDTH-1)-column) *
3586 (squareSize + lineGap);
3587 y = lineGap + row * (squareSize + lineGap);
3591 x = lineGap + column * (squareSize + lineGap);
3592 y = lineGap + ((BOARD_HEIGHT-1)-row) *
3593 (squareSize + lineGap);
3596 square_color = SquareColor(row, column);
3598 // [HGM] holdings: blank out area between board and holdings
3599 if ( column == BOARD_LEFT-1 || column == BOARD_RGHT
3600 || (column == BOARD_LEFT-2 && row < BOARD_HEIGHT-gameInfo.holdingsSize)
3601 || (column == BOARD_RGHT+1 && row >= gameInfo.holdingsSize) )
3603 BlankSquare(x, y, 2, EmptySquare, xBoardWindow);
3605 // [HGM] print piece counts next to holdings
3606 string[1] = NULLCHAR;
3609 cairo_text_extents_t extents;
3614 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
3616 string[0] = '0' + piece;
3618 /* TODO this has to go into the font-selection */
3619 cairo_select_font_face (cr, "Sans",
3620 CAIRO_FONT_SLANT_NORMAL,
3621 CAIRO_FONT_WEIGHT_NORMAL);
3623 cairo_set_font_size (cr, 12.0);
3624 cairo_text_extents (cr, string, &extents);
3626 if (column == (flipView ? BOARD_LEFT-1 : BOARD_RGHT) )
3628 xpos= x + squareSize - extents.width - 2;
3629 ypos= y + extents.y_bearing + 1;
3631 if (column == (flipView ? BOARD_RGHT : BOARD_LEFT-1) && piece > 1)
3634 ypos = y + extents.y_bearing + 1;
3637 /* TODO mono mode? */
3638 cairo_move_to (cr, xpos, ypos);
3639 cairo_text_path (cr, string);
3640 cairo_set_source_rgb (cr, 1.0, 1.0, 1);
3641 cairo_fill_preserve (cr);
3642 cairo_set_source_rgb (cr, 0, 0, 0);
3643 cairo_set_line_width (cr, 0.1);
3652 /* square on the board */
3653 if (piece == EmptySquare || appData.blindfold)
3655 BlankSquare(x, y, square_color, piece, xBoardWindow);
3659 if (do_flash && appData.flashCount > 0)
3661 for (i=0; i<appData.flashCount; ++i)
3664 DrawPiece(piece, square_color, x, y, xBoardWindow);
3665 do_flash_delay(flash_delay);
3667 BlankSquare(x, y, square_color, piece, xBoardWindow);
3668 do_flash_delay(flash_delay);
3671 DrawPiece(piece, square_color, x, y, xBoardWindow);
3675 /* show coordinates if necessary */
3676 if(appData.showCoords)
3678 cairo_text_extents_t extents;
3682 /* TODO this has to go into the font-selection */
3683 cairo_select_font_face (cr, "Sans",
3684 CAIRO_FONT_SLANT_NORMAL,
3685 CAIRO_FONT_WEIGHT_NORMAL);
3686 cairo_set_font_size (cr, 12.0);
3688 string[1] = NULLCHAR;
3691 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
3693 if (row == (flipView ? BOARD_HEIGHT-1 : 0) &&
3694 column >= BOARD_LEFT && column < BOARD_RGHT)
3696 string[0] = 'a' + column - BOARD_LEFT;
3697 cairo_text_extents (cr, string, &extents);
3699 xpos = x + squareSize - extents.width - 2;
3700 ypos = y + squareSize - extents.height - extents.y_bearing - 1;
3702 if (appData.monoMode)
3709 cairo_move_to (cr, xpos, ypos);
3710 cairo_text_path (cr, string);
3711 cairo_set_source_rgb (cr, 0.0, 0.0, 0);
3712 cairo_fill_preserve (cr);
3713 cairo_set_source_rgb (cr, 0, 1.0, 0);
3714 cairo_set_line_width (cr, 0.1);
3717 if ( column == (flipView ? BOARD_RGHT-1 : BOARD_LEFT))
3720 string[0] = ONE + row;
3721 cairo_text_extents (cr, string, &extents);
3724 ypos = y + extents.height + 1;
3726 if (appData.monoMode)
3733 cairo_move_to (cr, xpos, ypos);
3734 cairo_text_path (cr, string);
3735 cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
3736 cairo_fill_preserve (cr);
3737 cairo_set_source_rgb (cr, 0, 0, 1.0);
3738 cairo_set_line_width (cr, 0.1);
3750 /* Returns 1 if there are "too many" differences between b1 and b2
3751 (i.e. more than 1 move was made) */
3752 static int too_many_diffs(b1, b2)
3758 for (i=0; i<BOARD_HEIGHT; ++i) {
3759 for (j=0; j<BOARD_WIDTH; ++j) {
3760 if (b1[i][j] != b2[i][j]) {
3761 if (++c > 4) /* Castling causes 4 diffs */
3770 /* Matrix describing castling maneuvers */
3771 /* Row, ColRookFrom, ColKingFrom, ColRookTo, ColKingTo */
3772 static int castling_matrix[4][5] = {
3773 { 0, 0, 4, 3, 2 }, /* 0-0-0, white */
3774 { 0, 7, 4, 5, 6 }, /* 0-0, white */
3775 { 7, 0, 4, 3, 2 }, /* 0-0-0, black */
3776 { 7, 7, 4, 5, 6 } /* 0-0, black */
3779 /* Checks whether castling occurred. If it did, *rrow and *rcol
3780 are set to the destination (row,col) of the rook that moved.
3782 Returns 1 if castling occurred, 0 if not.
3784 Note: Only handles a max of 1 castling move, so be sure
3785 to call too_many_diffs() first.
3787 static int check_castle_draw(newb, oldb, rrow, rcol)
3794 /* For each type of castling... */
3795 for (i=0; i<4; ++i) {
3796 r = castling_matrix[i];
3798 /* Check the 4 squares involved in the castling move */
3800 for (j=1; j<=4; ++j) {
3801 if (newb[r[0]][r[j]] == oldb[r[0]][r[j]]) {
3808 /* All 4 changed, so it must be a castling move */
3817 static int damage[BOARD_SIZE][BOARD_SIZE];
3820 * event handler for redrawing the board
3822 void DrawPosition( repaint, board)
3823 /*Boolean*/int repaint;
3827 static int lastFlipView = 0;
3828 static int lastBoardValid = 0;
3829 static Board lastBoard;
3832 if (board == NULL) {
3833 if (!lastBoardValid) return;
3836 if (!lastBoardValid || lastFlipView != flipView) {
3837 // XtSetArg(args[0], XtNleftBitmap, (flipView ? xMarkPixmap : None));
3838 // XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flip View"),
3843 * It would be simpler to clear the window with XClearWindow()
3844 * but this causes a very distracting flicker.
3847 if (!repaint && lastBoardValid && lastFlipView == flipView)
3849 /* If too much changes (begin observing new game, etc.), don't
3851 do_flash = too_many_diffs(board, lastBoard) ? 0 : 1;
3853 /* Special check for castling so we don't flash both the king
3854 and the rook (just flash the king). */
3857 if (check_castle_draw(board, lastBoard, &rrow, &rcol))
3859 /* Draw rook with NO flashing. King will be drawn flashing later */
3860 DrawSquare(rrow, rcol, board[rrow][rcol], 0);
3861 lastBoard[rrow][rcol] = board[rrow][rcol];
3865 /* First pass -- Draw (newly) empty squares and repair damage.
3866 This prevents you from having a piece show up twice while it
3867 is flashing on its new square */
3868 for (i = 0; i < BOARD_HEIGHT; i++)
3869 for (j = 0; j < BOARD_WIDTH; j++)
3870 if ((board[i][j] != lastBoard[i][j] && board[i][j] == EmptySquare)
3873 DrawSquare(i, j, board[i][j], 0);
3874 damage[i][j] = False;
3877 /* Second pass -- Draw piece(s) in new position and flash them */
3878 for (i = 0; i < BOARD_HEIGHT; i++)
3879 for (j = 0; j < BOARD_WIDTH; j++)
3880 if (board[i][j] != lastBoard[i][j])
3882 DrawSquare(i, j, board[i][j], do_flash);
3894 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
3896 cairo_set_line_width (cr, lineGap);
3898 /* TODO: use appdata colors */
3899 cairo_set_source_rgba (cr, 0, 1, 0, 1.0);
3903 for (i = 0; i < BOARD_HEIGHT + 1; i++)
3906 x2 = lineGap + BOARD_WIDTH * (squareSize + lineGap);
3907 y1 = y2 = lineGap / 2 + (i * (squareSize + lineGap));
3909 cairo_move_to (cr, x1, y1);
3910 cairo_rel_line_to (cr, x2,0);
3914 for (j = 0; j < BOARD_WIDTH + 1; j++)
3917 y2 = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
3918 x1 = x2 = lineGap / 2 + (j * (squareSize + lineGap));
3920 cairo_move_to (cr, x1, y1);
3921 cairo_rel_line_to (cr, 0, y2);
3930 for (i = 0; i < BOARD_HEIGHT; i++)
3931 for (j = 0; j < BOARD_WIDTH; j++)
3933 DrawSquare(i, j, board[i][j], 0);
3934 damage[i][j] = False;
3938 CopyBoard(lastBoard, board);
3940 lastFlipView = flipView;
3942 /* Draw highlights */
3943 if (pm1X >= 0 && pm1Y >= 0)
3945 drawHighlight(pm1X, pm1Y, LINE_TYPE_PRE);
3947 if (pm2X >= 0 && pm2Y >= 0)
3949 drawHighlight(pm2X, pm2Y, LINE_TYPE_PRE);
3951 if (hi1X >= 0 && hi1Y >= 0)
3953 drawHighlight(hi1X, hi1Y, LINE_TYPE_HIGHLIGHT);
3955 if (hi2X >= 0 && hi2Y >= 0)
3957 drawHighlight(hi2X, hi2Y, LINE_TYPE_HIGHLIGHT);
3960 /* If piece being dragged around board, must redraw that too */
3967 * event handler for parsing user moves
3969 // [HGM] This routine will need quite some reworking. Although the backend still supports the old
3970 // way of doing things, by calling UserMoveEvent() to test the legality of the move and then perform
3971 // it at the end, and doing all kind of preliminary tests here (e.g. to weed out self-captures), it
3972 // should be made to use the new way, of calling UserMoveTest early to determine the legality of the
3973 // move, (which will weed out the illegal selfcaptures and moves into the holdings, and flag promotions),
3974 // and at the end FinishMove() to perform the move after optional promotion popups.
3975 // For now I patched it to allow self-capture with King, and suppress clicks between board and holdings.
3976 void HandleUserMove(w, event, prms, nprms)
3982 if (w != boardWidget || errorExitStatus != -1) return;
3985 if (event->type == ButtonPress) {
3986 // XtPopdown(promotionShell);
3987 // XtDestroyWidget(promotionShell);
3988 promotionUp = False;
3996 // [HGM] mouse: the rest of the mouse handler is moved to the backend, and called here
3997 if(event->type == ButtonPress) LeftClick(Press, event->xbutton.x, event->xbutton.y);
3998 if(event->type == ButtonRelease) LeftClick(Release, event->xbutton.x, event->xbutton.y);
4001 void AnimateUserMove (Widget w, XEvent * event,
4002 String * params, Cardinal * nParams)
4004 DragPieceMove(event->xmotion.x, event->xmotion.y);
4007 Widget CommentCreate(name, text, mutable, callback, lines)
4009 int /*Boolean*/ mutable;
4010 XtCallbackProc callback;
4014 Widget shell, layout, form, edit, b_ok, b_cancel, b_clear, b_close, b_edit;
4019 XtSetArg(args[j], XtNwidth, &bw_width); j++;
4020 XtGetValues(boardWidget, args, j);
4023 XtSetArg(args[j], XtNresizable, True); j++;
4026 XtCreatePopupShell(name, topLevelShellWidgetClass,
4027 shellWidget, args, j);
4030 XtCreatePopupShell(name, transientShellWidgetClass,
4031 shellWidget, args, j);
4034 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
4035 layoutArgs, XtNumber(layoutArgs));
4037 XtCreateManagedWidget("form", formWidgetClass, layout,
4038 formArgs, XtNumber(formArgs));
4042 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
4043 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
4045 XtSetArg(args[j], XtNstring, text); j++;
4046 XtSetArg(args[j], XtNtop, XtChainTop); j++;
4047 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4048 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4049 XtSetArg(args[j], XtNright, XtChainRight); j++;
4050 XtSetArg(args[j], XtNresizable, True); j++;
4051 XtSetArg(args[j], XtNwidth, bw_width); j++; /*force wider than buttons*/
4052 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
4053 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
4054 XtSetArg(args[j], XtNautoFill, True); j++;
4055 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
4057 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
4061 XtSetArg(args[j], XtNfromVert, edit); j++;
4062 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4063 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4064 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4065 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4067 XtCreateManagedWidget(_("ok"), commandWidgetClass, form, args, j);
4068 XtAddCallback(b_ok, XtNcallback, callback, (XtPointer) 0);
4071 XtSetArg(args[j], XtNfromVert, edit); j++;
4072 XtSetArg(args[j], XtNfromHoriz, b_ok); j++;
4073 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4074 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4075 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4076 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4078 XtCreateManagedWidget(_("cancel"), commandWidgetClass, form, args, j);
4079 XtAddCallback(b_cancel, XtNcallback, callback, (XtPointer) 0);
4082 XtSetArg(args[j], XtNfromVert, edit); j++;
4083 XtSetArg(args[j], XtNfromHoriz, b_cancel); j++;
4084 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4085 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4086 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4087 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4089 XtCreateManagedWidget(_("clear"), commandWidgetClass, form, args, j);
4090 XtAddCallback(b_clear, XtNcallback, callback, (XtPointer) 0);
4093 XtSetArg(args[j], XtNfromVert, edit); j++;
4094 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4095 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4096 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4097 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4099 XtCreateManagedWidget(_("close"), commandWidgetClass, form, args, j);
4100 XtAddCallback(b_close, XtNcallback, callback, (XtPointer) 0);
4103 XtSetArg(args[j], XtNfromVert, edit); j++;
4104 XtSetArg(args[j], XtNfromHoriz, b_close); j++;
4105 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4106 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4107 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4108 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4110 XtCreateManagedWidget(_("edit"), commandWidgetClass, form, args, j);
4111 XtAddCallback(b_edit, XtNcallback, callback, (XtPointer) 0);
4114 XtRealizeWidget(shell);
4116 if (commentX == -1) {
4119 Dimension pw_height;
4120 Dimension ew_height;
4123 XtSetArg(args[j], XtNheight, &ew_height); j++;
4124 XtGetValues(edit, args, j);
4127 XtSetArg(args[j], XtNheight, &pw_height); j++;
4128 XtGetValues(shell, args, j);
4129 commentH = pw_height + (lines - 1) * ew_height;
4130 commentW = bw_width - 16;
4132 XSync(xDisplay, False);
4134 /* This code seems to tickle an X bug if it is executed too soon
4135 after xboard starts up. The coordinates get transformed as if
4136 the main window was positioned at (0, 0).
4138 XtTranslateCoords(shellWidget,
4139 (bw_width - commentW) / 2, 0 - commentH / 2,
4140 &commentX, &commentY);
4142 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
4143 RootWindowOfScreen(XtScreen(shellWidget)),
4144 (bw_width - commentW) / 2, 0 - commentH / 2,
4149 if (commentY < 0) commentY = 0; /*avoid positioning top offscreen*/
4152 XtSetArg(args[j], XtNheight, commentH); j++;
4153 XtSetArg(args[j], XtNwidth, commentW); j++;
4154 XtSetArg(args[j], XtNx, commentX); j++;
4155 XtSetArg(args[j], XtNy, commentY); j++;
4156 XtSetValues(shell, args, j);
4157 XtSetKeyboardFocus(shell, edit);
4162 /* Used for analysis window and ICS input window */
4163 Widget MiscCreate(name, text, mutable, callback, lines)
4165 int /*Boolean*/ mutable;
4166 XtCallbackProc callback;
4170 Widget shell, layout, form, edit;
4172 Dimension bw_width, pw_height, ew_height, w, h;
4178 XtSetArg(args[j], XtNresizable, True); j++;
4181 XtCreatePopupShell(name, topLevelShellWidgetClass,
4182 shellWidget, args, j);
4185 XtCreatePopupShell(name, transientShellWidgetClass,
4186 shellWidget, args, j);
4189 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
4190 layoutArgs, XtNumber(layoutArgs));
4192 XtCreateManagedWidget("form", formWidgetClass, layout,
4193 formArgs, XtNumber(formArgs));
4197 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
4198 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
4200 XtSetArg(args[j], XtNstring, text); j++;
4201 XtSetArg(args[j], XtNtop, XtChainTop); j++;
4202 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4203 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4204 XtSetArg(args[j], XtNright, XtChainRight); j++;
4205 XtSetArg(args[j], XtNresizable, True); j++;
4206 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
4207 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
4208 XtSetArg(args[j], XtNautoFill, True); j++;
4209 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
4211 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
4213 XtRealizeWidget(shell);
4216 XtSetArg(args[j], XtNwidth, &bw_width); j++;
4217 XtGetValues(boardWidget, args, j);
4220 XtSetArg(args[j], XtNheight, &ew_height); j++;
4221 XtGetValues(edit, args, j);
4224 XtSetArg(args[j], XtNheight, &pw_height); j++;
4225 XtGetValues(shell, args, j);
4226 h = pw_height + (lines - 1) * ew_height;
4229 XSync(xDisplay, False);
4231 /* This code seems to tickle an X bug if it is executed too soon
4232 after xboard starts up. The coordinates get transformed as if
4233 the main window was positioned at (0, 0).
4235 XtTranslateCoords(shellWidget, (bw_width - w) / 2, 0 - h / 2, &x, &y);
4237 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
4238 RootWindowOfScreen(XtScreen(shellWidget)),
4239 (bw_width - w) / 2, 0 - h / 2, &xx, &yy, &junk);
4243 if (y < 0) y = 0; /*avoid positioning top offscreen*/
4246 XtSetArg(args[j], XtNheight, h); j++;
4247 XtSetArg(args[j], XtNwidth, w); j++;
4248 XtSetArg(args[j], XtNx, x); j++;
4249 XtSetArg(args[j], XtNy, y); j++;
4250 XtSetValues(shell, args, j);
4256 static int savedIndex; /* gross that this is global */
4258 void EditCommentPopUp(index, title, text)
4267 if (text == NULL) text = "";
4269 if (editShell == NULL) {
4271 CommentCreate(title, text, True, EditCommentCallback, 4);
4272 XtRealizeWidget(editShell);
4273 CatchDeleteWindow(editShell, "EditCommentPopDown");
4275 edit = XtNameToWidget(editShell, "*form.text");
4277 XtSetArg(args[j], XtNstring, text); j++;
4278 XtSetValues(edit, args, j);
4280 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4281 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4282 XtSetValues(editShell, args, j);
4285 XtPopup(editShell, XtGrabNone);
4289 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
4290 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
4294 void EditCommentCallback(w, client_data, call_data)
4296 XtPointer client_data, call_data;
4304 XtSetArg(args[j], XtNlabel, &name); j++;
4305 XtGetValues(w, args, j);
4307 if (strcmp(name, _("ok")) == 0) {
4308 edit = XtNameToWidget(editShell, "*form.text");
4310 XtSetArg(args[j], XtNstring, &val); j++;
4311 XtGetValues(edit, args, j);
4312 ReplaceComment(savedIndex, val);
4313 EditCommentPopDown();
4314 } else if (strcmp(name, _("cancel")) == 0) {
4315 EditCommentPopDown();
4316 } else if (strcmp(name, _("clear")) == 0) {
4317 edit = XtNameToWidget(editShell, "*form.text");
4318 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
4319 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
4323 void EditCommentPopDown()
4328 if (!editUp) return;
4330 XtSetArg(args[j], XtNx, &commentX); j++;
4331 XtSetArg(args[j], XtNy, &commentY); j++;
4332 XtSetArg(args[j], XtNheight, &commentH); j++;
4333 XtSetArg(args[j], XtNwidth, &commentW); j++;
4334 XtGetValues(editShell, args, j);
4335 XtPopdown(editShell);
4338 XtSetArg(args[j], XtNleftBitmap, None); j++;
4339 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
4343 void ICSInputBoxPopUp()
4348 char *title = _("ICS Input");
4351 if (ICSInputShell == NULL) {
4352 ICSInputShell = MiscCreate(title, "", True, NULL, 1);
4353 tr = XtParseTranslationTable(ICSInputTranslations);
4354 edit = XtNameToWidget(ICSInputShell, "*form.text");
4355 XtOverrideTranslations(edit, tr);
4356 XtRealizeWidget(ICSInputShell);
4357 CatchDeleteWindow(ICSInputShell, "ICSInputBoxPopDown");
4360 edit = XtNameToWidget(ICSInputShell, "*form.text");
4362 XtSetArg(args[j], XtNstring, ""); j++;
4363 XtSetValues(edit, args, j);
4365 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4366 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4367 XtSetValues(ICSInputShell, args, j);
4370 XtPopup(ICSInputShell, XtGrabNone);
4371 XtSetKeyboardFocus(ICSInputShell, edit);
4373 ICSInputBoxUp = True;
4375 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
4376 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
4380 void ICSInputSendText()
4387 edit = XtNameToWidget(ICSInputShell, "*form.text");
4389 XtSetArg(args[j], XtNstring, &val); j++;
4390 XtGetValues(edit, args, j);
4391 SendMultiLineToICS(val);
4392 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
4393 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
4396 void ICSInputBoxPopDown()
4401 if (!ICSInputBoxUp) return;
4403 XtPopdown(ICSInputShell);
4404 ICSInputBoxUp = False;
4406 XtSetArg(args[j], XtNleftBitmap, None); j++;
4407 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
4411 void CommentPopUp(title, text)
4418 if (commentShell == NULL) {
4420 CommentCreate(title, text, False, CommentCallback, 4);
4421 XtRealizeWidget(commentShell);
4422 CatchDeleteWindow(commentShell, "CommentPopDown");
4424 edit = XtNameToWidget(commentShell, "*form.text");
4426 XtSetArg(args[j], XtNstring, text); j++;
4427 XtSetValues(edit, args, j);
4429 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4430 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4431 XtSetValues(commentShell, args, j);
4434 XtPopup(commentShell, XtGrabNone);
4435 XSync(xDisplay, False);
4440 void CommentCallback(w, client_data, call_data)
4442 XtPointer client_data, call_data;
4449 XtSetArg(args[j], XtNlabel, &name); j++;
4450 XtGetValues(w, args, j);
4452 if (strcmp(name, _("close")) == 0) {
4454 } else if (strcmp(name, _("edit")) == 0) {
4461 void CommentPopDown()
4466 if (!commentUp) return;
4468 XtSetArg(args[j], XtNx, &commentX); j++;
4469 XtSetArg(args[j], XtNy, &commentY); j++;
4470 XtSetArg(args[j], XtNwidth, &commentW); j++;
4471 XtSetArg(args[j], XtNheight, &commentH); j++;
4472 XtGetValues(commentShell, args, j);
4473 XtPopdown(commentShell);
4474 XSync(xDisplay, False);
4478 void PromotionPopUp()
4481 Widget dialog, layout;
4483 Dimension bw_width, pw_width;
4487 XtSetArg(args[j], XtNwidth, &bw_width); j++;
4488 XtGetValues(boardWidget, args, j);
4491 XtSetArg(args[j], XtNresizable, True); j++;
4492 XtSetArg(args[j], XtNtitle, XtNewString(_("Promotion"))); j++;
4494 XtCreatePopupShell("Promotion", transientShellWidgetClass,
4495 shellWidget, args, j);
4497 XtCreateManagedWidget(layoutName, formWidgetClass, promotionShell,
4498 layoutArgs, XtNumber(layoutArgs));
4501 XtSetArg(args[j], XtNlabel, _("Promote to what?")); j++;
4502 XtSetArg(args[j], XtNborderWidth, 0); j++;
4503 dialog = XtCreateManagedWidget("promotion", dialogWidgetClass,
4506 if(gameInfo.variant != VariantShogi) {
4507 XawDialogAddButton(dialog, _("Queen"), PromotionCallback,
4508 (XtPointer) dialog);
4509 XawDialogAddButton(dialog, _("Rook"), PromotionCallback,
4510 (XtPointer) dialog);
4511 XawDialogAddButton(dialog, _("Bishop"), PromotionCallback,
4512 (XtPointer) dialog);
4513 XawDialogAddButton(dialog, _("Knight"), PromotionCallback,
4514 (XtPointer) dialog);
4515 if (!appData.testLegality || gameInfo.variant == VariantSuicide ||
4516 gameInfo.variant == VariantGiveaway) {
4517 XawDialogAddButton(dialog, _("King"), PromotionCallback,
4518 (XtPointer) dialog);
4520 if(gameInfo.variant == VariantCapablanca ||
4521 gameInfo.variant == VariantGothic ||
4522 gameInfo.variant == VariantCapaRandom) {
4523 XawDialogAddButton(dialog, _("Archbishop"), PromotionCallback,
4524 (XtPointer) dialog);
4525 XawDialogAddButton(dialog, _("Chancellor"), PromotionCallback,
4526 (XtPointer) dialog);
4528 } else // [HGM] shogi
4530 XawDialogAddButton(dialog, _("Promote"), PromotionCallback,
4531 (XtPointer) dialog);
4532 XawDialogAddButton(dialog, _("Defer"), PromotionCallback,
4533 (XtPointer) dialog);
4535 XawDialogAddButton(dialog, _("cancel"), PromotionCallback,
4536 (XtPointer) dialog);
4538 XtRealizeWidget(promotionShell);
4539 CatchDeleteWindow(promotionShell, "PromotionPopDown");
4542 XtSetArg(args[j], XtNwidth, &pw_width); j++;
4543 XtGetValues(promotionShell, args, j);
4545 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
4546 lineGap + squareSize/3 +
4547 ((toY == BOARD_HEIGHT-1) ^ (flipView) ?
4548 0 : 6*(squareSize + lineGap)), &x, &y);
4551 XtSetArg(args[j], XtNx, x); j++;
4552 XtSetArg(args[j], XtNy, y); j++;
4553 XtSetValues(promotionShell, args, j);
4555 XtPopup(promotionShell, XtGrabNone);
4560 void PromotionPopDown()
4562 if (!promotionUp) return;
4563 XtPopdown(promotionShell);
4564 XtDestroyWidget(promotionShell);
4565 promotionUp = False;
4568 void PromotionCallback(w, client_data, call_data)
4570 XtPointer client_data, call_data;
4576 XtSetArg(args[0], XtNlabel, &name);
4577 XtGetValues(w, args, 1);
4581 if (fromX == -1) return;
4583 if (strcmp(name, _("cancel")) == 0) {
4587 } else if (strcmp(name, _("Knight")) == 0) {
4589 } else if (strcmp(name, _("Promote")) == 0) {
4591 } else if (strcmp(name, _("Defer")) == 0) {
4594 promoChar = ToLower(name[0]);
4597 UserMoveEvent(fromX, fromY, toX, toY, promoChar);
4599 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
4600 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
4605 void ErrorCallback(w, client_data, call_data)
4607 XtPointer client_data, call_data;
4610 XtPopdown(w = XtParent(XtParent(XtParent(w))));
4612 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
4618 if (!errorUp) return;
4622 gtk_widget_destroy(GTK_WIDGET(GUI_Error));
4624 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
4629 void ErrorPopUp(title, label, modal)
4630 char *title, *label;
4633 GUI_Error = gtk_message_dialog_new(GTK_WINDOW(GUI_Window),
4634 GTK_DIALOG_DESTROY_WITH_PARENT,
4639 gtk_window_set_title(GTK_WINDOW(GUI_Error),(gchar *) title);
4642 gtk_dialog_run(GTK_DIALOG(GUI_Error));
4643 gtk_widget_destroy(GTK_WIDGET(GUI_Error));
4647 g_signal_connect_swapped (GUI_Error, "response",
4648 G_CALLBACK (ErrorPopDownProc),
4651 gtk_widget_show(GTK_WIDGET(GUI_Error));
4657 /* Disable all user input other than deleting the window */
4658 static int frozen = 0;
4662 /* Grab by a widget that doesn't accept input */
4663 // XtAddGrab(messageWidget, TRUE, FALSE);
4667 /* Undo a FreezeUI */
4670 if (!frozen) return;
4671 // XtRemoveGrab(messageWidget);
4675 char *ModeToWidgetName(mode)
4679 case BeginningOfGame:
4680 if (appData.icsActive)
4681 return "menuMode.ICS Client";
4682 else if (appData.noChessProgram ||
4683 *appData.cmailGameName != NULLCHAR)
4684 return "menuMode.Edit Game";
4686 return "menuMode.Machine Black";
4687 case MachinePlaysBlack:
4688 return "menuMode.Machine Black";
4689 case MachinePlaysWhite:
4690 return "menuMode.Machine White";
4692 return "menuMode.Analysis Mode";
4694 return "menuMode.Analyze File";
4695 case TwoMachinesPlay:
4696 return "menuMode.Two Machines";
4698 return "menuMode.Edit Game";
4699 case PlayFromGameFile:
4700 return "menuFile.Load Game";
4702 return "menuMode.Edit Position";
4704 return "menuMode.Training";
4705 case IcsPlayingWhite:
4706 case IcsPlayingBlack:
4710 return "menuMode.ICS Client";
4717 void ModeHighlight()
4719 static int oldPausing = FALSE;
4720 static GameMode oldmode = (GameMode) -1;
4723 // todo this toggling of the pause button doesn't seem to work?
4724 // e.g. select pause from buttonbar doesn't activate menumode.pause
4726 // if (!boardWidget || !XtIsRealized(boardWidget)) return;
4728 if (pausing != oldPausing) {
4729 oldPausing = pausing;
4730 gtk_button_set_relief(GTK_BUTTON (gtk_builder_get_object (builder, "menuMode.Pause")),pausing?GTK_RELIEF_NORMAL:GTK_RELIEF_NONE);
4731 /* toggle background color in showbuttonbar */
4732 if (appData.showButtonBar) {
4734 gtk_button_pressed(GTK_BUTTON (gtk_builder_get_object (builder, "buttonbar.Pause")));
4736 gtk_button_released(GTK_BUTTON (gtk_builder_get_object (builder, "buttonbar.Pause")));
4741 wname = ModeToWidgetName(oldmode);
4743 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, wname)),True);
4747 /* Maybe all the enables should be handled here, not just this one */
4748 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuMode.Training")),
4749 gameMode == Training || gameMode == PlayFromGameFile);
4754 * Button/menu procedures
4757 int LoadGamePopUp(f, gameNumber, title)
4762 cmailMsgLoaded = FALSE;
4764 if (gameNumber == 0)
4766 int error = GameListBuild(f);
4770 DisplayError(_("Cannot build game list"), error);
4772 else if (!ListEmpty(&gameList)
4773 && ((ListGame *) gameList.tailPred)->number > 1)
4775 // TODO convert to GTK
4776 // GameListPopUp(f, title);
4784 return LoadGame(f, gameNumber, title, FALSE);
4787 void ReloadCmailMsgProc(w, event, prms, nprms)
4793 ReloadCmailMsgEvent(FALSE);
4796 void MailMoveProc(w, event, prms, nprms)
4805 /* this variable is shared between CopyPositionProc and SendPositionSelection */
4806 static char *selected_fen_position=NULL;
4809 SendPositionSelection(Widget w, Atom *selection, Atom *target,
4810 Atom *type_return, XtPointer *value_return,
4811 unsigned long *length_return, int *format_return)
4813 char *selection_tmp;
4815 if (!selected_fen_position) return False; /* should never happen */
4816 if (*target == XA_STRING){
4817 /* note: since no XtSelectionDoneProc was registered, Xt will
4818 * automatically call XtFree on the value returned. So have to
4819 * make a copy of it allocated with XtMalloc */
4820 selection_tmp= XtMalloc(strlen(selected_fen_position)+16);
4821 strcpy(selection_tmp, selected_fen_position);
4823 *value_return=selection_tmp;
4824 *length_return=strlen(selection_tmp);
4825 *type_return=XA_STRING;
4826 *format_return = 8; /* bits per byte */
4833 /* note: when called from menu all parameters are NULL, so no clue what the
4834 * Widget which was clicked on was, or what the click event was
4836 void CopyPositionProc(w, event, prms, nprms)
4844 if (selected_fen_position) free(selected_fen_position);
4845 selected_fen_position = (char *)PositionToFEN(currentMove, NULL);
4846 if (!selected_fen_position) return;
4847 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
4849 SendPositionSelection,
4850 NULL/* lose_ownership_proc */ ,
4851 NULL/* transfer_done_proc */);
4853 free(selected_fen_position);
4854 selected_fen_position=NULL;
4858 /* function called when the data to Paste is ready */
4860 PastePositionCB(Widget w, XtPointer client_data, Atom *selection,
4861 Atom *type, XtPointer value, unsigned long *len, int *format)
4864 if (value==NULL || *len==0) return; /* nothing had been selected to copy */
4865 fenstr[*len]='\0'; /* normally this string is terminated, but be safe */
4866 EditPositionPasteFEN(fenstr);
4870 /* called when Paste Position button is pressed,
4871 * all parameters will be NULL */
4872 void PastePositionProc(w, event, prms, nprms)
4878 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
4879 /* (XtSelectionCallbackProc) */ PastePositionCB,
4880 NULL, /* client_data passed to PastePositionCB */
4882 /* better to use the time field from the event that triggered the
4883 * call to this function, but that isn't trivial to get
4891 SendGameSelection(Widget w, Atom *selection, Atom *target,
4892 Atom *type_return, XtPointer *value_return,
4893 unsigned long *length_return, int *format_return)
4895 char *selection_tmp;
4897 if (*target == XA_STRING){
4898 FILE* f = fopen(gameCopyFilename, "r");
4901 if (f == NULL) return False;
4905 selection_tmp = XtMalloc(len + 1);
4906 count = fread(selection_tmp, 1, len, f);
4908 XtFree(selection_tmp);
4911 selection_tmp[len] = NULLCHAR;
4912 *value_return = selection_tmp;
4913 *length_return = len;
4914 *type_return = XA_STRING;
4915 *format_return = 8; /* bits per byte */
4922 /* note: when called from menu all parameters are NULL, so no clue what the
4923 * Widget which was clicked on was, or what the click event was
4925 void CopyGameProc(w, event, prms, nprms)
4933 ret = SaveGameToFile(gameCopyFilename, FALSE);
4936 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
4939 NULL/* lose_ownership_proc */ ,
4940 NULL/* transfer_done_proc */);
4943 /* function called when the data to Paste is ready */
4945 PasteGameCB(Widget w, XtPointer client_data, Atom *selection,
4946 Atom *type, XtPointer value, unsigned long *len, int *format)
4949 if (value == NULL || *len == 0) {
4950 return; /* nothing had been selected to copy */
4952 f = fopen(gamePasteFilename, "w");
4954 DisplayError(_("Can't open temp file"), errno);
4957 fwrite(value, 1, *len, f);
4960 LoadGameFromFile(gamePasteFilename, 0, gamePasteFilename, TRUE);
4963 /* called when Paste Game button is pressed,
4964 * all parameters will be NULL */
4965 void PasteGameProc(w, event, prms, nprms)
4971 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
4972 /* (XtSelectionCallbackProc) */ PasteGameCB,
4973 NULL, /* client_data passed to PasteGameCB */
4975 /* better to use the time field from the event that triggered the
4976 * call to this function, but that isn't trivial to get
4986 SaveGameProc(NULL, NULL);
4990 void AnalyzeModeProc(w, event, prms, nprms)
4998 if (!first.analysisSupport) {
4999 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
5000 DisplayError(buf, 0);
5003 /* [DM] icsEngineAnalyze [HGM] This is horrible code; reverse the gameMode and isEngineAnalyze tests! */
5004 if (appData.icsActive) {
5005 if (gameMode != IcsObserving) {
5006 sprintf(buf,_("You are not observing a game"));
5007 DisplayError(buf, 0);
5009 if (appData.icsEngineAnalyze) {
5010 if (appData.debugMode)
5011 fprintf(debugFP, _("Found unexpected active ICS engine analyze \n"));
5017 /* if enable, use want disable icsEngineAnalyze */
5018 if (appData.icsEngineAnalyze) {
5023 appData.icsEngineAnalyze = TRUE;
5024 if (appData.debugMode)
5025 fprintf(debugFP, _("ICS engine analyze starting... \n"));
5027 if (!appData.showThinking)
5028 ShowThinkingProc(NULL,NULL);
5033 void EditGameProc(w, event, prms, nprms)
5042 void EditPositionProc(w, event, prms, nprms)
5048 EditPositionEvent();
5051 void TrainingProc(w, event, prms, nprms)
5060 void EditCommentProc(w, event, prms, nprms)
5067 EditCommentPopDown();
5073 void IcsInputBoxProc(w, event, prms, nprms)
5079 if (ICSInputBoxUp) {
5080 ICSInputBoxPopDown();
5087 void EnterKeyProc(w, event, prms, nprms)
5093 if (ICSInputBoxUp == True)
5098 void PonderNextMoveProc(w, event, prms, nprms)
5106 PonderNextMoveEvent(!appData.ponderNextMove);
5108 if (appData.ponderNextMove) {
5109 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5111 XtSetArg(args[0], XtNleftBitmap, None);
5113 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Ponder Next Move"),
5117 void PopupExitMessageProc(w, event, prms, nprms)
5125 appData.popupExitMessage = !appData.popupExitMessage;
5127 if (appData.popupExitMessage) {
5128 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5130 XtSetArg(args[0], XtNleftBitmap, None);
5132 XtSetValues(XtNameToWidget(menuBarWidget,
5133 "menuOptions.Popup Exit Message"), args, 1);
5136 void PopupMoveErrorsProc(w, event, prms, nprms)
5144 appData.popupMoveErrors = !appData.popupMoveErrors;
5146 if (appData.popupMoveErrors) {
5147 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5149 XtSetArg(args[0], XtNleftBitmap, None);
5151 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Popup Move Errors"),
5155 void PremoveProc(w, event, prms, nprms)
5163 appData.premove = !appData.premove;
5165 if (appData.premove) {
5166 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5168 XtSetArg(args[0], XtNleftBitmap, None);
5170 XtSetValues(XtNameToWidget(menuBarWidget,
5171 "menuOptions.Premove"), args, 1);
5174 void QuietPlayProc(w, event, prms, nprms)
5182 appData.quietPlay = !appData.quietPlay;
5184 if (appData.quietPlay) {
5185 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5187 XtSetArg(args[0], XtNleftBitmap, None);
5189 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Quiet Play"),
5193 void DebugProc(w, event, prms, nprms)
5199 appData.debugMode = !appData.debugMode;
5202 void AboutGameProc(w, event, prms, nprms)
5211 void NothingProc(w, event, prms, nprms)
5220 void Iconify(w, event, prms, nprms)
5229 XtSetArg(args[0], XtNiconic, True);
5230 XtSetValues(shellWidget, args, 1);
5233 void DisplayMessage(message, extMessage)
5234 gchar *message, *extMessage;
5241 snprintf(buf, sizeof(buf), "%s %s", message, extMessage);
5244 message = extMessage;
5247 gtk_label_set_text( GTK_LABEL(gtk_builder_get_object (builder, "Messages")),message);
5252 void DisplayTitle(text)
5255 gchar title[MSG_SIZ];
5257 if (text == NULL) text = "";
5259 if (appData.titleInWindow)
5264 if (*text != NULLCHAR)
5266 strcpy(title, text);
5268 else if (appData.icsActive)
5270 snprintf(title, sizeof(title), "%s: %s", programName, appData.icsHost);
5272 else if (appData.cmailGameName[0] != NULLCHAR)
5274 snprintf(title,sizeof(title), "%s: %s", programName, "CMail");
5276 // [HGM] license: This stuff should really be done in back-end, but WinBoard already had a pop-up for it
5278 else if (gameInfo.variant == VariantGothic)
5280 strcpy(title, GOTHIC);
5284 else if (gameInfo.variant == VariantFalcon)
5286 strcpy(title, FALCON);
5289 else if (appData.noChessProgram)
5291 strcpy(title, programName);
5295 snprintf(title,sizeof(title), "%s: %s", programName, first.tidy);
5297 gtk_window_set_title(GTK_WINDOW(GUI_Window),title);
5303 void DisplayError(message, error)
5310 if (appData.debugMode || appData.matchMode) {
5311 fprintf(stderr, "%s: %s\n", programName, message);
5314 if (appData.debugMode || appData.matchMode) {
5315 fprintf(stderr, "%s: %s: %s\n",
5316 programName, message, strerror(error));
5318 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
5321 ErrorPopUp(_("Error"), message, FALSE);
5325 void DisplayMoveError(message)
5330 DrawPosition(FALSE, NULL);
5331 if (appData.debugMode || appData.matchMode) {
5332 fprintf(stderr, "%s: %s\n", programName, message);
5334 if (appData.popupMoveErrors) {
5335 ErrorPopUp(_("Error"), message, FALSE);
5337 DisplayMessage(message, "");
5342 void DisplayFatalError(message, error, status)
5348 errorExitStatus = status;
5350 fprintf(stderr, "%s: %s\n", programName, message);
5352 fprintf(stderr, "%s: %s: %s\n",
5353 programName, message, strerror(error));
5354 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
5357 if (appData.popupExitMessage && boardWidget && XtIsRealized(boardWidget)) {
5358 ErrorPopUp(status ? _("Fatal Error") : _("Exiting"), message, TRUE);
5364 void DisplayInformation(message)
5368 ErrorPopUp(_("Information"), message, TRUE);
5371 void DisplayNote(message)
5375 ErrorPopUp(_("Note"), message, FALSE);
5379 NullXErrorCheck(dpy, error_event)
5381 XErrorEvent *error_event;
5386 void DisplayIcsInteractionTitle(message)
5389 if (oldICSInteractionTitle == NULL) {
5390 /* Magic to find the old window title, adapted from vim */
5391 char *wina = getenv("WINDOWID");
5393 Window win = (Window) atoi(wina);
5394 Window root, parent, *children;
5395 unsigned int nchildren;
5396 int (*oldHandler)() = XSetErrorHandler(NullXErrorCheck);
5398 if (XFetchName(xDisplay, win, &oldICSInteractionTitle)) break;
5399 if (!XQueryTree(xDisplay, win, &root, &parent,
5400 &children, &nchildren)) break;
5401 if (children) XFree((void *)children);
5402 if (parent == root || parent == 0) break;
5405 XSetErrorHandler(oldHandler);
5407 if (oldICSInteractionTitle == NULL) {
5408 oldICSInteractionTitle = "xterm";
5411 printf("\033]0;%s\007", message);
5415 char pendingReplyPrefix[MSG_SIZ];
5416 ProcRef pendingReplyPR;
5418 void AskQuestionProc(w, event, prms, nprms)
5425 fprintf(stderr, _("AskQuestionProc needed 4 parameters, got %d\n"),
5429 AskQuestionEvent(prms[0], prms[1], prms[2], prms[3]);
5432 void AskQuestionPopDown()
5434 if (!askQuestionUp) return;
5435 XtPopdown(askQuestionShell);
5436 XtDestroyWidget(askQuestionShell);
5437 askQuestionUp = False;
5440 void AskQuestionReplyAction(w, event, prms, nprms)
5450 reply = XawDialogGetValueString(w = XtParent(w));
5451 strcpy(buf, pendingReplyPrefix);
5452 if (*buf) strcat(buf, " ");
5455 OutputToProcess(pendingReplyPR, buf, strlen(buf), &err);
5456 AskQuestionPopDown();
5458 if (err) DisplayFatalError(_("Error writing to chess program"), err, 0);
5461 void AskQuestionCallback(w, client_data, call_data)
5463 XtPointer client_data, call_data;
5468 XtSetArg(args[0], XtNlabel, &name);
5469 XtGetValues(w, args, 1);
5471 if (strcmp(name, _("cancel")) == 0) {
5472 AskQuestionPopDown();
5474 AskQuestionReplyAction(w, NULL, NULL, NULL);
5478 void AskQuestion(title, question, replyPrefix, pr)
5479 char *title, *question, *replyPrefix;
5483 Widget popup, layout, dialog, edit;
5489 strcpy(pendingReplyPrefix, replyPrefix);
5490 pendingReplyPR = pr;
5493 XtSetArg(args[i], XtNresizable, True); i++;
5494 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
5495 askQuestionShell = popup =
5496 XtCreatePopupShell(title, transientShellWidgetClass,
5497 shellWidget, args, i);
5500 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
5501 layoutArgs, XtNumber(layoutArgs));
5504 XtSetArg(args[i], XtNlabel, question); i++;
5505 XtSetArg(args[i], XtNvalue, ""); i++;
5506 XtSetArg(args[i], XtNborderWidth, 0); i++;
5507 dialog = XtCreateManagedWidget("question", dialogWidgetClass,
5510 XawDialogAddButton(dialog, _("enter"), AskQuestionCallback,
5511 (XtPointer) dialog);
5512 XawDialogAddButton(dialog, _("cancel"), AskQuestionCallback,
5513 (XtPointer) dialog);
5515 XtRealizeWidget(popup);
5516 CatchDeleteWindow(popup, "AskQuestionPopDown");
5518 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
5519 &x, &y, &win_x, &win_y, &mask);
5521 XtSetArg(args[0], XtNx, x - 10);
5522 XtSetArg(args[1], XtNy, y - 30);
5523 XtSetValues(popup, args, 2);
5525 XtPopup(popup, XtGrabExclusive);
5526 askQuestionUp = True;
5528 edit = XtNameToWidget(dialog, "*value");
5529 XtSetKeyboardFocus(popup, edit);
5537 if (*name == NULLCHAR) {
5539 } else if (strcmp(name, "$") == 0) {
5540 putc(BELLCHAR, stderr);
5543 snprintf(buf, sizeof(buf), "%s '%s' &", appData.soundProgram, name);
5551 PlaySound(appData.soundMove);
5557 PlaySound(appData.soundIcsWin);
5563 PlaySound(appData.soundIcsLoss);
5569 PlaySound(appData.soundIcsDraw);
5573 PlayIcsUnfinishedSound()
5575 PlaySound(appData.soundIcsUnfinished);
5581 PlaySound(appData.soundIcsAlarm);
5587 system("stty echo");
5593 system("stty -echo");
5597 Colorize(cc, continuation)
5602 int count, outCount, error;
5604 if (textColors[(int)cc].bg > 0) {
5605 if (textColors[(int)cc].fg > 0) {
5606 sprintf(buf, "\033[0;%d;%d;%dm", textColors[(int)cc].attr,
5607 textColors[(int)cc].fg, textColors[(int)cc].bg);
5609 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
5610 textColors[(int)cc].bg);
5613 if (textColors[(int)cc].fg > 0) {
5614 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
5615 textColors[(int)cc].fg);
5617 sprintf(buf, "\033[0;%dm", textColors[(int)cc].attr);
5620 count = strlen(buf);
5621 outCount = OutputToProcess(NoProc, buf, count, &error);
5622 if (outCount < count) {
5623 DisplayFatalError(_("Error writing to display"), error, 1);
5626 if (continuation) return;
5629 PlaySound(appData.soundShout);
5632 PlaySound(appData.soundSShout);
5635 PlaySound(appData.soundChannel1);
5638 PlaySound(appData.soundChannel);
5641 PlaySound(appData.soundKibitz);
5644 PlaySound(appData.soundTell);
5646 case ColorChallenge:
5647 PlaySound(appData.soundChallenge);
5650 PlaySound(appData.soundRequest);
5653 PlaySound(appData.soundSeek);
5664 return getpwuid(getuid())->pw_name;
5667 static char *ExpandPathName(path)
5670 static char static_buf[2000];
5671 char *d, *s, buf[2000];
5677 while (*s && isspace(*s))
5686 if (*(s+1) == '/') {
5687 strcpy(d, getpwuid(getuid())->pw_dir);
5692 *strchr(buf, '/') = 0;
5693 pwd = getpwnam(buf);
5696 fprintf(stderr, _("ERROR: Unknown user %s (in path %s)\n"),
5700 strcpy(d, pwd->pw_dir);
5701 strcat(d, strchr(s+1, '/'));
5712 static char host_name[MSG_SIZ];
5714 #if HAVE_GETHOSTNAME
5715 gethostname(host_name, MSG_SIZ);
5717 #else /* not HAVE_GETHOSTNAME */
5718 # if HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H
5719 sysinfo(SI_HOSTNAME, host_name, MSG_SIZ);
5721 # else /* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
5723 # endif/* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
5724 #endif /* not HAVE_GETHOSTNAME */
5727 guint delayedEventTimerTag = 0;
5728 DelayedEventCallback delayedEventCallback = 0;
5731 FireDelayedEvent(data)
5735 g_source_remove(delayedEventTimerTag);
5736 delayedEventTimerTag = 0;
5739 delayedEventCallback();
5745 ScheduleDelayedEvent(cb, millisec)
5746 DelayedEventCallback cb; guint millisec;
5748 if(delayedEventTimerTag && delayedEventCallback == cb)
5749 // [HGM] alive: replace, rather than add or flush identical event
5750 g_source_remove(delayedEventTimerTag);
5751 delayedEventCallback = cb;
5752 delayedEventTimerTag = g_timeout_add(millisec,(GSourceFunc) FireDelayedEvent, NULL);
5756 DelayedEventCallback
5759 if (delayedEventTimerTag)
5761 return delayedEventCallback;
5770 CancelDelayedEvent()
5772 if (delayedEventTimerTag)
5774 g_source_remove(delayedEventTimerTag);
5775 delayedEventTimerTag = 0;
5781 guint loadGameTimerTag = 0;
5783 int LoadGameTimerRunning()
5785 return loadGameTimerTag != 0;
5788 int StopLoadGameTimer()
5790 if (loadGameTimerTag != 0) {
5791 g_source_remove(loadGameTimerTag);
5792 loadGameTimerTag = 0;
5800 LoadGameTimerCallback(data)
5804 g_source_remove(loadGameTimerTag);
5805 loadGameTimerTag = 0;
5812 StartLoadGameTimer(millisec)
5816 g_timeout_add( millisec, (GSourceFunc) LoadGameTimerCallback, NULL);
5820 guint analysisClockTag = 0;
5823 AnalysisClockCallback(data)
5826 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile
5827 || appData.icsEngineAnalyze)
5829 AnalysisPeriodicEvent(0);
5830 return 1; /* keep on going */
5832 return 0; /* stop timer */
5836 StartAnalysisClock()
5839 g_timeout_add( 2000,(GSourceFunc) AnalysisClockCallback, NULL);
5843 guint clockTimerTag = 0;
5845 int ClockTimerRunning()
5847 return clockTimerTag != 0;
5850 int StopClockTimer()
5852 if (clockTimerTag != 0)
5854 g_source_remove(clockTimerTag);
5865 ClockTimerCallback(data)
5869 g_source_remove(clockTimerTag);
5877 StartClockTimer(millisec)
5880 clockTimerTag = g_timeout_add(millisec,(GSourceFunc) ClockTimerCallback,NULL);
5885 DisplayTimerLabel(w, color, timer, highlight)
5894 if (appData.clockMode) {
5895 sprintf(buf, "%s: %s", color, TimeString(timer));
5897 sprintf(buf, "%s ", color);
5899 gtk_label_set_text(GTK_LABEL(w),buf);
5901 /* check for low time warning */
5902 // Pixel foregroundOrWarningColor = timerForegroundPixel;
5905 // appData.lowTimeWarning &&
5906 // (timer / 1000) < appData.icsAlarmTime)
5907 // foregroundOrWarningColor = lowTimeWarningColor;
5909 // if (appData.clockMode) {
5910 // sprintf(buf, "%s: %s", color, TimeString(timer));
5911 // XtSetArg(args[0], XtNlabel, buf);
5913 // sprintf(buf, "%s ", color);
5914 // XtSetArg(args[0], XtNlabel, buf);
5919 // XtSetArg(args[1], XtNbackground, foregroundOrWarningColor);
5920 // XtSetArg(args[2], XtNforeground, timerBackgroundPixel);
5922 // XtSetArg(args[1], XtNbackground, timerBackgroundPixel);
5923 // XtSetArg(args[2], XtNforeground, foregroundOrWarningColor);
5926 // XtSetValues(w, args, 3);
5931 DisplayWhiteClock(timeRemaining, highlight)
5935 if(appData.noGUI) return;
5937 DisplayTimerLabel(GUI_Whiteclock, _("White"), timeRemaining, highlight);
5938 if (highlight && WindowIcon == BlackIcon)
5940 WindowIcon = WhiteIcon;
5941 gtk_window_set_icon(GTK_WINDOW(GUI_Window),WindowIcon);
5946 DisplayBlackClock(timeRemaining, highlight)
5950 if(appData.noGUI) return;
5952 DisplayTimerLabel(GUI_Blackclock, _("Black"), timeRemaining, highlight);
5953 if (highlight && WindowIcon == WhiteIcon)
5955 WindowIcon = BlackIcon;
5956 gtk_window_set_icon(GTK_WINDOW(GUI_Window),WindowIcon);
5974 int StartChildProcess(cmdLine, dir, pr)
5981 int to_prog[2], from_prog[2];
5985 if (appData.debugMode) {
5986 fprintf(stderr, "StartChildProcess (dir=\"%s\") %s\n",dir, cmdLine);
5989 /* We do NOT feed the cmdLine to the shell; we just
5990 parse it into blank-separated arguments in the
5991 most simple-minded way possible.
5994 strcpy(buf, cmdLine);
5999 if (p == NULL) break;
6004 SetUpChildIO(to_prog, from_prog);
6006 if ((pid = fork()) == 0) {
6008 // [HGM] PSWBTM: made order resistant against case where fd of created pipe was 0 or 1
6009 close(to_prog[1]); // first close the unused pipe ends
6010 close(from_prog[0]);
6011 dup2(to_prog[0], 0); // to_prog was created first, nd is the only one to use 0 or 1
6012 dup2(from_prog[1], 1);
6013 if(to_prog[0] >= 2) close(to_prog[0]); // if 0 or 1, the dup2 already cosed the original
6014 close(from_prog[1]); // and closing again loses one of the pipes!
6015 if(fileno(stderr) >= 2) // better safe than sorry...
6016 dup2(1, fileno(stderr)); /* force stderr to the pipe */
6018 if (dir[0] != NULLCHAR && chdir(dir) != 0) {
6023 nice(appData.niceEngines); // [HGM] nice: adjust priority of engine proc
6025 execvp(argv[0], argv);
6027 /* If we get here, exec failed */
6032 /* Parent process */
6034 close(from_prog[1]);
6036 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
6039 cp->fdFrom = from_prog[0];
6040 cp->fdTo = to_prog[1];
6045 // [HGM] kill: implement the 'hard killing' of AS's Winboard_x
6046 static RETSIGTYPE AlarmCallBack(int n)
6052 DestroyChildProcess(pr, signalType)
6056 ChildProc *cp = (ChildProc *) pr;
6058 if (cp->kind != CPReal) return;
6060 if (signalType == 10) { // [HGM] kill: if it does not terminate in 3 sec, kill
6061 signal(SIGALRM, AlarmCallBack);
6063 if(wait((int *) 0) == -1) { // process does not terminate on its own accord
6064 kill(cp->pid, SIGKILL); // kill it forcefully
6065 wait((int *) 0); // and wait again
6069 kill(cp->pid, signalType == 9 ? SIGKILL : SIGTERM); // [HGM] kill: use hard kill if so requested
6071 /* Process is exiting either because of the kill or because of
6072 a quit command sent by the backend; either way, wait for it to die.
6081 InterruptChildProcess(pr)
6084 ChildProc *cp = (ChildProc *) pr;
6086 if (cp->kind != CPReal) return;
6087 (void) kill(cp->pid, SIGINT); /* stop it thinking */
6090 int OpenTelnet(host, port, pr)
6095 char cmdLine[MSG_SIZ];
6097 if (port[0] == NULLCHAR) {
6098 snprintf(cmdLine, sizeof(cmdLine), "%s %s", appData.telnetProgram, host);
6100 snprintf(cmdLine, sizeof(cmdLine), "%s %s %s", appData.telnetProgram, host, port);
6102 return StartChildProcess(cmdLine, "", pr);
6105 int OpenTCP(host, port, pr)
6111 DisplayFatalError(_("Socket support is not configured in"), 0, 2);
6112 #else /* !OMIT_SOCKETS */
6114 struct sockaddr_in sa;
6116 unsigned short uport;
6119 if ((s = socket(AF_INET, SOCK_STREAM, 6)) < 0) {
6123 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
6124 sa.sin_family = AF_INET;
6125 sa.sin_addr.s_addr = INADDR_ANY;
6126 uport = (unsigned short) 0;
6127 sa.sin_port = htons(uport);
6128 if (bind(s, (struct sockaddr *) &sa, sizeof(struct sockaddr_in)) < 0) {
6132 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
6133 if (!(hp = gethostbyname(host))) {
6135 if (sscanf(host, "%d.%d.%d.%d", &b0, &b1, &b2, &b3) == 4) {
6136 hp = (struct hostent *) calloc(1, sizeof(struct hostent));
6137 hp->h_addrtype = AF_INET;
6139 hp->h_addr_list = (char **) calloc(2, sizeof(char *));
6140 hp->h_addr_list[0] = (char *) malloc(4);
6141 hp->h_addr_list[0][0] = b0;
6142 hp->h_addr_list[0][1] = b1;
6143 hp->h_addr_list[0][2] = b2;
6144 hp->h_addr_list[0][3] = b3;
6149 sa.sin_family = hp->h_addrtype;
6150 uport = (unsigned short) atoi(port);
6151 sa.sin_port = htons(uport);
6152 memcpy((char *) &sa.sin_addr, hp->h_addr, hp->h_length);
6154 if (connect(s, (struct sockaddr *) &sa,
6155 sizeof(struct sockaddr_in)) < 0) {
6159 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
6166 #endif /* !OMIT_SOCKETS */
6171 int OpenCommPort(name, pr)
6178 fd = open(name, 2, 0);
6179 if (fd < 0) return errno;
6181 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
6191 int OpenLoopback(pr)
6197 SetUpChildIO(to, from);
6199 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
6202 cp->fdFrom = to[0]; /* note not from[0]; we are doing a loopback */
6209 int OpenRcmd(host, user, cmd, pr)
6210 char *host, *user, *cmd;
6213 DisplayFatalError(_("internal rcmd not implemented for Unix"), 0, 1);
6217 #define INPUT_SOURCE_BUF_SIZE 8192
6226 char buf[INPUT_SOURCE_BUF_SIZE];
6231 DoInputCallback(io,cond,data)
6236 /* read input from one of the input source (for example a chess program, ICS, etc).
6237 * and call a function that will handle the input
6240 int count; /* how many bytes did we read */
6244 /* All information (callback function, file descriptor, etc) is
6245 * saved in an InputSource structure
6247 InputSource *is = (InputSource *) data;
6251 count = read(is->fd, is->unused,
6252 INPUT_SOURCE_BUF_SIZE - (is->unused - is->buf));
6256 (is->func)(is, is->closure, is->buf, count, count ? errno : 0);
6259 is->unused += count;
6261 /* break input into lines and call the callback function on each
6264 while (p < is->unused)
6266 q = memchr(p, '\n', is->unused - p);
6267 if (q == NULL) break;
6269 (is->func)(is, is->closure, p, q - p, 0);
6272 /* remember not yet used part of the buffer */
6274 while (p < is->unused)
6282 /* read maximum length of input buffer and send the whole buffer
6283 * to the callback function
6285 count = read(is->fd, is->buf, INPUT_SOURCE_BUF_SIZE);
6290 (is->func)(is, is->closure, is->buf, count, error);
6296 InputSourceRef AddInputSource(pr, lineByLine, func, closure)
6303 GIOChannel *channel;
6304 ChildProc *cp = (ChildProc *) pr;
6306 is = (InputSource *) calloc(1, sizeof(InputSource));
6307 is->lineByLine = lineByLine;
6311 is->fd = fileno(stdin);
6313 is->kind = cp->kind;
6314 is->fd = cp->fdFrom;
6317 is->unused = is->buf;
6321 // is->xid = XtAppAddInput(appContext, is->fd,
6322 // (XtPointer) (XtInputReadMask),
6323 // (XtInputCallbackProc) DoInputCallback,
6327 /* TODO: will this work on windows?*/
6328 printf("DEBUG: fd=%d %d\n",is->fd,is);
6330 channel = g_io_channel_unix_new(is->fd);
6331 g_io_channel_set_close_on_unref (channel, TRUE);
6332 is->sid = g_io_add_watch(channel, G_IO_IN,(GIOFunc) DoInputCallback, is);
6333 is->closure = closure;
6334 return (InputSourceRef) is;
6338 RemoveInputSource(isr)
6341 InputSource *is = (InputSource *) isr;
6343 if (is->sid == 0) return;
6344 g_source_remove(is->sid);
6349 int OutputToProcess(pr, message, count, outError)
6355 static int line = 0;
6356 ChildProc *cp = (ChildProc *) pr;
6361 if (appData.noJoin || !appData.useInternalWrap)
6362 outCount = fwrite(message, 1, count, stdout);
6365 int width = get_term_width();
6366 int len = wrap(NULL, message, count, width, &line);
6367 char *msg = malloc(len);
6371 outCount = fwrite(message, 1, count, stdout);
6374 dbgchk = wrap(msg, message, count, width, &line);
6375 if (dbgchk != len && appData.debugMode)
6376 fprintf(debugFP, "wrap(): dbgchk(%d) != len(%d)\n", dbgchk, len);
6377 outCount = fwrite(msg, 1, dbgchk, stdout);
6383 outCount = write(cp->fdTo, message, count);
6393 /* Output message to process, with "ms" milliseconds of delay
6394 between each character. This is needed when sending the logon
6395 script to ICC, which for some reason doesn't like the
6396 instantaneous send. */
6397 int OutputToProcessDelayed(pr, message, count, outError, msdelay)
6404 ChildProc *cp = (ChildProc *) pr;
6409 r = write(cp->fdTo, message++, 1);
6422 /**** Animation code by Hugh Fisher, DCS, ANU.
6424 Known problem: if a window overlapping the board is
6425 moved away while a piece is being animated underneath,
6426 the newly exposed area won't be updated properly.
6427 I can live with this.
6429 Known problem: if you look carefully at the animation
6430 of pieces in mono mode, they are being drawn as solid
6431 shapes without interior detail while moving. Fixing
6432 this would be a major complication for minimal return.
6435 /* Masks for XPM pieces. Black and white pieces can have
6436 different shapes, but in the interest of retaining my
6437 sanity pieces must have the same outline on both light
6438 and dark squares, and all pieces must use the same
6439 background square colors/images. */
6441 static int xpmDone = 0;
6444 CreateAnimMasks (pieceDepth)
6451 unsigned long plane;
6454 /* just return for gtk at the moment */
6457 /* Need a bitmap just to get a GC with right depth */
6458 buf = XCreatePixmap(xDisplay, xBoardWindow,
6460 values.foreground = 1;
6461 values.background = 0;
6462 /* Don't use XtGetGC, not read only */
6463 maskGC = XCreateGC(xDisplay, buf,
6464 GCForeground | GCBackground, &values);
6465 XFreePixmap(xDisplay, buf);
6467 buf = XCreatePixmap(xDisplay, xBoardWindow,
6468 squareSize, squareSize, pieceDepth);
6469 values.foreground = XBlackPixel(xDisplay, xScreen);
6470 values.background = XWhitePixel(xDisplay, xScreen);
6471 bufGC = XCreateGC(xDisplay, buf,
6472 GCForeground | GCBackground, &values);
6474 for (piece = WhitePawn; piece <= BlackKing; piece++) {
6475 /* Begin with empty mask */
6476 if(!xpmDone) // [HGM] pieces: keep using existing
6477 xpmMask[piece] = XCreatePixmap(xDisplay, xBoardWindow,
6478 squareSize, squareSize, 1);
6479 XSetFunction(xDisplay, maskGC, GXclear);
6480 XFillRectangle(xDisplay, xpmMask[piece], maskGC,
6481 0, 0, squareSize, squareSize);
6483 /* Take a copy of the piece */
6488 XSetFunction(xDisplay, bufGC, GXcopy);
6489 XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % (int)BlackPawn],
6491 0, 0, squareSize, squareSize, 0, 0);
6493 /* XOR the background (light) over the piece */
6494 XSetFunction(xDisplay, bufGC, GXxor);
6496 XCopyArea(xDisplay, xpmLightSquare, buf, bufGC,
6497 0, 0, squareSize, squareSize, 0, 0);
6499 XSetForeground(xDisplay, bufGC, lightSquareColor);
6500 XFillRectangle(xDisplay, buf, bufGC, 0, 0, squareSize, squareSize);
6503 /* We now have an inverted piece image with the background
6504 erased. Construct mask by just selecting all the non-zero
6505 pixels - no need to reconstruct the original image. */
6506 XSetFunction(xDisplay, maskGC, GXor);
6508 /* Might be quicker to download an XImage and create bitmap
6509 data from it rather than this N copies per piece, but it
6510 only takes a fraction of a second and there is a much
6511 longer delay for loading the pieces. */
6512 for (n = 0; n < pieceDepth; n ++) {
6513 XCopyPlane(xDisplay, buf, xpmMask[piece], maskGC,
6514 0, 0, squareSize, squareSize,
6520 XFreePixmap(xDisplay, buf);
6521 XFreeGC(xDisplay, bufGC);
6522 XFreeGC(xDisplay, maskGC);
6526 InitAnimState (anim, info)
6528 XWindowAttributes * info;
6533 /* Each buffer is square size, same depth as window */
6534 // anim->saveBuf = XCreatePixmap(xDisplay, xBoardWindow,
6535 // squareSize, squareSize, info->depth);
6536 // anim->newBuf = XCreatePixmap(xDisplay, xBoardWindow,
6537 // squareSize, squareSize, info->depth);
6539 // /* Create a plain GC for blitting */
6540 // mask = GCForeground | GCBackground | GCFunction |
6541 // GCPlaneMask | GCGraphicsExposures;
6542 // values.foreground = XBlackPixel(xDisplay, xScreen);
6543 // values.background = XWhitePixel(xDisplay, xScreen);
6544 // values.function = GXcopy;
6545 // values.plane_mask = AllPlanes;
6546 // values.graphics_exposures = False;
6547 // anim->blitGC = XCreateGC(xDisplay, xBoardWindow, mask, &values);
6549 // /* Piece will be copied from an existing context at
6550 // the start of each new animation/drag. */
6551 // anim->pieceGC = XCreateGC(xDisplay, xBoardWindow, 0, &values);
6553 // /* Outline will be a read-only copy of an existing */
6554 // anim->outlineGC = None;
6560 static VariantClass old = (VariantClass) -1; // [HGM] pieces: redo every time variant changes
6561 XWindowAttributes info;
6563 /* for gtk at the moment just ... */
6566 if (xpmDone && gameInfo.variant == old) return;
6567 if(xpmDone) old = gameInfo.variant; // first time pieces might not be created yet
6568 // XGetWindowAttributes(xDisplay, xBoardWindow, &info);
6570 // InitAnimState(&game, &info);
6571 // InitAnimState(&player, &info);
6573 /* For XPM pieces, we need bitmaps to use as masks. */
6575 // CreateAnimMasks(info.depth);
6581 static Boolean frameWaiting;
6583 static RETSIGTYPE FrameAlarm (sig)
6586 frameWaiting = False;
6587 /* In case System-V style signals. Needed?? */
6588 signal(SIGALRM, FrameAlarm);
6595 struct itimerval delay;
6597 XSync(xDisplay, False);
6600 frameWaiting = True;
6601 signal(SIGALRM, FrameAlarm);
6602 delay.it_interval.tv_sec =
6603 delay.it_value.tv_sec = time / 1000;
6604 delay.it_interval.tv_usec =
6605 delay.it_value.tv_usec = (time % 1000) * 1000;
6606 setitimer(ITIMER_REAL, &delay, NULL);
6607 while (frameWaiting) pause();
6608 delay.it_interval.tv_sec = delay.it_value.tv_sec = 0;
6609 delay.it_interval.tv_usec = delay.it_value.tv_usec = 0;
6610 setitimer(ITIMER_REAL, &delay, NULL);
6620 // XSync(xDisplay, False);
6622 usleep(time * 1000);
6627 /* Convert board position to corner of screen rect and color */
6630 ScreenSquare(column, row, pt, color)
6631 int column; int row; XPoint * pt; int * color;
6634 pt->x = lineGap + ((BOARD_WIDTH-1)-column) * (squareSize + lineGap);
6635 pt->y = lineGap + row * (squareSize + lineGap);
6637 pt->x = lineGap + column * (squareSize + lineGap);
6638 pt->y = lineGap + ((BOARD_HEIGHT-1)-row) * (squareSize + lineGap);
6640 *color = SquareColor(row, column);
6643 /* Convert window coords to square */
6646 BoardSquare(x, y, column, row)
6647 int x; int y; int * column; int * row;
6649 *column = EventToSquare(x, BOARD_WIDTH);
6650 if (flipView && *column >= 0)
6651 *column = BOARD_WIDTH - 1 - *column;
6652 *row = EventToSquare(y, BOARD_HEIGHT);
6653 if (!flipView && *row >= 0)
6654 *row = BOARD_HEIGHT - 1 - *row;
6659 #undef Max /* just in case */
6661 #define Max(a, b) ((a) > (b) ? (a) : (b))
6662 #define Min(a, b) ((a) < (b) ? (a) : (b))
6665 SetRect(rect, x, y, width, height)
6666 XRectangle * rect; int x; int y; int width; int height;
6670 rect->width = width;
6671 rect->height = height;
6674 /* Test if two frames overlap. If they do, return
6675 intersection rect within old and location of
6676 that rect within new. */
6679 Intersect(old, new, size, area, pt)
6680 XPoint * old; XPoint * new;
6681 int size; XRectangle * area; XPoint * pt;
6683 if (old->x > new->x + size || new->x > old->x + size ||
6684 old->y > new->y + size || new->y > old->y + size) {
6687 SetRect(area, Max(new->x - old->x, 0), Max(new->y - old->y, 0),
6688 size - abs(old->x - new->x), size - abs(old->y - new->y));
6689 pt->x = Max(old->x - new->x, 0);
6690 pt->y = Max(old->y - new->y, 0);
6695 /* For two overlapping frames, return the rect(s)
6696 in the old that do not intersect with the new. */
6699 CalcUpdateRects(old, new, size, update, nUpdates)
6700 XPoint * old; XPoint * new; int size;
6701 XRectangle update[]; int * nUpdates;
6705 /* If old = new (shouldn't happen) then nothing to draw */
6706 if (old->x == new->x && old->y == new->y) {
6710 /* Work out what bits overlap. Since we know the rects
6711 are the same size we don't need a full intersect calc. */
6713 /* Top or bottom edge? */
6714 if (new->y > old->y) {
6715 SetRect(&(update[count]), old->x, old->y, size, new->y - old->y);
6717 } else if (old->y > new->y) {
6718 SetRect(&(update[count]), old->x, old->y + size - (old->y - new->y),
6719 size, old->y - new->y);
6722 /* Left or right edge - don't overlap any update calculated above. */
6723 if (new->x > old->x) {
6724 SetRect(&(update[count]), old->x, Max(new->y, old->y),
6725 new->x - old->x, size - abs(new->y - old->y));
6727 } else if (old->x > new->x) {
6728 SetRect(&(update[count]), new->x + size, Max(new->y, old->y),
6729 old->x - new->x, size - abs(new->y - old->y));
6736 /* Generate a series of frame coords from start->mid->finish.
6737 The movement rate doubles until the half way point is
6738 reached, then halves back down to the final destination,
6739 which gives a nice slow in/out effect. The algorithmn
6740 may seem to generate too many intermediates for short
6741 moves, but remember that the purpose is to attract the
6742 viewers attention to the piece about to be moved and
6743 then to where it ends up. Too few frames would be less
6747 Tween(start, mid, finish, factor, frames, nFrames)
6748 XPoint * start; XPoint * mid;
6749 XPoint * finish; int factor;
6750 XPoint frames[]; int * nFrames;
6752 int fraction, n, count;
6756 /* Slow in, stepping 1/16th, then 1/8th, ... */
6758 for (n = 0; n < factor; n++)
6760 for (n = 0; n < factor; n++) {
6761 frames[count].x = start->x + (mid->x - start->x) / fraction;
6762 frames[count].y = start->y + (mid->y - start->y) / fraction;
6764 fraction = fraction / 2;
6768 frames[count] = *mid;
6771 /* Slow out, stepping 1/2, then 1/4, ... */
6773 for (n = 0; n < factor; n++) {
6774 frames[count].x = finish->x - (finish->x - mid->x) / fraction;
6775 frames[count].y = finish->y - (finish->y - mid->y) / fraction;
6777 fraction = fraction * 2;
6782 /* Draw a piece on the screen without disturbing what's there */
6785 SelectGCMask(piece, clip, outline, mask)
6786 ChessSquare piece; GC * clip; GC * outline; Pixmap * mask;
6790 /* Bitmap for piece being moved. */
6791 if (appData.monoMode) {
6792 *mask = *pieceToSolid(piece);
6793 } else if (useImages) {
6795 *mask = xpmMask[piece];
6797 *mask = ximMaskPm[piece];
6800 *mask = *pieceToSolid(piece);
6803 /* GC for piece being moved. Square color doesn't matter, but
6804 since it gets modified we make a copy of the original. */
6806 if (appData.monoMode)
6811 if (appData.monoMode)
6816 // XCopyGC(xDisplay, source, 0xFFFFFFFF, *clip);
6818 /* Outline only used in mono mode and is not modified */
6820 *outline = bwPieceGC;
6822 *outline = wbPieceGC;
6826 OverlayPiece(piece, clip, outline, dest)
6827 ChessSquare piece; GC clip; GC outline; Drawable dest;
6832 /* Draw solid rectangle which will be clipped to shape of piece */
6833 // XFillRectangle(xDisplay, dest, clip,
6834 // 0, 0, squareSize, squareSize)
6836 if (appData.monoMode)
6837 /* Also draw outline in contrasting color for black
6838 on black / white on white cases */
6839 // XCopyPlane(xDisplay, *pieceToOutline(piece), dest, outline,
6840 // 0, 0, squareSize, squareSize, 0, 0, 1)
6843 /* Copy the piece */
6848 // XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
6850 // 0, 0, squareSize, squareSize,
6855 /* Animate the movement of a single piece */
6858 BeginAnimation(anim, piece, startColor, start)
6866 /* The old buffer is initialised with the start square (empty) */
6867 BlankSquare(0, 0, startColor, EmptySquare, anim->saveBuf);
6868 anim->prevFrame = *start;
6870 /* The piece will be drawn using its own bitmap as a matte */
6871 // SelectGCMask(piece, &anim->pieceGC, &anim->outlineGC, &mask);
6872 // XSetClipMask(xDisplay, anim->pieceGC, mask);
6876 AnimationFrame(anim, frame, piece)
6881 XRectangle updates[4];
6886 /* Save what we are about to draw into the new buffer */
6887 // XCopyArea(xDisplay, xBoardWindow, anim->newBuf, anim->blitGC,
6888 // frame->x, frame->y, squareSize, squareSize,
6891 /* Erase bits of the previous frame */
6892 if (Intersect(&anim->prevFrame, frame, squareSize, &overlap, &pt)) {
6893 /* Where the new frame overlapped the previous,
6894 the contents in newBuf are wrong. */
6895 // XCopyArea(xDisplay, anim->saveBuf, anim->newBuf, anim->blitGC,
6896 // overlap.x, overlap.y,
6897 // overlap.width, overlap.height,
6899 /* Repaint the areas in the old that don't overlap new */
6900 CalcUpdateRects(&anim->prevFrame, frame, squareSize, updates, &count);
6901 for (i = 0; i < count; i++)
6902 // XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
6903 // updates[i].x - anim->prevFrame.x,
6904 // updates[i].y - anim->prevFrame.y,
6905 // updates[i].width, updates[i].height,
6906 // updates[i].x, updates[i].y)
6909 /* Easy when no overlap */
6910 // XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
6911 // 0, 0, squareSize, squareSize,
6912 // anim->prevFrame.x, anim->prevFrame.y);
6915 /* Save this frame for next time round */
6916 // XCopyArea(xDisplay, anim->newBuf, anim->saveBuf, anim->blitGC,
6917 // 0, 0, squareSize, squareSize,
6919 anim->prevFrame = *frame;
6921 /* Draw piece over original screen contents, not current,
6922 and copy entire rect. Wipes out overlapping piece images. */
6923 OverlayPiece(piece, anim->pieceGC, anim->outlineGC, anim->newBuf);
6924 // XCopyArea(xDisplay, anim->newBuf, xBoardWindow, anim->blitGC,
6925 // 0, 0, squareSize, squareSize,
6926 // frame->x, frame->y);
6930 EndAnimation (anim, finish)
6934 XRectangle updates[4];
6939 /* The main code will redraw the final square, so we
6940 only need to erase the bits that don't overlap. */
6941 if (Intersect(&anim->prevFrame, finish, squareSize, &overlap, &pt)) {
6942 CalcUpdateRects(&anim->prevFrame, finish, squareSize, updates, &count);
6943 for (i = 0; i < count; i++)
6944 // XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
6945 // updates[i].x - anim->prevFrame.x,
6946 // updates[i].y - anim->prevFrame.y,
6947 // updates[i].width, updates[i].height,
6948 // updates[i].x, updates[i].y)
6951 // XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
6952 // 0, 0, squareSize, squareSize,
6953 // anim->prevFrame.x, anim->prevFrame.y);
6958 FrameSequence(anim, piece, startColor, start, finish, frames, nFrames)
6960 ChessSquare piece; int startColor;
6961 XPoint * start; XPoint * finish;
6962 XPoint frames[]; int nFrames;
6966 BeginAnimation(anim, piece, startColor, start);
6967 for (n = 0; n < nFrames; n++) {
6968 AnimationFrame(anim, &(frames[n]), piece);
6969 FrameDelay(appData.animSpeed);
6971 EndAnimation(anim, finish);
6974 /* Main control logic for deciding what to animate and how */
6977 AnimateMove(board, fromX, fromY, toX, toY)
6986 XPoint start, finish, mid;
6987 XPoint frames[kFactor * 2 + 1];
6988 int nFrames, startColor, endColor;
6990 /* Are we animating? */
6991 if (!appData.animate || appData.blindfold)
6994 if(board[toY][toX] == WhiteRook && board[fromY][fromX] == WhiteKing ||
6995 board[toY][toX] == BlackRook && board[fromY][fromX] == BlackKing)
6996 return; // [HGM] FRC: no animtion of FRC castlings, as to-square is not true to-square
6998 if (fromY < 0 || fromX < 0 || toX < 0 || toY < 0) return;
6999 piece = board[fromY][fromX];
7000 if (piece >= EmptySquare) return;
7005 hop = (piece == WhiteKnight || piece == BlackKnight);
7008 if (appData.debugMode) {
7009 fprintf(debugFP, hop ? _("AnimateMove: piece %d hops from %d,%d to %d,%d \n") :
7010 _("AnimateMove: piece %d slides from %d,%d to %d,%d \n"),
7011 piece, fromX, fromY, toX, toY); }
7013 ScreenSquare(fromX, fromY, &start, &startColor);
7014 ScreenSquare(toX, toY, &finish, &endColor);
7017 /* Knight: make diagonal movement then straight */
7018 if (abs(toY - fromY) < abs(toX - fromX)) {
7019 mid.x = start.x + (finish.x - start.x) / 2;
7023 mid.y = start.y + (finish.y - start.y) / 2;
7026 mid.x = start.x + (finish.x - start.x) / 2;
7027 mid.y = start.y + (finish.y - start.y) / 2;
7030 /* Don't use as many frames for very short moves */
7031 if (abs(toY - fromY) + abs(toX - fromX) <= 2)
7032 Tween(&start, &mid, &finish, kFactor - 1, frames, &nFrames);
7034 Tween(&start, &mid, &finish, kFactor, frames, &nFrames);
7035 FrameSequence(&game, piece, startColor, &start, &finish, frames, nFrames);
7037 /* Be sure end square is redrawn */
7038 damage[toY][toX] = True;
7042 DragPieceBegin(x, y)
7045 int boardX, boardY, color;
7048 /* Are we animating? */
7049 if (!appData.animateDragging || appData.blindfold)
7052 /* Figure out which square we start in and the
7053 mouse position relative to top left corner. */
7054 BoardSquare(x, y, &boardX, &boardY);
7055 player.startBoardX = boardX;
7056 player.startBoardY = boardY;
7057 ScreenSquare(boardX, boardY, &corner, &color);
7058 player.startSquare = corner;
7059 player.startColor = color;
7060 /* As soon as we start dragging, the piece will jump slightly to
7061 be centered over the mouse pointer. */
7062 player.mouseDelta.x = squareSize/2;
7063 player.mouseDelta.y = squareSize/2;
7064 /* Initialise animation */
7065 player.dragPiece = PieceForSquare(boardX, boardY);
7067 if (player.dragPiece >= 0 && player.dragPiece < EmptySquare) {
7068 player.dragActive = True;
7069 BeginAnimation(&player, player.dragPiece, color, &corner);
7070 /* Mark this square as needing to be redrawn. Note that
7071 we don't remove the piece though, since logically (ie
7072 as seen by opponent) the move hasn't been made yet. */
7073 if(boardX == BOARD_RGHT+1 && PieceForSquare(boardX-1, boardY) > 1 ||
7074 boardX == BOARD_LEFT-2 && PieceForSquare(boardX+1, boardY) > 1)
7075 // XCopyArea(xDisplay, xBoardWindow, player.saveBuf, player.blitGC,
7076 // corner.x, corner.y, squareSize, squareSize,
7077 // 0, 0); // [HGM] zh: unstack in stead of grab
7078 damage[boardY][boardX] = True;
7080 player.dragActive = False;
7090 /* Are we animating? */
7091 if (!appData.animateDragging || appData.blindfold)
7095 if (! player.dragActive)
7097 /* Move piece, maintaining same relative position
7098 of mouse within square */
7099 corner.x = x - player.mouseDelta.x;
7100 corner.y = y - player.mouseDelta.y;
7101 AnimationFrame(&player, &corner, player.dragPiece);
7103 if (appData.highlightDragging) {
7105 BoardSquare(x, y, &boardX, &boardY);
7106 SetHighlights(fromX, fromY, boardX, boardY);
7115 int boardX, boardY, color;
7118 /* Are we animating? */
7119 if (!appData.animateDragging || appData.blindfold)
7123 if (! player.dragActive)
7125 /* Last frame in sequence is square piece is
7126 placed on, which may not match mouse exactly. */
7127 BoardSquare(x, y, &boardX, &boardY);
7128 ScreenSquare(boardX, boardY, &corner, &color);
7129 EndAnimation(&player, &corner);
7131 /* Be sure end square is redrawn */
7132 damage[boardY][boardX] = True;
7134 /* This prevents weird things happening with fast successive
7135 clicks which on my Sun at least can cause motion events
7136 without corresponding press/release. */
7137 player.dragActive = False;
7140 /* Handle expose event while piece being dragged */
7145 if (!player.dragActive || appData.blindfold)
7148 /* What we're doing: logically, the move hasn't been made yet,
7149 so the piece is still in it's original square. But visually
7150 it's being dragged around the board. So we erase the square
7151 that the piece is on and draw it at the last known drag point. */
7152 BlankSquare(player.startSquare.x, player.startSquare.y,
7153 player.startColor, EmptySquare, xBoardWindow);
7154 AnimationFrame(&player, &player.prevFrame, player.dragPiece);
7155 damage[player.startBoardY][player.startBoardX] = TRUE;
7159 SetProgramStats( FrontEndProgramStats * stats )
7162 // [HGM] done, but perhaps backend should call this directly?
7163 EngineOutputUpdate( stats );
7166 #include <sys/ioctl.h>
7167 int get_term_width()
7169 int fd, default_width;
7172 default_width = 79; // this is FICS default anyway...
7174 #if !defined(TIOCGWINSZ) && defined(TIOCGSIZE)
7176 if (!ioctl(fd, TIOCGSIZE, &win))
7177 default_width = win.ts_cols;
7178 #elif defined(TIOCGWINSZ)
7180 if (!ioctl(fd, TIOCGWINSZ, &win))
7181 default_width = win.ws_col;
7183 return default_width;
7186 void update_ics_width()
7188 static int old_width = 0;
7189 int new_width = get_term_width();
7191 if (old_width != new_width)
7192 ics_printf("set width %d\n", new_width);
7193 old_width = new_width;
7196 void NotifyFrontendLogin()