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)
238 int main P((int argc, char **argv));
239 RETSIGTYPE CmailSigHandler P((int sig));
240 RETSIGTYPE IntSigHandler P((int sig));
241 void CreateGCs P((void));
242 void CreateXIMPieces P((void));
243 void CreateXPMPieces P((void));
244 void CreatePieces P((void));
245 void CreatePieceMenus P((void));
246 Widget CreateMenuBar P((Menu *mb));
247 Widget CreateButtonBar P ((MenuItem *mi));
248 char *FindFont P((char *pattern, int targetPxlSize));
249 void PieceMenuPopup P((Widget w, XEvent *event,
250 String *params, Cardinal *num_params));
251 static void PieceMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
252 static void DropMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
253 void CreateGrid P((void));
254 int EventToSquare P((int x, int limit));
255 void DrawSquare P((int row, int column, ChessSquare piece, int do_flash));
256 void HandleUserMove P((Widget w, XEvent *event,
257 String *prms, Cardinal *nprms));
258 void AnimateUserMove P((Widget w, XEvent * event,
259 String * params, Cardinal * nParams));
260 void WhiteClock P((Widget w, XEvent *event,
261 String *prms, Cardinal *nprms));
262 void BlackClock P((Widget w, XEvent *event,
263 String *prms, Cardinal *nprms));
264 void DrawPositionProc P((Widget w, XEvent *event,
265 String *prms, Cardinal *nprms));
266 void CommentPopUp P((char *title, char *label));
267 void CommentPopDown P((void));
268 void CommentCallback P((Widget w, XtPointer client_data,
269 XtPointer call_data));
270 void ICSInputBoxPopUp P((void));
271 void ICSInputBoxPopDown P((void));
272 void FileNamePopUp P((char *label, char *def,
273 FileProc proc, char *openMode));
274 void FileNamePopDown P((void));
275 void FileNameCallback P((Widget w, XtPointer client_data,
276 XtPointer call_data));
277 void FileNameAction P((Widget w, XEvent *event,
278 String *prms, Cardinal *nprms));
279 void AskQuestionReplyAction P((Widget w, XEvent *event,
280 String *prms, Cardinal *nprms));
281 void AskQuestionProc P((Widget w, XEvent *event,
282 String *prms, Cardinal *nprms));
283 void AskQuestionPopDown P((void));
284 void PromotionPopUp P((void));
285 void PromotionPopDown P((void));
286 void PromotionCallback P((Widget w, XtPointer client_data,
287 XtPointer call_data));
288 void EditCommentPopDown P((void));
289 void EditCommentCallback P((Widget w, XtPointer client_data,
290 XtPointer call_data));
291 void SelectCommand P((Widget w, XtPointer client_data, XtPointer call_data));
292 void LoadPositionProc P((Widget w, XEvent *event,
293 String *prms, Cardinal *nprms));
294 void LoadNextPositionProc P((Widget w, XEvent *event, String *prms,
296 void LoadPrevPositionProc P((Widget w, XEvent *event, String *prms,
298 void ReloadPositionProc P((Widget w, XEvent *event, String *prms,
300 void CopyPositionProc P((Widget w, XEvent *event, String *prms,
302 void PastePositionProc P((Widget w, XEvent *event, String *prms,
304 void CopyGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
305 void PasteGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
306 void SaveGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
307 void SavePositionProc P((Widget w, XEvent *event,
308 String *prms, Cardinal *nprms));
309 void MailMoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
310 void ReloadCmailMsgProc P((Widget w, XEvent *event, String *prms,
312 void MachineBlackProc P((Widget w, XEvent *event, String *prms,
314 void MachineWhiteProc P((Widget w, XEvent *event,
315 String *prms, Cardinal *nprms));
316 void AnalyzeModeProc P((Widget w, XEvent *event,
317 String *prms, Cardinal *nprms));
318 void AnalyzeFileProc P((Widget w, XEvent *event,
319 String *prms, Cardinal *nprms));
320 void TwoMachinesProc P((Widget w, XEvent *event, String *prms,
322 void IcsClientProc P((Widget w, XEvent *event, String *prms,
324 void EditGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
325 void EditPositionProc P((Widget w, XEvent *event,
326 String *prms, Cardinal *nprms));
327 void TrainingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
328 void EditCommentProc P((Widget w, XEvent *event,
329 String *prms, Cardinal *nprms));
330 void IcsInputBoxProc P((Widget w, XEvent *event,
331 String *prms, Cardinal *nprms));
332 void AcceptProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
333 void DeclineProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
334 void RematchProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
335 void CallFlagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
336 void DrawProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
337 void AbortProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
338 void AdjournProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
339 void ResignProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
340 void AdjuWhiteProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
341 void AdjuBlackProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
342 void AdjuDrawProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
343 void EnterKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
344 void StopObservingProc P((Widget w, XEvent *event, String *prms,
346 void StopExaminingProc P((Widget w, XEvent *event, String *prms,
348 void BackwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
349 void ForwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
350 void ToStartProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
351 void ToEndProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
352 void RevertProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
353 void TruncateGameProc P((Widget w, XEvent *event, String *prms,
355 void RetractMoveProc P((Widget w, XEvent *event, String *prms,
357 void MoveNowProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
358 void AlwaysQueenProc P((Widget w, XEvent *event, String *prms,
360 void AnimateDraggingProc P((Widget w, XEvent *event, String *prms,
362 void AnimateMovingProc P((Widget w, XEvent *event, String *prms,
364 void AutocommProc P((Widget w, XEvent *event, String *prms,
366 void AutoflagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
367 void AutoflipProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
368 void AutobsProc P((Widget w, XEvent *event, String *prms,
370 void AutoraiseProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
371 void AutosaveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
372 void BlindfoldProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
373 void FlashMovesProc P((Widget w, XEvent *event, String *prms,
375 void FlipViewProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
376 void GetMoveListProc P((Widget w, XEvent *event, String *prms,
378 void HighlightDraggingProc P((Widget w, XEvent *event, String *prms,
380 void HighlightLastMoveProc P((Widget w, XEvent *event, String *prms,
382 void MoveSoundProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
383 void IcsAlarmProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
384 void OldSaveStyleProc P((Widget w, XEvent *event, String *prms,
386 void PeriodicUpdatesProc P((Widget w, XEvent *event, String *prms,
388 void PonderNextMoveProc P((Widget w, XEvent *event, String *prms,
390 void PopupMoveErrorsProc P((Widget w, XEvent *event, String *prms,
392 void PopupExitMessageProc P((Widget w, XEvent *event, String *prms,
394 void PremoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
395 void QuietPlayProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
396 void ShowThinkingProc P((Widget w, XEvent *event, String *prms,
398 void HideThinkingProc P((Widget w, XEvent *event, String *prms,
400 void TestLegalityProc P((Widget w, XEvent *event, String *prms,
402 void InfoProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
403 void ManProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
404 void HintProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
405 void BookProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
406 void AboutGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
407 void DebugProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
408 void NothingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
409 void Iconify P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
410 void DisplayMove P((int moveNumber));
411 void DisplayTitle P((char *title));
412 void ICSInitScript P((void));
413 int LoadGamePopUp P((FILE *f, int gameNumber, char *title));
414 void ErrorPopUp P((char *title, char *text, int modal));
415 void ErrorPopDown P((void));
416 static char *ExpandPathName P((char *path));
417 static void CreateAnimVars P((void));
418 void DragPieceBegin P((int x, int y));
419 static void DragPieceMove P((int x, int y));
420 void DragPieceEnd P((int x, int y));
421 static void DrawDragPiece P((void));
422 char *ModeToWidgetName P((GameMode mode));
423 void EngineOutputUpdate( FrontEndProgramStats * stats );
424 void ShuffleMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
425 void EngineMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
426 void UciMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
427 void TimeControlProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
428 void NewVariantProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
429 void FirstSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
430 void SecondSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
431 void ShufflePopDown P(());
432 void EnginePopDown P(());
433 void UciPopDown P(());
434 void TimeControlPopDown P(());
435 void NewVariantPopDown P(());
436 void SettingsPopDown P(());
438 * XBoard depends on Xt R4 or higher
440 int xtVersion = XtSpecificationRelease;
445 Pixel lightSquareColor, darkSquareColor, whitePieceColor, blackPieceColor,
446 jailSquareColor, highlightSquareColor, premoveHighlightColor;
447 Pixel lowTimeWarningColor;
448 GC lightSquareGC, darkSquareGC, jailSquareGC, lineGC, wdPieceGC, wlPieceGC,
449 bdPieceGC, blPieceGC, wbPieceGC, bwPieceGC, coordGC, highlineGC,
450 wjPieceGC, bjPieceGC, prelineGC, countGC;
451 Pixmap iconPixmap, wIconPixmap, bIconPixmap, xMarkPixmap;
452 Widget shellWidget, layoutWidget, formWidget, boardWidget, messageWidget,
453 whiteTimerWidget, blackTimerWidget, titleWidget, widgetList[16],
454 commentShell, promotionShell, whitePieceMenu, blackPieceMenu, dropMenu,
455 menuBarWidget, buttonBarWidget, editShell, errorShell, analysisShell,
456 ICSInputShell, fileNameShell, askQuestionShell;
457 GdkSegment gridSegments[(BOARD_SIZE + 1) * 2];
458 XSegment jailGridSegments[(BOARD_SIZE + 3) * 2];
459 Font clockFontID, coordFontID, countFontID;
460 XFontStruct *clockFontStruct, *coordFontStruct, *countFontStruct;
461 XtAppContext appContext;
463 char *oldICSInteractionTitle;
467 char installDir[] = "."; // [HGM] UCI: needed for UCI; probably needs run-time initializtion
469 Position commentX = -1, commentY = -1;
470 Dimension commentW, commentH;
472 int squareSize, smallLayout = 0, tinyLayout = 0,
473 marginW, marginH, // [HGM] for run-time resizing
474 fromX = -1, fromY = -1, toX, toY, commentUp = False, analysisUp = False,
475 ICSInputBoxUp = False, askQuestionUp = False,
476 filenameUp = False, promotionUp = False, pmFromX = -1, pmFromY = -1,
477 editUp = False, errorUp = False, errorExitStatus = -1, lineGap;
478 Pixel timerForegroundPixel, timerBackgroundPixel;
479 Pixel buttonForegroundPixel, buttonBackgroundPixel;
480 char *chessDir, *programName, *programVersion,
481 *gameCopyFilename, *gamePasteFilename;
485 Pixmap pieceBitmap[2][(int)BlackPawn];
486 Pixmap pieceBitmap2[2][(int)BlackPawn+4]; /* [HGM] pieces */
487 Pixmap xpmPieceBitmap[4][(int)BlackPawn]; /* LL, LD, DL, DD actually used*/
488 Pixmap xpmPieceBitmap2[4][(int)BlackPawn+4]; /* LL, LD, DL, DD set to select from */
489 Pixmap xpmLightSquare, xpmDarkSquare, xpmJailSquare;
490 int useImages=0, useImageSqs;
491 XImage *ximPieceBitmap[4][(int)BlackPawn+4]; /* LL, LD, DL, DD */
492 Pixmap ximMaskPm[(int)BlackPawn]; /* clipmasks, used for XIM pieces */
493 Pixmap ximMaskPm2[(int)BlackPawn+4]; /* clipmasks, used for XIM pieces */
494 XImage *ximLightSquare, *ximDarkSquare;
497 #define pieceToSolid(piece) &pieceBitmap[SOLID][(piece) % (int)BlackPawn]
498 #define pieceToOutline(piece) &pieceBitmap[OUTLINE][(piece) % (int)BlackPawn]
500 #define White(piece) ((int)(piece) < (int)BlackPawn)
502 /* Variables for doing smooth animation. This whole thing
503 would be much easier if the board was double-buffered,
504 but that would require a fairly major rewrite. */
509 GC blitGC, pieceGC, outlineGC;
510 XPoint startSquare, prevFrame, mouseDelta;
514 int startBoardX, startBoardY;
517 /* There can be two pieces being animated at once: a player
518 can begin dragging a piece before the remote opponent has moved. */
520 static AnimState game, player;
522 /* Bitmaps for use as masks when drawing XPM pieces.
523 Need one for each black and white piece. */
524 static Pixmap xpmMask[BlackKing + 1];
526 /* This magic number is the number of intermediate frames used
527 in each half of the animation. For short moves it's reduced
528 by 1. The total number of frames will be factor * 2 + 1. */
531 SizeDefaults sizeDefaults[] = SIZE_DEFAULTS;
533 MenuItem fileMenu[] = {
534 {N_("New Shuffle Game ..."), ShuffleMenuProc},
535 {N_("New Variant ..."), NewVariantProc}, // [HGM] variant: not functional yet
536 {"----", NothingProc},
537 {N_("Save Game"), SaveGameProc},
538 {"----", NothingProc},
539 {N_("Copy Game"), CopyGameProc},
540 {N_("Paste Game"), PasteGameProc},
541 {"----", NothingProc},
542 {N_("Load Position"), LoadPositionProc},
543 {N_("Load Next Position"), LoadNextPositionProc},
544 {N_("Load Previous Position"), LoadPrevPositionProc},
545 {N_("Reload Same Position"), ReloadPositionProc},
546 {N_("Save Position"), SavePositionProc},
547 {"----", NothingProc},
548 {N_("Copy Position"), CopyPositionProc},
549 {N_("Paste Position"), PastePositionProc},
550 {"----", NothingProc},
551 {N_("Mail Move"), MailMoveProc},
552 {N_("Reload CMail Message"), ReloadCmailMsgProc},
553 {"----", NothingProc},
557 MenuItem modeMenu[] = {
558 {N_("Machine White"), MachineWhiteProc},
559 {N_("Machine Black"), MachineBlackProc},
560 {N_("Two Machines"), TwoMachinesProc},
561 {N_("Analysis Mode"), AnalyzeModeProc},
562 {N_("Analyze File"), AnalyzeFileProc },
563 {N_("ICS Client"), IcsClientProc},
564 {N_("Edit Game"), EditGameProc},
565 {N_("Edit Position"), EditPositionProc},
566 {N_("Training"), TrainingProc},
567 {"----", NothingProc},
568 {N_("Show Engine Output"), EngineOutputProc},
569 {N_("Show Evaluation Graph"), NothingProc}, // [HGM] evalgr: not functional yet
570 {N_("Show Game List"), ShowGameListProc},
571 {"Show Move History", HistoryShowProc}, // [HGM] hist: activate 4.2.7 code
572 {"----", NothingProc},
573 {N_("Edit Tags"), EditTagsProc},
574 {N_("Edit Comment"), EditCommentProc},
575 {N_("ICS Input Box"), IcsInputBoxProc},
579 MenuItem actionMenu[] = {
580 {N_("Accept"), AcceptProc},
581 {N_("Decline"), DeclineProc},
582 {N_("Rematch"), RematchProc},
583 {"----", NothingProc},
584 {N_("Call Flag"), CallFlagProc},
585 {N_("Draw"), DrawProc},
586 {N_("Adjourn"), AdjournProc},
587 {N_("Abort"), AbortProc},
588 {N_("Resign"), ResignProc},
589 {"----", NothingProc},
590 {N_("Stop Observing"), StopObservingProc},
591 {N_("Stop Examining"), StopExaminingProc},
592 {"----", NothingProc},
593 {N_("Adjudicate to White"), AdjuWhiteProc},
594 {N_("Adjudicate to Black"), AdjuBlackProc},
595 {N_("Adjudicate Draw"), AdjuDrawProc},
599 MenuItem stepMenu[] = {
600 {N_("Backward"), BackwardProc},
601 {N_("Forward"), ForwardProc},
602 {N_("Back to Start"), ToStartProc},
603 {N_("Forward to End"), ToEndProc},
604 {N_("Revert"), RevertProc},
605 {N_("Truncate Game"), TruncateGameProc},
606 {"----", NothingProc},
607 {N_("Move Now"), MoveNowProc},
608 {N_("Retract Move"), RetractMoveProc},
612 MenuItem optionsMenu[] = {
613 {N_("Flip View"), FlipViewProc},
614 {"----", NothingProc},
615 {N_("Adjudications ..."), EngineMenuProc},
616 {N_("General Settings ..."), UciMenuProc},
617 {N_("Engine #1 Settings ..."), FirstSettingsProc},
618 {N_("Engine #2 Settings ..."), SecondSettingsProc},
619 {N_("Time Control ..."), TimeControlProc},
620 {"----", NothingProc},
621 {N_("Always Queen"), AlwaysQueenProc},
622 {N_("Animate Dragging"), AnimateDraggingProc},
623 {N_("Animate Moving"), AnimateMovingProc},
624 {N_("Auto Comment"), AutocommProc},
625 {N_("Auto Flag"), AutoflagProc},
626 {N_("Auto Flip View"), AutoflipProc},
627 {N_("Auto Observe"), AutobsProc},
628 {N_("Auto Raise Board"), AutoraiseProc},
629 {N_("Auto Save"), AutosaveProc},
630 {N_("Blindfold"), BlindfoldProc},
631 {N_("Flash Moves"), FlashMovesProc},
632 {N_("Get Move List"), GetMoveListProc},
634 {N_("Highlight Dragging"), HighlightDraggingProc},
636 {N_("Highlight Last Move"), HighlightLastMoveProc},
637 {N_("Move Sound"), MoveSoundProc},
638 {N_("ICS Alarm"), IcsAlarmProc},
639 {N_("Old Save Style"), OldSaveStyleProc},
640 {N_("Periodic Updates"), PeriodicUpdatesProc},
641 {N_("Ponder Next Move"), PonderNextMoveProc},
642 {N_("Popup Exit Message"), PopupExitMessageProc},
643 {N_("Popup Move Errors"), PopupMoveErrorsProc},
644 {N_("Premove"), PremoveProc},
645 {N_("Quiet Play"), QuietPlayProc},
646 {N_("Hide Thinking"), HideThinkingProc},
647 {N_("Test Legality"), TestLegalityProc},
651 MenuItem helpMenu[] = {
652 {N_("Info XBoard"), InfoProc},
653 {N_("Man XBoard"), ManProc},
654 {"----", NothingProc},
655 {N_("Hint"), HintProc},
656 {N_("Book"), BookProc},
657 {"----", NothingProc},
662 {N_("File"), fileMenu},
663 {N_("Mode"), modeMenu},
664 {N_("Action"), actionMenu},
665 {N_("Step"), stepMenu},
666 {N_("Options"), optionsMenu},
667 {N_("Help"), helpMenu},
671 #define PAUSE_BUTTON N_("P")
672 MenuItem buttonBar[] = {
675 // {PAUSE_BUTTON, PauseProc},
681 #define PIECE_MENU_SIZE 18
682 String pieceMenuStrings[2][PIECE_MENU_SIZE] = {
683 { N_("White"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
684 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
685 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
686 N_("Empty square"), N_("Clear board") },
687 { N_("Black"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
688 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
689 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
690 N_("Empty square"), N_("Clear board") }
692 /* must be in same order as PieceMenuStrings! */
693 ChessSquare pieceMenuTranslation[2][PIECE_MENU_SIZE] = {
694 { WhitePlay, (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
695 WhiteRook, WhiteQueen, WhiteKing, (ChessSquare) 0, WhiteAlfil,
696 WhiteCannon, WhiteAngel, WhiteMarshall, (ChessSquare) 0,
697 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
698 { BlackPlay, (ChessSquare) 0, BlackPawn, BlackKnight, BlackBishop,
699 BlackRook, BlackQueen, BlackKing, (ChessSquare) 0, BlackAlfil,
700 BlackCannon, BlackAngel, BlackMarshall, (ChessSquare) 0,
701 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
704 #define DROP_MENU_SIZE 6
705 String dropMenuStrings[DROP_MENU_SIZE] = {
706 "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"), N_("Queen")
708 /* must be in same order as PieceMenuStrings! */
709 ChessSquare dropMenuTranslation[DROP_MENU_SIZE] = {
710 (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
711 WhiteRook, WhiteQueen
719 DropMenuEnables dmEnables[] = {
737 { XtNborderWidth, 0 },
738 { XtNdefaultDistance, 0 },
742 { XtNborderWidth, 0 },
743 { XtNresizable, (XtArgVal) True },
747 { XtNborderWidth, 0 },
753 { XtNjustify, (XtArgVal) XtJustifyRight },
754 { XtNlabel, (XtArgVal) "..." },
755 { XtNresizable, (XtArgVal) True },
756 { XtNresize, (XtArgVal) False }
759 Arg messageArgs[] = {
760 { XtNjustify, (XtArgVal) XtJustifyLeft },
761 { XtNlabel, (XtArgVal) "..." },
762 { XtNresizable, (XtArgVal) True },
763 { XtNresize, (XtArgVal) False }
767 { XtNborderWidth, 0 },
768 { XtNjustify, (XtArgVal) XtJustifyLeft }
771 XtResource clientResources[] = {
772 { "whitePieceColor", "whitePieceColor", XtRString, sizeof(String),
773 XtOffset(AppDataPtr, whitePieceColor), XtRString,
775 { "blackPieceColor", "blackPieceColor", XtRString, sizeof(String),
776 XtOffset(AppDataPtr, blackPieceColor), XtRString,
778 { "lightSquareColor", "lightSquareColor", XtRString,
779 sizeof(String), XtOffset(AppDataPtr, lightSquareColor),
780 XtRString, LIGHT_SQUARE_COLOR },
781 { "darkSquareColor", "darkSquareColor", XtRString, sizeof(String),
782 XtOffset(AppDataPtr, darkSquareColor), XtRString,
784 { "highlightSquareColor", "highlightSquareColor", XtRString,
785 sizeof(String), XtOffset(AppDataPtr, highlightSquareColor),
786 XtRString, HIGHLIGHT_SQUARE_COLOR },
787 { "premoveHighlightColor", "premoveHighlightColor", XtRString,
788 sizeof(String), XtOffset(AppDataPtr, premoveHighlightColor),
789 XtRString, PREMOVE_HIGHLIGHT_COLOR },
790 { "movesPerSession", "movesPerSession", XtRInt, sizeof(int),
791 XtOffset(AppDataPtr, movesPerSession), XtRImmediate,
792 (XtPointer) MOVES_PER_SESSION },
793 { "timeIncrement", "timeIncrement", XtRInt, sizeof(int),
794 XtOffset(AppDataPtr, timeIncrement), XtRImmediate,
795 (XtPointer) TIME_INCREMENT },
796 { "initString", "initString", XtRString, sizeof(String),
797 XtOffset(AppDataPtr, initString), XtRString, INIT_STRING },
798 { "secondInitString", "secondInitString", XtRString, sizeof(String),
799 XtOffset(AppDataPtr, secondInitString), XtRString, INIT_STRING },
800 { "firstComputerString", "firstComputerString", XtRString,
801 sizeof(String), XtOffset(AppDataPtr, firstComputerString), XtRString,
803 { "secondComputerString", "secondComputerString", XtRString,
804 sizeof(String), XtOffset(AppDataPtr, secondComputerString), XtRString,
806 { "firstChessProgram", "firstChessProgram", XtRString,
807 sizeof(String), XtOffset(AppDataPtr, firstChessProgram),
808 XtRString, FIRST_CHESS_PROGRAM },
809 { "secondChessProgram", "secondChessProgram", XtRString,
810 sizeof(String), XtOffset(AppDataPtr, secondChessProgram),
811 XtRString, SECOND_CHESS_PROGRAM },
812 { "firstPlaysBlack", "firstPlaysBlack", XtRBoolean,
813 sizeof(Boolean), XtOffset(AppDataPtr, firstPlaysBlack),
814 XtRImmediate, (XtPointer) False },
815 { "noChessProgram", "noChessProgram", XtRBoolean,
816 sizeof(Boolean), XtOffset(AppDataPtr, noChessProgram),
817 XtRImmediate, (XtPointer) False },
818 { "firstHost", "firstHost", XtRString, sizeof(String),
819 XtOffset(AppDataPtr, firstHost), XtRString, FIRST_HOST },
820 { "secondHost", "secondHost", XtRString, sizeof(String),
821 XtOffset(AppDataPtr, secondHost), XtRString, SECOND_HOST },
822 { "firstDirectory", "firstDirectory", XtRString, sizeof(String),
823 XtOffset(AppDataPtr, firstDirectory), XtRString, "." },
824 { "secondDirectory", "secondDirectory", XtRString, sizeof(String),
825 XtOffset(AppDataPtr, secondDirectory), XtRString, "." },
826 { "bitmapDirectory", "bitmapDirectory", XtRString,
827 sizeof(String), XtOffset(AppDataPtr, bitmapDirectory),
829 { "remoteShell", "remoteShell", XtRString, sizeof(String),
830 XtOffset(AppDataPtr, remoteShell), XtRString, REMOTE_SHELL },
831 { "remoteUser", "remoteUser", XtRString, sizeof(String),
832 XtOffset(AppDataPtr, remoteUser), XtRString, "" },
833 { "timeDelay", "timeDelay", XtRFloat, sizeof(float),
834 XtOffset(AppDataPtr, timeDelay), XtRString,
835 (XtPointer) TIME_DELAY_QUOTE },
836 { "timeControl", "timeControl", XtRString, sizeof(String),
837 XtOffset(AppDataPtr, timeControl), XtRString,
838 (XtPointer) TIME_CONTROL },
839 { "internetChessServerMode", "internetChessServerMode",
840 XtRBoolean, sizeof(Boolean),
841 XtOffset(AppDataPtr, icsActive), XtRImmediate,
843 { "internetChessServerHost", "internetChessServerHost",
844 XtRString, sizeof(String),
845 XtOffset(AppDataPtr, icsHost),
846 XtRString, (XtPointer) ICS_HOST },
847 { "internetChessServerPort", "internetChessServerPort",
848 XtRString, sizeof(String),
849 XtOffset(AppDataPtr, icsPort), XtRString,
850 (XtPointer) ICS_PORT },
851 { "internetChessServerCommPort", "internetChessServerCommPort",
852 XtRString, sizeof(String),
853 XtOffset(AppDataPtr, icsCommPort), XtRString,
855 { "internetChessServerLogonScript", "internetChessServerLogonScript",
856 XtRString, sizeof(String),
857 XtOffset(AppDataPtr, icsLogon), XtRString,
859 { "internetChessServerHelper", "internetChessServerHelper",
860 XtRString, sizeof(String),
861 XtOffset(AppDataPtr, icsHelper), XtRString, "" },
862 { "internetChessServerInputBox", "internetChessServerInputBox",
863 XtRBoolean, sizeof(Boolean),
864 XtOffset(AppDataPtr, icsInputBox), XtRImmediate,
866 { "icsAlarm", "icsAlarm",
867 XtRBoolean, sizeof(Boolean),
868 XtOffset(AppDataPtr, icsAlarm), XtRImmediate,
870 { "icsAlarmTime", "icsAlarmTime",
872 XtOffset(AppDataPtr, icsAlarmTime), XtRImmediate,
874 { "useTelnet", "useTelnet", XtRBoolean, sizeof(Boolean),
875 XtOffset(AppDataPtr, useTelnet), XtRImmediate,
877 { "telnetProgram", "telnetProgram", XtRString, sizeof(String),
878 XtOffset(AppDataPtr, telnetProgram), XtRString, TELNET_PROGRAM },
879 { "gateway", "gateway", XtRString, sizeof(String),
880 XtOffset(AppDataPtr, gateway), XtRString, "" },
881 { "loadGameFile", "loadGameFile", XtRString, sizeof(String),
882 XtOffset(AppDataPtr, loadGameFile), XtRString, "" },
883 { "loadGameIndex", "loadGameIndex",
885 XtOffset(AppDataPtr, loadGameIndex), XtRImmediate,
887 { "saveGameFile", "saveGameFile", XtRString, sizeof(String),
888 XtOffset(AppDataPtr, saveGameFile), XtRString, "" },
889 { "autoRaiseBoard", "autoRaiseBoard", XtRBoolean,
890 sizeof(Boolean), XtOffset(AppDataPtr, autoRaiseBoard),
891 XtRImmediate, (XtPointer) True },
892 { "autoSaveGames", "autoSaveGames", XtRBoolean,
893 sizeof(Boolean), XtOffset(AppDataPtr, autoSaveGames),
894 XtRImmediate, (XtPointer) False },
895 { "blindfold", "blindfold", XtRBoolean,
896 sizeof(Boolean), XtOffset(AppDataPtr, blindfold),
897 XtRImmediate, (XtPointer) False },
898 { "loadPositionFile", "loadPositionFile", XtRString,
899 sizeof(String), XtOffset(AppDataPtr, loadPositionFile),
901 { "loadPositionIndex", "loadPositionIndex",
903 XtOffset(AppDataPtr, loadPositionIndex), XtRImmediate,
905 { "savePositionFile", "savePositionFile", XtRString,
906 sizeof(String), XtOffset(AppDataPtr, savePositionFile),
908 { "matchMode", "matchMode", XtRBoolean, sizeof(Boolean),
909 XtOffset(AppDataPtr, matchMode), XtRImmediate, (XtPointer) False },
910 { "matchGames", "matchGames", XtRInt, sizeof(int),
911 XtOffset(AppDataPtr, matchGames), XtRImmediate,
913 { "monoMode", "monoMode", XtRBoolean, sizeof(Boolean),
914 XtOffset(AppDataPtr, monoMode), XtRImmediate,
916 { "debugMode", "debugMode", XtRBoolean, sizeof(Boolean),
917 XtOffset(AppDataPtr, debugMode), XtRImmediate,
919 { "clockMode", "clockMode", XtRBoolean, sizeof(Boolean),
920 XtOffset(AppDataPtr, clockMode), XtRImmediate,
922 { "boardSize", "boardSize", XtRString, sizeof(String),
923 XtOffset(AppDataPtr, boardSize), XtRString, "" },
924 { "searchTime", "searchTime", XtRString, sizeof(String),
925 XtOffset(AppDataPtr, searchTime), XtRString,
927 { "searchDepth", "searchDepth", XtRInt, sizeof(int),
928 XtOffset(AppDataPtr, searchDepth), XtRImmediate,
930 { "showCoords", "showCoords", XtRBoolean, sizeof(Boolean),
931 XtOffset(AppDataPtr, showCoords), XtRImmediate,
933 { "showJail", "showJail", XtRInt, sizeof(int),
934 XtOffset(AppDataPtr, showJail), XtRImmediate,
936 { "showThinking", "showThinking", XtRBoolean, sizeof(Boolean),
937 XtOffset(AppDataPtr, showThinking), XtRImmediate,
939 { "ponderNextMove", "ponderNextMove", XtRBoolean, sizeof(Boolean),
940 XtOffset(AppDataPtr, ponderNextMove), XtRImmediate,
942 { "periodicUpdates", "periodicUpdates", XtRBoolean, sizeof(Boolean),
943 XtOffset(AppDataPtr, periodicUpdates), XtRImmediate,
945 { "clockFont", "clockFont", XtRString, sizeof(String),
946 XtOffset(AppDataPtr, clockFont), XtRString, CLOCK_FONT },
947 { "coordFont", "coordFont", XtRString, sizeof(String),
948 XtOffset(AppDataPtr, coordFont), XtRString, COORD_FONT },
949 { "font", "font", XtRString, sizeof(String),
950 XtOffset(AppDataPtr, font), XtRString, DEFAULT_FONT },
951 { "ringBellAfterMoves", "ringBellAfterMoves",
952 XtRBoolean, sizeof(Boolean),
953 XtOffset(AppDataPtr, ringBellAfterMoves),
954 XtRImmediate, (XtPointer) False },
955 { "autoCallFlag", "autoCallFlag", XtRBoolean,
956 sizeof(Boolean), XtOffset(AppDataPtr, autoCallFlag),
957 XtRImmediate, (XtPointer) False },
958 { "autoFlipView", "autoFlipView", XtRBoolean,
959 sizeof(Boolean), XtOffset(AppDataPtr, autoFlipView),
960 XtRImmediate, (XtPointer) True },
961 { "autoObserve", "autoObserve", XtRBoolean,
962 sizeof(Boolean), XtOffset(AppDataPtr, autoObserve),
963 XtRImmediate, (XtPointer) False },
964 { "autoComment", "autoComment", XtRBoolean,
965 sizeof(Boolean), XtOffset(AppDataPtr, autoComment),
966 XtRImmediate, (XtPointer) False },
967 { "getMoveList", "getMoveList", XtRBoolean,
968 sizeof(Boolean), XtOffset(AppDataPtr, getMoveList),
969 XtRImmediate, (XtPointer) True },
971 { "highlightDragging", "highlightDragging", XtRBoolean,
972 sizeof(Boolean), XtOffset(AppDataPtr, highlightDragging),
973 XtRImmediate, (XtPointer) False },
975 { "highlightLastMove", "highlightLastMove", XtRBoolean,
976 sizeof(Boolean), XtOffset(AppDataPtr, highlightLastMove),
977 XtRImmediate, (XtPointer) False },
978 { "premove", "premove", XtRBoolean,
979 sizeof(Boolean), XtOffset(AppDataPtr, premove),
980 XtRImmediate, (XtPointer) True },
981 { "testLegality", "testLegality", XtRBoolean,
982 sizeof(Boolean), XtOffset(AppDataPtr, testLegality),
983 XtRImmediate, (XtPointer) True },
984 { "flipView", "flipView", XtRBoolean,
985 sizeof(Boolean), XtOffset(AppDataPtr, flipView),
986 XtRImmediate, (XtPointer) False },
987 { "cmail", "cmailGameName", XtRString, sizeof(String),
988 XtOffset(AppDataPtr, cmailGameName), XtRString, "" },
989 { "alwaysPromoteToQueen", "alwaysPromoteToQueen", XtRBoolean,
990 sizeof(Boolean), XtOffset(AppDataPtr, alwaysPromoteToQueen),
991 XtRImmediate, (XtPointer) False },
992 { "oldSaveStyle", "oldSaveStyle", XtRBoolean,
993 sizeof(Boolean), XtOffset(AppDataPtr, oldSaveStyle),
994 XtRImmediate, (XtPointer) False },
995 { "quietPlay", "quietPlay", XtRBoolean,
996 sizeof(Boolean), XtOffset(AppDataPtr, quietPlay),
997 XtRImmediate, (XtPointer) False },
998 { "titleInWindow", "titleInWindow", XtRBoolean,
999 sizeof(Boolean), XtOffset(AppDataPtr, titleInWindow),
1000 XtRImmediate, (XtPointer) False },
1001 { "localLineEditing", "localLineEditing", XtRBoolean,
1002 sizeof(Boolean), XtOffset(AppDataPtr, localLineEditing),
1003 XtRImmediate, (XtPointer) True }, /* not implemented, must be True */
1005 { "zippyTalk", "zippyTalk", XtRBoolean,
1006 sizeof(Boolean), XtOffset(AppDataPtr, zippyTalk),
1007 XtRImmediate, (XtPointer) ZIPPY_TALK },
1008 { "zippyPlay", "zippyPlay", XtRBoolean,
1009 sizeof(Boolean), XtOffset(AppDataPtr, zippyPlay),
1010 XtRImmediate, (XtPointer) ZIPPY_PLAY },
1011 { "zippyLines", "zippyLines", XtRString, sizeof(String),
1012 XtOffset(AppDataPtr, zippyLines), XtRString, ZIPPY_LINES },
1013 { "zippyPinhead", "zippyPinhead", XtRString, sizeof(String),
1014 XtOffset(AppDataPtr, zippyPinhead), XtRString, ZIPPY_PINHEAD },
1015 { "zippyPassword", "zippyPassword", XtRString, sizeof(String),
1016 XtOffset(AppDataPtr, zippyPassword), XtRString, ZIPPY_PASSWORD },
1017 { "zippyPassword2", "zippyPassword2", XtRString, sizeof(String),
1018 XtOffset(AppDataPtr, zippyPassword2), XtRString, ZIPPY_PASSWORD2 },
1019 { "zippyWrongPassword", "zippyWrongPassword", XtRString, sizeof(String),
1020 XtOffset(AppDataPtr, zippyWrongPassword), XtRString,
1021 ZIPPY_WRONG_PASSWORD },
1022 { "zippyAcceptOnly", "zippyAcceptOnly", XtRString, sizeof(String),
1023 XtOffset(AppDataPtr, zippyAcceptOnly), XtRString, ZIPPY_ACCEPT_ONLY },
1024 { "zippyUseI", "zippyUseI", XtRBoolean,
1025 sizeof(Boolean), XtOffset(AppDataPtr, zippyUseI),
1026 XtRImmediate, (XtPointer) ZIPPY_USE_I },
1027 { "zippyBughouse", "zippyBughouse", XtRInt,
1028 sizeof(int), XtOffset(AppDataPtr, zippyBughouse),
1029 XtRImmediate, (XtPointer) ZIPPY_BUGHOUSE },
1030 { "zippyNoplayCrafty", "zippyNoplayCrafty", XtRBoolean,
1031 sizeof(Boolean), XtOffset(AppDataPtr, zippyNoplayCrafty),
1032 XtRImmediate, (XtPointer) ZIPPY_NOPLAY_CRAFTY },
1033 { "zippyGameEnd", "zippyGameEnd", XtRString, sizeof(String),
1034 XtOffset(AppDataPtr, zippyGameEnd), XtRString, ZIPPY_GAME_END },
1035 { "zippyGameStart", "zippyGameStart", XtRString, sizeof(String),
1036 XtOffset(AppDataPtr, zippyGameStart), XtRString, ZIPPY_GAME_START },
1037 { "zippyAdjourn", "zippyAdjourn", XtRBoolean,
1038 sizeof(Boolean), XtOffset(AppDataPtr, zippyAdjourn),
1039 XtRImmediate, (XtPointer) ZIPPY_ADJOURN },
1040 { "zippyAbort", "zippyAbort", XtRBoolean,
1041 sizeof(Boolean), XtOffset(AppDataPtr, zippyAbort),
1042 XtRImmediate, (XtPointer) ZIPPY_ABORT },
1043 { "zippyVariants", "zippyVariants", XtRString, sizeof(String),
1044 XtOffset(AppDataPtr, zippyVariants), XtRString, ZIPPY_VARIANTS },
1045 { "zippyMaxGames", "zippyMaxGames", XtRInt, sizeof(int),
1046 XtOffset(AppDataPtr, zippyMaxGames), XtRImmediate,
1047 (XtPointer) ZIPPY_MAX_GAMES },
1048 { "zippyReplayTimeout", "zippyReplayTimeout", XtRInt, sizeof(int),
1049 XtOffset(AppDataPtr, zippyReplayTimeout), XtRImmediate,
1050 (XtPointer) ZIPPY_REPLAY_TIMEOUT },
1051 { "zippyShortGame", "zippyShortGame", XtRInt, sizeof(int),
1052 XtOffset(AppDataPtr, zippyShortGame), XtRImmediate,
1055 { "flashCount", "flashCount", XtRInt, sizeof(int),
1056 XtOffset(AppDataPtr, flashCount), XtRImmediate,
1057 (XtPointer) FLASH_COUNT },
1058 { "flashRate", "flashRate", XtRInt, sizeof(int),
1059 XtOffset(AppDataPtr, flashRate), XtRImmediate,
1060 (XtPointer) FLASH_RATE },
1061 { "pixmapDirectory", "pixmapDirectory", XtRString,
1062 sizeof(String), XtOffset(AppDataPtr, pixmapDirectory),
1064 { "msLoginDelay", "msLoginDelay", XtRInt, sizeof(int),
1065 XtOffset(AppDataPtr, msLoginDelay), XtRImmediate,
1066 (XtPointer) MS_LOGIN_DELAY },
1067 { "colorizeMessages", "colorizeMessages", XtRBoolean,
1068 sizeof(Boolean), XtOffset(AppDataPtr, colorize),
1069 XtRImmediate, (XtPointer) False },
1070 { "colorShout", "colorShout", XtRString,
1071 sizeof(String), XtOffset(AppDataPtr, colorShout),
1072 XtRString, COLOR_SHOUT },
1073 { "colorSShout", "colorSShout", XtRString,
1074 sizeof(String), XtOffset(AppDataPtr, colorSShout),
1075 XtRString, COLOR_SSHOUT },
1076 { "colorChannel1", "colorChannel1", XtRString,
1077 sizeof(String), XtOffset(AppDataPtr, colorChannel1),
1078 XtRString, COLOR_CHANNEL1 },
1079 { "colorChannel", "colorChannel", XtRString,
1080 sizeof(String), XtOffset(AppDataPtr, colorChannel),
1081 XtRString, COLOR_CHANNEL },
1082 { "colorKibitz", "colorKibitz", XtRString,
1083 sizeof(String), XtOffset(AppDataPtr, colorKibitz),
1084 XtRString, COLOR_KIBITZ },
1085 { "colorTell", "colorTell", XtRString,
1086 sizeof(String), XtOffset(AppDataPtr, colorTell),
1087 XtRString, COLOR_TELL },
1088 { "colorChallenge", "colorChallenge", XtRString,
1089 sizeof(String), XtOffset(AppDataPtr, colorChallenge),
1090 XtRString, COLOR_CHALLENGE },
1091 { "colorRequest", "colorRequest", XtRString,
1092 sizeof(String), XtOffset(AppDataPtr, colorRequest),
1093 XtRString, COLOR_REQUEST },
1094 { "colorSeek", "colorSeek", XtRString,
1095 sizeof(String), XtOffset(AppDataPtr, colorSeek),
1096 XtRString, COLOR_SEEK },
1097 { "colorNormal", "colorNormal", XtRString,
1098 sizeof(String), XtOffset(AppDataPtr, colorNormal),
1099 XtRString, COLOR_NORMAL },
1100 { "soundProgram", "soundProgram", XtRString,
1101 sizeof(String), XtOffset(AppDataPtr, soundProgram),
1102 XtRString, "play" },
1103 { "soundShout", "soundShout", XtRString,
1104 sizeof(String), XtOffset(AppDataPtr, soundShout),
1106 { "soundSShout", "soundSShout", XtRString,
1107 sizeof(String), XtOffset(AppDataPtr, soundSShout),
1109 { "soundChannel1", "soundChannel1", XtRString,
1110 sizeof(String), XtOffset(AppDataPtr, soundChannel1),
1112 { "soundChannel", "soundChannel", XtRString,
1113 sizeof(String), XtOffset(AppDataPtr, soundChannel),
1115 { "soundKibitz", "soundKibitz", XtRString,
1116 sizeof(String), XtOffset(AppDataPtr, soundKibitz),
1118 { "soundTell", "soundTell", XtRString,
1119 sizeof(String), XtOffset(AppDataPtr, soundTell),
1121 { "soundChallenge", "soundChallenge", XtRString,
1122 sizeof(String), XtOffset(AppDataPtr, soundChallenge),
1124 { "soundRequest", "soundRequest", XtRString,
1125 sizeof(String), XtOffset(AppDataPtr, soundRequest),
1127 { "soundSeek", "soundSeek", XtRString,
1128 sizeof(String), XtOffset(AppDataPtr, soundSeek),
1130 { "soundMove", "soundMove", XtRString,
1131 sizeof(String), XtOffset(AppDataPtr, soundMove),
1133 { "soundIcsWin", "soundIcsWin", XtRString,
1134 sizeof(String), XtOffset(AppDataPtr, soundIcsWin),
1136 { "soundIcsLoss", "soundIcsLoss", XtRString,
1137 sizeof(String), XtOffset(AppDataPtr, soundIcsLoss),
1139 { "soundIcsDraw", "soundIcsDraw", XtRString,
1140 sizeof(String), XtOffset(AppDataPtr, soundIcsDraw),
1142 { "soundIcsUnfinished", "soundIcsUnfinished", XtRString,
1143 sizeof(String), XtOffset(AppDataPtr, soundIcsUnfinished),
1145 { "soundIcsAlarm", "soundIcsAlarm", XtRString,
1146 sizeof(String), XtOffset(AppDataPtr, soundIcsAlarm),
1148 { "reuseFirst", "reuseFirst", XtRBoolean,
1149 sizeof(Boolean), XtOffset(AppDataPtr, reuseFirst),
1150 XtRImmediate, (XtPointer) True },
1151 { "reuseSecond", "reuseSecond", XtRBoolean,
1152 sizeof(Boolean), XtOffset(AppDataPtr, reuseSecond),
1153 XtRImmediate, (XtPointer) True },
1154 { "animateDragging", "animateDragging", XtRBoolean,
1155 sizeof(Boolean), XtOffset(AppDataPtr, animateDragging),
1156 XtRImmediate, (XtPointer) True },
1157 { "animateMoving", "animateMoving", XtRBoolean,
1158 sizeof(Boolean), XtOffset(AppDataPtr, animate),
1159 XtRImmediate, (XtPointer) True },
1160 { "animateSpeed", "animateSpeed", XtRInt,
1161 sizeof(int), XtOffset(AppDataPtr, animSpeed),
1162 XtRImmediate, (XtPointer)10 },
1163 { "popupExitMessage", "popupExitMessage", XtRBoolean,
1164 sizeof(Boolean), XtOffset(AppDataPtr, popupExitMessage),
1165 XtRImmediate, (XtPointer) True },
1166 { "popupMoveErrors", "popupMoveErrors", XtRBoolean,
1167 sizeof(Boolean), XtOffset(AppDataPtr, popupMoveErrors),
1168 XtRImmediate, (XtPointer) False },
1169 { "fontSizeTolerance", "fontSizeTolerance", XtRInt,
1170 sizeof(int), XtOffset(AppDataPtr, fontSizeTolerance),
1171 XtRImmediate, (XtPointer)4 },
1172 { "initialMode", "initialMode", XtRString,
1173 sizeof(String), XtOffset(AppDataPtr, initialMode),
1174 XtRImmediate, (XtPointer) "" },
1175 { "variant", "variant", XtRString,
1176 sizeof(String), XtOffset(AppDataPtr, variant),
1177 XtRImmediate, (XtPointer) "normal" },
1178 { "firstProtocolVersion", "firstProtocolVersion", XtRInt,
1179 sizeof(int), XtOffset(AppDataPtr, firstProtocolVersion),
1180 XtRImmediate, (XtPointer)PROTOVER },
1181 { "secondProtocolVersion", "secondProtocolVersion", XtRInt,
1182 sizeof(int), XtOffset(AppDataPtr, secondProtocolVersion),
1183 XtRImmediate, (XtPointer)PROTOVER },
1184 { "showButtonBar", "showButtonBar", XtRBoolean,
1185 sizeof(Boolean), XtOffset(AppDataPtr, showButtonBar),
1186 XtRImmediate, (XtPointer) True },
1187 { "lowTimeWarningColor", "lowTimeWarningColor", XtRString,
1188 sizeof(String), XtOffset(AppDataPtr, lowTimeWarningColor),
1189 XtRString, COLOR_LOWTIMEWARNING },
1190 { "lowTimeWarning", "lowTimeWarning", XtRBoolean,
1191 sizeof(Boolean), XtOffset(AppDataPtr, lowTimeWarning),
1192 XtRImmediate, (XtPointer) False },
1193 {"icsEngineAnalyze", "icsEngineAnalyze", XtRBoolean, /* [DM] icsEngineAnalyze */
1194 sizeof(Boolean), XtOffset(AppDataPtr, icsEngineAnalyze),
1195 XtRImmediate, (XtPointer) False },
1196 { "firstScoreAbs", "firstScoreAbs", XtRBoolean,
1197 sizeof(Boolean), XtOffset(AppDataPtr, firstScoreIsAbsolute),
1198 XtRImmediate, (XtPointer) False },
1199 { "secondScoreAbs", "secondScoreAbs", XtRBoolean,
1200 sizeof(Boolean), XtOffset(AppDataPtr, secondScoreIsAbsolute),
1201 XtRImmediate, (XtPointer) False },
1202 { "pgnExtendedInfo", "pgnExtendedInfo", XtRBoolean,
1203 sizeof(Boolean), XtOffset(AppDataPtr, saveExtendedInfoInPGN),
1204 XtRImmediate, (XtPointer) False },
1205 { "hideThinkingFromHuman", "hideThinkingFromHuman", XtRBoolean,
1206 sizeof(Boolean), XtOffset(AppDataPtr, hideThinkingFromHuman),
1207 XtRImmediate, (XtPointer) True },
1208 { "adjudicateLossThreshold", "adjudicateLossThreshold", XtRInt,
1209 sizeof(int), XtOffset(AppDataPtr, adjudicateLossThreshold),
1210 XtRImmediate, (XtPointer) 0},
1211 { "pgnEventHeader", "pgnEventHeader", XtRString,
1212 sizeof(String), XtOffset(AppDataPtr, pgnEventHeader),
1213 XtRImmediate, (XtPointer) "Computer Chess Game" },
1214 { "defaultFrcPosition", "defaultFrcPositon", XtRInt,
1215 sizeof(int), XtOffset(AppDataPtr, defaultFrcPosition),
1216 XtRImmediate, (XtPointer) -1},
1217 { "gameListTags", "gameListTags", XtRString,
1218 sizeof(String), XtOffset(AppDataPtr, gameListTags),
1219 XtRImmediate, (XtPointer) GLT_DEFAULT_TAGS },
1221 // [HGM] 4.3.xx options
1222 { "boardWidth", "boardWidth", XtRInt,
1223 sizeof(int), XtOffset(AppDataPtr, NrFiles),
1224 XtRImmediate, (XtPointer) -1},
1225 { "boardHeight", "boardHeight", XtRInt,
1226 sizeof(int), XtOffset(AppDataPtr, NrRanks),
1227 XtRImmediate, (XtPointer) -1},
1228 { "matchPause", "matchPause", XtRInt,
1229 sizeof(int), XtOffset(AppDataPtr, matchPause),
1230 XtRImmediate, (XtPointer) 10000},
1231 { "holdingsSize", "holdingsSize", XtRInt,
1232 sizeof(int), XtOffset(AppDataPtr, holdingsSize),
1233 XtRImmediate, (XtPointer) -1},
1234 { "flipBlack", "flipBlack", XtRBoolean,
1235 sizeof(Boolean), XtOffset(AppDataPtr, upsideDown),
1236 XtRImmediate, (XtPointer) False},
1237 { "allWhite", "allWhite", XtRBoolean,
1238 sizeof(Boolean), XtOffset(AppDataPtr, allWhite),
1239 XtRImmediate, (XtPointer) False},
1240 { "pieceToCharTable", "pieceToCharTable", XtRString,
1241 sizeof(String), XtOffset(AppDataPtr, pieceToCharTable),
1242 XtRImmediate, (XtPointer) 0},
1243 { "alphaRank", "alphaRank", XtRBoolean,
1244 sizeof(Boolean), XtOffset(AppDataPtr, alphaRank),
1245 XtRImmediate, (XtPointer) False},
1246 { "testClaims", "testClaims", XtRBoolean,
1247 sizeof(Boolean), XtOffset(AppDataPtr, testClaims),
1248 XtRImmediate, (XtPointer) True},
1249 { "checkMates", "checkMates", XtRBoolean,
1250 sizeof(Boolean), XtOffset(AppDataPtr, checkMates),
1251 XtRImmediate, (XtPointer) True},
1252 { "materialDraws", "materialDraws", XtRBoolean,
1253 sizeof(Boolean), XtOffset(AppDataPtr, materialDraws),
1254 XtRImmediate, (XtPointer) True},
1255 { "trivialDraws", "trivialDraws", XtRBoolean,
1256 sizeof(Boolean), XtOffset(AppDataPtr, trivialDraws),
1257 XtRImmediate, (XtPointer) False},
1258 { "ruleMoves", "ruleMoves", XtRInt,
1259 sizeof(int), XtOffset(AppDataPtr, ruleMoves),
1260 XtRImmediate, (XtPointer) 51},
1261 { "repeatsToDraw", "repeatsToDraw", XtRInt,
1262 sizeof(int), XtOffset(AppDataPtr, drawRepeats),
1263 XtRImmediate, (XtPointer) 6},
1264 { "engineDebugOutput", "engineDebugOutput", XtRInt,
1265 sizeof(int), XtOffset(AppDataPtr, engineComments),
1266 XtRImmediate, (XtPointer) 1},
1267 { "userName", "userName", XtRString,
1268 sizeof(int), XtOffset(AppDataPtr, userName),
1269 XtRImmediate, (XtPointer) 0},
1270 { "autoKibitz", "autoKibitz", XtRBoolean,
1271 sizeof(Boolean), XtOffset(AppDataPtr, autoKibitz),
1272 XtRImmediate, (XtPointer) False},
1273 { "firstTimeOdds", "firstTimeOdds", XtRInt,
1274 sizeof(int), XtOffset(AppDataPtr, firstTimeOdds),
1275 XtRImmediate, (XtPointer) 1},
1276 { "secondTimeOdds", "secondTimeOdds", XtRInt,
1277 sizeof(int), XtOffset(AppDataPtr, secondTimeOdds),
1278 XtRImmediate, (XtPointer) 1},
1279 { "timeOddsMode", "timeOddsMode", XtRInt,
1280 sizeof(int), XtOffset(AppDataPtr, timeOddsMode),
1281 XtRImmediate, (XtPointer) 0},
1282 { "firstAccumulateTC", "firstAccumulateTC", XtRInt,
1283 sizeof(int), XtOffset(AppDataPtr, firstAccumulateTC),
1284 XtRImmediate, (XtPointer) 1},
1285 { "secondAccumulateTC", "secondAccumulateTC", XtRInt,
1286 sizeof(int), XtOffset(AppDataPtr, secondAccumulateTC),
1287 XtRImmediate, (XtPointer) 1},
1288 { "firstNPS", "firstNPS", XtRInt,
1289 sizeof(int), XtOffset(AppDataPtr, firstNPS),
1290 XtRImmediate, (XtPointer) -1},
1291 { "secondNPS", "secondNPS", XtRInt,
1292 sizeof(int), XtOffset(AppDataPtr, secondNPS),
1293 XtRImmediate, (XtPointer) -1},
1294 { "serverMoves", "serverMoves", XtRString,
1295 sizeof(String), XtOffset(AppDataPtr, serverMovesName),
1296 XtRImmediate, (XtPointer) 0},
1297 { "serverPause", "serverPause", XtRInt,
1298 sizeof(int), XtOffset(AppDataPtr, serverPause),
1299 XtRImmediate, (XtPointer) 0},
1300 { "suppressLoadMoves", "suppressLoadMoves", XtRBoolean,
1301 sizeof(Boolean), XtOffset(AppDataPtr, suppressLoadMoves),
1302 XtRImmediate, (XtPointer) False},
1303 { "userName", "userName", XtRString,
1304 sizeof(String), XtOffset(AppDataPtr, userName),
1305 XtRImmediate, (XtPointer) 0},
1306 { "egtFormats", "egtFormats", XtRString,
1307 sizeof(String), XtOffset(AppDataPtr, egtFormats),
1308 XtRImmediate, (XtPointer) 0},
1309 { "rewindIndex", "rewindIndex", XtRInt,
1310 sizeof(int), XtOffset(AppDataPtr, rewindIndex),
1311 XtRImmediate, (XtPointer) 0},
1312 { "sameColorGames", "sameColorGames", XtRInt,
1313 sizeof(int), XtOffset(AppDataPtr, sameColorGames),
1314 XtRImmediate, (XtPointer) 0},
1315 { "smpCores", "smpCores", XtRInt,
1316 sizeof(int), XtOffset(AppDataPtr, smpCores),
1317 XtRImmediate, (XtPointer) 1},
1318 { "niceEngines", "niceEngines", XtRInt,
1319 sizeof(int), XtOffset(AppDataPtr, niceEngines),
1320 XtRImmediate, (XtPointer) 0},
1321 { "nameOfDebugFile", "nameOfDebugFile", XtRString,
1322 sizeof(String), XtOffset(AppDataPtr, nameOfDebugFile),
1323 XtRImmediate, (XtPointer) "xboard.debug"},
1324 { "engineDebugOutput", "engineDebugOutput", XtRInt,
1325 sizeof(int), XtOffset(AppDataPtr, engineComments),
1326 XtRImmediate, (XtPointer) 0},
1327 { "noGUI", "noGUI", XtRBoolean,
1328 sizeof(Boolean), XtOffset(AppDataPtr, noGUI),
1329 XtRImmediate, (XtPointer) 0},
1330 { "firstOptions", "firstOptions", XtRString,
1331 sizeof(String), XtOffset(AppDataPtr, firstOptions),
1332 XtRImmediate, (XtPointer) "" },
1333 { "secondOptions", "secondOptions", XtRString,
1334 sizeof(String), XtOffset(AppDataPtr, secondOptions),
1335 XtRImmediate, (XtPointer) "" },
1336 { "firstNeedsNoncompliantFEN", "firstNeedsNoncompliantFEN", XtRString,
1337 sizeof(String), XtOffset(AppDataPtr, fenOverride1),
1338 XtRImmediate, (XtPointer) 0 },
1339 { "secondNeedsNoncompliantFEN", "secondNeedsNoncompliantFEN", XtRString,
1340 sizeof(String), XtOffset(AppDataPtr, fenOverride2),
1341 XtRImmediate, (XtPointer) 0 },
1343 // [HGM] Winboard_x UCI options
1344 { "firstIsUCI", "firstIsUCI", XtRBoolean,
1345 sizeof(Boolean), XtOffset(AppDataPtr, firstIsUCI),
1346 XtRImmediate, (XtPointer) False},
1347 { "secondIsUCI", "secondIsUCI", XtRBoolean,
1348 sizeof(Boolean), XtOffset(AppDataPtr, secondIsUCI),
1349 XtRImmediate, (XtPointer) False},
1350 { "firstHasOwnBookUCI", "firstHasOwnBookUCI", XtRBoolean,
1351 sizeof(Boolean), XtOffset(AppDataPtr, firstHasOwnBookUCI),
1352 XtRImmediate, (XtPointer) True},
1353 { "secondHasOwnBookUCI", "secondHasOwnBookUCI", XtRBoolean,
1354 sizeof(Boolean), XtOffset(AppDataPtr, secondHasOwnBookUCI),
1355 XtRImmediate, (XtPointer) True},
1356 { "usePolyglotBook", "usePolyglotBook", XtRBoolean,
1357 sizeof(Boolean), XtOffset(AppDataPtr, usePolyglotBook),
1358 XtRImmediate, (XtPointer) False},
1359 { "defaultHashSize", "defaultHashSize", XtRInt,
1360 sizeof(int), XtOffset(AppDataPtr, defaultHashSize),
1361 XtRImmediate, (XtPointer) 64},
1362 { "defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XtRInt,
1363 sizeof(int), XtOffset(AppDataPtr, defaultCacheSizeEGTB),
1364 XtRImmediate, (XtPointer) 4},
1365 { "polyglotDir", "polyglotDir", XtRString,
1366 sizeof(String), XtOffset(AppDataPtr, polyglotDir),
1367 XtRImmediate, (XtPointer) "." },
1368 { "polyglotBook", "polyglotBook", XtRString,
1369 sizeof(String), XtOffset(AppDataPtr, polyglotBook),
1370 XtRImmediate, (XtPointer) "" },
1371 { "defaultPathEGTB", "defaultPathEGTB", XtRString,
1372 sizeof(String), XtOffset(AppDataPtr, defaultPathEGTB),
1373 XtRImmediate, (XtPointer) "/usr/local/share/egtb"},
1374 { "delayBeforeQuit", "delayBeforeQuit", XtRInt,
1375 sizeof(int), XtOffset(AppDataPtr, delayBeforeQuit),
1376 XtRImmediate, (XtPointer) 0},
1377 { "delayAfterQuit", "delayAfterQuit", XtRInt,
1378 sizeof(int), XtOffset(AppDataPtr, delayAfterQuit),
1379 XtRImmediate, (XtPointer) 0},
1382 XrmOptionDescRec shellOptions[] = {
1383 { "-whitePieceColor", "whitePieceColor", XrmoptionSepArg, NULL },
1384 { "-blackPieceColor", "blackPieceColor", XrmoptionSepArg, NULL },
1385 { "-lightSquareColor", "lightSquareColor", XrmoptionSepArg, NULL },
1386 { "-darkSquareColor", "darkSquareColor", XrmoptionSepArg, NULL },
1387 { "-highlightSquareColor", "highlightSquareColor", XrmoptionSepArg, NULL },
1388 { "-premoveHighlightColor", "premoveHighlightColor", XrmoptionSepArg,NULL},
1389 { "-movesPerSession", "movesPerSession", XrmoptionSepArg, NULL },
1390 { "-mps", "movesPerSession", XrmoptionSepArg, NULL },
1391 { "-timeIncrement", "timeIncrement", XrmoptionSepArg, NULL },
1392 { "-inc", "timeIncrement", XrmoptionSepArg, NULL },
1393 { "-initString", "initString", XrmoptionSepArg, NULL },
1394 { "-firstInitString", "initString", XrmoptionSepArg, NULL },
1395 { "-secondInitString", "secondInitString", XrmoptionSepArg, NULL },
1396 { "-firstComputerString", "firstComputerString", XrmoptionSepArg, NULL },
1397 { "-secondComputerString", "secondComputerString", XrmoptionSepArg, NULL },
1398 { "-firstChessProgram", "firstChessProgram", XrmoptionSepArg, NULL },
1399 { "-fcp", "firstChessProgram", XrmoptionSepArg, NULL },
1400 { "-secondChessProgram", "secondChessProgram", XrmoptionSepArg, NULL },
1401 { "-scp", "secondChessProgram", XrmoptionSepArg, NULL },
1402 { "-firstPlaysBlack", "firstPlaysBlack", XrmoptionSepArg, NULL },
1403 { "-fb", "firstPlaysBlack", XrmoptionNoArg, "True" },
1404 { "-xfb", "firstPlaysBlack", XrmoptionNoArg, "False" },
1405 { "-noChessProgram", "noChessProgram", XrmoptionSepArg, NULL },
1406 { "-ncp", "noChessProgram", XrmoptionNoArg, "True" },
1407 { "-xncp", "noChessProgram", XrmoptionNoArg, "False" },
1408 { "-firstHost", "firstHost", XrmoptionSepArg, NULL },
1409 { "-fh", "firstHost", XrmoptionSepArg, NULL },
1410 { "-secondHost", "secondHost", XrmoptionSepArg, NULL },
1411 { "-sh", "secondHost", XrmoptionSepArg, NULL },
1412 { "-firstDirectory", "firstDirectory", XrmoptionSepArg, NULL },
1413 { "-fd", "firstDirectory", XrmoptionSepArg, NULL },
1414 { "-secondDirectory", "secondDirectory", XrmoptionSepArg, NULL },
1415 { "-sd", "secondDirectory", XrmoptionSepArg, NULL },
1416 { "-bitmapDirectory", "bitmapDirectory", XrmoptionSepArg, NULL },
1417 { "-bm", "bitmapDirectory", XrmoptionSepArg, NULL },
1418 { "-remoteShell", "remoteShell", XrmoptionSepArg, NULL },
1419 { "-rsh", "remoteShell", XrmoptionSepArg, NULL },
1420 { "-remoteUser", "remoteUser", XrmoptionSepArg, NULL },
1421 { "-ruser", "remoteUser", XrmoptionSepArg, NULL },
1422 { "-timeDelay", "timeDelay", XrmoptionSepArg, NULL },
1423 { "-td", "timeDelay", XrmoptionSepArg, NULL },
1424 { "-timeControl", "timeControl", XrmoptionSepArg, NULL },
1425 { "-tc", "timeControl", XrmoptionSepArg, NULL },
1426 { "-internetChessServerMode", "internetChessServerMode",
1427 XrmoptionSepArg, NULL },
1428 { "-ics", "internetChessServerMode", XrmoptionNoArg, "True" },
1429 { "-xics", "internetChessServerMode", XrmoptionNoArg, "False" },
1430 { "-internetChessServerHost", "internetChessServerHost",
1431 XrmoptionSepArg, NULL },
1432 { "-icshost", "internetChessServerHost", XrmoptionSepArg, NULL },
1433 { "-internetChessServerPort", "internetChessServerPort",
1434 XrmoptionSepArg, NULL },
1435 { "-icsport", "internetChessServerPort", XrmoptionSepArg, NULL },
1436 { "-internetChessServerCommPort", "internetChessServerCommPort",
1437 XrmoptionSepArg, NULL },
1438 { "-icscomm", "internetChessServerCommPort", XrmoptionSepArg, NULL },
1439 { "-internetChessServerLogonScript", "internetChessServerLogonScript",
1440 XrmoptionSepArg, NULL },
1441 { "-icslogon", "internetChessServerLogonScript", XrmoptionSepArg, NULL },
1442 { "-internetChessServerHelper", "internetChessServerHelper",
1443 XrmoptionSepArg, NULL },
1444 { "-icshelper", "internetChessServerHelper", XrmoptionSepArg, NULL },
1445 { "-internetChessServerInputBox", "internetChessServerInputBox",
1446 XrmoptionSepArg, NULL },
1447 { "-icsinput", "internetChessServerInputBox", XrmoptionNoArg, "True" },
1448 { "-xicsinput", "internetChessServerInputBox", XrmoptionNoArg, "False" },
1449 { "-icsAlarm", "icsAlarm", XrmoptionSepArg, NULL },
1450 { "-alarm", "icsAlarm", XrmoptionNoArg, "True" },
1451 { "-xalarm", "icsAlarm", XrmoptionNoArg, "False" },
1452 { "-icsAlarmTime", "icsAlarmTime", XrmoptionSepArg, NULL },
1453 { "-useTelnet", "useTelnet", XrmoptionSepArg, NULL },
1454 { "-telnet", "useTelnet", XrmoptionNoArg, "True" },
1455 { "-xtelnet", "useTelnet", XrmoptionNoArg, "False" },
1456 { "-telnetProgram", "telnetProgram", XrmoptionSepArg, NULL },
1457 { "-gateway", "gateway", XrmoptionSepArg, NULL },
1458 { "-loadGameFile", "loadGameFile", XrmoptionSepArg, NULL },
1459 { "-lgf", "loadGameFile", XrmoptionSepArg, NULL },
1460 { "-loadGameIndex", "loadGameIndex", XrmoptionSepArg, NULL },
1461 { "-lgi", "loadGameIndex", XrmoptionSepArg, NULL },
1462 { "-saveGameFile", "saveGameFile", XrmoptionSepArg, NULL },
1463 { "-sgf", "saveGameFile", XrmoptionSepArg, NULL },
1464 { "-autoSaveGames", "autoSaveGames", XrmoptionSepArg, NULL },
1465 { "-autosave", "autoSaveGames", XrmoptionNoArg, "True" },
1466 { "-xautosave", "autoSaveGames", XrmoptionNoArg, "False" },
1467 { "-autoRaiseBoard", "autoRaiseBoard", XrmoptionSepArg, NULL },
1468 { "-autoraise", "autoRaiseBoard", XrmoptionNoArg, "True" },
1469 { "-xautoraise", "autoRaiseBoard", XrmoptionNoArg, "False" },
1470 { "-blindfold", "blindfold", XrmoptionSepArg, NULL },
1471 { "-blind", "blindfold", XrmoptionNoArg, "True" },
1472 { "-xblind", "blindfold", XrmoptionNoArg, "False" },
1473 { "-loadPositionFile", "loadPositionFile", XrmoptionSepArg, NULL },
1474 { "-lpf", "loadPositionFile", XrmoptionSepArg, NULL },
1475 { "-loadPositionIndex", "loadPositionIndex", XrmoptionSepArg, NULL },
1476 { "-lpi", "loadPositionIndex", XrmoptionSepArg, NULL },
1477 { "-savePositionFile", "savePositionFile", XrmoptionSepArg, NULL },
1478 { "-spf", "savePositionFile", XrmoptionSepArg, NULL },
1479 { "-matchMode", "matchMode", XrmoptionSepArg, NULL },
1480 { "-mm", "matchMode", XrmoptionNoArg, "True" },
1481 { "-xmm", "matchMode", XrmoptionNoArg, "False" },
1482 { "-matchGames", "matchGames", XrmoptionSepArg, NULL },
1483 { "-mg", "matchGames", XrmoptionSepArg, NULL },
1484 { "-monoMode", "monoMode", XrmoptionSepArg, NULL },
1485 { "-mono", "monoMode", XrmoptionNoArg, "True" },
1486 { "-xmono", "monoMode", XrmoptionNoArg, "False" },
1487 { "-debugMode", "debugMode", XrmoptionSepArg, NULL },
1488 { "-debug", "debugMode", XrmoptionNoArg, "True" },
1489 { "-xdebug", "debugMode", XrmoptionNoArg, "False" },
1490 { "-clockMode", "clockMode", XrmoptionSepArg, NULL },
1491 { "-clock", "clockMode", XrmoptionNoArg, "True" },
1492 { "-xclock", "clockMode", XrmoptionNoArg, "False" },
1493 { "-boardSize", "boardSize", XrmoptionSepArg, NULL },
1494 { "-size", "boardSize", XrmoptionSepArg, NULL },
1495 { "-searchTime", "searchTime", XrmoptionSepArg, NULL },
1496 { "-st", "searchTime", XrmoptionSepArg, NULL },
1497 { "-searchDepth", "searchDepth", XrmoptionSepArg, NULL },
1498 { "-depth", "searchDepth", XrmoptionSepArg, NULL },
1499 { "-showCoords", "showCoords", XrmoptionSepArg, NULL },
1500 { "-coords", "showCoords", XrmoptionNoArg, "True" },
1501 { "-xcoords", "showCoords", XrmoptionNoArg, "False" },
1503 { "-showJail", "showJail", XrmoptionSepArg, NULL },
1504 { "-jail", "showJail", XrmoptionNoArg, "1" },
1505 { "-sidejail", "showJail", XrmoptionNoArg, "2" },
1506 { "-xjail", "showJail", XrmoptionNoArg, "0" },
1508 { "-showThinking", "showThinking", XrmoptionSepArg, NULL },
1509 { "-thinking", "showThinking", XrmoptionNoArg, "True" },
1510 { "-xthinking", "showThinking", XrmoptionNoArg, "False" },
1511 { "-ponderNextMove", "ponderNextMove", XrmoptionSepArg, NULL },
1512 { "-ponder", "ponderNextMove", XrmoptionNoArg, "True" },
1513 { "-xponder", "ponderNextMove", XrmoptionNoArg, "False" },
1514 { "-periodicUpdates", "periodicUpdates", XrmoptionSepArg, NULL },
1515 { "-periodic", "periodicUpdates", XrmoptionNoArg, "True" },
1516 { "-xperiodic", "periodicUpdates", XrmoptionNoArg, "False" },
1517 { "-clockFont", "clockFont", XrmoptionSepArg, NULL },
1518 { "-coordFont", "coordFont", XrmoptionSepArg, NULL },
1519 { "-font", "font", XrmoptionSepArg, NULL },
1520 { "-ringBellAfterMoves", "ringBellAfterMoves", XrmoptionSepArg, NULL },
1521 { "-bell", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1522 { "-xbell", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1523 { "-movesound", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1524 { "-xmovesound", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1525 { "-autoCallFlag", "autoCallFlag", XrmoptionSepArg, NULL },
1526 { "-autoflag", "autoCallFlag", XrmoptionNoArg, "True" },
1527 { "-xautoflag", "autoCallFlag", XrmoptionNoArg, "False" },
1528 { "-autoFlipView", "autoFlipView", XrmoptionSepArg, NULL },
1529 { "-autoflip", "autoFlipView", XrmoptionNoArg, "True" },
1530 { "-xautoflip", "autoFlipView", XrmoptionNoArg, "False" },
1531 { "-autoObserve", "autoObserve", XrmoptionSepArg, NULL },
1532 { "-autobs", "autoObserve", XrmoptionNoArg, "True" },
1533 { "-xautobs", "autoObserve", XrmoptionNoArg, "False" },
1534 { "-autoComment", "autoComment", XrmoptionSepArg, NULL },
1535 { "-autocomm", "autoComment", XrmoptionNoArg, "True" },
1536 { "-xautocomm", "autoComment", XrmoptionNoArg, "False" },
1537 { "-getMoveList", "getMoveList", XrmoptionSepArg, NULL },
1538 { "-moves", "getMoveList", XrmoptionNoArg, "True" },
1539 { "-xmoves", "getMoveList", XrmoptionNoArg, "False" },
1541 { "-highlightDragging", "highlightDragging", XrmoptionSepArg, NULL },
1542 { "-highdrag", "highlightDragging", XrmoptionNoArg, "True" },
1543 { "-xhighdrag", "highlightDragging", XrmoptionNoArg, "False" },
1545 { "-highlightLastMove", "highlightLastMove", XrmoptionSepArg, NULL },
1546 { "-highlight", "highlightLastMove", XrmoptionNoArg, "True" },
1547 { "-xhighlight", "highlightLastMove", XrmoptionNoArg, "False" },
1548 { "-premove", "premove", XrmoptionSepArg, NULL },
1549 { "-pre", "premove", XrmoptionNoArg, "True" },
1550 { "-xpre", "premove", XrmoptionNoArg, "False" },
1551 { "-testLegality", "testLegality", XrmoptionSepArg, NULL },
1552 { "-legal", "testLegality", XrmoptionNoArg, "True" },
1553 { "-xlegal", "testLegality", XrmoptionNoArg, "False" },
1554 { "-flipView", "flipView", XrmoptionSepArg, NULL },
1555 { "-flip", "flipView", XrmoptionNoArg, "True" },
1556 { "-xflip", "flipView", XrmoptionNoArg, "False" },
1557 { "-cmail", "cmailGameName", XrmoptionSepArg, NULL },
1558 { "-alwaysPromoteToQueen", "alwaysPromoteToQueen",
1559 XrmoptionSepArg, NULL },
1560 { "-queen", "alwaysPromoteToQueen", XrmoptionNoArg, "True" },
1561 { "-xqueen", "alwaysPromoteToQueen", XrmoptionNoArg, "False" },
1562 { "-oldSaveStyle", "oldSaveStyle", XrmoptionSepArg, NULL },
1563 { "-oldsave", "oldSaveStyle", XrmoptionNoArg, "True" },
1564 { "-xoldsave", "oldSaveStyle", XrmoptionNoArg, "False" },
1565 { "-quietPlay", "quietPlay", XrmoptionSepArg, NULL },
1566 { "-quiet", "quietPlay", XrmoptionNoArg, "True" },
1567 { "-xquiet", "quietPlay", XrmoptionNoArg, "False" },
1568 { "-titleInWindow", "titleInWindow", XrmoptionSepArg, NULL },
1569 { "-title", "titleInWindow", XrmoptionNoArg, "True" },
1570 { "-xtitle", "titleInWindow", XrmoptionNoArg, "False" },
1572 { "-zippyTalk", "zippyTalk", XrmoptionSepArg, NULL },
1573 { "-zt", "zippyTalk", XrmoptionNoArg, "True" },
1574 { "-xzt", "zippyTalk", XrmoptionNoArg, "False" },
1575 { "-zippyPlay", "zippyPlay", XrmoptionSepArg, NULL },
1576 { "-zp", "zippyPlay", XrmoptionNoArg, "True" },
1577 { "-xzp", "zippyPlay", XrmoptionNoArg, "False" },
1578 { "-zippyLines", "zippyLines", XrmoptionSepArg, NULL },
1579 { "-zippyPinhead", "zippyPinhead", XrmoptionSepArg, NULL },
1580 { "-zippyPassword", "zippyPassword", XrmoptionSepArg, NULL },
1581 { "-zippyPassword2", "zippyPassword2", XrmoptionSepArg, NULL },
1582 { "-zippyWrongPassword", "zippyWrongPassword", XrmoptionSepArg, NULL },
1583 { "-zippyAcceptOnly", "zippyAcceptOnly", XrmoptionSepArg, NULL },
1584 { "-zippyUseI", "zippyUseI", XrmoptionSepArg, NULL },
1585 { "-zui", "zippyUseI", XrmoptionNoArg, "True" },
1586 { "-xzui", "zippyUseI", XrmoptionNoArg, "False" },
1587 { "-zippyBughouse", "zippyBughouse", XrmoptionSepArg, NULL },
1588 { "-zippyNoplayCrafty", "zippyNoplayCrafty", XrmoptionSepArg, NULL },
1589 { "-znc", "zippyNoplayCrafty", XrmoptionNoArg, "True" },
1590 { "-xznc", "zippyNoplayCrafty", XrmoptionNoArg, "False" },
1591 { "-zippyGameEnd", "zippyGameEnd", XrmoptionSepArg, NULL },
1592 { "-zippyGameStart", "zippyGameStart", XrmoptionSepArg, NULL },
1593 { "-zippyAdjourn", "zippyAdjourn", XrmoptionSepArg, NULL },
1594 { "-zadj", "zippyAdjourn", XrmoptionNoArg, "True" },
1595 { "-xzadj", "zippyAdjourn", XrmoptionNoArg, "False" },
1596 { "-zippyAbort", "zippyAbort", XrmoptionSepArg, NULL },
1597 { "-zab", "zippyAbort", XrmoptionNoArg, "True" },
1598 { "-xzab", "zippyAbort", XrmoptionNoArg, "False" },
1599 { "-zippyVariants", "zippyVariants", XrmoptionSepArg, NULL },
1600 { "-zippyMaxGames", "zippyMaxGames", XrmoptionSepArg, NULL },
1601 { "-zippyReplayTimeout", "zippyReplayTimeout", XrmoptionSepArg, NULL },
1602 { "-zippyShortGame", "zippyShortGame", XrmoptionSepArg, NULL },
1604 { "-flashCount", "flashCount", XrmoptionSepArg, NULL },
1605 { "-flash", "flashCount", XrmoptionNoArg, "3" },
1606 { "-xflash", "flashCount", XrmoptionNoArg, "0" },
1607 { "-flashRate", "flashRate", XrmoptionSepArg, NULL },
1608 { "-pixmapDirectory", "pixmapDirectory", XrmoptionSepArg, NULL },
1609 { "-msLoginDelay", "msLoginDelay", XrmoptionSepArg, NULL },
1610 { "-pixmap", "pixmapDirectory", XrmoptionSepArg, NULL },
1611 { "-colorizeMessages", "colorizeMessages", XrmoptionSepArg, NULL },
1612 { "-colorize", "colorizeMessages", XrmoptionNoArg, "True" },
1613 { "-xcolorize", "colorizeMessages", XrmoptionNoArg, "False" },
1614 { "-colorShout", "colorShout", XrmoptionSepArg, NULL },
1615 { "-colorSShout", "colorSShout", XrmoptionSepArg, NULL },
1616 { "-colorCShout", "colorSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1617 { "-colorChannel1", "colorChannel1", XrmoptionSepArg, NULL },
1618 { "-colorChannel", "colorChannel", XrmoptionSepArg, NULL },
1619 { "-colorKibitz", "colorKibitz", XrmoptionSepArg, NULL },
1620 { "-colorTell", "colorTell", XrmoptionSepArg, NULL },
1621 { "-colorChallenge", "colorChallenge", XrmoptionSepArg, NULL },
1622 { "-colorRequest", "colorRequest", XrmoptionSepArg, NULL },
1623 { "-colorSeek", "colorSeek", XrmoptionSepArg, NULL },
1624 { "-colorNormal", "colorNormal", XrmoptionSepArg, NULL },
1625 { "-soundProgram", "soundProgram", XrmoptionSepArg, NULL },
1626 { "-soundShout", "soundShout", XrmoptionSepArg, NULL },
1627 { "-soundSShout", "soundSShout", XrmoptionSepArg, NULL },
1628 { "-soundCShout", "soundSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1629 { "-soundChannel1", "soundChannel1", XrmoptionSepArg, NULL },
1630 { "-soundChannel", "soundChannel", XrmoptionSepArg, NULL },
1631 { "-soundKibitz", "soundKibitz", XrmoptionSepArg, NULL },
1632 { "-soundTell", "soundTell", XrmoptionSepArg, NULL },
1633 { "-soundChallenge", "soundChallenge", XrmoptionSepArg, NULL },
1634 { "-soundRequest", "soundRequest", XrmoptionSepArg, NULL },
1635 { "-soundSeek", "soundSeek", XrmoptionSepArg, NULL },
1636 { "-soundMove", "soundMove", XrmoptionSepArg, NULL },
1637 { "-soundIcsWin", "soundIcsWin", XrmoptionSepArg, NULL },
1638 { "-soundIcsLoss", "soundIcsLoss", XrmoptionSepArg, NULL },
1639 { "-soundIcsDraw", "soundIcsDraw", XrmoptionSepArg, NULL },
1640 { "-soundIcsUnfinished", "soundIcsUnfinished", XrmoptionSepArg, NULL },
1641 { "-soundIcsAlarm", "soundIcsAlarm", XrmoptionSepArg, NULL },
1642 { "-reuseFirst", "reuseFirst", XrmoptionSepArg, NULL },
1643 { "-reuseChessPrograms", "reuseFirst", XrmoptionSepArg, NULL }, /*compat*/
1644 { "-reuse", "reuseFirst", XrmoptionNoArg, "True" },
1645 { "-xreuse", "reuseFirst", XrmoptionNoArg, "False" },
1646 { "-reuseSecond", "reuseSecond", XrmoptionSepArg, NULL },
1647 { "-reuse2", "reuseSecond", XrmoptionNoArg, "True" },
1648 { "-xreuse2", "reuseSecond", XrmoptionNoArg, "False" },
1649 { "-animateMoving", "animateMoving", XrmoptionSepArg, NULL },
1650 { "-animate", "animateMoving", XrmoptionNoArg, "True" },
1651 { "-xanimate", "animateMoving", XrmoptionNoArg, "False" },
1652 { "-animateDragging", "animateDragging", XrmoptionSepArg, NULL },
1653 { "-drag", "animateDragging", XrmoptionNoArg, "True" },
1654 { "-xdrag", "animateDragging", XrmoptionNoArg, "False" },
1655 { "-animateSpeed", "animateSpeed", XrmoptionSepArg, NULL },
1656 { "-popupExitMessage", "popupExitMessage", XrmoptionSepArg, NULL },
1657 { "-exit", "popupExitMessage", XrmoptionNoArg, "True" },
1658 { "-xexit", "popupExitMessage", XrmoptionNoArg, "False" },
1659 { "-popupMoveErrors", "popupMoveErrors", XrmoptionSepArg, NULL },
1660 { "-popup", "popupMoveErrors", XrmoptionNoArg, "True" },
1661 { "-xpopup", "popupMoveErrors", XrmoptionNoArg, "False" },
1662 { "-fontSizeTolerance", "fontSizeTolerance", XrmoptionSepArg, NULL },
1663 { "-initialMode", "initialMode", XrmoptionSepArg, NULL },
1664 { "-mode", "initialMode", XrmoptionSepArg, NULL },
1665 { "-variant", "variant", XrmoptionSepArg, NULL },
1666 { "-firstProtocolVersion", "firstProtocolVersion", XrmoptionSepArg, NULL },
1667 { "-secondProtocolVersion","secondProtocolVersion",XrmoptionSepArg, NULL },
1668 { "-showButtonBar", "showButtonBar", XrmoptionSepArg, NULL },
1669 { "-buttons", "showButtonBar", XrmoptionNoArg, "True" },
1670 { "-xbuttons", "showButtonBar", XrmoptionNoArg, "False" },
1671 { "-lowTimeWarningColor", "lowTimeWarningColor", XrmoptionSepArg, NULL },
1672 { "-lowTimeWarning", "lowTimeWarning", XrmoptionSepArg, NULL },
1673 /* [AS,HR] New features */
1674 { "-firstScoreAbs", "firstScoreAbs", XrmoptionSepArg, NULL },
1675 { "-secondScoreAbs", "secondScoreAbs", XrmoptionSepArg, NULL },
1676 { "-pgnExtendedInfo", "pgnExtendedInfo", XrmoptionSepArg, NULL },
1677 { "-hideThinkingFromHuman", "hideThinkingFromHuman", XrmoptionSepArg, NULL },
1678 { "-adjudicateLossThreshold", "adjudicateLossThreshold", XrmoptionSepArg, NULL },
1679 { "-pgnEventHeader", "pgnEventHeader", XrmoptionSepArg, NULL },
1680 { "-firstIsUCI", "firstIsUCI", XrmoptionSepArg, NULL },
1681 { "-secondIsUCI", "secondIsUCI", XrmoptionSepArg, NULL },
1682 { "-fUCI", "firstIsUCI", XrmoptionNoArg, "True" },
1683 { "-sUCI", "secondIsUCI", XrmoptionNoArg, "True" },
1684 { "-firstHasOwnBookUCI", "firstHasOwnBookUCI", XrmoptionSepArg, NULL },
1685 { "-secondHasOwnBookUCI", "secondHasOwnBookUCI", XrmoptionSepArg, NULL },
1686 { "-fNoOwnBookUCI", "firstHasOwnBookUCI", XrmoptionNoArg, "False" },
1687 { "-sNoOwnBookUCI", "secondHasOwnBookUCI", XrmoptionNoArg, "False" },
1688 { "-firstXBook", "firstHasOwnBookUCI", XrmoptionNoArg, "False" },
1689 { "-secondXBook", "secondHasOwnBookUCI", XrmoptionNoArg, "False" },
1690 { "-polyglotDir", "polyglotDir", XrmoptionSepArg, NULL },
1691 { "-usePolyglotBook", "usePolyglotBook", XrmoptionSepArg, NULL },
1692 { "-polyglotBook", "polyglotBook", XrmoptionSepArg, NULL },
1693 { "-defaultHashSize", "defaultHashSize", XrmoptionSepArg, NULL },
1694 { "-defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XrmoptionSepArg, NULL },
1695 { "-defaultPathEGTB", "defaultPathEGTB", XrmoptionSepArg, NULL },
1696 { "-defaultFrcPosition", "defaultFrcPosition", XrmoptionSepArg, NULL },
1697 { "-gameListTags", "gameListTags", XrmoptionSepArg, NULL },
1698 // [HGM] I am sure AS added many more options, but we have to fish them out, from the list in winboard.c
1700 /* [HGM,HR] User-selectable board size */
1701 { "-boardWidth", "boardWidth", XrmoptionSepArg, NULL },
1702 { "-boardHeight", "boardHeight", XrmoptionSepArg, NULL },
1703 { "-matchPause", "matchPause", XrmoptionSepArg, NULL },
1705 /* [HGM] new arguments of 4.3.xx. All except first three are back-end options, which should work immediately */
1706 { "-holdingsSize", "holdingsSize", XrmoptionSepArg, NULL }, // requires extensive front-end changes to work
1707 { "-flipBlack", "flipBlack", XrmoptionSepArg, NULL }, // requires front-end changes to work
1708 { "-allWhite", "allWhite", XrmoptionSepArg, NULL }, // requires front-end changes to work
1709 { "-pieceToCharTable", "pieceToCharTable", XrmoptionSepArg, NULL },
1710 { "-alphaRank", "alphaRank", XrmoptionSepArg, NULL },
1711 { "-testClaims", "testClaims", XrmoptionSepArg, NULL },
1712 { "-checkMates", "checkMates", XrmoptionSepArg, NULL },
1713 { "-materialDraws", "materialDraws", XrmoptionSepArg, NULL },
1714 { "-trivialDraws", "trivialDraws", XrmoptionSepArg, NULL },
1715 { "-ruleMoves", "ruleMoves", XrmoptionSepArg, NULL },
1716 { "-repeatsToDraw", "repeatsToDraw", XrmoptionSepArg, NULL },
1717 { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL },
1718 { "-userName", "userName", XrmoptionSepArg, NULL },
1719 { "-autoKibitz", "autoKibitz", XrmoptionNoArg, "True" },
1720 { "-firstTimeOdds", "firstTimeOdds", XrmoptionSepArg, NULL },
1721 { "-secondTimeOdds", "secondTimeOdds", XrmoptionSepArg, NULL },
1722 { "-timeOddsMode", "timeOddsMode", XrmoptionSepArg, NULL },
1723 { "-firstAccumulateTC", "firstAccumulateTC", XrmoptionSepArg, NULL },
1724 { "-secondAccumulateTC", "secondAccumulateTC", XrmoptionSepArg, NULL },
1725 { "-firstNPS", "firstNPS", XrmoptionSepArg, NULL },
1726 { "-secondNPS", "secondNPS", XrmoptionSepArg, NULL },
1727 { "-serverMoves", "serverMoves", XrmoptionSepArg, NULL },
1728 { "-serverPause", "serverPause", XrmoptionSepArg, NULL },
1729 { "-suppressLoadMoves", "suppressLoadMoves", XrmoptionSepArg, NULL },
1730 { "-egtFormats", "egtFormats", XrmoptionSepArg, NULL },
1731 { "-userName", "userName", XrmoptionSepArg, NULL },
1732 { "-smpCores", "smpCores", XrmoptionSepArg, NULL },
1733 { "-sameColorGames", "sameColorGames", XrmoptionSepArg, NULL },
1734 { "-rewindIndex", "rewindIndex", XrmoptionSepArg, NULL },
1735 { "-niceEngines", "niceEngines", XrmoptionSepArg, NULL },
1736 { "-delayBeforeQuit", "delayBeforeQuit", XrmoptionSepArg, NULL },
1737 { "-delayAfterQuit", "delayAfterQuit", XrmoptionSepArg, NULL },
1738 { "-nameOfDebugFile", "nameOfDebugFile", XrmoptionSepArg, NULL },
1739 { "-debugFile", "nameOfDebugFile", XrmoptionSepArg, NULL },
1740 { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL },
1741 { "-noGUI", "noGUI", XrmoptionNoArg, "True" },
1742 { "-firstOptions", "firstOptions", XrmoptionSepArg, NULL },
1743 { "-secondOptions", "secondOptions", XrmoptionSepArg, NULL },
1744 { "-firstNeedsNoncompliantFEN", "firstNeedsNoncompliantFEN", XrmoptionSepArg, NULL },
1745 { "-secondNeedsNoncompliantFEN", "secondNeedsNoncompliantFEN", XrmoptionSepArg, NULL },
1749 XtActionsRec boardActions[] = {
1750 { "DrawPosition", DrawPositionProc },
1751 { "HandleUserMove", HandleUserMove },
1752 { "AnimateUserMove", AnimateUserMove },
1753 { "FileNameAction", FileNameAction },
1754 { "AskQuestionProc", AskQuestionProc },
1755 { "AskQuestionReplyAction", AskQuestionReplyAction },
1756 { "PieceMenuPopup", PieceMenuPopup },
1757 { "WhiteClock", WhiteClock },
1758 { "BlackClock", BlackClock },
1759 { "Iconify", Iconify },
1760 { "LoadSelectedProc", LoadSelectedProc },
1761 { "LoadPositionProc", LoadPositionProc },
1762 { "LoadNextPositionProc", LoadNextPositionProc },
1763 { "LoadPrevPositionProc", LoadPrevPositionProc },
1764 { "ReloadPositionProc", ReloadPositionProc },
1765 { "CopyPositionProc", CopyPositionProc },
1766 { "PastePositionProc", PastePositionProc },
1767 { "CopyGameProc", CopyGameProc },
1768 { "PasteGameProc", PasteGameProc },
1769 { "SaveGameProc", SaveGameProc },
1770 { "SavePositionProc", SavePositionProc },
1771 { "MailMoveProc", MailMoveProc },
1772 { "ReloadCmailMsgProc", ReloadCmailMsgProc },
1773 { "MachineWhiteProc", MachineWhiteProc },
1774 { "MachineBlackProc", MachineBlackProc },
1775 { "AnalysisModeProc", AnalyzeModeProc },
1776 { "AnalyzeFileProc", AnalyzeFileProc },
1777 { "TwoMachinesProc", TwoMachinesProc },
1778 { "IcsClientProc", IcsClientProc },
1779 { "EditGameProc", EditGameProc },
1780 { "EditPositionProc", EditPositionProc },
1781 { "TrainingProc", EditPositionProc },
1782 { "EngineOutputProc", EngineOutputProc}, // [HGM] Winboard_x engine-output window
1783 { "ShowGameListProc", ShowGameListProc },
1784 { "ShowMoveListProc", HistoryShowProc},
1785 { "EditTagsProc", EditCommentProc },
1786 { "EditCommentProc", EditCommentProc },
1787 { "IcsAlarmProc", IcsAlarmProc },
1788 { "IcsInputBoxProc", IcsInputBoxProc },
1789 { "AcceptProc", AcceptProc },
1790 { "DeclineProc", DeclineProc },
1791 { "RematchProc", RematchProc },
1792 { "CallFlagProc", CallFlagProc },
1793 { "DrawProc", DrawProc },
1794 { "AdjournProc", AdjournProc },
1795 { "AbortProc", AbortProc },
1796 { "ResignProc", ResignProc },
1797 { "AdjuWhiteProc", AdjuWhiteProc },
1798 { "AdjuBlackProc", AdjuBlackProc },
1799 { "AdjuDrawProc", AdjuDrawProc },
1800 { "EnterKeyProc", EnterKeyProc },
1801 { "StopObservingProc", StopObservingProc },
1802 { "StopExaminingProc", StopExaminingProc },
1803 { "BackwardProc", BackwardProc },
1804 { "ForwardProc", ForwardProc },
1805 { "ToStartProc", ToStartProc },
1806 { "ToEndProc", ToEndProc },
1807 { "RevertProc", RevertProc },
1808 { "TruncateGameProc", TruncateGameProc },
1809 { "MoveNowProc", MoveNowProc },
1810 { "RetractMoveProc", RetractMoveProc },
1811 { "AlwaysQueenProc", AlwaysQueenProc },
1812 { "AnimateDraggingProc", AnimateDraggingProc },
1813 { "AnimateMovingProc", AnimateMovingProc },
1814 { "AutoflagProc", AutoflagProc },
1815 { "AutoflipProc", AutoflipProc },
1816 { "AutobsProc", AutobsProc },
1817 { "AutoraiseProc", AutoraiseProc },
1818 { "AutosaveProc", AutosaveProc },
1819 { "BlindfoldProc", BlindfoldProc },
1820 { "FlashMovesProc", FlashMovesProc },
1821 { "FlipViewProc", FlipViewProc },
1822 { "GetMoveListProc", GetMoveListProc },
1824 { "HighlightDraggingProc", HighlightDraggingProc },
1826 { "HighlightLastMoveProc", HighlightLastMoveProc },
1827 { "IcsAlarmProc", IcsAlarmProc },
1828 { "MoveSoundProc", MoveSoundProc },
1829 { "OldSaveStyleProc", OldSaveStyleProc },
1830 { "PeriodicUpdatesProc", PeriodicUpdatesProc },
1831 { "PonderNextMoveProc", PonderNextMoveProc },
1832 { "PopupExitMessageProc", PopupExitMessageProc },
1833 { "PopupMoveErrorsProc", PopupMoveErrorsProc },
1834 { "PremoveProc", PremoveProc },
1835 { "QuietPlayProc", QuietPlayProc },
1836 { "ShowThinkingProc", ShowThinkingProc },
1837 { "HideThinkingProc", HideThinkingProc },
1838 { "TestLegalityProc", TestLegalityProc },
1839 { "InfoProc", InfoProc },
1840 { "ManProc", ManProc },
1841 { "HintProc", HintProc },
1842 { "BookProc", BookProc },
1843 { "AboutGameProc", AboutGameProc },
1844 { "DebugProc", DebugProc },
1845 { "NothingProc", NothingProc },
1846 { "CommentPopDown", (XtActionProc) CommentPopDown },
1847 { "EditCommentPopDown", (XtActionProc) EditCommentPopDown },
1848 { "TagsPopDown", (XtActionProc) TagsPopDown },
1849 { "ErrorPopDown", (XtActionProc) ErrorPopDown },
1850 { "ICSInputBoxPopDown", (XtActionProc) ICSInputBoxPopDown },
1851 { "AnalysisPopDown", (XtActionProc) AnalysisPopDown },
1852 { "FileNamePopDown", (XtActionProc) FileNamePopDown },
1853 { "AskQuestionPopDown", (XtActionProc) AskQuestionPopDown },
1854 { "GameListPopDown", (XtActionProc) GameListPopDown },
1855 { "PromotionPopDown", (XtActionProc) PromotionPopDown },
1856 { "HistoryPopDown", (XtActionProc) HistoryPopDown },
1857 { "EngineOutputPopDown", (XtActionProc) EngineOutputPopDown },
1858 { "ShufflePopDown", (XtActionProc) ShufflePopDown },
1859 { "EnginePopDown", (XtActionProc) EnginePopDown },
1860 { "UciPopDown", (XtActionProc) UciPopDown },
1861 { "TimeControlPopDown", (XtActionProc) TimeControlPopDown },
1862 { "NewVariantPopDown", (XtActionProc) NewVariantPopDown },
1863 { "SettingsPopDown", (XtActionProc) SettingsPopDown },
1866 char globalTranslations[] =
1867 ":<Key>R: ResignProc() \n \
1868 :<Key>F: ToEndProc() \n \
1869 :<Key>f: ForwardProc() \n \
1870 :<Key>B: ToStartProc() \n \
1871 :<Key>b: BackwardProc() \n \
1872 :<Key>d: DrawProc() \n \
1873 :<Key>t: CallFlagProc() \n \
1874 :<Key>i: Iconify() \n \
1875 :<Key>c: Iconify() \n \
1876 :<Key>v: FlipViewProc() \n \
1877 <KeyDown>Control_L: BackwardProc() \n \
1878 <KeyUp>Control_L: ForwardProc() \n \
1879 <KeyDown>Control_R: BackwardProc() \n \
1880 <KeyUp>Control_R: ForwardProc() \n \
1881 Shift<Key>1: AskQuestionProc(\"Direct command\",\
1882 \"Send to chess program:\",,1) \n \
1883 Shift<Key>2: AskQuestionProc(\"Direct command\",\
1884 \"Send to second chess program:\",,2) \n";
1886 char boardTranslations[] =
1887 "<Btn1Down>: HandleUserMove() \n \
1888 <Btn1Up>: HandleUserMove() \n \
1889 <Btn1Motion>: AnimateUserMove() \n \
1890 Shift<Btn2Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD)\
1891 PieceMenuPopup(menuB) \n \
1892 Any<Btn2Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD) \
1893 PieceMenuPopup(menuW) \n \
1894 Shift<Btn3Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD)\
1895 PieceMenuPopup(menuW) \n \
1896 Any<Btn3Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD) \
1897 PieceMenuPopup(menuB) \n";
1899 char whiteTranslations[] = "<BtnDown>: WhiteClock()\n";
1900 char blackTranslations[] = "<BtnDown>: BlackClock()\n";
1902 char ICSInputTranslations[] =
1903 "<Key>Return: EnterKeyProc() \n";
1905 String xboardResources[] = {
1906 "*fileName*value.translations: #override\\n <Key>Return: FileNameAction()",
1907 "*question*value.translations: #override\\n <Key>Return: AskQuestionReplyAction()",
1908 "*errorpopup*translations: #override\\n <Key>Return: ErrorPopDown()",
1913 /* Max possible square size */
1914 #define MAXSQSIZE 256
1916 static int xpm_avail[MAXSQSIZE];
1918 #ifdef HAVE_DIR_STRUCT
1920 /* Extract piece size from filename */
1922 xpm_getsize(name, len, ext)
1933 if ((p=strchr(name, '.')) == NULL ||
1934 StrCaseCmp(p+1, ext) != 0)
1940 while (*p && isdigit(*p))
1947 /* Setup xpm_avail */
1949 xpm_getavail(dirname, ext)
1957 for (i=0; i<MAXSQSIZE; ++i)
1960 if (appData.debugMode)
1961 fprintf(stderr, "XPM dir:%s:ext:%s:\n", dirname, ext);
1963 dir = opendir(dirname);
1966 fprintf(stderr, _("%s: Can't access XPM directory %s\n"),
1967 programName, dirname);
1971 while ((ent=readdir(dir)) != NULL) {
1972 i = xpm_getsize(ent->d_name, NAMLEN(ent), ext);
1973 if (i > 0 && i < MAXSQSIZE)
1983 xpm_print_avail(fp, ext)
1989 fprintf(fp, _("Available `%s' sizes:\n"), ext);
1990 for (i=1; i<MAXSQSIZE; ++i) {
1996 /* Return XPM piecesize closest to size */
1998 xpm_closest_to(dirname, size, ext)
2004 int sm_diff = MAXSQSIZE;
2008 xpm_getavail(dirname, ext);
2010 if (appData.debugMode)
2011 xpm_print_avail(stderr, ext);
2013 for (i=1; i<MAXSQSIZE; ++i) {
2016 diff = (diff<0) ? -diff : diff;
2017 if (diff < sm_diff) {
2025 fprintf(stderr, _("Error: No `%s' files!\n"), ext);
2031 #else /* !HAVE_DIR_STRUCT */
2032 /* If we are on a system without a DIR struct, we can't
2033 read the directory, so we can't collect a list of
2034 filenames, etc., so we can't do any size-fitting. */
2036 xpm_closest_to(dirname, size, ext)
2041 fprintf(stderr, _("\
2042 Warning: No DIR structure found on this system --\n\
2043 Unable to autosize for XPM/XIM pieces.\n\
2044 Please report this error to frankm@hiwaay.net.\n\
2045 Include system type & operating system in message.\n"));
2048 #endif /* HAVE_DIR_STRUCT */
2050 static char *cnames[9] = { "black", "red", "green", "yellow", "blue",
2051 "magenta", "cyan", "white" };
2055 TextColors textColors[(int)NColorClasses];
2057 /* String is: "fg, bg, attr". Which is 0, 1, 2 */
2059 parse_color(str, which)
2063 char *p, buf[100], *d;
2066 if (strlen(str) > 99) /* watch bounds on buf */
2071 for (i=0; i<which; ++i) {
2078 /* Could be looking at something like:
2080 .. in which case we want to stop on a comma also */
2081 while (*p && *p != ',' && !isalpha(*p) && !isdigit(*p))
2085 return -1; /* Use default for empty field */
2088 if (which == 2 || isdigit(*p))
2091 while (*p && isalpha(*p))
2096 for (i=0; i<8; ++i) {
2097 if (!StrCaseCmp(buf, cnames[i]))
2098 return which? (i+40) : (i+30);
2100 if (!StrCaseCmp(buf, "default")) return -1;
2102 fprintf(stderr, _("%s: unrecognized color %s\n"), programName, buf);
2107 parse_cpair(cc, str)
2111 if ((textColors[(int)cc].fg=parse_color(str, 0)) == -2) {
2112 fprintf(stderr, _("%s: can't parse foreground color in `%s'\n"),
2117 /* bg and attr are optional */
2118 textColors[(int)cc].bg = parse_color(str, 1);
2119 if ((textColors[(int)cc].attr = parse_color(str, 2)) < 0) {
2120 textColors[(int)cc].attr = 0;
2126 /* Arrange to catch delete-window events */
2127 Atom wm_delete_window;
2129 CatchDeleteWindow(Widget w, String procname)
2132 XSetWMProtocols(xDisplay, XtWindow(w), &wm_delete_window, 1);
2133 snprintf(buf, sizeof(buf), "<Message>WM_PROTOCOLS: %s() \n", procname);
2134 XtAugmentTranslations(w, XtParseTranslationTable(buf));
2140 /* this should raise the board to the top */
2141 gtk_window_present(GTK_WINDOW(GUI_Window));
2146 // eventually, all layout determining code should go into a subroutine, but until then IDSIZE remains undefined
2148 #define BoardSize int
2149 void InitDrawingSizes(BoardSize boardSize, int flags)
2150 { // [HGM] resize is functional now, but for board format changes only (nr of ranks, files)
2151 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
2153 XtGeometryResult gres;
2156 // if(!formWidget) return;
2159 * Enable shell resizing.
2161 // shellArgs[0].value = (XtArgVal) &w;
2162 // shellArgs[1].value = (XtArgVal) &h;
2163 // XtGetValues(shellWidget, shellArgs, 2);
2165 // shellArgs[4].value = 2*w; shellArgs[2].value = 10;
2166 // shellArgs[5].value = 2*h; shellArgs[3].value = 10;
2167 // XtSetValues(shellWidget, &shellArgs[2], 4);
2169 // XtSetArg(args[0], XtNdefaultDistance, &sep);
2170 // XtGetValues(formWidget, args, 1);
2172 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2173 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2176 // XtSetArg(args[0], XtNwidth, boardWidth);
2177 // XtSetArg(args[1], XtNheight, boardHeight);
2178 // XtSetValues(boardWidget, args, 2);
2180 timerWidth = (boardWidth - sep) / 2;
2181 // XtSetArg(args[0], XtNwidth, timerWidth);
2182 // XtSetValues(whiteTimerWidget, args, 1);
2183 // XtSetValues(blackTimerWidget, args, 1);
2185 // XawFormDoLayout(formWidget, False);
2187 if (appData.titleInWindow) {
2189 // XtSetArg(args[i], XtNborderWidth, &bor); i++;
2190 // XtSetArg(args[i], XtNheight, &h); i++;
2191 // XtGetValues(titleWidget, args, i);
2193 w = boardWidth - 2*bor;
2195 // XtSetArg(args[0], XtNwidth, &w);
2196 // XtGetValues(menuBarWidget, args, 1);
2197 w = boardWidth - w - sep - 2*bor - 2; // WIDTH_FUDGE
2200 // gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
2201 // if (gres != XtGeometryYes && appData.debugMode) {
2203 // _("%s: titleWidget geometry error %d %d %d %d %d\n"),
2204 // programName, gres, w, h, wr, hr);
2207 if(!formWidget) return;
2209 // XawFormDoLayout(formWidget, True);
2212 * Inhibit shell resizing.
2214 shellArgs[0].value = w = (XtArgVal) boardWidth + marginW;
2215 shellArgs[1].value = h = (XtArgVal) boardHeight + marginH;
2216 shellArgs[4].value = shellArgs[2].value = w;
2217 shellArgs[5].value = shellArgs[3].value = h;
2218 // XtSetValues(shellWidget, &shellArgs[0], 6);
2220 // [HGM] pieces: tailor piece bitmaps to needs of specific variant
2223 for(i=0; i<4; i++) {
2225 for(p=0; p<=(int)WhiteKing; p++)
2226 xpmPieceBitmap[i][p] = xpmPieceBitmap2[i][p]; // defaults
2227 if(gameInfo.variant == VariantShogi) {
2228 xpmPieceBitmap[i][(int)WhiteCannon] = xpmPieceBitmap2[i][(int)WhiteKing+1];
2229 xpmPieceBitmap[i][(int)WhiteNightrider] = xpmPieceBitmap2[i][(int)WhiteKing+2];
2230 xpmPieceBitmap[i][(int)WhiteSilver] = xpmPieceBitmap2[i][(int)WhiteKing+3];
2231 xpmPieceBitmap[i][(int)WhiteGrasshopper] = xpmPieceBitmap2[i][(int)WhiteKing+4];
2232 xpmPieceBitmap[i][(int)WhiteQueen] = xpmPieceBitmap2[i][(int)WhiteLance];
2235 if(gameInfo.variant == VariantGothic) {
2236 xpmPieceBitmap[i][(int)WhiteMarshall] = xpmPieceBitmap2[i][(int)WhiteSilver];
2240 // [HGM] why are thee ximMasks used at all? the ximPieceBitmaps seem to be never used!
2241 for(p=0; p<=(int)WhiteKing; p++)
2242 ximMaskPm[p] = ximMaskPm2[p]; // defaults
2243 if(gameInfo.variant == VariantShogi) {
2244 ximMaskPm[(int)WhiteCannon] = ximMaskPm2[(int)WhiteKing+1];
2245 ximMaskPm[(int)WhiteNightrider] = ximMaskPm2[(int)WhiteKing+2];
2246 ximMaskPm[(int)WhiteSilver] = ximMaskPm2[(int)WhiteKing+3];
2247 ximMaskPm[(int)WhiteGrasshopper] = ximMaskPm2[(int)WhiteKing+4];
2248 ximMaskPm[(int)WhiteQueen] = ximMaskPm2[(int)WhiteLance];
2251 if(gameInfo.variant == VariantGothic) {
2252 ximMaskPm[(int)WhiteMarshall] = ximMaskPm2[i][(int)WhiteSilver];
2258 for(i=0; i<2; i++) {
2260 for(p=0; p<=(int)WhiteKing; p++)
2261 pieceBitmap[i][p] = pieceBitmap2[i][p]; // defaults
2262 if(gameInfo.variant == VariantShogi) {
2263 pieceBitmap[i][(int)WhiteCannon] = pieceBitmap2[i][(int)WhiteKing+1];
2264 pieceBitmap[i][(int)WhiteNightrider] = pieceBitmap2[i][(int)WhiteKing+2];
2265 pieceBitmap[i][(int)WhiteSilver] = pieceBitmap2[i][(int)WhiteKing+3];
2266 pieceBitmap[i][(int)WhiteGrasshopper] = pieceBitmap2[i][(int)WhiteKing+4];
2267 pieceBitmap[i][(int)WhiteQueen] = pieceBitmap2[i][(int)WhiteLance];
2270 if(gameInfo.variant == VariantGothic) {
2271 pieceBitmap[i][(int)WhiteMarshall] = pieceBitmap2[i][(int)WhiteSilver];
2287 int i, j, clockFontPxlSize, coordFontPxlSize, fontPxlSize;
2288 XSetWindowAttributes window_attributes;
2290 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
2291 XrmValue vFrom, vTo;
2292 XtGeometryResult gres;
2295 int forceMono = False;
2298 // [HGM] before anything else, expand any indirection files amongst options
2299 char *argvCopy[1000]; // 1000 seems enough
2300 char newArgs[10000]; // holds actual characters
2303 srandom(time(0)); // [HGM] book: make random truly random
2306 for(i=0; i<argc; i++) {
2307 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2308 //fprintf(stderr, "arg %s\n", argv[i]);
2309 if(argv[i][0] != '@') argvCopy[j++] = argv[i]; else {
2311 FILE *f = fopen(argv[i]+1, "rb");
2312 if(f == NULL) { fprintf(stderr, _("ignore %s\n"), argv[i]); continue; } // do not expand non-existing
2313 argvCopy[j++] = newArgs + k; // get ready for first argument from file
2314 while((c = fgetc(f)) != EOF) { // each line of file inserts 1 argument in the list
2316 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2317 newArgs[k++] = 0; // terminate current arg
2318 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2319 argvCopy[j++] = newArgs + k; // get ready for next
2321 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2334 if(appData.debugMode,1) { // OK, appData is not initialized here yet...
2335 for(i=0; i<argc; i++) fprintf(stderr, "argv[%2d] = '%s'\n", i, argv[i]);
2341 setbuf(stdout, NULL);
2342 setbuf(stderr, NULL);
2345 programName = strrchr(argv[0], '/');
2346 if (programName == NULL)
2347 programName = argv[0];
2352 XtSetLanguageProc(NULL, NULL, NULL);
2353 bindtextdomain(PACKAGE, LOCALEDIR);
2354 textdomain(PACKAGE);
2358 XtAppInitialize(&appContext, "XBoard", shellOptions,
2359 XtNumber(shellOptions),
2360 &argc, argv, xboardResources, NULL, 0);
2362 gtk_init (&argc, &argv);
2364 /* parse glade file */
2366 builder = gtk_builder_new ();
2367 gtk_builder_add_from_file (builder, "gtk-interface.xml", NULL);
2369 GUI_Window = GTK_WIDGET (gtk_builder_get_object (builder, "MainWindow"));
2370 if(!GUI_Window) printf("Error: gtk_builder didn't work!\n");
2371 GUI_Board = GTK_WIDGET (gtk_builder_get_object (builder, "Board"));
2372 if(!GUI_Board) printf("Error: gtk_builder didn't work!\n");
2373 GUI_Whiteclock = GTK_WIDGET (gtk_builder_get_object (builder, "WhiteClock"));
2374 if(!GUI_Whiteclock) printf("Error: gtk_builder didn't work!\n");
2375 GUI_Blackclock = GTK_WIDGET (gtk_builder_get_object (builder, "BlackClock"));
2376 if(!GUI_Blackclock) printf("Error: gtk_builder didn't work!\n");
2378 gtk_builder_connect_signals (builder, NULL);
2379 // don't unref the builder, since we use it to get references to widgets
2380 // g_object_unref (G_OBJECT (builder));
2382 printf("DEBUG:finished building gtk\n");
2383 /* end parse glade file */
2386 fprintf(stderr, _("%s: unrecognized argument %s\n"),
2387 programName, argv[1]);
2388 fprintf(stderr, "Recognized options:\n");
2389 for(i = 0; i < XtNumber(shellOptions); i++) {
2390 j = fprintf(stderr, " %s%s", shellOptions[i].option,
2391 (shellOptions[i].argKind == XrmoptionSepArg
2393 if (i++ < XtNumber(shellOptions)) {
2394 fprintf(stderr, "%*c%s%s\n", 40 - j, ' ',
2395 shellOptions[i].option,
2396 (shellOptions[i].argKind == XrmoptionSepArg
2399 fprintf(stderr, "\n");
2405 if ((chessDir = (char *) getenv("CHESSDIR")) == NULL) {
2408 if (chdir(chessDir) != 0) {
2409 fprintf(stderr, _("%s: can't cd to CHESSDIR: "), programName);
2416 if (p == NULL) p = "/tmp";
2417 i = strlen(p) + strlen("/.xboardXXXXXx.pgn") + 1;
2418 gameCopyFilename = (char*) malloc(i);
2419 gamePasteFilename = (char*) malloc(i);
2420 snprintf(gameCopyFilename,i, "%s/.xboard%05uc.pgn", p, getpid());
2421 snprintf(gamePasteFilename,i, "%s/.xboard%05up.pgn", p, getpid());
2423 XtGetApplicationResources(shellWidget, (XtPointer) &appData,
2424 clientResources, XtNumber(clientResources),
2427 if (appData.debugMode && appData.nameOfDebugFile && strcmp(appData.nameOfDebugFile, "stderr")) {
2428 /* [DM] debug info to file [HGM] make the filename a command-line option, and allow it to remain stderr */
2429 if ((debugFP = fopen(appData.nameOfDebugFile, "w")) == NULL) {
2430 printf(_("Failed to open file '%s'\n"), appData.nameOfDebugFile);
2433 setbuf(debugFP, NULL);
2436 /* [HGM,HR] make sure board size is acceptable */
2437 if(appData.NrFiles > BOARD_SIZE ||
2438 appData.NrRanks > BOARD_SIZE )
2439 DisplayFatalError(_("Recompile with BOARD_SIZE > 12, to support this size"), 0, 2);
2442 /* This feature does not work; animation needs a rewrite */
2443 appData.highlightDragging = FALSE;
2447 xDisplay = XtDisplay(shellWidget);
2448 xScreen = DefaultScreen(xDisplay);
2449 wm_delete_window = XInternAtom(xDisplay, "WM_DELETE_WINDOW", True);
2451 gameInfo.variant = StringToVariant(appData.variant);
2452 InitPosition(FALSE);
2455 * Determine boardSize
2457 gameInfo.boardWidth = gameInfo.boardHeight = 8; // [HGM] boardsize: make sure we start as 8x8
2460 // [HGM] as long as we have not created the possibility to change size while running, start with requested size
2461 gameInfo.boardWidth = appData.NrFiles > 0 ? appData.NrFiles : 8;
2462 gameInfo.boardHeight = appData.NrRanks > 0 ? appData.NrRanks : 8;
2463 gameInfo.holdingsWidth = appData.holdingsSize > 0 ? 2 : 0;
2468 InitDrawingSizes(-1, 0); // [HGM] initsize: make this into a subroutine
2470 if (isdigit(appData.boardSize[0])) {
2471 i = sscanf(appData.boardSize, "%d,%d,%d,%d,%d,%d,%d", &squareSize,
2472 &lineGap, &clockFontPxlSize, &coordFontPxlSize,
2473 &fontPxlSize, &smallLayout, &tinyLayout);
2475 fprintf(stderr, _("%s: bad boardSize syntax %s\n"),
2476 programName, appData.boardSize);
2480 /* Find some defaults; use the nearest known size */
2481 SizeDefaults *szd, *nearest;
2482 int distance = 99999;
2483 nearest = szd = sizeDefaults;
2484 while (szd->name != NULL) {
2485 if (abs(szd->squareSize - squareSize) < distance) {
2487 distance = abs(szd->squareSize - squareSize);
2488 if (distance == 0) break;
2492 if (i < 2) lineGap = nearest->lineGap;
2493 if (i < 3) clockFontPxlSize = nearest->clockFontPxlSize;
2494 if (i < 4) coordFontPxlSize = nearest->coordFontPxlSize;
2495 if (i < 5) fontPxlSize = nearest->fontPxlSize;
2496 if (i < 6) smallLayout = nearest->smallLayout;
2497 if (i < 7) tinyLayout = nearest->tinyLayout;
2500 SizeDefaults *szd = sizeDefaults;
2501 if (*appData.boardSize == NULLCHAR) {
2502 while (DisplayWidth(xDisplay, xScreen) < szd->minScreenSize ||
2503 DisplayHeight(xDisplay, xScreen) < szd->minScreenSize) {
2506 if (szd->name == NULL) szd--;
2508 while (szd->name != NULL &&
2509 StrCaseCmp(szd->name, appData.boardSize) != 0) szd++;
2510 if (szd->name == NULL) {
2511 fprintf(stderr, _("%s: unrecognized boardSize name %s\n"),
2512 programName, appData.boardSize);
2516 squareSize = szd->squareSize;
2517 lineGap = szd->lineGap;
2518 clockFontPxlSize = szd->clockFontPxlSize;
2519 coordFontPxlSize = szd->coordFontPxlSize;
2520 fontPxlSize = szd->fontPxlSize;
2521 smallLayout = szd->smallLayout;
2522 tinyLayout = szd->tinyLayout;
2525 printf("DEBUG::main: squareSize %d\n",squareSize);
2527 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2528 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2529 if (appData.showJail == 1) {
2530 /* Jail on top and bottom */
2531 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2532 XtSetArg(boardArgs[2], XtNheight,
2533 boardHeight + 2*(lineGap + squareSize));
2534 } else if (appData.showJail == 2) {
2536 XtSetArg(boardArgs[1], XtNwidth,
2537 boardWidth + 2*(lineGap + squareSize));
2538 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2541 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2542 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2546 * Determine what fonts to use.
2548 appData.clockFont = FindFont(appData.clockFont, clockFontPxlSize);
2549 clockFontID = XLoadFont(xDisplay, appData.clockFont);
2550 clockFontStruct = XQueryFont(xDisplay, clockFontID);
2551 appData.coordFont = FindFont(appData.coordFont, coordFontPxlSize);
2552 coordFontID = XLoadFont(xDisplay, appData.coordFont);
2553 coordFontStruct = XQueryFont(xDisplay, coordFontID);
2554 appData.font = FindFont(appData.font, fontPxlSize);
2555 countFontID = XLoadFont(xDisplay, appData.coordFont); // [HGM] holdings
2556 countFontStruct = XQueryFont(xDisplay, countFontID);
2557 // appData.font = FindFont(appData.font, fontPxlSize);
2559 xdb = XtDatabase(xDisplay);
2560 XrmPutStringResource(&xdb, "*font", appData.font);
2563 * Detect if there are not enough colors available and adapt.
2565 if (DefaultDepth(xDisplay, xScreen) <= 2) {
2566 appData.monoMode = True;
2569 if (!appData.monoMode) {
2570 vFrom.addr = (caddr_t) appData.lightSquareColor;
2571 vFrom.size = strlen(appData.lightSquareColor);
2572 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2573 if (vTo.addr == NULL) {
2574 appData.monoMode = True;
2577 lightSquareColor = *(Pixel *) vTo.addr;
2580 if (!appData.monoMode) {
2581 vFrom.addr = (caddr_t) appData.darkSquareColor;
2582 vFrom.size = strlen(appData.darkSquareColor);
2583 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2584 if (vTo.addr == NULL) {
2585 appData.monoMode = True;
2588 darkSquareColor = *(Pixel *) vTo.addr;
2591 if (!appData.monoMode) {
2592 vFrom.addr = (caddr_t) appData.whitePieceColor;
2593 vFrom.size = strlen(appData.whitePieceColor);
2594 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2595 if (vTo.addr == NULL) {
2596 appData.monoMode = True;
2599 whitePieceColor = *(Pixel *) vTo.addr;
2602 if (!appData.monoMode) {
2603 vFrom.addr = (caddr_t) appData.blackPieceColor;
2604 vFrom.size = strlen(appData.blackPieceColor);
2605 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2606 if (vTo.addr == NULL) {
2607 appData.monoMode = True;
2610 blackPieceColor = *(Pixel *) vTo.addr;
2614 if (!appData.monoMode) {
2615 vFrom.addr = (caddr_t) appData.highlightSquareColor;
2616 vFrom.size = strlen(appData.highlightSquareColor);
2617 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2618 if (vTo.addr == NULL) {
2619 appData.monoMode = True;
2622 highlightSquareColor = *(Pixel *) vTo.addr;
2626 if (!appData.monoMode) {
2627 vFrom.addr = (caddr_t) appData.premoveHighlightColor;
2628 vFrom.size = strlen(appData.premoveHighlightColor);
2629 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2630 if (vTo.addr == NULL) {
2631 appData.monoMode = True;
2634 premoveHighlightColor = *(Pixel *) vTo.addr;
2639 fprintf(stderr, _("%s: too few colors available; trying monochrome mode\n"),
2642 if (appData.bitmapDirectory == NULL ||
2643 appData.bitmapDirectory[0] == NULLCHAR)
2644 appData.bitmapDirectory = DEF_BITMAP_DIR;
2647 if (appData.lowTimeWarning && !appData.monoMode) {
2648 vFrom.addr = (caddr_t) appData.lowTimeWarningColor;
2649 vFrom.size = strlen(appData.lowTimeWarningColor);
2650 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2651 if (vTo.addr == NULL)
2652 appData.monoMode = True;
2654 lowTimeWarningColor = *(Pixel *) vTo.addr;
2657 if (appData.monoMode && appData.debugMode) {
2658 fprintf(stderr, _("white pixel = 0x%lx, black pixel = 0x%lx\n"),
2659 (unsigned long) XWhitePixel(xDisplay, xScreen),
2660 (unsigned long) XBlackPixel(xDisplay, xScreen));
2663 if (parse_cpair(ColorShout, appData.colorShout) < 0 ||
2664 parse_cpair(ColorSShout, appData.colorSShout) < 0 ||
2665 parse_cpair(ColorChannel1, appData.colorChannel1) < 0 ||
2666 parse_cpair(ColorChannel, appData.colorChannel) < 0 ||
2667 parse_cpair(ColorKibitz, appData.colorKibitz) < 0 ||
2668 parse_cpair(ColorTell, appData.colorTell) < 0 ||
2669 parse_cpair(ColorChallenge, appData.colorChallenge) < 0 ||
2670 parse_cpair(ColorRequest, appData.colorRequest) < 0 ||
2671 parse_cpair(ColorSeek, appData.colorSeek) < 0 ||
2672 parse_cpair(ColorNormal, appData.colorNormal) < 0)
2674 if (appData.colorize) {
2676 _("%s: can't parse color names; disabling colorization\n"),
2679 appData.colorize = FALSE;
2681 textColors[ColorNone].fg = textColors[ColorNone].bg = -1;
2682 textColors[ColorNone].attr = 0;
2684 printf("DEBUG: I'm here 0\n");
2686 // XtAppAddActions(appContext, boardActions, XtNumber(boardActions));
2692 layoutName = "tinyLayout";
2693 } else if (smallLayout) {
2694 layoutName = "smallLayout";
2696 layoutName = "normalLayout";
2698 /* Outer layoutWidget is there only to provide a name for use in
2699 resources that depend on the layout style */
2701 XtCreateManagedWidget(layoutName, formWidgetClass, shellWidget,
2702 layoutArgs, XtNumber(layoutArgs));
2704 XtCreateManagedWidget("form", formWidgetClass, layoutWidget,
2705 formArgs, XtNumber(formArgs));
2706 XtSetArg(args[0], XtNdefaultDistance, &sep);
2707 XtGetValues(formWidget, args, 1);
2710 widgetList[j++] = menuBarWidget = CreateMenuBar(menuBar);
2711 XtSetArg(args[0], XtNtop, XtChainTop);
2712 XtSetArg(args[1], XtNbottom, XtChainTop);
2713 XtSetValues(menuBarWidget, args, 2);
2715 widgetList[j++] = whiteTimerWidget =
2716 XtCreateWidget("whiteTime", labelWidgetClass,
2717 formWidget, timerArgs, XtNumber(timerArgs));
2718 XtSetArg(args[0], XtNfont, clockFontStruct);
2719 XtSetArg(args[1], XtNtop, XtChainTop);
2720 XtSetArg(args[2], XtNbottom, XtChainTop);
2721 XtSetValues(whiteTimerWidget, args, 3);
2723 widgetList[j++] = blackTimerWidget =
2724 XtCreateWidget("blackTime", labelWidgetClass,
2725 formWidget, timerArgs, XtNumber(timerArgs));
2726 XtSetArg(args[0], XtNfont, clockFontStruct);
2727 XtSetArg(args[1], XtNtop, XtChainTop);
2728 XtSetArg(args[2], XtNbottom, XtChainTop);
2729 XtSetValues(blackTimerWidget, args, 3);
2730 printf("DEBUG: I'm here 1\n");
2732 if (appData.titleInWindow) {
2733 widgetList[j++] = titleWidget =
2734 XtCreateWidget("title", labelWidgetClass, formWidget,
2735 titleArgs, XtNumber(titleArgs));
2736 XtSetArg(args[0], XtNtop, XtChainTop);
2737 XtSetArg(args[1], XtNbottom, XtChainTop);
2738 XtSetValues(titleWidget, args, 2);
2741 if (appData.showButtonBar) {
2742 widgetList[j++] = buttonBarWidget = CreateButtonBar(buttonBar);
2743 XtSetArg(args[0], XtNleft, XtChainRight); // [HGM] glue to right window edge
2744 XtSetArg(args[1], XtNright, XtChainRight); // for good run-time sizing
2745 XtSetArg(args[2], XtNtop, XtChainTop);
2746 XtSetArg(args[3], XtNbottom, XtChainTop);
2747 XtSetValues(buttonBarWidget, args, 4);
2750 // widgetList[j++] = messageWidget =
2751 // XtCreateWidget("message", labelWidgetClass, formWidget,
2752 // messageArgs, XtNumber(messageArgs));
2753 // XtSetArg(args[0], XtNtop, XtChainTop);
2754 // XtSetArg(args[1], XtNbottom, XtChainTop);
2755 // XtSetValues(messageWidget, args, 2);
2757 // widgetList[j++] = boardWidget =
2758 // XtCreateWidget("board", widgetClass, formWidget, boardArgs,
2759 // XtNumber(boardArgs));
2761 // XtManageChildren(widgetList, j);
2763 // timerWidth = (boardWidth - sep) / 2;
2764 // XtSetArg(args[0], XtNwidth, timerWidth);
2765 // XtSetValues(whiteTimerWidget, args, 1);
2766 // XtSetValues(blackTimerWidget, args, 1);
2768 // XtSetArg(args[0], XtNbackground, &timerBackgroundPixel);
2769 // XtSetArg(args[1], XtNforeground, &timerForegroundPixel);
2770 // XtGetValues(whiteTimerWidget, args, 2);
2772 // if (appData.showButtonBar) {
2773 // XtSetArg(args[0], XtNbackground, &buttonBackgroundPixel);
2774 // XtSetArg(args[1], XtNforeground, &buttonForegroundPixel);
2775 // XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
2780 * gtk set properties of widgets
2783 /* set board size */
2784 gtk_widget_set_size_request(GTK_WIDGET(GUI_Board),
2785 boardWidth,boardHeight);
2787 /* end gtk set properties of widgets */
2789 printf("DEBUG: made it.\n");
2792 * formWidget uses these constraints but they are stored
2796 // XtSetArg(args[i], XtNfromHoriz, 0); i++;
2797 // XtSetValues(menuBarWidget, args, i);
2798 // if (appData.titleInWindow) {
2799 // if (smallLayout) {
2800 // printf("DEBUG: made it a.\n");
2802 // XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2803 // XtSetValues(whiteTimerWidget, args, i);
2805 // XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2806 // XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2807 // XtSetValues(blackTimerWidget, args, i);
2809 // XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2810 // XtSetArg(args[i], XtNjustify, XtJustifyLeft); i++;
2811 // XtSetValues(titleWidget, args, i);
2813 // XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2814 // XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2815 // XtSetValues(messageWidget, args, i);
2816 // if (appData.showButtonBar) {
2818 // XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2819 // XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2820 // XtSetValues(buttonBarWidget, args, i);
2823 // printf("DEBUG: made it b.\n");
2825 // XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2826 // XtSetValues(whiteTimerWidget, args, i);
2828 // XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2829 // XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2830 // XtSetValues(blackTimerWidget, args, i);
2832 // XtSetArg(args[i], XtNfromHoriz, menuBarWidget); i++;
2833 // XtSetValues(titleWidget, args, i);
2835 // XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2836 // XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2837 // XtSetValues(messageWidget, args, i);
2838 // if (appData.showButtonBar) {
2840 // XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2841 // XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2842 // XtSetValues(buttonBarWidget, args, i);
2845 // } else { printf("DEBUG: made it c.\n");
2848 // XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2849 // XtSetValues(whiteTimerWidget, args, i);
2851 // XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2852 // XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2853 // XtSetValues(blackTimerWidget, args, i);
2855 // XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2856 // XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2857 // XtSetValues(messageWidget, args, i);
2858 // if (appData.showButtonBar) {
2860 // XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2861 // XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2862 // XtSetValues(buttonBarWidget, args, i);
2865 // printf("DEBUG: made it 1.\n");
2867 // XtSetArg(args[0], XtNfromVert, messageWidget);
2868 // XtSetArg(args[1], XtNtop, XtChainTop);
2869 // XtSetArg(args[2], XtNbottom, XtChainBottom);
2870 // XtSetArg(args[3], XtNleft, XtChainLeft);
2871 // XtSetArg(args[4], XtNright, XtChainRight);
2872 // XtSetValues(boardWidget, args, 5);
2874 // XtRealizeWidget(shellWidget);
2876 printf("DEBUG: made it 2.\n");
2879 * Correct the width of the message and title widgets.
2880 * It is not known why some systems need the extra fudge term.
2881 * The value "2" is probably larger than needed.
2883 // XawFormDoLayout(formWidget, False);
2885 #define WIDTH_FUDGE 2
2887 // XtSetArg(args[i], XtNborderWidth, &bor); i++;
2888 // XtSetArg(args[i], XtNheight, &h); i++;
2889 // XtGetValues(messageWidget, args, i);
2890 if (appData.showButtonBar) {
2892 // XtSetArg(args[i], XtNwidth, &w); i++;
2893 // XtGetValues(buttonBarWidget, args, i);
2894 // w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2896 // w = boardWidth - 2*bor + 1; /*!! +1 compensates for kludge below */
2899 // gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2900 if (gres != XtGeometryYes && appData.debugMode) {
2901 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2902 programName, gres, w, h, wr, hr);
2905 /* !! Horrible hack to work around bug in XFree86 4.0.1 (X11R6.4.3) */
2906 /* The size used for the child widget in layout lags one resize behind
2907 its true size, so we resize a second time, 1 pixel smaller. Yeech! */
2909 // gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2910 if (gres != XtGeometryYes && appData.debugMode) {
2911 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2912 programName, gres, w, h, wr, hr);
2915 // XtSetArg(args[0], XtNleft, XtChainLeft); // [HGM] glue ends for good run-time sizing
2916 // XtSetArg(args[1], XtNright, XtChainRight);
2917 // XtSetValues(messageWidget, args, 2);
2919 if (appData.titleInWindow) {
2921 // XtSetArg(args[i], XtNborderWidth, &bor); i++;
2922 // XtSetArg(args[i], XtNheight, &h); i++;
2923 // XtGetValues(titleWidget, args, i);
2925 w = boardWidth - 2*bor;
2927 // XtSetArg(args[0], XtNwidth, &w);
2928 // XtGetValues(menuBarWidget, args, 1);
2929 // w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2932 // gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
2933 if (gres != XtGeometryYes && appData.debugMode) {
2935 _("%s: titleWidget geometry error %d %d %d %d %d\n"),
2936 programName, gres, w, h, wr, hr);
2939 // XawFormDoLayout(formWidget, True);
2941 // xBoardWindow = XtWindow(boardWidget);
2943 // [HGM] it seems the layout code ends here, but perhaps the color stuff is size independent and would
2944 // not need to go into InitDrawingSizes().
2947 if (appData.alwaysPromoteToQueen) {
2948 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Always Queen")),TRUE);
2950 if (appData.animateDragging) {
2951 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Animate Dragging")),TRUE);
2953 if (appData.animate) {
2954 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Animate Moving")),TRUE);
2956 if (appData.autoComment) {
2957 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Comment")),TRUE);
2959 if (appData.autoCallFlag) {
2960 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Flag")),TRUE);
2962 if (appData.autoFlipView) {
2963 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Flip View")),TRUE);
2965 if (appData.autoObserve) {
2966 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Observe")),TRUE);
2968 if (appData.autoRaiseBoard) {
2969 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Raise Board")),TRUE);
2971 if (appData.autoSaveGames) {
2972 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Save")),TRUE);
2974 if (appData.saveGameFile[0] != NULLCHAR) {
2975 /* Can't turn this off from menu */
2976 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Save")),TRUE);
2977 gtk_action_set_sensitive(GTK_ACTION (gtk_builder_get_object (builder, "menuOptions.Auto Save")),FALSE);
2979 if (appData.blindfold) {
2980 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Blindfold")),TRUE);
2982 if (appData.flashCount > 0) {
2983 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Flash Moves")),TRUE);
2985 if (appData.getMoveList) {
2986 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Get Move List")),TRUE);
2989 if (appData.highlightDragging) {
2990 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Highlight Dragging")),TRUE);
2993 if (appData.highlightLastMove) {
2994 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Highlight Last Move")),TRUE);
2996 if (appData.icsAlarm) {
2997 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.ICS Alarm")),TRUE);
2999 if (appData.ringBellAfterMoves) {
3000 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Move Sound")),TRUE);
3002 if (appData.oldSaveStyle) {
3003 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Old Save Style")),TRUE);
3005 if (appData.periodicUpdates) {
3006 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Periodic Updates")),TRUE);
3008 if (appData.ponderNextMove) {
3009 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Ponder Next Move")),TRUE);
3011 if (appData.popupExitMessage) {
3012 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Popup Exit Message")),TRUE);
3014 if (appData.popupMoveErrors) {
3015 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Popup Move Errors")),TRUE);
3017 if (appData.premove) {
3018 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Premove")),TRUE);
3020 if (appData.quietPlay) {
3021 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Quit Play")),TRUE);
3023 if (appData.showCoords) {
3024 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Show Coords")),TRUE);
3026 if (appData.showThinking) {
3027 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Show Thinking")),TRUE);
3029 if (appData.testLegality) {
3030 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Test Legality")),TRUE);
3036 // ReadBitmap(&wIconPixmap, "icon_white.bm",
3037 // icon_white_bits, icon_white_width, icon_white_height);
3038 // ReadBitmap(&bIconPixmap, "icon_black.bm",
3039 // icon_black_bits, icon_black_width, icon_black_height);
3040 // iconPixmap = wIconPixmap;
3042 // XtSetArg(args[i], XtNiconPixmap, iconPixmap); i++;
3043 // XtSetValues(shellWidget, args, i);
3046 printf("DEBUG: creating svgs.\n");
3048 /* load square colors */
3049 SVGLightSquare = load_pixbuf("svg/LightSquare.svg");
3050 SVGDarkSquare = load_pixbuf("svg/DarkSquare.svg");
3051 SVGNeutralSquare = load_pixbuf("svg/NeutralSquare.svg");
3053 /* use two icons to indicate if it is white's or black's turn */
3054 WhiteIcon = load_pixbuf("svg/icon_white.svg");
3055 BlackIcon = load_pixbuf("svg/icon_black.svg");
3056 WindowIcon = WhiteIcon;
3057 gtk_window_set_icon(GTK_WINDOW(GUI_Window),WindowIcon);
3059 /* do resizing to a fixed aspect ratio */
3061 hints.min_aspect = 0.8;
3062 hints.max_aspect = 0.8;
3063 gtk_window_set_geometry_hints (GTK_WINDOW (GUI_Window),
3064 GTK_WIDGET (GUI_Window),
3068 /* realize window */
3069 gtk_widget_show (GUI_Window);
3071 printf("DEBUG: before created stuff squareSize %d.\n",squareSize);
3079 if (appData.animate || appData.animateDragging)
3082 printf("DEBUG: created stuff squareSize %d.\n",squareSize);
3085 // XtAugmentTranslations(formWidget,
3086 // XtParseTranslationTable(globalTranslations));
3087 // XtAugmentTranslations(boardWidget,
3088 // XtParseTranslationTable(boardTranslations));
3089 // XtAugmentTranslations(whiteTimerWidget,
3090 // XtParseTranslationTable(whiteTranslations));
3091 // XtAugmentTranslations(blackTimerWidget,
3092 // XtParseTranslationTable(blackTranslations));
3096 printf("DEBUG: back end initiated.\n");
3098 if (errorExitStatus == -1) {
3099 if (appData.icsActive) {
3100 /* We now wait until we see "login:" from the ICS before
3101 sending the logon script (problems with timestamp otherwise) */
3102 /*ICSInitScript();*/
3103 if (appData.icsInputBox) ICSInputBoxPopUp();
3106 signal(SIGINT, IntSigHandler);
3107 signal(SIGTERM, IntSigHandler);
3108 if (*appData.cmailGameName != NULLCHAR) {
3109 signal(SIGUSR1, CmailSigHandler);
3112 gameInfo.boardWidth = 0; // [HGM] pieces: kludge to ensure InitPosition() calls InitDrawingSizes()
3116 * Create a cursor for the board widget.
3117 * (This needs to be called after the window has been created to have access to board-window)
3120 BoardCursor = gdk_cursor_new(GDK_HAND2);
3121 gdk_window_set_cursor(GUI_Board->window, BoardCursor);
3122 gdk_cursor_destroy(BoardCursor);
3125 printf("DEBUG: going into gtk-main.\n");
3129 if (appData.debugMode) fclose(debugFP); // [DM] debug
3136 if (appData.icsActive && oldICSInteractionTitle != NULL) {
3137 DisplayIcsInteractionTitle(oldICSInteractionTitle);
3139 unlink(gameCopyFilename);
3140 unlink(gamePasteFilename);
3151 CmailSigHandler(sig)
3157 signal(SIGUSR1, SIG_IGN); /* suspend handler */
3159 /* Activate call-back function CmailSigHandlerCallBack() */
3160 OutputToProcess(cmailPR, (char *)(&dummy), sizeof(int), &error);
3162 signal(SIGUSR1, CmailSigHandler); /* re-activate handler */
3166 CmailSigHandlerCallBack(isr, closure, message, count, error)
3174 ReloadCmailMsgEvent(TRUE); /* Reload cmail msg */
3176 /**** end signal code ****/
3186 f = fopen(appData.icsLogon, "r");
3192 strcat(buf, appData.icsLogon);
3193 f = fopen(buf, "r");
3197 ProcessICSInitScript(f);
3204 EditCommentPopDown();
3215 SetMenuEnables(enab)
3220 if (!builder) return;
3221 while (enab->name != NULL) {
3222 o = gtk_builder_get_object(builder, enab->name);
3223 if(GTK_IS_WIDGET(o))
3224 gtk_widget_set_sensitive(GTK_WIDGET (o),enab->value);
3227 if(GTK_IS_ACTION(o))
3228 gtk_action_set_sensitive(GTK_ACTION (o),enab->value);
3230 DisplayError(enab->name, 0);
3236 Enables icsEnables[] = {
3237 { "menuFile.Mail Move", False },
3238 { "menuFile.Reload CMail Message", False },
3239 { "menuMode.Machine Black", False },
3240 { "menuMode.Machine White", False },
3241 { "menuMode.Analysis Mode", False },
3242 { "menuMode.Analyze File", False },
3243 { "menuMode.Two Machines", False },
3245 { "menuHelp.Hint", False },
3246 { "menuHelp.Book", False },
3247 { "menuStep.Move Now", False },
3248 { "menuOptions.Periodic Updates", False },
3249 { "menuOptions.Hide Thinking", False },
3250 { "menuOptions.Ponder Next Move", False },
3255 Enables ncpEnables[] = {
3256 { "menuFile.Mail Move", False },
3257 { "menuFile.Reload CMail Message", False },
3258 { "menuMode.Machine White", False },
3259 { "menuMode.Machine Black", False },
3260 { "menuMode.Analysis Mode", False },
3261 { "menuMode.Analyze File", False },
3262 { "menuMode.Two Machines", False },
3263 { "menuMode.ICS Client", False },
3264 { "menuMode.ICS Input Box", False },
3265 { "Action", False },
3266 { "menuStep.Revert", False },
3267 { "menuStep.Move Now", False },
3268 { "menuStep.Retract Move", False },
3269 { "menuOptions.Auto Comment", False },
3270 { "menuOptions.Auto Flag", False },
3271 { "menuOptions.Auto Flip View", False },
3272 { "menuOptions.Auto Observe", False },
3273 { "menuOptions.Auto Raise Board", False },
3274 { "menuOptions.Get Move List", False },
3275 { "menuOptions.ICS Alarm", False },
3276 { "menuOptions.Move Sound", False },
3277 { "menuOptions.Quiet Play", False },
3278 { "menuOptions.Hide Thinking", False },
3279 { "menuOptions.Periodic Updates", False },
3280 { "menuOptions.Ponder Next Move", False },
3281 { "menuHelp.Hint", False },
3282 { "menuHelp.Book", False },
3286 Enables gnuEnables[] = {
3287 { "menuMode.ICS Client", False },
3288 { "menuMode.ICS Input Box", False },
3289 { "menuAction.Accept", False },
3290 { "menuAction.Decline", False },
3291 { "menuAction.Rematch", False },
3292 { "menuAction.Adjourn", False },
3293 { "menuAction.Stop Examining", False },
3294 { "menuAction.Stop Observing", False },
3295 { "menuStep.Revert", False },
3296 { "menuOptions.Auto Comment", False },
3297 { "menuOptions.Auto Observe", False },
3298 { "menuOptions.Auto Raise Board", False },
3299 { "menuOptions.Get Move List", False },
3300 { "menuOptions.Premove", False },
3301 { "menuOptions.Quiet Play", False },
3303 /* The next two options rely on SetCmailMode being called *after* */
3304 /* SetGNUMode so that when GNU is being used to give hints these */
3305 /* menu options are still available */
3307 { "menuFile.Mail Move", False },
3308 { "menuFile.Reload CMail Message", False },
3312 Enables cmailEnables[] = {
3314 { "menuAction.Call Flag", False },
3315 { "menuAction.Draw", True },
3316 { "menuAction.Adjourn", False },
3317 { "menuAction.Abort", False },
3318 { "menuAction.Stop Observing", False },
3319 { "menuAction.Stop Examining", False },
3320 { "menuFile.Mail Move", True },
3321 { "menuFile.Reload CMail Message", True },
3325 Enables trainingOnEnables[] = {
3326 { "menuMode.Edit Comment", False },
3327 { "menuMode.Pause", False },
3328 { "menuStep.Forward", False },
3329 { "menuStep.Backward", False },
3330 { "menuStep.Forward to End", False },
3331 { "menuStep.Back to Start", False },
3332 { "menuStep.Move Now", False },
3333 { "menuStep.Truncate Game", False },
3337 Enables trainingOffEnables[] = {
3338 { "menuMode.Edit Comment", True },
3339 { "menuMode.Pause", True },
3340 { "menuStep.Forward", True },
3341 { "menuStep.Backward", True },
3342 { "menuStep.Forward to End", True },
3343 { "menuStep.Back to Start", True },
3344 { "menuStep.Move Now", True },
3345 { "menuStep.Truncate Game", True },
3349 Enables machineThinkingEnables[] = {
3350 { "menuFile.Load Game", False },
3351 { "menuFile.Load Next Game", False },
3352 { "menuFile.Load Previous Game", False },
3353 { "menuFile.Reload Same Game", False },
3354 { "menuFile.Paste Game", False },
3355 { "menuFile.Load Position", False },
3356 { "menuFile.Load Next Position", False },
3357 { "menuFile.Load Previous Position", False },
3358 { "menuFile.Reload Same Position", False },
3359 { "menuFile.Paste Position", False },
3360 { "menuMode.Machine White", False },
3361 { "menuMode.Machine Black", False },
3362 { "menuMode.Two Machines", False },
3363 { "menuStep.Retract Move", False },
3367 Enables userThinkingEnables[] = {
3368 { "menuFile.Load Game", True },
3369 { "menuFile.Load Next Game", True },
3370 { "menuFile.Load Previous Game", True },
3371 { "menuFile.Reload Same Game", True },
3372 { "menuFile.Paste Game", True },
3373 { "menuFile.Load Position", True },
3374 { "menuFile.Load Next Position", True },
3375 { "menuFile.Load Previous Position", True },
3376 { "menuFile.Reload Same Position", True },
3377 { "menuFile.Paste Position", True },
3378 { "menuMode.Machine White", True },
3379 { "menuMode.Machine Black", True },
3380 { "menuMode.Two Machines", True },
3381 { "menuStep.Retract Move", True },
3387 SetMenuEnables(icsEnables);
3390 if (appData.zippyPlay && !appData.noChessProgram) /* [DM] icsEngineAnalyze */
3391 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Analysis Mode"), True);
3398 SetMenuEnables(ncpEnables);
3404 SetMenuEnables(gnuEnables);
3410 SetMenuEnables(cmailEnables);
3416 SetMenuEnables(trainingOnEnables);
3417 if (appData.showButtonBar) {
3418 XtSetSensitive(buttonBarWidget, False);
3424 SetTrainingModeOff()
3426 SetMenuEnables(trainingOffEnables);
3427 if (appData.showButtonBar) {
3428 XtSetSensitive(buttonBarWidget, True);
3433 SetUserThinkingEnables()
3435 if (appData.noChessProgram) return;
3436 SetMenuEnables(userThinkingEnables);
3440 SetMachineThinkingEnables()
3442 if (appData.noChessProgram) return;
3443 SetMenuEnables(machineThinkingEnables);
3445 case MachinePlaysBlack:
3446 case MachinePlaysWhite:
3447 case TwoMachinesPlay:
3448 XtSetSensitive(XtNameToWidget(menuBarWidget,
3449 ModeToWidgetName(gameMode)), True);
3456 #define Abs(n) ((n)<0 ? -(n) : (n))
3459 * Find a font that matches "pattern" that is as close as
3460 * possible to the targetPxlSize. Prefer fonts that are k
3461 * pixels smaller to fonts that are k pixels larger. The
3462 * pattern must be in the X Consortium standard format,
3463 * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".
3464 * The return value should be freed with XtFree when no
3467 char *FindFont(pattern, targetPxlSize)
3471 char **fonts, *p, *best, *scalable, *scalableTail;
3472 int i, j, nfonts, minerr, err, pxlSize;
3475 char **missing_list;
3477 char *def_string, *base_fnt_lst, strInt[3];
3479 XFontStruct **fnt_list;
3481 base_fnt_lst = calloc(1, strlen(pattern) + 3);
3482 sprintf(strInt, "%d", targetPxlSize);
3483 p = strstr(pattern, "--");
3484 strncpy(base_fnt_lst, pattern, p - pattern + 2);
3485 strcat(base_fnt_lst, strInt);
3486 strcat(base_fnt_lst, strchr(p + 2, '-'));
3488 if ((fntSet = XCreateFontSet(xDisplay,
3492 &def_string)) == NULL) {
3494 fprintf(stderr, _("Unable to create font set.\n"));
3498 nfonts = XFontsOfFontSet(fntSet, &fnt_list, &fonts);
3500 fonts = XListFonts(xDisplay, pattern, 999999, &nfonts);
3502 fprintf(stderr, _("%s: no fonts match pattern %s\n"),
3503 programName, pattern);
3511 for (i=0; i<nfonts; i++) {
3514 if (*p != '-') continue;
3516 if (*p == NULLCHAR) break;
3517 if (*p++ == '-') j++;
3519 if (j < 7) continue;
3522 scalable = fonts[i];
3525 err = pxlSize - targetPxlSize;
3526 if (Abs(err) < Abs(minerr) ||
3527 (minerr > 0 && err < 0 && -err == minerr)) {
3533 if (scalable && Abs(minerr) > appData.fontSizeTolerance) {
3534 /* If the error is too big and there is a scalable font,
3535 use the scalable font. */
3536 int headlen = scalableTail - scalable;
3537 p = (char *) XtMalloc(strlen(scalable) + 10);
3538 while (isdigit(*scalableTail)) scalableTail++;
3539 sprintf(p, "%.*s%d%s", headlen, scalable, targetPxlSize, scalableTail);
3541 p = (char *) XtMalloc(strlen(best) + 1);
3544 if (appData.debugMode) {
3545 fprintf(debugFP, _("resolved %s at pixel size %d\n to %s\n"),
3546 pattern, targetPxlSize, p);
3549 if (missing_count > 0)
3550 XFreeStringList(missing_list);
3551 XFreeFontSet(xDisplay, fntSet);
3553 XFreeFontNames(fonts);
3560 XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
3561 | GCBackground | GCFunction | GCPlaneMask;
3562 XGCValues gc_values;
3565 gc_values.plane_mask = AllPlanes;
3566 gc_values.line_width = lineGap;
3567 gc_values.line_style = LineSolid;
3568 gc_values.function = GXcopy;
3570 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3571 gc_values.background = XBlackPixel(xDisplay, xScreen);
3572 lineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3574 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3575 gc_values.background = XWhitePixel(xDisplay, xScreen);
3576 coordGC = XtGetGC(shellWidget, value_mask, &gc_values);
3577 XSetFont(xDisplay, coordGC, coordFontID);
3579 // [HGM] make font for holdings counts (white on black0
3580 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3581 gc_values.background = XBlackPixel(xDisplay, xScreen);
3582 countGC = XtGetGC(shellWidget, value_mask, &gc_values);
3583 XSetFont(xDisplay, countGC, countFontID);
3585 if (appData.monoMode) {
3586 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3587 gc_values.background = XWhitePixel(xDisplay, xScreen);
3588 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3590 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3591 gc_values.background = XBlackPixel(xDisplay, xScreen);
3592 lightSquareGC = wbPieceGC
3593 = XtGetGC(shellWidget, value_mask, &gc_values);
3595 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3596 gc_values.background = XWhitePixel(xDisplay, xScreen);
3597 darkSquareGC = bwPieceGC
3598 = XtGetGC(shellWidget, value_mask, &gc_values);
3600 if (DefaultDepth(xDisplay, xScreen) == 1) {
3601 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
3602 gc_values.function = GXcopyInverted;
3603 copyInvertedGC = XtGetGC(shellWidget, value_mask, &gc_values);
3604 gc_values.function = GXcopy;
3605 if (XBlackPixel(xDisplay, xScreen) == 1) {
3606 bwPieceGC = darkSquareGC;
3607 wbPieceGC = copyInvertedGC;
3609 bwPieceGC = copyInvertedGC;
3610 wbPieceGC = lightSquareGC;
3614 gc_values.foreground = highlightSquareColor;
3615 gc_values.background = highlightSquareColor;
3616 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3618 gc_values.foreground = premoveHighlightColor;
3619 gc_values.background = premoveHighlightColor;
3620 prelineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3622 gc_values.foreground = lightSquareColor;
3623 gc_values.background = darkSquareColor;
3624 lightSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3626 gc_values.foreground = darkSquareColor;
3627 gc_values.background = lightSquareColor;
3628 darkSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3630 gc_values.foreground = jailSquareColor;
3631 gc_values.background = jailSquareColor;
3632 jailSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3634 gc_values.foreground = whitePieceColor;
3635 gc_values.background = darkSquareColor;
3636 wdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3638 gc_values.foreground = whitePieceColor;
3639 gc_values.background = lightSquareColor;
3640 wlPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3642 gc_values.foreground = whitePieceColor;
3643 gc_values.background = jailSquareColor;
3644 wjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3646 gc_values.foreground = blackPieceColor;
3647 gc_values.background = darkSquareColor;
3648 bdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3650 gc_values.foreground = blackPieceColor;
3651 gc_values.background = lightSquareColor;
3652 blPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3654 gc_values.foreground = blackPieceColor;
3655 gc_values.background = jailSquareColor;
3656 bjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3663 WhitePawn, WhiteKnight, WhiteBishop, WhiteRook, WhiteQueen, WhiteKing,
3664 BlackPawn, BlackKnight, BlackBishop, BlackRook, BlackQueen, BlackKing,
3667 SVGpieces[WhitePawn] = load_pixbuf("svg/WhitePawn.svg");
3668 SVGpieces[WhiteKnight] = load_pixbuf("svg/WhiteKnight.svg");
3669 SVGpieces[WhiteBishop] = load_pixbuf("svg/WhiteBishop.svg");
3670 SVGpieces[WhiteRook] = load_pixbuf("svg/WhiteRook.svg");
3671 SVGpieces[WhiteQueen] = load_pixbuf("svg/WhiteQueen.svg");
3672 SVGpieces[WhiteKing] = load_pixbuf("svg/WhiteKing.svg");
3674 SVGpieces[BlackPawn] = load_pixbuf("svg/BlackPawn.svg");
3675 SVGpieces[BlackKnight] = load_pixbuf("svg/BlackKnight.svg");
3676 SVGpieces[BlackBishop] = load_pixbuf("svg/BlackBishop.svg");
3677 SVGpieces[BlackRook] = load_pixbuf("svg/BlackRook.svg");
3678 SVGpieces[BlackQueen] = load_pixbuf("svg/BlackQueen.svg");
3679 SVGpieces[BlackKing] = load_pixbuf("svg/BlackKing.svg");
3689 if (lineGap == 0) return;
3691 /* [HR] Split this into 2 loops for non-square boards. */
3693 for (i = 0; i < BOARD_HEIGHT + 1; i++) {
3694 gridSegments[i].x1 = 0;
3695 gridSegments[i].x2 =
3696 lineGap + BOARD_WIDTH * (squareSize + lineGap);
3697 gridSegments[i].y1 = gridSegments[i].y2
3698 = lineGap / 2 + (i * (squareSize + lineGap));
3701 for (j = 0; j < BOARD_WIDTH + 1; j++) {
3702 gridSegments[j + i].y1 = 0;
3703 gridSegments[j + i].y2 =
3704 lineGap + BOARD_HEIGHT * (squareSize + lineGap);
3705 gridSegments[j + i].x1 = gridSegments[j + i].x2
3706 = lineGap / 2 + (j * (squareSize + lineGap));
3710 static void MenuBarSelect(w, addr, index)
3715 XtActionProc proc = (XtActionProc) addr;
3717 (proc)(NULL, NULL, NULL, NULL);
3720 void CreateMenuBarPopup(parent, name, mb)
3730 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3733 XtSetArg(args[j], XtNleftMargin, 20); j++;
3734 XtSetArg(args[j], XtNrightMargin, 20); j++;
3736 while (mi->string != NULL) {
3737 if (strcmp(mi->string, "----") == 0) {
3738 entry = XtCreateManagedWidget(mi->string, smeLineObjectClass,
3741 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string)));
3742 entry = XtCreateManagedWidget(mi->string, smeBSBObjectClass,
3744 XtAddCallback(entry, XtNcallback,
3745 (XtCallbackProc) MenuBarSelect,
3746 (caddr_t) mi->proc);
3752 Widget CreateMenuBar(mb)
3756 Widget anchor, menuBar;
3758 char menuName[MSG_SIZ];
3761 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
3762 XtSetArg(args[j], XtNvSpace, 0); j++;
3763 XtSetArg(args[j], XtNborderWidth, 0); j++;
3764 menuBar = XtCreateWidget("menuBar", boxWidgetClass,
3765 formWidget, args, j);
3767 while (mb->name != NULL) {
3768 strcpy(menuName, "menu");
3769 strcat(menuName, mb->name);
3771 XtSetArg(args[j], XtNmenuName, XtNewString(menuName)); j++;
3774 shortName[0] = _(mb->name)[0];
3775 shortName[1] = NULLCHAR;
3776 XtSetArg(args[j], XtNlabel, XtNewString(shortName)); j++;
3779 XtSetArg(args[j], XtNlabel, XtNewString(_(mb->name))); j++;
3782 XtSetArg(args[j], XtNborderWidth, 0); j++;
3783 anchor = XtCreateManagedWidget(mb->name, menuButtonWidgetClass,
3785 CreateMenuBarPopup(menuBar, menuName, mb);
3791 Widget CreateButtonBar(mi)
3795 Widget button, buttonBar;
3799 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
3801 XtSetArg(args[j], XtNhSpace, 0); j++;
3803 XtSetArg(args[j], XtNborderWidth, 0); j++;
3804 XtSetArg(args[j], XtNvSpace, 0); j++;
3805 buttonBar = XtCreateWidget("buttonBar", boxWidgetClass,
3806 formWidget, args, j);
3808 while (mi->string != NULL) {
3811 XtSetArg(args[j], XtNinternalWidth, 2); j++;
3812 XtSetArg(args[j], XtNborderWidth, 0); j++;
3814 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string))); j++;
3815 button = XtCreateManagedWidget(mi->string, commandWidgetClass,
3816 buttonBar, args, j);
3817 XtAddCallback(button, XtNcallback,
3818 (XtCallbackProc) MenuBarSelect,
3819 (caddr_t) mi->proc);
3826 CreatePieceMenu(name, color)
3833 ChessSquare selection;
3835 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3836 boardWidget, args, 0);
3838 for (i = 0; i < PIECE_MENU_SIZE; i++) {
3839 String item = pieceMenuStrings[color][i];
3841 if (strcmp(item, "----") == 0) {
3842 entry = XtCreateManagedWidget(item, smeLineObjectClass,
3845 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
3846 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3848 selection = pieceMenuTranslation[color][i];
3849 XtAddCallback(entry, XtNcallback,
3850 (XtCallbackProc) PieceMenuSelect,
3851 (caddr_t) selection);
3852 if (selection == WhitePawn || selection == BlackPawn) {
3853 XtSetArg(args[0], XtNpopupOnEntry, entry);
3854 XtSetValues(menu, args, 1);
3867 ChessSquare selection;
3869 // whitePieceMenu = CreatePieceMenu("menuW", 0);
3870 // blackPieceMenu = CreatePieceMenu("menuB", 1);
3872 // XtRegisterGrabAction(PieceMenuPopup, True,
3873 // (unsigned)(ButtonPressMask|ButtonReleaseMask),
3874 // GrabModeAsync, GrabModeAsync);
3876 // XtSetArg(args[0], XtNlabel, _("Drop"));
3877 // dropMenu = XtCreatePopupShell("menuD", simpleMenuWidgetClass,
3878 // boardWidget, args, 1);
3879 // for (i = 0; i < DROP_MENU_SIZE; i++) {
3880 // String item = dropMenuStrings[i];
3882 // if (strcmp(item, "----") == 0) {
3883 // entry = XtCreateManagedWidget(item, smeLineObjectClass,
3884 // dropMenu, NULL, 0);
3886 // XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
3887 // entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3888 // dropMenu, args, 1);
3889 // selection = dropMenuTranslation[i];
3890 // XtAddCallback(entry, XtNcallback,
3891 // (XtCallbackProc) DropMenuSelect,
3892 // (caddr_t) selection);
3897 void SetupDropMenu()
3905 for (i=0; i<sizeof(dmEnables)/sizeof(DropMenuEnables); i++) {
3906 entry = XtNameToWidget(dropMenu, dmEnables[i].widget);
3907 p = strchr(gameMode == IcsPlayingWhite ? white_holding : black_holding,
3908 dmEnables[i].piece);
3909 XtSetSensitive(entry, p != NULL || !appData.testLegality
3910 /*!!temp:*/ || (gameInfo.variant == VariantCrazyhouse
3911 && !appData.icsActive));
3913 while (p && *p++ == dmEnables[i].piece) count++;
3914 snprintf(label, sizeof(label), "%s %d", dmEnables[i].widget, count);
3916 XtSetArg(args[j], XtNlabel, label); j++;
3917 XtSetValues(entry, args, j);
3921 void PieceMenuPopup(w, event, params, num_params)
3925 Cardinal *num_params;
3928 if (event->type != ButtonPress) return;
3929 if (errorUp) ErrorPopDown();
3933 whichMenu = params[0];
3935 case IcsPlayingWhite:
3936 case IcsPlayingBlack:
3938 case MachinePlaysWhite:
3939 case MachinePlaysBlack:
3940 if (appData.testLegality &&
3941 gameInfo.variant != VariantBughouse &&
3942 gameInfo.variant != VariantCrazyhouse) return;
3944 whichMenu = "menuD";
3950 if (((pmFromX = EventToSquare(event->xbutton.x, BOARD_WIDTH)) < 0) ||
3951 ((pmFromY = EventToSquare(event->xbutton.y, BOARD_HEIGHT)) < 0)) {
3952 pmFromX = pmFromY = -1;
3956 pmFromX = BOARD_WIDTH - 1 - pmFromX;
3958 pmFromY = BOARD_HEIGHT - 1 - pmFromY;
3960 XtPopupSpringLoaded(XtNameToWidget(boardWidget, whichMenu));
3963 static void PieceMenuSelect(w, piece, junk)
3968 if (pmFromX < 0 || pmFromY < 0) return;
3969 EditPositionMenuEvent(piece, pmFromX, pmFromY);
3972 static void DropMenuSelect(w, piece, junk)
3977 if (pmFromX < 0 || pmFromY < 0) return;
3978 DropMenuEvent(piece, pmFromX, pmFromY);
3981 void WhiteClock(w, event, prms, nprms)
3987 if (gameMode == EditPosition || gameMode == IcsExamining) {
3988 SetWhiteToPlayEvent();
3989 } else if (gameMode == IcsPlayingBlack || gameMode == MachinePlaysWhite) {
3994 void BlackClock(w, event, prms, nprms)
4000 if (gameMode == EditPosition || gameMode == IcsExamining) {
4001 SetBlackToPlayEvent();
4002 } else if (gameMode == IcsPlayingWhite || gameMode == MachinePlaysBlack) {
4009 * If the user selects on a border boundary, return -1; if off the board,
4010 * return -2. Otherwise map the event coordinate to the square.
4012 int EventToSquare(x, limit)
4020 if ((x % (squareSize + lineGap)) >= squareSize)
4022 x /= (squareSize + lineGap);
4028 static void do_flash_delay(msec)
4034 static void drawHighlight(file, rank, gc)
4040 if (lineGap == 0 || appData.blindfold) return;
4043 x = lineGap/2 + ((BOARD_WIDTH-1)-file) *
4044 (squareSize + lineGap);
4045 y = lineGap/2 + rank * (squareSize + lineGap);
4047 x = lineGap/2 + file * (squareSize + lineGap);
4048 y = lineGap/2 + ((BOARD_HEIGHT-1)-rank) *
4049 (squareSize + lineGap);
4052 XDrawRectangle(xDisplay, xBoardWindow, gc, x, y,
4053 squareSize+lineGap, squareSize+lineGap);
4056 int hi1X = -1, hi1Y = -1, hi2X = -1, hi2Y = -1;
4057 int pm1X = -1, pm1Y = -1, pm2X = -1, pm2Y = -1;
4060 SetHighlights(fromX, fromY, toX, toY)
4061 int fromX, fromY, toX, toY;
4063 if (hi1X != fromX || hi1Y != fromY) {
4064 if (hi1X >= 0 && hi1Y >= 0) {
4065 drawHighlight(hi1X, hi1Y, lineGC);
4067 if (fromX >= 0 && fromY >= 0) {
4068 drawHighlight(fromX, fromY, highlineGC);
4071 if (hi2X != toX || hi2Y != toY) {
4072 if (hi2X >= 0 && hi2Y >= 0) {
4073 drawHighlight(hi2X, hi2Y, lineGC);
4075 if (toX >= 0 && toY >= 0) {
4076 drawHighlight(toX, toY, highlineGC);
4088 SetHighlights(-1, -1, -1, -1);
4093 SetPremoveHighlights(fromX, fromY, toX, toY)
4094 int fromX, fromY, toX, toY;
4096 if (pm1X != fromX || pm1Y != fromY) {
4097 if (pm1X >= 0 && pm1Y >= 0) {
4098 drawHighlight(pm1X, pm1Y, lineGC);
4100 if (fromX >= 0 && fromY >= 0) {
4101 drawHighlight(fromX, fromY, prelineGC);
4104 if (pm2X != toX || pm2Y != toY) {
4105 if (pm2X >= 0 && pm2Y >= 0) {
4106 drawHighlight(pm2X, pm2Y, lineGC);
4108 if (toX >= 0 && toY >= 0) {
4109 drawHighlight(toX, toY, prelineGC);
4119 ClearPremoveHighlights()
4121 SetPremoveHighlights(-1, -1, -1, -1);
4124 static void BlankSquare(x, y, color, piece, dest)
4129 if (useImages && useImageSqs) {
4133 pb = SVGLightSquare;
4138 case 2: /* neutral */
4140 pb = SVGNeutralSquare;
4143 gdk_draw_pixbuf(GDK_WINDOW(GUI_Board->window),NULL,pb,0,0,x,y,-1,-1, GDK_RGB_DITHER_NORMAL, 0, 0);
4148 gc = gdk_gc_new(GDK_WINDOW(GUI_Board->window));
4152 // gc = lightSquareGC;
4156 gdk_gc_set_rgb_fg_color(gc, &tmp);
4159 // gc = darkSquareGC;
4163 gdk_gc_set_rgb_fg_color(gc, &tmp);
4165 case 2: /* neutral */
4167 // gc = jailSquareGC;
4171 gdk_gc_set_rgb_fg_color(gc, &tmp);
4174 gdk_draw_rectangle(GDK_WINDOW(GUI_Board->window),gc,1,x,y,squareSize,squareSize);
4180 I split out the routines to draw a piece so that I could
4181 make a generic flash routine.
4183 static void monoDrawPiece_1bit(piece, square_color, x, y, dest)
4185 int square_color, x, y;
4188 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
4189 switch (square_color) {
4191 case 2: /* neutral */
4193 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
4194 ? *pieceToOutline(piece)
4195 : *pieceToSolid(piece),
4196 dest, bwPieceGC, 0, 0,
4197 squareSize, squareSize, x, y);
4200 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
4201 ? *pieceToSolid(piece)
4202 : *pieceToOutline(piece),
4203 dest, wbPieceGC, 0, 0,
4204 squareSize, squareSize, x, y);
4209 static void monoDrawPiece(piece, square_color, x, y, dest)
4211 int square_color, x, y;
4214 switch (square_color) {
4216 case 2: /* neutral */
4218 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
4219 ? *pieceToOutline(piece)
4220 : *pieceToSolid(piece),
4221 dest, bwPieceGC, 0, 0,
4222 squareSize, squareSize, x, y, 1);
4225 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
4226 ? *pieceToSolid(piece)
4227 : *pieceToOutline(piece),
4228 dest, wbPieceGC, 0, 0,
4229 squareSize, squareSize, x, y, 1);
4234 static void colorDrawPiece(piece, square_color, x, y, dest)
4236 int square_color, x, y;
4239 printf("DEBUG::colorDrawPiece: piece %d square_color %d x %d y %d \n",piece,square_color,x,y);
4240 gdk_draw_pixbuf(GDK_WINDOW(GUI_Board->window),NULL,GDK_PIXBUF(SVGpieces[piece]),0,0,x,y,-1,-1, GDK_RGB_DITHER_NORMAL, 0, 0);
4243 // if(pieceToSolid(piece) == NULL) return; // [HGM] bitmaps: make it non-fatal if we have no bitmap;
4244 // switch (square_color) {
4245 // case 1: /* light */
4246 // XCopyPlane(xDisplay, *pieceToSolid(piece),
4247 // dest, (int) piece < (int) BlackPawn
4248 // ? wlPieceGC : blPieceGC, 0, 0,
4249 // squareSize, squareSize, x, y, 1);
4251 // case 0: /* dark */
4252 // XCopyPlane(xDisplay, *pieceToSolid(piece),
4253 // dest, (int) piece < (int) BlackPawn
4254 // ? wdPieceGC : bdPieceGC, 0, 0,
4255 // squareSize, squareSize, x, y, 1);
4257 // case 2: /* neutral */
4259 // XCopyPlane(xDisplay, *pieceToSolid(piece),
4260 // dest, (int) piece < (int) BlackPawn
4261 // ? wjPieceGC : bjPieceGC, 0, 0,
4262 // squareSize, squareSize, x, y, 1);
4267 static void colorDrawPieceImage(piece, square_color, x, y, dest)
4269 int square_color, x, y;
4274 switch (square_color) {
4276 case 2: /* neutral */
4278 if ((int)piece < (int) BlackPawn) {
4286 if ((int)piece < (int) BlackPawn) {
4294 XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
4295 dest, wlPieceGC, 0, 0,
4296 squareSize, squareSize, x, y);
4299 typedef void (*DrawFunc)();
4301 DrawFunc ChooseDrawFunc()
4303 printf("DEBUG::ChooseDrawFunc: appData.monoMode %d useImages %d\n",appData.monoMode,useImages);
4304 if (appData.monoMode) {
4305 if (DefaultDepth(xDisplay, xScreen) == 1) {
4306 return monoDrawPiece_1bit;
4308 return monoDrawPiece;
4312 return colorDrawPieceImage;
4314 return colorDrawPiece;
4318 /* [HR] determine square color depending on chess variant. */
4319 static int SquareColor(row, column)
4324 if (gameInfo.variant == VariantXiangqi) {
4325 if (column >= 3 && column <= 5 && row >= 0 && row <= 2) {
4327 } else if (column >= 3 && column <= 5 && row >= 7 && row <= 9) {
4329 } else if (row <= 4) {
4335 square_color = ((column + row) % 2) == 1;
4338 /* [hgm] holdings: next line makes all holdings squares light */
4339 if(column < BOARD_LEFT || column >= BOARD_RGHT) square_color = 1;
4341 return square_color;
4344 void DrawSquare(row, column, piece, do_flash)
4345 int row, column, do_flash;
4348 int square_color, x, y, direction, font_ascent, font_descent;
4351 XCharStruct overall;
4355 /* Calculate delay in milliseconds (2-delays per complete flash) */
4356 flash_delay = 500 / appData.flashRate;
4358 printf("DEBUG: linegap %d squareSize %d \n",lineGap,squareSize);
4360 /* calculate x and y coordinates from row and column */
4362 x = lineGap + ((BOARD_WIDTH-1)-column) *
4363 (squareSize + lineGap);
4364 y = lineGap + row * (squareSize + lineGap);
4366 x = lineGap + column * (squareSize + lineGap);
4367 y = lineGap + ((BOARD_HEIGHT-1)-row) *
4368 (squareSize + lineGap);
4371 square_color = SquareColor(row, column);
4373 printf("DEBUG::DrawSquare: row %d column %d piece %d do_flash %d square_color %d x %d y %d\n",row,column,piece,do_flash,square_color,x,y);
4375 if ( // [HGM] holdings: blank out area between board and holdings
4376 column == BOARD_LEFT-1 || column == BOARD_RGHT
4377 || (column == BOARD_LEFT-2 && row < BOARD_HEIGHT-gameInfo.holdingsSize)
4378 || (column == BOARD_RGHT+1 && row >= gameInfo.holdingsSize) ) {
4379 BlankSquare(x, y, 2, EmptySquare, xBoardWindow);
4381 // [HGM] print piece counts next to holdings
4382 string[1] = NULLCHAR;
4383 if (column == (flipView ? BOARD_LEFT-1 : BOARD_RGHT) && piece > 1 ) {
4384 string[0] = '0' + piece;
4385 XTextExtents(countFontStruct, string, 1, &direction,
4386 &font_ascent, &font_descent, &overall);
4387 if (appData.monoMode) {
4388 XDrawImageString(xDisplay, xBoardWindow, countGC,
4389 x + squareSize - overall.width - 2,
4390 y + font_ascent + 1, string, 1);
4392 XDrawString(xDisplay, xBoardWindow, countGC,
4393 x + squareSize - overall.width - 2,
4394 y + font_ascent + 1, string, 1);
4397 if (column == (flipView ? BOARD_RGHT : BOARD_LEFT-1) && piece > 1) {
4398 string[0] = '0' + piece;
4399 XTextExtents(countFontStruct, string, 1, &direction,
4400 &font_ascent, &font_descent, &overall);
4401 if (appData.monoMode) {
4402 XDrawImageString(xDisplay, xBoardWindow, countGC,
4403 x + 2, y + font_ascent + 1, string, 1);
4405 XDrawString(xDisplay, xBoardWindow, countGC,
4406 x + 2, y + font_ascent + 1, string, 1);
4410 if (piece == EmptySquare || appData.blindfold) {
4411 BlankSquare(x, y, square_color, piece, xBoardWindow);
4413 drawfunc = ChooseDrawFunc();
4414 if (do_flash && appData.flashCount > 0) {
4415 for (i=0; i<appData.flashCount; ++i) {
4417 drawfunc(piece, square_color, x, y, xBoardWindow);
4418 XSync(xDisplay, False);
4419 do_flash_delay(flash_delay);
4421 BlankSquare(x, y, square_color, piece, xBoardWindow);
4422 XSync(xDisplay, False);
4423 do_flash_delay(flash_delay);
4426 drawfunc(piece, square_color, x, y, xBoardWindow);
4430 string[1] = NULLCHAR;
4431 if (appData.showCoords && row == (flipView ? BOARD_HEIGHT-1 : 0)
4432 && column >= BOARD_LEFT && column < BOARD_RGHT) {
4433 string[0] = 'a' + column - BOARD_LEFT;
4434 XTextExtents(coordFontStruct, string, 1, &direction,
4435 &font_ascent, &font_descent, &overall);
4436 if (appData.monoMode) {
4437 XDrawImageString(xDisplay, xBoardWindow, coordGC,
4438 x + squareSize - overall.width - 2,
4439 y + squareSize - font_descent - 1, string, 1);
4441 XDrawString(xDisplay, xBoardWindow, coordGC,
4442 x + squareSize - overall.width - 2,
4443 y + squareSize - font_descent - 1, string, 1);
4446 if (appData.showCoords && column == (flipView ? BOARD_RGHT-1 : BOARD_LEFT)) {
4447 string[0] = ONE + row;
4448 XTextExtents(coordFontStruct, string, 1, &direction,
4449 &font_ascent, &font_descent, &overall);
4450 if (appData.monoMode) {
4451 XDrawImageString(xDisplay, xBoardWindow, coordGC,
4452 x + 2, y + font_ascent + 1, string, 1);
4454 XDrawString(xDisplay, xBoardWindow, coordGC,
4455 x + 2, y + font_ascent + 1, string, 1);
4461 /* Returns 1 if there are "too many" differences between b1 and b2
4462 (i.e. more than 1 move was made) */
4463 static int too_many_diffs(b1, b2)
4469 for (i=0; i<BOARD_HEIGHT; ++i) {
4470 for (j=0; j<BOARD_WIDTH; ++j) {
4471 if (b1[i][j] != b2[i][j]) {
4472 if (++c > 4) /* Castling causes 4 diffs */
4481 /* Matrix describing castling maneuvers */
4482 /* Row, ColRookFrom, ColKingFrom, ColRookTo, ColKingTo */
4483 static int castling_matrix[4][5] = {
4484 { 0, 0, 4, 3, 2 }, /* 0-0-0, white */
4485 { 0, 7, 4, 5, 6 }, /* 0-0, white */
4486 { 7, 0, 4, 3, 2 }, /* 0-0-0, black */
4487 { 7, 7, 4, 5, 6 } /* 0-0, black */
4490 /* Checks whether castling occurred. If it did, *rrow and *rcol
4491 are set to the destination (row,col) of the rook that moved.
4493 Returns 1 if castling occurred, 0 if not.
4495 Note: Only handles a max of 1 castling move, so be sure
4496 to call too_many_diffs() first.
4498 static int check_castle_draw(newb, oldb, rrow, rcol)
4505 /* For each type of castling... */
4506 for (i=0; i<4; ++i) {
4507 r = castling_matrix[i];
4509 /* Check the 4 squares involved in the castling move */
4511 for (j=1; j<=4; ++j) {
4512 if (newb[r[0]][r[j]] == oldb[r[0]][r[j]]) {
4519 /* All 4 changed, so it must be a castling move */
4528 static int damage[BOARD_SIZE][BOARD_SIZE];
4531 * event handler for redrawing the board
4533 void DrawPosition( repaint, board)
4534 /*Boolean*/int repaint;
4538 static int lastFlipView = 0;
4539 static int lastBoardValid = 0;
4540 static Board lastBoard;
4544 printf ("DEBUG::DrawPosition: start\n");
4547 if (board == NULL) {
4548 if (!lastBoardValid) return;
4551 if (!lastBoardValid || lastFlipView != flipView) {
4552 XtSetArg(args[0], XtNleftBitmap, (flipView ? xMarkPixmap : None));
4553 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flip View"),
4558 * It would be simpler to clear the window with XClearWindow()
4559 * but this causes a very distracting flicker.
4562 printf ("DEBUG::DrawPosition: in draw position 0.1\n");
4563 printf("DEBUG::DrawPosition: squareSize %d\n",squareSize);
4566 if (!repaint && lastBoardValid && lastFlipView == flipView) {
4568 printf ("DEBUG::DrawPosition: in draw position 0.1a\n");
4569 /* If too much changes (begin observing new game, etc.), don't
4571 do_flash = too_many_diffs(board, lastBoard) ? 0 : 1;
4573 /* Special check for castling so we don't flash both the king
4574 and the rook (just flash the king). */
4576 if (check_castle_draw(board, lastBoard, &rrow, &rcol)) {
4577 /* Draw rook with NO flashing. King will be drawn flashing later */
4578 DrawSquare(rrow, rcol, board[rrow][rcol], 0);
4579 lastBoard[rrow][rcol] = board[rrow][rcol];
4583 /* First pass -- Draw (newly) empty squares and repair damage.
4584 This prevents you from having a piece show up twice while it
4585 is flashing on its new square */
4586 for (i = 0; i < BOARD_HEIGHT; i++)
4587 for (j = 0; j < BOARD_WIDTH; j++)
4588 if ((board[i][j] != lastBoard[i][j] && board[i][j] == EmptySquare)
4590 DrawSquare(i, j, board[i][j], 0);
4591 damage[i][j] = False;
4594 /* Second pass -- Draw piece(s) in new position and flash them */
4595 for (i = 0; i < BOARD_HEIGHT; i++)
4596 for (j = 0; j < BOARD_WIDTH; j++)
4597 if (board[i][j] != lastBoard[i][j]) {
4598 DrawSquare(i, j, board[i][j], do_flash);
4601 printf("DEBUG::DrawPosition: in else linegap %d squareSize %d\n",lineGap,squareSize);
4604 /* todo move GC to setupgc */
4605 GdkGC *gtklineGC=NULL;
4608 gtklineGC = gdk_gc_new(GDK_WINDOW(GUI_Board->window));
4613 gdk_gc_set_rgb_fg_color(gtklineGC, &tmp);
4618 gdk_gc_set_rgb_bg_color(gtklineGC, &tmp);
4620 gdk_draw_segments(GUI_Board->window,gtklineGC,
4621 gridSegments, BOARD_HEIGHT + BOARD_WIDTH + 2 );
4625 for (i = 0; i < BOARD_HEIGHT; i++)
4626 for (j = 0; j < BOARD_WIDTH; j++) {
4627 printf("DEBUG::DrawPosition: squareSize %d\n",squareSize);
4628 DrawSquare(i, j, board[i][j], 0);
4629 damage[i][j] = False;
4633 CopyBoard(lastBoard, board);
4635 lastFlipView = flipView;
4637 /* Draw highlights */
4638 if (pm1X >= 0 && pm1Y >= 0) {
4639 drawHighlight(pm1X, pm1Y, prelineGC);
4641 if (pm2X >= 0 && pm2Y >= 0) {
4642 drawHighlight(pm2X, pm2Y, prelineGC);
4644 if (hi1X >= 0 && hi1Y >= 0) {
4645 drawHighlight(hi1X, hi1Y, highlineGC);
4647 if (hi2X >= 0 && hi2Y >= 0) {
4648 drawHighlight(hi2X, hi2Y, highlineGC);
4651 /* If piece being dragged around board, must redraw that too */
4654 // XSync(xDisplay, False);
4659 * event handler for redrawing the board
4661 void DrawPositionProc(w, event, prms, nprms)
4667 DrawPosition(True, NULL);
4672 * event handler for parsing user moves
4674 // [HGM] This routine will need quite some reworking. Although the backend still supports the old
4675 // way of doing things, by calling UserMoveEvent() to test the legality of the move and then perform
4676 // it at the end, and doing all kind of preliminary tests here (e.g. to weed out self-captures), it
4677 // should be made to use the new way, of calling UserMoveTest early to determine the legality of the
4678 // move, (which will weed out the illegal selfcaptures and moves into the holdings, and flag promotions),
4679 // and at the end FinishMove() to perform the move after optional promotion popups.
4680 // For now I patched it to allow self-capture with King, and suppress clicks between board and holdings.
4681 void HandleUserMove(w, event, prms, nprms)
4688 Boolean saveAnimate;
4689 static int second = 0;
4691 if (w != boardWidget || errorExitStatus != -1) return;
4693 if (event->type == ButtonPress) ErrorPopDown();
4696 if (event->type == ButtonPress) {
4697 XtPopdown(promotionShell);
4698 XtDestroyWidget(promotionShell);
4699 promotionUp = False;
4707 x = EventToSquare(event->xbutton.x, BOARD_WIDTH);
4708 y = EventToSquare(event->xbutton.y, BOARD_HEIGHT);
4709 if (!flipView && y >= 0) {
4710 y = BOARD_HEIGHT - 1 - y;
4712 if (flipView && x >= 0) {
4713 x = BOARD_WIDTH - 1 - x;
4716 /* [HGM] holdings: next 5 lines: ignore all clicks between board and holdings */
4717 if(event->type == ButtonPress
4718 && ( x == BOARD_LEFT-1 || x == BOARD_RGHT
4719 || x == BOARD_LEFT-2 && y < BOARD_HEIGHT-gameInfo.holdingsSize
4720 || x == BOARD_RGHT+1 && y >= gameInfo.holdingsSize) )
4724 if (event->type == ButtonPress) {
4726 if (OKToStartUserMove(x, y)) {
4730 DragPieceBegin(event->xbutton.x, event->xbutton.y);
4731 if (appData.highlightDragging) {
4732 SetHighlights(x, y, -1, -1);
4740 if (event->type == ButtonPress && gameMode != EditPosition &&
4745 /* Check if clicking again on the same color piece */
4746 fromP = boards[currentMove][fromY][fromX];
4747 toP = boards[currentMove][y][x];
4748 if ((WhitePawn <= fromP && fromP < WhiteKing && // [HGM] this test should go, as UserMoveTest now does it.
4749 WhitePawn <= toP && toP <= WhiteKing) || // For now I made it less critical by exempting King
4750 (BlackPawn <= fromP && fromP < BlackKing && // moves, to not interfere with FRC castlings.
4751 BlackPawn <= toP && toP <= BlackKing)) {
4752 /* Clicked again on same color piece -- changed his mind */
4753 second = (x == fromX && y == fromY);
4754 if (appData.highlightDragging) {
4755 SetHighlights(x, y, -1, -1);
4759 if (OKToStartUserMove(x, y)) {
4762 DragPieceBegin(event->xbutton.x, event->xbutton.y);
4768 if (event->type == ButtonRelease && x == fromX && y == fromY) {
4769 DragPieceEnd(event->xbutton.x, event->xbutton.y);
4770 if (appData.animateDragging) {
4771 /* Undo animation damage if any */
4772 DrawPosition(FALSE, NULL);
4775 /* Second up/down in same square; just abort move */
4780 ClearPremoveHighlights();
4782 /* First upclick in same square; start click-click mode */
4783 SetHighlights(x, y, -1, -1);
4788 /* Completed move */
4791 saveAnimate = appData.animate;
4792 if (event->type == ButtonPress) {
4793 /* Finish clickclick move */
4794 if (appData.animate || appData.highlightLastMove) {
4795 SetHighlights(fromX, fromY, toX, toY);
4800 /* Finish drag move */
4801 if (appData.highlightLastMove) {
4802 SetHighlights(fromX, fromY, toX, toY);
4806 DragPieceEnd(event->xbutton.x, event->xbutton.y);
4807 /* Don't animate move and drag both */
4808 appData.animate = FALSE;
4810 if (IsPromotion(fromX, fromY, toX, toY)) {
4811 if (appData.alwaysPromoteToQueen) {
4812 UserMoveEvent(fromX, fromY, toX, toY, 'q');
4813 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
4814 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
4817 SetHighlights(fromX, fromY, toX, toY);
4821 UserMoveEvent(fromX, fromY, toX, toY, NULLCHAR);
4822 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
4823 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
4826 appData.animate = saveAnimate;
4827 if (appData.animate || appData.animateDragging) {
4828 /* Undo animation damage if needed */
4829 DrawPosition(FALSE, NULL);
4833 void AnimateUserMove (Widget w, XEvent * event,
4834 String * params, Cardinal * nParams)
4836 DragPieceMove(event->xmotion.x, event->xmotion.y);
4839 Widget CommentCreate(name, text, mutable, callback, lines)
4841 int /*Boolean*/ mutable;
4842 XtCallbackProc callback;
4846 Widget shell, layout, form, edit, b_ok, b_cancel, b_clear, b_close, b_edit;
4851 XtSetArg(args[j], XtNwidth, &bw_width); j++;
4852 XtGetValues(boardWidget, args, j);
4855 XtSetArg(args[j], XtNresizable, True); j++;
4858 XtCreatePopupShell(name, topLevelShellWidgetClass,
4859 shellWidget, args, j);
4862 XtCreatePopupShell(name, transientShellWidgetClass,
4863 shellWidget, args, j);
4866 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
4867 layoutArgs, XtNumber(layoutArgs));
4869 XtCreateManagedWidget("form", formWidgetClass, layout,
4870 formArgs, XtNumber(formArgs));
4874 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
4875 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
4877 XtSetArg(args[j], XtNstring, text); j++;
4878 XtSetArg(args[j], XtNtop, XtChainTop); j++;
4879 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4880 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4881 XtSetArg(args[j], XtNright, XtChainRight); j++;
4882 XtSetArg(args[j], XtNresizable, True); j++;
4883 XtSetArg(args[j], XtNwidth, bw_width); j++; /*force wider than buttons*/
4885 XtSetArg(args[j], XtNscrollVertical, XawtextScrollWhenNeeded); j++;
4887 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
4888 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
4890 XtSetArg(args[j], XtNautoFill, True); j++;
4891 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
4893 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
4897 XtSetArg(args[j], XtNfromVert, edit); j++;
4898 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4899 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4900 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4901 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4903 XtCreateManagedWidget(_("ok"), commandWidgetClass, form, args, j);
4904 XtAddCallback(b_ok, XtNcallback, callback, (XtPointer) 0);
4907 XtSetArg(args[j], XtNfromVert, edit); j++;
4908 XtSetArg(args[j], XtNfromHoriz, b_ok); j++;
4909 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4910 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4911 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4912 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4914 XtCreateManagedWidget(_("cancel"), commandWidgetClass, form, args, j);
4915 XtAddCallback(b_cancel, XtNcallback, callback, (XtPointer) 0);
4918 XtSetArg(args[j], XtNfromVert, edit); j++;
4919 XtSetArg(args[j], XtNfromHoriz, b_cancel); j++;
4920 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4921 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4922 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4923 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4925 XtCreateManagedWidget(_("clear"), commandWidgetClass, form, args, j);
4926 XtAddCallback(b_clear, XtNcallback, callback, (XtPointer) 0);
4929 XtSetArg(args[j], XtNfromVert, edit); j++;
4930 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4931 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4932 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4933 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4935 XtCreateManagedWidget(_("close"), commandWidgetClass, form, args, j);
4936 XtAddCallback(b_close, XtNcallback, callback, (XtPointer) 0);
4939 XtSetArg(args[j], XtNfromVert, edit); j++;
4940 XtSetArg(args[j], XtNfromHoriz, b_close); j++;
4941 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4942 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4943 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4944 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4946 XtCreateManagedWidget(_("edit"), commandWidgetClass, form, args, j);
4947 XtAddCallback(b_edit, XtNcallback, callback, (XtPointer) 0);
4950 XtRealizeWidget(shell);
4952 if (commentX == -1) {
4955 Dimension pw_height;
4956 Dimension ew_height;
4959 XtSetArg(args[j], XtNheight, &ew_height); j++;
4960 XtGetValues(edit, args, j);
4963 XtSetArg(args[j], XtNheight, &pw_height); j++;
4964 XtGetValues(shell, args, j);
4965 commentH = pw_height + (lines - 1) * ew_height;
4966 commentW = bw_width - 16;
4968 XSync(xDisplay, False);
4970 /* This code seems to tickle an X bug if it is executed too soon
4971 after xboard starts up. The coordinates get transformed as if
4972 the main window was positioned at (0, 0).
4974 XtTranslateCoords(shellWidget,
4975 (bw_width - commentW) / 2, 0 - commentH / 2,
4976 &commentX, &commentY);
4978 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
4979 RootWindowOfScreen(XtScreen(shellWidget)),
4980 (bw_width - commentW) / 2, 0 - commentH / 2,
4985 if (commentY < 0) commentY = 0; /*avoid positioning top offscreen*/
4988 XtSetArg(args[j], XtNheight, commentH); j++;
4989 XtSetArg(args[j], XtNwidth, commentW); j++;
4990 XtSetArg(args[j], XtNx, commentX); j++;
4991 XtSetArg(args[j], XtNy, commentY); j++;
4992 XtSetValues(shell, args, j);
4993 XtSetKeyboardFocus(shell, edit);
4998 /* Used for analysis window and ICS input window */
4999 Widget MiscCreate(name, text, mutable, callback, lines)
5001 int /*Boolean*/ mutable;
5002 XtCallbackProc callback;
5006 Widget shell, layout, form, edit;
5008 Dimension bw_width, pw_height, ew_height, w, h;
5014 XtSetArg(args[j], XtNresizable, True); j++;
5017 XtCreatePopupShell(name, topLevelShellWidgetClass,
5018 shellWidget, args, j);
5021 XtCreatePopupShell(name, transientShellWidgetClass,
5022 shellWidget, args, j);
5025 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
5026 layoutArgs, XtNumber(layoutArgs));
5028 XtCreateManagedWidget("form", formWidgetClass, layout,
5029 formArgs, XtNumber(formArgs));
5033 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
5034 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
5036 XtSetArg(args[j], XtNstring, text); j++;
5037 XtSetArg(args[j], XtNtop, XtChainTop); j++;
5038 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5039 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5040 XtSetArg(args[j], XtNright, XtChainRight); j++;
5041 XtSetArg(args[j], XtNresizable, True); j++;
5043 XtSetArg(args[j], XtNscrollVertical, XawtextScrollWhenNeeded); j++;
5045 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
5046 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
5048 XtSetArg(args[j], XtNautoFill, True); j++;
5049 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
5051 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
5053 XtRealizeWidget(shell);
5056 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5057 XtGetValues(boardWidget, args, j);
5060 XtSetArg(args[j], XtNheight, &ew_height); j++;
5061 XtGetValues(edit, args, j);
5064 XtSetArg(args[j], XtNheight, &pw_height); j++;
5065 XtGetValues(shell, args, j);
5066 h = pw_height + (lines - 1) * ew_height;
5069 XSync(xDisplay, False);
5071 /* This code seems to tickle an X bug if it is executed too soon
5072 after xboard starts up. The coordinates get transformed as if
5073 the main window was positioned at (0, 0).
5075 XtTranslateCoords(shellWidget, (bw_width - w) / 2, 0 - h / 2, &x, &y);
5077 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
5078 RootWindowOfScreen(XtScreen(shellWidget)),
5079 (bw_width - w) / 2, 0 - h / 2, &xx, &yy, &junk);
5083 if (y < 0) y = 0; /*avoid positioning top offscreen*/
5086 XtSetArg(args[j], XtNheight, h); j++;
5087 XtSetArg(args[j], XtNwidth, w); j++;
5088 XtSetArg(args[j], XtNx, x); j++;
5089 XtSetArg(args[j], XtNy, y); j++;
5090 XtSetValues(shell, args, j);
5096 static int savedIndex; /* gross that this is global */
5098 void EditCommentPopUp(index, title, text)
5107 if (text == NULL) text = "";
5109 if (editShell == NULL) {
5111 CommentCreate(title, text, True, EditCommentCallback, 4);
5112 XtRealizeWidget(editShell);
5113 CatchDeleteWindow(editShell, "EditCommentPopDown");
5115 edit = XtNameToWidget(editShell, "*form.text");
5117 XtSetArg(args[j], XtNstring, text); j++;
5118 XtSetValues(edit, args, j);
5120 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5121 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5122 XtSetValues(editShell, args, j);
5125 XtPopup(editShell, XtGrabNone);
5129 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
5130 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
5134 void EditCommentCallback(w, client_data, call_data)
5136 XtPointer client_data, call_data;
5144 XtSetArg(args[j], XtNlabel, &name); j++;
5145 XtGetValues(w, args, j);
5147 if (strcmp(name, _("ok")) == 0) {
5148 edit = XtNameToWidget(editShell, "*form.text");
5150 XtSetArg(args[j], XtNstring, &val); j++;
5151 XtGetValues(edit, args, j);
5152 ReplaceComment(savedIndex, val);
5153 EditCommentPopDown();
5154 } else if (strcmp(name, _("cancel")) == 0) {
5155 EditCommentPopDown();
5156 } else if (strcmp(name, _("clear")) == 0) {
5157 edit = XtNameToWidget(editShell, "*form.text");
5158 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
5159 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
5163 void EditCommentPopDown()
5168 if (!editUp) return;
5170 XtSetArg(args[j], XtNx, &commentX); j++;
5171 XtSetArg(args[j], XtNy, &commentY); j++;
5172 XtSetArg(args[j], XtNheight, &commentH); j++;
5173 XtSetArg(args[j], XtNwidth, &commentW); j++;
5174 XtGetValues(editShell, args, j);
5175 XtPopdown(editShell);
5178 XtSetArg(args[j], XtNleftBitmap, None); j++;
5179 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
5183 void ICSInputBoxPopUp()
5188 char *title = _("ICS Input");
5191 if (ICSInputShell == NULL) {
5192 ICSInputShell = MiscCreate(title, "", True, NULL, 1);
5193 tr = XtParseTranslationTable(ICSInputTranslations);
5194 edit = XtNameToWidget(ICSInputShell, "*form.text");
5195 XtOverrideTranslations(edit, tr);
5196 XtRealizeWidget(ICSInputShell);
5197 CatchDeleteWindow(ICSInputShell, "ICSInputBoxPopDown");
5200 edit = XtNameToWidget(ICSInputShell, "*form.text");
5202 XtSetArg(args[j], XtNstring, ""); j++;
5203 XtSetValues(edit, args, j);
5205 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5206 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5207 XtSetValues(ICSInputShell, args, j);
5210 XtPopup(ICSInputShell, XtGrabNone);
5211 XtSetKeyboardFocus(ICSInputShell, edit);
5213 ICSInputBoxUp = True;
5215 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
5216 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
5220 void ICSInputSendText()
5227 edit = XtNameToWidget(ICSInputShell, "*form.text");
5229 XtSetArg(args[j], XtNstring, &val); j++;
5230 XtGetValues(edit, args, j);
5231 SendMultiLineToICS(val);
5232 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
5233 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
5236 void ICSInputBoxPopDown()
5241 if (!ICSInputBoxUp) return;
5243 XtPopdown(ICSInputShell);
5244 ICSInputBoxUp = False;
5246 XtSetArg(args[j], XtNleftBitmap, None); j++;
5247 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
5251 void CommentPopUp(title, text)
5258 if (commentShell == NULL) {
5260 CommentCreate(title, text, False, CommentCallback, 4);
5261 XtRealizeWidget(commentShell);
5262 CatchDeleteWindow(commentShell, "CommentPopDown");
5264 edit = XtNameToWidget(commentShell, "*form.text");
5266 XtSetArg(args[j], XtNstring, text); j++;
5267 XtSetValues(edit, args, j);
5269 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5270 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5271 XtSetValues(commentShell, args, j);
5274 XtPopup(commentShell, XtGrabNone);
5275 XSync(xDisplay, False);
5280 void AnalysisPopUp(title, text)
5287 if (analysisShell == NULL) {
5288 analysisShell = MiscCreate(title, text, False, NULL, 4);
5289 XtRealizeWidget(analysisShell);
5290 CatchDeleteWindow(analysisShell, "AnalysisPopDown");
5293 edit = XtNameToWidget(analysisShell, "*form.text");
5295 XtSetArg(args[j], XtNstring, text); j++;
5296 XtSetValues(edit, args, j);
5298 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5299 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5300 XtSetValues(analysisShell, args, j);
5304 XtPopup(analysisShell, XtGrabNone);
5306 XSync(xDisplay, False);
5311 void CommentCallback(w, client_data, call_data)
5313 XtPointer client_data, call_data;
5320 XtSetArg(args[j], XtNlabel, &name); j++;
5321 XtGetValues(w, args, j);
5323 if (strcmp(name, _("close")) == 0) {
5325 } else if (strcmp(name, _("edit")) == 0) {
5332 void CommentPopDown()
5337 if (!commentUp) return;
5339 XtSetArg(args[j], XtNx, &commentX); j++;
5340 XtSetArg(args[j], XtNy, &commentY); j++;
5341 XtSetArg(args[j], XtNwidth, &commentW); j++;
5342 XtSetArg(args[j], XtNheight, &commentH); j++;
5343 XtGetValues(commentShell, args, j);
5344 XtPopdown(commentShell);
5345 XSync(xDisplay, False);
5349 void AnalysisPopDown()
5351 if (!analysisUp) return;
5352 XtPopdown(analysisShell);
5353 XSync(xDisplay, False);
5355 if (appData.icsEngineAnalyze) ExitAnalyzeMode(); /* [DM] icsEngineAnalyze */
5359 void FileNamePopUp(label, def, proc, openMode)
5366 Widget popup, layout, dialog, edit;
5372 fileProc = proc; /* I can't see a way not */
5373 fileOpenMode = openMode; /* to use globals here */
5376 XtSetArg(args[i], XtNresizable, True); i++;
5377 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
5378 XtSetArg(args[i], XtNtitle, XtNewString(_("File name prompt"))); i++;
5379 fileNameShell = popup =
5380 XtCreatePopupShell("File name prompt", transientShellWidgetClass,
5381 shellWidget, args, i);
5384 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
5385 layoutArgs, XtNumber(layoutArgs));
5388 XtSetArg(args[i], XtNlabel, label); i++;
5389 XtSetArg(args[i], XtNvalue, def); i++;
5390 XtSetArg(args[i], XtNborderWidth, 0); i++;
5391 dialog = XtCreateManagedWidget("fileName", dialogWidgetClass,
5394 XawDialogAddButton(dialog, _("ok"), FileNameCallback, (XtPointer) dialog);
5395 XawDialogAddButton(dialog, _("cancel"), FileNameCallback,
5396 (XtPointer) dialog);
5398 XtRealizeWidget(popup);
5399 CatchDeleteWindow(popup, "FileNamePopDown");
5401 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
5402 &x, &y, &win_x, &win_y, &mask);
5404 XtSetArg(args[0], XtNx, x - 10);
5405 XtSetArg(args[1], XtNy, y - 30);
5406 XtSetValues(popup, args, 2);
5408 XtPopup(popup, XtGrabExclusive);
5411 edit = XtNameToWidget(dialog, "*value");
5412 XtSetKeyboardFocus(popup, edit);
5415 void FileNamePopDown()
5417 if (!filenameUp) return;
5418 XtPopdown(fileNameShell);
5419 XtDestroyWidget(fileNameShell);
5424 void FileNameCallback(w, client_data, call_data)
5426 XtPointer client_data, call_data;
5431 XtSetArg(args[0], XtNlabel, &name);
5432 XtGetValues(w, args, 1);
5434 if (strcmp(name, _("cancel")) == 0) {
5439 FileNameAction(w, NULL, NULL, NULL);
5442 void FileNameAction(w, event, prms, nprms)
5454 name = XawDialogGetValueString(w = XtParent(w));
5456 if ((name != NULL) && (*name != NULLCHAR)) {
5458 XtPopdown(w = XtParent(XtParent(w)));
5462 p = strrchr(buf, ' ');
5469 fullname = ExpandPathName(buf);
5471 ErrorPopUp(_("Error"), _("Can't open file"), FALSE);
5474 f = fopen(fullname, fileOpenMode);
5476 DisplayError(_("Failed to open file"), errno);
5478 (void) (*fileProc)(f, index, buf);
5485 XtPopdown(w = XtParent(XtParent(w)));
5491 void PromotionPopUp()
5494 Widget dialog, layout;
5496 Dimension bw_width, pw_width;
5500 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5501 XtGetValues(boardWidget, args, j);
5504 XtSetArg(args[j], XtNresizable, True); j++;
5505 XtSetArg(args[j], XtNtitle, XtNewString(_("Promotion"))); j++;
5507 XtCreatePopupShell("Promotion", transientShellWidgetClass,
5508 shellWidget, args, j);
5510 XtCreateManagedWidget(layoutName, formWidgetClass, promotionShell,
5511 layoutArgs, XtNumber(layoutArgs));
5514 XtSetArg(args[j], XtNlabel, _("Promote to what?")); j++;
5515 XtSetArg(args[j], XtNborderWidth, 0); j++;
5516 dialog = XtCreateManagedWidget("promotion", dialogWidgetClass,
5519 if(gameInfo.variant != VariantShogi) {
5520 XawDialogAddButton(dialog, _("Queen"), PromotionCallback,
5521 (XtPointer) dialog);
5522 XawDialogAddButton(dialog, _("Rook"), PromotionCallback,
5523 (XtPointer) dialog);
5524 XawDialogAddButton(dialog, _("Bishop"), PromotionCallback,
5525 (XtPointer) dialog);
5526 XawDialogAddButton(dialog, _("Knight"), PromotionCallback,
5527 (XtPointer) dialog);
5528 if (!appData.testLegality || gameInfo.variant == VariantSuicide ||
5529 gameInfo.variant == VariantGiveaway) {
5530 XawDialogAddButton(dialog, _("King"), PromotionCallback,
5531 (XtPointer) dialog);
5533 if(gameInfo.variant == VariantCapablanca ||
5534 gameInfo.variant == VariantGothic ||
5535 gameInfo.variant == VariantCapaRandom) {
5536 XawDialogAddButton(dialog, _("Archbishop"), PromotionCallback,
5537 (XtPointer) dialog);
5538 XawDialogAddButton(dialog, _("Chancellor"), PromotionCallback,
5539 (XtPointer) dialog);
5541 } else // [HGM] shogi
5543 XawDialogAddButton(dialog, _("Promote"), PromotionCallback,
5544 (XtPointer) dialog);
5545 XawDialogAddButton(dialog, _("Defer"), PromotionCallback,
5546 (XtPointer) dialog);
5548 XawDialogAddButton(dialog, _("cancel"), PromotionCallback,
5549 (XtPointer) dialog);
5551 XtRealizeWidget(promotionShell);
5552 CatchDeleteWindow(promotionShell, "PromotionPopDown");
5555 XtSetArg(args[j], XtNwidth, &pw_width); j++;
5556 XtGetValues(promotionShell, args, j);
5558 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
5559 lineGap + squareSize/3 +
5560 ((toY == BOARD_HEIGHT-1) ^ (flipView) ?
5561 0 : 6*(squareSize + lineGap)), &x, &y);
5564 XtSetArg(args[j], XtNx, x); j++;
5565 XtSetArg(args[j], XtNy, y); j++;
5566 XtSetValues(promotionShell, args, j);
5568 XtPopup(promotionShell, XtGrabNone);
5573 void PromotionPopDown()
5575 if (!promotionUp) return;
5576 XtPopdown(promotionShell);
5577 XtDestroyWidget(promotionShell);
5578 promotionUp = False;
5581 void PromotionCallback(w, client_data, call_data)
5583 XtPointer client_data, call_data;
5589 XtSetArg(args[0], XtNlabel, &name);
5590 XtGetValues(w, args, 1);
5594 if (fromX == -1) return;
5596 if (strcmp(name, _("cancel")) == 0) {
5600 } else if (strcmp(name, _("Knight")) == 0) {
5602 } else if (strcmp(name, _("Promote")) == 0) {
5604 } else if (strcmp(name, _("Defer")) == 0) {
5607 promoChar = ToLower(name[0]);
5610 UserMoveEvent(fromX, fromY, toX, toY, promoChar);
5612 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
5613 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
5618 void ErrorCallback(w, client_data, call_data)
5620 XtPointer client_data, call_data;
5623 XtPopdown(w = XtParent(XtParent(XtParent(w))));
5625 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
5631 if (!errorUp) return;
5633 XtPopdown(errorShell);
5634 XtDestroyWidget(errorShell);
5635 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
5638 void ErrorPopUp(title, label, modal)
5639 char *title, *label;
5644 printf ("DEBUG: error %s %s\n\n",title,label);
5646 dialog = gtk_message_dialog_new(GTK_WINDOW(GUI_Window),
5647 GTK_DIALOG_DESTROY_WITH_PARENT,
5652 gtk_window_set_title(GTK_WINDOW(dialog),(gchar *) title);
5655 gtk_dialog_run(GTK_DIALOG(dialog));
5656 gtk_widget_destroy(GTK_WIDGET(dialog));
5660 g_signal_connect_swapped (dialog, "response",
5661 G_CALLBACK (ErrorPopDownProc),
5664 gtk_widget_show(GTK_WIDGET(dialog));
5668 /* Disable all user input other than deleting the window */
5669 static int frozen = 0;
5673 /* Grab by a widget that doesn't accept input */
5674 // XtAddGrab(messageWidget, TRUE, FALSE);
5678 /* Undo a FreezeUI */
5681 if (!frozen) return;
5682 XtRemoveGrab(messageWidget);
5686 char *ModeToWidgetName(mode)
5690 case BeginningOfGame:
5691 if (appData.icsActive)
5692 return "menuMode.ICS Client";
5693 else if (appData.noChessProgram ||
5694 *appData.cmailGameName != NULLCHAR)
5695 return "menuMode.Edit Game";
5697 return "menuMode.Machine Black";
5698 case MachinePlaysBlack:
5699 return "menuMode.Machine Black";
5700 case MachinePlaysWhite:
5701 return "menuMode.Machine White";
5703 return "menuMode.Analysis Mode";
5705 return "menuMode.Analyze File";
5706 case TwoMachinesPlay:
5707 return "menuMode.Two Machines";
5709 return "menuMode.Edit Game";
5710 case PlayFromGameFile:
5711 return "menuFile.Load Game";
5713 return "menuMode.Edit Position";
5715 return "menuMode.Training";
5716 case IcsPlayingWhite:
5717 case IcsPlayingBlack:
5721 return "menuMode.ICS Client";
5728 void ModeHighlight()
5730 static int oldPausing = FALSE;
5731 static GameMode oldmode = (GameMode) -1;
5734 // todo this toggling of the pause button doesn't seem to work?
5735 // e.g. select pause from buttonbar doesn't activate menumode.pause
5737 // fprintf(stderr,"DEBUG: oldmode %d newmode %d oldpause %d newpause %d\n",oldmode,gameMode,oldPausing,pausing);
5740 // if (!boardWidget || !XtIsRealized(boardWidget)) return;
5742 if (pausing != oldPausing) {
5743 oldPausing = pausing;
5744 gtk_button_set_relief(GTK_BUTTON (gtk_builder_get_object (builder, "menuMode.Pause")),pausing?GTK_RELIEF_NORMAL:GTK_RELIEF_NONE);
5745 /* toggle background color in showbuttonbar */
5746 if (appData.showButtonBar) {
5748 gtk_button_pressed(GTK_BUTTON (gtk_builder_get_object (builder, "buttonbar.Pause")));
5750 gtk_button_released(GTK_BUTTON (gtk_builder_get_object (builder, "buttonbar.Pause")));
5755 wname = ModeToWidgetName(oldmode);
5757 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, wname)),True);
5761 /* Maybe all the enables should be handled here, not just this one */
5762 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuMode.Training")),
5763 gameMode == Training || gameMode == PlayFromGameFile);
5768 * Button/menu procedures
5771 int LoadGamePopUp(f, gameNumber, title)
5776 cmailMsgLoaded = FALSE;
5777 if (gameNumber == 0) {
5778 int error = GameListBuild(f);
5780 DisplayError(_("Cannot build game list"), error);
5781 } else if (!ListEmpty(&gameList) &&
5782 ((ListGame *) gameList.tailPred)->number > 1) {
5783 GameListPopUp(f, title);
5789 return LoadGame(f, gameNumber, title, FALSE);
5793 void LoadNextPositionProc(w, event, prms, nprms)
5802 void LoadPrevPositionProc(w, event, prms, nprms)
5811 void ReloadPositionProc(w, event, prms, nprms)
5820 void LoadPositionProc(w, event, prms, nprms)
5826 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
5829 FileNamePopUp(_("Load position file name?"), "", LoadPosition, "rb");
5832 void SaveGameProc(w, event, prms, nprms)
5838 FileNamePopUp(_("Save game file name?"),
5839 DefaultFileName(appData.oldSaveStyle ? "game" : "pgn"),
5843 void SavePositionProc(w, event, prms, nprms)
5849 FileNamePopUp(_("Save position file name?"),
5850 DefaultFileName(appData.oldSaveStyle ? "pos" : "fen"),
5854 void ReloadCmailMsgProc(w, event, prms, nprms)
5860 ReloadCmailMsgEvent(FALSE);
5863 void MailMoveProc(w, event, prms, nprms)
5872 /* this variable is shared between CopyPositionProc and SendPositionSelection */
5873 static char *selected_fen_position=NULL;
5876 SendPositionSelection(Widget w, Atom *selection, Atom *target,
5877 Atom *type_return, XtPointer *value_return,
5878 unsigned long *length_return, int *format_return)
5880 char *selection_tmp;
5882 if (!selected_fen_position) return False; /* should never happen */
5883 if (*target == XA_STRING){
5884 /* note: since no XtSelectionDoneProc was registered, Xt will
5885 * automatically call XtFree on the value returned. So have to
5886 * make a copy of it allocated with XtMalloc */
5887 selection_tmp= XtMalloc(strlen(selected_fen_position)+16);
5888 strcpy(selection_tmp, selected_fen_position);
5890 *value_return=selection_tmp;
5891 *length_return=strlen(selection_tmp);
5892 *type_return=XA_STRING;
5893 *format_return = 8; /* bits per byte */
5900 /* note: when called from menu all parameters are NULL, so no clue what the
5901 * Widget which was clicked on was, or what the click event was
5903 void CopyPositionProc(w, event, prms, nprms)
5911 if (selected_fen_position) free(selected_fen_position);
5912 selected_fen_position = (char *)PositionToFEN(currentMove, NULL);
5913 if (!selected_fen_position) return;
5914 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
5916 SendPositionSelection,
5917 NULL/* lose_ownership_proc */ ,
5918 NULL/* transfer_done_proc */);
5920 free(selected_fen_position);
5921 selected_fen_position=NULL;
5925 /* function called when the data to Paste is ready */
5927 PastePositionCB(Widget w, XtPointer client_data, Atom *selection,
5928 Atom *type, XtPointer value, unsigned long *len, int *format)
5931 if (value==NULL || *len==0) return; /* nothing had been selected to copy */
5932 fenstr[*len]='\0'; /* normally this string is terminated, but be safe */
5933 EditPositionPasteFEN(fenstr);
5937 /* called when Paste Position button is pressed,
5938 * all parameters will be NULL */
5939 void PastePositionProc(w, event, prms, nprms)
5945 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
5946 /* (XtSelectionCallbackProc) */ PastePositionCB,
5947 NULL, /* client_data passed to PastePositionCB */
5949 /* better to use the time field from the event that triggered the
5950 * call to this function, but that isn't trivial to get
5958 SendGameSelection(Widget w, Atom *selection, Atom *target,
5959 Atom *type_return, XtPointer *value_return,
5960 unsigned long *length_return, int *format_return)
5962 char *selection_tmp;
5964 if (*target == XA_STRING){
5965 FILE* f = fopen(gameCopyFilename, "r");
5968 if (f == NULL) return False;
5972 selection_tmp = XtMalloc(len + 1);
5973 count = fread(selection_tmp, 1, len, f);
5975 XtFree(selection_tmp);
5978 selection_tmp[len] = NULLCHAR;
5979 *value_return = selection_tmp;
5980 *length_return = len;
5981 *type_return = XA_STRING;
5982 *format_return = 8; /* bits per byte */
5989 /* note: when called from menu all parameters are NULL, so no clue what the
5990 * Widget which was clicked on was, or what the click event was
5992 void CopyGameProc(w, event, prms, nprms)
6000 ret = SaveGameToFile(gameCopyFilename, FALSE);
6003 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
6006 NULL/* lose_ownership_proc */ ,
6007 NULL/* transfer_done_proc */);
6010 /* function called when the data to Paste is ready */
6012 PasteGameCB(Widget w, XtPointer client_data, Atom *selection,
6013 Atom *type, XtPointer value, unsigned long *len, int *format)
6016 if (value == NULL || *len == 0) {
6017 return; /* nothing had been selected to copy */
6019 f = fopen(gamePasteFilename, "w");
6021 DisplayError(_("Can't open temp file"), errno);
6024 fwrite(value, 1, *len, f);
6027 LoadGameFromFile(gamePasteFilename, 0, gamePasteFilename, TRUE);
6030 /* called when Paste Game button is pressed,
6031 * all parameters will be NULL */
6032 void PasteGameProc(w, event, prms, nprms)
6038 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
6039 /* (XtSelectionCallbackProc) */ PasteGameCB,
6040 NULL, /* client_data passed to PasteGameCB */
6042 /* better to use the time field from the event that triggered the
6043 * call to this function, but that isn't trivial to get
6053 SaveGameProc(NULL, NULL, NULL, NULL);
6056 void MachineBlackProc(w, event, prms, nprms)
6062 MachineBlackEvent();
6065 void MachineWhiteProc(w, event, prms, nprms)
6071 MachineWhiteEvent();
6074 void AnalyzeModeProc(w, event, prms, nprms)
6082 if (!first.analysisSupport) {
6083 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
6084 DisplayError(buf, 0);
6087 /* [DM] icsEngineAnalyze [HGM] This is horrible code; reverse the gameMode and isEngineAnalyze tests! */
6088 if (appData.icsActive) {
6089 if (gameMode != IcsObserving) {
6090 sprintf(buf,_("You are not observing a game"));
6091 DisplayError(buf, 0);
6093 if (appData.icsEngineAnalyze) {
6094 if (appData.debugMode)
6095 fprintf(debugFP, _("Found unexpected active ICS engine analyze \n"));
6101 /* if enable, use want disable icsEngineAnalyze */
6102 if (appData.icsEngineAnalyze) {
6107 appData.icsEngineAnalyze = TRUE;
6108 if (appData.debugMode)
6109 fprintf(debugFP, _("ICS engine analyze starting... \n"));
6111 if (!appData.showThinking)
6112 ShowThinkingProc(w,event,prms,nprms);
6117 void AnalyzeFileProc(w, event, prms, nprms)
6123 if (!first.analysisSupport) {
6125 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
6126 DisplayError(buf, 0);
6131 if (!appData.showThinking)
6132 ShowThinkingProc(w,event,prms,nprms);
6135 FileNamePopUp(_("File to analyze"), "", LoadGamePopUp, "rb");
6136 AnalysisPeriodicEvent(1);
6139 void TwoMachinesProc(w, event, prms, nprms)
6148 void IcsClientProc(w, event, prms, nprms)
6157 void EditGameProc(w, event, prms, nprms)
6166 void EditPositionProc(w, event, prms, nprms)
6172 EditPositionEvent();
6175 void TrainingProc(w, event, prms, nprms)
6184 void EditCommentProc(w, event, prms, nprms)
6191 EditCommentPopDown();
6197 void IcsInputBoxProc(w, event, prms, nprms)
6203 if (ICSInputBoxUp) {
6204 ICSInputBoxPopDown();
6210 void AcceptProc(w, event, prms, nprms)
6219 void DeclineProc(w, event, prms, nprms)
6228 void RematchProc(w, event, prms, nprms)
6237 void CallFlagProc(w, event, prms, nprms)
6246 void DrawProc(w, event, prms, nprms)
6255 void AbortProc(w, event, prms, nprms)
6264 void AdjournProc(w, event, prms, nprms)
6273 void ResignProc(w, event, prms, nprms)
6282 void AdjuWhiteProc(w, event, prms, nprms)
6288 UserAdjudicationEvent(+1);
6291 void AdjuBlackProc(w, event, prms, nprms)
6297 UserAdjudicationEvent(-1);
6300 void AdjuDrawProc(w, event, prms, nprms)
6306 UserAdjudicationEvent(0);
6309 void EnterKeyProc(w, event, prms, nprms)
6315 if (ICSInputBoxUp == True)
6319 void StopObservingProc(w, event, prms, nprms)
6325 StopObservingEvent();
6328 void StopExaminingProc(w, event, prms, nprms)
6334 StopExaminingEvent();
6338 void ForwardProc(w, event, prms, nprms)
6348 void BackwardProc(w, event, prms, nprms)
6357 void ToStartProc(w, event, prms, nprms)
6366 void ToEndProc(w, event, prms, nprms)
6375 void RevertProc(w, event, prms, nprms)
6384 void TruncateGameProc(w, event, prms, nprms)
6390 TruncateGameEvent();
6392 void RetractMoveProc(w, event, prms, nprms)
6401 void MoveNowProc(w, event, prms, nprms)
6411 void AlwaysQueenProc(w, event, prms, nprms)
6419 appData.alwaysPromoteToQueen = !appData.alwaysPromoteToQueen;
6421 if (appData.alwaysPromoteToQueen) {
6422 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6424 XtSetArg(args[0], XtNleftBitmap, None);
6426 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
6430 void AnimateDraggingProc(w, event, prms, nprms)
6438 appData.animateDragging = !appData.animateDragging;
6440 if (appData.animateDragging) {
6441 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6444 XtSetArg(args[0], XtNleftBitmap, None);
6446 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Dragging"),
6450 void AnimateMovingProc(w, event, prms, nprms)
6458 appData.animate = !appData.animate;
6460 if (appData.animate) {
6461 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6464 XtSetArg(args[0], XtNleftBitmap, None);
6466 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
6470 void AutocommProc(w, event, prms, nprms)
6478 appData.autoComment = !appData.autoComment;
6480 if (appData.autoComment) {
6481 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6483 XtSetArg(args[0], XtNleftBitmap, None);
6485 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
6490 void AutoflagProc(w, event, prms, nprms)
6498 appData.autoCallFlag = !appData.autoCallFlag;
6500 if (appData.autoCallFlag) {
6501 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6503 XtSetArg(args[0], XtNleftBitmap, None);
6505 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
6509 void AutoflipProc(w, event, prms, nprms)
6517 appData.autoFlipView = !appData.autoFlipView;
6519 if (appData.autoFlipView) {
6520 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6522 XtSetArg(args[0], XtNleftBitmap, None);
6524 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flip View"),
6528 void AutobsProc(w, event, prms, nprms)
6536 appData.autoObserve = !appData.autoObserve;
6538 if (appData.autoObserve) {
6539 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6541 XtSetArg(args[0], XtNleftBitmap, None);
6543 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
6547 void AutoraiseProc(w, event, prms, nprms)
6555 appData.autoRaiseBoard = !appData.autoRaiseBoard;
6557 if (appData.autoRaiseBoard) {
6558 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6560 XtSetArg(args[0], XtNleftBitmap, None);
6562 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Raise Board"),
6566 void AutosaveProc(w, event, prms, nprms)
6574 appData.autoSaveGames = !appData.autoSaveGames;
6576 if (appData.autoSaveGames) {
6577 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6579 XtSetArg(args[0], XtNleftBitmap, None);
6581 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
6585 void BlindfoldProc(w, event, prms, nprms)
6593 appData.blindfold = !appData.blindfold;
6595 if (appData.blindfold) {
6596 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6598 XtSetArg(args[0], XtNleftBitmap, None);
6600 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Blindfold"),
6603 DrawPosition(True, NULL);
6606 void TestLegalityProc(w, event, prms, nprms)
6614 appData.testLegality = !appData.testLegality;
6616 if (appData.testLegality) {
6617 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6619 XtSetArg(args[0], XtNleftBitmap, None);
6621 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Test Legality"),
6626 void FlashMovesProc(w, event, prms, nprms)
6634 if (appData.flashCount == 0) {
6635 appData.flashCount = 3;
6637 appData.flashCount = -appData.flashCount;
6640 if (appData.flashCount > 0) {
6641 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6643 XtSetArg(args[0], XtNleftBitmap, None);
6645 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flash Moves"),
6649 void FlipViewProc(w, event, prms, nprms)
6655 flipView = !flipView;
6656 DrawPosition(True, NULL);
6659 void GetMoveListProc(w, event, prms, nprms)
6667 appData.getMoveList = !appData.getMoveList;
6669 if (appData.getMoveList) {
6670 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6673 XtSetArg(args[0], XtNleftBitmap, None);
6675 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
6680 void HighlightDraggingProc(w, event, prms, nprms)
6688 appData.highlightDragging = !appData.highlightDragging;
6690 if (appData.highlightDragging) {
6691 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6693 XtSetArg(args[0], XtNleftBitmap, None);
6695 XtSetValues(XtNameToWidget(menuBarWidget,
6696 "menuOptions.Highlight Dragging"), args, 1);
6700 void HighlightLastMoveProc(w, event, prms, nprms)
6708 appData.highlightLastMove = !appData.highlightLastMove;
6710 if (appData.highlightLastMove) {
6711 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6713 XtSetArg(args[0], XtNleftBitmap, None);
6715 XtSetValues(XtNameToWidget(menuBarWidget,
6716 "menuOptions.Highlight Last Move"), args, 1);
6719 void IcsAlarmProc(w, event, prms, nprms)
6727 appData.icsAlarm = !appData.icsAlarm;
6729 if (appData.icsAlarm) {
6730 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6732 XtSetArg(args[0], XtNleftBitmap, None);
6734 XtSetValues(XtNameToWidget(menuBarWidget,
6735 "menuOptions.ICS Alarm"), args, 1);
6738 void MoveSoundProc(w, event, prms, nprms)
6746 appData.ringBellAfterMoves = !appData.ringBellAfterMoves;
6748 if (appData.ringBellAfterMoves) {
6749 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6751 XtSetArg(args[0], XtNleftBitmap, None);
6753 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
6758 void OldSaveStyleProc(w, event, prms, nprms)
6766 appData.oldSaveStyle = !appData.oldSaveStyle;
6768 if (appData.oldSaveStyle) {
6769 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6771 XtSetArg(args[0], XtNleftBitmap, None);
6773 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Old Save Style"),
6777 void PeriodicUpdatesProc(w, event, prms, nprms)
6785 PeriodicUpdatesEvent(!appData.periodicUpdates);
6787 if (appData.periodicUpdates) {
6788 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6790 XtSetArg(args[0], XtNleftBitmap, None);
6792 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Periodic Updates"),
6796 void PonderNextMoveProc(w, event, prms, nprms)
6804 PonderNextMoveEvent(!appData.ponderNextMove);
6806 if (appData.ponderNextMove) {
6807 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6809 XtSetArg(args[0], XtNleftBitmap, None);
6811 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Ponder Next Move"),
6815 void PopupExitMessageProc(w, event, prms, nprms)
6823 appData.popupExitMessage = !appData.popupExitMessage;
6825 if (appData.popupExitMessage) {
6826 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6828 XtSetArg(args[0], XtNleftBitmap, None);
6830 XtSetValues(XtNameToWidget(menuBarWidget,
6831 "menuOptions.Popup Exit Message"), args, 1);
6834 void PopupMoveErrorsProc(w, event, prms, nprms)
6842 appData.popupMoveErrors = !appData.popupMoveErrors;
6844 if (appData.popupMoveErrors) {
6845 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6847 XtSetArg(args[0], XtNleftBitmap, None);
6849 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Popup Move Errors"),
6853 void PremoveProc(w, event, prms, nprms)
6861 appData.premove = !appData.premove;
6863 if (appData.premove) {
6864 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6866 XtSetArg(args[0], XtNleftBitmap, None);
6868 XtSetValues(XtNameToWidget(menuBarWidget,
6869 "menuOptions.Premove"), args, 1);
6872 void QuietPlayProc(w, event, prms, nprms)
6880 appData.quietPlay = !appData.quietPlay;
6882 if (appData.quietPlay) {
6883 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6885 XtSetArg(args[0], XtNleftBitmap, None);
6887 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Quiet Play"),
6891 void ShowThinkingProc(w, event, prms, nprms)
6899 appData.showThinking = !appData.showThinking; // [HGM] thinking: tken out of ShowThinkingEvent
6900 ShowThinkingEvent();
6902 // [HGM] thinking: currently no suc menu item; replaced by Hide Thinking (From Human)
6903 if (appData.showThinking) {
6904 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6906 XtSetArg(args[0], XtNleftBitmap, None);
6908 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Thinking"),
6913 void HideThinkingProc(w, event, prms, nprms)
6921 appData.hideThinkingFromHuman = !appData.hideThinkingFromHuman; // [HGM] thinking: tken out of ShowThinkingEvent
6922 ShowThinkingEvent();
6924 if (appData.hideThinkingFromHuman) {
6925 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6927 XtSetArg(args[0], XtNleftBitmap, None);
6929 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
6933 void InfoProc(w, event, prms, nprms)
6940 snprintf(buf, sizeof(buf), "xterm -e info --directory %s --directory . -f %s &",
6945 void ManProc(w, event, prms, nprms)
6953 if (nprms && *nprms > 0)
6957 snprintf(buf, sizeof(buf), "xterm -e man %s &", name);
6961 void HintProc(w, event, prms, nprms)
6970 void BookProc(w, event, prms, nprms)
6979 void DebugProc(w, event, prms, nprms)
6985 appData.debugMode = !appData.debugMode;
6988 void AboutGameProc(w, event, prms, nprms)
6997 void NothingProc(w, event, prms, nprms)
7006 void Iconify(w, event, prms, nprms)
7015 XtSetArg(args[0], XtNiconic, True);
7016 XtSetValues(shellWidget, args, 1);
7019 void DisplayMessage(message, extMessage)
7020 gchar *message, *extMessage;
7027 snprintf(buf, sizeof(buf), "%s %s", message, extMessage);
7030 message = extMessage;
7034 printf("TODO: message %s\n",message);
7035 gtk_label_set_text( GTK_LABEL(gtk_builder_get_object (builder, "Messages")),message);
7038 void DisplayTitle(text)
7043 char title[MSG_SIZ];
7046 if (text == NULL) text = "";
7048 if (appData.titleInWindow) {
7050 XtSetArg(args[i], XtNlabel, text); i++;
7051 XtSetValues(titleWidget, args, i);
7054 if (*text != NULLCHAR) {
7056 strcpy(title, text);
7057 } else if (appData.icsActive) {
7058 snprintf(icon, sizeof(icon), "%s", appData.icsHost);
7059 snprintf(title, sizeof(title), "%s: %s", programName, appData.icsHost);
7060 } else if (appData.cmailGameName[0] != NULLCHAR) {
7061 snprintf(icon, sizeof(icon), "%s", "CMail");
7062 snprintf(title,sizeof(title), "%s: %s", programName, "CMail");
7064 // [HGM] license: This stuff should really be done in back-end, but WinBoard already had a pop-up for it
7065 } else if (gameInfo.variant == VariantGothic) {
7066 strcpy(icon, programName);
7067 strcpy(title, GOTHIC);
7070 } else if (gameInfo.variant == VariantFalcon) {
7071 strcpy(icon, programName);
7072 strcpy(title, FALCON);
7074 } else if (appData.noChessProgram) {
7075 strcpy(icon, programName);
7076 strcpy(title, programName);
7078 strcpy(icon, first.tidy);
7079 snprintf(title,sizeof(title), "%s: %s", programName, first.tidy);
7082 XtSetArg(args[i], XtNiconName, (XtArgVal) icon); i++;
7083 XtSetArg(args[i], XtNtitle, (XtArgVal) title); i++;
7084 XtSetValues(shellWidget, args, i);
7088 void DisplayError(message, error)
7095 if (appData.debugMode || appData.matchMode) {
7096 fprintf(stderr, "%s: %s\n", programName, message);
7099 if (appData.debugMode || appData.matchMode) {
7100 fprintf(stderr, "%s: %s: %s\n",
7101 programName, message, strerror(error));
7103 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
7106 ErrorPopUp(_("Error"), message, FALSE);
7110 void DisplayMoveError(message)
7115 DrawPosition(FALSE, NULL);
7116 if (appData.debugMode || appData.matchMode) {
7117 fprintf(stderr, "%s: %s\n", programName, message);
7119 if (appData.popupMoveErrors) {
7120 ErrorPopUp(_("Error"), message, FALSE);
7122 DisplayMessage(message, "");
7127 void DisplayFatalError(message, error, status)
7133 errorExitStatus = status;
7135 fprintf(stderr, "%s: %s\n", programName, message);
7137 fprintf(stderr, "%s: %s: %s\n",
7138 programName, message, strerror(error));
7139 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
7142 if (appData.popupExitMessage && boardWidget && XtIsRealized(boardWidget)) {
7143 ErrorPopUp(status ? _("Fatal Error") : _("Exiting"), message, TRUE);
7149 void DisplayInformation(message)
7153 ErrorPopUp(_("Information"), message, TRUE);
7156 void DisplayNote(message)
7160 ErrorPopUp(_("Note"), message, FALSE);
7164 NullXErrorCheck(dpy, error_event)
7166 XErrorEvent *error_event;
7171 void DisplayIcsInteractionTitle(message)
7174 if (oldICSInteractionTitle == NULL) {
7175 /* Magic to find the old window title, adapted from vim */
7176 char *wina = getenv("WINDOWID");
7178 Window win = (Window) atoi(wina);
7179 Window root, parent, *children;
7180 unsigned int nchildren;
7181 int (*oldHandler)() = XSetErrorHandler(NullXErrorCheck);
7183 if (XFetchName(xDisplay, win, &oldICSInteractionTitle)) break;
7184 if (!XQueryTree(xDisplay, win, &root, &parent,
7185 &children, &nchildren)) break;
7186 if (children) XFree((void *)children);
7187 if (parent == root || parent == 0) break;
7190 XSetErrorHandler(oldHandler);
7192 if (oldICSInteractionTitle == NULL) {
7193 oldICSInteractionTitle = "xterm";
7196 printf("\033]0;%s\007", message);
7200 char pendingReplyPrefix[MSG_SIZ];
7201 ProcRef pendingReplyPR;
7203 void AskQuestionProc(w, event, prms, nprms)
7210 fprintf(stderr, _("AskQuestionProc needed 4 parameters, got %d\n"),
7214 AskQuestionEvent(prms[0], prms[1], prms[2], prms[3]);
7217 void AskQuestionPopDown()
7219 if (!askQuestionUp) return;
7220 XtPopdown(askQuestionShell);
7221 XtDestroyWidget(askQuestionShell);
7222 askQuestionUp = False;
7225 void AskQuestionReplyAction(w, event, prms, nprms)
7235 reply = XawDialogGetValueString(w = XtParent(w));
7236 strcpy(buf, pendingReplyPrefix);
7237 if (*buf) strcat(buf, " ");
7240 OutputToProcess(pendingReplyPR, buf, strlen(buf), &err);
7241 AskQuestionPopDown();
7243 if (err) DisplayFatalError(_("Error writing to chess program"), err, 0);
7246 void AskQuestionCallback(w, client_data, call_data)
7248 XtPointer client_data, call_data;
7253 XtSetArg(args[0], XtNlabel, &name);
7254 XtGetValues(w, args, 1);
7256 if (strcmp(name, _("cancel")) == 0) {
7257 AskQuestionPopDown();
7259 AskQuestionReplyAction(w, NULL, NULL, NULL);
7263 void AskQuestion(title, question, replyPrefix, pr)
7264 char *title, *question, *replyPrefix;
7268 Widget popup, layout, dialog, edit;
7274 strcpy(pendingReplyPrefix, replyPrefix);
7275 pendingReplyPR = pr;
7278 XtSetArg(args[i], XtNresizable, True); i++;
7279 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
7280 askQuestionShell = popup =
7281 XtCreatePopupShell(title, transientShellWidgetClass,
7282 shellWidget, args, i);
7285 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
7286 layoutArgs, XtNumber(layoutArgs));
7289 XtSetArg(args[i], XtNlabel, question); i++;
7290 XtSetArg(args[i], XtNvalue, ""); i++;
7291 XtSetArg(args[i], XtNborderWidth, 0); i++;
7292 dialog = XtCreateManagedWidget("question", dialogWidgetClass,
7295 XawDialogAddButton(dialog, _("enter"), AskQuestionCallback,
7296 (XtPointer) dialog);
7297 XawDialogAddButton(dialog, _("cancel"), AskQuestionCallback,
7298 (XtPointer) dialog);
7300 XtRealizeWidget(popup);
7301 CatchDeleteWindow(popup, "AskQuestionPopDown");
7303 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
7304 &x, &y, &win_x, &win_y, &mask);
7306 XtSetArg(args[0], XtNx, x - 10);
7307 XtSetArg(args[1], XtNy, y - 30);
7308 XtSetValues(popup, args, 2);
7310 XtPopup(popup, XtGrabExclusive);
7311 askQuestionUp = True;
7313 edit = XtNameToWidget(dialog, "*value");
7314 XtSetKeyboardFocus(popup, edit);
7322 if (*name == NULLCHAR) {
7324 } else if (strcmp(name, "$") == 0) {
7325 putc(BELLCHAR, stderr);
7328 snprintf(buf, sizeof(buf), "%s '%s' &", appData.soundProgram, name);
7336 PlaySound(appData.soundMove);
7342 PlaySound(appData.soundIcsWin);
7348 PlaySound(appData.soundIcsLoss);
7354 PlaySound(appData.soundIcsDraw);
7358 PlayIcsUnfinishedSound()
7360 PlaySound(appData.soundIcsUnfinished);
7366 PlaySound(appData.soundIcsAlarm);
7372 system("stty echo");
7378 system("stty -echo");
7382 Colorize(cc, continuation)
7387 int count, outCount, error;
7389 if (textColors[(int)cc].bg > 0) {
7390 if (textColors[(int)cc].fg > 0) {
7391 sprintf(buf, "\033[0;%d;%d;%dm", textColors[(int)cc].attr,
7392 textColors[(int)cc].fg, textColors[(int)cc].bg);
7394 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
7395 textColors[(int)cc].bg);
7398 if (textColors[(int)cc].fg > 0) {
7399 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
7400 textColors[(int)cc].fg);
7402 sprintf(buf, "\033[0;%dm", textColors[(int)cc].attr);
7405 count = strlen(buf);
7406 outCount = OutputToProcess(NoProc, buf, count, &error);
7407 if (outCount < count) {
7408 DisplayFatalError(_("Error writing to display"), error, 1);
7411 if (continuation) return;
7414 PlaySound(appData.soundShout);
7417 PlaySound(appData.soundSShout);
7420 PlaySound(appData.soundChannel1);
7423 PlaySound(appData.soundChannel);
7426 PlaySound(appData.soundKibitz);
7429 PlaySound(appData.soundTell);
7431 case ColorChallenge:
7432 PlaySound(appData.soundChallenge);
7435 PlaySound(appData.soundRequest);
7438 PlaySound(appData.soundSeek);
7449 return getpwuid(getuid())->pw_name;
7452 static char *ExpandPathName(path)
7455 static char static_buf[2000];
7456 char *d, *s, buf[2000];
7462 while (*s && isspace(*s))
7471 if (*(s+1) == '/') {
7472 strcpy(d, getpwuid(getuid())->pw_dir);
7477 *strchr(buf, '/') = 0;
7478 pwd = getpwnam(buf);
7481 fprintf(stderr, _("ERROR: Unknown user %s (in path %s)\n"),
7485 strcpy(d, pwd->pw_dir);
7486 strcat(d, strchr(s+1, '/'));
7497 static char host_name[MSG_SIZ];
7499 #if HAVE_GETHOSTNAME
7500 gethostname(host_name, MSG_SIZ);
7502 #else /* not HAVE_GETHOSTNAME */
7503 # if HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H
7504 sysinfo(SI_HOSTNAME, host_name, MSG_SIZ);
7506 # else /* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
7508 # endif/* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
7509 #endif /* not HAVE_GETHOSTNAME */
7512 XtIntervalId delayedEventTimerXID = 0;
7513 DelayedEventCallback delayedEventCallback = 0;
7518 delayedEventTimerXID = 0;
7519 delayedEventCallback();
7523 ScheduleDelayedEvent(cb, millisec)
7524 DelayedEventCallback cb; long millisec;
7526 delayedEventCallback = cb;
7527 delayedEventTimerXID =
7528 XtAppAddTimeOut(appContext, millisec,
7529 (XtTimerCallbackProc) FireDelayedEvent, (XtPointer) 0);
7532 DelayedEventCallback
7535 if (delayedEventTimerXID) {
7536 return delayedEventCallback;
7543 CancelDelayedEvent()
7545 if (delayedEventTimerXID) {
7546 XtRemoveTimeOut(delayedEventTimerXID);
7547 delayedEventTimerXID = 0;
7551 XtIntervalId loadGameTimerXID = 0;
7553 int LoadGameTimerRunning()
7555 return loadGameTimerXID != 0;
7558 int StopLoadGameTimer()
7560 if (loadGameTimerXID != 0) {
7561 XtRemoveTimeOut(loadGameTimerXID);
7562 loadGameTimerXID = 0;
7570 LoadGameTimerCallback(arg, id)
7574 loadGameTimerXID = 0;
7579 StartLoadGameTimer(millisec)
7583 XtAppAddTimeOut(appContext, millisec,
7584 (XtTimerCallbackProc) LoadGameTimerCallback,
7588 XtIntervalId analysisClockXID = 0;
7591 AnalysisClockCallback(arg, id)
7595 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile
7596 || appData.icsEngineAnalyze) { // [DM]
7597 AnalysisPeriodicEvent(0);
7598 StartAnalysisClock();
7603 StartAnalysisClock()
7606 XtAppAddTimeOut(appContext, 2000,
7607 (XtTimerCallbackProc) AnalysisClockCallback,
7611 gint clockTimerTag = 0;
7613 int ClockTimerRunning()
7615 return clockTimerTag != 0;
7618 int StopClockTimer()
7620 if (clockTimerTag != 0) {
7621 gtk_timeout_remove(clockTimerTag);
7630 ClockTimerCallback(data)
7639 StartClockTimer(millisec)
7642 clockTimerTag = gtk_timeout_add(millisec,(GtkFunction) ClockTimerCallback,NULL);
7647 DisplayTimerLabel(w, color, timer, highlight)
7656 if (appData.clockMode) {
7657 sprintf(buf, "%s: %s", color, TimeString(timer));
7659 sprintf(buf, "%s ", color);
7661 gtk_label_set_text(GTK_LABEL(w),buf);
7663 /* check for low time warning */
7664 // Pixel foregroundOrWarningColor = timerForegroundPixel;
7667 // appData.lowTimeWarning &&
7668 // (timer / 1000) < appData.icsAlarmTime)
7669 // foregroundOrWarningColor = lowTimeWarningColor;
7671 // if (appData.clockMode) {
7672 // sprintf(buf, "%s: %s", color, TimeString(timer));
7673 // XtSetArg(args[0], XtNlabel, buf);
7675 // sprintf(buf, "%s ", color);
7676 // XtSetArg(args[0], XtNlabel, buf);
7681 // XtSetArg(args[1], XtNbackground, foregroundOrWarningColor);
7682 // XtSetArg(args[2], XtNforeground, timerBackgroundPixel);
7684 // XtSetArg(args[1], XtNbackground, timerBackgroundPixel);
7685 // XtSetArg(args[2], XtNforeground, foregroundOrWarningColor);
7688 // XtSetValues(w, args, 3);
7693 DisplayWhiteClock(timeRemaining, highlight)
7697 if(appData.noGUI) return;
7699 DisplayTimerLabel(GUI_Whiteclock, _("White"), timeRemaining, highlight);
7700 if (highlight && WindowIcon == BlackIcon) {
7701 WindowIcon = WhiteIcon;
7702 gtk_window_set_icon(GTK_WINDOW(GUI_Window),WindowIcon);
7707 DisplayBlackClock(timeRemaining, highlight)
7711 if(appData.noGUI) return;
7712 DisplayTimerLabel(GUI_Blackclock, _("Black"), timeRemaining, highlight);
7713 if (highlight && WindowIcon == WhiteIcon) {
7714 WindowIcon = BlackIcon;
7715 gtk_window_set_icon(GTK_WINDOW(GUI_Window),WindowIcon);
7733 int StartChildProcess(cmdLine, dir, pr)
7740 int to_prog[2], from_prog[2];
7744 if (appData.debugMode) {
7745 fprintf(stderr, "StartChildProcess (dir=\"%s\") %s\n",dir, cmdLine);
7748 /* We do NOT feed the cmdLine to the shell; we just
7749 parse it into blank-separated arguments in the
7750 most simple-minded way possible.
7753 strcpy(buf, cmdLine);
7758 if (p == NULL) break;
7763 SetUpChildIO(to_prog, from_prog);
7765 if ((pid = fork()) == 0) {
7767 // [HGM] PSWBTM: made order resistant against case where fd of created pipe was 0 or 1
7768 close(to_prog[1]); // first close the unused pipe ends
7769 close(from_prog[0]);
7770 dup2(to_prog[0], 0); // to_prog was created first, nd is the only one to use 0 or 1
7771 dup2(from_prog[1], 1);
7772 if(to_prog[0] >= 2) close(to_prog[0]); // if 0 or 1, the dup2 already cosed the original
7773 close(from_prog[1]); // and closing again loses one of the pipes!
7774 if(fileno(stderr) >= 2) // better safe than sorry...
7775 dup2(1, fileno(stderr)); /* force stderr to the pipe */
7777 if (dir[0] != NULLCHAR && chdir(dir) != 0) {
7782 nice(appData.niceEngines); // [HGM] nice: adjust priority of engine proc
7784 execvp(argv[0], argv);
7786 /* If we get here, exec failed */
7791 /* Parent process */
7793 close(from_prog[1]);
7795 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7798 cp->fdFrom = from_prog[0];
7799 cp->fdTo = to_prog[1];
7804 // [HGM] kill: implement the 'hard killing' of AS's Winboard_x
7805 static RETSIGTYPE AlarmCallBack(int n)
7811 DestroyChildProcess(pr, signalType)
7815 ChildProc *cp = (ChildProc *) pr;
7817 if (cp->kind != CPReal) return;
7819 if (signalType == 10) { // [HGM] kill: if it does not terminate in 3 sec, kill
7820 signal(SIGALRM, AlarmCallBack);
7822 if(wait((int *) 0) == -1) { // process does not terminate on its own accord
7823 kill(cp->pid, SIGKILL); // kill it forcefully
7824 wait((int *) 0); // and wait again
7828 kill(cp->pid, signalType == 9 ? SIGKILL : SIGTERM); // [HGM] kill: use hard kill if so requested
7830 /* Process is exiting either because of the kill or because of
7831 a quit command sent by the backend; either way, wait for it to die.
7840 InterruptChildProcess(pr)
7843 ChildProc *cp = (ChildProc *) pr;
7845 if (cp->kind != CPReal) return;
7846 (void) kill(cp->pid, SIGINT); /* stop it thinking */
7849 int OpenTelnet(host, port, pr)
7854 char cmdLine[MSG_SIZ];
7856 if (port[0] == NULLCHAR) {
7857 snprintf(cmdLine, sizeof(cmdLine), "%s %s", appData.telnetProgram, host);
7859 snprintf(cmdLine, sizeof(cmdLine), "%s %s %s", appData.telnetProgram, host, port);
7861 return StartChildProcess(cmdLine, "", pr);
7864 int OpenTCP(host, port, pr)
7870 DisplayFatalError(_("Socket support is not configured in"), 0, 2);
7871 #else /* !OMIT_SOCKETS */
7873 struct sockaddr_in sa;
7875 unsigned short uport;
7878 if ((s = socket(AF_INET, SOCK_STREAM, 6)) < 0) {
7882 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
7883 sa.sin_family = AF_INET;
7884 sa.sin_addr.s_addr = INADDR_ANY;
7885 uport = (unsigned short) 0;
7886 sa.sin_port = htons(uport);
7887 if (bind(s, (struct sockaddr *) &sa, sizeof(struct sockaddr_in)) < 0) {
7891 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
7892 if (!(hp = gethostbyname(host))) {
7894 if (sscanf(host, "%d.%d.%d.%d", &b0, &b1, &b2, &b3) == 4) {
7895 hp = (struct hostent *) calloc(1, sizeof(struct hostent));
7896 hp->h_addrtype = AF_INET;
7898 hp->h_addr_list = (char **) calloc(2, sizeof(char *));
7899 hp->h_addr_list[0] = (char *) malloc(4);
7900 hp->h_addr_list[0][0] = b0;
7901 hp->h_addr_list[0][1] = b1;
7902 hp->h_addr_list[0][2] = b2;
7903 hp->h_addr_list[0][3] = b3;
7908 sa.sin_family = hp->h_addrtype;
7909 uport = (unsigned short) atoi(port);
7910 sa.sin_port = htons(uport);
7911 memcpy((char *) &sa.sin_addr, hp->h_addr, hp->h_length);
7913 if (connect(s, (struct sockaddr *) &sa,
7914 sizeof(struct sockaddr_in)) < 0) {
7918 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7925 #endif /* !OMIT_SOCKETS */
7930 int OpenCommPort(name, pr)
7937 fd = open(name, 2, 0);
7938 if (fd < 0) return errno;
7940 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7950 int OpenLoopback(pr)
7956 SetUpChildIO(to, from);
7958 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7961 cp->fdFrom = to[0]; /* note not from[0]; we are doing a loopback */
7968 int OpenRcmd(host, user, cmd, pr)
7969 char *host, *user, *cmd;
7972 DisplayFatalError(_("internal rcmd not implemented for Unix"), 0, 1);
7976 #define INPUT_SOURCE_BUF_SIZE 8192
7985 char buf[INPUT_SOURCE_BUF_SIZE];
7990 DoInputCallback(closure, source, xid)
7995 InputSource *is = (InputSource *) closure;
8000 if (is->lineByLine) {
8001 count = read(is->fd, is->unused,
8002 INPUT_SOURCE_BUF_SIZE - (is->unused - is->buf));
8004 (is->func)(is, is->closure, is->buf, count, count ? errno : 0);
8007 is->unused += count;
8009 while (p < is->unused) {
8010 q = memchr(p, '\n', is->unused - p);
8011 if (q == NULL) break;
8013 (is->func)(is, is->closure, p, q - p, 0);
8017 while (p < is->unused) {
8022 count = read(is->fd, is->buf, INPUT_SOURCE_BUF_SIZE);
8027 (is->func)(is, is->closure, is->buf, count, error);
8031 InputSourceRef AddInputSource(pr, lineByLine, func, closure)
8038 ChildProc *cp = (ChildProc *) pr;
8040 is = (InputSource *) calloc(1, sizeof(InputSource));
8041 is->lineByLine = lineByLine;
8045 is->fd = fileno(stdin);
8047 is->kind = cp->kind;
8048 is->fd = cp->fdFrom;
8051 is->unused = is->buf;
8054 is->xid = XtAppAddInput(appContext, is->fd,
8055 (XtPointer) (XtInputReadMask),
8056 (XtInputCallbackProc) DoInputCallback,
8058 is->closure = closure;
8059 return (InputSourceRef) is;
8063 RemoveInputSource(isr)
8066 InputSource *is = (InputSource *) isr;
8068 if (is->xid == 0) return;
8069 XtRemoveInput(is->xid);
8073 int OutputToProcess(pr, message, count, outError)
8079 ChildProc *cp = (ChildProc *) pr;
8083 outCount = fwrite(message, 1, count, stdout);
8085 outCount = write(cp->fdTo, message, count);
8095 /* Output message to process, with "ms" milliseconds of delay
8096 between each character. This is needed when sending the logon
8097 script to ICC, which for some reason doesn't like the
8098 instantaneous send. */
8099 int OutputToProcessDelayed(pr, message, count, outError, msdelay)
8106 ChildProc *cp = (ChildProc *) pr;
8111 r = write(cp->fdTo, message++, 1);
8124 /**** Animation code by Hugh Fisher, DCS, ANU.
8126 Known problem: if a window overlapping the board is
8127 moved away while a piece is being animated underneath,
8128 the newly exposed area won't be updated properly.
8129 I can live with this.
8131 Known problem: if you look carefully at the animation
8132 of pieces in mono mode, they are being drawn as solid
8133 shapes without interior detail while moving. Fixing
8134 this would be a major complication for minimal return.
8137 /* Masks for XPM pieces. Black and white pieces can have
8138 different shapes, but in the interest of retaining my
8139 sanity pieces must have the same outline on both light
8140 and dark squares, and all pieces must use the same
8141 background square colors/images. */
8143 static int xpmDone = 0;
8146 CreateAnimMasks (pieceDepth)
8153 unsigned long plane;
8156 /* Need a bitmap just to get a GC with right depth */
8157 buf = XCreatePixmap(xDisplay, xBoardWindow,
8159 values.foreground = 1;
8160 values.background = 0;
8161 /* Don't use XtGetGC, not read only */
8162 maskGC = XCreateGC(xDisplay, buf,
8163 GCForeground | GCBackground, &values);
8164 XFreePixmap(xDisplay, buf);
8166 buf = XCreatePixmap(xDisplay, xBoardWindow,
8167 squareSize, squareSize, pieceDepth);
8168 values.foreground = XBlackPixel(xDisplay, xScreen);
8169 values.background = XWhitePixel(xDisplay, xScreen);
8170 bufGC = XCreateGC(xDisplay, buf,
8171 GCForeground | GCBackground, &values);
8173 for (piece = WhitePawn; piece <= BlackKing; piece++) {
8174 /* Begin with empty mask */
8175 if(!xpmDone) // [HGM] pieces: keep using existing
8176 xpmMask[piece] = XCreatePixmap(xDisplay, xBoardWindow,
8177 squareSize, squareSize, 1);
8178 XSetFunction(xDisplay, maskGC, GXclear);
8179 XFillRectangle(xDisplay, xpmMask[piece], maskGC,
8180 0, 0, squareSize, squareSize);
8182 /* Take a copy of the piece */
8187 XSetFunction(xDisplay, bufGC, GXcopy);
8188 XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % (int)BlackPawn],
8190 0, 0, squareSize, squareSize, 0, 0);
8192 /* XOR the background (light) over the piece */
8193 XSetFunction(xDisplay, bufGC, GXxor);
8195 XCopyArea(xDisplay, xpmLightSquare, buf, bufGC,
8196 0, 0, squareSize, squareSize, 0, 0);
8198 XSetForeground(xDisplay, bufGC, lightSquareColor);
8199 XFillRectangle(xDisplay, buf, bufGC, 0, 0, squareSize, squareSize);
8202 /* We now have an inverted piece image with the background
8203 erased. Construct mask by just selecting all the non-zero
8204 pixels - no need to reconstruct the original image. */
8205 XSetFunction(xDisplay, maskGC, GXor);
8207 /* Might be quicker to download an XImage and create bitmap
8208 data from it rather than this N copies per piece, but it
8209 only takes a fraction of a second and there is a much
8210 longer delay for loading the pieces. */
8211 for (n = 0; n < pieceDepth; n ++) {
8212 XCopyPlane(xDisplay, buf, xpmMask[piece], maskGC,
8213 0, 0, squareSize, squareSize,
8219 XFreePixmap(xDisplay, buf);
8220 XFreeGC(xDisplay, bufGC);
8221 XFreeGC(xDisplay, maskGC);
8225 InitAnimState (anim, info)
8227 XWindowAttributes * info;
8232 /* Each buffer is square size, same depth as window */
8233 anim->saveBuf = XCreatePixmap(xDisplay, xBoardWindow,
8234 squareSize, squareSize, info->depth);
8235 anim->newBuf = XCreatePixmap(xDisplay, xBoardWindow,
8236 squareSize, squareSize, info->depth);
8238 /* Create a plain GC for blitting */
8239 mask = GCForeground | GCBackground | GCFunction |
8240 GCPlaneMask | GCGraphicsExposures;
8241 values.foreground = XBlackPixel(xDisplay, xScreen);
8242 values.background = XWhitePixel(xDisplay, xScreen);
8243 values.function = GXcopy;
8244 values.plane_mask = AllPlanes;
8245 values.graphics_exposures = False;
8246 anim->blitGC = XCreateGC(xDisplay, xBoardWindow, mask, &values);
8248 /* Piece will be copied from an existing context at
8249 the start of each new animation/drag. */
8250 anim->pieceGC = XCreateGC(xDisplay, xBoardWindow, 0, &values);
8252 /* Outline will be a read-only copy of an existing */
8253 anim->outlineGC = None;
8259 static VariantClass old = (VariantClass) -1; // [HGM] pieces: redo every time variant changes
8260 XWindowAttributes info;
8262 if (xpmDone && gameInfo.variant == old) return;
8263 if(xpmDone) old = gameInfo.variant; // first time pieces might not be created yet
8264 // XGetWindowAttributes(xDisplay, xBoardWindow, &info);
8266 InitAnimState(&game, &info);
8267 InitAnimState(&player, &info);
8269 /* For XPM pieces, we need bitmaps to use as masks. */
8271 CreateAnimMasks(info.depth);
8277 static Boolean frameWaiting;
8279 static RETSIGTYPE FrameAlarm (sig)
8282 frameWaiting = False;
8283 /* In case System-V style signals. Needed?? */
8284 signal(SIGALRM, FrameAlarm);
8291 struct itimerval delay;
8293 XSync(xDisplay, False);
8296 frameWaiting = True;
8297 signal(SIGALRM, FrameAlarm);
8298 delay.it_interval.tv_sec =
8299 delay.it_value.tv_sec = time / 1000;
8300 delay.it_interval.tv_usec =
8301 delay.it_value.tv_usec = (time % 1000) * 1000;
8302 setitimer(ITIMER_REAL, &delay, NULL);
8304 /* Ugh -- busy-wait! --tpm */
8305 while (frameWaiting);
8307 while (frameWaiting) pause();
8309 delay.it_interval.tv_sec = delay.it_value.tv_sec = 0;
8310 delay.it_interval.tv_usec = delay.it_value.tv_usec = 0;
8311 setitimer(ITIMER_REAL, &delay, NULL);
8321 XSync(xDisplay, False);
8323 usleep(time * 1000);
8328 /* Convert board position to corner of screen rect and color */
8331 ScreenSquare(column, row, pt, color)
8332 int column; int row; XPoint * pt; int * color;
8335 pt->x = lineGap + ((BOARD_WIDTH-1)-column) * (squareSize + lineGap);
8336 pt->y = lineGap + row * (squareSize + lineGap);
8338 pt->x = lineGap + column * (squareSize + lineGap);
8339 pt->y = lineGap + ((BOARD_HEIGHT-1)-row) * (squareSize + lineGap);
8341 *color = SquareColor(row, column);
8344 /* Convert window coords to square */
8347 BoardSquare(x, y, column, row)
8348 int x; int y; int * column; int * row;
8350 *column = EventToSquare(x, BOARD_WIDTH);
8351 if (flipView && *column >= 0)
8352 *column = BOARD_WIDTH - 1 - *column;
8353 *row = EventToSquare(y, BOARD_HEIGHT);
8354 if (!flipView && *row >= 0)
8355 *row = BOARD_HEIGHT - 1 - *row;
8360 #undef Max /* just in case */
8362 #define Max(a, b) ((a) > (b) ? (a) : (b))
8363 #define Min(a, b) ((a) < (b) ? (a) : (b))
8366 SetRect(rect, x, y, width, height)
8367 XRectangle * rect; int x; int y; int width; int height;
8371 rect->width = width;
8372 rect->height = height;
8375 /* Test if two frames overlap. If they do, return
8376 intersection rect within old and location of
8377 that rect within new. */
8380 Intersect(old, new, size, area, pt)
8381 XPoint * old; XPoint * new;
8382 int size; XRectangle * area; XPoint * pt;
8384 if (old->x > new->x + size || new->x > old->x + size ||
8385 old->y > new->y + size || new->y > old->y + size) {
8388 SetRect(area, Max(new->x - old->x, 0), Max(new->y - old->y, 0),
8389 size - abs(old->x - new->x), size - abs(old->y - new->y));
8390 pt->x = Max(old->x - new->x, 0);
8391 pt->y = Max(old->y - new->y, 0);
8396 /* For two overlapping frames, return the rect(s)
8397 in the old that do not intersect with the new. */
8400 CalcUpdateRects(old, new, size, update, nUpdates)
8401 XPoint * old; XPoint * new; int size;
8402 XRectangle update[]; int * nUpdates;
8406 /* If old = new (shouldn't happen) then nothing to draw */
8407 if (old->x == new->x && old->y == new->y) {
8411 /* Work out what bits overlap. Since we know the rects
8412 are the same size we don't need a full intersect calc. */
8414 /* Top or bottom edge? */
8415 if (new->y > old->y) {
8416 SetRect(&(update[count]), old->x, old->y, size, new->y - old->y);
8418 } else if (old->y > new->y) {
8419 SetRect(&(update[count]), old->x, old->y + size - (old->y - new->y),
8420 size, old->y - new->y);
8423 /* Left or right edge - don't overlap any update calculated above. */
8424 if (new->x > old->x) {
8425 SetRect(&(update[count]), old->x, Max(new->y, old->y),
8426 new->x - old->x, size - abs(new->y - old->y));
8428 } else if (old->x > new->x) {
8429 SetRect(&(update[count]), new->x + size, Max(new->y, old->y),
8430 old->x - new->x, size - abs(new->y - old->y));
8437 /* Generate a series of frame coords from start->mid->finish.
8438 The movement rate doubles until the half way point is
8439 reached, then halves back down to the final destination,
8440 which gives a nice slow in/out effect. The algorithmn
8441 may seem to generate too many intermediates for short
8442 moves, but remember that the purpose is to attract the
8443 viewers attention to the piece about to be moved and
8444 then to where it ends up. Too few frames would be less
8448 Tween(start, mid, finish, factor, frames, nFrames)
8449 XPoint * start; XPoint * mid;
8450 XPoint * finish; int factor;
8451 XPoint frames[]; int * nFrames;
8453 int fraction, n, count;
8457 /* Slow in, stepping 1/16th, then 1/8th, ... */
8459 for (n = 0; n < factor; n++)
8461 for (n = 0; n < factor; n++) {
8462 frames[count].x = start->x + (mid->x - start->x) / fraction;
8463 frames[count].y = start->y + (mid->y - start->y) / fraction;
8465 fraction = fraction / 2;
8469 frames[count] = *mid;
8472 /* Slow out, stepping 1/2, then 1/4, ... */
8474 for (n = 0; n < factor; n++) {
8475 frames[count].x = finish->x - (finish->x - mid->x) / fraction;
8476 frames[count].y = finish->y - (finish->y - mid->y) / fraction;
8478 fraction = fraction * 2;
8483 /* Draw a piece on the screen without disturbing what's there */
8486 SelectGCMask(piece, clip, outline, mask)
8487 ChessSquare piece; GC * clip; GC * outline; Pixmap * mask;
8491 /* Bitmap for piece being moved. */
8492 if (appData.monoMode) {
8493 *mask = *pieceToSolid(piece);
8494 } else if (useImages) {
8496 *mask = xpmMask[piece];
8498 *mask = ximMaskPm[piece];
8501 *mask = *pieceToSolid(piece);
8504 /* GC for piece being moved. Square color doesn't matter, but
8505 since it gets modified we make a copy of the original. */
8507 if (appData.monoMode)
8512 if (appData.monoMode)
8517 XCopyGC(xDisplay, source, 0xFFFFFFFF, *clip);
8519 /* Outline only used in mono mode and is not modified */
8521 *outline = bwPieceGC;
8523 *outline = wbPieceGC;
8527 OverlayPiece(piece, clip, outline, dest)
8528 ChessSquare piece; GC clip; GC outline; Drawable dest;
8533 /* Draw solid rectangle which will be clipped to shape of piece */
8534 XFillRectangle(xDisplay, dest, clip,
8535 0, 0, squareSize, squareSize);
8536 if (appData.monoMode)
8537 /* Also draw outline in contrasting color for black
8538 on black / white on white cases */
8539 XCopyPlane(xDisplay, *pieceToOutline(piece), dest, outline,
8540 0, 0, squareSize, squareSize, 0, 0, 1);
8542 /* Copy the piece */
8547 XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
8549 0, 0, squareSize, squareSize,
8554 /* Animate the movement of a single piece */
8557 BeginAnimation(anim, piece, startColor, start)
8565 /* The old buffer is initialised with the start square (empty) */
8566 BlankSquare(0, 0, startColor, EmptySquare, anim->saveBuf);
8567 anim->prevFrame = *start;
8569 /* The piece will be drawn using its own bitmap as a matte */
8570 SelectGCMask(piece, &anim->pieceGC, &anim->outlineGC, &mask);
8571 XSetClipMask(xDisplay, anim->pieceGC, mask);
8575 AnimationFrame(anim, frame, piece)
8580 XRectangle updates[4];
8585 /* Save what we are about to draw into the new buffer */
8586 XCopyArea(xDisplay, xBoardWindow, anim->newBuf, anim->blitGC,
8587 frame->x, frame->y, squareSize, squareSize,
8590 /* Erase bits of the previous frame */
8591 if (Intersect(&anim->prevFrame, frame, squareSize, &overlap, &pt)) {
8592 /* Where the new frame overlapped the previous,
8593 the contents in newBuf are wrong. */
8594 XCopyArea(xDisplay, anim->saveBuf, anim->newBuf, anim->blitGC,
8595 overlap.x, overlap.y,
8596 overlap.width, overlap.height,
8598 /* Repaint the areas in the old that don't overlap new */
8599 CalcUpdateRects(&anim->prevFrame, frame, squareSize, updates, &count);
8600 for (i = 0; i < count; i++)
8601 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
8602 updates[i].x - anim->prevFrame.x,
8603 updates[i].y - anim->prevFrame.y,
8604 updates[i].width, updates[i].height,
8605 updates[i].x, updates[i].y);
8607 /* Easy when no overlap */
8608 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
8609 0, 0, squareSize, squareSize,
8610 anim->prevFrame.x, anim->prevFrame.y);
8613 /* Save this frame for next time round */
8614 XCopyArea(xDisplay, anim->newBuf, anim->saveBuf, anim->blitGC,
8615 0, 0, squareSize, squareSize,
8617 anim->prevFrame = *frame;
8619 /* Draw piece over original screen contents, not current,
8620 and copy entire rect. Wipes out overlapping piece images. */
8621 OverlayPiece(piece, anim->pieceGC, anim->outlineGC, anim->newBuf);
8622 XCopyArea(xDisplay, anim->newBuf, xBoardWindow, anim->blitGC,
8623 0, 0, squareSize, squareSize,
8624 frame->x, frame->y);
8628 EndAnimation (anim, finish)
8632 XRectangle updates[4];
8637 /* The main code will redraw the final square, so we
8638 only need to erase the bits that don't overlap. */
8639 if (Intersect(&anim->prevFrame, finish, squareSize, &overlap, &pt)) {
8640 CalcUpdateRects(&anim->prevFrame, finish, squareSize, updates, &count);
8641 for (i = 0; i < count; i++)
8642 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
8643 updates[i].x - anim->prevFrame.x,
8644 updates[i].y - anim->prevFrame.y,
8645 updates[i].width, updates[i].height,
8646 updates[i].x, updates[i].y);
8648 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
8649 0, 0, squareSize, squareSize,
8650 anim->prevFrame.x, anim->prevFrame.y);
8655 FrameSequence(anim, piece, startColor, start, finish, frames, nFrames)
8657 ChessSquare piece; int startColor;
8658 XPoint * start; XPoint * finish;
8659 XPoint frames[]; int nFrames;
8663 BeginAnimation(anim, piece, startColor, start);
8664 for (n = 0; n < nFrames; n++) {
8665 AnimationFrame(anim, &(frames[n]), piece);
8666 FrameDelay(appData.animSpeed);
8668 EndAnimation(anim, finish);
8671 /* Main control logic for deciding what to animate and how */
8674 AnimateMove(board, fromX, fromY, toX, toY)
8683 XPoint start, finish, mid;
8684 XPoint frames[kFactor * 2 + 1];
8685 int nFrames, startColor, endColor;
8687 /* Are we animating? */
8688 if (!appData.animate || appData.blindfold)
8691 if(board[toY][toX] == WhiteRook && board[fromY][fromX] == WhiteKing ||
8692 board[toY][toX] == BlackRook && board[fromY][fromX] == BlackKing)
8693 return; // [HGM] FRC: no animtion of FRC castlings, as to-square is not true to-square
8695 if (fromY < 0 || fromX < 0 || toX < 0 || toY < 0) return;
8696 piece = board[fromY][fromX];
8697 if (piece >= EmptySquare) return;
8702 hop = (piece == WhiteKnight || piece == BlackKnight);
8705 if (appData.debugMode) {
8706 fprintf(debugFP, hop ? _("AnimateMove: piece %d hops from %d,%d to %d,%d \n") :
8707 _("AnimateMove: piece %d slides from %d,%d to %d,%d \n"),
8708 piece, fromX, fromY, toX, toY); }
8710 ScreenSquare(fromX, fromY, &start, &startColor);
8711 ScreenSquare(toX, toY, &finish, &endColor);
8714 /* Knight: make diagonal movement then straight */
8715 if (abs(toY - fromY) < abs(toX - fromX)) {
8716 mid.x = start.x + (finish.x - start.x) / 2;
8720 mid.y = start.y + (finish.y - start.y) / 2;
8723 mid.x = start.x + (finish.x - start.x) / 2;
8724 mid.y = start.y + (finish.y - start.y) / 2;
8727 /* Don't use as many frames for very short moves */
8728 if (abs(toY - fromY) + abs(toX - fromX) <= 2)
8729 Tween(&start, &mid, &finish, kFactor - 1, frames, &nFrames);
8731 Tween(&start, &mid, &finish, kFactor, frames, &nFrames);
8732 FrameSequence(&game, piece, startColor, &start, &finish, frames, nFrames);
8734 /* Be sure end square is redrawn */
8735 damage[toY][toX] = True;
8739 DragPieceBegin(x, y)
8742 int boardX, boardY, color;
8745 /* Are we animating? */
8746 if (!appData.animateDragging || appData.blindfold)
8749 /* Figure out which square we start in and the
8750 mouse position relative to top left corner. */
8751 BoardSquare(x, y, &boardX, &boardY);
8752 player.startBoardX = boardX;
8753 player.startBoardY = boardY;
8754 ScreenSquare(boardX, boardY, &corner, &color);
8755 player.startSquare = corner;
8756 player.startColor = color;
8758 /* Start from exactly where the piece is. This can be confusing
8759 if you start dragging far from the center of the square; most
8760 or all of the piece can be over a different square from the one
8761 the mouse pointer is in. */
8762 player.mouseDelta.x = x - corner.x;
8763 player.mouseDelta.y = y - corner.y;
8765 /* As soon as we start dragging, the piece will jump slightly to
8766 be centered over the mouse pointer. */
8767 player.mouseDelta.x = squareSize/2;
8768 player.mouseDelta.y = squareSize/2;
8770 /* Initialise animation */
8771 player.dragPiece = PieceForSquare(boardX, boardY);
8773 if (player.dragPiece >= 0 && player.dragPiece < EmptySquare) {
8774 player.dragActive = True;
8775 BeginAnimation(&player, player.dragPiece, color, &corner);
8776 /* Mark this square as needing to be redrawn. Note that
8777 we don't remove the piece though, since logically (ie
8778 as seen by opponent) the move hasn't been made yet. */
8779 if(boardX == BOARD_RGHT+1 && PieceForSquare(boardX-1, boardY) > 1 ||
8780 boardX == BOARD_LEFT-2 && PieceForSquare(boardX+1, boardY) > 1)
8781 XCopyArea(xDisplay, xBoardWindow, player.saveBuf, player.blitGC,
8782 corner.x, corner.y, squareSize, squareSize,
8783 0, 0); // [HGM] zh: unstack in stead of grab
8784 damage[boardY][boardX] = True;
8786 player.dragActive = False;
8796 /* Are we animating? */
8797 if (!appData.animateDragging || appData.blindfold)
8801 if (! player.dragActive)
8803 /* Move piece, maintaining same relative position
8804 of mouse within square */
8805 corner.x = x - player.mouseDelta.x;
8806 corner.y = y - player.mouseDelta.y;
8807 AnimationFrame(&player, &corner, player.dragPiece);
8809 if (appData.highlightDragging) {
8811 BoardSquare(x, y, &boardX, &boardY);
8812 SetHighlights(fromX, fromY, boardX, boardY);
8821 int boardX, boardY, color;
8824 /* Are we animating? */
8825 if (!appData.animateDragging || appData.blindfold)
8829 if (! player.dragActive)
8831 /* Last frame in sequence is square piece is
8832 placed on, which may not match mouse exactly. */
8833 BoardSquare(x, y, &boardX, &boardY);
8834 ScreenSquare(boardX, boardY, &corner, &color);
8835 EndAnimation(&player, &corner);
8837 /* Be sure end square is redrawn */
8838 damage[boardY][boardX] = True;
8840 /* This prevents weird things happening with fast successive
8841 clicks which on my Sun at least can cause motion events
8842 without corresponding press/release. */
8843 player.dragActive = False;
8846 /* Handle expose event while piece being dragged */
8851 if (!player.dragActive || appData.blindfold)
8854 /* What we're doing: logically, the move hasn't been made yet,
8855 so the piece is still in it's original square. But visually
8856 it's being dragged around the board. So we erase the square
8857 that the piece is on and draw it at the last known drag point. */
8858 BlankSquare(player.startSquare.x, player.startSquare.y,
8859 player.startColor, EmptySquare, xBoardWindow);
8860 AnimationFrame(&player, &player.prevFrame, player.dragPiece);
8861 damage[player.startBoardY][player.startBoardX] = TRUE;
8865 SetProgramStats( FrontEndProgramStats * stats )
8868 // [HGM] done, but perhaps backend should call this directly?
8869 EngineOutputUpdate( stats );