2 * xboard.c -- X front end for XBoard
4 * Copyright 1991 by Digital Equipment Corporation, Maynard,
7 * Enhancements Copyright 1992-2001, 2002, 2003, 2004, 2005, 2006,
8 * 2007, 2008, 2009 Free Software Foundation, Inc.
10 * The following terms apply to Digital Equipment Corporation's copyright
12 * ------------------------------------------------------------------------
15 * Permission to use, copy, modify, and distribute this software and its
16 * documentation for any purpose and without fee is hereby granted,
17 * provided that the above copyright notice appear in all copies and that
18 * both that copyright notice and this permission notice appear in
19 * supporting documentation, and that the name of Digital not be
20 * used in advertising or publicity pertaining to distribution of the
21 * software without specific, written prior permission.
23 * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
24 * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
25 * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
26 * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
27 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
28 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
30 * ------------------------------------------------------------------------
32 * The following terms apply to the enhanced version of XBoard
33 * distributed by the Free Software Foundation:
34 * ------------------------------------------------------------------------
36 * GNU XBoard is free software: you can redistribute it and/or modify
37 * it under the terms of the GNU General Public License as published by
38 * the Free Software Foundation, either version 3 of the License, or (at
39 * your option) any later version.
41 * GNU XBoard is distributed in the hope that it will be useful, but
42 * WITHOUT ANY WARRANTY; without even the implied warranty of
43 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
44 * General Public License for more details.
46 * You should have received a copy of the GNU General Public License
47 * along with this program. If not, see http://www.gnu.org/licenses/. *
49 *------------------------------------------------------------------------
50 ** See the file ChangeLog for a revision history. */
58 #include <sys/types.h>
63 # if HAVE_SYS_SOCKET_H
64 # include <sys/socket.h>
65 # include <netinet/in.h>
67 # else /* not HAVE_SYS_SOCKET_H */
68 # if HAVE_LAN_SOCKET_H
69 # include <lan/socket.h>
71 # include <lan/netdb.h>
72 # else /* not HAVE_LAN_SOCKET_H */
73 # define OMIT_SOCKETS 1
74 # endif /* not HAVE_LAN_SOCKET_H */
75 # endif /* not HAVE_SYS_SOCKET_H */
76 #endif /* !OMIT_SOCKETS */
81 #else /* not STDC_HEADERS */
82 extern char *getenv();
85 # else /* not HAVE_STRING_H */
87 # endif /* not HAVE_STRING_H */
88 #endif /* not STDC_HEADERS */
91 # include <sys/fcntl.h>
92 #else /* not HAVE_SYS_FCNTL_H */
95 # endif /* HAVE_FCNTL_H */
96 #endif /* not HAVE_SYS_FCNTL_H */
98 #if HAVE_SYS_SYSTEMINFO_H
99 # include <sys/systeminfo.h>
100 #endif /* HAVE_SYS_SYSTEMINFO_H */
102 #if TIME_WITH_SYS_TIME
103 # include <sys/time.h>
107 # include <sys/time.h>
118 # include <sys/wait.h>
123 # define NAMLEN(dirent) strlen((dirent)->d_name)
124 # define HAVE_DIR_STRUCT
126 # define dirent direct
127 # define NAMLEN(dirent) (dirent)->d_namlen
129 # include <sys/ndir.h>
130 # define HAVE_DIR_STRUCT
133 # include <sys/dir.h>
134 # define HAVE_DIR_STRUCT
138 # define HAVE_DIR_STRUCT
142 #include <X11/Intrinsic.h>
143 #include <X11/StringDefs.h>
144 #include <X11/Shell.h>
145 #include <X11/cursorfont.h>
146 #include <X11/Xatom.h>
148 #include <X11/Xaw3d/Dialog.h>
149 #include <X11/Xaw3d/Form.h>
150 #include <X11/Xaw3d/List.h>
151 #include <X11/Xaw3d/Label.h>
152 #include <X11/Xaw3d/SimpleMenu.h>
153 #include <X11/Xaw3d/SmeBSB.h>
154 #include <X11/Xaw3d/SmeLine.h>
155 #include <X11/Xaw3d/Box.h>
156 #include <X11/Xaw3d/MenuButton.h>
157 #include <X11/Xaw3d/Text.h>
158 #include <X11/Xaw3d/AsciiText.h>
160 #include <X11/Xaw/Dialog.h>
161 #include <X11/Xaw/Form.h>
162 #include <X11/Xaw/List.h>
163 #include <X11/Xaw/Label.h>
164 #include <X11/Xaw/SimpleMenu.h>
165 #include <X11/Xaw/SmeBSB.h>
166 #include <X11/Xaw/SmeLine.h>
167 #include <X11/Xaw/Box.h>
168 #include <X11/Xaw/MenuButton.h>
169 #include <X11/Xaw/Text.h>
170 #include <X11/Xaw/AsciiText.h>
173 // [HGM] bitmaps: put before incuding the bitmaps / pixmaps, to know how many piece types there are.
178 #include "pixmaps/pixmaps.h"
179 #define IMAGE_EXT "xpm"
181 #define IMAGE_EXT "xim"
182 #include "bitmaps/bitmaps.h"
187 #include <gdk-pixbuf/gdk-pixbuf.h>
189 #include "bitmaps/icon_white.bm"
190 #include "bitmaps/icon_black.bm"
191 #include "bitmaps/checkmark.bm"
193 #include "frontend.h"
198 #include "xgamelist.h"
199 #include "xhistory.h"
200 #include "xedittags.h"
202 #include "callback.h"
203 #include "interface.h"
205 // must be moved to xengineoutput.h
207 void EngineOutputProc P((Widget w, XEvent *event,
208 String *prms, Cardinal *nprms));
210 void EngineOutputPopDown();
217 #define usleep(t) _sleep2(((t)+500)/1000)
221 # define _(s) gettext (s)
222 # define N_(s) gettext_noop (s)
245 int main P((int argc, char **argv));
246 RETSIGTYPE CmailSigHandler P((int sig));
247 RETSIGTYPE IntSigHandler P((int sig));
248 RETSIGTYPE TermSizeSigHandler P((int sig));
249 void CreateGCs P((void));
250 void CreateXIMPieces P((void));
251 void CreateXPMPieces P((void));
252 void CreatePieces P((void));
253 void CreatePieceMenus P((void));
254 Widget CreateMenuBar P((Menu *mb));
255 char *FindFont P((char *pattern, int targetPxlSize));
256 void PieceMenuPopup P((Widget w, XEvent *event,
257 String *params, Cardinal *num_params));
258 static void PieceMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
259 static void DropMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
260 int EventToSquare P((int x, int limit));
261 void DrawSquare P((int row, int column, ChessSquare piece, int do_flash));
262 void HandleUserMove P((Widget w, XEvent *event,
263 String *prms, Cardinal *nprms));
264 void AnimateUserMove P((Widget w, XEvent * event,
265 String * params, Cardinal * nParams));
266 void CommentPopUp P((char *title, char *label));
267 void CommentPopDown P((void));
268 void CommentCallback P((Widget w, XtPointer client_data,
269 XtPointer call_data));
270 void ICSInputBoxPopUp P((void));
271 void ICSInputBoxPopDown P((void));
272 void AskQuestionReplyAction P((Widget w, XEvent *event,
273 String *prms, Cardinal *nprms));
274 void AskQuestionProc P((Widget w, XEvent *event,
275 String *prms, Cardinal *nprms));
276 void AskQuestionPopDown P((void));
277 void PromotionPopUp P((void));
278 void PromotionPopDown P((void));
279 void PromotionCallback P((Widget w, XtPointer client_data,
280 XtPointer call_data));
281 void EditCommentPopDown P((void));
282 void EditCommentCallback P((Widget w, XtPointer client_data,
283 XtPointer call_data));
284 void SelectCommand P((Widget w, XtPointer client_data, XtPointer call_data));
285 void CopyPositionProc P((Widget w, XEvent *event, String *prms,
287 void PastePositionProc P((Widget w, XEvent *event, String *prms,
289 void CopyGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
290 void PasteGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
291 void MailMoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
292 void ReloadCmailMsgProc P((Widget w, XEvent *event, String *prms,
294 void AnalyzeModeProc P((Widget w, XEvent *event,
295 String *prms, Cardinal *nprms));
296 void EditGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
297 void EditPositionProc P((Widget w, XEvent *event,
298 String *prms, Cardinal *nprms));
299 void TrainingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
300 void EditCommentProc P((Widget w, XEvent *event,
301 String *prms, Cardinal *nprms));
302 void IcsInputBoxProc P((Widget w, XEvent *event,
303 String *prms, Cardinal *nprms));
304 void EnterKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
305 void PonderNextMoveProc P((Widget w, XEvent *event, String *prms,
307 void PopupMoveErrorsProc P((Widget w, XEvent *event, String *prms,
309 void PopupExitMessageProc P((Widget w, XEvent *event, String *prms,
311 void PremoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
312 void QuietPlayProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
313 void AboutGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
314 void DebugProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
315 void NothingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
316 void Iconify P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
317 void DisplayMove P((int moveNumber));
318 void DisplayTitle P((char *title));
319 void ICSInitScript P((void));
320 int LoadGamePopUp P((FILE *f, int gameNumber, char *title));
321 void ErrorPopUp P((char *title, char *text, int modal));
322 void ErrorPopDown P((void));
323 static char *ExpandPathName P((char *path));
324 static void CreateAnimVars P((void));
325 void DragPieceBegin P((int x, int y));
326 static void DragPieceMove P((int x, int y));
327 void DragPieceEnd P((int x, int y));
328 static void DrawDragPiece P((void));
329 char *ModeToWidgetName P((GameMode mode));
330 void EngineOutputUpdate( FrontEndProgramStats * stats );
331 void ShuffleMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
332 void EngineMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
333 void UciMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
334 void TimeControlProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
335 void NewVariantProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
336 void FirstSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
337 void SecondSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
338 void ShufflePopDown P(());
339 void EnginePopDown P(());
340 void UciPopDown P(());
341 void TimeControlPopDown P(());
342 void NewVariantPopDown P(());
343 void SettingsPopDown P(());
344 void SetMenuEnables P((Enables *enab));
345 void update_ics_width P(());
346 int get_term_width P(());
348 * XBoard depends on Xt R4 or higher
350 int xtVersion = XtSpecificationRelease;
355 Pixel lightSquareColor, darkSquareColor, whitePieceColor, blackPieceColor,
356 jailSquareColor, highlightSquareColor, premoveHighlightColor;
357 Pixel lowTimeWarningColor;
359 #define LINE_TYPE_NORMAL 0
360 #define LINE_TYPE_HIGHLIGHT 1
361 #define LINE_TYPE_PRE 2
364 GC lightSquareGC, darkSquareGC, jailSquareGC, wdPieceGC, wlPieceGC,
365 bdPieceGC, blPieceGC, wbPieceGC, bwPieceGC, coordGC,
366 wjPieceGC, bjPieceGC;
367 Pixmap iconPixmap, wIconPixmap, bIconPixmap, xMarkPixmap;
368 Widget shellWidget, layoutWidget, formWidget, boardWidget, messageWidget,
369 whiteTimerWidget, blackTimerWidget, titleWidget, widgetList[16],
370 commentShell, promotionShell, whitePieceMenu, blackPieceMenu, dropMenu,
371 menuBarWidget, editShell, errorShell, analysisShell,
372 ICSInputShell, fileNameShell, askQuestionShell;
373 Font clockFontID, coordFontID, countFontID;
374 XFontStruct *clockFontStruct, *coordFontStruct, *countFontStruct;
375 XtAppContext appContext;
377 char *oldICSInteractionTitle;
381 char installDir[] = "."; // [HGM] UCI: needed for UCI; probably needs run-time initializtion
383 Position commentX = -1, commentY = -1;
384 Dimension commentW, commentH;
386 int squareSize, smallLayout = 0, tinyLayout = 0,
387 marginW, marginH, // [HGM] for run-time resizing
388 fromX = -1, fromY = -1, toX, toY, commentUp = False, analysisUp = False,
389 ICSInputBoxUp = False, askQuestionUp = False,
390 filenameUp = False, promotionUp = False, pmFromX = -1, pmFromY = -1,
391 editUp = False, errorUp = False, errorExitStatus = -1, lineGap;
392 Pixel timerForegroundPixel, timerBackgroundPixel;
393 Pixel buttonForegroundPixel, buttonBackgroundPixel;
394 char *chessDir, *programName, *programVersion,
395 *gameCopyFilename, *gamePasteFilename;
399 Pixmap pieceBitmap[2][(int)BlackPawn];
400 Pixmap pieceBitmap2[2][(int)BlackPawn+4]; /* [HGM] pieces */
401 Pixmap xpmPieceBitmap[4][(int)BlackPawn]; /* LL, LD, DL, DD actually used*/
402 Pixmap xpmPieceBitmap2[4][(int)BlackPawn+4]; /* LL, LD, DL, DD set to select from */
403 Pixmap xpmLightSquare, xpmDarkSquare, xpmJailSquare;
404 int useImages=0, useImageSqs;
405 XImage *ximPieceBitmap[4][(int)BlackPawn+4]; /* LL, LD, DL, DD */
406 Pixmap ximMaskPm[(int)BlackPawn]; /* clipmasks, used for XIM pieces */
407 Pixmap ximMaskPm2[(int)BlackPawn+4]; /* clipmasks, used for XIM pieces */
408 XImage *ximLightSquare, *ximDarkSquare;
411 #define pieceToSolid(piece) &pieceBitmap[SOLID][(piece) % (int)BlackPawn]
412 #define pieceToOutline(piece) &pieceBitmap[OUTLINE][(piece) % (int)BlackPawn]
414 #define White(piece) ((int)(piece) < (int)BlackPawn)
416 /* Variables for doing smooth animation. This whole thing
417 would be much easier if the board was double-buffered,
418 but that would require a fairly major rewrite. */
423 GC blitGC, pieceGC, outlineGC;
424 XPoint startSquare, prevFrame, mouseDelta;
428 int startBoardX, startBoardY;
431 /* There can be two pieces being animated at once: a player
432 can begin dragging a piece before the remote opponent has moved. */
434 static AnimState game, player;
436 /* Bitmaps for use as masks when drawing XPM pieces.
437 Need one for each black and white piece. */
438 static Pixmap xpmMask[BlackKing + 1];
440 /* This magic number is the number of intermediate frames used
441 in each half of the animation. For short moves it's reduced
442 by 1. The total number of frames will be factor * 2 + 1. */
445 SizeDefaults sizeDefaults[] = SIZE_DEFAULTS;
447 Enables icsEnables[] = {
448 { "menuFile.Mail Move", False },
449 { "menuFile.Reload CMail Message", False },
450 { "menuMode.Machine Black", False },
451 { "menuMode.Machine White", False },
452 { "menuMode.Analysis Mode", False },
453 { "menuMode.Analyze File", False },
454 { "menuMode.Two Machines", False },
456 { "menuHelp.Hint", False },
457 { "menuHelp.Book", False },
458 { "menuStep.Move Now", False },
459 { "menuOptions.Periodic Updates", False },
460 { "menuOptions.Hide Thinking", False },
461 { "menuOptions.Ponder Next Move", False },
466 Enables ncpEnables[] = {
467 { "menuFile.Mail Move", False },
468 { "menuFile.Reload CMail Message", False },
469 { "menuMode.Machine White", False },
470 { "menuMode.Machine Black", False },
471 { "menuMode.Analysis Mode", False },
472 { "menuMode.Analyze File", False },
473 { "menuMode.Two Machines", False },
474 { "menuMode.ICS Client", False },
475 { "menuMode.ICS Input Box", False },
477 { "menuStep.Revert", False },
478 { "menuStep.Move Now", False },
479 { "menuStep.Retract Move", False },
480 { "menuOptions.Auto Comment", False },
481 { "menuOptions.Auto Flag", False },
482 { "menuOptions.Auto Flip View", False },
483 { "menuOptions.Auto Observe", False },
484 { "menuOptions.Auto Raise Board", False },
485 { "menuOptions.Get Move List", False },
486 { "menuOptions.ICS Alarm", False },
487 { "menuOptions.Move Sound", False },
488 { "menuOptions.Quiet Play", False },
489 { "menuOptions.Hide Thinking", False },
490 { "menuOptions.Periodic Updates", False },
491 { "menuOptions.Ponder Next Move", False },
492 { "menuHelp.Hint", False },
493 { "menuHelp.Book", False },
497 Enables gnuEnables[] = {
498 { "menuMode.ICS Client", False },
499 { "menuMode.ICS Input Box", False },
500 { "menuAction.Accept", False },
501 { "menuAction.Decline", False },
502 { "menuAction.Rematch", False },
503 { "menuAction.Adjourn", False },
504 { "menuAction.Stop Examining", False },
505 { "menuAction.Stop Observing", False },
506 { "menuStep.Revert", False },
507 { "menuOptions.Auto Comment", False },
508 { "menuOptions.Auto Observe", False },
509 { "menuOptions.Auto Raise Board", False },
510 { "menuOptions.Get Move List", False },
511 { "menuOptions.Premove", False },
512 { "menuOptions.Quiet Play", False },
514 /* The next two options rely on SetCmailMode being called *after* */
515 /* SetGNUMode so that when GNU is being used to give hints these */
516 /* menu options are still available */
518 { "menuFile.Mail Move", False },
519 { "menuFile.Reload CMail Message", False },
523 Enables cmailEnables[] = {
525 { "menuAction.Call Flag", False },
526 { "menuAction.Draw", True },
527 { "menuAction.Adjourn", False },
528 { "menuAction.Abort", False },
529 { "menuAction.Stop Observing", False },
530 { "menuAction.Stop Examining", False },
531 { "menuFile.Mail Move", True },
532 { "menuFile.Reload CMail Message", True },
536 Enables trainingOnEnables[] = {
537 { "menuMode.Edit Comment", False },
538 { "menuMode.Pause", False },
539 { "menuStep.Forward", False },
540 { "menuStep.Backward", False },
541 { "menuStep.Forward to End", False },
542 { "menuStep.Back to Start", False },
543 { "menuStep.Move Now", False },
544 { "menuStep.Truncate Game", False },
548 Enables trainingOffEnables[] = {
549 { "menuMode.Edit Comment", True },
550 { "menuMode.Pause", True },
551 { "menuStep.Forward", True },
552 { "menuStep.Backward", True },
553 { "menuStep.Forward to End", True },
554 { "menuStep.Back to Start", True },
555 { "menuStep.Move Now", True },
556 { "menuStep.Truncate Game", True },
560 Enables machineThinkingEnables[] = {
561 { "menuFile.Load Game", False },
562 { "menuFile.Load Next Game", False },
563 { "menuFile.Load Previous Game", False },
564 { "menuFile.Reload Same Game", False },
565 { "menuFile.Paste Game", False },
566 { "menuFile.Load Position", False },
567 { "menuFile.Load Next Position", False },
568 { "menuFile.Load Previous Position", False },
569 { "menuFile.Reload Same Position", False },
570 { "menuFile.Paste Position", False },
571 { "menuMode.Machine White", False },
572 { "menuMode.Machine Black", False },
573 { "menuMode.Two Machines", False },
574 { "menuStep.Retract Move", False },
578 Enables userThinkingEnables[] = {
579 { "menuFile.Load Game", True },
580 { "menuFile.Load Next Game", True },
581 { "menuFile.Load Previous Game", True },
582 { "menuFile.Reload Same Game", True },
583 { "menuFile.Paste Game", True },
584 { "menuFile.Load Position", True },
585 { "menuFile.Load Next Position", True },
586 { "menuFile.Load Previous Position", True },
587 { "menuFile.Reload Same Position", True },
588 { "menuFile.Paste Position", True },
589 { "menuMode.Machine White", True },
590 { "menuMode.Machine Black", True },
591 { "menuMode.Two Machines", True },
592 { "menuStep.Retract Move", True },
598 MenuItem fileMenu[] = {
599 {N_("New Shuffle Game ..."), ShuffleMenuProc},
600 {N_("New Variant ..."), NewVariantProc}, // [HGM] variant: not functional yet
601 // {"----", NothingProc},
602 // {N_("Save Game"), SaveGameProc},
603 // {"----", NothingProc},
604 {N_("Copy Game"), CopyGameProc},
605 {N_("Paste Game"), PasteGameProc},
606 // {"----", NothingProc},
607 // {N_("Load Position"), LoadPositionProc},
608 // {N_("Load Next Position"), LoadNextPositionProc},
609 // {N_("Load Previous Position"), LoadPrevPositionProc},
610 // {N_("Reload Same Position"), ReloadPositionProc},
611 // {N_("Save Position"), SavePositionProc},
612 // {"----", NothingProc},
613 {N_("Copy Position"), CopyPositionProc},
614 {N_("Paste Position"), PastePositionProc},
615 // {"----", NothingProc},
616 {N_("Mail Move"), MailMoveProc},
617 {N_("Reload CMail Message"), ReloadCmailMsgProc},
618 // {"----", NothingProc},
622 MenuItem modeMenu[] = {
623 // {N_("Machine White"), MachineWhiteProc},
624 // {N_("Machine Black"), MachineBlackProc},
625 // {N_("Two Machines"), TwoMachinesProc},
626 {N_("Analysis Mode"), AnalyzeModeProc},
627 // {N_("Analyze File"), AnalyzeFileProc },
628 // {N_("ICS Client"), IcsClientProc},
629 {N_("Edit Game"), EditGameProc},
630 {N_("Edit Position"), EditPositionProc},
631 {N_("Training"), TrainingProc},
632 {"----", NothingProc},
633 {N_("Show Engine Output"), EngineOutputProc},
634 {N_("Show Evaluation Graph"), NothingProc}, // [HGM] evalgr: not functional yet
635 {N_("Show Game List"), ShowGameListProc},
636 // {"Show Move History", HistoryShowProc}, // [HGM] hist: activate 4.2.7 code
637 {"----", NothingProc},
638 {N_("Edit Tags"), EditTagsProc},
639 {N_("Edit Comment"), EditCommentProc},
640 {N_("ICS Input Box"), IcsInputBoxProc},
644 MenuItem optionsMenu[] = {
645 // {N_("Flip View"), FlipViewProc},
646 // {"----", NothingProc},
647 {N_("Adjudications ..."), EngineMenuProc},
648 {N_("General Settings ..."), UciMenuProc},
649 {N_("Engine #1 Settings ..."), FirstSettingsProc},
650 {N_("Engine #2 Settings ..."), SecondSettingsProc},
651 {N_("Time Control ..."), TimeControlProc},
652 {"----", NothingProc},
653 // {N_("Always Queen"), AlwaysQueenProc},
654 // {N_("Animate Dragging"), AnimateDraggingProc},
655 // {N_("Animate Moving"), AnimateMovingProc},
656 // {N_("Auto Comment"), AutocommProc},
657 // {N_("Auto Flag"), AutoflagProc},
658 // {N_("Auto Flip View"), AutoflipProc},
659 // {N_("Auto Observe"), AutobsProc},
660 // {N_("Auto Raise Board"), AutoraiseProc},
661 // {N_("Auto Save"), AutosaveProc},
662 // {N_("Blindfold"), BlindfoldProc},
663 // {N_("Flash Moves"), FlashMovesProc},
664 // {N_("Get Move List"), GetMoveListProc},
666 // {N_("Highlight Dragging"), HighlightDraggingProc},
668 // {N_("Highlight Last Move"), HighlightLastMoveProc},
669 // {N_("Move Sound"), MoveSoundProc},
670 // {N_("ICS Alarm"), IcsAlarmProc},
671 // {N_("Old Save Style"), OldSaveStyleProc},
672 // {N_("Periodic Updates"), PeriodicUpdatesProc},
673 {N_("Ponder Next Move"), PonderNextMoveProc},
674 {N_("Popup Exit Message"), PopupExitMessageProc},
675 {N_("Popup Move Errors"), PopupMoveErrorsProc},
676 {N_("Premove"), PremoveProc},
677 {N_("Quiet Play"), QuietPlayProc},
678 // {N_("Hide Thinking"), HideThinkingProc},
679 // {N_("Test Legality"), TestLegalityProc},
684 {N_("File"), fileMenu},
685 {N_("Mode"), modeMenu},
686 {N_("Options"), optionsMenu},
690 #define PIECE_MENU_SIZE 18
691 String pieceMenuStrings[2][PIECE_MENU_SIZE] = {
692 { N_("White"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
693 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
694 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
695 N_("Empty square"), N_("Clear board") },
696 { N_("Black"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
697 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
698 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
699 N_("Empty square"), N_("Clear board") }
701 /* must be in same order as PieceMenuStrings! */
702 ChessSquare pieceMenuTranslation[2][PIECE_MENU_SIZE] = {
703 { WhitePlay, (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
704 WhiteRook, WhiteQueen, WhiteKing, (ChessSquare) 0, WhiteAlfil,
705 WhiteCannon, WhiteAngel, WhiteMarshall, (ChessSquare) 0,
706 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
707 { BlackPlay, (ChessSquare) 0, BlackPawn, BlackKnight, BlackBishop,
708 BlackRook, BlackQueen, BlackKing, (ChessSquare) 0, BlackAlfil,
709 BlackCannon, BlackAngel, BlackMarshall, (ChessSquare) 0,
710 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
713 #define DROP_MENU_SIZE 6
714 String dropMenuStrings[DROP_MENU_SIZE] = {
715 "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"), N_("Queen")
717 /* must be in same order as PieceMenuStrings! */
718 ChessSquare dropMenuTranslation[DROP_MENU_SIZE] = {
719 (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
720 WhiteRook, WhiteQueen
728 DropMenuEnables dmEnables[] = {
737 { XtNborderWidth, 0 },
738 { XtNdefaultDistance, 0 },
742 { XtNborderWidth, 0 },
743 { XtNresizable, (XtArgVal) True },
747 { XtNborderWidth, 0 },
752 XtResource clientResources[] = {
753 { "whitePieceColor", "whitePieceColor", XtRString, sizeof(String),
754 XtOffset(AppDataPtr, whitePieceColor), XtRString,
756 { "blackPieceColor", "blackPieceColor", XtRString, sizeof(String),
757 XtOffset(AppDataPtr, blackPieceColor), XtRString,
759 { "lightSquareColor", "lightSquareColor", XtRString,
760 sizeof(String), XtOffset(AppDataPtr, lightSquareColor),
761 XtRString, LIGHT_SQUARE_COLOR },
762 { "darkSquareColor", "darkSquareColor", XtRString, sizeof(String),
763 XtOffset(AppDataPtr, darkSquareColor), XtRString,
765 { "highlightSquareColor", "highlightSquareColor", XtRString,
766 sizeof(String), XtOffset(AppDataPtr, highlightSquareColor),
767 XtRString, HIGHLIGHT_SQUARE_COLOR },
768 { "premoveHighlightColor", "premoveHighlightColor", XtRString,
769 sizeof(String), XtOffset(AppDataPtr, premoveHighlightColor),
770 XtRString, PREMOVE_HIGHLIGHT_COLOR },
771 { "movesPerSession", "movesPerSession", XtRInt, sizeof(int),
772 XtOffset(AppDataPtr, movesPerSession), XtRImmediate,
773 (XtPointer) MOVES_PER_SESSION },
774 { "timeIncrement", "timeIncrement", XtRInt, sizeof(int),
775 XtOffset(AppDataPtr, timeIncrement), XtRImmediate,
776 (XtPointer) TIME_INCREMENT },
777 { "initString", "initString", XtRString, sizeof(String),
778 XtOffset(AppDataPtr, initString), XtRString, INIT_STRING },
779 { "secondInitString", "secondInitString", XtRString, sizeof(String),
780 XtOffset(AppDataPtr, secondInitString), XtRString, INIT_STRING },
781 { "firstComputerString", "firstComputerString", XtRString,
782 sizeof(String), XtOffset(AppDataPtr, firstComputerString), XtRString,
784 { "secondComputerString", "secondComputerString", XtRString,
785 sizeof(String), XtOffset(AppDataPtr, secondComputerString), XtRString,
787 { "firstChessProgram", "firstChessProgram", XtRString,
788 sizeof(String), XtOffset(AppDataPtr, firstChessProgram),
789 XtRString, FIRST_CHESS_PROGRAM },
790 { "secondChessProgram", "secondChessProgram", XtRString,
791 sizeof(String), XtOffset(AppDataPtr, secondChessProgram),
792 XtRString, SECOND_CHESS_PROGRAM },
793 { "firstPlaysBlack", "firstPlaysBlack", XtRBoolean,
794 sizeof(Boolean), XtOffset(AppDataPtr, firstPlaysBlack),
795 XtRImmediate, (XtPointer) False },
796 { "noChessProgram", "noChessProgram", XtRBoolean,
797 sizeof(Boolean), XtOffset(AppDataPtr, noChessProgram),
798 XtRImmediate, (XtPointer) False },
799 { "firstHost", "firstHost", XtRString, sizeof(String),
800 XtOffset(AppDataPtr, firstHost), XtRString, FIRST_HOST },
801 { "secondHost", "secondHost", XtRString, sizeof(String),
802 XtOffset(AppDataPtr, secondHost), XtRString, SECOND_HOST },
803 { "firstDirectory", "firstDirectory", XtRString, sizeof(String),
804 XtOffset(AppDataPtr, firstDirectory), XtRString, "." },
805 { "secondDirectory", "secondDirectory", XtRString, sizeof(String),
806 XtOffset(AppDataPtr, secondDirectory), XtRString, "." },
807 { "bitmapDirectory", "bitmapDirectory", XtRString,
808 sizeof(String), XtOffset(AppDataPtr, bitmapDirectory),
810 { "remoteShell", "remoteShell", XtRString, sizeof(String),
811 XtOffset(AppDataPtr, remoteShell), XtRString, REMOTE_SHELL },
812 { "remoteUser", "remoteUser", XtRString, sizeof(String),
813 XtOffset(AppDataPtr, remoteUser), XtRString, "" },
814 { "timeDelay", "timeDelay", XtRFloat, sizeof(float),
815 XtOffset(AppDataPtr, timeDelay), XtRString,
816 (XtPointer) TIME_DELAY_QUOTE },
817 { "timeControl", "timeControl", XtRString, sizeof(String),
818 XtOffset(AppDataPtr, timeControl), XtRString,
819 (XtPointer) TIME_CONTROL },
820 { "internetChessServerMode", "internetChessServerMode",
821 XtRBoolean, sizeof(Boolean),
822 XtOffset(AppDataPtr, icsActive), XtRImmediate,
824 { "internetChessServerHost", "internetChessServerHost",
825 XtRString, sizeof(String),
826 XtOffset(AppDataPtr, icsHost),
827 XtRString, (XtPointer) ICS_HOST },
828 { "internetChessServerPort", "internetChessServerPort",
829 XtRString, sizeof(String),
830 XtOffset(AppDataPtr, icsPort), XtRString,
831 (XtPointer) ICS_PORT },
832 { "internetChessServerCommPort", "internetChessServerCommPort",
833 XtRString, sizeof(String),
834 XtOffset(AppDataPtr, icsCommPort), XtRString,
836 { "internetChessServerLogonScript", "internetChessServerLogonScript",
837 XtRString, sizeof(String),
838 XtOffset(AppDataPtr, icsLogon), XtRString,
840 { "internetChessServerHelper", "internetChessServerHelper",
841 XtRString, sizeof(String),
842 XtOffset(AppDataPtr, icsHelper), XtRString, "" },
843 { "internetChessServerInputBox", "internetChessServerInputBox",
844 XtRBoolean, sizeof(Boolean),
845 XtOffset(AppDataPtr, icsInputBox), XtRImmediate,
847 { "icsAlarm", "icsAlarm",
848 XtRBoolean, sizeof(Boolean),
849 XtOffset(AppDataPtr, icsAlarm), XtRImmediate,
851 { "icsAlarmTime", "icsAlarmTime",
853 XtOffset(AppDataPtr, icsAlarmTime), XtRImmediate,
855 { "useTelnet", "useTelnet", XtRBoolean, sizeof(Boolean),
856 XtOffset(AppDataPtr, useTelnet), XtRImmediate,
858 { "telnetProgram", "telnetProgram", XtRString, sizeof(String),
859 XtOffset(AppDataPtr, telnetProgram), XtRString, TELNET_PROGRAM },
860 { "gateway", "gateway", XtRString, sizeof(String),
861 XtOffset(AppDataPtr, gateway), XtRString, "" },
862 { "loadGameFile", "loadGameFile", XtRString, sizeof(String),
863 XtOffset(AppDataPtr, loadGameFile), XtRString, "" },
864 { "loadGameIndex", "loadGameIndex",
866 XtOffset(AppDataPtr, loadGameIndex), XtRImmediate,
868 { "saveGameFile", "saveGameFile", XtRString, sizeof(String),
869 XtOffset(AppDataPtr, saveGameFile), XtRString, "" },
870 { "autoRaiseBoard", "autoRaiseBoard", XtRBoolean,
871 sizeof(Boolean), XtOffset(AppDataPtr, autoRaiseBoard),
872 XtRImmediate, (XtPointer) True },
873 { "autoSaveGames", "autoSaveGames", XtRBoolean,
874 sizeof(Boolean), XtOffset(AppDataPtr, autoSaveGames),
875 XtRImmediate, (XtPointer) False },
876 { "blindfold", "blindfold", XtRBoolean,
877 sizeof(Boolean), XtOffset(AppDataPtr, blindfold),
878 XtRImmediate, (XtPointer) False },
879 { "loadPositionFile", "loadPositionFile", XtRString,
880 sizeof(String), XtOffset(AppDataPtr, loadPositionFile),
882 { "loadPositionIndex", "loadPositionIndex",
884 XtOffset(AppDataPtr, loadPositionIndex), XtRImmediate,
886 { "savePositionFile", "savePositionFile", XtRString,
887 sizeof(String), XtOffset(AppDataPtr, savePositionFile),
889 { "matchMode", "matchMode", XtRBoolean, sizeof(Boolean),
890 XtOffset(AppDataPtr, matchMode), XtRImmediate, (XtPointer) False },
891 { "matchGames", "matchGames", XtRInt, sizeof(int),
892 XtOffset(AppDataPtr, matchGames), XtRImmediate,
894 { "monoMode", "monoMode", XtRBoolean, sizeof(Boolean),
895 XtOffset(AppDataPtr, monoMode), XtRImmediate,
897 { "debugMode", "debugMode", XtRBoolean, sizeof(Boolean),
898 XtOffset(AppDataPtr, debugMode), XtRImmediate,
900 { "clockMode", "clockMode", XtRBoolean, sizeof(Boolean),
901 XtOffset(AppDataPtr, clockMode), XtRImmediate,
903 { "boardSize", "boardSize", XtRString, sizeof(String),
904 XtOffset(AppDataPtr, boardSize), XtRString, "" },
905 { "searchTime", "searchTime", XtRString, sizeof(String),
906 XtOffset(AppDataPtr, searchTime), XtRString,
908 { "searchDepth", "searchDepth", XtRInt, sizeof(int),
909 XtOffset(AppDataPtr, searchDepth), XtRImmediate,
911 { "showCoords", "showCoords", XtRBoolean, sizeof(Boolean),
912 XtOffset(AppDataPtr, showCoords), XtRImmediate,
914 { "showJail", "showJail", XtRInt, sizeof(int),
915 XtOffset(AppDataPtr, showJail), XtRImmediate,
917 { "showThinking", "showThinking", XtRBoolean, sizeof(Boolean),
918 XtOffset(AppDataPtr, showThinking), XtRImmediate,
920 { "ponderNextMove", "ponderNextMove", XtRBoolean, sizeof(Boolean),
921 XtOffset(AppDataPtr, ponderNextMove), XtRImmediate,
923 { "periodicUpdates", "periodicUpdates", XtRBoolean, sizeof(Boolean),
924 XtOffset(AppDataPtr, periodicUpdates), XtRImmediate,
926 { "clockFont", "clockFont", XtRString, sizeof(String),
927 XtOffset(AppDataPtr, clockFont), XtRString, CLOCK_FONT },
928 { "coordFont", "coordFont", XtRString, sizeof(String),
929 XtOffset(AppDataPtr, coordFont), XtRString, COORD_FONT },
930 { "font", "font", XtRString, sizeof(String),
931 XtOffset(AppDataPtr, font), XtRString, DEFAULT_FONT },
932 { "ringBellAfterMoves", "ringBellAfterMoves",
933 XtRBoolean, sizeof(Boolean),
934 XtOffset(AppDataPtr, ringBellAfterMoves),
935 XtRImmediate, (XtPointer) False },
936 { "autoCallFlag", "autoCallFlag", XtRBoolean,
937 sizeof(Boolean), XtOffset(AppDataPtr, autoCallFlag),
938 XtRImmediate, (XtPointer) False },
939 { "autoFlipView", "autoFlipView", XtRBoolean,
940 sizeof(Boolean), XtOffset(AppDataPtr, autoFlipView),
941 XtRImmediate, (XtPointer) True },
942 { "autoObserve", "autoObserve", XtRBoolean,
943 sizeof(Boolean), XtOffset(AppDataPtr, autoObserve),
944 XtRImmediate, (XtPointer) False },
945 { "autoComment", "autoComment", XtRBoolean,
946 sizeof(Boolean), XtOffset(AppDataPtr, autoComment),
947 XtRImmediate, (XtPointer) False },
948 { "getMoveList", "getMoveList", XtRBoolean,
949 sizeof(Boolean), XtOffset(AppDataPtr, getMoveList),
950 XtRImmediate, (XtPointer) True },
952 { "highlightDragging", "highlightDragging", XtRBoolean,
953 sizeof(Boolean), XtOffset(AppDataPtr, highlightDragging),
954 XtRImmediate, (XtPointer) False },
956 { "highlightLastMove", "highlightLastMove", XtRBoolean,
957 sizeof(Boolean), XtOffset(AppDataPtr, highlightLastMove),
958 XtRImmediate, (XtPointer) False },
959 { "premove", "premove", XtRBoolean,
960 sizeof(Boolean), XtOffset(AppDataPtr, premove),
961 XtRImmediate, (XtPointer) True },
962 { "testLegality", "testLegality", XtRBoolean,
963 sizeof(Boolean), XtOffset(AppDataPtr, testLegality),
964 XtRImmediate, (XtPointer) True },
965 { "flipView", "flipView", XtRBoolean,
966 sizeof(Boolean), XtOffset(AppDataPtr, flipView),
967 XtRImmediate, (XtPointer) False },
968 { "cmail", "cmailGameName", XtRString, sizeof(String),
969 XtOffset(AppDataPtr, cmailGameName), XtRString, "" },
970 { "alwaysPromoteToQueen", "alwaysPromoteToQueen", XtRBoolean,
971 sizeof(Boolean), XtOffset(AppDataPtr, alwaysPromoteToQueen),
972 XtRImmediate, (XtPointer) False },
973 { "oldSaveStyle", "oldSaveStyle", XtRBoolean,
974 sizeof(Boolean), XtOffset(AppDataPtr, oldSaveStyle),
975 XtRImmediate, (XtPointer) False },
976 { "quietPlay", "quietPlay", XtRBoolean,
977 sizeof(Boolean), XtOffset(AppDataPtr, quietPlay),
978 XtRImmediate, (XtPointer) False },
979 { "titleInWindow", "titleInWindow", XtRBoolean,
980 sizeof(Boolean), XtOffset(AppDataPtr, titleInWindow),
981 XtRImmediate, (XtPointer) False },
982 { "localLineEditing", "localLineEditing", XtRBoolean,
983 sizeof(Boolean), XtOffset(AppDataPtr, localLineEditing),
984 XtRImmediate, (XtPointer) True }, /* not implemented, must be True */
986 { "zippyTalk", "zippyTalk", XtRBoolean,
987 sizeof(Boolean), XtOffset(AppDataPtr, zippyTalk),
988 XtRImmediate, (XtPointer) ZIPPY_TALK },
989 { "zippyPlay", "zippyPlay", XtRBoolean,
990 sizeof(Boolean), XtOffset(AppDataPtr, zippyPlay),
991 XtRImmediate, (XtPointer) ZIPPY_PLAY },
992 { "zippyLines", "zippyLines", XtRString, sizeof(String),
993 XtOffset(AppDataPtr, zippyLines), XtRString, ZIPPY_LINES },
994 { "zippyPinhead", "zippyPinhead", XtRString, sizeof(String),
995 XtOffset(AppDataPtr, zippyPinhead), XtRString, ZIPPY_PINHEAD },
996 { "zippyPassword", "zippyPassword", XtRString, sizeof(String),
997 XtOffset(AppDataPtr, zippyPassword), XtRString, ZIPPY_PASSWORD },
998 { "zippyPassword2", "zippyPassword2", XtRString, sizeof(String),
999 XtOffset(AppDataPtr, zippyPassword2), XtRString, ZIPPY_PASSWORD2 },
1000 { "zippyWrongPassword", "zippyWrongPassword", XtRString, sizeof(String),
1001 XtOffset(AppDataPtr, zippyWrongPassword), XtRString,
1002 ZIPPY_WRONG_PASSWORD },
1003 { "zippyAcceptOnly", "zippyAcceptOnly", XtRString, sizeof(String),
1004 XtOffset(AppDataPtr, zippyAcceptOnly), XtRString, ZIPPY_ACCEPT_ONLY },
1005 { "zippyUseI", "zippyUseI", XtRBoolean,
1006 sizeof(Boolean), XtOffset(AppDataPtr, zippyUseI),
1007 XtRImmediate, (XtPointer) ZIPPY_USE_I },
1008 { "zippyBughouse", "zippyBughouse", XtRInt,
1009 sizeof(int), XtOffset(AppDataPtr, zippyBughouse),
1010 XtRImmediate, (XtPointer) ZIPPY_BUGHOUSE },
1011 { "zippyNoplayCrafty", "zippyNoplayCrafty", XtRBoolean,
1012 sizeof(Boolean), XtOffset(AppDataPtr, zippyNoplayCrafty),
1013 XtRImmediate, (XtPointer) ZIPPY_NOPLAY_CRAFTY },
1014 { "zippyGameEnd", "zippyGameEnd", XtRString, sizeof(String),
1015 XtOffset(AppDataPtr, zippyGameEnd), XtRString, ZIPPY_GAME_END },
1016 { "zippyGameStart", "zippyGameStart", XtRString, sizeof(String),
1017 XtOffset(AppDataPtr, zippyGameStart), XtRString, ZIPPY_GAME_START },
1018 { "zippyAdjourn", "zippyAdjourn", XtRBoolean,
1019 sizeof(Boolean), XtOffset(AppDataPtr, zippyAdjourn),
1020 XtRImmediate, (XtPointer) ZIPPY_ADJOURN },
1021 { "zippyAbort", "zippyAbort", XtRBoolean,
1022 sizeof(Boolean), XtOffset(AppDataPtr, zippyAbort),
1023 XtRImmediate, (XtPointer) ZIPPY_ABORT },
1024 { "zippyVariants", "zippyVariants", XtRString, sizeof(String),
1025 XtOffset(AppDataPtr, zippyVariants), XtRString, ZIPPY_VARIANTS },
1026 { "zippyMaxGames", "zippyMaxGames", XtRInt, sizeof(int),
1027 XtOffset(AppDataPtr, zippyMaxGames), XtRImmediate,
1028 (XtPointer) ZIPPY_MAX_GAMES },
1029 { "zippyReplayTimeout", "zippyReplayTimeout", XtRInt, sizeof(int),
1030 XtOffset(AppDataPtr, zippyReplayTimeout), XtRImmediate,
1031 (XtPointer) ZIPPY_REPLAY_TIMEOUT },
1032 { "zippyShortGame", "zippyShortGame", XtRInt, sizeof(int),
1033 XtOffset(AppDataPtr, zippyShortGame), XtRImmediate,
1036 { "flashCount", "flashCount", XtRInt, sizeof(int),
1037 XtOffset(AppDataPtr, flashCount), XtRImmediate,
1038 (XtPointer) FLASH_COUNT },
1039 { "flashRate", "flashRate", XtRInt, sizeof(int),
1040 XtOffset(AppDataPtr, flashRate), XtRImmediate,
1041 (XtPointer) FLASH_RATE },
1042 { "pixmapDirectory", "pixmapDirectory", XtRString,
1043 sizeof(String), XtOffset(AppDataPtr, pixmapDirectory),
1045 { "msLoginDelay", "msLoginDelay", XtRInt, sizeof(int),
1046 XtOffset(AppDataPtr, msLoginDelay), XtRImmediate,
1047 (XtPointer) MS_LOGIN_DELAY },
1048 { "colorizeMessages", "colorizeMessages", XtRBoolean,
1049 sizeof(Boolean), XtOffset(AppDataPtr, colorize),
1050 XtRImmediate, (XtPointer) False },
1051 { "colorShout", "colorShout", XtRString,
1052 sizeof(String), XtOffset(AppDataPtr, colorShout),
1053 XtRString, COLOR_SHOUT },
1054 { "colorSShout", "colorSShout", XtRString,
1055 sizeof(String), XtOffset(AppDataPtr, colorSShout),
1056 XtRString, COLOR_SSHOUT },
1057 { "colorChannel1", "colorChannel1", XtRString,
1058 sizeof(String), XtOffset(AppDataPtr, colorChannel1),
1059 XtRString, COLOR_CHANNEL1 },
1060 { "colorChannel", "colorChannel", XtRString,
1061 sizeof(String), XtOffset(AppDataPtr, colorChannel),
1062 XtRString, COLOR_CHANNEL },
1063 { "colorKibitz", "colorKibitz", XtRString,
1064 sizeof(String), XtOffset(AppDataPtr, colorKibitz),
1065 XtRString, COLOR_KIBITZ },
1066 { "colorTell", "colorTell", XtRString,
1067 sizeof(String), XtOffset(AppDataPtr, colorTell),
1068 XtRString, COLOR_TELL },
1069 { "colorChallenge", "colorChallenge", XtRString,
1070 sizeof(String), XtOffset(AppDataPtr, colorChallenge),
1071 XtRString, COLOR_CHALLENGE },
1072 { "colorRequest", "colorRequest", XtRString,
1073 sizeof(String), XtOffset(AppDataPtr, colorRequest),
1074 XtRString, COLOR_REQUEST },
1075 { "colorSeek", "colorSeek", XtRString,
1076 sizeof(String), XtOffset(AppDataPtr, colorSeek),
1077 XtRString, COLOR_SEEK },
1078 { "colorNormal", "colorNormal", XtRString,
1079 sizeof(String), XtOffset(AppDataPtr, colorNormal),
1080 XtRString, COLOR_NORMAL },
1081 { "soundProgram", "soundProgram", XtRString,
1082 sizeof(String), XtOffset(AppDataPtr, soundProgram),
1083 XtRString, "play" },
1084 { "soundShout", "soundShout", XtRString,
1085 sizeof(String), XtOffset(AppDataPtr, soundShout),
1087 { "soundSShout", "soundSShout", XtRString,
1088 sizeof(String), XtOffset(AppDataPtr, soundSShout),
1090 { "soundChannel1", "soundChannel1", XtRString,
1091 sizeof(String), XtOffset(AppDataPtr, soundChannel1),
1093 { "soundChannel", "soundChannel", XtRString,
1094 sizeof(String), XtOffset(AppDataPtr, soundChannel),
1096 { "soundKibitz", "soundKibitz", XtRString,
1097 sizeof(String), XtOffset(AppDataPtr, soundKibitz),
1099 { "soundTell", "soundTell", XtRString,
1100 sizeof(String), XtOffset(AppDataPtr, soundTell),
1102 { "soundChallenge", "soundChallenge", XtRString,
1103 sizeof(String), XtOffset(AppDataPtr, soundChallenge),
1105 { "soundRequest", "soundRequest", XtRString,
1106 sizeof(String), XtOffset(AppDataPtr, soundRequest),
1108 { "soundSeek", "soundSeek", XtRString,
1109 sizeof(String), XtOffset(AppDataPtr, soundSeek),
1111 { "soundMove", "soundMove", XtRString,
1112 sizeof(String), XtOffset(AppDataPtr, soundMove),
1114 { "soundIcsWin", "soundIcsWin", XtRString,
1115 sizeof(String), XtOffset(AppDataPtr, soundIcsWin),
1117 { "soundIcsLoss", "soundIcsLoss", XtRString,
1118 sizeof(String), XtOffset(AppDataPtr, soundIcsLoss),
1120 { "soundIcsDraw", "soundIcsDraw", XtRString,
1121 sizeof(String), XtOffset(AppDataPtr, soundIcsDraw),
1123 { "soundIcsUnfinished", "soundIcsUnfinished", XtRString,
1124 sizeof(String), XtOffset(AppDataPtr, soundIcsUnfinished),
1126 { "soundIcsAlarm", "soundIcsAlarm", XtRString,
1127 sizeof(String), XtOffset(AppDataPtr, soundIcsAlarm),
1129 { "reuseFirst", "reuseFirst", XtRBoolean,
1130 sizeof(Boolean), XtOffset(AppDataPtr, reuseFirst),
1131 XtRImmediate, (XtPointer) True },
1132 { "reuseSecond", "reuseSecond", XtRBoolean,
1133 sizeof(Boolean), XtOffset(AppDataPtr, reuseSecond),
1134 XtRImmediate, (XtPointer) True },
1135 { "animateDragging", "animateDragging", XtRBoolean,
1136 sizeof(Boolean), XtOffset(AppDataPtr, animateDragging),
1137 XtRImmediate, (XtPointer) True },
1138 { "animateMoving", "animateMoving", XtRBoolean,
1139 sizeof(Boolean), XtOffset(AppDataPtr, animate),
1140 XtRImmediate, (XtPointer) True },
1141 { "animateSpeed", "animateSpeed", XtRInt,
1142 sizeof(int), XtOffset(AppDataPtr, animSpeed),
1143 XtRImmediate, (XtPointer)10 },
1144 { "popupExitMessage", "popupExitMessage", XtRBoolean,
1145 sizeof(Boolean), XtOffset(AppDataPtr, popupExitMessage),
1146 XtRImmediate, (XtPointer) True },
1147 { "popupMoveErrors", "popupMoveErrors", XtRBoolean,
1148 sizeof(Boolean), XtOffset(AppDataPtr, popupMoveErrors),
1149 XtRImmediate, (XtPointer) False },
1150 { "fontSizeTolerance", "fontSizeTolerance", XtRInt,
1151 sizeof(int), XtOffset(AppDataPtr, fontSizeTolerance),
1152 XtRImmediate, (XtPointer)4 },
1153 { "initialMode", "initialMode", XtRString,
1154 sizeof(String), XtOffset(AppDataPtr, initialMode),
1155 XtRImmediate, (XtPointer) "" },
1156 { "variant", "variant", XtRString,
1157 sizeof(String), XtOffset(AppDataPtr, variant),
1158 XtRImmediate, (XtPointer) "normal" },
1159 { "firstProtocolVersion", "firstProtocolVersion", XtRInt,
1160 sizeof(int), XtOffset(AppDataPtr, firstProtocolVersion),
1161 XtRImmediate, (XtPointer)PROTOVER },
1162 { "secondProtocolVersion", "secondProtocolVersion", XtRInt,
1163 sizeof(int), XtOffset(AppDataPtr, secondProtocolVersion),
1164 XtRImmediate, (XtPointer)PROTOVER },
1165 { "showButtonBar", "showButtonBar", XtRBoolean,
1166 sizeof(Boolean), XtOffset(AppDataPtr, showButtonBar),
1167 XtRImmediate, (XtPointer) True },
1168 { "lowTimeWarningColor", "lowTimeWarningColor", XtRString,
1169 sizeof(String), XtOffset(AppDataPtr, lowTimeWarningColor),
1170 XtRString, COLOR_LOWTIMEWARNING },
1171 { "lowTimeWarning", "lowTimeWarning", XtRBoolean,
1172 sizeof(Boolean), XtOffset(AppDataPtr, lowTimeWarning),
1173 XtRImmediate, (XtPointer) False },
1174 {"icsEngineAnalyze", "icsEngineAnalyze", XtRBoolean, /* [DM] icsEngineAnalyze */
1175 sizeof(Boolean), XtOffset(AppDataPtr, icsEngineAnalyze),
1176 XtRImmediate, (XtPointer) False },
1177 { "firstScoreAbs", "firstScoreAbs", XtRBoolean,
1178 sizeof(Boolean), XtOffset(AppDataPtr, firstScoreIsAbsolute),
1179 XtRImmediate, (XtPointer) False },
1180 { "secondScoreAbs", "secondScoreAbs", XtRBoolean,
1181 sizeof(Boolean), XtOffset(AppDataPtr, secondScoreIsAbsolute),
1182 XtRImmediate, (XtPointer) False },
1183 { "pgnExtendedInfo", "pgnExtendedInfo", XtRBoolean,
1184 sizeof(Boolean), XtOffset(AppDataPtr, saveExtendedInfoInPGN),
1185 XtRImmediate, (XtPointer) False },
1186 { "hideThinkingFromHuman", "hideThinkingFromHuman", XtRBoolean,
1187 sizeof(Boolean), XtOffset(AppDataPtr, hideThinkingFromHuman),
1188 XtRImmediate, (XtPointer) True },
1189 { "adjudicateLossThreshold", "adjudicateLossThreshold", XtRInt,
1190 sizeof(int), XtOffset(AppDataPtr, adjudicateLossThreshold),
1191 XtRImmediate, (XtPointer) 0},
1192 { "adjudicateDrawMoves", "adjudicateDrawMoves", XtRInt,
1193 sizeof(int), XtOffset(AppDataPtr, adjudicateDrawMoves),
1194 XtRImmediate, (XtPointer) 0},
1195 { "pgnEventHeader", "pgnEventHeader", XtRString,
1196 sizeof(String), XtOffset(AppDataPtr, pgnEventHeader),
1197 XtRImmediate, (XtPointer) "Computer Chess Game" },
1198 { "defaultFrcPosition", "defaultFrcPositon", XtRInt,
1199 sizeof(int), XtOffset(AppDataPtr, defaultFrcPosition),
1200 XtRImmediate, (XtPointer) -1},
1201 { "gameListTags", "gameListTags", XtRString,
1202 sizeof(String), XtOffset(AppDataPtr, gameListTags),
1203 XtRImmediate, (XtPointer) GLT_DEFAULT_TAGS },
1205 // [HGM] 4.3.xx options
1206 { "boardWidth", "boardWidth", XtRInt,
1207 sizeof(int), XtOffset(AppDataPtr, NrFiles),
1208 XtRImmediate, (XtPointer) -1},
1209 { "boardHeight", "boardHeight", XtRInt,
1210 sizeof(int), XtOffset(AppDataPtr, NrRanks),
1211 XtRImmediate, (XtPointer) -1},
1212 { "matchPause", "matchPause", XtRInt,
1213 sizeof(int), XtOffset(AppDataPtr, matchPause),
1214 XtRImmediate, (XtPointer) 10000},
1215 { "holdingsSize", "holdingsSize", XtRInt,
1216 sizeof(int), XtOffset(AppDataPtr, holdingsSize),
1217 XtRImmediate, (XtPointer) -1},
1218 { "flipBlack", "flipBlack", XtRBoolean,
1219 sizeof(Boolean), XtOffset(AppDataPtr, upsideDown),
1220 XtRImmediate, (XtPointer) False},
1221 { "allWhite", "allWhite", XtRBoolean,
1222 sizeof(Boolean), XtOffset(AppDataPtr, allWhite),
1223 XtRImmediate, (XtPointer) False},
1224 { "pieceToCharTable", "pieceToCharTable", XtRString,
1225 sizeof(String), XtOffset(AppDataPtr, pieceToCharTable),
1226 XtRImmediate, (XtPointer) 0},
1227 { "alphaRank", "alphaRank", XtRBoolean,
1228 sizeof(Boolean), XtOffset(AppDataPtr, alphaRank),
1229 XtRImmediate, (XtPointer) False},
1230 { "testClaims", "testClaims", XtRBoolean,
1231 sizeof(Boolean), XtOffset(AppDataPtr, testClaims),
1232 XtRImmediate, (XtPointer) True},
1233 { "checkMates", "checkMates", XtRBoolean,
1234 sizeof(Boolean), XtOffset(AppDataPtr, checkMates),
1235 XtRImmediate, (XtPointer) True},
1236 { "materialDraws", "materialDraws", XtRBoolean,
1237 sizeof(Boolean), XtOffset(AppDataPtr, materialDraws),
1238 XtRImmediate, (XtPointer) True},
1239 { "trivialDraws", "trivialDraws", XtRBoolean,
1240 sizeof(Boolean), XtOffset(AppDataPtr, trivialDraws),
1241 XtRImmediate, (XtPointer) False},
1242 { "ruleMoves", "ruleMoves", XtRInt,
1243 sizeof(int), XtOffset(AppDataPtr, ruleMoves),
1244 XtRImmediate, (XtPointer) 51},
1245 { "repeatsToDraw", "repeatsToDraw", XtRInt,
1246 sizeof(int), XtOffset(AppDataPtr, drawRepeats),
1247 XtRImmediate, (XtPointer) 6},
1248 { "engineDebugOutput", "engineDebugOutput", XtRInt,
1249 sizeof(int), XtOffset(AppDataPtr, engineComments),
1250 XtRImmediate, (XtPointer) 1},
1251 { "userName", "userName", XtRString,
1252 sizeof(int), XtOffset(AppDataPtr, userName),
1253 XtRImmediate, (XtPointer) 0},
1254 { "autoKibitz", "autoKibitz", XtRBoolean,
1255 sizeof(Boolean), XtOffset(AppDataPtr, autoKibitz),
1256 XtRImmediate, (XtPointer) False},
1257 { "firstTimeOdds", "firstTimeOdds", XtRInt,
1258 sizeof(int), XtOffset(AppDataPtr, firstTimeOdds),
1259 XtRImmediate, (XtPointer) 1},
1260 { "secondTimeOdds", "secondTimeOdds", XtRInt,
1261 sizeof(int), XtOffset(AppDataPtr, secondTimeOdds),
1262 XtRImmediate, (XtPointer) 1},
1263 { "timeOddsMode", "timeOddsMode", XtRInt,
1264 sizeof(int), XtOffset(AppDataPtr, timeOddsMode),
1265 XtRImmediate, (XtPointer) 0},
1266 { "firstAccumulateTC", "firstAccumulateTC", XtRInt,
1267 sizeof(int), XtOffset(AppDataPtr, firstAccumulateTC),
1268 XtRImmediate, (XtPointer) 1},
1269 { "secondAccumulateTC", "secondAccumulateTC", XtRInt,
1270 sizeof(int), XtOffset(AppDataPtr, secondAccumulateTC),
1271 XtRImmediate, (XtPointer) 1},
1272 { "firstNPS", "firstNPS", XtRInt,
1273 sizeof(int), XtOffset(AppDataPtr, firstNPS),
1274 XtRImmediate, (XtPointer) -1},
1275 { "secondNPS", "secondNPS", XtRInt,
1276 sizeof(int), XtOffset(AppDataPtr, secondNPS),
1277 XtRImmediate, (XtPointer) -1},
1278 { "serverMoves", "serverMoves", XtRString,
1279 sizeof(String), XtOffset(AppDataPtr, serverMovesName),
1280 XtRImmediate, (XtPointer) 0},
1281 { "serverPause", "serverPause", XtRInt,
1282 sizeof(int), XtOffset(AppDataPtr, serverPause),
1283 XtRImmediate, (XtPointer) 0},
1284 { "suppressLoadMoves", "suppressLoadMoves", XtRBoolean,
1285 sizeof(Boolean), XtOffset(AppDataPtr, suppressLoadMoves),
1286 XtRImmediate, (XtPointer) False},
1287 { "userName", "userName", XtRString,
1288 sizeof(String), XtOffset(AppDataPtr, userName),
1289 XtRImmediate, (XtPointer) 0},
1290 { "egtFormats", "egtFormats", XtRString,
1291 sizeof(String), XtOffset(AppDataPtr, egtFormats),
1292 XtRImmediate, (XtPointer) 0},
1293 { "rewindIndex", "rewindIndex", XtRInt,
1294 sizeof(int), XtOffset(AppDataPtr, rewindIndex),
1295 XtRImmediate, (XtPointer) 0},
1296 { "sameColorGames", "sameColorGames", XtRInt,
1297 sizeof(int), XtOffset(AppDataPtr, sameColorGames),
1298 XtRImmediate, (XtPointer) 0},
1299 { "smpCores", "smpCores", XtRInt,
1300 sizeof(int), XtOffset(AppDataPtr, smpCores),
1301 XtRImmediate, (XtPointer) 1},
1302 { "niceEngines", "niceEngines", XtRInt,
1303 sizeof(int), XtOffset(AppDataPtr, niceEngines),
1304 XtRImmediate, (XtPointer) 0},
1305 { "nameOfDebugFile", "nameOfDebugFile", XtRString,
1306 sizeof(String), XtOffset(AppDataPtr, nameOfDebugFile),
1307 XtRImmediate, (XtPointer) "xboard.debug"},
1308 { "engineDebugOutput", "engineDebugOutput", XtRInt,
1309 sizeof(int), XtOffset(AppDataPtr, engineComments),
1310 XtRImmediate, (XtPointer) 1},
1311 { "noGUI", "noGUI", XtRBoolean,
1312 sizeof(Boolean), XtOffset(AppDataPtr, noGUI),
1313 XtRImmediate, (XtPointer) 0},
1314 { "firstOptions", "firstOptions", XtRString,
1315 sizeof(String), XtOffset(AppDataPtr, firstOptions),
1316 XtRImmediate, (XtPointer) "" },
1317 { "secondOptions", "secondOptions", XtRString,
1318 sizeof(String), XtOffset(AppDataPtr, secondOptions),
1319 XtRImmediate, (XtPointer) "" },
1320 { "firstNeedsNoncompliantFEN", "firstNeedsNoncompliantFEN", XtRString,
1321 sizeof(String), XtOffset(AppDataPtr, fenOverride1),
1322 XtRImmediate, (XtPointer) 0 },
1323 { "secondNeedsNoncompliantFEN", "secondNeedsNoncompliantFEN", XtRString,
1324 sizeof(String), XtOffset(AppDataPtr, fenOverride2),
1325 XtRImmediate, (XtPointer) 0 },
1327 // [HGM] Winboard_x UCI options
1328 { "firstIsUCI", "firstIsUCI", XtRBoolean,
1329 sizeof(Boolean), XtOffset(AppDataPtr, firstIsUCI),
1330 XtRImmediate, (XtPointer) False},
1331 { "secondIsUCI", "secondIsUCI", XtRBoolean,
1332 sizeof(Boolean), XtOffset(AppDataPtr, secondIsUCI),
1333 XtRImmediate, (XtPointer) False},
1334 { "firstHasOwnBookUCI", "firstHasOwnBookUCI", XtRBoolean,
1335 sizeof(Boolean), XtOffset(AppDataPtr, firstHasOwnBookUCI),
1336 XtRImmediate, (XtPointer) True},
1337 { "secondHasOwnBookUCI", "secondHasOwnBookUCI", XtRBoolean,
1338 sizeof(Boolean), XtOffset(AppDataPtr, secondHasOwnBookUCI),
1339 XtRImmediate, (XtPointer) True},
1340 { "usePolyglotBook", "usePolyglotBook", XtRBoolean,
1341 sizeof(Boolean), XtOffset(AppDataPtr, usePolyglotBook),
1342 XtRImmediate, (XtPointer) False},
1343 { "defaultHashSize", "defaultHashSize", XtRInt,
1344 sizeof(int), XtOffset(AppDataPtr, defaultHashSize),
1345 XtRImmediate, (XtPointer) 64},
1346 { "defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XtRInt,
1347 sizeof(int), XtOffset(AppDataPtr, defaultCacheSizeEGTB),
1348 XtRImmediate, (XtPointer) 4},
1349 { "polyglotDir", "polyglotDir", XtRString,
1350 sizeof(String), XtOffset(AppDataPtr, polyglotDir),
1351 XtRImmediate, (XtPointer) "." },
1352 { "polyglotBook", "polyglotBook", XtRString,
1353 sizeof(String), XtOffset(AppDataPtr, polyglotBook),
1354 XtRImmediate, (XtPointer) "" },
1355 { "defaultPathEGTB", "defaultPathEGTB", XtRString,
1356 sizeof(String), XtOffset(AppDataPtr, defaultPathEGTB),
1357 XtRImmediate, (XtPointer) "/usr/local/share/egtb"},
1358 { "delayBeforeQuit", "delayBeforeQuit", XtRInt,
1359 sizeof(int), XtOffset(AppDataPtr, delayBeforeQuit),
1360 XtRImmediate, (XtPointer) 0},
1361 { "delayAfterQuit", "delayAfterQuit", XtRInt,
1362 sizeof(int), XtOffset(AppDataPtr, delayAfterQuit),
1363 XtRImmediate, (XtPointer) 0},
1364 { "keepAlive", "keepAlive", XtRInt,
1365 sizeof(int), XtOffset(AppDataPtr, keepAlive),
1366 XtRImmediate, (XtPointer) 0},
1367 { "forceIllegalMoves", "forceIllegalMoves", XtRBoolean,
1368 sizeof(Boolean), XtOffset(AppDataPtr, forceIllegal),
1369 XtRImmediate, (XtPointer) False},
1370 { "keepLineBreaksICS", "keepLineBreaksICS", XtRBoolean,
1371 sizeof(Boolean), XtOffset(AppDataPtr, noJoin),
1372 XtRImmediate, (XtPointer) True},
1375 XrmOptionDescRec shellOptions[] = {
1376 { "-whitePieceColor", "whitePieceColor", XrmoptionSepArg, NULL },
1377 { "-blackPieceColor", "blackPieceColor", XrmoptionSepArg, NULL },
1378 { "-lightSquareColor", "lightSquareColor", XrmoptionSepArg, NULL },
1379 { "-darkSquareColor", "darkSquareColor", XrmoptionSepArg, NULL },
1380 { "-highlightSquareColor", "highlightSquareColor", XrmoptionSepArg, NULL },
1381 { "-premoveHighlightColor", "premoveHighlightColor", XrmoptionSepArg,NULL},
1382 { "-movesPerSession", "movesPerSession", XrmoptionSepArg, NULL },
1383 { "-mps", "movesPerSession", XrmoptionSepArg, NULL },
1384 { "-timeIncrement", "timeIncrement", XrmoptionSepArg, NULL },
1385 { "-inc", "timeIncrement", XrmoptionSepArg, NULL },
1386 { "-initString", "initString", XrmoptionSepArg, NULL },
1387 { "-firstInitString", "initString", XrmoptionSepArg, NULL },
1388 { "-secondInitString", "secondInitString", XrmoptionSepArg, NULL },
1389 { "-firstComputerString", "firstComputerString", XrmoptionSepArg, NULL },
1390 { "-secondComputerString", "secondComputerString", XrmoptionSepArg, NULL },
1391 { "-firstChessProgram", "firstChessProgram", XrmoptionSepArg, NULL },
1392 { "-fcp", "firstChessProgram", XrmoptionSepArg, NULL },
1393 { "-secondChessProgram", "secondChessProgram", XrmoptionSepArg, NULL },
1394 { "-scp", "secondChessProgram", XrmoptionSepArg, NULL },
1395 { "-firstPlaysBlack", "firstPlaysBlack", XrmoptionSepArg, NULL },
1396 { "-fb", "firstPlaysBlack", XrmoptionNoArg, "True" },
1397 { "-xfb", "firstPlaysBlack", XrmoptionNoArg, "False" },
1398 { "-noChessProgram", "noChessProgram", XrmoptionSepArg, NULL },
1399 { "-ncp", "noChessProgram", XrmoptionNoArg, "True" },
1400 { "-xncp", "noChessProgram", XrmoptionNoArg, "False" },
1401 { "-firstHost", "firstHost", XrmoptionSepArg, NULL },
1402 { "-fh", "firstHost", XrmoptionSepArg, NULL },
1403 { "-secondHost", "secondHost", XrmoptionSepArg, NULL },
1404 { "-sh", "secondHost", XrmoptionSepArg, NULL },
1405 { "-firstDirectory", "firstDirectory", XrmoptionSepArg, NULL },
1406 { "-fd", "firstDirectory", XrmoptionSepArg, NULL },
1407 { "-secondDirectory", "secondDirectory", XrmoptionSepArg, NULL },
1408 { "-sd", "secondDirectory", XrmoptionSepArg, NULL },
1409 { "-bitmapDirectory", "bitmapDirectory", XrmoptionSepArg, NULL },
1410 { "-bm", "bitmapDirectory", XrmoptionSepArg, NULL },
1411 { "-remoteShell", "remoteShell", XrmoptionSepArg, NULL },
1412 { "-rsh", "remoteShell", XrmoptionSepArg, NULL },
1413 { "-remoteUser", "remoteUser", XrmoptionSepArg, NULL },
1414 { "-ruser", "remoteUser", XrmoptionSepArg, NULL },
1415 { "-timeDelay", "timeDelay", XrmoptionSepArg, NULL },
1416 { "-td", "timeDelay", XrmoptionSepArg, NULL },
1417 { "-timeControl", "timeControl", XrmoptionSepArg, NULL },
1418 { "-tc", "timeControl", XrmoptionSepArg, NULL },
1419 { "-internetChessServerMode", "internetChessServerMode",
1420 XrmoptionSepArg, NULL },
1421 { "-ics", "internetChessServerMode", XrmoptionNoArg, "True" },
1422 { "-xics", "internetChessServerMode", XrmoptionNoArg, "False" },
1423 { "-internetChessServerHost", "internetChessServerHost",
1424 XrmoptionSepArg, NULL },
1425 { "-icshost", "internetChessServerHost", XrmoptionSepArg, NULL },
1426 { "-internetChessServerPort", "internetChessServerPort",
1427 XrmoptionSepArg, NULL },
1428 { "-icsport", "internetChessServerPort", XrmoptionSepArg, NULL },
1429 { "-internetChessServerCommPort", "internetChessServerCommPort",
1430 XrmoptionSepArg, NULL },
1431 { "-icscomm", "internetChessServerCommPort", XrmoptionSepArg, NULL },
1432 { "-internetChessServerLogonScript", "internetChessServerLogonScript",
1433 XrmoptionSepArg, NULL },
1434 { "-icslogon", "internetChessServerLogonScript", XrmoptionSepArg, NULL },
1435 { "-internetChessServerHelper", "internetChessServerHelper",
1436 XrmoptionSepArg, NULL },
1437 { "-icshelper", "internetChessServerHelper", XrmoptionSepArg, NULL },
1438 { "-internetChessServerInputBox", "internetChessServerInputBox",
1439 XrmoptionSepArg, NULL },
1440 { "-icsinput", "internetChessServerInputBox", XrmoptionNoArg, "True" },
1441 { "-xicsinput", "internetChessServerInputBox", XrmoptionNoArg, "False" },
1442 { "-icsAlarm", "icsAlarm", XrmoptionSepArg, NULL },
1443 { "-alarm", "icsAlarm", XrmoptionNoArg, "True" },
1444 { "-xalarm", "icsAlarm", XrmoptionNoArg, "False" },
1445 { "-icsAlarmTime", "icsAlarmTime", XrmoptionSepArg, NULL },
1446 { "-useTelnet", "useTelnet", XrmoptionSepArg, NULL },
1447 { "-telnet", "useTelnet", XrmoptionNoArg, "True" },
1448 { "-xtelnet", "useTelnet", XrmoptionNoArg, "False" },
1449 { "-telnetProgram", "telnetProgram", XrmoptionSepArg, NULL },
1450 { "-gateway", "gateway", XrmoptionSepArg, NULL },
1451 { "-loadGameFile", "loadGameFile", XrmoptionSepArg, NULL },
1452 { "-lgf", "loadGameFile", XrmoptionSepArg, NULL },
1453 { "-loadGameIndex", "loadGameIndex", XrmoptionSepArg, NULL },
1454 { "-lgi", "loadGameIndex", XrmoptionSepArg, NULL },
1455 { "-saveGameFile", "saveGameFile", XrmoptionSepArg, NULL },
1456 { "-sgf", "saveGameFile", XrmoptionSepArg, NULL },
1457 { "-autoSaveGames", "autoSaveGames", XrmoptionSepArg, NULL },
1458 { "-autosave", "autoSaveGames", XrmoptionNoArg, "True" },
1459 { "-xautosave", "autoSaveGames", XrmoptionNoArg, "False" },
1460 { "-autoRaiseBoard", "autoRaiseBoard", XrmoptionSepArg, NULL },
1461 { "-autoraise", "autoRaiseBoard", XrmoptionNoArg, "True" },
1462 { "-xautoraise", "autoRaiseBoard", XrmoptionNoArg, "False" },
1463 { "-blindfold", "blindfold", XrmoptionSepArg, NULL },
1464 { "-blind", "blindfold", XrmoptionNoArg, "True" },
1465 { "-xblind", "blindfold", XrmoptionNoArg, "False" },
1466 { "-loadPositionFile", "loadPositionFile", XrmoptionSepArg, NULL },
1467 { "-lpf", "loadPositionFile", XrmoptionSepArg, NULL },
1468 { "-loadPositionIndex", "loadPositionIndex", XrmoptionSepArg, NULL },
1469 { "-lpi", "loadPositionIndex", XrmoptionSepArg, NULL },
1470 { "-savePositionFile", "savePositionFile", XrmoptionSepArg, NULL },
1471 { "-spf", "savePositionFile", XrmoptionSepArg, NULL },
1472 { "-matchMode", "matchMode", XrmoptionSepArg, NULL },
1473 { "-mm", "matchMode", XrmoptionNoArg, "True" },
1474 { "-xmm", "matchMode", XrmoptionNoArg, "False" },
1475 { "-matchGames", "matchGames", XrmoptionSepArg, NULL },
1476 { "-mg", "matchGames", XrmoptionSepArg, NULL },
1477 { "-monoMode", "monoMode", XrmoptionSepArg, NULL },
1478 { "-mono", "monoMode", XrmoptionNoArg, "True" },
1479 { "-xmono", "monoMode", XrmoptionNoArg, "False" },
1480 { "-debugMode", "debugMode", XrmoptionSepArg, NULL },
1481 { "-debug", "debugMode", XrmoptionNoArg, "True" },
1482 { "-xdebug", "debugMode", XrmoptionNoArg, "False" },
1483 { "-clockMode", "clockMode", XrmoptionSepArg, NULL },
1484 { "-clock", "clockMode", XrmoptionNoArg, "True" },
1485 { "-xclock", "clockMode", XrmoptionNoArg, "False" },
1486 { "-boardSize", "boardSize", XrmoptionSepArg, NULL },
1487 { "-size", "boardSize", XrmoptionSepArg, NULL },
1488 { "-searchTime", "searchTime", XrmoptionSepArg, NULL },
1489 { "-st", "searchTime", XrmoptionSepArg, NULL },
1490 { "-searchDepth", "searchDepth", XrmoptionSepArg, NULL },
1491 { "-depth", "searchDepth", XrmoptionSepArg, NULL },
1492 { "-showCoords", "showCoords", XrmoptionSepArg, NULL },
1493 { "-coords", "showCoords", XrmoptionNoArg, "True" },
1494 { "-xcoords", "showCoords", XrmoptionNoArg, "False" },
1496 { "-showJail", "showJail", XrmoptionSepArg, NULL },
1497 { "-jail", "showJail", XrmoptionNoArg, "1" },
1498 { "-sidejail", "showJail", XrmoptionNoArg, "2" },
1499 { "-xjail", "showJail", XrmoptionNoArg, "0" },
1501 { "-showThinking", "showThinking", XrmoptionSepArg, NULL },
1502 { "-thinking", "showThinking", XrmoptionNoArg, "True" },
1503 { "-xthinking", "showThinking", XrmoptionNoArg, "False" },
1504 { "-ponderNextMove", "ponderNextMove", XrmoptionSepArg, NULL },
1505 { "-ponder", "ponderNextMove", XrmoptionNoArg, "True" },
1506 { "-xponder", "ponderNextMove", XrmoptionNoArg, "False" },
1507 { "-periodicUpdates", "periodicUpdates", XrmoptionSepArg, NULL },
1508 { "-periodic", "periodicUpdates", XrmoptionNoArg, "True" },
1509 { "-xperiodic", "periodicUpdates", XrmoptionNoArg, "False" },
1510 { "-clockFont", "clockFont", XrmoptionSepArg, NULL },
1511 { "-coordFont", "coordFont", XrmoptionSepArg, NULL },
1512 { "-font", "font", XrmoptionSepArg, NULL },
1513 { "-ringBellAfterMoves", "ringBellAfterMoves", XrmoptionSepArg, NULL },
1514 { "-bell", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1515 { "-xbell", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1516 { "-movesound", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1517 { "-xmovesound", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1518 { "-autoCallFlag", "autoCallFlag", XrmoptionSepArg, NULL },
1519 { "-autoflag", "autoCallFlag", XrmoptionNoArg, "True" },
1520 { "-xautoflag", "autoCallFlag", XrmoptionNoArg, "False" },
1521 { "-autoFlipView", "autoFlipView", XrmoptionSepArg, NULL },
1522 { "-autoflip", "autoFlipView", XrmoptionNoArg, "True" },
1523 { "-xautoflip", "autoFlipView", XrmoptionNoArg, "False" },
1524 { "-autoObserve", "autoObserve", XrmoptionSepArg, NULL },
1525 { "-autobs", "autoObserve", XrmoptionNoArg, "True" },
1526 { "-xautobs", "autoObserve", XrmoptionNoArg, "False" },
1527 { "-autoComment", "autoComment", XrmoptionSepArg, NULL },
1528 { "-autocomm", "autoComment", XrmoptionNoArg, "True" },
1529 { "-xautocomm", "autoComment", XrmoptionNoArg, "False" },
1530 { "-getMoveList", "getMoveList", XrmoptionSepArg, NULL },
1531 { "-moves", "getMoveList", XrmoptionNoArg, "True" },
1532 { "-xmoves", "getMoveList", XrmoptionNoArg, "False" },
1534 { "-highlightDragging", "highlightDragging", XrmoptionSepArg, NULL },
1535 { "-highdrag", "highlightDragging", XrmoptionNoArg, "True" },
1536 { "-xhighdrag", "highlightDragging", XrmoptionNoArg, "False" },
1538 { "-highlightLastMove", "highlightLastMove", XrmoptionSepArg, NULL },
1539 { "-highlight", "highlightLastMove", XrmoptionNoArg, "True" },
1540 { "-xhighlight", "highlightLastMove", XrmoptionNoArg, "False" },
1541 { "-premove", "premove", XrmoptionSepArg, NULL },
1542 { "-pre", "premove", XrmoptionNoArg, "True" },
1543 { "-xpre", "premove", XrmoptionNoArg, "False" },
1544 { "-testLegality", "testLegality", XrmoptionSepArg, NULL },
1545 { "-legal", "testLegality", XrmoptionNoArg, "True" },
1546 { "-xlegal", "testLegality", XrmoptionNoArg, "False" },
1547 { "-flipView", "flipView", XrmoptionSepArg, NULL },
1548 { "-flip", "flipView", XrmoptionNoArg, "True" },
1549 { "-xflip", "flipView", XrmoptionNoArg, "False" },
1550 { "-cmail", "cmailGameName", XrmoptionSepArg, NULL },
1551 { "-alwaysPromoteToQueen", "alwaysPromoteToQueen",
1552 XrmoptionSepArg, NULL },
1553 { "-queen", "alwaysPromoteToQueen", XrmoptionNoArg, "True" },
1554 { "-xqueen", "alwaysPromoteToQueen", XrmoptionNoArg, "False" },
1555 { "-oldSaveStyle", "oldSaveStyle", XrmoptionSepArg, NULL },
1556 { "-oldsave", "oldSaveStyle", XrmoptionNoArg, "True" },
1557 { "-xoldsave", "oldSaveStyle", XrmoptionNoArg, "False" },
1558 { "-quietPlay", "quietPlay", XrmoptionSepArg, NULL },
1559 { "-quiet", "quietPlay", XrmoptionNoArg, "True" },
1560 { "-xquiet", "quietPlay", XrmoptionNoArg, "False" },
1561 { "-titleInWindow", "titleInWindow", XrmoptionSepArg, NULL },
1562 { "-title", "titleInWindow", XrmoptionNoArg, "True" },
1563 { "-xtitle", "titleInWindow", XrmoptionNoArg, "False" },
1565 { "-zippyTalk", "zippyTalk", XrmoptionSepArg, NULL },
1566 { "-zt", "zippyTalk", XrmoptionNoArg, "True" },
1567 { "-xzt", "zippyTalk", XrmoptionNoArg, "False" },
1568 { "-zippyPlay", "zippyPlay", XrmoptionSepArg, NULL },
1569 { "-zp", "zippyPlay", XrmoptionNoArg, "True" },
1570 { "-xzp", "zippyPlay", XrmoptionNoArg, "False" },
1571 { "-zippyLines", "zippyLines", XrmoptionSepArg, NULL },
1572 { "-zippyPinhead", "zippyPinhead", XrmoptionSepArg, NULL },
1573 { "-zippyPassword", "zippyPassword", XrmoptionSepArg, NULL },
1574 { "-zippyPassword2", "zippyPassword2", XrmoptionSepArg, NULL },
1575 { "-zippyWrongPassword", "zippyWrongPassword", XrmoptionSepArg, NULL },
1576 { "-zippyAcceptOnly", "zippyAcceptOnly", XrmoptionSepArg, NULL },
1577 { "-zippyUseI", "zippyUseI", XrmoptionSepArg, NULL },
1578 { "-zui", "zippyUseI", XrmoptionNoArg, "True" },
1579 { "-xzui", "zippyUseI", XrmoptionNoArg, "False" },
1580 { "-zippyBughouse", "zippyBughouse", XrmoptionSepArg, NULL },
1581 { "-zippyNoplayCrafty", "zippyNoplayCrafty", XrmoptionSepArg, NULL },
1582 { "-znc", "zippyNoplayCrafty", XrmoptionNoArg, "True" },
1583 { "-xznc", "zippyNoplayCrafty", XrmoptionNoArg, "False" },
1584 { "-zippyGameEnd", "zippyGameEnd", XrmoptionSepArg, NULL },
1585 { "-zippyGameStart", "zippyGameStart", XrmoptionSepArg, NULL },
1586 { "-zippyAdjourn", "zippyAdjourn", XrmoptionSepArg, NULL },
1587 { "-zadj", "zippyAdjourn", XrmoptionNoArg, "True" },
1588 { "-xzadj", "zippyAdjourn", XrmoptionNoArg, "False" },
1589 { "-zippyAbort", "zippyAbort", XrmoptionSepArg, NULL },
1590 { "-zab", "zippyAbort", XrmoptionNoArg, "True" },
1591 { "-xzab", "zippyAbort", XrmoptionNoArg, "False" },
1592 { "-zippyVariants", "zippyVariants", XrmoptionSepArg, NULL },
1593 { "-zippyMaxGames", "zippyMaxGames", XrmoptionSepArg, NULL },
1594 { "-zippyReplayTimeout", "zippyReplayTimeout", XrmoptionSepArg, NULL },
1595 { "-zippyShortGame", "zippyShortGame", XrmoptionSepArg, NULL },
1597 { "-flashCount", "flashCount", XrmoptionSepArg, NULL },
1598 { "-flash", "flashCount", XrmoptionNoArg, "3" },
1599 { "-xflash", "flashCount", XrmoptionNoArg, "0" },
1600 { "-flashRate", "flashRate", XrmoptionSepArg, NULL },
1601 { "-pixmapDirectory", "pixmapDirectory", XrmoptionSepArg, NULL },
1602 { "-msLoginDelay", "msLoginDelay", XrmoptionSepArg, NULL },
1603 { "-pixmap", "pixmapDirectory", XrmoptionSepArg, NULL },
1604 { "-colorizeMessages", "colorizeMessages", XrmoptionSepArg, NULL },
1605 { "-colorize", "colorizeMessages", XrmoptionNoArg, "True" },
1606 { "-xcolorize", "colorizeMessages", XrmoptionNoArg, "False" },
1607 { "-colorShout", "colorShout", XrmoptionSepArg, NULL },
1608 { "-colorSShout", "colorSShout", XrmoptionSepArg, NULL },
1609 { "-colorCShout", "colorSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1610 { "-colorChannel1", "colorChannel1", XrmoptionSepArg, NULL },
1611 { "-colorChannel", "colorChannel", XrmoptionSepArg, NULL },
1612 { "-colorKibitz", "colorKibitz", XrmoptionSepArg, NULL },
1613 { "-colorTell", "colorTell", XrmoptionSepArg, NULL },
1614 { "-colorChallenge", "colorChallenge", XrmoptionSepArg, NULL },
1615 { "-colorRequest", "colorRequest", XrmoptionSepArg, NULL },
1616 { "-colorSeek", "colorSeek", XrmoptionSepArg, NULL },
1617 { "-colorNormal", "colorNormal", XrmoptionSepArg, NULL },
1618 { "-soundProgram", "soundProgram", XrmoptionSepArg, NULL },
1619 { "-soundShout", "soundShout", XrmoptionSepArg, NULL },
1620 { "-soundSShout", "soundSShout", XrmoptionSepArg, NULL },
1621 { "-soundCShout", "soundSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1622 { "-soundChannel1", "soundChannel1", XrmoptionSepArg, NULL },
1623 { "-soundChannel", "soundChannel", XrmoptionSepArg, NULL },
1624 { "-soundKibitz", "soundKibitz", XrmoptionSepArg, NULL },
1625 { "-soundTell", "soundTell", XrmoptionSepArg, NULL },
1626 { "-soundChallenge", "soundChallenge", XrmoptionSepArg, NULL },
1627 { "-soundRequest", "soundRequest", XrmoptionSepArg, NULL },
1628 { "-soundSeek", "soundSeek", XrmoptionSepArg, NULL },
1629 { "-soundMove", "soundMove", XrmoptionSepArg, NULL },
1630 { "-soundIcsWin", "soundIcsWin", XrmoptionSepArg, NULL },
1631 { "-soundIcsLoss", "soundIcsLoss", XrmoptionSepArg, NULL },
1632 { "-soundIcsDraw", "soundIcsDraw", XrmoptionSepArg, NULL },
1633 { "-soundIcsUnfinished", "soundIcsUnfinished", XrmoptionSepArg, NULL },
1634 { "-soundIcsAlarm", "soundIcsAlarm", XrmoptionSepArg, NULL },
1635 { "-reuseFirst", "reuseFirst", XrmoptionSepArg, NULL },
1636 { "-reuseChessPrograms", "reuseFirst", XrmoptionSepArg, NULL }, /*compat*/
1637 { "-reuse", "reuseFirst", XrmoptionNoArg, "True" },
1638 { "-xreuse", "reuseFirst", XrmoptionNoArg, "False" },
1639 { "-reuseSecond", "reuseSecond", XrmoptionSepArg, NULL },
1640 { "-reuse2", "reuseSecond", XrmoptionNoArg, "True" },
1641 { "-xreuse2", "reuseSecond", XrmoptionNoArg, "False" },
1642 { "-animateMoving", "animateMoving", XrmoptionSepArg, NULL },
1643 { "-animate", "animateMoving", XrmoptionNoArg, "True" },
1644 { "-xanimate", "animateMoving", XrmoptionNoArg, "False" },
1645 { "-animateDragging", "animateDragging", XrmoptionSepArg, NULL },
1646 { "-drag", "animateDragging", XrmoptionNoArg, "True" },
1647 { "-xdrag", "animateDragging", XrmoptionNoArg, "False" },
1648 { "-animateSpeed", "animateSpeed", XrmoptionSepArg, NULL },
1649 { "-popupExitMessage", "popupExitMessage", XrmoptionSepArg, NULL },
1650 { "-exit", "popupExitMessage", XrmoptionNoArg, "True" },
1651 { "-xexit", "popupExitMessage", XrmoptionNoArg, "False" },
1652 { "-popupMoveErrors", "popupMoveErrors", XrmoptionSepArg, NULL },
1653 { "-popup", "popupMoveErrors", XrmoptionNoArg, "True" },
1654 { "-xpopup", "popupMoveErrors", XrmoptionNoArg, "False" },
1655 { "-fontSizeTolerance", "fontSizeTolerance", XrmoptionSepArg, NULL },
1656 { "-initialMode", "initialMode", XrmoptionSepArg, NULL },
1657 { "-mode", "initialMode", XrmoptionSepArg, NULL },
1658 { "-variant", "variant", XrmoptionSepArg, NULL },
1659 { "-firstProtocolVersion", "firstProtocolVersion", XrmoptionSepArg, NULL },
1660 { "-secondProtocolVersion","secondProtocolVersion",XrmoptionSepArg, NULL },
1661 { "-showButtonBar", "showButtonBar", XrmoptionSepArg, NULL },
1662 { "-buttons", "showButtonBar", XrmoptionNoArg, "True" },
1663 { "-xbuttons", "showButtonBar", XrmoptionNoArg, "False" },
1664 { "-lowTimeWarningColor", "lowTimeWarningColor", XrmoptionSepArg, NULL },
1665 { "-lowTimeWarning", "lowTimeWarning", XrmoptionSepArg, NULL },
1666 /* [AS,HR] New features */
1667 { "-firstScoreAbs", "firstScoreAbs", XrmoptionSepArg, NULL },
1668 { "-secondScoreAbs", "secondScoreAbs", XrmoptionSepArg, NULL },
1669 { "-pgnExtendedInfo", "pgnExtendedInfo", XrmoptionSepArg, NULL },
1670 { "-hideThinkingFromHuman", "hideThinkingFromHuman", XrmoptionSepArg, NULL },
1671 { "-adjudicateLossThreshold", "adjudicateLossThreshold", XrmoptionSepArg, NULL },
1672 { "-adjudicateDrawMoves", "adjudicateDrawMoves", XrmoptionSepArg, NULL },
1673 { "-pgnEventHeader", "pgnEventHeader", XrmoptionSepArg, NULL },
1674 { "-firstIsUCI", "firstIsUCI", XrmoptionSepArg, NULL },
1675 { "-secondIsUCI", "secondIsUCI", XrmoptionSepArg, NULL },
1676 { "-fUCI", "firstIsUCI", XrmoptionNoArg, "True" },
1677 { "-sUCI", "secondIsUCI", XrmoptionNoArg, "True" },
1678 { "-firstHasOwnBookUCI", "firstHasOwnBookUCI", XrmoptionSepArg, NULL },
1679 { "-secondHasOwnBookUCI", "secondHasOwnBookUCI", XrmoptionSepArg, NULL },
1680 { "-fNoOwnBookUCI", "firstHasOwnBookUCI", XrmoptionNoArg, "False" },
1681 { "-sNoOwnBookUCI", "secondHasOwnBookUCI", XrmoptionNoArg, "False" },
1682 { "-firstXBook", "firstHasOwnBookUCI", XrmoptionNoArg, "False" },
1683 { "-secondXBook", "secondHasOwnBookUCI", XrmoptionNoArg, "False" },
1684 { "-polyglotDir", "polyglotDir", XrmoptionSepArg, NULL },
1685 { "-usePolyglotBook", "usePolyglotBook", XrmoptionSepArg, NULL },
1686 { "-polyglotBook", "polyglotBook", XrmoptionSepArg, NULL },
1687 { "-defaultHashSize", "defaultHashSize", XrmoptionSepArg, NULL },
1688 { "-defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XrmoptionSepArg, NULL },
1689 { "-defaultPathEGTB", "defaultPathEGTB", XrmoptionSepArg, NULL },
1690 { "-defaultFrcPosition", "defaultFrcPosition", XrmoptionSepArg, NULL },
1691 { "-gameListTags", "gameListTags", XrmoptionSepArg, NULL },
1692 // [HGM] I am sure AS added many more options, but we have to fish them out, from the list in winboard.c
1694 /* [HGM,HR] User-selectable board size */
1695 { "-boardWidth", "boardWidth", XrmoptionSepArg, NULL },
1696 { "-boardHeight", "boardHeight", XrmoptionSepArg, NULL },
1697 { "-matchPause", "matchPause", XrmoptionSepArg, NULL },
1699 /* [HGM] new arguments of 4.3.xx. All except first three are back-end options, which should work immediately */
1700 { "-holdingsSize", "holdingsSize", XrmoptionSepArg, NULL }, // requires extensive front-end changes to work
1701 { "-flipBlack", "flipBlack", XrmoptionSepArg, NULL }, // requires front-end changes to work
1702 { "-allWhite", "allWhite", XrmoptionSepArg, NULL }, // requires front-end changes to work
1703 { "-pieceToCharTable", "pieceToCharTable", XrmoptionSepArg, NULL },
1704 { "-alphaRank", "alphaRank", XrmoptionSepArg, NULL },
1705 { "-testClaims", "testClaims", XrmoptionSepArg, NULL },
1706 { "-checkMates", "checkMates", XrmoptionSepArg, NULL },
1707 { "-materialDraws", "materialDraws", XrmoptionSepArg, NULL },
1708 { "-trivialDraws", "trivialDraws", XrmoptionSepArg, NULL },
1709 { "-ruleMoves", "ruleMoves", XrmoptionSepArg, NULL },
1710 { "-repeatsToDraw", "repeatsToDraw", XrmoptionSepArg, NULL },
1711 { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL },
1712 { "-userName", "userName", XrmoptionSepArg, NULL },
1713 { "-autoKibitz", "autoKibitz", XrmoptionNoArg, "True" },
1714 { "-firstTimeOdds", "firstTimeOdds", XrmoptionSepArg, NULL },
1715 { "-secondTimeOdds", "secondTimeOdds", XrmoptionSepArg, NULL },
1716 { "-timeOddsMode", "timeOddsMode", XrmoptionSepArg, NULL },
1717 { "-firstAccumulateTC", "firstAccumulateTC", XrmoptionSepArg, NULL },
1718 { "-secondAccumulateTC", "secondAccumulateTC", XrmoptionSepArg, NULL },
1719 { "-firstNPS", "firstNPS", XrmoptionSepArg, NULL },
1720 { "-secondNPS", "secondNPS", XrmoptionSepArg, NULL },
1721 { "-serverMoves", "serverMoves", XrmoptionSepArg, NULL },
1722 { "-serverPause", "serverPause", XrmoptionSepArg, NULL },
1723 { "-suppressLoadMoves", "suppressLoadMoves", XrmoptionSepArg, NULL },
1724 { "-egtFormats", "egtFormats", XrmoptionSepArg, NULL },
1725 { "-userName", "userName", XrmoptionSepArg, NULL },
1726 { "-smpCores", "smpCores", XrmoptionSepArg, NULL },
1727 { "-sameColorGames", "sameColorGames", XrmoptionSepArg, NULL },
1728 { "-rewindIndex", "rewindIndex", XrmoptionSepArg, NULL },
1729 { "-niceEngines", "niceEngines", XrmoptionSepArg, NULL },
1730 { "-delayBeforeQuit", "delayBeforeQuit", XrmoptionSepArg, NULL },
1731 { "-delayAfterQuit", "delayAfterQuit", XrmoptionSepArg, NULL },
1732 { "-nameOfDebugFile", "nameOfDebugFile", XrmoptionSepArg, NULL },
1733 { "-debugFile", "nameOfDebugFile", XrmoptionSepArg, NULL },
1734 { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL },
1735 { "-noGUI", "noGUI", XrmoptionNoArg, "True" },
1736 { "-firstOptions", "firstOptions", XrmoptionSepArg, NULL },
1737 { "-secondOptions", "secondOptions", XrmoptionSepArg, NULL },
1738 { "-firstNeedsNoncompliantFEN", "firstNeedsNoncompliantFEN", XrmoptionSepArg, NULL },
1739 { "-secondNeedsNoncompliantFEN", "secondNeedsNoncompliantFEN", XrmoptionSepArg, NULL },
1740 { "-keepAlive", "keepAlive", XrmoptionSepArg, NULL },
1741 { "-forceIllegalMoves", "forceIllegalMoves", XrmoptionNoArg, "True" },
1742 { "-keepLineBreaksICS", "keepLineBreaksICS", XrmoptionSepArg, NULL },
1746 XtActionsRec boardActions[] = {
1747 { "HandleUserMove", HandleUserMove },
1748 { "AnimateUserMove", AnimateUserMove },
1749 // { "FileNameAction", FileNameAction },
1750 { "AskQuestionProc", AskQuestionProc },
1751 { "AskQuestionReplyAction", AskQuestionReplyAction },
1752 { "PieceMenuPopup", PieceMenuPopup },
1753 // { "WhiteClock", WhiteClock },
1754 // { "BlackClock", BlackClock },
1755 { "Iconify", Iconify },
1756 { "LoadSelectedProc", LoadSelectedProc },
1757 // { "LoadPositionProc", LoadPositionProc },
1758 // { "LoadNextPositionProc", LoadNextPositionProc },
1759 // { "LoadPrevPositionProc", LoadPrevPositionProc },
1760 // { "ReloadPositionProc", ReloadPositionProc },
1761 { "CopyPositionProc", CopyPositionProc },
1762 { "PastePositionProc", PastePositionProc },
1763 { "CopyGameProc", CopyGameProc },
1764 { "PasteGameProc", PasteGameProc },
1765 // { "SaveGameProc", SaveGameProc },
1766 // { "SavePositionProc", SavePositionProc },
1767 { "MailMoveProc", MailMoveProc },
1768 { "ReloadCmailMsgProc", ReloadCmailMsgProc },
1769 // { "MachineWhiteProc", MachineWhiteProc },
1770 // { "MachineBlackProc", MachineBlackProc },
1771 { "AnalysisModeProc", AnalyzeModeProc },
1772 // { "AnalyzeFileProc", AnalyzeFileProc },
1773 // { "TwoMachinesProc", TwoMachinesProc },
1774 // { "IcsClientProc", IcsClientProc },
1775 { "EditGameProc", EditGameProc },
1776 { "EditPositionProc", EditPositionProc },
1777 { "TrainingProc", EditPositionProc },
1778 { "EngineOutputProc", EngineOutputProc}, // [HGM] Winboard_x engine-output window
1779 { "ShowGameListProc", ShowGameListProc },
1780 // { "ShowMoveListProc", HistoryShowProc},
1781 { "EditTagsProc", EditCommentProc },
1782 { "EditCommentProc", EditCommentProc },
1783 // { "IcsAlarmProc", IcsAlarmProc },
1784 { "IcsInputBoxProc", IcsInputBoxProc },
1785 // { "AcceptProc", AcceptProc },
1786 // { "DeclineProc", DeclineProc },
1787 // { "RematchProc", RematchProc },
1788 // { "CallFlagProc", CallFlagProc },
1789 // { "DrawProc", DrawProc },
1790 // { "AdjournProc", AdjournProc },
1791 // { "AbortProc", AbortProc },
1792 // { "ResignProc", ResignProc },
1793 // { "AdjuWhiteProc", AdjuWhiteProc },
1794 // { "AdjuBlackProc", AdjuBlackProc },
1795 // { "AdjuDrawProc", AdjuDrawProc },
1796 { "EnterKeyProc", EnterKeyProc },
1797 // { "StopObservingProc", StopObservingProc },
1798 // { "StopExaminingProc", StopExaminingProc },
1799 // { "BackwardProc", BackwardProc },
1800 // { "ForwardProc", ForwardProc },
1801 // { "ToStartProc", ToStartProc },
1802 // { "ToEndProc", ToEndProc },
1803 // { "RevertProc", RevertProc },
1804 // { "TruncateGameProc", TruncateGameProc },
1805 // { "MoveNowProc", MoveNowProc },
1806 // { "RetractMoveProc", RetractMoveProc },
1807 // { "AlwaysQueenProc", AlwaysQueenProc },
1808 // { "AnimateDraggingProc", AnimateDraggingProc },
1809 // { "AnimateMovingProc", AnimateMovingProc },
1810 // { "AutoflagProc", AutoflagProc },
1811 // { "AutoflipProc", AutoflipProc },
1812 // { "AutobsProc", AutobsProc },
1813 // { "AutoraiseProc", AutoraiseProc },
1814 // { "AutosaveProc", AutosaveProc },
1815 // { "BlindfoldProc", BlindfoldProc },
1816 // { "FlashMovesProc", FlashMovesProc },
1817 // { "FlipViewProc", FlipViewProc },
1818 // { "GetMoveListProc", GetMoveListProc },
1820 // { "HighlightDraggingProc", HighlightDraggingProc },
1822 // { "HighlightLastMoveProc", HighlightLastMoveProc },
1823 // { "IcsAlarmProc", IcsAlarmProc },
1824 // { "MoveSoundProc", MoveSoundProc },
1825 // { "OldSaveStyleProc", OldSaveStyleProc },
1826 // { "PeriodicUpdatesProc", PeriodicUpdatesProc },
1827 { "PonderNextMoveProc", PonderNextMoveProc },
1828 { "PopupExitMessageProc", PopupExitMessageProc },
1829 { "PopupMoveErrorsProc", PopupMoveErrorsProc },
1830 { "PremoveProc", PremoveProc },
1831 { "QuietPlayProc", QuietPlayProc },
1832 // { "ShowThinkingProc", ShowThinkingProc },
1833 // { "HideThinkingProc", HideThinkingProc },
1834 { "TestLegalityProc", TestLegalityProc },
1835 // { "InfoProc", InfoProc },
1836 // { "ManProc", ManProc },
1837 // { "HintProc", HintProc },
1838 // { "BookProc", BookProc },
1839 { "AboutGameProc", AboutGameProc },
1840 { "DebugProc", DebugProc },
1841 { "NothingProc", NothingProc },
1842 { "CommentPopDown", (XtActionProc) CommentPopDown },
1843 { "EditCommentPopDown", (XtActionProc) EditCommentPopDown },
1844 { "TagsPopDown", (XtActionProc) TagsPopDown },
1845 { "ErrorPopDown", (XtActionProc) ErrorPopDown },
1846 { "ICSInputBoxPopDown", (XtActionProc) ICSInputBoxPopDown },
1847 { "EngineOutputPopDown", (XtActionProc) EngineOutputPopDown },
1848 // { "FileNamePopDown", (XtActionProc) FileNamePopDown },
1849 { "AskQuestionPopDown", (XtActionProc) AskQuestionPopDown },
1850 { "GameListPopDown", (XtActionProc) GameListPopDown },
1851 { "PromotionPopDown", (XtActionProc) PromotionPopDown },
1852 // { "HistoryPopDown", (XtActionProc) HistoryPopDown },
1853 { "EngineOutputPopDown", (XtActionProc) EngineOutputPopDown },
1854 { "ShufflePopDown", (XtActionProc) ShufflePopDown },
1855 { "EnginePopDown", (XtActionProc) EnginePopDown },
1856 { "UciPopDown", (XtActionProc) UciPopDown },
1857 { "TimeControlPopDown", (XtActionProc) TimeControlPopDown },
1858 { "NewVariantPopDown", (XtActionProc) NewVariantPopDown },
1859 { "SettingsPopDown", (XtActionProc) SettingsPopDown },
1863 char ICSInputTranslations[] =
1864 "<Key>Return: EnterKeyProc() \n";
1866 String xboardResources[] = {
1867 // "*fileName*value.translations: #override\\n <Key>Return: FileNameAction()",
1868 "*question*value.translations: #override\\n <Key>Return: AskQuestionReplyAction()",
1869 "*errorpopup*translations: #override\\n <Key>Return: ErrorPopDown()",
1873 static char *cnames[9] = { "black", "red", "green", "yellow", "blue",
1874 "magenta", "cyan", "white" };
1878 TextColors textColors[(int)NColorClasses];
1880 /* String is: "fg, bg, attr". Which is 0, 1, 2 */
1882 parse_color(str, which)
1886 char *p, buf[100], *d;
1889 if (strlen(str) > 99) /* watch bounds on buf */
1894 for (i=0; i<which; ++i) {
1901 /* Could be looking at something like:
1903 .. in which case we want to stop on a comma also */
1904 while (*p && *p != ',' && !isalpha(*p) && !isdigit(*p))
1908 return -1; /* Use default for empty field */
1911 if (which == 2 || isdigit(*p))
1914 while (*p && isalpha(*p))
1919 for (i=0; i<8; ++i) {
1920 if (!StrCaseCmp(buf, cnames[i]))
1921 return which? (i+40) : (i+30);
1923 if (!StrCaseCmp(buf, "default")) return -1;
1925 fprintf(stderr, _("%s: unrecognized color %s\n"), programName, buf);
1930 parse_cpair(cc, str)
1934 if ((textColors[(int)cc].fg=parse_color(str, 0)) == -2) {
1935 fprintf(stderr, _("%s: can't parse foreground color in `%s'\n"),
1940 /* bg and attr are optional */
1941 textColors[(int)cc].bg = parse_color(str, 1);
1942 if ((textColors[(int)cc].attr = parse_color(str, 2)) < 0) {
1943 textColors[(int)cc].attr = 0;
1949 /* Arrange to catch delete-window events */
1950 Atom wm_delete_window;
1952 CatchDeleteWindow(Widget w, String procname)
1955 XSetWMProtocols(xDisplay, XtWindow(w), &wm_delete_window, 1);
1956 snprintf(buf, sizeof(buf), "<Message>WM_PROTOCOLS: %s() \n", procname);
1957 XtAugmentTranslations(w, XtParseTranslationTable(buf));
1963 /* this should raise the board to the top */
1964 gtk_window_present(GTK_WINDOW(GUI_Window));
1968 #define BoardSize int
1969 void InitDrawingSizes(BoardSize boardSize, int flags)
1970 { // [HGM] resize is functional now, but for board format changes only (nr of ranks, files)
1971 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
1973 XtGeometryResult gres;
1976 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
1977 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
1979 timerWidth = (boardWidth - sep) / 2;
1981 if (appData.titleInWindow)
1986 w = boardWidth - 2*bor;
1990 w = boardWidth - w - sep - 2*bor - 2; // WIDTH_FUDGE
1994 if(!formWidget) return;
1997 * Inhibit shell resizing.
2000 // [HGM] pieces: tailor piece bitmaps to needs of specific variant
2003 for(i=0; i<4; i++) {
2005 for(p=0; p<=(int)WhiteKing; p++)
2006 xpmPieceBitmap[i][p] = xpmPieceBitmap2[i][p]; // defaults
2007 if(gameInfo.variant == VariantShogi) {
2008 xpmPieceBitmap[i][(int)WhiteCannon] = xpmPieceBitmap2[i][(int)WhiteKing+1];
2009 xpmPieceBitmap[i][(int)WhiteNightrider] = xpmPieceBitmap2[i][(int)WhiteKing+2];
2010 xpmPieceBitmap[i][(int)WhiteSilver] = xpmPieceBitmap2[i][(int)WhiteKing+3];
2011 xpmPieceBitmap[i][(int)WhiteGrasshopper] = xpmPieceBitmap2[i][(int)WhiteKing+4];
2012 xpmPieceBitmap[i][(int)WhiteQueen] = xpmPieceBitmap2[i][(int)WhiteLance];
2015 if(gameInfo.variant == VariantGothic) {
2016 xpmPieceBitmap[i][(int)WhiteMarshall] = xpmPieceBitmap2[i][(int)WhiteSilver];
2020 // [HGM] why are thee ximMasks used at all? the ximPieceBitmaps seem to be never used!
2021 for(p=0; p<=(int)WhiteKing; p++)
2022 ximMaskPm[p] = ximMaskPm2[p]; // defaults
2023 if(gameInfo.variant == VariantShogi) {
2024 ximMaskPm[(int)WhiteCannon] = ximMaskPm2[(int)WhiteKing+1];
2025 ximMaskPm[(int)WhiteNightrider] = ximMaskPm2[(int)WhiteKing+2];
2026 ximMaskPm[(int)WhiteSilver] = ximMaskPm2[(int)WhiteKing+3];
2027 ximMaskPm[(int)WhiteGrasshopper] = ximMaskPm2[(int)WhiteKing+4];
2028 ximMaskPm[(int)WhiteQueen] = ximMaskPm2[(int)WhiteLance];
2031 if(gameInfo.variant == VariantGothic) {
2032 ximMaskPm[(int)WhiteMarshall] = ximMaskPm2[(int)WhiteSilver];
2038 for(i=0; i<2; i++) {
2040 for(p=0; p<=(int)WhiteKing; p++)
2041 pieceBitmap[i][p] = pieceBitmap2[i][p]; // defaults
2042 if(gameInfo.variant == VariantShogi) {
2043 pieceBitmap[i][(int)WhiteCannon] = pieceBitmap2[i][(int)WhiteKing+1];
2044 pieceBitmap[i][(int)WhiteNightrider] = pieceBitmap2[i][(int)WhiteKing+2];
2045 pieceBitmap[i][(int)WhiteSilver] = pieceBitmap2[i][(int)WhiteKing+3];
2046 pieceBitmap[i][(int)WhiteGrasshopper] = pieceBitmap2[i][(int)WhiteKing+4];
2047 pieceBitmap[i][(int)WhiteQueen] = pieceBitmap2[i][(int)WhiteLance];
2050 if(gameInfo.variant == VariantGothic) {
2051 pieceBitmap[i][(int)WhiteMarshall] = pieceBitmap2[i][(int)WhiteSilver];
2061 void EscapeExpand(char *p, char *q)
2062 { // [HGM] initstring: routine to shape up string arguments
2063 while(*p++ = *q++) if(p[-1] == '\\')
2065 case 'n': p[-1] = '\n'; break;
2066 case 'r': p[-1] = '\r'; break;
2067 case 't': p[-1] = '\t'; break;
2068 case '\\': p[-1] = '\\'; break;
2069 case 0: *p = 0; return;
2070 default: p[-1] = q[-1]; break;
2079 int i, j, clockFontPxlSize, coordFontPxlSize, fontPxlSize;
2080 XSetWindowAttributes window_attributes;
2082 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
2083 XrmValue vFrom, vTo;
2084 XtGeometryResult gres;
2087 int forceMono = False;
2091 // [HGM] before anything else, expand any indirection files amongst options
2092 char *argvCopy[1000]; // 1000 seems enough
2093 char newArgs[10000]; // holds actual characters
2096 srandom(time(0)); // [HGM] book: make random truly random
2099 for(i=0; i<argc; i++) {
2100 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2101 //fprintf(stderr, "arg %s\n", argv[i]);
2102 if(argv[i][0] != '@') argvCopy[j++] = argv[i]; else {
2104 FILE *f = fopen(argv[i]+1, "rb");
2105 if(f == NULL) { fprintf(stderr, _("ignore %s\n"), argv[i]); continue; } // do not expand non-existing
2106 argvCopy[j++] = newArgs + k; // get ready for first argument from file
2107 while((c = fgetc(f)) != EOF) { // each line of file inserts 1 argument in the list
2109 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2110 newArgs[k++] = 0; // terminate current arg
2111 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2112 argvCopy[j++] = newArgs + k; // get ready for next
2114 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2128 setbuf(stdout, NULL);
2129 setbuf(stderr, NULL);
2132 programName = strrchr(argv[0], '/');
2133 if (programName == NULL)
2134 programName = argv[0];
2139 XtSetLanguageProc(NULL, NULL, NULL);
2140 bindtextdomain(PACKAGE, LOCALEDIR);
2141 textdomain(PACKAGE);
2145 XtAppInitialize(&appContext, "XBoard", shellOptions,
2146 XtNumber(shellOptions),
2147 &argc, argv, xboardResources, NULL, 0);
2150 gtk_init (&argc, &argv);
2152 /* parse glade file to build widgets */
2154 builder = gtk_builder_new ();
2155 gtk_builder_add_from_file (builder, "gtk-interface.xml", NULL);
2157 /* test if everything worked ok */
2159 GUI_Window = GTK_WIDGET (gtk_builder_get_object (builder, "MainWindow"));
2160 if(!GUI_Window) printf("Error: gtk_builder didn't work!\n");
2162 GUI_Aspect = GTK_WIDGET (gtk_builder_get_object (builder, "Aspectframe"));
2163 if(!GUI_Aspect) printf("Error: gtk_builder didn't work!\n");
2165 GUI_History = GTK_WIDGET (gtk_builder_get_object (builder, "MoveHistory"));
2166 if(!GUI_History) printf("Error: gtk_builder didn't work!\n");
2168 GUI_Menubar = GTK_WIDGET (gtk_builder_get_object (builder, "MenuBar"));
2169 if(!GUI_Menubar) printf("Error: gtk_builder didn't work!\n");
2170 GUI_Timer = GTK_WIDGET (gtk_builder_get_object (builder, "Timer"));
2171 if(!GUI_Timer) printf("Error: gtk_builder didn't work!\n");
2172 GUI_Buttonbar = GTK_WIDGET (gtk_builder_get_object (builder, "ButtonBar"));
2173 if(!GUI_Buttonbar) printf("Error: gtk_builder didn't work!\n");
2174 GUI_Board = GTK_WIDGET (gtk_builder_get_object (builder, "Board"));
2175 if(!GUI_Board) printf("Error: gtk_builder didn't work!\n");
2177 GUI_Whiteclock = GTK_WIDGET (gtk_builder_get_object (builder, "WhiteClock"));
2178 if(!GUI_Whiteclock) printf("Error: gtk_builder didn't work!\n");
2180 GUI_Blackclock = GTK_WIDGET (gtk_builder_get_object (builder, "BlackClock"));
2181 if(!GUI_Blackclock) printf("Error: gtk_builder didn't work!\n");
2183 LIST_MoveHistory = GTK_LIST_STORE (gtk_builder_get_object (builder, "MoveHistoryStore"));
2184 if(!LIST_MoveHistory) printf("Error: gtk_builder didn't work!\n");
2187 gtk_builder_connect_signals (builder, NULL);
2189 // don't unref the builder, since we use it to get references to widgets
2190 // g_object_unref (G_OBJECT (builder));
2192 /* end parse glade file */
2196 fprintf(stderr, _("%s: unrecognized argument %s\n"),
2197 programName, argv[1]);
2199 fprintf(stderr, "Recognized options:\n");
2200 for(i = 0; i < XtNumber(shellOptions); i++)
2202 /* print first column */
2203 j = fprintf(stderr, " %s%s", shellOptions[i].option,
2204 (shellOptions[i].argKind == XrmoptionSepArg
2206 /* print second column and end line */
2207 if (++i < XtNumber(shellOptions))
2209 fprintf(stderr, "%*c%s%s\n", 40 - j, ' ',
2210 shellOptions[i].option,
2211 (shellOptions[i].argKind == XrmoptionSepArg
2216 fprintf(stderr, "\n");
2223 if (p == NULL) p = "/tmp";
2224 i = strlen(p) + strlen("/.xboardXXXXXx.pgn") + 1;
2225 gameCopyFilename = (char*) malloc(i);
2226 gamePasteFilename = (char*) malloc(i);
2227 snprintf(gameCopyFilename,i, "%s/.xboard%05uc.pgn", p, getpid());
2228 snprintf(gamePasteFilename,i, "%s/.xboard%05up.pgn", p, getpid());
2230 XtGetApplicationResources(shellWidget, (XtPointer) &appData,
2231 clientResources, XtNumber(clientResources),
2234 { // [HGM] initstring: kludge to fix bad bug. expand '\n' characters in init string and computer string.
2235 static char buf[MSG_SIZ];
2236 EscapeExpand(buf, appData.initString);
2237 appData.initString = strdup(buf);
2238 EscapeExpand(buf, appData.secondInitString);
2239 appData.secondInitString = strdup(buf);
2240 EscapeExpand(buf, appData.firstComputerString);
2241 appData.firstComputerString = strdup(buf);
2242 EscapeExpand(buf, appData.secondComputerString);
2243 appData.secondComputerString = strdup(buf);
2246 if ((chessDir = (char *) getenv("CHESSDIR")) == NULL) {
2249 if (chdir(chessDir) != 0) {
2250 fprintf(stderr, _("%s: can't cd to CHESSDIR: "), programName);
2256 if (appData.debugMode && appData.nameOfDebugFile && strcmp(appData.nameOfDebugFile, "stderr")) {
2257 /* [DM] debug info to file [HGM] make the filename a command-line option, and allow it to remain stderr */
2258 if ((debugFP = fopen(appData.nameOfDebugFile, "w")) == NULL) {
2259 printf(_("Failed to open file '%s'\n"), appData.nameOfDebugFile);
2262 setbuf(debugFP, NULL);
2265 /* [HGM,HR] make sure board size is acceptable */
2266 if(appData.NrFiles > BOARD_SIZE ||
2267 appData.NrRanks > BOARD_SIZE )
2268 DisplayFatalError(_("Recompile with BOARD_SIZE > 12, to support this size"), 0, 2);
2271 /* This feature does not work; animation needs a rewrite */
2272 appData.highlightDragging = FALSE;
2276 xDisplay = XtDisplay(shellWidget);
2277 xScreen = DefaultScreen(xDisplay);
2278 wm_delete_window = XInternAtom(xDisplay, "WM_DELETE_WINDOW", True);
2280 gameInfo.variant = StringToVariant(appData.variant);
2281 InitPosition(FALSE);
2283 /* calc board size */
2284 if (isdigit(appData.boardSize[0]))
2286 i = sscanf(appData.boardSize, "%d,%d,%d,%d,%d,%d,%d", &squareSize,
2287 &lineGap, &clockFontPxlSize, &coordFontPxlSize,
2288 &fontPxlSize, &smallLayout, &tinyLayout);
2291 fprintf(stderr, _("%s: bad boardSize syntax %s\n"),
2292 programName, appData.boardSize);
2297 /* Find some defaults; use the nearest known size */
2298 SizeDefaults *szd, *nearest;
2299 int distance = 99999;
2300 nearest = szd = sizeDefaults;
2301 while (szd->name != NULL)
2303 if (abs(szd->squareSize - squareSize) < distance)
2306 distance = abs(szd->squareSize - squareSize);
2307 if (distance == 0) break;
2311 if (i < 2) lineGap = nearest->lineGap;
2312 if (i < 3) clockFontPxlSize = nearest->clockFontPxlSize;
2313 if (i < 4) coordFontPxlSize = nearest->coordFontPxlSize;
2314 if (i < 5) fontPxlSize = nearest->fontPxlSize;
2315 if (i < 6) smallLayout = nearest->smallLayout;
2316 if (i < 7) tinyLayout = nearest->tinyLayout;
2321 SizeDefaults *szd = sizeDefaults;
2322 if (*appData.boardSize == NULLCHAR)
2324 while (DisplayWidth(xDisplay, xScreen) < szd->minScreenSize
2325 || DisplayHeight(xDisplay, xScreen) < szd->minScreenSize)
2329 if (szd->name == NULL) szd--;
2333 while (szd->name != NULL
2334 && StrCaseCmp(szd->name, appData.boardSize) != 0)
2336 if (szd->name == NULL)
2338 fprintf(stderr, _("%s: unrecognized boardSize name %s\n"),
2339 programName, appData.boardSize);
2343 squareSize = szd->squareSize;
2344 lineGap = szd->lineGap;
2345 clockFontPxlSize = szd->clockFontPxlSize;
2346 coordFontPxlSize = szd->coordFontPxlSize;
2347 fontPxlSize = szd->fontPxlSize;
2348 smallLayout = szd->smallLayout;
2349 tinyLayout = szd->tinyLayout;
2351 /* end figuring out what size to use */
2353 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2354 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2357 * Determine what fonts to use.
2359 appData.clockFont = FindFont(appData.clockFont, clockFontPxlSize);
2360 clockFontID = XLoadFont(xDisplay, appData.clockFont);
2361 clockFontStruct = XQueryFont(xDisplay, clockFontID);
2362 appData.coordFont = FindFont(appData.coordFont, coordFontPxlSize);
2363 coordFontID = XLoadFont(xDisplay, appData.coordFont);
2364 coordFontStruct = XQueryFont(xDisplay, coordFontID);
2365 appData.font = FindFont(appData.font, fontPxlSize);
2366 countFontID = XLoadFont(xDisplay, appData.coordFont); // [HGM] holdings
2367 countFontStruct = XQueryFont(xDisplay, countFontID);
2368 // appData.font = FindFont(appData.font, fontPxlSize);
2370 xdb = XtDatabase(xDisplay);
2371 XrmPutStringResource(&xdb, "*font", appData.font);
2374 * Detect if there are not enough colors available and adapt.
2376 if (DefaultDepth(xDisplay, xScreen) <= 2) {
2377 appData.monoMode = True;
2380 if (!appData.monoMode) {
2381 vFrom.addr = (caddr_t) appData.lightSquareColor;
2382 vFrom.size = strlen(appData.lightSquareColor);
2383 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2384 if (vTo.addr == NULL) {
2385 appData.monoMode = True;
2388 lightSquareColor = *(Pixel *) vTo.addr;
2391 if (!appData.monoMode) {
2392 vFrom.addr = (caddr_t) appData.darkSquareColor;
2393 vFrom.size = strlen(appData.darkSquareColor);
2394 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2395 if (vTo.addr == NULL) {
2396 appData.monoMode = True;
2399 darkSquareColor = *(Pixel *) vTo.addr;
2402 if (!appData.monoMode) {
2403 vFrom.addr = (caddr_t) appData.whitePieceColor;
2404 vFrom.size = strlen(appData.whitePieceColor);
2405 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2406 if (vTo.addr == NULL) {
2407 appData.monoMode = True;
2410 whitePieceColor = *(Pixel *) vTo.addr;
2413 if (!appData.monoMode) {
2414 vFrom.addr = (caddr_t) appData.blackPieceColor;
2415 vFrom.size = strlen(appData.blackPieceColor);
2416 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2417 if (vTo.addr == NULL) {
2418 appData.monoMode = True;
2421 blackPieceColor = *(Pixel *) vTo.addr;
2425 if (!appData.monoMode) {
2426 vFrom.addr = (caddr_t) appData.highlightSquareColor;
2427 vFrom.size = strlen(appData.highlightSquareColor);
2428 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2429 if (vTo.addr == NULL) {
2430 appData.monoMode = True;
2433 highlightSquareColor = *(Pixel *) vTo.addr;
2437 if (!appData.monoMode) {
2438 vFrom.addr = (caddr_t) appData.premoveHighlightColor;
2439 vFrom.size = strlen(appData.premoveHighlightColor);
2440 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2441 if (vTo.addr == NULL) {
2442 appData.monoMode = True;
2445 premoveHighlightColor = *(Pixel *) vTo.addr;
2450 fprintf(stderr, _("%s: too few colors available; trying monochrome mode\n"),
2453 if (appData.bitmapDirectory == NULL ||
2454 appData.bitmapDirectory[0] == NULLCHAR)
2455 appData.bitmapDirectory = DEF_BITMAP_DIR;
2458 if (appData.lowTimeWarning && !appData.monoMode) {
2459 vFrom.addr = (caddr_t) appData.lowTimeWarningColor;
2460 vFrom.size = strlen(appData.lowTimeWarningColor);
2461 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2462 if (vTo.addr == NULL)
2463 appData.monoMode = True;
2465 lowTimeWarningColor = *(Pixel *) vTo.addr;
2468 if (appData.monoMode && appData.debugMode) {
2469 fprintf(stderr, _("white pixel = 0x%lx, black pixel = 0x%lx\n"),
2470 (unsigned long) XWhitePixel(xDisplay, xScreen),
2471 (unsigned long) XBlackPixel(xDisplay, xScreen));
2474 if (parse_cpair(ColorShout, appData.colorShout) < 0 ||
2475 parse_cpair(ColorSShout, appData.colorSShout) < 0 ||
2476 parse_cpair(ColorChannel1, appData.colorChannel1) < 0 ||
2477 parse_cpair(ColorChannel, appData.colorChannel) < 0 ||
2478 parse_cpair(ColorKibitz, appData.colorKibitz) < 0 ||
2479 parse_cpair(ColorTell, appData.colorTell) < 0 ||
2480 parse_cpair(ColorChallenge, appData.colorChallenge) < 0 ||
2481 parse_cpair(ColorRequest, appData.colorRequest) < 0 ||
2482 parse_cpair(ColorSeek, appData.colorSeek) < 0 ||
2483 parse_cpair(ColorNormal, appData.colorNormal) < 0)
2485 if (appData.colorize) {
2487 _("%s: can't parse color names; disabling colorization\n"),
2490 appData.colorize = FALSE;
2492 textColors[ColorNone].fg = textColors[ColorNone].bg = -1;
2493 textColors[ColorNone].attr = 0;
2495 // XtAppAddActions(appContext, boardActions, XtNumber(boardActions));
2501 layoutName = "tinyLayout";
2502 } else if (smallLayout) {
2503 layoutName = "smallLayout";
2505 layoutName = "normalLayout";
2508 if (appData.titleInWindow) {
2509 /* todo check what this appdata does */
2512 if (appData.showButtonBar) {
2513 /* TODO hide button bar if requested */
2517 if (appData.titleInWindow)
2522 if (appData.showButtonBar)
2529 if (appData.showButtonBar)
2539 /* set some checkboxes in the menu according to appData */
2541 if (appData.alwaysPromoteToQueen)
2542 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Always Queen")),TRUE);
2544 if (appData.animateDragging)
2545 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Animate Dragging")),TRUE);
2547 if (appData.animate)
2548 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Animate Moving")),TRUE);
2550 if (appData.autoComment)
2551 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Comment")),TRUE);
2553 if (appData.autoCallFlag)
2554 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Flag")),TRUE);
2556 if (appData.autoFlipView)
2557 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Flip View")),TRUE);
2559 if (appData.autoObserve)
2560 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Observe")),TRUE);
2562 if (appData.autoRaiseBoard)
2563 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Raise Board")),TRUE);
2565 if (appData.autoSaveGames)
2566 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Save")),TRUE);
2568 if (appData.saveGameFile[0] != NULLCHAR)
2570 /* Can't turn this off from menu */
2571 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Save")),TRUE);
2572 gtk_action_set_sensitive(GTK_ACTION (gtk_builder_get_object (builder, "menuOptions.Auto Save")),FALSE);
2575 if (appData.blindfold)
2576 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Blindfold")),TRUE);
2578 if (appData.flashCount > 0)
2579 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Flash Moves")),TRUE);
2581 if (appData.getMoveList)
2582 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Get Move List")),TRUE);
2585 if (appData.highlightDragging)
2586 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Highlight Dragging")),TRUE);
2589 if (appData.highlightLastMove)
2590 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Highlight Last Move")),TRUE);
2592 if (appData.icsAlarm)
2593 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.ICS Alarm")),TRUE);
2595 if (appData.ringBellAfterMoves)
2596 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Move Sound")),TRUE);
2598 if (appData.oldSaveStyle)
2599 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Old Save Style")),TRUE);
2601 if (appData.periodicUpdates)
2602 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Periodic Updates")),TRUE);
2604 if (appData.ponderNextMove)
2605 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Ponder Next Move")),TRUE);
2607 if (appData.popupExitMessage)
2608 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Popup Exit Message")),TRUE);
2610 if (appData.popupMoveErrors)
2611 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Popup Move Errors")),TRUE);
2613 if (appData.premove)
2614 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Premove")),TRUE);
2616 if (appData.quietPlay)
2617 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Quit Play")),TRUE);
2619 if (appData.showCoords)
2620 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Show Coords")),TRUE);
2622 if (appData.showThinking)
2623 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Show Thinking")),TRUE);
2625 if (appData.testLegality)
2626 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Test Legality")),TRUE);
2628 /* end setting check boxes */
2630 /* load square colors */
2631 SVGLightSquare = load_pixbuf("svg/LightSquare.svg",squareSize);
2632 SVGDarkSquare = load_pixbuf("svg/DarkSquare.svg",squareSize);
2633 SVGNeutralSquare = load_pixbuf("svg/NeutralSquare.svg",squareSize);
2635 /* use two icons to indicate if it is white's or black's turn */
2636 WhiteIcon = load_pixbuf("svg/icon_white.svg",0);
2637 BlackIcon = load_pixbuf("svg/icon_black.svg",0);
2638 WindowIcon = WhiteIcon;
2639 gtk_window_set_icon(GTK_WINDOW(GUI_Window),WindowIcon);
2642 /* realize window */
2643 gtk_widget_show (GUI_Window);
2645 /* recalc boardsize */
2650 if (appData.animate || appData.animateDragging)
2655 if (errorExitStatus == -1) {
2656 if (appData.icsActive) {
2657 /* We now wait until we see "login:" from the ICS before
2658 sending the logon script (problems with timestamp otherwise) */
2659 /*ICSInitScript();*/
2660 if (appData.icsInputBox) ICSInputBoxPopUp();
2663 signal(SIGINT, IntSigHandler);
2664 signal(SIGTERM, IntSigHandler);
2665 if (*appData.cmailGameName != NULLCHAR) {
2666 signal(SIGUSR1, CmailSigHandler);
2669 gameInfo.boardWidth = 0; // [HGM] pieces: kludge to ensure InitPosition() calls InitDrawingSizes()
2673 * Create a cursor for the board widget.
2674 * (This needs to be called after the window has been created to have access to board-window)
2677 BoardCursor = gdk_cursor_new(GDK_HAND2);
2678 gdk_window_set_cursor(GUI_Board->window, BoardCursor);
2679 gdk_cursor_destroy(BoardCursor);
2684 if (appData.debugMode) fclose(debugFP); // [DM] debug
2691 if (appData.icsActive && oldICSInteractionTitle != NULL) {
2692 DisplayIcsInteractionTitle(oldICSInteractionTitle);
2694 unlink(gameCopyFilename);
2695 unlink(gamePasteFilename);
2698 RETSIGTYPE TermSizeSigHandler(int sig)
2711 CmailSigHandler(sig)
2717 signal(SIGUSR1, SIG_IGN); /* suspend handler */
2719 /* Activate call-back function CmailSigHandlerCallBack() */
2720 OutputToProcess(cmailPR, (char *)(&dummy), sizeof(int), &error);
2722 signal(SIGUSR1, CmailSigHandler); /* re-activate handler */
2726 CmailSigHandlerCallBack(isr, closure, message, count, error)
2734 ReloadCmailMsgEvent(TRUE); /* Reload cmail msg */
2736 /**** end signal code ****/
2746 f = fopen(appData.icsLogon, "r");
2752 strcat(buf, appData.icsLogon);
2753 f = fopen(buf, "r");
2757 ProcessICSInitScript(f);
2764 EditCommentPopDown();
2770 SetMenuEnables(enab)
2775 if (!builder) return;
2776 while (enab->name != NULL) {
2777 o = gtk_builder_get_object(builder, enab->name);
2778 if(GTK_IS_WIDGET(o))
2779 gtk_widget_set_sensitive(GTK_WIDGET (o),enab->value);
2782 if(GTK_IS_ACTION(o))
2783 gtk_action_set_sensitive(GTK_ACTION (o),enab->value);
2785 DisplayError(enab->name, 0);
2793 SetMenuEnables(icsEnables);
2796 if (appData.zippyPlay && !appData.noChessProgram) /* [DM] icsEngineAnalyze */
2797 {}; // XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Analysis Mode"), True);
2804 SetMenuEnables(ncpEnables);
2810 SetMenuEnables(gnuEnables);
2816 SetMenuEnables(cmailEnables);
2822 SetMenuEnables(trainingOnEnables);
2823 if (appData.showButtonBar) {
2824 // XtSetSensitive(buttonBarWidget, False);
2830 SetTrainingModeOff()
2832 SetMenuEnables(trainingOffEnables);
2833 if (appData.showButtonBar) {
2834 // XtSetSensitive(buttonBarWidget, True);
2839 SetUserThinkingEnables()
2841 if (appData.noChessProgram) return;
2842 SetMenuEnables(userThinkingEnables);
2846 SetMachineThinkingEnables()
2848 if (appData.noChessProgram) return;
2849 SetMenuEnables(machineThinkingEnables);
2851 case MachinePlaysBlack:
2852 case MachinePlaysWhite:
2853 case TwoMachinesPlay:
2854 // XtSetSensitive(XtNameToWidget(menuBarWidget,
2855 // ModeToWidgetName(gameMode)), True);
2862 #define Abs(n) ((n)<0 ? -(n) : (n))
2865 * Find a font that matches "pattern" that is as close as
2866 * possible to the targetPxlSize. Prefer fonts that are k
2867 * pixels smaller to fonts that are k pixels larger. The
2868 * pattern must be in the X Consortium standard format,
2869 * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".
2870 * The return value should be freed with XtFree when no
2873 char *FindFont(pattern, targetPxlSize)
2877 char **fonts, *p, *best, *scalable, *scalableTail;
2878 int i, j, nfonts, minerr, err, pxlSize;
2881 char **missing_list;
2883 char *def_string, *base_fnt_lst, strInt[3];
2885 XFontStruct **fnt_list;
2887 base_fnt_lst = calloc(1, strlen(pattern) + 3);
2888 sprintf(strInt, "%d", targetPxlSize);
2889 p = strstr(pattern, "--");
2890 strncpy(base_fnt_lst, pattern, p - pattern + 2);
2891 strcat(base_fnt_lst, strInt);
2892 strcat(base_fnt_lst, strchr(p + 2, '-'));
2894 if ((fntSet = XCreateFontSet(xDisplay,
2898 &def_string)) == NULL) {
2900 fprintf(stderr, _("Unable to create font set.\n"));
2904 nfonts = XFontsOfFontSet(fntSet, &fnt_list, &fonts);
2906 fonts = XListFonts(xDisplay, pattern, 999999, &nfonts);
2908 fprintf(stderr, _("%s: no fonts match pattern %s\n"),
2909 programName, pattern);
2917 for (i=0; i<nfonts; i++) {
2920 if (*p != '-') continue;
2922 if (*p == NULLCHAR) break;
2923 if (*p++ == '-') j++;
2925 if (j < 7) continue;
2928 scalable = fonts[i];
2931 err = pxlSize - targetPxlSize;
2932 if (Abs(err) < Abs(minerr) ||
2933 (minerr > 0 && err < 0 && -err == minerr)) {
2939 if (scalable && Abs(minerr) > appData.fontSizeTolerance) {
2940 /* If the error is too big and there is a scalable font,
2941 use the scalable font. */
2942 int headlen = scalableTail - scalable;
2943 p = (char *) XtMalloc(strlen(scalable) + 10);
2944 while (isdigit(*scalableTail)) scalableTail++;
2945 sprintf(p, "%.*s%d%s", headlen, scalable, targetPxlSize, scalableTail);
2947 p = (char *) XtMalloc(strlen(best) + 1);
2950 if (appData.debugMode) {
2951 fprintf(debugFP, _("resolved %s at pixel size %d\n to %s\n"),
2952 pattern, targetPxlSize, p);
2955 if (missing_count > 0)
2956 XFreeStringList(missing_list);
2957 XFreeFontSet(xDisplay, fntSet);
2959 XFreeFontNames(fonts);
2966 /* 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*/
2968 XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
2969 | GCBackground | GCFunction | GCPlaneMask;
2970 XGCValues gc_values;
2973 gc_values.plane_mask = AllPlanes;
2974 gc_values.line_width = lineGap;
2975 gc_values.line_style = LineSolid;
2976 gc_values.function = GXcopy;
2978 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
2979 gc_values.background = XWhitePixel(xDisplay, xScreen);
2980 coordGC = XtGetGC(shellWidget, value_mask, &gc_values);
2981 XSetFont(xDisplay, coordGC, coordFontID);
2983 if (appData.monoMode) {
2984 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
2985 gc_values.background = XBlackPixel(xDisplay, xScreen);
2986 lightSquareGC = wbPieceGC
2987 = XtGetGC(shellWidget, value_mask, &gc_values);
2989 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
2990 gc_values.background = XWhitePixel(xDisplay, xScreen);
2991 darkSquareGC = bwPieceGC
2992 = XtGetGC(shellWidget, value_mask, &gc_values);
2994 if (DefaultDepth(xDisplay, xScreen) == 1) {
2995 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
2996 gc_values.function = GXcopyInverted;
2997 copyInvertedGC = XtGetGC(shellWidget, value_mask, &gc_values);
2998 gc_values.function = GXcopy;
2999 if (XBlackPixel(xDisplay, xScreen) == 1) {
3000 bwPieceGC = darkSquareGC;
3001 wbPieceGC = copyInvertedGC;
3003 bwPieceGC = copyInvertedGC;
3004 wbPieceGC = lightSquareGC;
3008 gc_values.foreground = lightSquareColor;
3009 gc_values.background = darkSquareColor;
3010 lightSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3012 gc_values.foreground = darkSquareColor;
3013 gc_values.background = lightSquareColor;
3014 darkSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3016 gc_values.foreground = jailSquareColor;
3017 gc_values.background = jailSquareColor;
3018 jailSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3020 gc_values.foreground = whitePieceColor;
3021 gc_values.background = darkSquareColor;
3022 wdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3024 gc_values.foreground = whitePieceColor;
3025 gc_values.background = lightSquareColor;
3026 wlPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3028 gc_values.foreground = whitePieceColor;
3029 gc_values.background = jailSquareColor;
3030 wjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3032 gc_values.foreground = blackPieceColor;
3033 gc_values.background = darkSquareColor;
3034 bdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3036 gc_values.foreground = blackPieceColor;
3037 gc_values.background = lightSquareColor;
3038 blPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3040 gc_values.foreground = blackPieceColor;
3041 gc_values.background = jailSquareColor;
3042 bjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3051 for(i=0;i<MAXPIECES;i++)
3055 g_free(SVGpieces[i]);
3062 SVGLightSquare = load_pixbuf("svg/LightSquare.svg",squareSize);
3063 SVGDarkSquare = load_pixbuf("svg/DarkSquare.svg",squareSize);
3064 SVGNeutralSquare = load_pixbuf("svg/NeutralSquare.svg",squareSize);
3067 /* get some defaults going */
3068 for(i=WhitePawn; i<DemotePiece+1; i++)
3069 SVGpieces[i] = load_pixbuf("svg/NeutralSquare.svg",squareSize);
3071 SVGpieces[WhitePawn] = load_pixbuf("svg/WhitePawn.svg",squareSize);
3072 SVGpieces[WhiteKnight] = load_pixbuf("svg/WhiteKnight.svg",squareSize);
3073 SVGpieces[WhiteBishop] = load_pixbuf("svg/WhiteBishop.svg",squareSize);
3074 SVGpieces[WhiteRook] = load_pixbuf("svg/WhiteRook.svg",squareSize);
3075 SVGpieces[WhiteQueen] = load_pixbuf("svg/WhiteQueen.svg",squareSize);
3076 SVGpieces[WhiteKing] = load_pixbuf("svg/WhiteKing.svg",squareSize);
3078 SVGpieces[BlackPawn] = load_pixbuf("svg/BlackPawn.svg",squareSize);
3079 SVGpieces[BlackKnight] = load_pixbuf("svg/BlackKnight.svg",squareSize);
3080 SVGpieces[BlackBishop] = load_pixbuf("svg/BlackBishop.svg",squareSize);
3081 SVGpieces[BlackRook] = load_pixbuf("svg/BlackRook.svg",squareSize);
3082 SVGpieces[BlackQueen] = load_pixbuf("svg/BlackQueen.svg",squareSize);
3083 SVGpieces[BlackKing] = load_pixbuf("svg/BlackKing.svg",squareSize);
3089 static void MenuBarSelect(w, addr, index)
3094 XtActionProc proc = (XtActionProc) addr;
3096 (proc)(NULL, NULL, NULL, NULL);
3099 void CreateMenuBarPopup(parent, name, mb)
3109 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3112 XtSetArg(args[j], XtNleftMargin, 20); j++;
3113 XtSetArg(args[j], XtNrightMargin, 20); j++;
3115 while (mi->string != NULL) {
3116 if (strcmp(mi->string, "----") == 0) {
3117 entry = XtCreateManagedWidget(mi->string, smeLineObjectClass,
3120 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string)));
3121 entry = XtCreateManagedWidget(mi->string, smeBSBObjectClass,
3123 XtAddCallback(entry, XtNcallback,
3124 (XtCallbackProc) MenuBarSelect,
3125 (caddr_t) mi->proc);
3131 Widget CreateMenuBar(mb)
3135 Widget anchor, menuBar;
3137 char menuName[MSG_SIZ];
3140 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
3141 XtSetArg(args[j], XtNvSpace, 0); j++;
3142 XtSetArg(args[j], XtNborderWidth, 0); j++;
3143 menuBar = XtCreateWidget("menuBar", boxWidgetClass,
3144 formWidget, args, j);
3146 while (mb->name != NULL) {
3147 strcpy(menuName, "menu");
3148 strcat(menuName, mb->name);
3150 XtSetArg(args[j], XtNmenuName, XtNewString(menuName)); j++;
3153 shortName[0] = _(mb->name)[0];
3154 shortName[1] = NULLCHAR;
3155 XtSetArg(args[j], XtNlabel, XtNewString(shortName)); j++;
3158 XtSetArg(args[j], XtNlabel, XtNewString(_(mb->name))); j++;
3161 XtSetArg(args[j], XtNborderWidth, 0); j++;
3162 anchor = XtCreateManagedWidget(mb->name, menuButtonWidgetClass,
3164 CreateMenuBarPopup(menuBar, menuName, mb);
3172 CreatePieceMenu(name, color)
3179 ChessSquare selection;
3181 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3182 boardWidget, args, 0);
3184 for (i = 0; i < PIECE_MENU_SIZE; i++) {
3185 String item = pieceMenuStrings[color][i];
3187 if (strcmp(item, "----") == 0) {
3188 entry = XtCreateManagedWidget(item, smeLineObjectClass,
3191 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
3192 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3194 selection = pieceMenuTranslation[color][i];
3195 XtAddCallback(entry, XtNcallback,
3196 (XtCallbackProc) PieceMenuSelect,
3197 (caddr_t) selection);
3198 if (selection == WhitePawn || selection == BlackPawn) {
3199 XtSetArg(args[0], XtNpopupOnEntry, entry);
3200 XtSetValues(menu, args, 1);
3213 ChessSquare selection;
3215 // whitePieceMenu = CreatePieceMenu("menuW", 0);
3216 // blackPieceMenu = CreatePieceMenu("menuB", 1);
3218 // XtRegisterGrabAction(PieceMenuPopup, True,
3219 // (unsigned)(ButtonPressMask|ButtonReleaseMask),
3220 // GrabModeAsync, GrabModeAsync);
3222 // XtSetArg(args[0], XtNlabel, _("Drop"));
3223 // dropMenu = XtCreatePopupShell("menuD", simpleMenuWidgetClass,
3224 // boardWidget, args, 1);
3225 // for (i = 0; i < DROP_MENU_SIZE; i++) {
3226 // String item = dropMenuStrings[i];
3228 // if (strcmp(item, "----") == 0) {
3229 // entry = XtCreateManagedWidget(item, smeLineObjectClass,
3230 // dropMenu, NULL, 0);
3232 // XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
3233 // entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3234 // dropMenu, args, 1);
3235 // selection = dropMenuTranslation[i];
3236 // XtAddCallback(entry, XtNcallback,
3237 // (XtCallbackProc) DropMenuSelect,
3238 // (caddr_t) selection);
3243 void SetupDropMenu()
3251 for (i=0; i<sizeof(dmEnables)/sizeof(DropMenuEnables); i++) {
3252 entry = XtNameToWidget(dropMenu, dmEnables[i].widget);
3253 p = strchr(gameMode == IcsPlayingWhite ? white_holding : black_holding,
3254 dmEnables[i].piece);
3255 XtSetSensitive(entry, p != NULL || !appData.testLegality
3256 /*!!temp:*/ || (gameInfo.variant == VariantCrazyhouse
3257 && !appData.icsActive));
3259 while (p && *p++ == dmEnables[i].piece) count++;
3260 snprintf(label, sizeof(label), "%s %d", dmEnables[i].widget, count);
3262 XtSetArg(args[j], XtNlabel, label); j++;
3263 XtSetValues(entry, args, j);
3267 void PieceMenuPopup(w, event, params, num_params)
3271 Cardinal *num_params;
3274 if (event->type != ButtonPress) return;
3275 if (errorUp) ErrorPopDown();
3279 whichMenu = params[0];
3281 case IcsPlayingWhite:
3282 case IcsPlayingBlack:
3284 case MachinePlaysWhite:
3285 case MachinePlaysBlack:
3286 if (appData.testLegality &&
3287 gameInfo.variant != VariantBughouse &&
3288 gameInfo.variant != VariantCrazyhouse) return;
3290 whichMenu = "menuD";
3296 if (((pmFromX = EventToSquare(event->xbutton.x, BOARD_WIDTH)) < 0) ||
3297 ((pmFromY = EventToSquare(event->xbutton.y, BOARD_HEIGHT)) < 0)) {
3298 pmFromX = pmFromY = -1;
3302 pmFromX = BOARD_WIDTH - 1 - pmFromX;
3304 pmFromY = BOARD_HEIGHT - 1 - pmFromY;
3306 XtPopupSpringLoaded(XtNameToWidget(boardWidget, whichMenu));
3309 static void PieceMenuSelect(w, piece, junk)
3314 if (pmFromX < 0 || pmFromY < 0) return;
3315 EditPositionMenuEvent(piece, pmFromX, pmFromY);
3318 static void DropMenuSelect(w, piece, junk)
3323 if (pmFromX < 0 || pmFromY < 0) return;
3324 DropMenuEvent(piece, pmFromX, pmFromY);
3328 * If the user selects on a border boundary, return -1; if off the board,
3329 * return -2. Otherwise map the event coordinate to the square.
3331 int EventToSquare(x, limit)
3339 if ((x % (squareSize + lineGap)) >= squareSize)
3341 x /= (squareSize + lineGap);
3347 static void do_flash_delay(msec)
3353 static void drawHighlight(file, rank, line_type)
3354 int file, rank, line_type;
3359 if (lineGap == 0 || appData.blindfold) return;
3363 x = lineGap/2 + ((BOARD_WIDTH-1)-file) *
3364 (squareSize + lineGap);
3365 y = lineGap/2 + rank * (squareSize + lineGap);
3369 x = lineGap/2 + file * (squareSize + lineGap);
3370 y = lineGap/2 + ((BOARD_HEIGHT-1)-rank) *
3371 (squareSize + lineGap);
3375 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
3377 /* draw the highlight */
3378 cairo_move_to (cr, x, y);
3379 cairo_rel_line_to (cr, 0,squareSize+lineGap);
3380 cairo_rel_line_to (cr, squareSize+lineGap,0);
3381 cairo_rel_line_to (cr, 0,-squareSize-lineGap);
3382 cairo_close_path (cr);
3384 cairo_set_line_width (cr, lineGap);
3387 /* TODO: use appdata colors */
3388 case LINE_TYPE_HIGHLIGHT:
3389 cairo_set_source_rgba (cr, 1, 1, 0, 1.0);
3392 cairo_set_source_rgba (cr, 1, 0, 0, 1.0);
3394 case LINE_TYPE_NORMAL:
3396 cairo_set_source_rgba (cr, 0, 1, 0, 1.0);
3407 int hi1X = -1, hi1Y = -1, hi2X = -1, hi2Y = -1;
3408 int pm1X = -1, pm1Y = -1, pm2X = -1, pm2Y = -1;
3411 SetHighlights(fromX, fromY, toX, toY)
3412 int fromX, fromY, toX, toY;
3414 if (hi1X != fromX || hi1Y != fromY)
3416 if (hi1X >= 0 && hi1Y >= 0)
3418 drawHighlight(hi1X, hi1Y, LINE_TYPE_NORMAL);
3420 if (fromX >= 0 && fromY >= 0)
3422 drawHighlight(fromX, fromY, LINE_TYPE_HIGHLIGHT);
3425 if (hi2X != toX || hi2Y != toY)
3427 if (hi2X >= 0 && hi2Y >= 0)
3429 drawHighlight(hi2X, hi2Y, LINE_TYPE_NORMAL);
3431 if (toX >= 0 && toY >= 0)
3433 drawHighlight(toX, toY, LINE_TYPE_HIGHLIGHT);
3447 SetHighlights(-1, -1, -1, -1);
3452 SetPremoveHighlights(fromX, fromY, toX, toY)
3453 int fromX, fromY, toX, toY;
3455 if (pm1X != fromX || pm1Y != fromY)
3457 if (pm1X >= 0 && pm1Y >= 0)
3459 drawHighlight(pm1X, pm1Y, LINE_TYPE_NORMAL);
3461 if (fromX >= 0 && fromY >= 0)
3463 drawHighlight(fromX, fromY, LINE_TYPE_PRE);
3466 if (pm2X != toX || pm2Y != toY)
3468 if (pm2X >= 0 && pm2Y >= 0)
3470 drawHighlight(pm2X, pm2Y, LINE_TYPE_NORMAL);
3472 if (toX >= 0 && toY >= 0)
3474 drawHighlight(toX, toY, LINE_TYPE_PRE);
3487 ClearPremoveHighlights()
3489 SetPremoveHighlights(-1, -1, -1, -1);
3492 static void BlankSquare(x, y, color, piece, dest)
3505 pb = SVGLightSquare;
3507 case 2: /* neutral */
3509 pb = SVGNeutralSquare;
3512 gdk_draw_pixbuf(GDK_WINDOW(GUI_Board->window),NULL,pb,0,0,x,y,-1,-1, GDK_RGB_DITHER_NORMAL, 0, 0);
3516 static void DrawPiece(piece, square_color, x, y, dest)
3518 int square_color, x, y;
3521 /* redraw background, since piece might be transparent in some areas */
3522 BlankSquare(x,y,square_color,piece,dest);
3525 gdk_draw_pixbuf(GDK_WINDOW(GUI_Board->window),NULL,
3526 GDK_PIXBUF(SVGpieces[piece]),0,0,x,y,-1,-1,
3527 GDK_RGB_DITHER_NORMAL, 0, 0);
3531 /* [HR] determine square color depending on chess variant. */
3532 static int SquareColor(row, column)
3537 if (gameInfo.variant == VariantXiangqi) {
3538 if (column >= 3 && column <= 5 && row >= 0 && row <= 2) {
3540 } else if (column >= 3 && column <= 5 && row >= 7 && row <= 9) {
3542 } else if (row <= 4) {
3548 square_color = ((column + row) % 2) == 1;
3551 /* [hgm] holdings: next line makes all holdings squares light */
3552 if(column < BOARD_LEFT || column >= BOARD_RGHT) square_color = 1;
3554 return square_color;
3557 void DrawSquare(row, column, piece, do_flash)
3558 int row, column, do_flash;
3561 int square_color, x, y;
3566 /* Calculate delay in milliseconds (2-delays per complete flash) */
3567 flash_delay = 500 / appData.flashRate;
3569 /* calculate x and y coordinates from row and column */
3572 x = lineGap + ((BOARD_WIDTH-1)-column) *
3573 (squareSize + lineGap);
3574 y = lineGap + row * (squareSize + lineGap);
3578 x = lineGap + column * (squareSize + lineGap);
3579 y = lineGap + ((BOARD_HEIGHT-1)-row) *
3580 (squareSize + lineGap);
3583 square_color = SquareColor(row, column);
3585 // [HGM] holdings: blank out area between board and holdings
3586 if ( column == BOARD_LEFT-1 || column == BOARD_RGHT
3587 || (column == BOARD_LEFT-2 && row < BOARD_HEIGHT-gameInfo.holdingsSize)
3588 || (column == BOARD_RGHT+1 && row >= gameInfo.holdingsSize) )
3590 BlankSquare(x, y, 2, EmptySquare, xBoardWindow);
3592 // [HGM] print piece counts next to holdings
3593 string[1] = NULLCHAR;
3596 cairo_text_extents_t extents;
3601 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
3603 string[0] = '0' + piece;
3605 /* TODO this has to go into the font-selection */
3606 cairo_select_font_face (cr, "Sans",
3607 CAIRO_FONT_SLANT_NORMAL,
3608 CAIRO_FONT_WEIGHT_NORMAL);
3610 cairo_set_font_size (cr, 12.0);
3611 cairo_text_extents (cr, string, &extents);
3613 if (column == (flipView ? BOARD_LEFT-1 : BOARD_RGHT) )
3615 xpos= x + squareSize - extents.width - 2;
3616 ypos= y + extents.y_bearing + 1;
3618 if (column == (flipView ? BOARD_RGHT : BOARD_LEFT-1) && piece > 1)
3621 ypos = y + extents.y_bearing + 1;
3624 /* TODO mono mode? */
3625 cairo_move_to (cr, xpos, ypos);
3626 cairo_text_path (cr, string);
3627 cairo_set_source_rgb (cr, 1.0, 1.0, 1);
3628 cairo_fill_preserve (cr);
3629 cairo_set_source_rgb (cr, 0, 0, 0);
3630 cairo_set_line_width (cr, 0.1);
3639 /* square on the board */
3640 if (piece == EmptySquare || appData.blindfold)
3642 BlankSquare(x, y, square_color, piece, xBoardWindow);
3646 if (do_flash && appData.flashCount > 0)
3648 for (i=0; i<appData.flashCount; ++i)
3651 DrawPiece(piece, square_color, x, y, xBoardWindow);
3652 do_flash_delay(flash_delay);
3654 BlankSquare(x, y, square_color, piece, xBoardWindow);
3655 do_flash_delay(flash_delay);
3658 DrawPiece(piece, square_color, x, y, xBoardWindow);
3662 /* show coordinates if necessary */
3663 if(appData.showCoords)
3665 cairo_text_extents_t extents;
3669 /* TODO this has to go into the font-selection */
3670 cairo_select_font_face (cr, "Sans",
3671 CAIRO_FONT_SLANT_NORMAL,
3672 CAIRO_FONT_WEIGHT_NORMAL);
3673 cairo_set_font_size (cr, 12.0);
3675 string[1] = NULLCHAR;
3678 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
3680 if (row == (flipView ? BOARD_HEIGHT-1 : 0) &&
3681 column >= BOARD_LEFT && column < BOARD_RGHT)
3683 string[0] = 'a' + column - BOARD_LEFT;
3684 cairo_text_extents (cr, string, &extents);
3686 xpos = x + squareSize - extents.width - 2;
3687 ypos = y + squareSize - extents.height - extents.y_bearing - 1;
3689 if (appData.monoMode)
3696 cairo_move_to (cr, xpos, ypos);
3697 cairo_text_path (cr, string);
3698 cairo_set_source_rgb (cr, 0.0, 0.0, 0);
3699 cairo_fill_preserve (cr);
3700 cairo_set_source_rgb (cr, 0, 1.0, 0);
3701 cairo_set_line_width (cr, 0.1);
3704 if ( column == (flipView ? BOARD_RGHT-1 : BOARD_LEFT))
3707 string[0] = ONE + row;
3708 cairo_text_extents (cr, string, &extents);
3711 ypos = y + extents.height + 1;
3713 if (appData.monoMode)
3720 cairo_move_to (cr, xpos, ypos);
3721 cairo_text_path (cr, string);
3722 cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
3723 cairo_fill_preserve (cr);
3724 cairo_set_source_rgb (cr, 0, 0, 1.0);
3725 cairo_set_line_width (cr, 0.1);
3737 /* Returns 1 if there are "too many" differences between b1 and b2
3738 (i.e. more than 1 move was made) */
3739 static int too_many_diffs(b1, b2)
3745 for (i=0; i<BOARD_HEIGHT; ++i) {
3746 for (j=0; j<BOARD_WIDTH; ++j) {
3747 if (b1[i][j] != b2[i][j]) {
3748 if (++c > 4) /* Castling causes 4 diffs */
3757 /* Matrix describing castling maneuvers */
3758 /* Row, ColRookFrom, ColKingFrom, ColRookTo, ColKingTo */
3759 static int castling_matrix[4][5] = {
3760 { 0, 0, 4, 3, 2 }, /* 0-0-0, white */
3761 { 0, 7, 4, 5, 6 }, /* 0-0, white */
3762 { 7, 0, 4, 3, 2 }, /* 0-0-0, black */
3763 { 7, 7, 4, 5, 6 } /* 0-0, black */
3766 /* Checks whether castling occurred. If it did, *rrow and *rcol
3767 are set to the destination (row,col) of the rook that moved.
3769 Returns 1 if castling occurred, 0 if not.
3771 Note: Only handles a max of 1 castling move, so be sure
3772 to call too_many_diffs() first.
3774 static int check_castle_draw(newb, oldb, rrow, rcol)
3781 /* For each type of castling... */
3782 for (i=0; i<4; ++i) {
3783 r = castling_matrix[i];
3785 /* Check the 4 squares involved in the castling move */
3787 for (j=1; j<=4; ++j) {
3788 if (newb[r[0]][r[j]] == oldb[r[0]][r[j]]) {
3795 /* All 4 changed, so it must be a castling move */
3804 static int damage[BOARD_SIZE][BOARD_SIZE];
3807 * event handler for redrawing the board
3809 void DrawPosition( repaint, board)
3810 /*Boolean*/int repaint;
3814 static int lastFlipView = 0;
3815 static int lastBoardValid = 0;
3816 static Board lastBoard;
3819 if (board == NULL) {
3820 if (!lastBoardValid) return;
3823 if (!lastBoardValid || lastFlipView != flipView) {
3824 // XtSetArg(args[0], XtNleftBitmap, (flipView ? xMarkPixmap : None));
3825 // XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flip View"),
3830 * It would be simpler to clear the window with XClearWindow()
3831 * but this causes a very distracting flicker.
3834 if (!repaint && lastBoardValid && lastFlipView == flipView)
3836 /* If too much changes (begin observing new game, etc.), don't
3838 do_flash = too_many_diffs(board, lastBoard) ? 0 : 1;
3840 /* Special check for castling so we don't flash both the king
3841 and the rook (just flash the king). */
3844 if (check_castle_draw(board, lastBoard, &rrow, &rcol))
3846 /* Draw rook with NO flashing. King will be drawn flashing later */
3847 DrawSquare(rrow, rcol, board[rrow][rcol], 0);
3848 lastBoard[rrow][rcol] = board[rrow][rcol];
3852 /* First pass -- Draw (newly) empty squares and repair damage.
3853 This prevents you from having a piece show up twice while it
3854 is flashing on its new square */
3855 for (i = 0; i < BOARD_HEIGHT; i++)
3856 for (j = 0; j < BOARD_WIDTH; j++)
3857 if ((board[i][j] != lastBoard[i][j] && board[i][j] == EmptySquare)
3860 DrawSquare(i, j, board[i][j], 0);
3861 damage[i][j] = False;
3864 /* Second pass -- Draw piece(s) in new position and flash them */
3865 for (i = 0; i < BOARD_HEIGHT; i++)
3866 for (j = 0; j < BOARD_WIDTH; j++)
3867 if (board[i][j] != lastBoard[i][j])
3869 DrawSquare(i, j, board[i][j], do_flash);
3881 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
3883 cairo_set_line_width (cr, lineGap);
3885 /* TODO: use appdata colors */
3886 cairo_set_source_rgba (cr, 0, 1, 0, 1.0);
3890 for (i = 0; i < BOARD_HEIGHT + 1; i++)
3893 x2 = lineGap + BOARD_WIDTH * (squareSize + lineGap);
3894 y1 = y2 = lineGap / 2 + (i * (squareSize + lineGap));
3896 cairo_move_to (cr, x1, y1);
3897 cairo_rel_line_to (cr, x2,0);
3901 for (j = 0; j < BOARD_WIDTH + 1; j++)
3904 y2 = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
3905 x1 = x2 = lineGap / 2 + (j * (squareSize + lineGap));
3907 cairo_move_to (cr, x1, y1);
3908 cairo_rel_line_to (cr, 0, y2);
3917 for (i = 0; i < BOARD_HEIGHT; i++)
3918 for (j = 0; j < BOARD_WIDTH; j++)
3920 DrawSquare(i, j, board[i][j], 0);
3921 damage[i][j] = False;
3925 CopyBoard(lastBoard, board);
3927 lastFlipView = flipView;
3929 /* Draw highlights */
3930 if (pm1X >= 0 && pm1Y >= 0)
3932 drawHighlight(pm1X, pm1Y, LINE_TYPE_PRE);
3934 if (pm2X >= 0 && pm2Y >= 0)
3936 drawHighlight(pm2X, pm2Y, LINE_TYPE_PRE);
3938 if (hi1X >= 0 && hi1Y >= 0)
3940 drawHighlight(hi1X, hi1Y, LINE_TYPE_HIGHLIGHT);
3942 if (hi2X >= 0 && hi2Y >= 0)
3944 drawHighlight(hi2X, hi2Y, LINE_TYPE_HIGHLIGHT);
3947 /* If piece being dragged around board, must redraw that too */
3954 * event handler for parsing user moves
3956 // [HGM] This routine will need quite some reworking. Although the backend still supports the old
3957 // way of doing things, by calling UserMoveEvent() to test the legality of the move and then perform
3958 // it at the end, and doing all kind of preliminary tests here (e.g. to weed out self-captures), it
3959 // should be made to use the new way, of calling UserMoveTest early to determine the legality of the
3960 // move, (which will weed out the illegal selfcaptures and moves into the holdings, and flag promotions),
3961 // and at the end FinishMove() to perform the move after optional promotion popups.
3962 // For now I patched it to allow self-capture with King, and suppress clicks between board and holdings.
3963 void HandleUserMove(w, event, prms, nprms)
3970 Boolean saveAnimate;
3971 static int second = 0, promotionChoice = 0;
3974 if (w != boardWidget || errorExitStatus != -1) return;
3976 x = EventToSquare(event->xbutton.x, BOARD_WIDTH);
3977 y = EventToSquare(event->xbutton.y, BOARD_HEIGHT);
3978 if (!flipView && y >= 0) {
3979 y = BOARD_HEIGHT - 1 - y;
3981 if (flipView && x >= 0) {
3982 x = BOARD_WIDTH - 1 - x;
3985 if(promotionChoice) { // we are waiting for a click to indicate promotion piece
3986 if(event->type == ButtonRelease) return; // ignore upclick of click-click destination
3987 promotionChoice = FALSE; // only one chance: if click not OK it is interpreted as cancel
3988 if(appData.debugMode) fprintf(debugFP, "promotion click, x=%d, y=%d\n", x, y);
3989 if(gameInfo.holdingsWidth &&
3990 (WhiteOnMove(currentMove)
3991 ? x == BOARD_WIDTH-1 && y < gameInfo.holdingsSize && y > 0
3992 : x == 0 && y >= BOARD_HEIGHT - gameInfo.holdingsSize && y < BOARD_HEIGHT-1) ) {
3993 // click in right holdings, for determining promotion piece
3994 ChessSquare p = boards[currentMove][y][x];
3995 if(appData.debugMode) fprintf(debugFP, "square contains %d\n", (int)p);
3996 if(p != EmptySquare) {
3997 FinishMove(NormalMove, fromX, fromY, toX, toY, ToLower(PieceToChar(p)));
4002 DrawPosition(FALSE, boards[currentMove]);
4005 if (event->type == ButtonPress) ErrorPopDown();
4008 if (event->type == ButtonPress) {
4009 // XtPopdown(promotionShell);
4010 // XtDestroyWidget(promotionShell);
4011 promotionUp = False;
4019 /* [HGM] holdings: next 5 lines: ignore all clicks between board and holdings */
4020 if(event->type == ButtonPress
4021 && ( x == BOARD_LEFT-1 ||
4023 (x == BOARD_LEFT-2 && y < BOARD_HEIGHT-gameInfo.holdingsSize ) ||
4024 (x == BOARD_RGHT+1 && y >= gameInfo.holdingsSize)) )
4028 if (event->type == ButtonPress) {
4029 /* First square, prepare to drag */
4030 if (OKToStartUserMove(x, y)) {
4034 DragPieceBegin(event->xbutton.x, event->xbutton.y);
4035 if (appData.highlightDragging) {
4036 SetHighlights(x, y, -1, -1);
4044 if (event->type == ButtonRelease && x == fromX && y == fromY) {
4045 /* Click on single square in stead of drag-drop */
4046 DragPieceEnd(event->xbutton.x, event->xbutton.y);
4047 if (appData.animateDragging) {
4048 /* Undo animation damage if any */
4049 DrawPosition(FALSE, NULL);
4052 /* Second up/down in same square; just abort move */
4057 ClearPremoveHighlights();
4059 /* First upclick in same square; start click-click mode */
4060 SetHighlights(x, y, -1, -1);
4065 moveType = UserMoveTest(fromX, fromY, x, y, NULLCHAR, event->type == ButtonRelease);
4067 if (moveType == Comment) { // kludge for indicating capture-own on Press
4068 /* Clicked again on same color piece -- changed his mind */
4069 /* note that re-clicking same square always hits same color piece */
4070 second = (x == fromX && y == fromY);
4071 if (appData.highlightDragging) {
4072 SetHighlights(x, y, -1, -1);
4076 if (OKToStartUserMove(x, y)) {
4079 DragPieceBegin(event->xbutton.x, event->xbutton.y);
4084 if(moveType == AmbiguousMove) { // kludge to indicate edit-position move
4087 DragPieceEnd(event->xbutton.x, event->xbutton.y);
4088 DrawPosition(FALSE, boards[currentMove]);
4092 /* Complete move; (x,y) is now different from (fromX, fromY) on both Press and Release */
4095 saveAnimate = appData.animate;
4096 if (event->type == ButtonPress) {
4097 /* Finish clickclick move */
4098 if (appData.animate || appData.highlightLastMove) {
4099 SetHighlights(fromX, fromY, toX, toY);
4104 /* Finish drag move */
4105 if (appData.highlightLastMove) {
4106 SetHighlights(fromX, fromY, toX, toY);
4110 DragPieceEnd(event->xbutton.x, event->xbutton.y);
4111 /* Don't animate move and drag both */
4112 appData.animate = FALSE;
4114 if (moveType == WhitePromotionKnight || moveType == BlackPromotionKnight ||
4115 (moveType == WhitePromotionQueen || moveType == BlackPromotionQueen) &&
4116 appData.alwaysPromoteToQueen) { // promotion, but no choice
4117 FinishMove(moveType, fromX, fromY, toX, toY, 'q');
4119 if (moveType == WhitePromotionQueen || moveType == BlackPromotionQueen ) {
4120 SetHighlights(fromX, fromY, toX, toY);
4121 if(gameInfo.variant == VariantSuper || gameInfo.variant == VariantGreat) {
4122 // [HGM] super: promotion to captured piece selected from holdings
4123 ChessSquare p = boards[currentMove][fromY][fromX], q = boards[currentMove][toY][toX];
4124 promotionChoice = TRUE;
4125 // kludge follows to temporarily execute move on display, without promoting yet
4126 boards[currentMove][fromY][fromX] = EmptySquare; // move Pawn to 8th rank
4127 boards[currentMove][toY][toX] = p;
4128 DrawPosition(FALSE, boards[currentMove]);
4129 boards[currentMove][fromY][fromX] = p; // take back, but display stays
4130 boards[currentMove][toY][toX] = q;
4131 DisplayMessage("Click in holdings to choose piece", "");
4135 goto skipClearingFrom; // the skipped stuff is done asynchronously by PromotionCallback
4137 if(moveType != ImpossibleMove) { // valid move, but no promotion
4138 FinishMove(moveType, fromX, fromY, toX, toY, NULLCHAR);
4139 } else { // invalid move; could have set premove
4142 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
4143 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
4146 appData.animate = saveAnimate;
4147 if (appData.animate || appData.animateDragging) {
4148 /* Undo animation damage if needed */
4149 DrawPosition(FALSE, NULL);
4153 void AnimateUserMove (Widget w, XEvent * event,
4154 String * params, Cardinal * nParams)
4156 DragPieceMove(event->xmotion.x, event->xmotion.y);
4159 Widget CommentCreate(name, text, mutable, callback, lines)
4161 int /*Boolean*/ mutable;
4162 XtCallbackProc callback;
4166 Widget shell, layout, form, edit, b_ok, b_cancel, b_clear, b_close, b_edit;
4171 XtSetArg(args[j], XtNwidth, &bw_width); j++;
4172 XtGetValues(boardWidget, args, j);
4175 XtSetArg(args[j], XtNresizable, True); j++;
4178 XtCreatePopupShell(name, topLevelShellWidgetClass,
4179 shellWidget, args, j);
4182 XtCreatePopupShell(name, transientShellWidgetClass,
4183 shellWidget, args, j);
4186 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
4187 layoutArgs, XtNumber(layoutArgs));
4189 XtCreateManagedWidget("form", formWidgetClass, layout,
4190 formArgs, XtNumber(formArgs));
4194 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
4195 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
4197 XtSetArg(args[j], XtNstring, text); j++;
4198 XtSetArg(args[j], XtNtop, XtChainTop); j++;
4199 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4200 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4201 XtSetArg(args[j], XtNright, XtChainRight); j++;
4202 XtSetArg(args[j], XtNresizable, True); j++;
4203 XtSetArg(args[j], XtNwidth, bw_width); j++; /*force wider than buttons*/
4204 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
4205 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
4206 XtSetArg(args[j], XtNautoFill, True); j++;
4207 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
4209 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
4213 XtSetArg(args[j], XtNfromVert, edit); j++;
4214 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4215 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4216 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4217 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4219 XtCreateManagedWidget(_("ok"), commandWidgetClass, form, args, j);
4220 XtAddCallback(b_ok, XtNcallback, callback, (XtPointer) 0);
4223 XtSetArg(args[j], XtNfromVert, edit); j++;
4224 XtSetArg(args[j], XtNfromHoriz, b_ok); j++;
4225 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4226 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4227 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4228 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4230 XtCreateManagedWidget(_("cancel"), commandWidgetClass, form, args, j);
4231 XtAddCallback(b_cancel, XtNcallback, callback, (XtPointer) 0);
4234 XtSetArg(args[j], XtNfromVert, edit); j++;
4235 XtSetArg(args[j], XtNfromHoriz, b_cancel); j++;
4236 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4237 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4238 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4239 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4241 XtCreateManagedWidget(_("clear"), commandWidgetClass, form, args, j);
4242 XtAddCallback(b_clear, XtNcallback, callback, (XtPointer) 0);
4245 XtSetArg(args[j], XtNfromVert, edit); j++;
4246 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4247 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4248 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4249 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4251 XtCreateManagedWidget(_("close"), commandWidgetClass, form, args, j);
4252 XtAddCallback(b_close, XtNcallback, callback, (XtPointer) 0);
4255 XtSetArg(args[j], XtNfromVert, edit); j++;
4256 XtSetArg(args[j], XtNfromHoriz, b_close); j++;
4257 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4258 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4259 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4260 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4262 XtCreateManagedWidget(_("edit"), commandWidgetClass, form, args, j);
4263 XtAddCallback(b_edit, XtNcallback, callback, (XtPointer) 0);
4266 XtRealizeWidget(shell);
4268 if (commentX == -1) {
4271 Dimension pw_height;
4272 Dimension ew_height;
4275 XtSetArg(args[j], XtNheight, &ew_height); j++;
4276 XtGetValues(edit, args, j);
4279 XtSetArg(args[j], XtNheight, &pw_height); j++;
4280 XtGetValues(shell, args, j);
4281 commentH = pw_height + (lines - 1) * ew_height;
4282 commentW = bw_width - 16;
4284 XSync(xDisplay, False);
4286 /* This code seems to tickle an X bug if it is executed too soon
4287 after xboard starts up. The coordinates get transformed as if
4288 the main window was positioned at (0, 0).
4290 XtTranslateCoords(shellWidget,
4291 (bw_width - commentW) / 2, 0 - commentH / 2,
4292 &commentX, &commentY);
4294 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
4295 RootWindowOfScreen(XtScreen(shellWidget)),
4296 (bw_width - commentW) / 2, 0 - commentH / 2,
4301 if (commentY < 0) commentY = 0; /*avoid positioning top offscreen*/
4304 XtSetArg(args[j], XtNheight, commentH); j++;
4305 XtSetArg(args[j], XtNwidth, commentW); j++;
4306 XtSetArg(args[j], XtNx, commentX); j++;
4307 XtSetArg(args[j], XtNy, commentY); j++;
4308 XtSetValues(shell, args, j);
4309 XtSetKeyboardFocus(shell, edit);
4314 /* Used for analysis window and ICS input window */
4315 Widget MiscCreate(name, text, mutable, callback, lines)
4317 int /*Boolean*/ mutable;
4318 XtCallbackProc callback;
4322 Widget shell, layout, form, edit;
4324 Dimension bw_width, pw_height, ew_height, w, h;
4330 XtSetArg(args[j], XtNresizable, True); j++;
4333 XtCreatePopupShell(name, topLevelShellWidgetClass,
4334 shellWidget, args, j);
4337 XtCreatePopupShell(name, transientShellWidgetClass,
4338 shellWidget, args, j);
4341 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
4342 layoutArgs, XtNumber(layoutArgs));
4344 XtCreateManagedWidget("form", formWidgetClass, layout,
4345 formArgs, XtNumber(formArgs));
4349 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
4350 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
4352 XtSetArg(args[j], XtNstring, text); j++;
4353 XtSetArg(args[j], XtNtop, XtChainTop); j++;
4354 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4355 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4356 XtSetArg(args[j], XtNright, XtChainRight); j++;
4357 XtSetArg(args[j], XtNresizable, True); j++;
4358 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
4359 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
4360 XtSetArg(args[j], XtNautoFill, True); j++;
4361 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
4363 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
4365 XtRealizeWidget(shell);
4368 XtSetArg(args[j], XtNwidth, &bw_width); j++;
4369 XtGetValues(boardWidget, args, j);
4372 XtSetArg(args[j], XtNheight, &ew_height); j++;
4373 XtGetValues(edit, args, j);
4376 XtSetArg(args[j], XtNheight, &pw_height); j++;
4377 XtGetValues(shell, args, j);
4378 h = pw_height + (lines - 1) * ew_height;
4381 XSync(xDisplay, False);
4383 /* This code seems to tickle an X bug if it is executed too soon
4384 after xboard starts up. The coordinates get transformed as if
4385 the main window was positioned at (0, 0).
4387 XtTranslateCoords(shellWidget, (bw_width - w) / 2, 0 - h / 2, &x, &y);
4389 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
4390 RootWindowOfScreen(XtScreen(shellWidget)),
4391 (bw_width - w) / 2, 0 - h / 2, &xx, &yy, &junk);
4395 if (y < 0) y = 0; /*avoid positioning top offscreen*/
4398 XtSetArg(args[j], XtNheight, h); j++;
4399 XtSetArg(args[j], XtNwidth, w); j++;
4400 XtSetArg(args[j], XtNx, x); j++;
4401 XtSetArg(args[j], XtNy, y); j++;
4402 XtSetValues(shell, args, j);
4408 static int savedIndex; /* gross that this is global */
4410 void EditCommentPopUp(index, title, text)
4419 if (text == NULL) text = "";
4421 if (editShell == NULL) {
4423 CommentCreate(title, text, True, EditCommentCallback, 4);
4424 XtRealizeWidget(editShell);
4425 CatchDeleteWindow(editShell, "EditCommentPopDown");
4427 edit = XtNameToWidget(editShell, "*form.text");
4429 XtSetArg(args[j], XtNstring, text); j++;
4430 XtSetValues(edit, args, j);
4432 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4433 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4434 XtSetValues(editShell, args, j);
4437 XtPopup(editShell, XtGrabNone);
4441 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
4442 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
4446 void EditCommentCallback(w, client_data, call_data)
4448 XtPointer client_data, call_data;
4456 XtSetArg(args[j], XtNlabel, &name); j++;
4457 XtGetValues(w, args, j);
4459 if (strcmp(name, _("ok")) == 0) {
4460 edit = XtNameToWidget(editShell, "*form.text");
4462 XtSetArg(args[j], XtNstring, &val); j++;
4463 XtGetValues(edit, args, j);
4464 ReplaceComment(savedIndex, val);
4465 EditCommentPopDown();
4466 } else if (strcmp(name, _("cancel")) == 0) {
4467 EditCommentPopDown();
4468 } else if (strcmp(name, _("clear")) == 0) {
4469 edit = XtNameToWidget(editShell, "*form.text");
4470 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
4471 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
4475 void EditCommentPopDown()
4480 if (!editUp) return;
4482 XtSetArg(args[j], XtNx, &commentX); j++;
4483 XtSetArg(args[j], XtNy, &commentY); j++;
4484 XtSetArg(args[j], XtNheight, &commentH); j++;
4485 XtSetArg(args[j], XtNwidth, &commentW); j++;
4486 XtGetValues(editShell, args, j);
4487 XtPopdown(editShell);
4490 XtSetArg(args[j], XtNleftBitmap, None); j++;
4491 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
4495 void ICSInputBoxPopUp()
4500 char *title = _("ICS Input");
4503 if (ICSInputShell == NULL) {
4504 ICSInputShell = MiscCreate(title, "", True, NULL, 1);
4505 tr = XtParseTranslationTable(ICSInputTranslations);
4506 edit = XtNameToWidget(ICSInputShell, "*form.text");
4507 XtOverrideTranslations(edit, tr);
4508 XtRealizeWidget(ICSInputShell);
4509 CatchDeleteWindow(ICSInputShell, "ICSInputBoxPopDown");
4512 edit = XtNameToWidget(ICSInputShell, "*form.text");
4514 XtSetArg(args[j], XtNstring, ""); j++;
4515 XtSetValues(edit, args, j);
4517 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4518 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4519 XtSetValues(ICSInputShell, args, j);
4522 XtPopup(ICSInputShell, XtGrabNone);
4523 XtSetKeyboardFocus(ICSInputShell, edit);
4525 ICSInputBoxUp = True;
4527 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
4528 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
4532 void ICSInputSendText()
4539 edit = XtNameToWidget(ICSInputShell, "*form.text");
4541 XtSetArg(args[j], XtNstring, &val); j++;
4542 XtGetValues(edit, args, j);
4543 SendMultiLineToICS(val);
4544 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
4545 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
4548 void ICSInputBoxPopDown()
4553 if (!ICSInputBoxUp) return;
4555 XtPopdown(ICSInputShell);
4556 ICSInputBoxUp = False;
4558 XtSetArg(args[j], XtNleftBitmap, None); j++;
4559 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
4563 void CommentPopUp(title, text)
4570 if (commentShell == NULL) {
4572 CommentCreate(title, text, False, CommentCallback, 4);
4573 XtRealizeWidget(commentShell);
4574 CatchDeleteWindow(commentShell, "CommentPopDown");
4576 edit = XtNameToWidget(commentShell, "*form.text");
4578 XtSetArg(args[j], XtNstring, text); j++;
4579 XtSetValues(edit, args, j);
4581 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4582 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4583 XtSetValues(commentShell, args, j);
4586 XtPopup(commentShell, XtGrabNone);
4587 XSync(xDisplay, False);
4592 void CommentCallback(w, client_data, call_data)
4594 XtPointer client_data, call_data;
4601 XtSetArg(args[j], XtNlabel, &name); j++;
4602 XtGetValues(w, args, j);
4604 if (strcmp(name, _("close")) == 0) {
4606 } else if (strcmp(name, _("edit")) == 0) {
4613 void CommentPopDown()
4618 if (!commentUp) return;
4620 XtSetArg(args[j], XtNx, &commentX); j++;
4621 XtSetArg(args[j], XtNy, &commentY); j++;
4622 XtSetArg(args[j], XtNwidth, &commentW); j++;
4623 XtSetArg(args[j], XtNheight, &commentH); j++;
4624 XtGetValues(commentShell, args, j);
4625 XtPopdown(commentShell);
4626 XSync(xDisplay, False);
4630 void PromotionPopUp()
4633 Widget dialog, layout;
4635 Dimension bw_width, pw_width;
4639 XtSetArg(args[j], XtNwidth, &bw_width); j++;
4640 XtGetValues(boardWidget, args, j);
4643 XtSetArg(args[j], XtNresizable, True); j++;
4644 XtSetArg(args[j], XtNtitle, XtNewString(_("Promotion"))); j++;
4646 XtCreatePopupShell("Promotion", transientShellWidgetClass,
4647 shellWidget, args, j);
4649 XtCreateManagedWidget(layoutName, formWidgetClass, promotionShell,
4650 layoutArgs, XtNumber(layoutArgs));
4653 XtSetArg(args[j], XtNlabel, _("Promote to what?")); j++;
4654 XtSetArg(args[j], XtNborderWidth, 0); j++;
4655 dialog = XtCreateManagedWidget("promotion", dialogWidgetClass,
4658 if(gameInfo.variant != VariantShogi) {
4659 XawDialogAddButton(dialog, _("Queen"), PromotionCallback,
4660 (XtPointer) dialog);
4661 XawDialogAddButton(dialog, _("Rook"), PromotionCallback,
4662 (XtPointer) dialog);
4663 XawDialogAddButton(dialog, _("Bishop"), PromotionCallback,
4664 (XtPointer) dialog);
4665 XawDialogAddButton(dialog, _("Knight"), PromotionCallback,
4666 (XtPointer) dialog);
4667 if (!appData.testLegality || gameInfo.variant == VariantSuicide ||
4668 gameInfo.variant == VariantGiveaway) {
4669 XawDialogAddButton(dialog, _("King"), PromotionCallback,
4670 (XtPointer) dialog);
4672 if(gameInfo.variant == VariantCapablanca ||
4673 gameInfo.variant == VariantGothic ||
4674 gameInfo.variant == VariantCapaRandom) {
4675 XawDialogAddButton(dialog, _("Archbishop"), PromotionCallback,
4676 (XtPointer) dialog);
4677 XawDialogAddButton(dialog, _("Chancellor"), PromotionCallback,
4678 (XtPointer) dialog);
4680 } else // [HGM] shogi
4682 XawDialogAddButton(dialog, _("Promote"), PromotionCallback,
4683 (XtPointer) dialog);
4684 XawDialogAddButton(dialog, _("Defer"), PromotionCallback,
4685 (XtPointer) dialog);
4687 XawDialogAddButton(dialog, _("cancel"), PromotionCallback,
4688 (XtPointer) dialog);
4690 XtRealizeWidget(promotionShell);
4691 CatchDeleteWindow(promotionShell, "PromotionPopDown");
4694 XtSetArg(args[j], XtNwidth, &pw_width); j++;
4695 XtGetValues(promotionShell, args, j);
4697 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
4698 lineGap + squareSize/3 +
4699 ((toY == BOARD_HEIGHT-1) ^ (flipView) ?
4700 0 : 6*(squareSize + lineGap)), &x, &y);
4703 XtSetArg(args[j], XtNx, x); j++;
4704 XtSetArg(args[j], XtNy, y); j++;
4705 XtSetValues(promotionShell, args, j);
4707 XtPopup(promotionShell, XtGrabNone);
4712 void PromotionPopDown()
4714 if (!promotionUp) return;
4715 XtPopdown(promotionShell);
4716 XtDestroyWidget(promotionShell);
4717 promotionUp = False;
4720 void PromotionCallback(w, client_data, call_data)
4722 XtPointer client_data, call_data;
4728 XtSetArg(args[0], XtNlabel, &name);
4729 XtGetValues(w, args, 1);
4733 if (fromX == -1) return;
4735 if (strcmp(name, _("cancel")) == 0) {
4739 } else if (strcmp(name, _("Knight")) == 0) {
4741 } else if (strcmp(name, _("Promote")) == 0) {
4743 } else if (strcmp(name, _("Defer")) == 0) {
4746 promoChar = ToLower(name[0]);
4749 FinishMove(NormalMove, fromX, fromY, toX, toY, promoChar);
4751 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
4752 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
4757 void ErrorCallback(w, client_data, call_data)
4759 XtPointer client_data, call_data;
4762 XtPopdown(w = XtParent(XtParent(XtParent(w))));
4764 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
4770 if (!errorUp) return;
4774 gtk_widget_destroy(GTK_WIDGET(GUI_Error));
4776 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
4781 void ErrorPopUp(title, label, modal)
4782 char *title, *label;
4785 GUI_Error = gtk_message_dialog_new(GTK_WINDOW(GUI_Window),
4786 GTK_DIALOG_DESTROY_WITH_PARENT,
4791 gtk_window_set_title(GTK_WINDOW(GUI_Error),(gchar *) title);
4794 gtk_dialog_run(GTK_DIALOG(GUI_Error));
4795 gtk_widget_destroy(GTK_WIDGET(GUI_Error));
4799 g_signal_connect_swapped (GUI_Error, "response",
4800 G_CALLBACK (ErrorPopDownProc),
4803 gtk_widget_show(GTK_WIDGET(GUI_Error));
4809 /* Disable all user input other than deleting the window */
4810 static int frozen = 0;
4814 /* Grab by a widget that doesn't accept input */
4815 // XtAddGrab(messageWidget, TRUE, FALSE);
4819 /* Undo a FreezeUI */
4822 if (!frozen) return;
4823 // XtRemoveGrab(messageWidget);
4827 char *ModeToWidgetName(mode)
4831 case BeginningOfGame:
4832 if (appData.icsActive)
4833 return "menuMode.ICS Client";
4834 else if (appData.noChessProgram ||
4835 *appData.cmailGameName != NULLCHAR)
4836 return "menuMode.Edit Game";
4838 return "menuMode.Machine Black";
4839 case MachinePlaysBlack:
4840 return "menuMode.Machine Black";
4841 case MachinePlaysWhite:
4842 return "menuMode.Machine White";
4844 return "menuMode.Analysis Mode";
4846 return "menuMode.Analyze File";
4847 case TwoMachinesPlay:
4848 return "menuMode.Two Machines";
4850 return "menuMode.Edit Game";
4851 case PlayFromGameFile:
4852 return "menuFile.Load Game";
4854 return "menuMode.Edit Position";
4856 return "menuMode.Training";
4857 case IcsPlayingWhite:
4858 case IcsPlayingBlack:
4862 return "menuMode.ICS Client";
4869 void ModeHighlight()
4871 static int oldPausing = FALSE;
4872 static GameMode oldmode = (GameMode) -1;
4875 // todo this toggling of the pause button doesn't seem to work?
4876 // e.g. select pause from buttonbar doesn't activate menumode.pause
4878 // if (!boardWidget || !XtIsRealized(boardWidget)) return;
4880 if (pausing != oldPausing) {
4881 oldPausing = pausing;
4882 gtk_button_set_relief(GTK_BUTTON (gtk_builder_get_object (builder, "menuMode.Pause")),pausing?GTK_RELIEF_NORMAL:GTK_RELIEF_NONE);
4883 /* toggle background color in showbuttonbar */
4884 if (appData.showButtonBar) {
4886 gtk_button_pressed(GTK_BUTTON (gtk_builder_get_object (builder, "buttonbar.Pause")));
4888 gtk_button_released(GTK_BUTTON (gtk_builder_get_object (builder, "buttonbar.Pause")));
4893 wname = ModeToWidgetName(oldmode);
4895 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, wname)),True);
4899 /* Maybe all the enables should be handled here, not just this one */
4900 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuMode.Training")),
4901 gameMode == Training || gameMode == PlayFromGameFile);
4906 * Button/menu procedures
4909 int LoadGamePopUp(f, gameNumber, title)
4914 cmailMsgLoaded = FALSE;
4916 if (gameNumber == 0)
4918 int error = GameListBuild(f);
4922 DisplayError(_("Cannot build game list"), error);
4924 else if (!ListEmpty(&gameList)
4925 && ((ListGame *) gameList.tailPred)->number > 1)
4927 // TODO convert to GTK
4928 // GameListPopUp(f, title);
4936 return LoadGame(f, gameNumber, title, FALSE);
4939 void ReloadCmailMsgProc(w, event, prms, nprms)
4945 ReloadCmailMsgEvent(FALSE);
4948 void MailMoveProc(w, event, prms, nprms)
4957 /* this variable is shared between CopyPositionProc and SendPositionSelection */
4958 static char *selected_fen_position=NULL;
4961 SendPositionSelection(Widget w, Atom *selection, Atom *target,
4962 Atom *type_return, XtPointer *value_return,
4963 unsigned long *length_return, int *format_return)
4965 char *selection_tmp;
4967 if (!selected_fen_position) return False; /* should never happen */
4968 if (*target == XA_STRING){
4969 /* note: since no XtSelectionDoneProc was registered, Xt will
4970 * automatically call XtFree on the value returned. So have to
4971 * make a copy of it allocated with XtMalloc */
4972 selection_tmp= XtMalloc(strlen(selected_fen_position)+16);
4973 strcpy(selection_tmp, selected_fen_position);
4975 *value_return=selection_tmp;
4976 *length_return=strlen(selection_tmp);
4977 *type_return=XA_STRING;
4978 *format_return = 8; /* bits per byte */
4985 /* note: when called from menu all parameters are NULL, so no clue what the
4986 * Widget which was clicked on was, or what the click event was
4988 void CopyPositionProc(w, event, prms, nprms)
4996 if (selected_fen_position) free(selected_fen_position);
4997 selected_fen_position = (char *)PositionToFEN(currentMove, NULL);
4998 if (!selected_fen_position) return;
4999 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
5001 SendPositionSelection,
5002 NULL/* lose_ownership_proc */ ,
5003 NULL/* transfer_done_proc */);
5005 free(selected_fen_position);
5006 selected_fen_position=NULL;
5010 /* function called when the data to Paste is ready */
5012 PastePositionCB(Widget w, XtPointer client_data, Atom *selection,
5013 Atom *type, XtPointer value, unsigned long *len, int *format)
5016 if (value==NULL || *len==0) return; /* nothing had been selected to copy */
5017 fenstr[*len]='\0'; /* normally this string is terminated, but be safe */
5018 EditPositionPasteFEN(fenstr);
5022 /* called when Paste Position button is pressed,
5023 * all parameters will be NULL */
5024 void PastePositionProc(w, event, prms, nprms)
5030 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
5031 /* (XtSelectionCallbackProc) */ PastePositionCB,
5032 NULL, /* client_data passed to PastePositionCB */
5034 /* better to use the time field from the event that triggered the
5035 * call to this function, but that isn't trivial to get
5043 SendGameSelection(Widget w, Atom *selection, Atom *target,
5044 Atom *type_return, XtPointer *value_return,
5045 unsigned long *length_return, int *format_return)
5047 char *selection_tmp;
5049 if (*target == XA_STRING){
5050 FILE* f = fopen(gameCopyFilename, "r");
5053 if (f == NULL) return False;
5057 selection_tmp = XtMalloc(len + 1);
5058 count = fread(selection_tmp, 1, len, f);
5060 XtFree(selection_tmp);
5063 selection_tmp[len] = NULLCHAR;
5064 *value_return = selection_tmp;
5065 *length_return = len;
5066 *type_return = XA_STRING;
5067 *format_return = 8; /* bits per byte */
5074 /* note: when called from menu all parameters are NULL, so no clue what the
5075 * Widget which was clicked on was, or what the click event was
5077 void CopyGameProc(w, event, prms, nprms)
5085 ret = SaveGameToFile(gameCopyFilename, FALSE);
5088 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
5091 NULL/* lose_ownership_proc */ ,
5092 NULL/* transfer_done_proc */);
5095 /* function called when the data to Paste is ready */
5097 PasteGameCB(Widget w, XtPointer client_data, Atom *selection,
5098 Atom *type, XtPointer value, unsigned long *len, int *format)
5101 if (value == NULL || *len == 0) {
5102 return; /* nothing had been selected to copy */
5104 f = fopen(gamePasteFilename, "w");
5106 DisplayError(_("Can't open temp file"), errno);
5109 fwrite(value, 1, *len, f);
5112 LoadGameFromFile(gamePasteFilename, 0, gamePasteFilename, TRUE);
5115 /* called when Paste Game button is pressed,
5116 * all parameters will be NULL */
5117 void PasteGameProc(w, event, prms, nprms)
5123 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
5124 /* (XtSelectionCallbackProc) */ PasteGameCB,
5125 NULL, /* client_data passed to PasteGameCB */
5127 /* better to use the time field from the event that triggered the
5128 * call to this function, but that isn't trivial to get
5138 SaveGameProc(NULL, NULL);
5142 void AnalyzeModeProc(w, event, prms, nprms)
5150 if (!first.analysisSupport) {
5151 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
5152 DisplayError(buf, 0);
5155 /* [DM] icsEngineAnalyze [HGM] This is horrible code; reverse the gameMode and isEngineAnalyze tests! */
5156 if (appData.icsActive) {
5157 if (gameMode != IcsObserving) {
5158 sprintf(buf,_("You are not observing a game"));
5159 DisplayError(buf, 0);
5161 if (appData.icsEngineAnalyze) {
5162 if (appData.debugMode)
5163 fprintf(debugFP, _("Found unexpected active ICS engine analyze \n"));
5169 /* if enable, use want disable icsEngineAnalyze */
5170 if (appData.icsEngineAnalyze) {
5175 appData.icsEngineAnalyze = TRUE;
5176 if (appData.debugMode)
5177 fprintf(debugFP, _("ICS engine analyze starting... \n"));
5179 if (!appData.showThinking)
5180 ShowThinkingProc(NULL,NULL);
5185 void EditGameProc(w, event, prms, nprms)
5194 void EditPositionProc(w, event, prms, nprms)
5200 EditPositionEvent();
5203 void TrainingProc(w, event, prms, nprms)
5212 void EditCommentProc(w, event, prms, nprms)
5219 EditCommentPopDown();
5225 void IcsInputBoxProc(w, event, prms, nprms)
5231 if (ICSInputBoxUp) {
5232 ICSInputBoxPopDown();
5239 void EnterKeyProc(w, event, prms, nprms)
5245 if (ICSInputBoxUp == True)
5250 void PonderNextMoveProc(w, event, prms, nprms)
5258 PonderNextMoveEvent(!appData.ponderNextMove);
5260 if (appData.ponderNextMove) {
5261 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5263 XtSetArg(args[0], XtNleftBitmap, None);
5265 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Ponder Next Move"),
5269 void PopupExitMessageProc(w, event, prms, nprms)
5277 appData.popupExitMessage = !appData.popupExitMessage;
5279 if (appData.popupExitMessage) {
5280 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5282 XtSetArg(args[0], XtNleftBitmap, None);
5284 XtSetValues(XtNameToWidget(menuBarWidget,
5285 "menuOptions.Popup Exit Message"), args, 1);
5288 void PopupMoveErrorsProc(w, event, prms, nprms)
5296 appData.popupMoveErrors = !appData.popupMoveErrors;
5298 if (appData.popupMoveErrors) {
5299 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5301 XtSetArg(args[0], XtNleftBitmap, None);
5303 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Popup Move Errors"),
5307 void PremoveProc(w, event, prms, nprms)
5315 appData.premove = !appData.premove;
5317 if (appData.premove) {
5318 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5320 XtSetArg(args[0], XtNleftBitmap, None);
5322 XtSetValues(XtNameToWidget(menuBarWidget,
5323 "menuOptions.Premove"), args, 1);
5326 void QuietPlayProc(w, event, prms, nprms)
5334 appData.quietPlay = !appData.quietPlay;
5336 if (appData.quietPlay) {
5337 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5339 XtSetArg(args[0], XtNleftBitmap, None);
5341 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Quiet Play"),
5345 void DebugProc(w, event, prms, nprms)
5351 appData.debugMode = !appData.debugMode;
5354 void AboutGameProc(w, event, prms, nprms)
5363 void NothingProc(w, event, prms, nprms)
5372 void Iconify(w, event, prms, nprms)
5381 XtSetArg(args[0], XtNiconic, True);
5382 XtSetValues(shellWidget, args, 1);
5385 void DisplayMessage(message, extMessage)
5386 gchar *message, *extMessage;
5393 snprintf(buf, sizeof(buf), "%s %s", message, extMessage);
5396 message = extMessage;
5399 gtk_label_set_text( GTK_LABEL(gtk_builder_get_object (builder, "Messages")),message);
5404 void DisplayTitle(text)
5407 gchar title[MSG_SIZ];
5409 if (text == NULL) text = "";
5411 if (appData.titleInWindow)
5416 if (*text != NULLCHAR)
5418 strcpy(title, text);
5420 else if (appData.icsActive)
5422 snprintf(title, sizeof(title), "%s: %s", programName, appData.icsHost);
5424 else if (appData.cmailGameName[0] != NULLCHAR)
5426 snprintf(title,sizeof(title), "%s: %s", programName, "CMail");
5428 // [HGM] license: This stuff should really be done in back-end, but WinBoard already had a pop-up for it
5430 else if (gameInfo.variant == VariantGothic)
5432 strcpy(title, GOTHIC);
5436 else if (gameInfo.variant == VariantFalcon)
5438 strcpy(title, FALCON);
5441 else if (appData.noChessProgram)
5443 strcpy(title, programName);
5447 snprintf(title,sizeof(title), "%s: %s", programName, first.tidy);
5449 gtk_window_set_title(GTK_WINDOW(GUI_Window),title);
5455 void DisplayError(message, error)
5462 if (appData.debugMode || appData.matchMode) {
5463 fprintf(stderr, "%s: %s\n", programName, message);
5466 if (appData.debugMode || appData.matchMode) {
5467 fprintf(stderr, "%s: %s: %s\n",
5468 programName, message, strerror(error));
5470 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
5473 ErrorPopUp(_("Error"), message, FALSE);
5477 void DisplayMoveError(message)
5482 DrawPosition(FALSE, NULL);
5483 if (appData.debugMode || appData.matchMode) {
5484 fprintf(stderr, "%s: %s\n", programName, message);
5486 if (appData.popupMoveErrors) {
5487 ErrorPopUp(_("Error"), message, FALSE);
5489 DisplayMessage(message, "");
5494 void DisplayFatalError(message, error, status)
5500 errorExitStatus = status;
5502 fprintf(stderr, "%s: %s\n", programName, message);
5504 fprintf(stderr, "%s: %s: %s\n",
5505 programName, message, strerror(error));
5506 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
5509 if (appData.popupExitMessage && boardWidget && XtIsRealized(boardWidget)) {
5510 ErrorPopUp(status ? _("Fatal Error") : _("Exiting"), message, TRUE);
5516 void DisplayInformation(message)
5520 ErrorPopUp(_("Information"), message, TRUE);
5523 void DisplayNote(message)
5527 ErrorPopUp(_("Note"), message, FALSE);
5531 NullXErrorCheck(dpy, error_event)
5533 XErrorEvent *error_event;
5538 void DisplayIcsInteractionTitle(message)
5541 if (oldICSInteractionTitle == NULL) {
5542 /* Magic to find the old window title, adapted from vim */
5543 char *wina = getenv("WINDOWID");
5545 Window win = (Window) atoi(wina);
5546 Window root, parent, *children;
5547 unsigned int nchildren;
5548 int (*oldHandler)() = XSetErrorHandler(NullXErrorCheck);
5550 if (XFetchName(xDisplay, win, &oldICSInteractionTitle)) break;
5551 if (!XQueryTree(xDisplay, win, &root, &parent,
5552 &children, &nchildren)) break;
5553 if (children) XFree((void *)children);
5554 if (parent == root || parent == 0) break;
5557 XSetErrorHandler(oldHandler);
5559 if (oldICSInteractionTitle == NULL) {
5560 oldICSInteractionTitle = "xterm";
5563 printf("\033]0;%s\007", message);
5567 char pendingReplyPrefix[MSG_SIZ];
5568 ProcRef pendingReplyPR;
5570 void AskQuestionProc(w, event, prms, nprms)
5577 fprintf(stderr, _("AskQuestionProc needed 4 parameters, got %d\n"),
5581 AskQuestionEvent(prms[0], prms[1], prms[2], prms[3]);
5584 void AskQuestionPopDown()
5586 if (!askQuestionUp) return;
5587 XtPopdown(askQuestionShell);
5588 XtDestroyWidget(askQuestionShell);
5589 askQuestionUp = False;
5592 void AskQuestionReplyAction(w, event, prms, nprms)
5602 reply = XawDialogGetValueString(w = XtParent(w));
5603 strcpy(buf, pendingReplyPrefix);
5604 if (*buf) strcat(buf, " ");
5607 OutputToProcess(pendingReplyPR, buf, strlen(buf), &err);
5608 AskQuestionPopDown();
5610 if (err) DisplayFatalError(_("Error writing to chess program"), err, 0);
5613 void AskQuestionCallback(w, client_data, call_data)
5615 XtPointer client_data, call_data;
5620 XtSetArg(args[0], XtNlabel, &name);
5621 XtGetValues(w, args, 1);
5623 if (strcmp(name, _("cancel")) == 0) {
5624 AskQuestionPopDown();
5626 AskQuestionReplyAction(w, NULL, NULL, NULL);
5630 void AskQuestion(title, question, replyPrefix, pr)
5631 char *title, *question, *replyPrefix;
5635 Widget popup, layout, dialog, edit;
5641 strcpy(pendingReplyPrefix, replyPrefix);
5642 pendingReplyPR = pr;
5645 XtSetArg(args[i], XtNresizable, True); i++;
5646 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
5647 askQuestionShell = popup =
5648 XtCreatePopupShell(title, transientShellWidgetClass,
5649 shellWidget, args, i);
5652 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
5653 layoutArgs, XtNumber(layoutArgs));
5656 XtSetArg(args[i], XtNlabel, question); i++;
5657 XtSetArg(args[i], XtNvalue, ""); i++;
5658 XtSetArg(args[i], XtNborderWidth, 0); i++;
5659 dialog = XtCreateManagedWidget("question", dialogWidgetClass,
5662 XawDialogAddButton(dialog, _("enter"), AskQuestionCallback,
5663 (XtPointer) dialog);
5664 XawDialogAddButton(dialog, _("cancel"), AskQuestionCallback,
5665 (XtPointer) dialog);
5667 XtRealizeWidget(popup);
5668 CatchDeleteWindow(popup, "AskQuestionPopDown");
5670 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
5671 &x, &y, &win_x, &win_y, &mask);
5673 XtSetArg(args[0], XtNx, x - 10);
5674 XtSetArg(args[1], XtNy, y - 30);
5675 XtSetValues(popup, args, 2);
5677 XtPopup(popup, XtGrabExclusive);
5678 askQuestionUp = True;
5680 edit = XtNameToWidget(dialog, "*value");
5681 XtSetKeyboardFocus(popup, edit);
5689 if (*name == NULLCHAR) {
5691 } else if (strcmp(name, "$") == 0) {
5692 putc(BELLCHAR, stderr);
5695 snprintf(buf, sizeof(buf), "%s '%s' &", appData.soundProgram, name);
5703 PlaySound(appData.soundMove);
5709 PlaySound(appData.soundIcsWin);
5715 PlaySound(appData.soundIcsLoss);
5721 PlaySound(appData.soundIcsDraw);
5725 PlayIcsUnfinishedSound()
5727 PlaySound(appData.soundIcsUnfinished);
5733 PlaySound(appData.soundIcsAlarm);
5739 system("stty echo");
5745 system("stty -echo");
5749 Colorize(cc, continuation)
5754 int count, outCount, error;
5756 if (textColors[(int)cc].bg > 0) {
5757 if (textColors[(int)cc].fg > 0) {
5758 sprintf(buf, "\033[0;%d;%d;%dm", textColors[(int)cc].attr,
5759 textColors[(int)cc].fg, textColors[(int)cc].bg);
5761 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
5762 textColors[(int)cc].bg);
5765 if (textColors[(int)cc].fg > 0) {
5766 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
5767 textColors[(int)cc].fg);
5769 sprintf(buf, "\033[0;%dm", textColors[(int)cc].attr);
5772 count = strlen(buf);
5773 outCount = OutputToProcess(NoProc, buf, count, &error);
5774 if (outCount < count) {
5775 DisplayFatalError(_("Error writing to display"), error, 1);
5778 if (continuation) return;
5781 PlaySound(appData.soundShout);
5784 PlaySound(appData.soundSShout);
5787 PlaySound(appData.soundChannel1);
5790 PlaySound(appData.soundChannel);
5793 PlaySound(appData.soundKibitz);
5796 PlaySound(appData.soundTell);
5798 case ColorChallenge:
5799 PlaySound(appData.soundChallenge);
5802 PlaySound(appData.soundRequest);
5805 PlaySound(appData.soundSeek);
5816 return getpwuid(getuid())->pw_name;
5819 static char *ExpandPathName(path)
5822 static char static_buf[2000];
5823 char *d, *s, buf[2000];
5829 while (*s && isspace(*s))
5838 if (*(s+1) == '/') {
5839 strcpy(d, getpwuid(getuid())->pw_dir);
5844 *strchr(buf, '/') = 0;
5845 pwd = getpwnam(buf);
5848 fprintf(stderr, _("ERROR: Unknown user %s (in path %s)\n"),
5852 strcpy(d, pwd->pw_dir);
5853 strcat(d, strchr(s+1, '/'));
5864 static char host_name[MSG_SIZ];
5866 #if HAVE_GETHOSTNAME
5867 gethostname(host_name, MSG_SIZ);
5869 #else /* not HAVE_GETHOSTNAME */
5870 # if HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H
5871 sysinfo(SI_HOSTNAME, host_name, MSG_SIZ);
5873 # else /* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
5875 # endif/* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
5876 #endif /* not HAVE_GETHOSTNAME */
5879 guint delayedEventTimerTag = 0;
5880 DelayedEventCallback delayedEventCallback = 0;
5883 FireDelayedEvent(data)
5887 g_source_remove(delayedEventTimerTag);
5888 delayedEventTimerTag = 0;
5891 delayedEventCallback();
5897 ScheduleDelayedEvent(cb, millisec)
5898 DelayedEventCallback cb; guint millisec;
5900 if(delayedEventTimerTag && delayedEventCallback == cb)
5901 // [HGM] alive: replace, rather than add or flush identical event
5902 g_source_remove(delayedEventTimerTag);
5903 delayedEventCallback = cb;
5904 delayedEventTimerTag = g_timeout_add(millisec,(GSourceFunc) FireDelayedEvent, NULL);
5908 DelayedEventCallback
5911 if (delayedEventTimerTag)
5913 return delayedEventCallback;
5922 CancelDelayedEvent()
5924 if (delayedEventTimerTag)
5926 g_source_remove(delayedEventTimerTag);
5927 delayedEventTimerTag = 0;
5933 guint loadGameTimerTag = 0;
5935 int LoadGameTimerRunning()
5937 return loadGameTimerTag != 0;
5940 int StopLoadGameTimer()
5942 if (loadGameTimerTag != 0) {
5943 g_source_remove(loadGameTimerTag);
5944 loadGameTimerTag = 0;
5952 LoadGameTimerCallback(data)
5956 g_source_remove(loadGameTimerTag);
5957 loadGameTimerTag = 0;
5964 StartLoadGameTimer(millisec)
5968 g_timeout_add( millisec, (GSourceFunc) LoadGameTimerCallback, NULL);
5972 guint analysisClockTag = 0;
5975 AnalysisClockCallback(data)
5978 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile
5979 || appData.icsEngineAnalyze)
5981 AnalysisPeriodicEvent(0);
5982 return 1; /* keep on going */
5984 return 0; /* stop timer */
5988 StartAnalysisClock()
5991 g_timeout_add( 2000,(GSourceFunc) AnalysisClockCallback, NULL);
5995 guint clockTimerTag = 0;
5997 int ClockTimerRunning()
5999 return clockTimerTag != 0;
6002 int StopClockTimer()
6004 if (clockTimerTag != 0)
6006 g_source_remove(clockTimerTag);
6017 ClockTimerCallback(data)
6021 g_source_remove(clockTimerTag);
6029 StartClockTimer(millisec)
6032 clockTimerTag = g_timeout_add(millisec,(GSourceFunc) ClockTimerCallback,NULL);
6037 DisplayTimerLabel(w, color, timer, highlight)
6046 if (appData.clockMode) {
6047 sprintf(buf, "%s: %s", color, TimeString(timer));
6049 sprintf(buf, "%s ", color);
6051 gtk_label_set_text(GTK_LABEL(w),buf);
6053 /* check for low time warning */
6054 // Pixel foregroundOrWarningColor = timerForegroundPixel;
6057 // appData.lowTimeWarning &&
6058 // (timer / 1000) < appData.icsAlarmTime)
6059 // foregroundOrWarningColor = lowTimeWarningColor;
6061 // if (appData.clockMode) {
6062 // sprintf(buf, "%s: %s", color, TimeString(timer));
6063 // XtSetArg(args[0], XtNlabel, buf);
6065 // sprintf(buf, "%s ", color);
6066 // XtSetArg(args[0], XtNlabel, buf);
6071 // XtSetArg(args[1], XtNbackground, foregroundOrWarningColor);
6072 // XtSetArg(args[2], XtNforeground, timerBackgroundPixel);
6074 // XtSetArg(args[1], XtNbackground, timerBackgroundPixel);
6075 // XtSetArg(args[2], XtNforeground, foregroundOrWarningColor);
6078 // XtSetValues(w, args, 3);
6083 DisplayWhiteClock(timeRemaining, highlight)
6087 if(appData.noGUI) return;
6089 DisplayTimerLabel(GUI_Whiteclock, _("White"), timeRemaining, highlight);
6090 if (highlight && WindowIcon == BlackIcon)
6092 WindowIcon = WhiteIcon;
6093 gtk_window_set_icon(GTK_WINDOW(GUI_Window),WindowIcon);
6098 DisplayBlackClock(timeRemaining, highlight)
6102 if(appData.noGUI) return;
6104 DisplayTimerLabel(GUI_Blackclock, _("Black"), timeRemaining, highlight);
6105 if (highlight && WindowIcon == WhiteIcon)
6107 WindowIcon = BlackIcon;
6108 gtk_window_set_icon(GTK_WINDOW(GUI_Window),WindowIcon);
6126 int StartChildProcess(cmdLine, dir, pr)
6133 int to_prog[2], from_prog[2];
6137 if (appData.debugMode) {
6138 fprintf(stderr, "StartChildProcess (dir=\"%s\") %s\n",dir, cmdLine);
6141 /* We do NOT feed the cmdLine to the shell; we just
6142 parse it into blank-separated arguments in the
6143 most simple-minded way possible.
6146 strcpy(buf, cmdLine);
6151 if (p == NULL) break;
6156 SetUpChildIO(to_prog, from_prog);
6159 signal(SIGWINCH, TermSizeSigHandler);
6162 if ((pid = fork()) == 0) {
6164 // [HGM] PSWBTM: made order resistant against case where fd of created pipe was 0 or 1
6165 close(to_prog[1]); // first close the unused pipe ends
6166 close(from_prog[0]);
6167 dup2(to_prog[0], 0); // to_prog was created first, nd is the only one to use 0 or 1
6168 dup2(from_prog[1], 1);
6169 if(to_prog[0] >= 2) close(to_prog[0]); // if 0 or 1, the dup2 already cosed the original
6170 close(from_prog[1]); // and closing again loses one of the pipes!
6171 if(fileno(stderr) >= 2) // better safe than sorry...
6172 dup2(1, fileno(stderr)); /* force stderr to the pipe */
6174 if (dir[0] != NULLCHAR && chdir(dir) != 0) {
6179 nice(appData.niceEngines); // [HGM] nice: adjust priority of engine proc
6181 execvp(argv[0], argv);
6183 /* If we get here, exec failed */
6188 /* Parent process */
6190 close(from_prog[1]);
6192 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
6195 cp->fdFrom = from_prog[0];
6196 cp->fdTo = to_prog[1];
6201 // [HGM] kill: implement the 'hard killing' of AS's Winboard_x
6202 static RETSIGTYPE AlarmCallBack(int n)
6208 DestroyChildProcess(pr, signalType)
6212 ChildProc *cp = (ChildProc *) pr;
6214 if (cp->kind != CPReal) return;
6216 if (signalType == 10) { // [HGM] kill: if it does not terminate in 3 sec, kill
6217 signal(SIGALRM, AlarmCallBack);
6219 if(wait((int *) 0) == -1) { // process does not terminate on its own accord
6220 kill(cp->pid, SIGKILL); // kill it forcefully
6221 wait((int *) 0); // and wait again
6225 kill(cp->pid, signalType == 9 ? SIGKILL : SIGTERM); // [HGM] kill: use hard kill if so requested
6227 /* Process is exiting either because of the kill or because of
6228 a quit command sent by the backend; either way, wait for it to die.
6237 InterruptChildProcess(pr)
6240 ChildProc *cp = (ChildProc *) pr;
6242 if (cp->kind != CPReal) return;
6243 (void) kill(cp->pid, SIGINT); /* stop it thinking */
6246 int OpenTelnet(host, port, pr)
6251 char cmdLine[MSG_SIZ];
6253 if (port[0] == NULLCHAR) {
6254 snprintf(cmdLine, sizeof(cmdLine), "%s %s", appData.telnetProgram, host);
6256 snprintf(cmdLine, sizeof(cmdLine), "%s %s %s", appData.telnetProgram, host, port);
6258 return StartChildProcess(cmdLine, "", pr);
6261 int OpenTCP(host, port, pr)
6267 DisplayFatalError(_("Socket support is not configured in"), 0, 2);
6268 #else /* !OMIT_SOCKETS */
6270 struct sockaddr_in sa;
6272 unsigned short uport;
6275 if ((s = socket(AF_INET, SOCK_STREAM, 6)) < 0) {
6279 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
6280 sa.sin_family = AF_INET;
6281 sa.sin_addr.s_addr = INADDR_ANY;
6282 uport = (unsigned short) 0;
6283 sa.sin_port = htons(uport);
6284 if (bind(s, (struct sockaddr *) &sa, sizeof(struct sockaddr_in)) < 0) {
6288 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
6289 if (!(hp = gethostbyname(host))) {
6291 if (sscanf(host, "%d.%d.%d.%d", &b0, &b1, &b2, &b3) == 4) {
6292 hp = (struct hostent *) calloc(1, sizeof(struct hostent));
6293 hp->h_addrtype = AF_INET;
6295 hp->h_addr_list = (char **) calloc(2, sizeof(char *));
6296 hp->h_addr_list[0] = (char *) malloc(4);
6297 hp->h_addr_list[0][0] = b0;
6298 hp->h_addr_list[0][1] = b1;
6299 hp->h_addr_list[0][2] = b2;
6300 hp->h_addr_list[0][3] = b3;
6305 sa.sin_family = hp->h_addrtype;
6306 uport = (unsigned short) atoi(port);
6307 sa.sin_port = htons(uport);
6308 memcpy((char *) &sa.sin_addr, hp->h_addr, hp->h_length);
6310 if (connect(s, (struct sockaddr *) &sa,
6311 sizeof(struct sockaddr_in)) < 0) {
6315 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
6322 #endif /* !OMIT_SOCKETS */
6327 int OpenCommPort(name, pr)
6334 fd = open(name, 2, 0);
6335 if (fd < 0) return errno;
6337 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
6347 int OpenLoopback(pr)
6353 SetUpChildIO(to, from);
6355 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
6358 cp->fdFrom = to[0]; /* note not from[0]; we are doing a loopback */
6365 int OpenRcmd(host, user, cmd, pr)
6366 char *host, *user, *cmd;
6369 DisplayFatalError(_("internal rcmd not implemented for Unix"), 0, 1);
6373 #define INPUT_SOURCE_BUF_SIZE 8192
6382 char buf[INPUT_SOURCE_BUF_SIZE];
6387 DoInputCallback(io,cond,data)
6392 /* read input from one of the input source (for example a chess program, ICS, etc).
6393 * and call a function that will handle the input
6396 int count; /* how many bytes did we read */
6400 /* All information (callback function, file descriptor, etc) is
6401 * saved in an InputSource structure
6403 InputSource *is = (InputSource *) data;
6407 count = read(is->fd, is->unused,
6408 INPUT_SOURCE_BUF_SIZE - (is->unused - is->buf));
6412 (is->func)(is, is->closure, is->buf, count, count ? errno : 0);
6415 is->unused += count;
6417 /* break input into lines and call the callback function on each
6420 while (p < is->unused)
6422 q = memchr(p, '\n', is->unused - p);
6423 if (q == NULL) break;
6425 (is->func)(is, is->closure, p, q - p, 0);
6428 /* remember not yet used part of the buffer */
6430 while (p < is->unused)
6438 /* read maximum length of input buffer and send the whole buffer
6439 * to the callback function
6441 count = read(is->fd, is->buf, INPUT_SOURCE_BUF_SIZE);
6446 (is->func)(is, is->closure, is->buf, count, error);
6452 InputSourceRef AddInputSource(pr, lineByLine, func, closure)
6459 GIOChannel *channel;
6460 ChildProc *cp = (ChildProc *) pr;
6462 is = (InputSource *) calloc(1, sizeof(InputSource));
6463 is->lineByLine = lineByLine;
6467 is->fd = fileno(stdin);
6469 is->kind = cp->kind;
6470 is->fd = cp->fdFrom;
6473 is->unused = is->buf;
6477 // is->xid = XtAppAddInput(appContext, is->fd,
6478 // (XtPointer) (XtInputReadMask),
6479 // (XtInputCallbackProc) DoInputCallback,
6483 /* TODO: will this work on windows?*/
6484 printf("DEBUG: fd=%d %d\n",is->fd,is);
6486 channel = g_io_channel_unix_new(is->fd);
6487 g_io_channel_set_close_on_unref (channel, TRUE);
6488 is->sid = g_io_add_watch(channel, G_IO_IN,(GIOFunc) DoInputCallback, is);
6489 is->closure = closure;
6490 return (InputSourceRef) is;
6494 RemoveInputSource(isr)
6497 InputSource *is = (InputSource *) isr;
6499 if (is->sid == 0) return;
6500 g_source_remove(is->sid);
6505 int OutputToProcess(pr, message, count, outError)
6511 ChildProc *cp = (ChildProc *) pr;
6515 outCount = fwrite(message, 1, count, stdout);
6517 outCount = write(cp->fdTo, message, count);
6527 /* Output message to process, with "ms" milliseconds of delay
6528 between each character. This is needed when sending the logon
6529 script to ICC, which for some reason doesn't like the
6530 instantaneous send. */
6531 int OutputToProcessDelayed(pr, message, count, outError, msdelay)
6538 ChildProc *cp = (ChildProc *) pr;
6543 r = write(cp->fdTo, message++, 1);
6556 /**** Animation code by Hugh Fisher, DCS, ANU.
6558 Known problem: if a window overlapping the board is
6559 moved away while a piece is being animated underneath,
6560 the newly exposed area won't be updated properly.
6561 I can live with this.
6563 Known problem: if you look carefully at the animation
6564 of pieces in mono mode, they are being drawn as solid
6565 shapes without interior detail while moving. Fixing
6566 this would be a major complication for minimal return.
6569 /* Masks for XPM pieces. Black and white pieces can have
6570 different shapes, but in the interest of retaining my
6571 sanity pieces must have the same outline on both light
6572 and dark squares, and all pieces must use the same
6573 background square colors/images. */
6575 static int xpmDone = 0;
6578 CreateAnimMasks (pieceDepth)
6585 unsigned long plane;
6588 /* just return for gtk at the moment */
6591 /* Need a bitmap just to get a GC with right depth */
6592 buf = XCreatePixmap(xDisplay, xBoardWindow,
6594 values.foreground = 1;
6595 values.background = 0;
6596 /* Don't use XtGetGC, not read only */
6597 maskGC = XCreateGC(xDisplay, buf,
6598 GCForeground | GCBackground, &values);
6599 XFreePixmap(xDisplay, buf);
6601 buf = XCreatePixmap(xDisplay, xBoardWindow,
6602 squareSize, squareSize, pieceDepth);
6603 values.foreground = XBlackPixel(xDisplay, xScreen);
6604 values.background = XWhitePixel(xDisplay, xScreen);
6605 bufGC = XCreateGC(xDisplay, buf,
6606 GCForeground | GCBackground, &values);
6608 for (piece = WhitePawn; piece <= BlackKing; piece++) {
6609 /* Begin with empty mask */
6610 if(!xpmDone) // [HGM] pieces: keep using existing
6611 xpmMask[piece] = XCreatePixmap(xDisplay, xBoardWindow,
6612 squareSize, squareSize, 1);
6613 XSetFunction(xDisplay, maskGC, GXclear);
6614 XFillRectangle(xDisplay, xpmMask[piece], maskGC,
6615 0, 0, squareSize, squareSize);
6617 /* Take a copy of the piece */
6622 XSetFunction(xDisplay, bufGC, GXcopy);
6623 XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % (int)BlackPawn],
6625 0, 0, squareSize, squareSize, 0, 0);
6627 /* XOR the background (light) over the piece */
6628 XSetFunction(xDisplay, bufGC, GXxor);
6630 XCopyArea(xDisplay, xpmLightSquare, buf, bufGC,
6631 0, 0, squareSize, squareSize, 0, 0);
6633 XSetForeground(xDisplay, bufGC, lightSquareColor);
6634 XFillRectangle(xDisplay, buf, bufGC, 0, 0, squareSize, squareSize);
6637 /* We now have an inverted piece image with the background
6638 erased. Construct mask by just selecting all the non-zero
6639 pixels - no need to reconstruct the original image. */
6640 XSetFunction(xDisplay, maskGC, GXor);
6642 /* Might be quicker to download an XImage and create bitmap
6643 data from it rather than this N copies per piece, but it
6644 only takes a fraction of a second and there is a much
6645 longer delay for loading the pieces. */
6646 for (n = 0; n < pieceDepth; n ++) {
6647 XCopyPlane(xDisplay, buf, xpmMask[piece], maskGC,
6648 0, 0, squareSize, squareSize,
6654 XFreePixmap(xDisplay, buf);
6655 XFreeGC(xDisplay, bufGC);
6656 XFreeGC(xDisplay, maskGC);
6660 InitAnimState (anim, info)
6662 XWindowAttributes * info;
6667 /* Each buffer is square size, same depth as window */
6668 // anim->saveBuf = XCreatePixmap(xDisplay, xBoardWindow,
6669 // squareSize, squareSize, info->depth);
6670 // anim->newBuf = XCreatePixmap(xDisplay, xBoardWindow,
6671 // squareSize, squareSize, info->depth);
6673 // /* Create a plain GC for blitting */
6674 // mask = GCForeground | GCBackground | GCFunction |
6675 // GCPlaneMask | GCGraphicsExposures;
6676 // values.foreground = XBlackPixel(xDisplay, xScreen);
6677 // values.background = XWhitePixel(xDisplay, xScreen);
6678 // values.function = GXcopy;
6679 // values.plane_mask = AllPlanes;
6680 // values.graphics_exposures = False;
6681 // anim->blitGC = XCreateGC(xDisplay, xBoardWindow, mask, &values);
6683 // /* Piece will be copied from an existing context at
6684 // the start of each new animation/drag. */
6685 // anim->pieceGC = XCreateGC(xDisplay, xBoardWindow, 0, &values);
6687 // /* Outline will be a read-only copy of an existing */
6688 // anim->outlineGC = None;
6694 static VariantClass old = (VariantClass) -1; // [HGM] pieces: redo every time variant changes
6695 XWindowAttributes info;
6697 /* for gtk at the moment just ... */
6700 if (xpmDone && gameInfo.variant == old) return;
6701 if(xpmDone) old = gameInfo.variant; // first time pieces might not be created yet
6702 // XGetWindowAttributes(xDisplay, xBoardWindow, &info);
6704 // InitAnimState(&game, &info);
6705 // InitAnimState(&player, &info);
6707 /* For XPM pieces, we need bitmaps to use as masks. */
6709 // CreateAnimMasks(info.depth);
6715 static Boolean frameWaiting;
6717 static RETSIGTYPE FrameAlarm (sig)
6720 frameWaiting = False;
6721 /* In case System-V style signals. Needed?? */
6722 signal(SIGALRM, FrameAlarm);
6729 struct itimerval delay;
6731 XSync(xDisplay, False);
6734 frameWaiting = True;
6735 signal(SIGALRM, FrameAlarm);
6736 delay.it_interval.tv_sec =
6737 delay.it_value.tv_sec = time / 1000;
6738 delay.it_interval.tv_usec =
6739 delay.it_value.tv_usec = (time % 1000) * 1000;
6740 setitimer(ITIMER_REAL, &delay, NULL);
6741 while (frameWaiting) pause();
6742 delay.it_interval.tv_sec = delay.it_value.tv_sec = 0;
6743 delay.it_interval.tv_usec = delay.it_value.tv_usec = 0;
6744 setitimer(ITIMER_REAL, &delay, NULL);
6754 // XSync(xDisplay, False);
6756 usleep(time * 1000);
6761 /* Convert board position to corner of screen rect and color */
6764 ScreenSquare(column, row, pt, color)
6765 int column; int row; XPoint * pt; int * color;
6768 pt->x = lineGap + ((BOARD_WIDTH-1)-column) * (squareSize + lineGap);
6769 pt->y = lineGap + row * (squareSize + lineGap);
6771 pt->x = lineGap + column * (squareSize + lineGap);
6772 pt->y = lineGap + ((BOARD_HEIGHT-1)-row) * (squareSize + lineGap);
6774 *color = SquareColor(row, column);
6777 /* Convert window coords to square */
6780 BoardSquare(x, y, column, row)
6781 int x; int y; int * column; int * row;
6783 *column = EventToSquare(x, BOARD_WIDTH);
6784 if (flipView && *column >= 0)
6785 *column = BOARD_WIDTH - 1 - *column;
6786 *row = EventToSquare(y, BOARD_HEIGHT);
6787 if (!flipView && *row >= 0)
6788 *row = BOARD_HEIGHT - 1 - *row;
6793 #undef Max /* just in case */
6795 #define Max(a, b) ((a) > (b) ? (a) : (b))
6796 #define Min(a, b) ((a) < (b) ? (a) : (b))
6799 SetRect(rect, x, y, width, height)
6800 XRectangle * rect; int x; int y; int width; int height;
6804 rect->width = width;
6805 rect->height = height;
6808 /* Test if two frames overlap. If they do, return
6809 intersection rect within old and location of
6810 that rect within new. */
6813 Intersect(old, new, size, area, pt)
6814 XPoint * old; XPoint * new;
6815 int size; XRectangle * area; XPoint * pt;
6817 if (old->x > new->x + size || new->x > old->x + size ||
6818 old->y > new->y + size || new->y > old->y + size) {
6821 SetRect(area, Max(new->x - old->x, 0), Max(new->y - old->y, 0),
6822 size - abs(old->x - new->x), size - abs(old->y - new->y));
6823 pt->x = Max(old->x - new->x, 0);
6824 pt->y = Max(old->y - new->y, 0);
6829 /* For two overlapping frames, return the rect(s)
6830 in the old that do not intersect with the new. */
6833 CalcUpdateRects(old, new, size, update, nUpdates)
6834 XPoint * old; XPoint * new; int size;
6835 XRectangle update[]; int * nUpdates;
6839 /* If old = new (shouldn't happen) then nothing to draw */
6840 if (old->x == new->x && old->y == new->y) {
6844 /* Work out what bits overlap. Since we know the rects
6845 are the same size we don't need a full intersect calc. */
6847 /* Top or bottom edge? */
6848 if (new->y > old->y) {
6849 SetRect(&(update[count]), old->x, old->y, size, new->y - old->y);
6851 } else if (old->y > new->y) {
6852 SetRect(&(update[count]), old->x, old->y + size - (old->y - new->y),
6853 size, old->y - new->y);
6856 /* Left or right edge - don't overlap any update calculated above. */
6857 if (new->x > old->x) {
6858 SetRect(&(update[count]), old->x, Max(new->y, old->y),
6859 new->x - old->x, size - abs(new->y - old->y));
6861 } else if (old->x > new->x) {
6862 SetRect(&(update[count]), new->x + size, Max(new->y, old->y),
6863 old->x - new->x, size - abs(new->y - old->y));
6870 /* Generate a series of frame coords from start->mid->finish.
6871 The movement rate doubles until the half way point is
6872 reached, then halves back down to the final destination,
6873 which gives a nice slow in/out effect. The algorithmn
6874 may seem to generate too many intermediates for short
6875 moves, but remember that the purpose is to attract the
6876 viewers attention to the piece about to be moved and
6877 then to where it ends up. Too few frames would be less
6881 Tween(start, mid, finish, factor, frames, nFrames)
6882 XPoint * start; XPoint * mid;
6883 XPoint * finish; int factor;
6884 XPoint frames[]; int * nFrames;
6886 int fraction, n, count;
6890 /* Slow in, stepping 1/16th, then 1/8th, ... */
6892 for (n = 0; n < factor; n++)
6894 for (n = 0; n < factor; n++) {
6895 frames[count].x = start->x + (mid->x - start->x) / fraction;
6896 frames[count].y = start->y + (mid->y - start->y) / fraction;
6898 fraction = fraction / 2;
6902 frames[count] = *mid;
6905 /* Slow out, stepping 1/2, then 1/4, ... */
6907 for (n = 0; n < factor; n++) {
6908 frames[count].x = finish->x - (finish->x - mid->x) / fraction;
6909 frames[count].y = finish->y - (finish->y - mid->y) / fraction;
6911 fraction = fraction * 2;
6916 /* Draw a piece on the screen without disturbing what's there */
6919 SelectGCMask(piece, clip, outline, mask)
6920 ChessSquare piece; GC * clip; GC * outline; Pixmap * mask;
6924 /* Bitmap for piece being moved. */
6925 if (appData.monoMode) {
6926 *mask = *pieceToSolid(piece);
6927 } else if (useImages) {
6929 *mask = xpmMask[piece];
6931 *mask = ximMaskPm[piece];
6934 *mask = *pieceToSolid(piece);
6937 /* GC for piece being moved. Square color doesn't matter, but
6938 since it gets modified we make a copy of the original. */
6940 if (appData.monoMode)
6945 if (appData.monoMode)
6950 // XCopyGC(xDisplay, source, 0xFFFFFFFF, *clip);
6952 /* Outline only used in mono mode and is not modified */
6954 *outline = bwPieceGC;
6956 *outline = wbPieceGC;
6960 OverlayPiece(piece, clip, outline, dest)
6961 ChessSquare piece; GC clip; GC outline; Drawable dest;
6966 /* Draw solid rectangle which will be clipped to shape of piece */
6967 // XFillRectangle(xDisplay, dest, clip,
6968 // 0, 0, squareSize, squareSize)
6970 if (appData.monoMode)
6971 /* Also draw outline in contrasting color for black
6972 on black / white on white cases */
6973 // XCopyPlane(xDisplay, *pieceToOutline(piece), dest, outline,
6974 // 0, 0, squareSize, squareSize, 0, 0, 1)
6977 /* Copy the piece */
6982 // XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
6984 // 0, 0, squareSize, squareSize,
6989 /* Animate the movement of a single piece */
6992 BeginAnimation(anim, piece, startColor, start)
7000 /* The old buffer is initialised with the start square (empty) */
7001 BlankSquare(0, 0, startColor, EmptySquare, anim->saveBuf);
7002 anim->prevFrame = *start;
7004 /* The piece will be drawn using its own bitmap as a matte */
7005 // SelectGCMask(piece, &anim->pieceGC, &anim->outlineGC, &mask);
7006 // XSetClipMask(xDisplay, anim->pieceGC, mask);
7010 AnimationFrame(anim, frame, piece)
7015 XRectangle updates[4];
7020 /* Save what we are about to draw into the new buffer */
7021 // XCopyArea(xDisplay, xBoardWindow, anim->newBuf, anim->blitGC,
7022 // frame->x, frame->y, squareSize, squareSize,
7025 /* Erase bits of the previous frame */
7026 if (Intersect(&anim->prevFrame, frame, squareSize, &overlap, &pt)) {
7027 /* Where the new frame overlapped the previous,
7028 the contents in newBuf are wrong. */
7029 // XCopyArea(xDisplay, anim->saveBuf, anim->newBuf, anim->blitGC,
7030 // overlap.x, overlap.y,
7031 // overlap.width, overlap.height,
7033 /* Repaint the areas in the old that don't overlap new */
7034 CalcUpdateRects(&anim->prevFrame, frame, squareSize, updates, &count);
7035 for (i = 0; i < count; i++)
7036 // XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
7037 // updates[i].x - anim->prevFrame.x,
7038 // updates[i].y - anim->prevFrame.y,
7039 // updates[i].width, updates[i].height,
7040 // updates[i].x, updates[i].y)
7043 /* Easy when no overlap */
7044 // XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
7045 // 0, 0, squareSize, squareSize,
7046 // anim->prevFrame.x, anim->prevFrame.y);
7049 /* Save this frame for next time round */
7050 // XCopyArea(xDisplay, anim->newBuf, anim->saveBuf, anim->blitGC,
7051 // 0, 0, squareSize, squareSize,
7053 anim->prevFrame = *frame;
7055 /* Draw piece over original screen contents, not current,
7056 and copy entire rect. Wipes out overlapping piece images. */
7057 OverlayPiece(piece, anim->pieceGC, anim->outlineGC, anim->newBuf);
7058 // XCopyArea(xDisplay, anim->newBuf, xBoardWindow, anim->blitGC,
7059 // 0, 0, squareSize, squareSize,
7060 // frame->x, frame->y);
7064 EndAnimation (anim, finish)
7068 XRectangle updates[4];
7073 /* The main code will redraw the final square, so we
7074 only need to erase the bits that don't overlap. */
7075 if (Intersect(&anim->prevFrame, finish, squareSize, &overlap, &pt)) {
7076 CalcUpdateRects(&anim->prevFrame, finish, squareSize, updates, &count);
7077 for (i = 0; i < count; i++)
7078 // XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
7079 // updates[i].x - anim->prevFrame.x,
7080 // updates[i].y - anim->prevFrame.y,
7081 // updates[i].width, updates[i].height,
7082 // updates[i].x, updates[i].y)
7085 // XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
7086 // 0, 0, squareSize, squareSize,
7087 // anim->prevFrame.x, anim->prevFrame.y);
7092 FrameSequence(anim, piece, startColor, start, finish, frames, nFrames)
7094 ChessSquare piece; int startColor;
7095 XPoint * start; XPoint * finish;
7096 XPoint frames[]; int nFrames;
7100 BeginAnimation(anim, piece, startColor, start);
7101 for (n = 0; n < nFrames; n++) {
7102 AnimationFrame(anim, &(frames[n]), piece);
7103 FrameDelay(appData.animSpeed);
7105 EndAnimation(anim, finish);
7108 /* Main control logic for deciding what to animate and how */
7111 AnimateMove(board, fromX, fromY, toX, toY)
7120 XPoint start, finish, mid;
7121 XPoint frames[kFactor * 2 + 1];
7122 int nFrames, startColor, endColor;
7124 /* Are we animating? */
7125 if (!appData.animate || appData.blindfold)
7128 if(board[toY][toX] == WhiteRook && board[fromY][fromX] == WhiteKing ||
7129 board[toY][toX] == BlackRook && board[fromY][fromX] == BlackKing)
7130 return; // [HGM] FRC: no animtion of FRC castlings, as to-square is not true to-square
7132 if (fromY < 0 || fromX < 0 || toX < 0 || toY < 0) return;
7133 piece = board[fromY][fromX];
7134 if (piece >= EmptySquare) return;
7139 hop = (piece == WhiteKnight || piece == BlackKnight);
7142 if (appData.debugMode) {
7143 fprintf(debugFP, hop ? _("AnimateMove: piece %d hops from %d,%d to %d,%d \n") :
7144 _("AnimateMove: piece %d slides from %d,%d to %d,%d \n"),
7145 piece, fromX, fromY, toX, toY); }
7147 ScreenSquare(fromX, fromY, &start, &startColor);
7148 ScreenSquare(toX, toY, &finish, &endColor);
7151 /* Knight: make diagonal movement then straight */
7152 if (abs(toY - fromY) < abs(toX - fromX)) {
7153 mid.x = start.x + (finish.x - start.x) / 2;
7157 mid.y = start.y + (finish.y - start.y) / 2;
7160 mid.x = start.x + (finish.x - start.x) / 2;
7161 mid.y = start.y + (finish.y - start.y) / 2;
7164 /* Don't use as many frames for very short moves */
7165 if (abs(toY - fromY) + abs(toX - fromX) <= 2)
7166 Tween(&start, &mid, &finish, kFactor - 1, frames, &nFrames);
7168 Tween(&start, &mid, &finish, kFactor, frames, &nFrames);
7169 FrameSequence(&game, piece, startColor, &start, &finish, frames, nFrames);
7171 /* Be sure end square is redrawn */
7172 damage[toY][toX] = True;
7176 DragPieceBegin(x, y)
7179 int boardX, boardY, color;
7182 /* Are we animating? */
7183 if (!appData.animateDragging || appData.blindfold)
7186 /* Figure out which square we start in and the
7187 mouse position relative to top left corner. */
7188 BoardSquare(x, y, &boardX, &boardY);
7189 player.startBoardX = boardX;
7190 player.startBoardY = boardY;
7191 ScreenSquare(boardX, boardY, &corner, &color);
7192 player.startSquare = corner;
7193 player.startColor = color;
7194 /* As soon as we start dragging, the piece will jump slightly to
7195 be centered over the mouse pointer. */
7196 player.mouseDelta.x = squareSize/2;
7197 player.mouseDelta.y = squareSize/2;
7198 /* Initialise animation */
7199 player.dragPiece = PieceForSquare(boardX, boardY);
7201 if (player.dragPiece >= 0 && player.dragPiece < EmptySquare) {
7202 player.dragActive = True;
7203 BeginAnimation(&player, player.dragPiece, color, &corner);
7204 /* Mark this square as needing to be redrawn. Note that
7205 we don't remove the piece though, since logically (ie
7206 as seen by opponent) the move hasn't been made yet. */
7207 if(boardX == BOARD_RGHT+1 && PieceForSquare(boardX-1, boardY) > 1 ||
7208 boardX == BOARD_LEFT-2 && PieceForSquare(boardX+1, boardY) > 1)
7209 // XCopyArea(xDisplay, xBoardWindow, player.saveBuf, player.blitGC,
7210 // corner.x, corner.y, squareSize, squareSize,
7211 // 0, 0); // [HGM] zh: unstack in stead of grab
7212 damage[boardY][boardX] = True;
7214 player.dragActive = False;
7224 /* Are we animating? */
7225 if (!appData.animateDragging || appData.blindfold)
7229 if (! player.dragActive)
7231 /* Move piece, maintaining same relative position
7232 of mouse within square */
7233 corner.x = x - player.mouseDelta.x;
7234 corner.y = y - player.mouseDelta.y;
7235 AnimationFrame(&player, &corner, player.dragPiece);
7237 if (appData.highlightDragging) {
7239 BoardSquare(x, y, &boardX, &boardY);
7240 SetHighlights(fromX, fromY, boardX, boardY);
7249 int boardX, boardY, color;
7252 /* Are we animating? */
7253 if (!appData.animateDragging || appData.blindfold)
7257 if (! player.dragActive)
7259 /* Last frame in sequence is square piece is
7260 placed on, which may not match mouse exactly. */
7261 BoardSquare(x, y, &boardX, &boardY);
7262 ScreenSquare(boardX, boardY, &corner, &color);
7263 EndAnimation(&player, &corner);
7265 /* Be sure end square is redrawn */
7266 damage[boardY][boardX] = True;
7268 /* This prevents weird things happening with fast successive
7269 clicks which on my Sun at least can cause motion events
7270 without corresponding press/release. */
7271 player.dragActive = False;
7274 /* Handle expose event while piece being dragged */
7279 if (!player.dragActive || appData.blindfold)
7282 /* What we're doing: logically, the move hasn't been made yet,
7283 so the piece is still in it's original square. But visually
7284 it's being dragged around the board. So we erase the square
7285 that the piece is on and draw it at the last known drag point. */
7286 BlankSquare(player.startSquare.x, player.startSquare.y,
7287 player.startColor, EmptySquare, xBoardWindow);
7288 AnimationFrame(&player, &player.prevFrame, player.dragPiece);
7289 damage[player.startBoardY][player.startBoardX] = TRUE;
7293 SetProgramStats( FrontEndProgramStats * stats )
7296 // [HGM] done, but perhaps backend should call this directly?
7297 EngineOutputUpdate( stats );
7300 #include <sys/ioctl.h>
7301 int get_term_width()
7303 int fd, default_width;
7306 default_width = 79; // this is FICS default anyway...
7308 #if !defined(TIOCGWINSZ) && defined(TIOCGSIZE)
7310 if (!ioctl(fd, TIOCGSIZE, &win))
7311 default_width = win.ts_cols;
7312 #elif defined(TIOCGWINSZ)
7314 if (!ioctl(fd, TIOCGWINSZ, &win))
7315 default_width = win.ws_col;
7317 return default_width;
7320 void update_ics_width()
7322 static int old_width = 0;
7323 int new_width = get_term_width();
7325 if (old_width != new_width)
7326 ics_printf("set width %d\n", new_width);
7327 old_width = new_width;
7330 void NotifyFrontendLogin()