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");
2186 /* EditTags window */
2187 GUI_EditTags = GTK_WIDGET (gtk_builder_get_object (builder, "EditTags"));
2188 if(!GUI_EditTags) printf("Error: gtk_builder didn't work!\n");
2190 GUI_EditTagsTextArea = GTK_WIDGET (gtk_builder_get_object (builder, "EditTagsTextArea"));
2191 if(!GUI_EditTagsTextArea) printf("Error: gtk_builder didn't work!\n");
2194 gtk_builder_connect_signals (builder, NULL);
2196 // don't unref the builder, since we use it to get references to widgets
2197 // g_object_unref (G_OBJECT (builder));
2199 /* end parse glade file */
2203 fprintf(stderr, _("%s: unrecognized argument %s\n"),
2204 programName, argv[1]);
2206 fprintf(stderr, "Recognized options:\n");
2207 for(i = 0; i < XtNumber(shellOptions); i++)
2209 /* print first column */
2210 j = fprintf(stderr, " %s%s", shellOptions[i].option,
2211 (shellOptions[i].argKind == XrmoptionSepArg
2213 /* print second column and end line */
2214 if (++i < XtNumber(shellOptions))
2216 fprintf(stderr, "%*c%s%s\n", 40 - j, ' ',
2217 shellOptions[i].option,
2218 (shellOptions[i].argKind == XrmoptionSepArg
2223 fprintf(stderr, "\n");
2230 if (p == NULL) p = "/tmp";
2231 i = strlen(p) + strlen("/.xboardXXXXXx.pgn") + 1;
2232 gameCopyFilename = (char*) malloc(i);
2233 gamePasteFilename = (char*) malloc(i);
2234 snprintf(gameCopyFilename,i, "%s/.xboard%05uc.pgn", p, getpid());
2235 snprintf(gamePasteFilename,i, "%s/.xboard%05up.pgn", p, getpid());
2237 XtGetApplicationResources(shellWidget, (XtPointer) &appData,
2238 clientResources, XtNumber(clientResources),
2241 { // [HGM] initstring: kludge to fix bad bug. expand '\n' characters in init string and computer string.
2242 static char buf[MSG_SIZ];
2243 EscapeExpand(buf, appData.initString);
2244 appData.initString = strdup(buf);
2245 EscapeExpand(buf, appData.secondInitString);
2246 appData.secondInitString = strdup(buf);
2247 EscapeExpand(buf, appData.firstComputerString);
2248 appData.firstComputerString = strdup(buf);
2249 EscapeExpand(buf, appData.secondComputerString);
2250 appData.secondComputerString = strdup(buf);
2253 if ((chessDir = (char *) getenv("CHESSDIR")) == NULL) {
2256 if (chdir(chessDir) != 0) {
2257 fprintf(stderr, _("%s: can't cd to CHESSDIR: "), programName);
2263 if (appData.debugMode && appData.nameOfDebugFile && strcmp(appData.nameOfDebugFile, "stderr")) {
2264 /* [DM] debug info to file [HGM] make the filename a command-line option, and allow it to remain stderr */
2265 if ((debugFP = fopen(appData.nameOfDebugFile, "w")) == NULL) {
2266 printf(_("Failed to open file '%s'\n"), appData.nameOfDebugFile);
2269 setbuf(debugFP, NULL);
2272 /* [HGM,HR] make sure board size is acceptable */
2273 if(appData.NrFiles > BOARD_SIZE ||
2274 appData.NrRanks > BOARD_SIZE )
2275 DisplayFatalError(_("Recompile with BOARD_SIZE > 12, to support this size"), 0, 2);
2278 /* This feature does not work; animation needs a rewrite */
2279 appData.highlightDragging = FALSE;
2283 xDisplay = XtDisplay(shellWidget);
2284 xScreen = DefaultScreen(xDisplay);
2285 wm_delete_window = XInternAtom(xDisplay, "WM_DELETE_WINDOW", True);
2287 gameInfo.variant = StringToVariant(appData.variant);
2288 InitPosition(FALSE);
2290 /* calc board size */
2291 if (isdigit(appData.boardSize[0]))
2293 i = sscanf(appData.boardSize, "%d,%d,%d,%d,%d,%d,%d", &squareSize,
2294 &lineGap, &clockFontPxlSize, &coordFontPxlSize,
2295 &fontPxlSize, &smallLayout, &tinyLayout);
2298 fprintf(stderr, _("%s: bad boardSize syntax %s\n"),
2299 programName, appData.boardSize);
2304 /* Find some defaults; use the nearest known size */
2305 SizeDefaults *szd, *nearest;
2306 int distance = 99999;
2307 nearest = szd = sizeDefaults;
2308 while (szd->name != NULL)
2310 if (abs(szd->squareSize - squareSize) < distance)
2313 distance = abs(szd->squareSize - squareSize);
2314 if (distance == 0) break;
2318 if (i < 2) lineGap = nearest->lineGap;
2319 if (i < 3) clockFontPxlSize = nearest->clockFontPxlSize;
2320 if (i < 4) coordFontPxlSize = nearest->coordFontPxlSize;
2321 if (i < 5) fontPxlSize = nearest->fontPxlSize;
2322 if (i < 6) smallLayout = nearest->smallLayout;
2323 if (i < 7) tinyLayout = nearest->tinyLayout;
2328 SizeDefaults *szd = sizeDefaults;
2329 if (*appData.boardSize == NULLCHAR)
2331 while (DisplayWidth(xDisplay, xScreen) < szd->minScreenSize
2332 || DisplayHeight(xDisplay, xScreen) < szd->minScreenSize)
2336 if (szd->name == NULL) szd--;
2340 while (szd->name != NULL
2341 && StrCaseCmp(szd->name, appData.boardSize) != 0)
2343 if (szd->name == NULL)
2345 fprintf(stderr, _("%s: unrecognized boardSize name %s\n"),
2346 programName, appData.boardSize);
2350 squareSize = szd->squareSize;
2351 lineGap = szd->lineGap;
2352 clockFontPxlSize = szd->clockFontPxlSize;
2353 coordFontPxlSize = szd->coordFontPxlSize;
2354 fontPxlSize = szd->fontPxlSize;
2355 smallLayout = szd->smallLayout;
2356 tinyLayout = szd->tinyLayout;
2358 /* end figuring out what size to use */
2360 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2361 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2364 * Determine what fonts to use.
2366 appData.clockFont = FindFont(appData.clockFont, clockFontPxlSize);
2367 clockFontID = XLoadFont(xDisplay, appData.clockFont);
2368 clockFontStruct = XQueryFont(xDisplay, clockFontID);
2369 appData.coordFont = FindFont(appData.coordFont, coordFontPxlSize);
2370 coordFontID = XLoadFont(xDisplay, appData.coordFont);
2371 coordFontStruct = XQueryFont(xDisplay, coordFontID);
2372 appData.font = FindFont(appData.font, fontPxlSize);
2373 countFontID = XLoadFont(xDisplay, appData.coordFont); // [HGM] holdings
2374 countFontStruct = XQueryFont(xDisplay, countFontID);
2375 // appData.font = FindFont(appData.font, fontPxlSize);
2377 xdb = XtDatabase(xDisplay);
2378 XrmPutStringResource(&xdb, "*font", appData.font);
2381 * Detect if there are not enough colors available and adapt.
2383 if (DefaultDepth(xDisplay, xScreen) <= 2) {
2384 appData.monoMode = True;
2387 if (!appData.monoMode) {
2388 vFrom.addr = (caddr_t) appData.lightSquareColor;
2389 vFrom.size = strlen(appData.lightSquareColor);
2390 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2391 if (vTo.addr == NULL) {
2392 appData.monoMode = True;
2395 lightSquareColor = *(Pixel *) vTo.addr;
2398 if (!appData.monoMode) {
2399 vFrom.addr = (caddr_t) appData.darkSquareColor;
2400 vFrom.size = strlen(appData.darkSquareColor);
2401 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2402 if (vTo.addr == NULL) {
2403 appData.monoMode = True;
2406 darkSquareColor = *(Pixel *) vTo.addr;
2409 if (!appData.monoMode) {
2410 vFrom.addr = (caddr_t) appData.whitePieceColor;
2411 vFrom.size = strlen(appData.whitePieceColor);
2412 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2413 if (vTo.addr == NULL) {
2414 appData.monoMode = True;
2417 whitePieceColor = *(Pixel *) vTo.addr;
2420 if (!appData.monoMode) {
2421 vFrom.addr = (caddr_t) appData.blackPieceColor;
2422 vFrom.size = strlen(appData.blackPieceColor);
2423 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2424 if (vTo.addr == NULL) {
2425 appData.monoMode = True;
2428 blackPieceColor = *(Pixel *) vTo.addr;
2432 if (!appData.monoMode) {
2433 vFrom.addr = (caddr_t) appData.highlightSquareColor;
2434 vFrom.size = strlen(appData.highlightSquareColor);
2435 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2436 if (vTo.addr == NULL) {
2437 appData.monoMode = True;
2440 highlightSquareColor = *(Pixel *) vTo.addr;
2444 if (!appData.monoMode) {
2445 vFrom.addr = (caddr_t) appData.premoveHighlightColor;
2446 vFrom.size = strlen(appData.premoveHighlightColor);
2447 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2448 if (vTo.addr == NULL) {
2449 appData.monoMode = True;
2452 premoveHighlightColor = *(Pixel *) vTo.addr;
2457 fprintf(stderr, _("%s: too few colors available; trying monochrome mode\n"),
2460 if (appData.bitmapDirectory == NULL ||
2461 appData.bitmapDirectory[0] == NULLCHAR)
2462 appData.bitmapDirectory = DEF_BITMAP_DIR;
2465 if (appData.lowTimeWarning && !appData.monoMode) {
2466 vFrom.addr = (caddr_t) appData.lowTimeWarningColor;
2467 vFrom.size = strlen(appData.lowTimeWarningColor);
2468 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2469 if (vTo.addr == NULL)
2470 appData.monoMode = True;
2472 lowTimeWarningColor = *(Pixel *) vTo.addr;
2475 if (appData.monoMode && appData.debugMode) {
2476 fprintf(stderr, _("white pixel = 0x%lx, black pixel = 0x%lx\n"),
2477 (unsigned long) XWhitePixel(xDisplay, xScreen),
2478 (unsigned long) XBlackPixel(xDisplay, xScreen));
2481 if (parse_cpair(ColorShout, appData.colorShout) < 0 ||
2482 parse_cpair(ColorSShout, appData.colorSShout) < 0 ||
2483 parse_cpair(ColorChannel1, appData.colorChannel1) < 0 ||
2484 parse_cpair(ColorChannel, appData.colorChannel) < 0 ||
2485 parse_cpair(ColorKibitz, appData.colorKibitz) < 0 ||
2486 parse_cpair(ColorTell, appData.colorTell) < 0 ||
2487 parse_cpair(ColorChallenge, appData.colorChallenge) < 0 ||
2488 parse_cpair(ColorRequest, appData.colorRequest) < 0 ||
2489 parse_cpair(ColorSeek, appData.colorSeek) < 0 ||
2490 parse_cpair(ColorNormal, appData.colorNormal) < 0)
2492 if (appData.colorize) {
2494 _("%s: can't parse color names; disabling colorization\n"),
2497 appData.colorize = FALSE;
2499 textColors[ColorNone].fg = textColors[ColorNone].bg = -1;
2500 textColors[ColorNone].attr = 0;
2502 // XtAppAddActions(appContext, boardActions, XtNumber(boardActions));
2508 layoutName = "tinyLayout";
2509 } else if (smallLayout) {
2510 layoutName = "smallLayout";
2512 layoutName = "normalLayout";
2515 if (appData.titleInWindow) {
2516 /* todo check what this appdata does */
2519 if (appData.showButtonBar) {
2520 /* TODO hide button bar if requested */
2524 if (appData.titleInWindow)
2529 if (appData.showButtonBar)
2536 if (appData.showButtonBar)
2546 /* set some checkboxes in the menu according to appData */
2548 if (appData.alwaysPromoteToQueen)
2549 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Always Queen")),TRUE);
2551 if (appData.animateDragging)
2552 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Animate Dragging")),TRUE);
2554 if (appData.animate)
2555 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Animate Moving")),TRUE);
2557 if (appData.autoComment)
2558 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Comment")),TRUE);
2560 if (appData.autoCallFlag)
2561 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Flag")),TRUE);
2563 if (appData.autoFlipView)
2564 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Flip View")),TRUE);
2566 if (appData.autoObserve)
2567 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Observe")),TRUE);
2569 if (appData.autoRaiseBoard)
2570 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Raise Board")),TRUE);
2572 if (appData.autoSaveGames)
2573 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Save")),TRUE);
2575 if (appData.saveGameFile[0] != NULLCHAR)
2577 /* Can't turn this off from menu */
2578 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Save")),TRUE);
2579 gtk_action_set_sensitive(GTK_ACTION (gtk_builder_get_object (builder, "menuOptions.Auto Save")),FALSE);
2582 if (appData.blindfold)
2583 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Blindfold")),TRUE);
2585 if (appData.flashCount > 0)
2586 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Flash Moves")),TRUE);
2588 if (appData.getMoveList)
2589 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Get Move List")),TRUE);
2592 if (appData.highlightDragging)
2593 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Highlight Dragging")),TRUE);
2596 if (appData.highlightLastMove)
2597 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Highlight Last Move")),TRUE);
2599 if (appData.icsAlarm)
2600 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.ICS Alarm")),TRUE);
2602 if (appData.ringBellAfterMoves)
2603 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Move Sound")),TRUE);
2605 if (appData.oldSaveStyle)
2606 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Old Save Style")),TRUE);
2608 if (appData.periodicUpdates)
2609 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Periodic Updates")),TRUE);
2611 if (appData.ponderNextMove)
2612 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Ponder Next Move")),TRUE);
2614 if (appData.popupExitMessage)
2615 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Popup Exit Message")),TRUE);
2617 if (appData.popupMoveErrors)
2618 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Popup Move Errors")),TRUE);
2620 if (appData.premove)
2621 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Premove")),TRUE);
2623 if (appData.quietPlay)
2624 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Quit Play")),TRUE);
2626 if (appData.showCoords)
2627 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Show Coords")),TRUE);
2629 if (appData.showThinking)
2630 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Show Thinking")),TRUE);
2632 if (appData.testLegality)
2633 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Test Legality")),TRUE);
2635 /* end setting check boxes */
2637 /* load square colors */
2638 SVGLightSquare = load_pixbuf("svg/LightSquare.svg",squareSize);
2639 SVGDarkSquare = load_pixbuf("svg/DarkSquare.svg",squareSize);
2640 SVGNeutralSquare = load_pixbuf("svg/NeutralSquare.svg",squareSize);
2642 /* use two icons to indicate if it is white's or black's turn */
2643 WhiteIcon = load_pixbuf("svg/icon_white.svg",0);
2644 BlackIcon = load_pixbuf("svg/icon_black.svg",0);
2645 WindowIcon = WhiteIcon;
2646 gtk_window_set_icon(GTK_WINDOW(GUI_Window),WindowIcon);
2649 /* realize window */
2650 gtk_widget_show (GUI_Window);
2652 /* recalc boardsize */
2657 if (appData.animate || appData.animateDragging)
2662 if (errorExitStatus == -1) {
2663 if (appData.icsActive) {
2664 /* We now wait until we see "login:" from the ICS before
2665 sending the logon script (problems with timestamp otherwise) */
2666 /*ICSInitScript();*/
2667 if (appData.icsInputBox) ICSInputBoxPopUp();
2670 signal(SIGINT, IntSigHandler);
2671 signal(SIGTERM, IntSigHandler);
2672 if (*appData.cmailGameName != NULLCHAR) {
2673 signal(SIGUSR1, CmailSigHandler);
2676 gameInfo.boardWidth = 0; // [HGM] pieces: kludge to ensure InitPosition() calls InitDrawingSizes()
2680 * Create a cursor for the board widget.
2681 * (This needs to be called after the window has been created to have access to board-window)
2684 BoardCursor = gdk_cursor_new(GDK_HAND2);
2685 gdk_window_set_cursor(GUI_Board->window, BoardCursor);
2686 gdk_cursor_destroy(BoardCursor);
2691 if (appData.debugMode) fclose(debugFP); // [DM] debug
2698 if (appData.icsActive && oldICSInteractionTitle != NULL) {
2699 DisplayIcsInteractionTitle(oldICSInteractionTitle);
2701 unlink(gameCopyFilename);
2702 unlink(gamePasteFilename);
2705 RETSIGTYPE TermSizeSigHandler(int sig)
2718 CmailSigHandler(sig)
2724 signal(SIGUSR1, SIG_IGN); /* suspend handler */
2726 /* Activate call-back function CmailSigHandlerCallBack() */
2727 OutputToProcess(cmailPR, (char *)(&dummy), sizeof(int), &error);
2729 signal(SIGUSR1, CmailSigHandler); /* re-activate handler */
2733 CmailSigHandlerCallBack(isr, closure, message, count, error)
2741 ReloadCmailMsgEvent(TRUE); /* Reload cmail msg */
2743 /**** end signal code ****/
2753 f = fopen(appData.icsLogon, "r");
2759 strcat(buf, appData.icsLogon);
2760 f = fopen(buf, "r");
2764 ProcessICSInitScript(f);
2771 EditCommentPopDown();
2777 SetMenuEnables(enab)
2782 if (!builder) return;
2783 while (enab->name != NULL) {
2784 o = gtk_builder_get_object(builder, enab->name);
2785 if(GTK_IS_WIDGET(o))
2786 gtk_widget_set_sensitive(GTK_WIDGET (o),enab->value);
2789 if(GTK_IS_ACTION(o))
2790 gtk_action_set_sensitive(GTK_ACTION (o),enab->value);
2792 DisplayError(enab->name, 0);
2800 SetMenuEnables(icsEnables);
2803 if (appData.zippyPlay && !appData.noChessProgram) /* [DM] icsEngineAnalyze */
2804 {}; // XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Analysis Mode"), True);
2811 SetMenuEnables(ncpEnables);
2817 SetMenuEnables(gnuEnables);
2823 SetMenuEnables(cmailEnables);
2829 SetMenuEnables(trainingOnEnables);
2830 if (appData.showButtonBar) {
2831 // XtSetSensitive(buttonBarWidget, False);
2837 SetTrainingModeOff()
2839 SetMenuEnables(trainingOffEnables);
2840 if (appData.showButtonBar) {
2841 // XtSetSensitive(buttonBarWidget, True);
2846 SetUserThinkingEnables()
2848 if (appData.noChessProgram) return;
2849 SetMenuEnables(userThinkingEnables);
2853 SetMachineThinkingEnables()
2855 if (appData.noChessProgram) return;
2856 SetMenuEnables(machineThinkingEnables);
2858 case MachinePlaysBlack:
2859 case MachinePlaysWhite:
2860 case TwoMachinesPlay:
2861 // XtSetSensitive(XtNameToWidget(menuBarWidget,
2862 // ModeToWidgetName(gameMode)), True);
2869 #define Abs(n) ((n)<0 ? -(n) : (n))
2872 * Find a font that matches "pattern" that is as close as
2873 * possible to the targetPxlSize. Prefer fonts that are k
2874 * pixels smaller to fonts that are k pixels larger. The
2875 * pattern must be in the X Consortium standard format,
2876 * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".
2877 * The return value should be freed with XtFree when no
2880 char *FindFont(pattern, targetPxlSize)
2884 char **fonts, *p, *best, *scalable, *scalableTail;
2885 int i, j, nfonts, minerr, err, pxlSize;
2888 char **missing_list;
2890 char *def_string, *base_fnt_lst, strInt[3];
2892 XFontStruct **fnt_list;
2894 base_fnt_lst = calloc(1, strlen(pattern) + 3);
2895 sprintf(strInt, "%d", targetPxlSize);
2896 p = strstr(pattern, "--");
2897 strncpy(base_fnt_lst, pattern, p - pattern + 2);
2898 strcat(base_fnt_lst, strInt);
2899 strcat(base_fnt_lst, strchr(p + 2, '-'));
2901 if ((fntSet = XCreateFontSet(xDisplay,
2905 &def_string)) == NULL) {
2907 fprintf(stderr, _("Unable to create font set.\n"));
2911 nfonts = XFontsOfFontSet(fntSet, &fnt_list, &fonts);
2913 fonts = XListFonts(xDisplay, pattern, 999999, &nfonts);
2915 fprintf(stderr, _("%s: no fonts match pattern %s\n"),
2916 programName, pattern);
2924 for (i=0; i<nfonts; i++) {
2927 if (*p != '-') continue;
2929 if (*p == NULLCHAR) break;
2930 if (*p++ == '-') j++;
2932 if (j < 7) continue;
2935 scalable = fonts[i];
2938 err = pxlSize - targetPxlSize;
2939 if (Abs(err) < Abs(minerr) ||
2940 (minerr > 0 && err < 0 && -err == minerr)) {
2946 if (scalable && Abs(minerr) > appData.fontSizeTolerance) {
2947 /* If the error is too big and there is a scalable font,
2948 use the scalable font. */
2949 int headlen = scalableTail - scalable;
2950 p = (char *) XtMalloc(strlen(scalable) + 10);
2951 while (isdigit(*scalableTail)) scalableTail++;
2952 sprintf(p, "%.*s%d%s", headlen, scalable, targetPxlSize, scalableTail);
2954 p = (char *) XtMalloc(strlen(best) + 1);
2957 if (appData.debugMode) {
2958 fprintf(debugFP, _("resolved %s at pixel size %d\n to %s\n"),
2959 pattern, targetPxlSize, p);
2962 if (missing_count > 0)
2963 XFreeStringList(missing_list);
2964 XFreeFontSet(xDisplay, fntSet);
2966 XFreeFontNames(fonts);
2973 /* 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*/
2975 XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
2976 | GCBackground | GCFunction | GCPlaneMask;
2977 XGCValues gc_values;
2980 gc_values.plane_mask = AllPlanes;
2981 gc_values.line_width = lineGap;
2982 gc_values.line_style = LineSolid;
2983 gc_values.function = GXcopy;
2985 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
2986 gc_values.background = XWhitePixel(xDisplay, xScreen);
2987 coordGC = XtGetGC(shellWidget, value_mask, &gc_values);
2988 XSetFont(xDisplay, coordGC, coordFontID);
2990 if (appData.monoMode) {
2991 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
2992 gc_values.background = XBlackPixel(xDisplay, xScreen);
2993 lightSquareGC = wbPieceGC
2994 = XtGetGC(shellWidget, value_mask, &gc_values);
2996 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
2997 gc_values.background = XWhitePixel(xDisplay, xScreen);
2998 darkSquareGC = bwPieceGC
2999 = XtGetGC(shellWidget, value_mask, &gc_values);
3001 if (DefaultDepth(xDisplay, xScreen) == 1) {
3002 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
3003 gc_values.function = GXcopyInverted;
3004 copyInvertedGC = XtGetGC(shellWidget, value_mask, &gc_values);
3005 gc_values.function = GXcopy;
3006 if (XBlackPixel(xDisplay, xScreen) == 1) {
3007 bwPieceGC = darkSquareGC;
3008 wbPieceGC = copyInvertedGC;
3010 bwPieceGC = copyInvertedGC;
3011 wbPieceGC = lightSquareGC;
3015 gc_values.foreground = lightSquareColor;
3016 gc_values.background = darkSquareColor;
3017 lightSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3019 gc_values.foreground = darkSquareColor;
3020 gc_values.background = lightSquareColor;
3021 darkSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3023 gc_values.foreground = jailSquareColor;
3024 gc_values.background = jailSquareColor;
3025 jailSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3027 gc_values.foreground = whitePieceColor;
3028 gc_values.background = darkSquareColor;
3029 wdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3031 gc_values.foreground = whitePieceColor;
3032 gc_values.background = lightSquareColor;
3033 wlPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3035 gc_values.foreground = whitePieceColor;
3036 gc_values.background = jailSquareColor;
3037 wjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3039 gc_values.foreground = blackPieceColor;
3040 gc_values.background = darkSquareColor;
3041 bdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3043 gc_values.foreground = blackPieceColor;
3044 gc_values.background = lightSquareColor;
3045 blPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3047 gc_values.foreground = blackPieceColor;
3048 gc_values.background = jailSquareColor;
3049 bjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3058 for(i=0;i<MAXPIECES;i++)
3062 g_free(SVGpieces[i]);
3069 SVGLightSquare = load_pixbuf("svg/LightSquare.svg",squareSize);
3070 SVGDarkSquare = load_pixbuf("svg/DarkSquare.svg",squareSize);
3071 SVGNeutralSquare = load_pixbuf("svg/NeutralSquare.svg",squareSize);
3074 /* get some defaults going */
3075 for(i=WhitePawn; i<DemotePiece+1; i++)
3076 SVGpieces[i] = load_pixbuf("svg/NeutralSquare.svg",squareSize);
3078 SVGpieces[WhitePawn] = load_pixbuf("svg/WhitePawn.svg",squareSize);
3079 SVGpieces[WhiteKnight] = load_pixbuf("svg/WhiteKnight.svg",squareSize);
3080 SVGpieces[WhiteBishop] = load_pixbuf("svg/WhiteBishop.svg",squareSize);
3081 SVGpieces[WhiteRook] = load_pixbuf("svg/WhiteRook.svg",squareSize);
3082 SVGpieces[WhiteQueen] = load_pixbuf("svg/WhiteQueen.svg",squareSize);
3083 SVGpieces[WhiteKing] = load_pixbuf("svg/WhiteKing.svg",squareSize);
3085 SVGpieces[BlackPawn] = load_pixbuf("svg/BlackPawn.svg",squareSize);
3086 SVGpieces[BlackKnight] = load_pixbuf("svg/BlackKnight.svg",squareSize);
3087 SVGpieces[BlackBishop] = load_pixbuf("svg/BlackBishop.svg",squareSize);
3088 SVGpieces[BlackRook] = load_pixbuf("svg/BlackRook.svg",squareSize);
3089 SVGpieces[BlackQueen] = load_pixbuf("svg/BlackQueen.svg",squareSize);
3090 SVGpieces[BlackKing] = load_pixbuf("svg/BlackKing.svg",squareSize);
3096 static void MenuBarSelect(w, addr, index)
3101 XtActionProc proc = (XtActionProc) addr;
3103 (proc)(NULL, NULL, NULL, NULL);
3106 void CreateMenuBarPopup(parent, name, mb)
3116 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3119 XtSetArg(args[j], XtNleftMargin, 20); j++;
3120 XtSetArg(args[j], XtNrightMargin, 20); j++;
3122 while (mi->string != NULL) {
3123 if (strcmp(mi->string, "----") == 0) {
3124 entry = XtCreateManagedWidget(mi->string, smeLineObjectClass,
3127 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string)));
3128 entry = XtCreateManagedWidget(mi->string, smeBSBObjectClass,
3130 XtAddCallback(entry, XtNcallback,
3131 (XtCallbackProc) MenuBarSelect,
3132 (caddr_t) mi->proc);
3138 Widget CreateMenuBar(mb)
3142 Widget anchor, menuBar;
3144 char menuName[MSG_SIZ];
3147 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
3148 XtSetArg(args[j], XtNvSpace, 0); j++;
3149 XtSetArg(args[j], XtNborderWidth, 0); j++;
3150 menuBar = XtCreateWidget("menuBar", boxWidgetClass,
3151 formWidget, args, j);
3153 while (mb->name != NULL) {
3154 strcpy(menuName, "menu");
3155 strcat(menuName, mb->name);
3157 XtSetArg(args[j], XtNmenuName, XtNewString(menuName)); j++;
3160 shortName[0] = _(mb->name)[0];
3161 shortName[1] = NULLCHAR;
3162 XtSetArg(args[j], XtNlabel, XtNewString(shortName)); j++;
3165 XtSetArg(args[j], XtNlabel, XtNewString(_(mb->name))); j++;
3168 XtSetArg(args[j], XtNborderWidth, 0); j++;
3169 anchor = XtCreateManagedWidget(mb->name, menuButtonWidgetClass,
3171 CreateMenuBarPopup(menuBar, menuName, mb);
3179 CreatePieceMenu(name, color)
3186 ChessSquare selection;
3188 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3189 boardWidget, args, 0);
3191 for (i = 0; i < PIECE_MENU_SIZE; i++) {
3192 String item = pieceMenuStrings[color][i];
3194 if (strcmp(item, "----") == 0) {
3195 entry = XtCreateManagedWidget(item, smeLineObjectClass,
3198 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
3199 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3201 selection = pieceMenuTranslation[color][i];
3202 XtAddCallback(entry, XtNcallback,
3203 (XtCallbackProc) PieceMenuSelect,
3204 (caddr_t) selection);
3205 if (selection == WhitePawn || selection == BlackPawn) {
3206 XtSetArg(args[0], XtNpopupOnEntry, entry);
3207 XtSetValues(menu, args, 1);
3220 ChessSquare selection;
3222 // whitePieceMenu = CreatePieceMenu("menuW", 0);
3223 // blackPieceMenu = CreatePieceMenu("menuB", 1);
3225 // XtRegisterGrabAction(PieceMenuPopup, True,
3226 // (unsigned)(ButtonPressMask|ButtonReleaseMask),
3227 // GrabModeAsync, GrabModeAsync);
3229 // XtSetArg(args[0], XtNlabel, _("Drop"));
3230 // dropMenu = XtCreatePopupShell("menuD", simpleMenuWidgetClass,
3231 // boardWidget, args, 1);
3232 // for (i = 0; i < DROP_MENU_SIZE; i++) {
3233 // String item = dropMenuStrings[i];
3235 // if (strcmp(item, "----") == 0) {
3236 // entry = XtCreateManagedWidget(item, smeLineObjectClass,
3237 // dropMenu, NULL, 0);
3239 // XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
3240 // entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3241 // dropMenu, args, 1);
3242 // selection = dropMenuTranslation[i];
3243 // XtAddCallback(entry, XtNcallback,
3244 // (XtCallbackProc) DropMenuSelect,
3245 // (caddr_t) selection);
3250 void SetupDropMenu()
3258 for (i=0; i<sizeof(dmEnables)/sizeof(DropMenuEnables); i++) {
3259 entry = XtNameToWidget(dropMenu, dmEnables[i].widget);
3260 p = strchr(gameMode == IcsPlayingWhite ? white_holding : black_holding,
3261 dmEnables[i].piece);
3262 XtSetSensitive(entry, p != NULL || !appData.testLegality
3263 /*!!temp:*/ || (gameInfo.variant == VariantCrazyhouse
3264 && !appData.icsActive));
3266 while (p && *p++ == dmEnables[i].piece) count++;
3267 snprintf(label, sizeof(label), "%s %d", dmEnables[i].widget, count);
3269 XtSetArg(args[j], XtNlabel, label); j++;
3270 XtSetValues(entry, args, j);
3274 void PieceMenuPopup(w, event, params, num_params)
3278 Cardinal *num_params;
3281 if (event->type != ButtonPress) return;
3282 if (errorUp) ErrorPopDown();
3286 whichMenu = params[0];
3288 case IcsPlayingWhite:
3289 case IcsPlayingBlack:
3291 case MachinePlaysWhite:
3292 case MachinePlaysBlack:
3293 if (appData.testLegality &&
3294 gameInfo.variant != VariantBughouse &&
3295 gameInfo.variant != VariantCrazyhouse) return;
3297 whichMenu = "menuD";
3303 if (((pmFromX = EventToSquare(event->xbutton.x, BOARD_WIDTH)) < 0) ||
3304 ((pmFromY = EventToSquare(event->xbutton.y, BOARD_HEIGHT)) < 0)) {
3305 pmFromX = pmFromY = -1;
3309 pmFromX = BOARD_WIDTH - 1 - pmFromX;
3311 pmFromY = BOARD_HEIGHT - 1 - pmFromY;
3313 XtPopupSpringLoaded(XtNameToWidget(boardWidget, whichMenu));
3316 static void PieceMenuSelect(w, piece, junk)
3321 if (pmFromX < 0 || pmFromY < 0) return;
3322 EditPositionMenuEvent(piece, pmFromX, pmFromY);
3325 static void DropMenuSelect(w, piece, junk)
3330 if (pmFromX < 0 || pmFromY < 0) return;
3331 DropMenuEvent(piece, pmFromX, pmFromY);
3335 * If the user selects on a border boundary, return -1; if off the board,
3336 * return -2. Otherwise map the event coordinate to the square.
3338 int EventToSquare(x, limit)
3346 if ((x % (squareSize + lineGap)) >= squareSize)
3348 x /= (squareSize + lineGap);
3354 static void do_flash_delay(msec)
3360 static void drawHighlight(file, rank, line_type)
3361 int file, rank, line_type;
3366 if (lineGap == 0 || appData.blindfold) return;
3370 x = lineGap/2 + ((BOARD_WIDTH-1)-file) *
3371 (squareSize + lineGap);
3372 y = lineGap/2 + rank * (squareSize + lineGap);
3376 x = lineGap/2 + file * (squareSize + lineGap);
3377 y = lineGap/2 + ((BOARD_HEIGHT-1)-rank) *
3378 (squareSize + lineGap);
3382 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
3384 /* draw the highlight */
3385 cairo_move_to (cr, x, y);
3386 cairo_rel_line_to (cr, 0,squareSize+lineGap);
3387 cairo_rel_line_to (cr, squareSize+lineGap,0);
3388 cairo_rel_line_to (cr, 0,-squareSize-lineGap);
3389 cairo_close_path (cr);
3391 cairo_set_line_width (cr, lineGap);
3394 /* TODO: use appdata colors */
3395 case LINE_TYPE_HIGHLIGHT:
3396 cairo_set_source_rgba (cr, 1, 1, 0, 1.0);
3399 cairo_set_source_rgba (cr, 1, 0, 0, 1.0);
3401 case LINE_TYPE_NORMAL:
3403 cairo_set_source_rgba (cr, 0, 1, 0, 1.0);
3414 int hi1X = -1, hi1Y = -1, hi2X = -1, hi2Y = -1;
3415 int pm1X = -1, pm1Y = -1, pm2X = -1, pm2Y = -1;
3418 SetHighlights(fromX, fromY, toX, toY)
3419 int fromX, fromY, toX, toY;
3421 if (hi1X != fromX || hi1Y != fromY)
3423 if (hi1X >= 0 && hi1Y >= 0)
3425 drawHighlight(hi1X, hi1Y, LINE_TYPE_NORMAL);
3427 if (fromX >= 0 && fromY >= 0)
3429 drawHighlight(fromX, fromY, LINE_TYPE_HIGHLIGHT);
3432 if (hi2X != toX || hi2Y != toY)
3434 if (hi2X >= 0 && hi2Y >= 0)
3436 drawHighlight(hi2X, hi2Y, LINE_TYPE_NORMAL);
3438 if (toX >= 0 && toY >= 0)
3440 drawHighlight(toX, toY, LINE_TYPE_HIGHLIGHT);
3454 SetHighlights(-1, -1, -1, -1);
3459 SetPremoveHighlights(fromX, fromY, toX, toY)
3460 int fromX, fromY, toX, toY;
3462 if (pm1X != fromX || pm1Y != fromY)
3464 if (pm1X >= 0 && pm1Y >= 0)
3466 drawHighlight(pm1X, pm1Y, LINE_TYPE_NORMAL);
3468 if (fromX >= 0 && fromY >= 0)
3470 drawHighlight(fromX, fromY, LINE_TYPE_PRE);
3473 if (pm2X != toX || pm2Y != toY)
3475 if (pm2X >= 0 && pm2Y >= 0)
3477 drawHighlight(pm2X, pm2Y, LINE_TYPE_NORMAL);
3479 if (toX >= 0 && toY >= 0)
3481 drawHighlight(toX, toY, LINE_TYPE_PRE);
3494 ClearPremoveHighlights()
3496 SetPremoveHighlights(-1, -1, -1, -1);
3499 static void BlankSquare(x, y, color, piece, dest)
3512 pb = SVGLightSquare;
3514 case 2: /* neutral */
3516 pb = SVGNeutralSquare;
3519 gdk_draw_pixbuf(GDK_WINDOW(GUI_Board->window),NULL,pb,0,0,x,y,-1,-1, GDK_RGB_DITHER_NORMAL, 0, 0);
3523 static void DrawPiece(piece, square_color, x, y, dest)
3525 int square_color, x, y;
3528 /* redraw background, since piece might be transparent in some areas */
3529 BlankSquare(x,y,square_color,piece,dest);
3532 gdk_draw_pixbuf(GDK_WINDOW(GUI_Board->window),NULL,
3533 GDK_PIXBUF(SVGpieces[piece]),0,0,x,y,-1,-1,
3534 GDK_RGB_DITHER_NORMAL, 0, 0);
3538 /* [HR] determine square color depending on chess variant. */
3539 static int SquareColor(row, column)
3544 if (gameInfo.variant == VariantXiangqi) {
3545 if (column >= 3 && column <= 5 && row >= 0 && row <= 2) {
3547 } else if (column >= 3 && column <= 5 && row >= 7 && row <= 9) {
3549 } else if (row <= 4) {
3555 square_color = ((column + row) % 2) == 1;
3558 /* [hgm] holdings: next line makes all holdings squares light */
3559 if(column < BOARD_LEFT || column >= BOARD_RGHT) square_color = 1;
3561 return square_color;
3564 void DrawSquare(row, column, piece, do_flash)
3565 int row, column, do_flash;
3568 int square_color, x, y;
3573 /* Calculate delay in milliseconds (2-delays per complete flash) */
3574 flash_delay = 500 / appData.flashRate;
3576 /* calculate x and y coordinates from row and column */
3579 x = lineGap + ((BOARD_WIDTH-1)-column) *
3580 (squareSize + lineGap);
3581 y = lineGap + row * (squareSize + lineGap);
3585 x = lineGap + column * (squareSize + lineGap);
3586 y = lineGap + ((BOARD_HEIGHT-1)-row) *
3587 (squareSize + lineGap);
3590 square_color = SquareColor(row, column);
3592 // [HGM] holdings: blank out area between board and holdings
3593 if ( column == BOARD_LEFT-1 || column == BOARD_RGHT
3594 || (column == BOARD_LEFT-2 && row < BOARD_HEIGHT-gameInfo.holdingsSize)
3595 || (column == BOARD_RGHT+1 && row >= gameInfo.holdingsSize) )
3597 BlankSquare(x, y, 2, EmptySquare, xBoardWindow);
3599 // [HGM] print piece counts next to holdings
3600 string[1] = NULLCHAR;
3603 cairo_text_extents_t extents;
3608 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
3610 string[0] = '0' + piece;
3612 /* TODO this has to go into the font-selection */
3613 cairo_select_font_face (cr, "Sans",
3614 CAIRO_FONT_SLANT_NORMAL,
3615 CAIRO_FONT_WEIGHT_NORMAL);
3617 cairo_set_font_size (cr, 12.0);
3618 cairo_text_extents (cr, string, &extents);
3620 if (column == (flipView ? BOARD_LEFT-1 : BOARD_RGHT) )
3622 xpos= x + squareSize - extents.width - 2;
3623 ypos= y + extents.y_bearing + 1;
3625 if (column == (flipView ? BOARD_RGHT : BOARD_LEFT-1) && piece > 1)
3628 ypos = y + extents.y_bearing + 1;
3631 /* TODO mono mode? */
3632 cairo_move_to (cr, xpos, ypos);
3633 cairo_text_path (cr, string);
3634 cairo_set_source_rgb (cr, 1.0, 1.0, 1);
3635 cairo_fill_preserve (cr);
3636 cairo_set_source_rgb (cr, 0, 0, 0);
3637 cairo_set_line_width (cr, 0.1);
3646 /* square on the board */
3647 if (piece == EmptySquare || appData.blindfold)
3649 BlankSquare(x, y, square_color, piece, xBoardWindow);
3653 if (do_flash && appData.flashCount > 0)
3655 for (i=0; i<appData.flashCount; ++i)
3658 DrawPiece(piece, square_color, x, y, xBoardWindow);
3659 do_flash_delay(flash_delay);
3661 BlankSquare(x, y, square_color, piece, xBoardWindow);
3662 do_flash_delay(flash_delay);
3665 DrawPiece(piece, square_color, x, y, xBoardWindow);
3669 /* show coordinates if necessary */
3670 if(appData.showCoords)
3672 cairo_text_extents_t extents;
3676 /* TODO this has to go into the font-selection */
3677 cairo_select_font_face (cr, "Sans",
3678 CAIRO_FONT_SLANT_NORMAL,
3679 CAIRO_FONT_WEIGHT_NORMAL);
3680 cairo_set_font_size (cr, 12.0);
3682 string[1] = NULLCHAR;
3685 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
3687 if (row == (flipView ? BOARD_HEIGHT-1 : 0) &&
3688 column >= BOARD_LEFT && column < BOARD_RGHT)
3690 string[0] = 'a' + column - BOARD_LEFT;
3691 cairo_text_extents (cr, string, &extents);
3693 xpos = x + squareSize - extents.width - 2;
3694 ypos = y + squareSize - extents.height - extents.y_bearing - 1;
3696 if (appData.monoMode)
3703 cairo_move_to (cr, xpos, ypos);
3704 cairo_text_path (cr, string);
3705 cairo_set_source_rgb (cr, 0.0, 0.0, 0);
3706 cairo_fill_preserve (cr);
3707 cairo_set_source_rgb (cr, 0, 1.0, 0);
3708 cairo_set_line_width (cr, 0.1);
3711 if ( column == (flipView ? BOARD_RGHT-1 : BOARD_LEFT))
3714 string[0] = ONE + row;
3715 cairo_text_extents (cr, string, &extents);
3718 ypos = y + extents.height + 1;
3720 if (appData.monoMode)
3727 cairo_move_to (cr, xpos, ypos);
3728 cairo_text_path (cr, string);
3729 cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
3730 cairo_fill_preserve (cr);
3731 cairo_set_source_rgb (cr, 0, 0, 1.0);
3732 cairo_set_line_width (cr, 0.1);
3744 /* Returns 1 if there are "too many" differences between b1 and b2
3745 (i.e. more than 1 move was made) */
3746 static int too_many_diffs(b1, b2)
3752 for (i=0; i<BOARD_HEIGHT; ++i) {
3753 for (j=0; j<BOARD_WIDTH; ++j) {
3754 if (b1[i][j] != b2[i][j]) {
3755 if (++c > 4) /* Castling causes 4 diffs */
3764 /* Matrix describing castling maneuvers */
3765 /* Row, ColRookFrom, ColKingFrom, ColRookTo, ColKingTo */
3766 static int castling_matrix[4][5] = {
3767 { 0, 0, 4, 3, 2 }, /* 0-0-0, white */
3768 { 0, 7, 4, 5, 6 }, /* 0-0, white */
3769 { 7, 0, 4, 3, 2 }, /* 0-0-0, black */
3770 { 7, 7, 4, 5, 6 } /* 0-0, black */
3773 /* Checks whether castling occurred. If it did, *rrow and *rcol
3774 are set to the destination (row,col) of the rook that moved.
3776 Returns 1 if castling occurred, 0 if not.
3778 Note: Only handles a max of 1 castling move, so be sure
3779 to call too_many_diffs() first.
3781 static int check_castle_draw(newb, oldb, rrow, rcol)
3788 /* For each type of castling... */
3789 for (i=0; i<4; ++i) {
3790 r = castling_matrix[i];
3792 /* Check the 4 squares involved in the castling move */
3794 for (j=1; j<=4; ++j) {
3795 if (newb[r[0]][r[j]] == oldb[r[0]][r[j]]) {
3802 /* All 4 changed, so it must be a castling move */
3811 static int damage[BOARD_SIZE][BOARD_SIZE];
3814 * event handler for redrawing the board
3816 void DrawPosition( repaint, board)
3817 /*Boolean*/int repaint;
3821 static int lastFlipView = 0;
3822 static int lastBoardValid = 0;
3823 static Board lastBoard;
3826 if (board == NULL) {
3827 if (!lastBoardValid) return;
3830 if (!lastBoardValid || lastFlipView != flipView) {
3831 // XtSetArg(args[0], XtNleftBitmap, (flipView ? xMarkPixmap : None));
3832 // XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flip View"),
3837 * It would be simpler to clear the window with XClearWindow()
3838 * but this causes a very distracting flicker.
3841 if (!repaint && lastBoardValid && lastFlipView == flipView)
3843 /* If too much changes (begin observing new game, etc.), don't
3845 do_flash = too_many_diffs(board, lastBoard) ? 0 : 1;
3847 /* Special check for castling so we don't flash both the king
3848 and the rook (just flash the king). */
3851 if (check_castle_draw(board, lastBoard, &rrow, &rcol))
3853 /* Draw rook with NO flashing. King will be drawn flashing later */
3854 DrawSquare(rrow, rcol, board[rrow][rcol], 0);
3855 lastBoard[rrow][rcol] = board[rrow][rcol];
3859 /* First pass -- Draw (newly) empty squares and repair damage.
3860 This prevents you from having a piece show up twice while it
3861 is flashing on its new square */
3862 for (i = 0; i < BOARD_HEIGHT; i++)
3863 for (j = 0; j < BOARD_WIDTH; j++)
3864 if ((board[i][j] != lastBoard[i][j] && board[i][j] == EmptySquare)
3867 DrawSquare(i, j, board[i][j], 0);
3868 damage[i][j] = False;
3871 /* Second pass -- Draw piece(s) in new position and flash them */
3872 for (i = 0; i < BOARD_HEIGHT; i++)
3873 for (j = 0; j < BOARD_WIDTH; j++)
3874 if (board[i][j] != lastBoard[i][j])
3876 DrawSquare(i, j, board[i][j], do_flash);
3888 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
3890 cairo_set_line_width (cr, lineGap);
3892 /* TODO: use appdata colors */
3893 cairo_set_source_rgba (cr, 0, 1, 0, 1.0);
3897 for (i = 0; i < BOARD_HEIGHT + 1; i++)
3900 x2 = lineGap + BOARD_WIDTH * (squareSize + lineGap);
3901 y1 = y2 = lineGap / 2 + (i * (squareSize + lineGap));
3903 cairo_move_to (cr, x1, y1);
3904 cairo_rel_line_to (cr, x2,0);
3908 for (j = 0; j < BOARD_WIDTH + 1; j++)
3911 y2 = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
3912 x1 = x2 = lineGap / 2 + (j * (squareSize + lineGap));
3914 cairo_move_to (cr, x1, y1);
3915 cairo_rel_line_to (cr, 0, y2);
3924 for (i = 0; i < BOARD_HEIGHT; i++)
3925 for (j = 0; j < BOARD_WIDTH; j++)
3927 DrawSquare(i, j, board[i][j], 0);
3928 damage[i][j] = False;
3932 CopyBoard(lastBoard, board);
3934 lastFlipView = flipView;
3936 /* Draw highlights */
3937 if (pm1X >= 0 && pm1Y >= 0)
3939 drawHighlight(pm1X, pm1Y, LINE_TYPE_PRE);
3941 if (pm2X >= 0 && pm2Y >= 0)
3943 drawHighlight(pm2X, pm2Y, LINE_TYPE_PRE);
3945 if (hi1X >= 0 && hi1Y >= 0)
3947 drawHighlight(hi1X, hi1Y, LINE_TYPE_HIGHLIGHT);
3949 if (hi2X >= 0 && hi2Y >= 0)
3951 drawHighlight(hi2X, hi2Y, LINE_TYPE_HIGHLIGHT);
3954 /* If piece being dragged around board, must redraw that too */
3961 * event handler for parsing user moves
3963 // [HGM] This routine will need quite some reworking. Although the backend still supports the old
3964 // way of doing things, by calling UserMoveEvent() to test the legality of the move and then perform
3965 // it at the end, and doing all kind of preliminary tests here (e.g. to weed out self-captures), it
3966 // should be made to use the new way, of calling UserMoveTest early to determine the legality of the
3967 // move, (which will weed out the illegal selfcaptures and moves into the holdings, and flag promotions),
3968 // and at the end FinishMove() to perform the move after optional promotion popups.
3969 // For now I patched it to allow self-capture with King, and suppress clicks between board and holdings.
3970 void HandleUserMove(w, event, prms, nprms)
3977 Boolean saveAnimate;
3978 static int second = 0, promotionChoice = 0;
3981 if (w != boardWidget || errorExitStatus != -1) return;
3983 x = EventToSquare(event->xbutton.x, BOARD_WIDTH);
3984 y = EventToSquare(event->xbutton.y, BOARD_HEIGHT);
3985 if (!flipView && y >= 0) {
3986 y = BOARD_HEIGHT - 1 - y;
3988 if (flipView && x >= 0) {
3989 x = BOARD_WIDTH - 1 - x;
3992 if(promotionChoice) { // we are waiting for a click to indicate promotion piece
3993 if(event->type == ButtonRelease) return; // ignore upclick of click-click destination
3994 promotionChoice = FALSE; // only one chance: if click not OK it is interpreted as cancel
3995 if(appData.debugMode) fprintf(debugFP, "promotion click, x=%d, y=%d\n", x, y);
3996 if(gameInfo.holdingsWidth &&
3997 (WhiteOnMove(currentMove)
3998 ? x == BOARD_WIDTH-1 && y < gameInfo.holdingsSize && y > 0
3999 : x == 0 && y >= BOARD_HEIGHT - gameInfo.holdingsSize && y < BOARD_HEIGHT-1) ) {
4000 // click in right holdings, for determining promotion piece
4001 ChessSquare p = boards[currentMove][y][x];
4002 if(appData.debugMode) fprintf(debugFP, "square contains %d\n", (int)p);
4003 if(p != EmptySquare) {
4004 FinishMove(NormalMove, fromX, fromY, toX, toY, ToLower(PieceToChar(p)));
4009 DrawPosition(FALSE, boards[currentMove]);
4012 if (event->type == ButtonPress) ErrorPopDown();
4015 if (event->type == ButtonPress) {
4016 // XtPopdown(promotionShell);
4017 // XtDestroyWidget(promotionShell);
4018 promotionUp = False;
4026 /* [HGM] holdings: next 5 lines: ignore all clicks between board and holdings */
4027 if(event->type == ButtonPress
4028 && ( x == BOARD_LEFT-1 ||
4030 (x == BOARD_LEFT-2 && y < BOARD_HEIGHT-gameInfo.holdingsSize ) ||
4031 (x == BOARD_RGHT+1 && y >= gameInfo.holdingsSize)) )
4035 if (event->type == ButtonPress) {
4036 /* First square, prepare to drag */
4037 if (OKToStartUserMove(x, y)) {
4041 DragPieceBegin(event->xbutton.x, event->xbutton.y);
4042 if (appData.highlightDragging) {
4043 SetHighlights(x, y, -1, -1);
4051 if (event->type == ButtonRelease && x == fromX && y == fromY) {
4052 /* Click on single square in stead of drag-drop */
4053 DragPieceEnd(event->xbutton.x, event->xbutton.y);
4054 if (appData.animateDragging) {
4055 /* Undo animation damage if any */
4056 DrawPosition(FALSE, NULL);
4059 /* Second up/down in same square; just abort move */
4064 ClearPremoveHighlights();
4066 /* First upclick in same square; start click-click mode */
4067 SetHighlights(x, y, -1, -1);
4072 moveType = UserMoveTest(fromX, fromY, x, y, NULLCHAR, event->type == ButtonRelease);
4074 if (moveType == Comment) { // kludge for indicating capture-own on Press
4075 /* Clicked again on same color piece -- changed his mind */
4076 /* note that re-clicking same square always hits same color piece */
4077 second = (x == fromX && y == fromY);
4078 if (appData.highlightDragging) {
4079 SetHighlights(x, y, -1, -1);
4083 if (OKToStartUserMove(x, y)) {
4086 DragPieceBegin(event->xbutton.x, event->xbutton.y);
4091 if(moveType == AmbiguousMove) { // kludge to indicate edit-position move
4094 DragPieceEnd(event->xbutton.x, event->xbutton.y);
4095 DrawPosition(FALSE, boards[currentMove]);
4099 /* Complete move; (x,y) is now different from (fromX, fromY) on both Press and Release */
4102 saveAnimate = appData.animate;
4103 if (event->type == ButtonPress) {
4104 /* Finish clickclick move */
4105 if (appData.animate || appData.highlightLastMove) {
4106 SetHighlights(fromX, fromY, toX, toY);
4111 /* Finish drag move */
4112 if (appData.highlightLastMove) {
4113 SetHighlights(fromX, fromY, toX, toY);
4117 DragPieceEnd(event->xbutton.x, event->xbutton.y);
4118 /* Don't animate move and drag both */
4119 appData.animate = FALSE;
4121 if (moveType == WhitePromotionKnight || moveType == BlackPromotionKnight ||
4122 (moveType == WhitePromotionQueen || moveType == BlackPromotionQueen) &&
4123 appData.alwaysPromoteToQueen) { // promotion, but no choice
4124 FinishMove(moveType, fromX, fromY, toX, toY, 'q');
4126 if (moveType == WhitePromotionQueen || moveType == BlackPromotionQueen ) {
4127 SetHighlights(fromX, fromY, toX, toY);
4128 if(gameInfo.variant == VariantSuper || gameInfo.variant == VariantGreat) {
4129 // [HGM] super: promotion to captured piece selected from holdings
4130 ChessSquare p = boards[currentMove][fromY][fromX], q = boards[currentMove][toY][toX];
4131 promotionChoice = TRUE;
4132 // kludge follows to temporarily execute move on display, without promoting yet
4133 boards[currentMove][fromY][fromX] = EmptySquare; // move Pawn to 8th rank
4134 boards[currentMove][toY][toX] = p;
4135 DrawPosition(FALSE, boards[currentMove]);
4136 boards[currentMove][fromY][fromX] = p; // take back, but display stays
4137 boards[currentMove][toY][toX] = q;
4138 DisplayMessage("Click in holdings to choose piece", "");
4142 goto skipClearingFrom; // the skipped stuff is done asynchronously by PromotionCallback
4144 if(moveType != ImpossibleMove) { // valid move, but no promotion
4145 FinishMove(moveType, fromX, fromY, toX, toY, NULLCHAR);
4146 } else { // invalid move; could have set premove
4149 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
4150 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
4153 appData.animate = saveAnimate;
4154 if (appData.animate || appData.animateDragging) {
4155 /* Undo animation damage if needed */
4156 DrawPosition(FALSE, NULL);
4160 void AnimateUserMove (Widget w, XEvent * event,
4161 String * params, Cardinal * nParams)
4163 DragPieceMove(event->xmotion.x, event->xmotion.y);
4166 Widget CommentCreate(name, text, mutable, callback, lines)
4168 int /*Boolean*/ mutable;
4169 XtCallbackProc callback;
4173 Widget shell, layout, form, edit, b_ok, b_cancel, b_clear, b_close, b_edit;
4178 XtSetArg(args[j], XtNwidth, &bw_width); j++;
4179 XtGetValues(boardWidget, args, j);
4182 XtSetArg(args[j], XtNresizable, True); j++;
4185 XtCreatePopupShell(name, topLevelShellWidgetClass,
4186 shellWidget, args, j);
4189 XtCreatePopupShell(name, transientShellWidgetClass,
4190 shellWidget, args, j);
4193 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
4194 layoutArgs, XtNumber(layoutArgs));
4196 XtCreateManagedWidget("form", formWidgetClass, layout,
4197 formArgs, XtNumber(formArgs));
4201 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
4202 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
4204 XtSetArg(args[j], XtNstring, text); j++;
4205 XtSetArg(args[j], XtNtop, XtChainTop); j++;
4206 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4207 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4208 XtSetArg(args[j], XtNright, XtChainRight); j++;
4209 XtSetArg(args[j], XtNresizable, True); j++;
4210 XtSetArg(args[j], XtNwidth, bw_width); j++; /*force wider than buttons*/
4211 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
4212 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
4213 XtSetArg(args[j], XtNautoFill, True); j++;
4214 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
4216 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
4220 XtSetArg(args[j], XtNfromVert, edit); j++;
4221 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4222 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4223 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4224 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4226 XtCreateManagedWidget(_("ok"), commandWidgetClass, form, args, j);
4227 XtAddCallback(b_ok, XtNcallback, callback, (XtPointer) 0);
4230 XtSetArg(args[j], XtNfromVert, edit); j++;
4231 XtSetArg(args[j], XtNfromHoriz, b_ok); j++;
4232 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4233 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4234 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4235 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4237 XtCreateManagedWidget(_("cancel"), commandWidgetClass, form, args, j);
4238 XtAddCallback(b_cancel, XtNcallback, callback, (XtPointer) 0);
4241 XtSetArg(args[j], XtNfromVert, edit); j++;
4242 XtSetArg(args[j], XtNfromHoriz, b_cancel); j++;
4243 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4244 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4245 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4246 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4248 XtCreateManagedWidget(_("clear"), commandWidgetClass, form, args, j);
4249 XtAddCallback(b_clear, XtNcallback, callback, (XtPointer) 0);
4252 XtSetArg(args[j], XtNfromVert, edit); j++;
4253 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4254 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4255 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4256 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4258 XtCreateManagedWidget(_("close"), commandWidgetClass, form, args, j);
4259 XtAddCallback(b_close, XtNcallback, callback, (XtPointer) 0);
4262 XtSetArg(args[j], XtNfromVert, edit); j++;
4263 XtSetArg(args[j], XtNfromHoriz, b_close); j++;
4264 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4265 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4266 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4267 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4269 XtCreateManagedWidget(_("edit"), commandWidgetClass, form, args, j);
4270 XtAddCallback(b_edit, XtNcallback, callback, (XtPointer) 0);
4273 XtRealizeWidget(shell);
4275 if (commentX == -1) {
4278 Dimension pw_height;
4279 Dimension ew_height;
4282 XtSetArg(args[j], XtNheight, &ew_height); j++;
4283 XtGetValues(edit, args, j);
4286 XtSetArg(args[j], XtNheight, &pw_height); j++;
4287 XtGetValues(shell, args, j);
4288 commentH = pw_height + (lines - 1) * ew_height;
4289 commentW = bw_width - 16;
4291 XSync(xDisplay, False);
4293 /* This code seems to tickle an X bug if it is executed too soon
4294 after xboard starts up. The coordinates get transformed as if
4295 the main window was positioned at (0, 0).
4297 XtTranslateCoords(shellWidget,
4298 (bw_width - commentW) / 2, 0 - commentH / 2,
4299 &commentX, &commentY);
4301 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
4302 RootWindowOfScreen(XtScreen(shellWidget)),
4303 (bw_width - commentW) / 2, 0 - commentH / 2,
4308 if (commentY < 0) commentY = 0; /*avoid positioning top offscreen*/
4311 XtSetArg(args[j], XtNheight, commentH); j++;
4312 XtSetArg(args[j], XtNwidth, commentW); j++;
4313 XtSetArg(args[j], XtNx, commentX); j++;
4314 XtSetArg(args[j], XtNy, commentY); j++;
4315 XtSetValues(shell, args, j);
4316 XtSetKeyboardFocus(shell, edit);
4321 /* Used for analysis window and ICS input window */
4322 Widget MiscCreate(name, text, mutable, callback, lines)
4324 int /*Boolean*/ mutable;
4325 XtCallbackProc callback;
4329 Widget shell, layout, form, edit;
4331 Dimension bw_width, pw_height, ew_height, w, h;
4337 XtSetArg(args[j], XtNresizable, True); j++;
4340 XtCreatePopupShell(name, topLevelShellWidgetClass,
4341 shellWidget, args, j);
4344 XtCreatePopupShell(name, transientShellWidgetClass,
4345 shellWidget, args, j);
4348 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
4349 layoutArgs, XtNumber(layoutArgs));
4351 XtCreateManagedWidget("form", formWidgetClass, layout,
4352 formArgs, XtNumber(formArgs));
4356 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
4357 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
4359 XtSetArg(args[j], XtNstring, text); j++;
4360 XtSetArg(args[j], XtNtop, XtChainTop); j++;
4361 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4362 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4363 XtSetArg(args[j], XtNright, XtChainRight); j++;
4364 XtSetArg(args[j], XtNresizable, True); j++;
4365 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
4366 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
4367 XtSetArg(args[j], XtNautoFill, True); j++;
4368 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
4370 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
4372 XtRealizeWidget(shell);
4375 XtSetArg(args[j], XtNwidth, &bw_width); j++;
4376 XtGetValues(boardWidget, args, j);
4379 XtSetArg(args[j], XtNheight, &ew_height); j++;
4380 XtGetValues(edit, args, j);
4383 XtSetArg(args[j], XtNheight, &pw_height); j++;
4384 XtGetValues(shell, args, j);
4385 h = pw_height + (lines - 1) * ew_height;
4388 XSync(xDisplay, False);
4390 /* This code seems to tickle an X bug if it is executed too soon
4391 after xboard starts up. The coordinates get transformed as if
4392 the main window was positioned at (0, 0).
4394 XtTranslateCoords(shellWidget, (bw_width - w) / 2, 0 - h / 2, &x, &y);
4396 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
4397 RootWindowOfScreen(XtScreen(shellWidget)),
4398 (bw_width - w) / 2, 0 - h / 2, &xx, &yy, &junk);
4402 if (y < 0) y = 0; /*avoid positioning top offscreen*/
4405 XtSetArg(args[j], XtNheight, h); j++;
4406 XtSetArg(args[j], XtNwidth, w); j++;
4407 XtSetArg(args[j], XtNx, x); j++;
4408 XtSetArg(args[j], XtNy, y); j++;
4409 XtSetValues(shell, args, j);
4415 static int savedIndex; /* gross that this is global */
4417 void EditCommentPopUp(index, title, text)
4426 if (text == NULL) text = "";
4428 if (editShell == NULL) {
4430 CommentCreate(title, text, True, EditCommentCallback, 4);
4431 XtRealizeWidget(editShell);
4432 CatchDeleteWindow(editShell, "EditCommentPopDown");
4434 edit = XtNameToWidget(editShell, "*form.text");
4436 XtSetArg(args[j], XtNstring, text); j++;
4437 XtSetValues(edit, args, j);
4439 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4440 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4441 XtSetValues(editShell, args, j);
4444 XtPopup(editShell, XtGrabNone);
4448 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
4449 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
4453 void EditCommentCallback(w, client_data, call_data)
4455 XtPointer client_data, call_data;
4463 XtSetArg(args[j], XtNlabel, &name); j++;
4464 XtGetValues(w, args, j);
4466 if (strcmp(name, _("ok")) == 0) {
4467 edit = XtNameToWidget(editShell, "*form.text");
4469 XtSetArg(args[j], XtNstring, &val); j++;
4470 XtGetValues(edit, args, j);
4471 ReplaceComment(savedIndex, val);
4472 EditCommentPopDown();
4473 } else if (strcmp(name, _("cancel")) == 0) {
4474 EditCommentPopDown();
4475 } else if (strcmp(name, _("clear")) == 0) {
4476 edit = XtNameToWidget(editShell, "*form.text");
4477 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
4478 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
4482 void EditCommentPopDown()
4487 if (!editUp) return;
4489 XtSetArg(args[j], XtNx, &commentX); j++;
4490 XtSetArg(args[j], XtNy, &commentY); j++;
4491 XtSetArg(args[j], XtNheight, &commentH); j++;
4492 XtSetArg(args[j], XtNwidth, &commentW); j++;
4493 XtGetValues(editShell, args, j);
4494 XtPopdown(editShell);
4497 XtSetArg(args[j], XtNleftBitmap, None); j++;
4498 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
4502 void ICSInputBoxPopUp()
4507 char *title = _("ICS Input");
4510 if (ICSInputShell == NULL) {
4511 ICSInputShell = MiscCreate(title, "", True, NULL, 1);
4512 tr = XtParseTranslationTable(ICSInputTranslations);
4513 edit = XtNameToWidget(ICSInputShell, "*form.text");
4514 XtOverrideTranslations(edit, tr);
4515 XtRealizeWidget(ICSInputShell);
4516 CatchDeleteWindow(ICSInputShell, "ICSInputBoxPopDown");
4519 edit = XtNameToWidget(ICSInputShell, "*form.text");
4521 XtSetArg(args[j], XtNstring, ""); j++;
4522 XtSetValues(edit, args, j);
4524 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4525 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4526 XtSetValues(ICSInputShell, args, j);
4529 XtPopup(ICSInputShell, XtGrabNone);
4530 XtSetKeyboardFocus(ICSInputShell, edit);
4532 ICSInputBoxUp = True;
4534 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
4535 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
4539 void ICSInputSendText()
4546 edit = XtNameToWidget(ICSInputShell, "*form.text");
4548 XtSetArg(args[j], XtNstring, &val); j++;
4549 XtGetValues(edit, args, j);
4550 SendMultiLineToICS(val);
4551 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
4552 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
4555 void ICSInputBoxPopDown()
4560 if (!ICSInputBoxUp) return;
4562 XtPopdown(ICSInputShell);
4563 ICSInputBoxUp = False;
4565 XtSetArg(args[j], XtNleftBitmap, None); j++;
4566 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
4570 void CommentPopUp(title, text)
4577 if (commentShell == NULL) {
4579 CommentCreate(title, text, False, CommentCallback, 4);
4580 XtRealizeWidget(commentShell);
4581 CatchDeleteWindow(commentShell, "CommentPopDown");
4583 edit = XtNameToWidget(commentShell, "*form.text");
4585 XtSetArg(args[j], XtNstring, text); j++;
4586 XtSetValues(edit, args, j);
4588 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4589 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4590 XtSetValues(commentShell, args, j);
4593 XtPopup(commentShell, XtGrabNone);
4594 XSync(xDisplay, False);
4599 void CommentCallback(w, client_data, call_data)
4601 XtPointer client_data, call_data;
4608 XtSetArg(args[j], XtNlabel, &name); j++;
4609 XtGetValues(w, args, j);
4611 if (strcmp(name, _("close")) == 0) {
4613 } else if (strcmp(name, _("edit")) == 0) {
4620 void CommentPopDown()
4625 if (!commentUp) return;
4627 XtSetArg(args[j], XtNx, &commentX); j++;
4628 XtSetArg(args[j], XtNy, &commentY); j++;
4629 XtSetArg(args[j], XtNwidth, &commentW); j++;
4630 XtSetArg(args[j], XtNheight, &commentH); j++;
4631 XtGetValues(commentShell, args, j);
4632 XtPopdown(commentShell);
4633 XSync(xDisplay, False);
4637 void PromotionPopUp()
4640 Widget dialog, layout;
4642 Dimension bw_width, pw_width;
4646 XtSetArg(args[j], XtNwidth, &bw_width); j++;
4647 XtGetValues(boardWidget, args, j);
4650 XtSetArg(args[j], XtNresizable, True); j++;
4651 XtSetArg(args[j], XtNtitle, XtNewString(_("Promotion"))); j++;
4653 XtCreatePopupShell("Promotion", transientShellWidgetClass,
4654 shellWidget, args, j);
4656 XtCreateManagedWidget(layoutName, formWidgetClass, promotionShell,
4657 layoutArgs, XtNumber(layoutArgs));
4660 XtSetArg(args[j], XtNlabel, _("Promote to what?")); j++;
4661 XtSetArg(args[j], XtNborderWidth, 0); j++;
4662 dialog = XtCreateManagedWidget("promotion", dialogWidgetClass,
4665 if(gameInfo.variant != VariantShogi) {
4666 XawDialogAddButton(dialog, _("Queen"), PromotionCallback,
4667 (XtPointer) dialog);
4668 XawDialogAddButton(dialog, _("Rook"), PromotionCallback,
4669 (XtPointer) dialog);
4670 XawDialogAddButton(dialog, _("Bishop"), PromotionCallback,
4671 (XtPointer) dialog);
4672 XawDialogAddButton(dialog, _("Knight"), PromotionCallback,
4673 (XtPointer) dialog);
4674 if (!appData.testLegality || gameInfo.variant == VariantSuicide ||
4675 gameInfo.variant == VariantGiveaway) {
4676 XawDialogAddButton(dialog, _("King"), PromotionCallback,
4677 (XtPointer) dialog);
4679 if(gameInfo.variant == VariantCapablanca ||
4680 gameInfo.variant == VariantGothic ||
4681 gameInfo.variant == VariantCapaRandom) {
4682 XawDialogAddButton(dialog, _("Archbishop"), PromotionCallback,
4683 (XtPointer) dialog);
4684 XawDialogAddButton(dialog, _("Chancellor"), PromotionCallback,
4685 (XtPointer) dialog);
4687 } else // [HGM] shogi
4689 XawDialogAddButton(dialog, _("Promote"), PromotionCallback,
4690 (XtPointer) dialog);
4691 XawDialogAddButton(dialog, _("Defer"), PromotionCallback,
4692 (XtPointer) dialog);
4694 XawDialogAddButton(dialog, _("cancel"), PromotionCallback,
4695 (XtPointer) dialog);
4697 XtRealizeWidget(promotionShell);
4698 CatchDeleteWindow(promotionShell, "PromotionPopDown");
4701 XtSetArg(args[j], XtNwidth, &pw_width); j++;
4702 XtGetValues(promotionShell, args, j);
4704 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
4705 lineGap + squareSize/3 +
4706 ((toY == BOARD_HEIGHT-1) ^ (flipView) ?
4707 0 : 6*(squareSize + lineGap)), &x, &y);
4710 XtSetArg(args[j], XtNx, x); j++;
4711 XtSetArg(args[j], XtNy, y); j++;
4712 XtSetValues(promotionShell, args, j);
4714 XtPopup(promotionShell, XtGrabNone);
4719 void PromotionPopDown()
4721 if (!promotionUp) return;
4722 XtPopdown(promotionShell);
4723 XtDestroyWidget(promotionShell);
4724 promotionUp = False;
4727 void PromotionCallback(w, client_data, call_data)
4729 XtPointer client_data, call_data;
4735 XtSetArg(args[0], XtNlabel, &name);
4736 XtGetValues(w, args, 1);
4740 if (fromX == -1) return;
4742 if (strcmp(name, _("cancel")) == 0) {
4746 } else if (strcmp(name, _("Knight")) == 0) {
4748 } else if (strcmp(name, _("Promote")) == 0) {
4750 } else if (strcmp(name, _("Defer")) == 0) {
4753 promoChar = ToLower(name[0]);
4756 FinishMove(NormalMove, fromX, fromY, toX, toY, promoChar);
4758 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
4759 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
4764 void ErrorCallback(w, client_data, call_data)
4766 XtPointer client_data, call_data;
4769 XtPopdown(w = XtParent(XtParent(XtParent(w))));
4771 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
4777 if (!errorUp) return;
4781 gtk_widget_destroy(GTK_WIDGET(GUI_Error));
4783 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
4788 void ErrorPopUp(title, label, modal)
4789 char *title, *label;
4792 GUI_Error = gtk_message_dialog_new(GTK_WINDOW(GUI_Window),
4793 GTK_DIALOG_DESTROY_WITH_PARENT,
4798 gtk_window_set_title(GTK_WINDOW(GUI_Error),(gchar *) title);
4801 gtk_dialog_run(GTK_DIALOG(GUI_Error));
4802 gtk_widget_destroy(GTK_WIDGET(GUI_Error));
4806 g_signal_connect_swapped (GUI_Error, "response",
4807 G_CALLBACK (ErrorPopDownProc),
4810 gtk_widget_show(GTK_WIDGET(GUI_Error));
4816 /* Disable all user input other than deleting the window */
4817 static int frozen = 0;
4821 /* Grab by a widget that doesn't accept input */
4822 // XtAddGrab(messageWidget, TRUE, FALSE);
4826 /* Undo a FreezeUI */
4829 if (!frozen) return;
4830 // XtRemoveGrab(messageWidget);
4834 char *ModeToWidgetName(mode)
4838 case BeginningOfGame:
4839 if (appData.icsActive)
4840 return "menuMode.ICS Client";
4841 else if (appData.noChessProgram ||
4842 *appData.cmailGameName != NULLCHAR)
4843 return "menuMode.Edit Game";
4845 return "menuMode.Machine Black";
4846 case MachinePlaysBlack:
4847 return "menuMode.Machine Black";
4848 case MachinePlaysWhite:
4849 return "menuMode.Machine White";
4851 return "menuMode.Analysis Mode";
4853 return "menuMode.Analyze File";
4854 case TwoMachinesPlay:
4855 return "menuMode.Two Machines";
4857 return "menuMode.Edit Game";
4858 case PlayFromGameFile:
4859 return "menuFile.Load Game";
4861 return "menuMode.Edit Position";
4863 return "menuMode.Training";
4864 case IcsPlayingWhite:
4865 case IcsPlayingBlack:
4869 return "menuMode.ICS Client";
4876 void ModeHighlight()
4878 static int oldPausing = FALSE;
4879 static GameMode oldmode = (GameMode) -1;
4882 // todo this toggling of the pause button doesn't seem to work?
4883 // e.g. select pause from buttonbar doesn't activate menumode.pause
4885 // if (!boardWidget || !XtIsRealized(boardWidget)) return;
4887 if (pausing != oldPausing) {
4888 oldPausing = pausing;
4889 gtk_button_set_relief(GTK_BUTTON (gtk_builder_get_object (builder, "menuMode.Pause")),pausing?GTK_RELIEF_NORMAL:GTK_RELIEF_NONE);
4890 /* toggle background color in showbuttonbar */
4891 if (appData.showButtonBar) {
4893 gtk_button_pressed(GTK_BUTTON (gtk_builder_get_object (builder, "buttonbar.Pause")));
4895 gtk_button_released(GTK_BUTTON (gtk_builder_get_object (builder, "buttonbar.Pause")));
4900 wname = ModeToWidgetName(oldmode);
4902 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, wname)),True);
4906 /* Maybe all the enables should be handled here, not just this one */
4907 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuMode.Training")),
4908 gameMode == Training || gameMode == PlayFromGameFile);
4913 * Button/menu procedures
4916 int LoadGamePopUp(f, gameNumber, title)
4921 cmailMsgLoaded = FALSE;
4923 if (gameNumber == 0)
4925 int error = GameListBuild(f);
4929 DisplayError(_("Cannot build game list"), error);
4931 else if (!ListEmpty(&gameList)
4932 && ((ListGame *) gameList.tailPred)->number > 1)
4934 // TODO convert to GTK
4935 // GameListPopUp(f, title);
4943 return LoadGame(f, gameNumber, title, FALSE);
4946 void ReloadCmailMsgProc(w, event, prms, nprms)
4952 ReloadCmailMsgEvent(FALSE);
4955 void MailMoveProc(w, event, prms, nprms)
4964 /* this variable is shared between CopyPositionProc and SendPositionSelection */
4965 static char *selected_fen_position=NULL;
4968 SendPositionSelection(Widget w, Atom *selection, Atom *target,
4969 Atom *type_return, XtPointer *value_return,
4970 unsigned long *length_return, int *format_return)
4972 char *selection_tmp;
4974 if (!selected_fen_position) return False; /* should never happen */
4975 if (*target == XA_STRING){
4976 /* note: since no XtSelectionDoneProc was registered, Xt will
4977 * automatically call XtFree on the value returned. So have to
4978 * make a copy of it allocated with XtMalloc */
4979 selection_tmp= XtMalloc(strlen(selected_fen_position)+16);
4980 strcpy(selection_tmp, selected_fen_position);
4982 *value_return=selection_tmp;
4983 *length_return=strlen(selection_tmp);
4984 *type_return=XA_STRING;
4985 *format_return = 8; /* bits per byte */
4992 /* note: when called from menu all parameters are NULL, so no clue what the
4993 * Widget which was clicked on was, or what the click event was
4995 void CopyPositionProc(w, event, prms, nprms)
5003 if (selected_fen_position) free(selected_fen_position);
5004 selected_fen_position = (char *)PositionToFEN(currentMove, NULL);
5005 if (!selected_fen_position) return;
5006 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
5008 SendPositionSelection,
5009 NULL/* lose_ownership_proc */ ,
5010 NULL/* transfer_done_proc */);
5012 free(selected_fen_position);
5013 selected_fen_position=NULL;
5017 /* function called when the data to Paste is ready */
5019 PastePositionCB(Widget w, XtPointer client_data, Atom *selection,
5020 Atom *type, XtPointer value, unsigned long *len, int *format)
5023 if (value==NULL || *len==0) return; /* nothing had been selected to copy */
5024 fenstr[*len]='\0'; /* normally this string is terminated, but be safe */
5025 EditPositionPasteFEN(fenstr);
5029 /* called when Paste Position button is pressed,
5030 * all parameters will be NULL */
5031 void PastePositionProc(w, event, prms, nprms)
5037 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
5038 /* (XtSelectionCallbackProc) */ PastePositionCB,
5039 NULL, /* client_data passed to PastePositionCB */
5041 /* better to use the time field from the event that triggered the
5042 * call to this function, but that isn't trivial to get
5050 SendGameSelection(Widget w, Atom *selection, Atom *target,
5051 Atom *type_return, XtPointer *value_return,
5052 unsigned long *length_return, int *format_return)
5054 char *selection_tmp;
5056 if (*target == XA_STRING){
5057 FILE* f = fopen(gameCopyFilename, "r");
5060 if (f == NULL) return False;
5064 selection_tmp = XtMalloc(len + 1);
5065 count = fread(selection_tmp, 1, len, f);
5067 XtFree(selection_tmp);
5070 selection_tmp[len] = NULLCHAR;
5071 *value_return = selection_tmp;
5072 *length_return = len;
5073 *type_return = XA_STRING;
5074 *format_return = 8; /* bits per byte */
5081 /* note: when called from menu all parameters are NULL, so no clue what the
5082 * Widget which was clicked on was, or what the click event was
5084 void CopyGameProc(w, event, prms, nprms)
5092 ret = SaveGameToFile(gameCopyFilename, FALSE);
5095 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
5098 NULL/* lose_ownership_proc */ ,
5099 NULL/* transfer_done_proc */);
5102 /* function called when the data to Paste is ready */
5104 PasteGameCB(Widget w, XtPointer client_data, Atom *selection,
5105 Atom *type, XtPointer value, unsigned long *len, int *format)
5108 if (value == NULL || *len == 0) {
5109 return; /* nothing had been selected to copy */
5111 f = fopen(gamePasteFilename, "w");
5113 DisplayError(_("Can't open temp file"), errno);
5116 fwrite(value, 1, *len, f);
5119 LoadGameFromFile(gamePasteFilename, 0, gamePasteFilename, TRUE);
5122 /* called when Paste Game button is pressed,
5123 * all parameters will be NULL */
5124 void PasteGameProc(w, event, prms, nprms)
5130 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
5131 /* (XtSelectionCallbackProc) */ PasteGameCB,
5132 NULL, /* client_data passed to PasteGameCB */
5134 /* better to use the time field from the event that triggered the
5135 * call to this function, but that isn't trivial to get
5145 SaveGameProc(NULL, NULL);
5149 void AnalyzeModeProc(w, event, prms, nprms)
5157 if (!first.analysisSupport) {
5158 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
5159 DisplayError(buf, 0);
5162 /* [DM] icsEngineAnalyze [HGM] This is horrible code; reverse the gameMode and isEngineAnalyze tests! */
5163 if (appData.icsActive) {
5164 if (gameMode != IcsObserving) {
5165 sprintf(buf,_("You are not observing a game"));
5166 DisplayError(buf, 0);
5168 if (appData.icsEngineAnalyze) {
5169 if (appData.debugMode)
5170 fprintf(debugFP, _("Found unexpected active ICS engine analyze \n"));
5176 /* if enable, use want disable icsEngineAnalyze */
5177 if (appData.icsEngineAnalyze) {
5182 appData.icsEngineAnalyze = TRUE;
5183 if (appData.debugMode)
5184 fprintf(debugFP, _("ICS engine analyze starting... \n"));
5186 if (!appData.showThinking)
5187 ShowThinkingProc(NULL,NULL);
5192 void EditGameProc(w, event, prms, nprms)
5201 void EditPositionProc(w, event, prms, nprms)
5207 EditPositionEvent();
5210 void TrainingProc(w, event, prms, nprms)
5219 void EditCommentProc(w, event, prms, nprms)
5226 EditCommentPopDown();
5232 void IcsInputBoxProc(w, event, prms, nprms)
5238 if (ICSInputBoxUp) {
5239 ICSInputBoxPopDown();
5246 void EnterKeyProc(w, event, prms, nprms)
5252 if (ICSInputBoxUp == True)
5257 void PonderNextMoveProc(w, event, prms, nprms)
5265 PonderNextMoveEvent(!appData.ponderNextMove);
5267 if (appData.ponderNextMove) {
5268 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5270 XtSetArg(args[0], XtNleftBitmap, None);
5272 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Ponder Next Move"),
5276 void PopupExitMessageProc(w, event, prms, nprms)
5284 appData.popupExitMessage = !appData.popupExitMessage;
5286 if (appData.popupExitMessage) {
5287 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5289 XtSetArg(args[0], XtNleftBitmap, None);
5291 XtSetValues(XtNameToWidget(menuBarWidget,
5292 "menuOptions.Popup Exit Message"), args, 1);
5295 void PopupMoveErrorsProc(w, event, prms, nprms)
5303 appData.popupMoveErrors = !appData.popupMoveErrors;
5305 if (appData.popupMoveErrors) {
5306 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5308 XtSetArg(args[0], XtNleftBitmap, None);
5310 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Popup Move Errors"),
5314 void PremoveProc(w, event, prms, nprms)
5322 appData.premove = !appData.premove;
5324 if (appData.premove) {
5325 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5327 XtSetArg(args[0], XtNleftBitmap, None);
5329 XtSetValues(XtNameToWidget(menuBarWidget,
5330 "menuOptions.Premove"), args, 1);
5333 void QuietPlayProc(w, event, prms, nprms)
5341 appData.quietPlay = !appData.quietPlay;
5343 if (appData.quietPlay) {
5344 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5346 XtSetArg(args[0], XtNleftBitmap, None);
5348 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Quiet Play"),
5352 void DebugProc(w, event, prms, nprms)
5358 appData.debugMode = !appData.debugMode;
5361 void AboutGameProc(w, event, prms, nprms)
5370 void NothingProc(w, event, prms, nprms)
5379 void Iconify(w, event, prms, nprms)
5388 XtSetArg(args[0], XtNiconic, True);
5389 XtSetValues(shellWidget, args, 1);
5392 void DisplayMessage(message, extMessage)
5393 gchar *message, *extMessage;
5400 snprintf(buf, sizeof(buf), "%s %s", message, extMessage);
5403 message = extMessage;
5406 gtk_label_set_text( GTK_LABEL(gtk_builder_get_object (builder, "Messages")),message);
5411 void DisplayTitle(text)
5414 gchar title[MSG_SIZ];
5416 if (text == NULL) text = "";
5418 if (appData.titleInWindow)
5423 if (*text != NULLCHAR)
5425 strcpy(title, text);
5427 else if (appData.icsActive)
5429 snprintf(title, sizeof(title), "%s: %s", programName, appData.icsHost);
5431 else if (appData.cmailGameName[0] != NULLCHAR)
5433 snprintf(title,sizeof(title), "%s: %s", programName, "CMail");
5435 // [HGM] license: This stuff should really be done in back-end, but WinBoard already had a pop-up for it
5437 else if (gameInfo.variant == VariantGothic)
5439 strcpy(title, GOTHIC);
5443 else if (gameInfo.variant == VariantFalcon)
5445 strcpy(title, FALCON);
5448 else if (appData.noChessProgram)
5450 strcpy(title, programName);
5454 snprintf(title,sizeof(title), "%s: %s", programName, first.tidy);
5456 gtk_window_set_title(GTK_WINDOW(GUI_Window),title);
5462 void DisplayError(message, error)
5469 if (appData.debugMode || appData.matchMode) {
5470 fprintf(stderr, "%s: %s\n", programName, message);
5473 if (appData.debugMode || appData.matchMode) {
5474 fprintf(stderr, "%s: %s: %s\n",
5475 programName, message, strerror(error));
5477 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
5480 ErrorPopUp(_("Error"), message, FALSE);
5484 void DisplayMoveError(message)
5489 DrawPosition(FALSE, NULL);
5490 if (appData.debugMode || appData.matchMode) {
5491 fprintf(stderr, "%s: %s\n", programName, message);
5493 if (appData.popupMoveErrors) {
5494 ErrorPopUp(_("Error"), message, FALSE);
5496 DisplayMessage(message, "");
5501 void DisplayFatalError(message, error, status)
5507 errorExitStatus = status;
5509 fprintf(stderr, "%s: %s\n", programName, message);
5511 fprintf(stderr, "%s: %s: %s\n",
5512 programName, message, strerror(error));
5513 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
5516 if (appData.popupExitMessage && boardWidget && XtIsRealized(boardWidget)) {
5517 ErrorPopUp(status ? _("Fatal Error") : _("Exiting"), message, TRUE);
5523 void DisplayInformation(message)
5527 ErrorPopUp(_("Information"), message, TRUE);
5530 void DisplayNote(message)
5534 ErrorPopUp(_("Note"), message, FALSE);
5538 NullXErrorCheck(dpy, error_event)
5540 XErrorEvent *error_event;
5545 void DisplayIcsInteractionTitle(message)
5548 if (oldICSInteractionTitle == NULL) {
5549 /* Magic to find the old window title, adapted from vim */
5550 char *wina = getenv("WINDOWID");
5552 Window win = (Window) atoi(wina);
5553 Window root, parent, *children;
5554 unsigned int nchildren;
5555 int (*oldHandler)() = XSetErrorHandler(NullXErrorCheck);
5557 if (XFetchName(xDisplay, win, &oldICSInteractionTitle)) break;
5558 if (!XQueryTree(xDisplay, win, &root, &parent,
5559 &children, &nchildren)) break;
5560 if (children) XFree((void *)children);
5561 if (parent == root || parent == 0) break;
5564 XSetErrorHandler(oldHandler);
5566 if (oldICSInteractionTitle == NULL) {
5567 oldICSInteractionTitle = "xterm";
5570 printf("\033]0;%s\007", message);
5574 char pendingReplyPrefix[MSG_SIZ];
5575 ProcRef pendingReplyPR;
5577 void AskQuestionProc(w, event, prms, nprms)
5584 fprintf(stderr, _("AskQuestionProc needed 4 parameters, got %d\n"),
5588 AskQuestionEvent(prms[0], prms[1], prms[2], prms[3]);
5591 void AskQuestionPopDown()
5593 if (!askQuestionUp) return;
5594 XtPopdown(askQuestionShell);
5595 XtDestroyWidget(askQuestionShell);
5596 askQuestionUp = False;
5599 void AskQuestionReplyAction(w, event, prms, nprms)
5609 reply = XawDialogGetValueString(w = XtParent(w));
5610 strcpy(buf, pendingReplyPrefix);
5611 if (*buf) strcat(buf, " ");
5614 OutputToProcess(pendingReplyPR, buf, strlen(buf), &err);
5615 AskQuestionPopDown();
5617 if (err) DisplayFatalError(_("Error writing to chess program"), err, 0);
5620 void AskQuestionCallback(w, client_data, call_data)
5622 XtPointer client_data, call_data;
5627 XtSetArg(args[0], XtNlabel, &name);
5628 XtGetValues(w, args, 1);
5630 if (strcmp(name, _("cancel")) == 0) {
5631 AskQuestionPopDown();
5633 AskQuestionReplyAction(w, NULL, NULL, NULL);
5637 void AskQuestion(title, question, replyPrefix, pr)
5638 char *title, *question, *replyPrefix;
5642 Widget popup, layout, dialog, edit;
5648 strcpy(pendingReplyPrefix, replyPrefix);
5649 pendingReplyPR = pr;
5652 XtSetArg(args[i], XtNresizable, True); i++;
5653 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
5654 askQuestionShell = popup =
5655 XtCreatePopupShell(title, transientShellWidgetClass,
5656 shellWidget, args, i);
5659 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
5660 layoutArgs, XtNumber(layoutArgs));
5663 XtSetArg(args[i], XtNlabel, question); i++;
5664 XtSetArg(args[i], XtNvalue, ""); i++;
5665 XtSetArg(args[i], XtNborderWidth, 0); i++;
5666 dialog = XtCreateManagedWidget("question", dialogWidgetClass,
5669 XawDialogAddButton(dialog, _("enter"), AskQuestionCallback,
5670 (XtPointer) dialog);
5671 XawDialogAddButton(dialog, _("cancel"), AskQuestionCallback,
5672 (XtPointer) dialog);
5674 XtRealizeWidget(popup);
5675 CatchDeleteWindow(popup, "AskQuestionPopDown");
5677 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
5678 &x, &y, &win_x, &win_y, &mask);
5680 XtSetArg(args[0], XtNx, x - 10);
5681 XtSetArg(args[1], XtNy, y - 30);
5682 XtSetValues(popup, args, 2);
5684 XtPopup(popup, XtGrabExclusive);
5685 askQuestionUp = True;
5687 edit = XtNameToWidget(dialog, "*value");
5688 XtSetKeyboardFocus(popup, edit);
5696 if (*name == NULLCHAR) {
5698 } else if (strcmp(name, "$") == 0) {
5699 putc(BELLCHAR, stderr);
5702 snprintf(buf, sizeof(buf), "%s '%s' &", appData.soundProgram, name);
5710 PlaySound(appData.soundMove);
5716 PlaySound(appData.soundIcsWin);
5722 PlaySound(appData.soundIcsLoss);
5728 PlaySound(appData.soundIcsDraw);
5732 PlayIcsUnfinishedSound()
5734 PlaySound(appData.soundIcsUnfinished);
5740 PlaySound(appData.soundIcsAlarm);
5746 system("stty echo");
5752 system("stty -echo");
5756 Colorize(cc, continuation)
5761 int count, outCount, error;
5763 if (textColors[(int)cc].bg > 0) {
5764 if (textColors[(int)cc].fg > 0) {
5765 sprintf(buf, "\033[0;%d;%d;%dm", textColors[(int)cc].attr,
5766 textColors[(int)cc].fg, textColors[(int)cc].bg);
5768 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
5769 textColors[(int)cc].bg);
5772 if (textColors[(int)cc].fg > 0) {
5773 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
5774 textColors[(int)cc].fg);
5776 sprintf(buf, "\033[0;%dm", textColors[(int)cc].attr);
5779 count = strlen(buf);
5780 outCount = OutputToProcess(NoProc, buf, count, &error);
5781 if (outCount < count) {
5782 DisplayFatalError(_("Error writing to display"), error, 1);
5785 if (continuation) return;
5788 PlaySound(appData.soundShout);
5791 PlaySound(appData.soundSShout);
5794 PlaySound(appData.soundChannel1);
5797 PlaySound(appData.soundChannel);
5800 PlaySound(appData.soundKibitz);
5803 PlaySound(appData.soundTell);
5805 case ColorChallenge:
5806 PlaySound(appData.soundChallenge);
5809 PlaySound(appData.soundRequest);
5812 PlaySound(appData.soundSeek);
5823 return getpwuid(getuid())->pw_name;
5826 static char *ExpandPathName(path)
5829 static char static_buf[2000];
5830 char *d, *s, buf[2000];
5836 while (*s && isspace(*s))
5845 if (*(s+1) == '/') {
5846 strcpy(d, getpwuid(getuid())->pw_dir);
5851 *strchr(buf, '/') = 0;
5852 pwd = getpwnam(buf);
5855 fprintf(stderr, _("ERROR: Unknown user %s (in path %s)\n"),
5859 strcpy(d, pwd->pw_dir);
5860 strcat(d, strchr(s+1, '/'));
5871 static char host_name[MSG_SIZ];
5873 #if HAVE_GETHOSTNAME
5874 gethostname(host_name, MSG_SIZ);
5876 #else /* not HAVE_GETHOSTNAME */
5877 # if HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H
5878 sysinfo(SI_HOSTNAME, host_name, MSG_SIZ);
5880 # else /* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
5882 # endif/* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
5883 #endif /* not HAVE_GETHOSTNAME */
5886 guint delayedEventTimerTag = 0;
5887 DelayedEventCallback delayedEventCallback = 0;
5890 FireDelayedEvent(data)
5894 g_source_remove(delayedEventTimerTag);
5895 delayedEventTimerTag = 0;
5898 delayedEventCallback();
5904 ScheduleDelayedEvent(cb, millisec)
5905 DelayedEventCallback cb; guint millisec;
5907 if(delayedEventTimerTag && delayedEventCallback == cb)
5908 // [HGM] alive: replace, rather than add or flush identical event
5909 g_source_remove(delayedEventTimerTag);
5910 delayedEventCallback = cb;
5911 delayedEventTimerTag = g_timeout_add(millisec,(GSourceFunc) FireDelayedEvent, NULL);
5915 DelayedEventCallback
5918 if (delayedEventTimerTag)
5920 return delayedEventCallback;
5929 CancelDelayedEvent()
5931 if (delayedEventTimerTag)
5933 g_source_remove(delayedEventTimerTag);
5934 delayedEventTimerTag = 0;
5940 guint loadGameTimerTag = 0;
5942 int LoadGameTimerRunning()
5944 return loadGameTimerTag != 0;
5947 int StopLoadGameTimer()
5949 if (loadGameTimerTag != 0) {
5950 g_source_remove(loadGameTimerTag);
5951 loadGameTimerTag = 0;
5959 LoadGameTimerCallback(data)
5963 g_source_remove(loadGameTimerTag);
5964 loadGameTimerTag = 0;
5971 StartLoadGameTimer(millisec)
5975 g_timeout_add( millisec, (GSourceFunc) LoadGameTimerCallback, NULL);
5979 guint analysisClockTag = 0;
5982 AnalysisClockCallback(data)
5985 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile
5986 || appData.icsEngineAnalyze)
5988 AnalysisPeriodicEvent(0);
5989 return 1; /* keep on going */
5991 return 0; /* stop timer */
5995 StartAnalysisClock()
5998 g_timeout_add( 2000,(GSourceFunc) AnalysisClockCallback, NULL);
6002 guint clockTimerTag = 0;
6004 int ClockTimerRunning()
6006 return clockTimerTag != 0;
6009 int StopClockTimer()
6011 if (clockTimerTag != 0)
6013 g_source_remove(clockTimerTag);
6024 ClockTimerCallback(data)
6028 g_source_remove(clockTimerTag);
6036 StartClockTimer(millisec)
6039 clockTimerTag = g_timeout_add(millisec,(GSourceFunc) ClockTimerCallback,NULL);
6044 DisplayTimerLabel(w, color, timer, highlight)
6053 if (appData.clockMode) {
6054 sprintf(buf, "%s: %s", color, TimeString(timer));
6056 sprintf(buf, "%s ", color);
6058 gtk_label_set_text(GTK_LABEL(w),buf);
6060 /* check for low time warning */
6061 // Pixel foregroundOrWarningColor = timerForegroundPixel;
6064 // appData.lowTimeWarning &&
6065 // (timer / 1000) < appData.icsAlarmTime)
6066 // foregroundOrWarningColor = lowTimeWarningColor;
6068 // if (appData.clockMode) {
6069 // sprintf(buf, "%s: %s", color, TimeString(timer));
6070 // XtSetArg(args[0], XtNlabel, buf);
6072 // sprintf(buf, "%s ", color);
6073 // XtSetArg(args[0], XtNlabel, buf);
6078 // XtSetArg(args[1], XtNbackground, foregroundOrWarningColor);
6079 // XtSetArg(args[2], XtNforeground, timerBackgroundPixel);
6081 // XtSetArg(args[1], XtNbackground, timerBackgroundPixel);
6082 // XtSetArg(args[2], XtNforeground, foregroundOrWarningColor);
6085 // XtSetValues(w, args, 3);
6090 DisplayWhiteClock(timeRemaining, highlight)
6094 if(appData.noGUI) return;
6096 DisplayTimerLabel(GUI_Whiteclock, _("White"), timeRemaining, highlight);
6097 if (highlight && WindowIcon == BlackIcon)
6099 WindowIcon = WhiteIcon;
6100 gtk_window_set_icon(GTK_WINDOW(GUI_Window),WindowIcon);
6105 DisplayBlackClock(timeRemaining, highlight)
6109 if(appData.noGUI) return;
6111 DisplayTimerLabel(GUI_Blackclock, _("Black"), timeRemaining, highlight);
6112 if (highlight && WindowIcon == WhiteIcon)
6114 WindowIcon = BlackIcon;
6115 gtk_window_set_icon(GTK_WINDOW(GUI_Window),WindowIcon);
6133 int StartChildProcess(cmdLine, dir, pr)
6140 int to_prog[2], from_prog[2];
6144 if (appData.debugMode) {
6145 fprintf(stderr, "StartChildProcess (dir=\"%s\") %s\n",dir, cmdLine);
6148 /* We do NOT feed the cmdLine to the shell; we just
6149 parse it into blank-separated arguments in the
6150 most simple-minded way possible.
6153 strcpy(buf, cmdLine);
6158 if (p == NULL) break;
6163 SetUpChildIO(to_prog, from_prog);
6166 signal(SIGWINCH, TermSizeSigHandler);
6169 if ((pid = fork()) == 0) {
6171 // [HGM] PSWBTM: made order resistant against case where fd of created pipe was 0 or 1
6172 close(to_prog[1]); // first close the unused pipe ends
6173 close(from_prog[0]);
6174 dup2(to_prog[0], 0); // to_prog was created first, nd is the only one to use 0 or 1
6175 dup2(from_prog[1], 1);
6176 if(to_prog[0] >= 2) close(to_prog[0]); // if 0 or 1, the dup2 already cosed the original
6177 close(from_prog[1]); // and closing again loses one of the pipes!
6178 if(fileno(stderr) >= 2) // better safe than sorry...
6179 dup2(1, fileno(stderr)); /* force stderr to the pipe */
6181 if (dir[0] != NULLCHAR && chdir(dir) != 0) {
6186 nice(appData.niceEngines); // [HGM] nice: adjust priority of engine proc
6188 execvp(argv[0], argv);
6190 /* If we get here, exec failed */
6195 /* Parent process */
6197 close(from_prog[1]);
6199 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
6202 cp->fdFrom = from_prog[0];
6203 cp->fdTo = to_prog[1];
6208 // [HGM] kill: implement the 'hard killing' of AS's Winboard_x
6209 static RETSIGTYPE AlarmCallBack(int n)
6215 DestroyChildProcess(pr, signalType)
6219 ChildProc *cp = (ChildProc *) pr;
6221 if (cp->kind != CPReal) return;
6223 if (signalType == 10) { // [HGM] kill: if it does not terminate in 3 sec, kill
6224 signal(SIGALRM, AlarmCallBack);
6226 if(wait((int *) 0) == -1) { // process does not terminate on its own accord
6227 kill(cp->pid, SIGKILL); // kill it forcefully
6228 wait((int *) 0); // and wait again
6232 kill(cp->pid, signalType == 9 ? SIGKILL : SIGTERM); // [HGM] kill: use hard kill if so requested
6234 /* Process is exiting either because of the kill or because of
6235 a quit command sent by the backend; either way, wait for it to die.
6244 InterruptChildProcess(pr)
6247 ChildProc *cp = (ChildProc *) pr;
6249 if (cp->kind != CPReal) return;
6250 (void) kill(cp->pid, SIGINT); /* stop it thinking */
6253 int OpenTelnet(host, port, pr)
6258 char cmdLine[MSG_SIZ];
6260 if (port[0] == NULLCHAR) {
6261 snprintf(cmdLine, sizeof(cmdLine), "%s %s", appData.telnetProgram, host);
6263 snprintf(cmdLine, sizeof(cmdLine), "%s %s %s", appData.telnetProgram, host, port);
6265 return StartChildProcess(cmdLine, "", pr);
6268 int OpenTCP(host, port, pr)
6274 DisplayFatalError(_("Socket support is not configured in"), 0, 2);
6275 #else /* !OMIT_SOCKETS */
6277 struct sockaddr_in sa;
6279 unsigned short uport;
6282 if ((s = socket(AF_INET, SOCK_STREAM, 6)) < 0) {
6286 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
6287 sa.sin_family = AF_INET;
6288 sa.sin_addr.s_addr = INADDR_ANY;
6289 uport = (unsigned short) 0;
6290 sa.sin_port = htons(uport);
6291 if (bind(s, (struct sockaddr *) &sa, sizeof(struct sockaddr_in)) < 0) {
6295 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
6296 if (!(hp = gethostbyname(host))) {
6298 if (sscanf(host, "%d.%d.%d.%d", &b0, &b1, &b2, &b3) == 4) {
6299 hp = (struct hostent *) calloc(1, sizeof(struct hostent));
6300 hp->h_addrtype = AF_INET;
6302 hp->h_addr_list = (char **) calloc(2, sizeof(char *));
6303 hp->h_addr_list[0] = (char *) malloc(4);
6304 hp->h_addr_list[0][0] = b0;
6305 hp->h_addr_list[0][1] = b1;
6306 hp->h_addr_list[0][2] = b2;
6307 hp->h_addr_list[0][3] = b3;
6312 sa.sin_family = hp->h_addrtype;
6313 uport = (unsigned short) atoi(port);
6314 sa.sin_port = htons(uport);
6315 memcpy((char *) &sa.sin_addr, hp->h_addr, hp->h_length);
6317 if (connect(s, (struct sockaddr *) &sa,
6318 sizeof(struct sockaddr_in)) < 0) {
6322 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
6329 #endif /* !OMIT_SOCKETS */
6334 int OpenCommPort(name, pr)
6341 fd = open(name, 2, 0);
6342 if (fd < 0) return errno;
6344 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
6354 int OpenLoopback(pr)
6360 SetUpChildIO(to, from);
6362 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
6365 cp->fdFrom = to[0]; /* note not from[0]; we are doing a loopback */
6372 int OpenRcmd(host, user, cmd, pr)
6373 char *host, *user, *cmd;
6376 DisplayFatalError(_("internal rcmd not implemented for Unix"), 0, 1);
6380 #define INPUT_SOURCE_BUF_SIZE 8192
6389 char buf[INPUT_SOURCE_BUF_SIZE];
6394 DoInputCallback(io,cond,data)
6399 /* read input from one of the input source (for example a chess program, ICS, etc).
6400 * and call a function that will handle the input
6403 int count; /* how many bytes did we read */
6407 /* All information (callback function, file descriptor, etc) is
6408 * saved in an InputSource structure
6410 InputSource *is = (InputSource *) data;
6414 count = read(is->fd, is->unused,
6415 INPUT_SOURCE_BUF_SIZE - (is->unused - is->buf));
6419 (is->func)(is, is->closure, is->buf, count, count ? errno : 0);
6422 is->unused += count;
6424 /* break input into lines and call the callback function on each
6427 while (p < is->unused)
6429 q = memchr(p, '\n', is->unused - p);
6430 if (q == NULL) break;
6432 (is->func)(is, is->closure, p, q - p, 0);
6435 /* remember not yet used part of the buffer */
6437 while (p < is->unused)
6445 /* read maximum length of input buffer and send the whole buffer
6446 * to the callback function
6448 count = read(is->fd, is->buf, INPUT_SOURCE_BUF_SIZE);
6453 (is->func)(is, is->closure, is->buf, count, error);
6459 InputSourceRef AddInputSource(pr, lineByLine, func, closure)
6466 GIOChannel *channel;
6467 ChildProc *cp = (ChildProc *) pr;
6469 is = (InputSource *) calloc(1, sizeof(InputSource));
6470 is->lineByLine = lineByLine;
6474 is->fd = fileno(stdin);
6476 is->kind = cp->kind;
6477 is->fd = cp->fdFrom;
6480 is->unused = is->buf;
6484 // is->xid = XtAppAddInput(appContext, is->fd,
6485 // (XtPointer) (XtInputReadMask),
6486 // (XtInputCallbackProc) DoInputCallback,
6490 /* TODO: will this work on windows?*/
6491 printf("DEBUG: fd=%d %d\n",is->fd,is);
6493 channel = g_io_channel_unix_new(is->fd);
6494 g_io_channel_set_close_on_unref (channel, TRUE);
6495 is->sid = g_io_add_watch(channel, G_IO_IN,(GIOFunc) DoInputCallback, is);
6496 is->closure = closure;
6497 return (InputSourceRef) is;
6501 RemoveInputSource(isr)
6504 InputSource *is = (InputSource *) isr;
6506 if (is->sid == 0) return;
6507 g_source_remove(is->sid);
6512 int OutputToProcess(pr, message, count, outError)
6518 ChildProc *cp = (ChildProc *) pr;
6522 outCount = fwrite(message, 1, count, stdout);
6524 outCount = write(cp->fdTo, message, count);
6534 /* Output message to process, with "ms" milliseconds of delay
6535 between each character. This is needed when sending the logon
6536 script to ICC, which for some reason doesn't like the
6537 instantaneous send. */
6538 int OutputToProcessDelayed(pr, message, count, outError, msdelay)
6545 ChildProc *cp = (ChildProc *) pr;
6550 r = write(cp->fdTo, message++, 1);
6563 /**** Animation code by Hugh Fisher, DCS, ANU.
6565 Known problem: if a window overlapping the board is
6566 moved away while a piece is being animated underneath,
6567 the newly exposed area won't be updated properly.
6568 I can live with this.
6570 Known problem: if you look carefully at the animation
6571 of pieces in mono mode, they are being drawn as solid
6572 shapes without interior detail while moving. Fixing
6573 this would be a major complication for minimal return.
6576 /* Masks for XPM pieces. Black and white pieces can have
6577 different shapes, but in the interest of retaining my
6578 sanity pieces must have the same outline on both light
6579 and dark squares, and all pieces must use the same
6580 background square colors/images. */
6582 static int xpmDone = 0;
6585 CreateAnimMasks (pieceDepth)
6592 unsigned long plane;
6595 /* just return for gtk at the moment */
6598 /* Need a bitmap just to get a GC with right depth */
6599 buf = XCreatePixmap(xDisplay, xBoardWindow,
6601 values.foreground = 1;
6602 values.background = 0;
6603 /* Don't use XtGetGC, not read only */
6604 maskGC = XCreateGC(xDisplay, buf,
6605 GCForeground | GCBackground, &values);
6606 XFreePixmap(xDisplay, buf);
6608 buf = XCreatePixmap(xDisplay, xBoardWindow,
6609 squareSize, squareSize, pieceDepth);
6610 values.foreground = XBlackPixel(xDisplay, xScreen);
6611 values.background = XWhitePixel(xDisplay, xScreen);
6612 bufGC = XCreateGC(xDisplay, buf,
6613 GCForeground | GCBackground, &values);
6615 for (piece = WhitePawn; piece <= BlackKing; piece++) {
6616 /* Begin with empty mask */
6617 if(!xpmDone) // [HGM] pieces: keep using existing
6618 xpmMask[piece] = XCreatePixmap(xDisplay, xBoardWindow,
6619 squareSize, squareSize, 1);
6620 XSetFunction(xDisplay, maskGC, GXclear);
6621 XFillRectangle(xDisplay, xpmMask[piece], maskGC,
6622 0, 0, squareSize, squareSize);
6624 /* Take a copy of the piece */
6629 XSetFunction(xDisplay, bufGC, GXcopy);
6630 XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % (int)BlackPawn],
6632 0, 0, squareSize, squareSize, 0, 0);
6634 /* XOR the background (light) over the piece */
6635 XSetFunction(xDisplay, bufGC, GXxor);
6637 XCopyArea(xDisplay, xpmLightSquare, buf, bufGC,
6638 0, 0, squareSize, squareSize, 0, 0);
6640 XSetForeground(xDisplay, bufGC, lightSquareColor);
6641 XFillRectangle(xDisplay, buf, bufGC, 0, 0, squareSize, squareSize);
6644 /* We now have an inverted piece image with the background
6645 erased. Construct mask by just selecting all the non-zero
6646 pixels - no need to reconstruct the original image. */
6647 XSetFunction(xDisplay, maskGC, GXor);
6649 /* Might be quicker to download an XImage and create bitmap
6650 data from it rather than this N copies per piece, but it
6651 only takes a fraction of a second and there is a much
6652 longer delay for loading the pieces. */
6653 for (n = 0; n < pieceDepth; n ++) {
6654 XCopyPlane(xDisplay, buf, xpmMask[piece], maskGC,
6655 0, 0, squareSize, squareSize,
6661 XFreePixmap(xDisplay, buf);
6662 XFreeGC(xDisplay, bufGC);
6663 XFreeGC(xDisplay, maskGC);
6667 InitAnimState (anim, info)
6669 XWindowAttributes * info;
6674 /* Each buffer is square size, same depth as window */
6675 // anim->saveBuf = XCreatePixmap(xDisplay, xBoardWindow,
6676 // squareSize, squareSize, info->depth);
6677 // anim->newBuf = XCreatePixmap(xDisplay, xBoardWindow,
6678 // squareSize, squareSize, info->depth);
6680 // /* Create a plain GC for blitting */
6681 // mask = GCForeground | GCBackground | GCFunction |
6682 // GCPlaneMask | GCGraphicsExposures;
6683 // values.foreground = XBlackPixel(xDisplay, xScreen);
6684 // values.background = XWhitePixel(xDisplay, xScreen);
6685 // values.function = GXcopy;
6686 // values.plane_mask = AllPlanes;
6687 // values.graphics_exposures = False;
6688 // anim->blitGC = XCreateGC(xDisplay, xBoardWindow, mask, &values);
6690 // /* Piece will be copied from an existing context at
6691 // the start of each new animation/drag. */
6692 // anim->pieceGC = XCreateGC(xDisplay, xBoardWindow, 0, &values);
6694 // /* Outline will be a read-only copy of an existing */
6695 // anim->outlineGC = None;
6701 static VariantClass old = (VariantClass) -1; // [HGM] pieces: redo every time variant changes
6702 XWindowAttributes info;
6704 /* for gtk at the moment just ... */
6707 if (xpmDone && gameInfo.variant == old) return;
6708 if(xpmDone) old = gameInfo.variant; // first time pieces might not be created yet
6709 // XGetWindowAttributes(xDisplay, xBoardWindow, &info);
6711 // InitAnimState(&game, &info);
6712 // InitAnimState(&player, &info);
6714 /* For XPM pieces, we need bitmaps to use as masks. */
6716 // CreateAnimMasks(info.depth);
6722 static Boolean frameWaiting;
6724 static RETSIGTYPE FrameAlarm (sig)
6727 frameWaiting = False;
6728 /* In case System-V style signals. Needed?? */
6729 signal(SIGALRM, FrameAlarm);
6736 struct itimerval delay;
6738 XSync(xDisplay, False);
6741 frameWaiting = True;
6742 signal(SIGALRM, FrameAlarm);
6743 delay.it_interval.tv_sec =
6744 delay.it_value.tv_sec = time / 1000;
6745 delay.it_interval.tv_usec =
6746 delay.it_value.tv_usec = (time % 1000) * 1000;
6747 setitimer(ITIMER_REAL, &delay, NULL);
6748 while (frameWaiting) pause();
6749 delay.it_interval.tv_sec = delay.it_value.tv_sec = 0;
6750 delay.it_interval.tv_usec = delay.it_value.tv_usec = 0;
6751 setitimer(ITIMER_REAL, &delay, NULL);
6761 // XSync(xDisplay, False);
6763 usleep(time * 1000);
6768 /* Convert board position to corner of screen rect and color */
6771 ScreenSquare(column, row, pt, color)
6772 int column; int row; XPoint * pt; int * color;
6775 pt->x = lineGap + ((BOARD_WIDTH-1)-column) * (squareSize + lineGap);
6776 pt->y = lineGap + row * (squareSize + lineGap);
6778 pt->x = lineGap + column * (squareSize + lineGap);
6779 pt->y = lineGap + ((BOARD_HEIGHT-1)-row) * (squareSize + lineGap);
6781 *color = SquareColor(row, column);
6784 /* Convert window coords to square */
6787 BoardSquare(x, y, column, row)
6788 int x; int y; int * column; int * row;
6790 *column = EventToSquare(x, BOARD_WIDTH);
6791 if (flipView && *column >= 0)
6792 *column = BOARD_WIDTH - 1 - *column;
6793 *row = EventToSquare(y, BOARD_HEIGHT);
6794 if (!flipView && *row >= 0)
6795 *row = BOARD_HEIGHT - 1 - *row;
6800 #undef Max /* just in case */
6802 #define Max(a, b) ((a) > (b) ? (a) : (b))
6803 #define Min(a, b) ((a) < (b) ? (a) : (b))
6806 SetRect(rect, x, y, width, height)
6807 XRectangle * rect; int x; int y; int width; int height;
6811 rect->width = width;
6812 rect->height = height;
6815 /* Test if two frames overlap. If they do, return
6816 intersection rect within old and location of
6817 that rect within new. */
6820 Intersect(old, new, size, area, pt)
6821 XPoint * old; XPoint * new;
6822 int size; XRectangle * area; XPoint * pt;
6824 if (old->x > new->x + size || new->x > old->x + size ||
6825 old->y > new->y + size || new->y > old->y + size) {
6828 SetRect(area, Max(new->x - old->x, 0), Max(new->y - old->y, 0),
6829 size - abs(old->x - new->x), size - abs(old->y - new->y));
6830 pt->x = Max(old->x - new->x, 0);
6831 pt->y = Max(old->y - new->y, 0);
6836 /* For two overlapping frames, return the rect(s)
6837 in the old that do not intersect with the new. */
6840 CalcUpdateRects(old, new, size, update, nUpdates)
6841 XPoint * old; XPoint * new; int size;
6842 XRectangle update[]; int * nUpdates;
6846 /* If old = new (shouldn't happen) then nothing to draw */
6847 if (old->x == new->x && old->y == new->y) {
6851 /* Work out what bits overlap. Since we know the rects
6852 are the same size we don't need a full intersect calc. */
6854 /* Top or bottom edge? */
6855 if (new->y > old->y) {
6856 SetRect(&(update[count]), old->x, old->y, size, new->y - old->y);
6858 } else if (old->y > new->y) {
6859 SetRect(&(update[count]), old->x, old->y + size - (old->y - new->y),
6860 size, old->y - new->y);
6863 /* Left or right edge - don't overlap any update calculated above. */
6864 if (new->x > old->x) {
6865 SetRect(&(update[count]), old->x, Max(new->y, old->y),
6866 new->x - old->x, size - abs(new->y - old->y));
6868 } else if (old->x > new->x) {
6869 SetRect(&(update[count]), new->x + size, Max(new->y, old->y),
6870 old->x - new->x, size - abs(new->y - old->y));
6877 /* Generate a series of frame coords from start->mid->finish.
6878 The movement rate doubles until the half way point is
6879 reached, then halves back down to the final destination,
6880 which gives a nice slow in/out effect. The algorithmn
6881 may seem to generate too many intermediates for short
6882 moves, but remember that the purpose is to attract the
6883 viewers attention to the piece about to be moved and
6884 then to where it ends up. Too few frames would be less
6888 Tween(start, mid, finish, factor, frames, nFrames)
6889 XPoint * start; XPoint * mid;
6890 XPoint * finish; int factor;
6891 XPoint frames[]; int * nFrames;
6893 int fraction, n, count;
6897 /* Slow in, stepping 1/16th, then 1/8th, ... */
6899 for (n = 0; n < factor; n++)
6901 for (n = 0; n < factor; n++) {
6902 frames[count].x = start->x + (mid->x - start->x) / fraction;
6903 frames[count].y = start->y + (mid->y - start->y) / fraction;
6905 fraction = fraction / 2;
6909 frames[count] = *mid;
6912 /* Slow out, stepping 1/2, then 1/4, ... */
6914 for (n = 0; n < factor; n++) {
6915 frames[count].x = finish->x - (finish->x - mid->x) / fraction;
6916 frames[count].y = finish->y - (finish->y - mid->y) / fraction;
6918 fraction = fraction * 2;
6923 /* Draw a piece on the screen without disturbing what's there */
6926 SelectGCMask(piece, clip, outline, mask)
6927 ChessSquare piece; GC * clip; GC * outline; Pixmap * mask;
6931 /* Bitmap for piece being moved. */
6932 if (appData.monoMode) {
6933 *mask = *pieceToSolid(piece);
6934 } else if (useImages) {
6936 *mask = xpmMask[piece];
6938 *mask = ximMaskPm[piece];
6941 *mask = *pieceToSolid(piece);
6944 /* GC for piece being moved. Square color doesn't matter, but
6945 since it gets modified we make a copy of the original. */
6947 if (appData.monoMode)
6952 if (appData.monoMode)
6957 // XCopyGC(xDisplay, source, 0xFFFFFFFF, *clip);
6959 /* Outline only used in mono mode and is not modified */
6961 *outline = bwPieceGC;
6963 *outline = wbPieceGC;
6967 OverlayPiece(piece, clip, outline, dest)
6968 ChessSquare piece; GC clip; GC outline; Drawable dest;
6973 /* Draw solid rectangle which will be clipped to shape of piece */
6974 // XFillRectangle(xDisplay, dest, clip,
6975 // 0, 0, squareSize, squareSize)
6977 if (appData.monoMode)
6978 /* Also draw outline in contrasting color for black
6979 on black / white on white cases */
6980 // XCopyPlane(xDisplay, *pieceToOutline(piece), dest, outline,
6981 // 0, 0, squareSize, squareSize, 0, 0, 1)
6984 /* Copy the piece */
6989 // XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
6991 // 0, 0, squareSize, squareSize,
6996 /* Animate the movement of a single piece */
6999 BeginAnimation(anim, piece, startColor, start)
7007 /* The old buffer is initialised with the start square (empty) */
7008 BlankSquare(0, 0, startColor, EmptySquare, anim->saveBuf);
7009 anim->prevFrame = *start;
7011 /* The piece will be drawn using its own bitmap as a matte */
7012 // SelectGCMask(piece, &anim->pieceGC, &anim->outlineGC, &mask);
7013 // XSetClipMask(xDisplay, anim->pieceGC, mask);
7017 AnimationFrame(anim, frame, piece)
7022 XRectangle updates[4];
7027 /* Save what we are about to draw into the new buffer */
7028 // XCopyArea(xDisplay, xBoardWindow, anim->newBuf, anim->blitGC,
7029 // frame->x, frame->y, squareSize, squareSize,
7032 /* Erase bits of the previous frame */
7033 if (Intersect(&anim->prevFrame, frame, squareSize, &overlap, &pt)) {
7034 /* Where the new frame overlapped the previous,
7035 the contents in newBuf are wrong. */
7036 // XCopyArea(xDisplay, anim->saveBuf, anim->newBuf, anim->blitGC,
7037 // overlap.x, overlap.y,
7038 // overlap.width, overlap.height,
7040 /* Repaint the areas in the old that don't overlap new */
7041 CalcUpdateRects(&anim->prevFrame, frame, squareSize, updates, &count);
7042 for (i = 0; i < count; i++)
7043 // XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
7044 // updates[i].x - anim->prevFrame.x,
7045 // updates[i].y - anim->prevFrame.y,
7046 // updates[i].width, updates[i].height,
7047 // updates[i].x, updates[i].y)
7050 /* Easy when no overlap */
7051 // XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
7052 // 0, 0, squareSize, squareSize,
7053 // anim->prevFrame.x, anim->prevFrame.y);
7056 /* Save this frame for next time round */
7057 // XCopyArea(xDisplay, anim->newBuf, anim->saveBuf, anim->blitGC,
7058 // 0, 0, squareSize, squareSize,
7060 anim->prevFrame = *frame;
7062 /* Draw piece over original screen contents, not current,
7063 and copy entire rect. Wipes out overlapping piece images. */
7064 OverlayPiece(piece, anim->pieceGC, anim->outlineGC, anim->newBuf);
7065 // XCopyArea(xDisplay, anim->newBuf, xBoardWindow, anim->blitGC,
7066 // 0, 0, squareSize, squareSize,
7067 // frame->x, frame->y);
7071 EndAnimation (anim, finish)
7075 XRectangle updates[4];
7080 /* The main code will redraw the final square, so we
7081 only need to erase the bits that don't overlap. */
7082 if (Intersect(&anim->prevFrame, finish, squareSize, &overlap, &pt)) {
7083 CalcUpdateRects(&anim->prevFrame, finish, squareSize, updates, &count);
7084 for (i = 0; i < count; i++)
7085 // XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
7086 // updates[i].x - anim->prevFrame.x,
7087 // updates[i].y - anim->prevFrame.y,
7088 // updates[i].width, updates[i].height,
7089 // updates[i].x, updates[i].y)
7092 // XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
7093 // 0, 0, squareSize, squareSize,
7094 // anim->prevFrame.x, anim->prevFrame.y);
7099 FrameSequence(anim, piece, startColor, start, finish, frames, nFrames)
7101 ChessSquare piece; int startColor;
7102 XPoint * start; XPoint * finish;
7103 XPoint frames[]; int nFrames;
7107 BeginAnimation(anim, piece, startColor, start);
7108 for (n = 0; n < nFrames; n++) {
7109 AnimationFrame(anim, &(frames[n]), piece);
7110 FrameDelay(appData.animSpeed);
7112 EndAnimation(anim, finish);
7115 /* Main control logic for deciding what to animate and how */
7118 AnimateMove(board, fromX, fromY, toX, toY)
7127 XPoint start, finish, mid;
7128 XPoint frames[kFactor * 2 + 1];
7129 int nFrames, startColor, endColor;
7131 /* Are we animating? */
7132 if (!appData.animate || appData.blindfold)
7135 if(board[toY][toX] == WhiteRook && board[fromY][fromX] == WhiteKing ||
7136 board[toY][toX] == BlackRook && board[fromY][fromX] == BlackKing)
7137 return; // [HGM] FRC: no animtion of FRC castlings, as to-square is not true to-square
7139 if (fromY < 0 || fromX < 0 || toX < 0 || toY < 0) return;
7140 piece = board[fromY][fromX];
7141 if (piece >= EmptySquare) return;
7146 hop = (piece == WhiteKnight || piece == BlackKnight);
7149 if (appData.debugMode) {
7150 fprintf(debugFP, hop ? _("AnimateMove: piece %d hops from %d,%d to %d,%d \n") :
7151 _("AnimateMove: piece %d slides from %d,%d to %d,%d \n"),
7152 piece, fromX, fromY, toX, toY); }
7154 ScreenSquare(fromX, fromY, &start, &startColor);
7155 ScreenSquare(toX, toY, &finish, &endColor);
7158 /* Knight: make diagonal movement then straight */
7159 if (abs(toY - fromY) < abs(toX - fromX)) {
7160 mid.x = start.x + (finish.x - start.x) / 2;
7164 mid.y = start.y + (finish.y - start.y) / 2;
7167 mid.x = start.x + (finish.x - start.x) / 2;
7168 mid.y = start.y + (finish.y - start.y) / 2;
7171 /* Don't use as many frames for very short moves */
7172 if (abs(toY - fromY) + abs(toX - fromX) <= 2)
7173 Tween(&start, &mid, &finish, kFactor - 1, frames, &nFrames);
7175 Tween(&start, &mid, &finish, kFactor, frames, &nFrames);
7176 FrameSequence(&game, piece, startColor, &start, &finish, frames, nFrames);
7178 /* Be sure end square is redrawn */
7179 damage[toY][toX] = True;
7183 DragPieceBegin(x, y)
7186 int boardX, boardY, color;
7189 /* Are we animating? */
7190 if (!appData.animateDragging || appData.blindfold)
7193 /* Figure out which square we start in and the
7194 mouse position relative to top left corner. */
7195 BoardSquare(x, y, &boardX, &boardY);
7196 player.startBoardX = boardX;
7197 player.startBoardY = boardY;
7198 ScreenSquare(boardX, boardY, &corner, &color);
7199 player.startSquare = corner;
7200 player.startColor = color;
7201 /* As soon as we start dragging, the piece will jump slightly to
7202 be centered over the mouse pointer. */
7203 player.mouseDelta.x = squareSize/2;
7204 player.mouseDelta.y = squareSize/2;
7205 /* Initialise animation */
7206 player.dragPiece = PieceForSquare(boardX, boardY);
7208 if (player.dragPiece >= 0 && player.dragPiece < EmptySquare) {
7209 player.dragActive = True;
7210 BeginAnimation(&player, player.dragPiece, color, &corner);
7211 /* Mark this square as needing to be redrawn. Note that
7212 we don't remove the piece though, since logically (ie
7213 as seen by opponent) the move hasn't been made yet. */
7214 if(boardX == BOARD_RGHT+1 && PieceForSquare(boardX-1, boardY) > 1 ||
7215 boardX == BOARD_LEFT-2 && PieceForSquare(boardX+1, boardY) > 1)
7216 // XCopyArea(xDisplay, xBoardWindow, player.saveBuf, player.blitGC,
7217 // corner.x, corner.y, squareSize, squareSize,
7218 // 0, 0); // [HGM] zh: unstack in stead of grab
7219 damage[boardY][boardX] = True;
7221 player.dragActive = False;
7231 /* Are we animating? */
7232 if (!appData.animateDragging || appData.blindfold)
7236 if (! player.dragActive)
7238 /* Move piece, maintaining same relative position
7239 of mouse within square */
7240 corner.x = x - player.mouseDelta.x;
7241 corner.y = y - player.mouseDelta.y;
7242 AnimationFrame(&player, &corner, player.dragPiece);
7244 if (appData.highlightDragging) {
7246 BoardSquare(x, y, &boardX, &boardY);
7247 SetHighlights(fromX, fromY, boardX, boardY);
7256 int boardX, boardY, color;
7259 /* Are we animating? */
7260 if (!appData.animateDragging || appData.blindfold)
7264 if (! player.dragActive)
7266 /* Last frame in sequence is square piece is
7267 placed on, which may not match mouse exactly. */
7268 BoardSquare(x, y, &boardX, &boardY);
7269 ScreenSquare(boardX, boardY, &corner, &color);
7270 EndAnimation(&player, &corner);
7272 /* Be sure end square is redrawn */
7273 damage[boardY][boardX] = True;
7275 /* This prevents weird things happening with fast successive
7276 clicks which on my Sun at least can cause motion events
7277 without corresponding press/release. */
7278 player.dragActive = False;
7281 /* Handle expose event while piece being dragged */
7286 if (!player.dragActive || appData.blindfold)
7289 /* What we're doing: logically, the move hasn't been made yet,
7290 so the piece is still in it's original square. But visually
7291 it's being dragged around the board. So we erase the square
7292 that the piece is on and draw it at the last known drag point. */
7293 BlankSquare(player.startSquare.x, player.startSquare.y,
7294 player.startColor, EmptySquare, xBoardWindow);
7295 AnimationFrame(&player, &player.prevFrame, player.dragPiece);
7296 damage[player.startBoardY][player.startBoardX] = TRUE;
7300 SetProgramStats( FrontEndProgramStats * stats )
7303 // [HGM] done, but perhaps backend should call this directly?
7304 EngineOutputUpdate( stats );
7307 #include <sys/ioctl.h>
7308 int get_term_width()
7310 int fd, default_width;
7313 default_width = 79; // this is FICS default anyway...
7315 #if !defined(TIOCGWINSZ) && defined(TIOCGSIZE)
7317 if (!ioctl(fd, TIOCGSIZE, &win))
7318 default_width = win.ts_cols;
7319 #elif defined(TIOCGWINSZ)
7321 if (!ioctl(fd, TIOCGWINSZ, &win))
7322 default_width = win.ws_col;
7324 return default_width;
7327 void update_ics_width()
7329 static int old_width = 0;
7330 int new_width = get_term_width();
7332 if (old_width != new_width)
7333 ics_printf("set width %d\n", new_width);
7334 old_width = new_width;
7337 void NotifyFrontendLogin()