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, 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));
2141 XtSetArg(args[0], XtNiconic, False);
2142 XtSetValues(shellWidget, args, 1);
2144 XtPopup(shellWidget, XtGrabNone); /* Raise if lowered */
2148 // eventually, all layout determining code should go into a subroutine, but until then IDSIZE remains undefined
2150 #define BoardSize int
2151 void InitDrawingSizes(BoardSize boardSize, int flags)
2152 { // [HGM] resize is functional now, but for board format changes only (nr of ranks, files)
2153 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
2155 XtGeometryResult gres;
2158 if(!formWidget) return;
2161 * Enable shell resizing.
2163 // shellArgs[0].value = (XtArgVal) &w;
2164 // shellArgs[1].value = (XtArgVal) &h;
2165 // XtGetValues(shellWidget, shellArgs, 2);
2167 // shellArgs[4].value = 2*w; shellArgs[2].value = 10;
2168 // shellArgs[5].value = 2*h; shellArgs[3].value = 10;
2169 // XtSetValues(shellWidget, &shellArgs[2], 4);
2171 // XtSetArg(args[0], XtNdefaultDistance, &sep);
2172 // XtGetValues(formWidget, args, 1);
2174 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2175 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2178 // XtSetArg(args[0], XtNwidth, boardWidth);
2179 // XtSetArg(args[1], XtNheight, boardHeight);
2180 // XtSetValues(boardWidget, args, 2);
2182 timerWidth = (boardWidth - sep) / 2;
2183 // XtSetArg(args[0], XtNwidth, timerWidth);
2184 // XtSetValues(whiteTimerWidget, args, 1);
2185 // XtSetValues(blackTimerWidget, args, 1);
2187 // XawFormDoLayout(formWidget, False);
2189 if (appData.titleInWindow) {
2191 // XtSetArg(args[i], XtNborderWidth, &bor); i++;
2192 // XtSetArg(args[i], XtNheight, &h); i++;
2193 // XtGetValues(titleWidget, args, i);
2195 w = boardWidth - 2*bor;
2197 // XtSetArg(args[0], XtNwidth, &w);
2198 // XtGetValues(menuBarWidget, args, 1);
2199 w = boardWidth - w - sep - 2*bor - 2; // WIDTH_FUDGE
2202 // gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
2203 // if (gres != XtGeometryYes && appData.debugMode) {
2205 // _("%s: titleWidget geometry error %d %d %d %d %d\n"),
2206 // programName, gres, w, h, wr, hr);
2210 // XawFormDoLayout(formWidget, True);
2213 * Inhibit shell resizing.
2215 shellArgs[0].value = w = (XtArgVal) boardWidth + marginW;
2216 shellArgs[1].value = h = (XtArgVal) boardHeight + marginH;
2217 shellArgs[4].value = shellArgs[2].value = w;
2218 shellArgs[5].value = shellArgs[3].value = h;
2219 // XtSetValues(shellWidget, &shellArgs[0], 6);
2221 // [HGM] pieces: tailor piece bitmaps to needs of specific variant
2224 for(i=0; i<4; i++) {
2226 for(p=0; p<=(int)WhiteKing; p++)
2227 xpmPieceBitmap[i][p] = xpmPieceBitmap2[i][p]; // defaults
2228 if(gameInfo.variant == VariantShogi) {
2229 xpmPieceBitmap[i][(int)WhiteCannon] = xpmPieceBitmap2[i][(int)WhiteKing+1];
2230 xpmPieceBitmap[i][(int)WhiteNightrider] = xpmPieceBitmap2[i][(int)WhiteKing+2];
2231 xpmPieceBitmap[i][(int)WhiteSilver] = xpmPieceBitmap2[i][(int)WhiteKing+3];
2232 xpmPieceBitmap[i][(int)WhiteGrasshopper] = xpmPieceBitmap2[i][(int)WhiteKing+4];
2233 xpmPieceBitmap[i][(int)WhiteQueen] = xpmPieceBitmap2[i][(int)WhiteLance];
2236 if(gameInfo.variant == VariantGothic) {
2237 xpmPieceBitmap[i][(int)WhiteMarshall] = xpmPieceBitmap2[i][(int)WhiteSilver];
2241 // [HGM] why are thee ximMasks used at all? the ximPieceBitmaps seem to be never used!
2242 for(p=0; p<=(int)WhiteKing; p++)
2243 ximMaskPm[p] = ximMaskPm2[p]; // defaults
2244 if(gameInfo.variant == VariantShogi) {
2245 ximMaskPm[(int)WhiteCannon] = ximMaskPm2[(int)WhiteKing+1];
2246 ximMaskPm[(int)WhiteNightrider] = ximMaskPm2[(int)WhiteKing+2];
2247 ximMaskPm[(int)WhiteSilver] = ximMaskPm2[(int)WhiteKing+3];
2248 ximMaskPm[(int)WhiteGrasshopper] = ximMaskPm2[(int)WhiteKing+4];
2249 ximMaskPm[(int)WhiteQueen] = ximMaskPm2[(int)WhiteLance];
2252 if(gameInfo.variant == VariantGothic) {
2253 ximMaskPm[(int)WhiteMarshall] = ximMaskPm2[i][(int)WhiteSilver];
2259 for(i=0; i<2; i++) {
2261 for(p=0; p<=(int)WhiteKing; p++)
2262 pieceBitmap[i][p] = pieceBitmap2[i][p]; // defaults
2263 if(gameInfo.variant == VariantShogi) {
2264 pieceBitmap[i][(int)WhiteCannon] = pieceBitmap2[i][(int)WhiteKing+1];
2265 pieceBitmap[i][(int)WhiteNightrider] = pieceBitmap2[i][(int)WhiteKing+2];
2266 pieceBitmap[i][(int)WhiteSilver] = pieceBitmap2[i][(int)WhiteKing+3];
2267 pieceBitmap[i][(int)WhiteGrasshopper] = pieceBitmap2[i][(int)WhiteKing+4];
2268 pieceBitmap[i][(int)WhiteQueen] = pieceBitmap2[i][(int)WhiteLance];
2271 if(gameInfo.variant == VariantGothic) {
2272 pieceBitmap[i][(int)WhiteMarshall] = pieceBitmap2[i][(int)WhiteSilver];
2288 int i, j, clockFontPxlSize, coordFontPxlSize, fontPxlSize;
2289 XSetWindowAttributes window_attributes;
2291 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
2292 XrmValue vFrom, vTo;
2293 XtGeometryResult gres;
2296 int forceMono = False;
2299 // [HGM] before anything else, expand any indirection files amongst options
2300 char *argvCopy[1000]; // 1000 seems enough
2301 char newArgs[10000]; // holds actual characters
2304 srandom(time(0)); // [HGM] book: make random truly random
2307 for(i=0; i<argc; i++) {
2308 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2309 //fprintf(stderr, "arg %s\n", argv[i]);
2310 if(argv[i][0] != '@') argvCopy[j++] = argv[i]; else {
2312 FILE *f = fopen(argv[i]+1, "rb");
2313 if(f == NULL) { fprintf(stderr, _("ignore %s\n"), argv[i]); continue; } // do not expand non-existing
2314 argvCopy[j++] = newArgs + k; // get ready for first argument from file
2315 while((c = fgetc(f)) != EOF) { // each line of file inserts 1 argument in the list
2317 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2318 newArgs[k++] = 0; // terminate current arg
2319 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2320 argvCopy[j++] = newArgs + k; // get ready for next
2322 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2335 if(appData.debugMode,1) { // OK, appData is not initialized here yet...
2336 for(i=0; i<argc; i++) fprintf(stderr, "argv[%2d] = '%s'\n", i, argv[i]);
2342 setbuf(stdout, NULL);
2343 setbuf(stderr, NULL);
2346 programName = strrchr(argv[0], '/');
2347 if (programName == NULL)
2348 programName = argv[0];
2353 XtSetLanguageProc(NULL, NULL, NULL);
2354 bindtextdomain(PACKAGE, LOCALEDIR);
2355 textdomain(PACKAGE);
2359 XtAppInitialize(&appContext, "XBoard", shellOptions,
2360 XtNumber(shellOptions),
2361 &argc, argv, xboardResources, NULL, 0);
2363 gtk_init (&argc, &argv);
2365 /* parse glade file */
2367 builder = gtk_builder_new ();
2368 gtk_builder_add_from_file (builder, "gtk-interface.xml", NULL);
2370 GUI_Window = GTK_WIDGET (gtk_builder_get_object (builder, "MainWindow"));
2371 if(!GUI_Window) printf("Error: gtk_builder didn't work!\n");
2372 GUI_Board = GTK_WIDGET (gtk_builder_get_object (builder, "Board"));
2373 if(!GUI_Board) printf("Error: gtk_builder didn't work!\n");
2374 GUI_Whiteclock = GTK_WIDGET (gtk_builder_get_object (builder, "WhiteClock"));
2375 if(!GUI_Whiteclock) printf("Error: gtk_builder didn't work!\n");
2376 GUI_Blackclock = GTK_WIDGET (gtk_builder_get_object (builder, "BlackClock"));
2377 if(!GUI_Blackclock) printf("Error: gtk_builder didn't work!\n");
2379 gtk_builder_connect_signals (builder, NULL);
2380 // don't unref the builder, since we use it to get references to widgets
2381 // g_object_unref (G_OBJECT (builder));
2383 printf("DEBUG:finished building gtk\n");
2384 /* end parse glade file */
2387 fprintf(stderr, _("%s: unrecognized argument %s\n"),
2388 programName, argv[1]);
2389 fprintf(stderr, "Recognized options:\n");
2390 for(i = 0; i < XtNumber(shellOptions); i++) {
2391 j = fprintf(stderr, " %s%s", shellOptions[i].option,
2392 (shellOptions[i].argKind == XrmoptionSepArg
2394 if (i++ < XtNumber(shellOptions)) {
2395 fprintf(stderr, "%*c%s%s\n", 40 - j, ' ',
2396 shellOptions[i].option,
2397 (shellOptions[i].argKind == XrmoptionSepArg
2400 fprintf(stderr, "\n");
2406 if ((chessDir = (char *) getenv("CHESSDIR")) == NULL) {
2409 if (chdir(chessDir) != 0) {
2410 fprintf(stderr, _("%s: can't cd to CHESSDIR: "), programName);
2417 if (p == NULL) p = "/tmp";
2418 i = strlen(p) + strlen("/.xboardXXXXXx.pgn") + 1;
2419 gameCopyFilename = (char*) malloc(i);
2420 gamePasteFilename = (char*) malloc(i);
2421 snprintf(gameCopyFilename,i, "%s/.xboard%05uc.pgn", p, getpid());
2422 snprintf(gamePasteFilename,i, "%s/.xboard%05up.pgn", p, getpid());
2424 XtGetApplicationResources(shellWidget, (XtPointer) &appData,
2425 clientResources, XtNumber(clientResources),
2428 if (appData.debugMode && appData.nameOfDebugFile && strcmp(appData.nameOfDebugFile, "stderr")) {
2429 /* [DM] debug info to file [HGM] make the filename a command-line option, and allow it to remain stderr */
2430 if ((debugFP = fopen(appData.nameOfDebugFile, "w")) == NULL) {
2431 printf(_("Failed to open file '%s'\n"), appData.nameOfDebugFile);
2434 setbuf(debugFP, NULL);
2437 /* [HGM,HR] make sure board size is acceptable */
2438 if(appData.NrFiles > BOARD_SIZE ||
2439 appData.NrRanks > BOARD_SIZE )
2440 DisplayFatalError(_("Recompile with BOARD_SIZE > 12, to support this size"), 0, 2);
2443 /* This feature does not work; animation needs a rewrite */
2444 appData.highlightDragging = FALSE;
2448 xDisplay = XtDisplay(shellWidget);
2449 xScreen = DefaultScreen(xDisplay);
2450 wm_delete_window = XInternAtom(xDisplay, "WM_DELETE_WINDOW", True);
2452 gameInfo.variant = StringToVariant(appData.variant);
2453 InitPosition(FALSE);
2456 * Determine boardSize
2458 gameInfo.boardWidth = gameInfo.boardHeight = 8; // [HGM] boardsize: make sure we start as 8x8
2461 // [HGM] as long as we have not created the possibility to change size while running, start with requested size
2462 gameInfo.boardWidth = appData.NrFiles > 0 ? appData.NrFiles : 8;
2463 gameInfo.boardHeight = appData.NrRanks > 0 ? appData.NrRanks : 8;
2464 gameInfo.holdingsWidth = appData.holdingsSize > 0 ? 2 : 0;
2469 InitDrawingSizes(-1, 0); // [HGM] initsize: make this into a subroutine
2471 if (isdigit(appData.boardSize[0])) {
2472 i = sscanf(appData.boardSize, "%d,%d,%d,%d,%d,%d,%d", &squareSize,
2473 &lineGap, &clockFontPxlSize, &coordFontPxlSize,
2474 &fontPxlSize, &smallLayout, &tinyLayout);
2476 fprintf(stderr, _("%s: bad boardSize syntax %s\n"),
2477 programName, appData.boardSize);
2481 /* Find some defaults; use the nearest known size */
2482 SizeDefaults *szd, *nearest;
2483 int distance = 99999;
2484 nearest = szd = sizeDefaults;
2485 while (szd->name != NULL) {
2486 if (abs(szd->squareSize - squareSize) < distance) {
2488 distance = abs(szd->squareSize - squareSize);
2489 if (distance == 0) break;
2493 if (i < 2) lineGap = nearest->lineGap;
2494 if (i < 3) clockFontPxlSize = nearest->clockFontPxlSize;
2495 if (i < 4) coordFontPxlSize = nearest->coordFontPxlSize;
2496 if (i < 5) fontPxlSize = nearest->fontPxlSize;
2497 if (i < 6) smallLayout = nearest->smallLayout;
2498 if (i < 7) tinyLayout = nearest->tinyLayout;
2501 SizeDefaults *szd = sizeDefaults;
2502 if (*appData.boardSize == NULLCHAR) {
2503 while (DisplayWidth(xDisplay, xScreen) < szd->minScreenSize ||
2504 DisplayHeight(xDisplay, xScreen) < szd->minScreenSize) {
2507 if (szd->name == NULL) szd--;
2509 while (szd->name != NULL &&
2510 StrCaseCmp(szd->name, appData.boardSize) != 0) szd++;
2511 if (szd->name == NULL) {
2512 fprintf(stderr, _("%s: unrecognized boardSize name %s\n"),
2513 programName, appData.boardSize);
2517 squareSize = szd->squareSize;
2518 lineGap = szd->lineGap;
2519 clockFontPxlSize = szd->clockFontPxlSize;
2520 coordFontPxlSize = szd->coordFontPxlSize;
2521 fontPxlSize = szd->fontPxlSize;
2522 smallLayout = szd->smallLayout;
2523 tinyLayout = szd->tinyLayout;
2526 /* Now, using squareSize as a hint, find a good XPM/XIM set size */
2527 if (strlen(appData.pixmapDirectory) > 0) {
2528 p = ExpandPathName(appData.pixmapDirectory);
2530 fprintf(stderr, _("Error expanding path name \"%s\"\n"),
2531 appData.pixmapDirectory);
2534 if (appData.debugMode) {
2535 fprintf(stderr, _("\
2536 XBoard square size (hint): %d\n\
2537 %s fulldir:%s:\n"), squareSize, IMAGE_EXT, p);
2539 squareSize = xpm_closest_to(p, squareSize, IMAGE_EXT);
2540 if (appData.debugMode) {
2541 fprintf(stderr, _("Closest %s size: %d\n"), IMAGE_EXT, squareSize);
2545 /* [HR] height treated separately (hacked) */
2546 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2547 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2548 if (appData.showJail == 1) {
2549 /* Jail on top and bottom */
2550 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2551 XtSetArg(boardArgs[2], XtNheight,
2552 boardHeight + 2*(lineGap + squareSize));
2553 } else if (appData.showJail == 2) {
2555 XtSetArg(boardArgs[1], XtNwidth,
2556 boardWidth + 2*(lineGap + squareSize));
2557 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2560 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2561 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2565 * Determine what fonts to use.
2567 appData.clockFont = FindFont(appData.clockFont, clockFontPxlSize);
2568 clockFontID = XLoadFont(xDisplay, appData.clockFont);
2569 clockFontStruct = XQueryFont(xDisplay, clockFontID);
2570 appData.coordFont = FindFont(appData.coordFont, coordFontPxlSize);
2571 coordFontID = XLoadFont(xDisplay, appData.coordFont);
2572 coordFontStruct = XQueryFont(xDisplay, coordFontID);
2573 appData.font = FindFont(appData.font, fontPxlSize);
2574 countFontID = XLoadFont(xDisplay, appData.coordFont); // [HGM] holdings
2575 countFontStruct = XQueryFont(xDisplay, countFontID);
2576 // appData.font = FindFont(appData.font, fontPxlSize);
2578 xdb = XtDatabase(xDisplay);
2579 XrmPutStringResource(&xdb, "*font", appData.font);
2582 * Detect if there are not enough colors available and adapt.
2584 if (DefaultDepth(xDisplay, xScreen) <= 2) {
2585 appData.monoMode = True;
2588 if (!appData.monoMode) {
2589 vFrom.addr = (caddr_t) appData.lightSquareColor;
2590 vFrom.size = strlen(appData.lightSquareColor);
2591 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2592 if (vTo.addr == NULL) {
2593 appData.monoMode = True;
2596 lightSquareColor = *(Pixel *) vTo.addr;
2599 if (!appData.monoMode) {
2600 vFrom.addr = (caddr_t) appData.darkSquareColor;
2601 vFrom.size = strlen(appData.darkSquareColor);
2602 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2603 if (vTo.addr == NULL) {
2604 appData.monoMode = True;
2607 darkSquareColor = *(Pixel *) vTo.addr;
2610 if (!appData.monoMode) {
2611 vFrom.addr = (caddr_t) appData.whitePieceColor;
2612 vFrom.size = strlen(appData.whitePieceColor);
2613 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2614 if (vTo.addr == NULL) {
2615 appData.monoMode = True;
2618 whitePieceColor = *(Pixel *) vTo.addr;
2621 if (!appData.monoMode) {
2622 vFrom.addr = (caddr_t) appData.blackPieceColor;
2623 vFrom.size = strlen(appData.blackPieceColor);
2624 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2625 if (vTo.addr == NULL) {
2626 appData.monoMode = True;
2629 blackPieceColor = *(Pixel *) vTo.addr;
2633 if (!appData.monoMode) {
2634 vFrom.addr = (caddr_t) appData.highlightSquareColor;
2635 vFrom.size = strlen(appData.highlightSquareColor);
2636 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2637 if (vTo.addr == NULL) {
2638 appData.monoMode = True;
2641 highlightSquareColor = *(Pixel *) vTo.addr;
2645 if (!appData.monoMode) {
2646 vFrom.addr = (caddr_t) appData.premoveHighlightColor;
2647 vFrom.size = strlen(appData.premoveHighlightColor);
2648 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2649 if (vTo.addr == NULL) {
2650 appData.monoMode = True;
2653 premoveHighlightColor = *(Pixel *) vTo.addr;
2658 fprintf(stderr, _("%s: too few colors available; trying monochrome mode\n"),
2661 if (appData.bitmapDirectory == NULL ||
2662 appData.bitmapDirectory[0] == NULLCHAR)
2663 appData.bitmapDirectory = DEF_BITMAP_DIR;
2666 if (appData.lowTimeWarning && !appData.monoMode) {
2667 vFrom.addr = (caddr_t) appData.lowTimeWarningColor;
2668 vFrom.size = strlen(appData.lowTimeWarningColor);
2669 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2670 if (vTo.addr == NULL)
2671 appData.monoMode = True;
2673 lowTimeWarningColor = *(Pixel *) vTo.addr;
2676 if (appData.monoMode && appData.debugMode) {
2677 fprintf(stderr, _("white pixel = 0x%lx, black pixel = 0x%lx\n"),
2678 (unsigned long) XWhitePixel(xDisplay, xScreen),
2679 (unsigned long) XBlackPixel(xDisplay, xScreen));
2682 if (parse_cpair(ColorShout, appData.colorShout) < 0 ||
2683 parse_cpair(ColorSShout, appData.colorSShout) < 0 ||
2684 parse_cpair(ColorChannel1, appData.colorChannel1) < 0 ||
2685 parse_cpair(ColorChannel, appData.colorChannel) < 0 ||
2686 parse_cpair(ColorKibitz, appData.colorKibitz) < 0 ||
2687 parse_cpair(ColorTell, appData.colorTell) < 0 ||
2688 parse_cpair(ColorChallenge, appData.colorChallenge) < 0 ||
2689 parse_cpair(ColorRequest, appData.colorRequest) < 0 ||
2690 parse_cpair(ColorSeek, appData.colorSeek) < 0 ||
2691 parse_cpair(ColorNormal, appData.colorNormal) < 0)
2693 if (appData.colorize) {
2695 _("%s: can't parse color names; disabling colorization\n"),
2698 appData.colorize = FALSE;
2700 textColors[ColorNone].fg = textColors[ColorNone].bg = -1;
2701 textColors[ColorNone].attr = 0;
2703 printf("DEBUG: I'm here 0\n");
2705 // XtAppAddActions(appContext, boardActions, XtNumber(boardActions));
2711 layoutName = "tinyLayout";
2712 } else if (smallLayout) {
2713 layoutName = "smallLayout";
2715 layoutName = "normalLayout";
2717 /* Outer layoutWidget is there only to provide a name for use in
2718 resources that depend on the layout style */
2720 XtCreateManagedWidget(layoutName, formWidgetClass, shellWidget,
2721 layoutArgs, XtNumber(layoutArgs));
2723 XtCreateManagedWidget("form", formWidgetClass, layoutWidget,
2724 formArgs, XtNumber(formArgs));
2725 XtSetArg(args[0], XtNdefaultDistance, &sep);
2726 XtGetValues(formWidget, args, 1);
2729 widgetList[j++] = menuBarWidget = CreateMenuBar(menuBar);
2730 XtSetArg(args[0], XtNtop, XtChainTop);
2731 XtSetArg(args[1], XtNbottom, XtChainTop);
2732 XtSetValues(menuBarWidget, args, 2);
2734 widgetList[j++] = whiteTimerWidget =
2735 XtCreateWidget("whiteTime", labelWidgetClass,
2736 formWidget, timerArgs, XtNumber(timerArgs));
2737 XtSetArg(args[0], XtNfont, clockFontStruct);
2738 XtSetArg(args[1], XtNtop, XtChainTop);
2739 XtSetArg(args[2], XtNbottom, XtChainTop);
2740 XtSetValues(whiteTimerWidget, args, 3);
2742 widgetList[j++] = blackTimerWidget =
2743 XtCreateWidget("blackTime", labelWidgetClass,
2744 formWidget, timerArgs, XtNumber(timerArgs));
2745 XtSetArg(args[0], XtNfont, clockFontStruct);
2746 XtSetArg(args[1], XtNtop, XtChainTop);
2747 XtSetArg(args[2], XtNbottom, XtChainTop);
2748 XtSetValues(blackTimerWidget, args, 3);
2749 printf("DEBUG: I'm here 1\n");
2751 if (appData.titleInWindow) {
2752 widgetList[j++] = titleWidget =
2753 XtCreateWidget("title", labelWidgetClass, formWidget,
2754 titleArgs, XtNumber(titleArgs));
2755 XtSetArg(args[0], XtNtop, XtChainTop);
2756 XtSetArg(args[1], XtNbottom, XtChainTop);
2757 XtSetValues(titleWidget, args, 2);
2760 if (appData.showButtonBar) {
2761 widgetList[j++] = buttonBarWidget = CreateButtonBar(buttonBar);
2762 XtSetArg(args[0], XtNleft, XtChainRight); // [HGM] glue to right window edge
2763 XtSetArg(args[1], XtNright, XtChainRight); // for good run-time sizing
2764 XtSetArg(args[2], XtNtop, XtChainTop);
2765 XtSetArg(args[3], XtNbottom, XtChainTop);
2766 XtSetValues(buttonBarWidget, args, 4);
2769 // widgetList[j++] = messageWidget =
2770 // XtCreateWidget("message", labelWidgetClass, formWidget,
2771 // messageArgs, XtNumber(messageArgs));
2772 // XtSetArg(args[0], XtNtop, XtChainTop);
2773 // XtSetArg(args[1], XtNbottom, XtChainTop);
2774 // XtSetValues(messageWidget, args, 2);
2776 // widgetList[j++] = boardWidget =
2777 // XtCreateWidget("board", widgetClass, formWidget, boardArgs,
2778 // XtNumber(boardArgs));
2780 // XtManageChildren(widgetList, j);
2782 // timerWidth = (boardWidth - sep) / 2;
2783 // XtSetArg(args[0], XtNwidth, timerWidth);
2784 // XtSetValues(whiteTimerWidget, args, 1);
2785 // XtSetValues(blackTimerWidget, args, 1);
2787 // XtSetArg(args[0], XtNbackground, &timerBackgroundPixel);
2788 // XtSetArg(args[1], XtNforeground, &timerForegroundPixel);
2789 // XtGetValues(whiteTimerWidget, args, 2);
2791 // if (appData.showButtonBar) {
2792 // XtSetArg(args[0], XtNbackground, &buttonBackgroundPixel);
2793 // XtSetArg(args[1], XtNforeground, &buttonForegroundPixel);
2794 // XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
2799 * gtk set properties of widgets
2802 /* set board size */
2803 gtk_widget_set_size_request(GTK_WIDGET(GUI_Board),
2804 boardWidth,boardHeight);
2806 /* end gtk set properties of widgets */
2808 printf("DEBUG: made it.\n");
2811 * formWidget uses these constraints but they are stored
2815 // XtSetArg(args[i], XtNfromHoriz, 0); i++;
2816 // XtSetValues(menuBarWidget, args, i);
2817 // if (appData.titleInWindow) {
2818 // if (smallLayout) {
2819 // printf("DEBUG: made it a.\n");
2821 // XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2822 // XtSetValues(whiteTimerWidget, args, i);
2824 // XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2825 // XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2826 // XtSetValues(blackTimerWidget, args, i);
2828 // XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2829 // XtSetArg(args[i], XtNjustify, XtJustifyLeft); i++;
2830 // XtSetValues(titleWidget, args, i);
2832 // XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2833 // XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2834 // XtSetValues(messageWidget, args, i);
2835 // if (appData.showButtonBar) {
2837 // XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2838 // XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2839 // XtSetValues(buttonBarWidget, args, i);
2842 // printf("DEBUG: made it b.\n");
2844 // XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2845 // XtSetValues(whiteTimerWidget, args, i);
2847 // XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2848 // XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2849 // XtSetValues(blackTimerWidget, args, i);
2851 // XtSetArg(args[i], XtNfromHoriz, menuBarWidget); i++;
2852 // XtSetValues(titleWidget, args, i);
2854 // XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2855 // XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2856 // XtSetValues(messageWidget, args, i);
2857 // if (appData.showButtonBar) {
2859 // XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2860 // XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2861 // XtSetValues(buttonBarWidget, args, i);
2864 // } else { printf("DEBUG: made it c.\n");
2867 // XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2868 // XtSetValues(whiteTimerWidget, args, i);
2870 // XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2871 // XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2872 // XtSetValues(blackTimerWidget, args, i);
2874 // XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2875 // XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2876 // XtSetValues(messageWidget, args, i);
2877 // if (appData.showButtonBar) {
2879 // XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2880 // XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2881 // XtSetValues(buttonBarWidget, args, i);
2884 // printf("DEBUG: made it 1.\n");
2886 // XtSetArg(args[0], XtNfromVert, messageWidget);
2887 // XtSetArg(args[1], XtNtop, XtChainTop);
2888 // XtSetArg(args[2], XtNbottom, XtChainBottom);
2889 // XtSetArg(args[3], XtNleft, XtChainLeft);
2890 // XtSetArg(args[4], XtNright, XtChainRight);
2891 // XtSetValues(boardWidget, args, 5);
2893 // XtRealizeWidget(shellWidget);
2895 printf("DEBUG: made it 2.\n");
2898 * Correct the width of the message and title widgets.
2899 * It is not known why some systems need the extra fudge term.
2900 * The value "2" is probably larger than needed.
2902 // XawFormDoLayout(formWidget, False);
2904 #define WIDTH_FUDGE 2
2906 // XtSetArg(args[i], XtNborderWidth, &bor); i++;
2907 // XtSetArg(args[i], XtNheight, &h); i++;
2908 // XtGetValues(messageWidget, args, i);
2909 if (appData.showButtonBar) {
2911 // XtSetArg(args[i], XtNwidth, &w); i++;
2912 // XtGetValues(buttonBarWidget, args, i);
2913 // w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2915 // w = boardWidth - 2*bor + 1; /*!! +1 compensates for kludge below */
2918 // gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2919 if (gres != XtGeometryYes && appData.debugMode) {
2920 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2921 programName, gres, w, h, wr, hr);
2924 /* !! Horrible hack to work around bug in XFree86 4.0.1 (X11R6.4.3) */
2925 /* The size used for the child widget in layout lags one resize behind
2926 its true size, so we resize a second time, 1 pixel smaller. Yeech! */
2928 // gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2929 if (gres != XtGeometryYes && appData.debugMode) {
2930 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2931 programName, gres, w, h, wr, hr);
2934 // XtSetArg(args[0], XtNleft, XtChainLeft); // [HGM] glue ends for good run-time sizing
2935 // XtSetArg(args[1], XtNright, XtChainRight);
2936 // XtSetValues(messageWidget, args, 2);
2938 if (appData.titleInWindow) {
2940 // XtSetArg(args[i], XtNborderWidth, &bor); i++;
2941 // XtSetArg(args[i], XtNheight, &h); i++;
2942 // XtGetValues(titleWidget, args, i);
2944 w = boardWidth - 2*bor;
2946 // XtSetArg(args[0], XtNwidth, &w);
2947 // XtGetValues(menuBarWidget, args, 1);
2948 // w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2951 // gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
2952 if (gres != XtGeometryYes && appData.debugMode) {
2954 _("%s: titleWidget geometry error %d %d %d %d %d\n"),
2955 programName, gres, w, h, wr, hr);
2958 // XawFormDoLayout(formWidget, True);
2960 // xBoardWindow = XtWindow(boardWidget);
2962 // [HGM] it seems the layout code ends here, but perhaps the color stuff is size independent and would
2963 // not need to go into InitDrawingSizes().
2966 if (appData.alwaysPromoteToQueen) {
2967 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Always Queen")),TRUE);
2969 if (appData.animateDragging) {
2970 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Animate Dragging")),TRUE);
2972 if (appData.animate) {
2973 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Animate Moving")),TRUE);
2975 if (appData.autoComment) {
2976 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Comment")),TRUE);
2978 if (appData.autoCallFlag) {
2979 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Flag")),TRUE);
2981 if (appData.autoFlipView) {
2982 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Flip View")),TRUE);
2984 if (appData.autoObserve) {
2985 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Observe")),TRUE);
2987 if (appData.autoRaiseBoard) {
2988 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Raise Board")),TRUE);
2990 if (appData.autoSaveGames) {
2991 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Save")),TRUE);
2993 if (appData.saveGameFile[0] != NULLCHAR) {
2994 /* Can't turn this off from menu */
2995 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Save")),TRUE);
2996 gtk_action_set_sensitive(GTK_ACTION (gtk_builder_get_object (builder, "menuOptions.Auto Save")),FALSE);
2998 if (appData.blindfold) {
2999 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Blindfold")),TRUE);
3001 if (appData.flashCount > 0) {
3002 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Flash Moves")),TRUE);
3004 if (appData.getMoveList) {
3005 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Get Move List")),TRUE);
3008 if (appData.highlightDragging) {
3009 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Highlight Dragging")),TRUE);
3012 if (appData.highlightLastMove) {
3013 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Highlight Last Move")),TRUE);
3015 if (appData.icsAlarm) {
3016 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.ICS Alarm")),TRUE);
3018 if (appData.ringBellAfterMoves) {
3019 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Move Sound")),TRUE);
3021 if (appData.oldSaveStyle) {
3022 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Old Save Style")),TRUE);
3024 if (appData.periodicUpdates) {
3025 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Periodic Updates")),TRUE);
3027 if (appData.ponderNextMove) {
3028 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Ponder Next Move")),TRUE);
3030 if (appData.popupExitMessage) {
3031 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Popup Exit Message")),TRUE);
3033 if (appData.popupMoveErrors) {
3034 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Popup Move Errors")),TRUE);
3036 if (appData.premove) {
3037 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Premove")),TRUE);
3039 if (appData.quietPlay) {
3040 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Quit Play")),TRUE);
3042 if (appData.showCoords) {
3043 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Show Coords")),TRUE);
3045 if (appData.showThinking) {
3046 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Show Thinking")),TRUE);
3048 if (appData.testLegality) {
3049 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Test Legality")),TRUE);
3055 // ReadBitmap(&wIconPixmap, "icon_white.bm",
3056 // icon_white_bits, icon_white_width, icon_white_height);
3057 // ReadBitmap(&bIconPixmap, "icon_black.bm",
3058 // icon_black_bits, icon_black_width, icon_black_height);
3059 // iconPixmap = wIconPixmap;
3061 // XtSetArg(args[i], XtNiconPixmap, iconPixmap); i++;
3062 // XtSetValues(shellWidget, args, i);
3065 printf("DEBUG: creating svgs.\n");
3067 /* load square colors */
3068 SVGLightSquare = load_pixbuf("svg/LightSquare.svg");
3069 SVGDarkSquare = load_pixbuf("svg/DarkSquare.svg");
3070 SVGNeutralSquare = load_pixbuf("svg/NeutralSquare.svg");
3072 /* use two icons to indicate if it is white's or black's turn */
3073 WhiteIcon = load_pixbuf("svg/icon_white.svg");
3074 BlackIcon = load_pixbuf("svg/icon_black.svg");
3075 WindowIcon = WhiteIcon;
3076 gtk_window_set_icon(GTK_WINDOW(GUI_Window),WindowIcon);
3078 /* do resizing to a fixed aspect ratio */
3080 hints.min_aspect = 0.8;
3081 hints.max_aspect = 0.8;
3082 gtk_window_set_geometry_hints (GTK_WINDOW (GUI_Window),
3083 GTK_WIDGET (GUI_Window),
3087 /* realize window */
3088 gtk_widget_show (GUI_Window);
3096 if (appData.animate || appData.animateDragging)
3099 printf("DEBUG: created stuff.\n");
3102 // XtAugmentTranslations(formWidget,
3103 // XtParseTranslationTable(globalTranslations));
3104 // XtAugmentTranslations(boardWidget,
3105 // XtParseTranslationTable(boardTranslations));
3106 // XtAugmentTranslations(whiteTimerWidget,
3107 // XtParseTranslationTable(whiteTranslations));
3108 // XtAugmentTranslations(blackTimerWidget,
3109 // XtParseTranslationTable(blackTranslations));
3113 printf("DEBUG: back end initiated.\n");
3115 if (errorExitStatus == -1) {
3116 if (appData.icsActive) {
3117 /* We now wait until we see "login:" from the ICS before
3118 sending the logon script (problems with timestamp otherwise) */
3119 /*ICSInitScript();*/
3120 if (appData.icsInputBox) ICSInputBoxPopUp();
3123 signal(SIGINT, IntSigHandler);
3124 signal(SIGTERM, IntSigHandler);
3125 if (*appData.cmailGameName != NULLCHAR) {
3126 signal(SIGUSR1, CmailSigHandler);
3129 gameInfo.boardWidth = 0; // [HGM] pieces: kludge to ensure InitPosition() calls InitDrawingSizes()
3133 * Create a cursor for the board widget.
3134 * (This needs to be called after the window has been created to have access to board-window)
3137 BoardCursor = gdk_cursor_new(GDK_HAND2);
3138 gdk_window_set_cursor(GUI_Board->window, BoardCursor);
3139 gdk_cursor_destroy(BoardCursor);
3142 printf("DEBUG: going into main.\n");
3146 if (appData.debugMode) fclose(debugFP); // [DM] debug
3153 if (appData.icsActive && oldICSInteractionTitle != NULL) {
3154 DisplayIcsInteractionTitle(oldICSInteractionTitle);
3156 unlink(gameCopyFilename);
3157 unlink(gamePasteFilename);
3168 CmailSigHandler(sig)
3174 signal(SIGUSR1, SIG_IGN); /* suspend handler */
3176 /* Activate call-back function CmailSigHandlerCallBack() */
3177 OutputToProcess(cmailPR, (char *)(&dummy), sizeof(int), &error);
3179 signal(SIGUSR1, CmailSigHandler); /* re-activate handler */
3183 CmailSigHandlerCallBack(isr, closure, message, count, error)
3191 ReloadCmailMsgEvent(TRUE); /* Reload cmail msg */
3193 /**** end signal code ****/
3203 f = fopen(appData.icsLogon, "r");
3209 strcat(buf, appData.icsLogon);
3210 f = fopen(buf, "r");
3214 ProcessICSInitScript(f);
3221 EditCommentPopDown();
3232 SetMenuEnables(enab)
3237 if (!builder) return;
3238 while (enab->name != NULL) {
3239 o = gtk_builder_get_object(builder, enab->name);
3240 if(GTK_IS_WIDGET(o))
3241 gtk_widget_set_sensitive(GTK_WIDGET (o),enab->value);
3244 if(GTK_IS_ACTION(o))
3245 gtk_action_set_sensitive(GTK_ACTION (o),enab->value);
3247 DisplayError(enab->name, 0);
3253 Enables icsEnables[] = {
3254 { "menuFile.Mail Move", False },
3255 { "menuFile.Reload CMail Message", False },
3256 { "menuMode.Machine Black", False },
3257 { "menuMode.Machine White", False },
3258 { "menuMode.Analysis Mode", False },
3259 { "menuMode.Analyze File", False },
3260 { "menuMode.Two Machines", False },
3262 { "menuHelp.Hint", False },
3263 { "menuHelp.Book", False },
3264 { "menuStep.Move Now", False },
3265 { "menuOptions.Periodic Updates", False },
3266 { "menuOptions.Hide Thinking", False },
3267 { "menuOptions.Ponder Next Move", False },
3272 Enables ncpEnables[] = {
3273 { "menuFile.Mail Move", False },
3274 { "menuFile.Reload CMail Message", False },
3275 { "menuMode.Machine White", False },
3276 { "menuMode.Machine Black", False },
3277 { "menuMode.Analysis Mode", False },
3278 { "menuMode.Analyze File", False },
3279 { "menuMode.Two Machines", False },
3280 { "menuMode.ICS Client", False },
3281 { "menuMode.ICS Input Box", False },
3282 { "Action", False },
3283 { "menuStep.Revert", False },
3284 { "menuStep.Move Now", False },
3285 { "menuStep.Retract Move", False },
3286 { "menuOptions.Auto Comment", False },
3287 { "menuOptions.Auto Flag", False },
3288 { "menuOptions.Auto Flip View", False },
3289 { "menuOptions.Auto Observe", False },
3290 { "menuOptions.Auto Raise Board", False },
3291 { "menuOptions.Get Move List", False },
3292 { "menuOptions.ICS Alarm", False },
3293 { "menuOptions.Move Sound", False },
3294 { "menuOptions.Quiet Play", False },
3295 { "menuOptions.Hide Thinking", False },
3296 { "menuOptions.Periodic Updates", False },
3297 { "menuOptions.Ponder Next Move", False },
3298 { "menuHelp.Hint", False },
3299 { "menuHelp.Book", False },
3303 Enables gnuEnables[] = {
3304 { "menuMode.ICS Client", False },
3305 { "menuMode.ICS Input Box", False },
3306 { "menuAction.Accept", False },
3307 { "menuAction.Decline", False },
3308 { "menuAction.Rematch", False },
3309 { "menuAction.Adjourn", False },
3310 { "menuAction.Stop Examining", False },
3311 { "menuAction.Stop Observing", False },
3312 { "menuStep.Revert", False },
3313 { "menuOptions.Auto Comment", False },
3314 { "menuOptions.Auto Observe", False },
3315 { "menuOptions.Auto Raise Board", False },
3316 { "menuOptions.Get Move List", False },
3317 { "menuOptions.Premove", False },
3318 { "menuOptions.Quiet Play", False },
3320 /* The next two options rely on SetCmailMode being called *after* */
3321 /* SetGNUMode so that when GNU is being used to give hints these */
3322 /* menu options are still available */
3324 { "menuFile.Mail Move", False },
3325 { "menuFile.Reload CMail Message", False },
3329 Enables cmailEnables[] = {
3331 { "menuAction.Call Flag", False },
3332 { "menuAction.Draw", True },
3333 { "menuAction.Adjourn", False },
3334 { "menuAction.Abort", False },
3335 { "menuAction.Stop Observing", False },
3336 { "menuAction.Stop Examining", False },
3337 { "menuFile.Mail Move", True },
3338 { "menuFile.Reload CMail Message", True },
3342 Enables trainingOnEnables[] = {
3343 { "menuMode.Edit Comment", False },
3344 { "menuMode.Pause", False },
3345 { "menuStep.Forward", False },
3346 { "menuStep.Backward", False },
3347 { "menuStep.Forward to End", False },
3348 { "menuStep.Back to Start", False },
3349 { "menuStep.Move Now", False },
3350 { "menuStep.Truncate Game", False },
3354 Enables trainingOffEnables[] = {
3355 { "menuMode.Edit Comment", True },
3356 { "menuMode.Pause", True },
3357 { "menuStep.Forward", True },
3358 { "menuStep.Backward", True },
3359 { "menuStep.Forward to End", True },
3360 { "menuStep.Back to Start", True },
3361 { "menuStep.Move Now", True },
3362 { "menuStep.Truncate Game", True },
3366 Enables machineThinkingEnables[] = {
3367 { "menuFile.Load Game", False },
3368 { "menuFile.Load Next Game", False },
3369 { "menuFile.Load Previous Game", False },
3370 { "menuFile.Reload Same Game", False },
3371 { "menuFile.Paste Game", False },
3372 { "menuFile.Load Position", False },
3373 { "menuFile.Load Next Position", False },
3374 { "menuFile.Load Previous Position", False },
3375 { "menuFile.Reload Same Position", False },
3376 { "menuFile.Paste Position", False },
3377 { "menuMode.Machine White", False },
3378 { "menuMode.Machine Black", False },
3379 { "menuMode.Two Machines", False },
3380 { "menuStep.Retract Move", False },
3384 Enables userThinkingEnables[] = {
3385 { "menuFile.Load Game", True },
3386 { "menuFile.Load Next Game", True },
3387 { "menuFile.Load Previous Game", True },
3388 { "menuFile.Reload Same Game", True },
3389 { "menuFile.Paste Game", True },
3390 { "menuFile.Load Position", True },
3391 { "menuFile.Load Next Position", True },
3392 { "menuFile.Load Previous Position", True },
3393 { "menuFile.Reload Same Position", True },
3394 { "menuFile.Paste Position", True },
3395 { "menuMode.Machine White", True },
3396 { "menuMode.Machine Black", True },
3397 { "menuMode.Two Machines", True },
3398 { "menuStep.Retract Move", True },
3404 SetMenuEnables(icsEnables);
3407 if (appData.zippyPlay && !appData.noChessProgram) /* [DM] icsEngineAnalyze */
3408 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Analysis Mode"), True);
3415 SetMenuEnables(ncpEnables);
3421 SetMenuEnables(gnuEnables);
3427 SetMenuEnables(cmailEnables);
3433 SetMenuEnables(trainingOnEnables);
3434 if (appData.showButtonBar) {
3435 XtSetSensitive(buttonBarWidget, False);
3441 SetTrainingModeOff()
3443 SetMenuEnables(trainingOffEnables);
3444 if (appData.showButtonBar) {
3445 XtSetSensitive(buttonBarWidget, True);
3450 SetUserThinkingEnables()
3452 if (appData.noChessProgram) return;
3453 SetMenuEnables(userThinkingEnables);
3457 SetMachineThinkingEnables()
3459 if (appData.noChessProgram) return;
3460 SetMenuEnables(machineThinkingEnables);
3462 case MachinePlaysBlack:
3463 case MachinePlaysWhite:
3464 case TwoMachinesPlay:
3465 XtSetSensitive(XtNameToWidget(menuBarWidget,
3466 ModeToWidgetName(gameMode)), True);
3473 #define Abs(n) ((n)<0 ? -(n) : (n))
3476 * Find a font that matches "pattern" that is as close as
3477 * possible to the targetPxlSize. Prefer fonts that are k
3478 * pixels smaller to fonts that are k pixels larger. The
3479 * pattern must be in the X Consortium standard format,
3480 * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".
3481 * The return value should be freed with XtFree when no
3484 char *FindFont(pattern, targetPxlSize)
3488 char **fonts, *p, *best, *scalable, *scalableTail;
3489 int i, j, nfonts, minerr, err, pxlSize;
3492 char **missing_list;
3494 char *def_string, *base_fnt_lst, strInt[3];
3496 XFontStruct **fnt_list;
3498 base_fnt_lst = calloc(1, strlen(pattern) + 3);
3499 sprintf(strInt, "%d", targetPxlSize);
3500 p = strstr(pattern, "--");
3501 strncpy(base_fnt_lst, pattern, p - pattern + 2);
3502 strcat(base_fnt_lst, strInt);
3503 strcat(base_fnt_lst, strchr(p + 2, '-'));
3505 if ((fntSet = XCreateFontSet(xDisplay,
3509 &def_string)) == NULL) {
3511 fprintf(stderr, _("Unable to create font set.\n"));
3515 nfonts = XFontsOfFontSet(fntSet, &fnt_list, &fonts);
3517 fonts = XListFonts(xDisplay, pattern, 999999, &nfonts);
3519 fprintf(stderr, _("%s: no fonts match pattern %s\n"),
3520 programName, pattern);
3528 for (i=0; i<nfonts; i++) {
3531 if (*p != '-') continue;
3533 if (*p == NULLCHAR) break;
3534 if (*p++ == '-') j++;
3536 if (j < 7) continue;
3539 scalable = fonts[i];
3542 err = pxlSize - targetPxlSize;
3543 if (Abs(err) < Abs(minerr) ||
3544 (minerr > 0 && err < 0 && -err == minerr)) {
3550 if (scalable && Abs(minerr) > appData.fontSizeTolerance) {
3551 /* If the error is too big and there is a scalable font,
3552 use the scalable font. */
3553 int headlen = scalableTail - scalable;
3554 p = (char *) XtMalloc(strlen(scalable) + 10);
3555 while (isdigit(*scalableTail)) scalableTail++;
3556 sprintf(p, "%.*s%d%s", headlen, scalable, targetPxlSize, scalableTail);
3558 p = (char *) XtMalloc(strlen(best) + 1);
3561 if (appData.debugMode) {
3562 fprintf(debugFP, _("resolved %s at pixel size %d\n to %s\n"),
3563 pattern, targetPxlSize, p);
3566 if (missing_count > 0)
3567 XFreeStringList(missing_list);
3568 XFreeFontSet(xDisplay, fntSet);
3570 XFreeFontNames(fonts);
3577 XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
3578 | GCBackground | GCFunction | GCPlaneMask;
3579 XGCValues gc_values;
3582 gc_values.plane_mask = AllPlanes;
3583 gc_values.line_width = lineGap;
3584 gc_values.line_style = LineSolid;
3585 gc_values.function = GXcopy;
3587 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3588 gc_values.background = XBlackPixel(xDisplay, xScreen);
3589 lineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3591 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3592 gc_values.background = XWhitePixel(xDisplay, xScreen);
3593 coordGC = XtGetGC(shellWidget, value_mask, &gc_values);
3594 XSetFont(xDisplay, coordGC, coordFontID);
3596 // [HGM] make font for holdings counts (white on black0
3597 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3598 gc_values.background = XBlackPixel(xDisplay, xScreen);
3599 countGC = XtGetGC(shellWidget, value_mask, &gc_values);
3600 XSetFont(xDisplay, countGC, countFontID);
3602 if (appData.monoMode) {
3603 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3604 gc_values.background = XWhitePixel(xDisplay, xScreen);
3605 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3607 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3608 gc_values.background = XBlackPixel(xDisplay, xScreen);
3609 lightSquareGC = wbPieceGC
3610 = XtGetGC(shellWidget, value_mask, &gc_values);
3612 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3613 gc_values.background = XWhitePixel(xDisplay, xScreen);
3614 darkSquareGC = bwPieceGC
3615 = XtGetGC(shellWidget, value_mask, &gc_values);
3617 if (DefaultDepth(xDisplay, xScreen) == 1) {
3618 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
3619 gc_values.function = GXcopyInverted;
3620 copyInvertedGC = XtGetGC(shellWidget, value_mask, &gc_values);
3621 gc_values.function = GXcopy;
3622 if (XBlackPixel(xDisplay, xScreen) == 1) {
3623 bwPieceGC = darkSquareGC;
3624 wbPieceGC = copyInvertedGC;
3626 bwPieceGC = copyInvertedGC;
3627 wbPieceGC = lightSquareGC;
3631 gc_values.foreground = highlightSquareColor;
3632 gc_values.background = highlightSquareColor;
3633 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3635 gc_values.foreground = premoveHighlightColor;
3636 gc_values.background = premoveHighlightColor;
3637 prelineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3639 gc_values.foreground = lightSquareColor;
3640 gc_values.background = darkSquareColor;
3641 lightSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3643 gc_values.foreground = darkSquareColor;
3644 gc_values.background = lightSquareColor;
3645 darkSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3647 gc_values.foreground = jailSquareColor;
3648 gc_values.background = jailSquareColor;
3649 jailSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3651 gc_values.foreground = whitePieceColor;
3652 gc_values.background = darkSquareColor;
3653 wdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3655 gc_values.foreground = whitePieceColor;
3656 gc_values.background = lightSquareColor;
3657 wlPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3659 gc_values.foreground = whitePieceColor;
3660 gc_values.background = jailSquareColor;
3661 wjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3663 gc_values.foreground = blackPieceColor;
3664 gc_values.background = darkSquareColor;
3665 bdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3667 gc_values.foreground = blackPieceColor;
3668 gc_values.background = lightSquareColor;
3669 blPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3671 gc_values.foreground = blackPieceColor;
3672 gc_values.background = jailSquareColor;
3673 bjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3680 WhitePawn, WhiteKnight, WhiteBishop, WhiteRook, WhiteQueen, WhiteKing,
3681 BlackPawn, BlackKnight, BlackBishop, BlackRook, BlackQueen, BlackKing,
3684 SVGpieces[WhitePawn] = load_pixbuf("svg/WhitePawn.svg");
3685 SVGpieces[WhiteKnight] = load_pixbuf("svg/WhiteKnight.svg");
3686 SVGpieces[WhiteBishop] = load_pixbuf("svg/WhiteBishop.svg");
3687 SVGpieces[WhiteRook] = load_pixbuf("svg/WhiteRook.svg");
3688 SVGpieces[WhiteQueen] = load_pixbuf("svg/WhiteQueen.svg");
3689 SVGpieces[WhiteKing] = load_pixbuf("svg/WhiteKing.svg");
3691 SVGpieces[BlackPawn] = load_pixbuf("svg/BlackPawn.svg");
3692 SVGpieces[BlackKnight] = load_pixbuf("svg/BlackKnight.svg");
3693 SVGpieces[BlackBishop] = load_pixbuf("svg/BlackBishop.svg");
3694 SVGpieces[BlackRook] = load_pixbuf("svg/BlackRook.svg");
3695 SVGpieces[BlackQueen] = load_pixbuf("svg/BlackQueen.svg");
3696 SVGpieces[BlackKing] = load_pixbuf("svg/BlackKing.svg");
3706 if (lineGap == 0) return;
3708 /* [HR] Split this into 2 loops for non-square boards. */
3710 for (i = 0; i < BOARD_HEIGHT + 1; i++) {
3711 gridSegments[i].x1 = 0;
3712 gridSegments[i].x2 =
3713 lineGap + BOARD_WIDTH * (squareSize + lineGap);
3714 gridSegments[i].y1 = gridSegments[i].y2
3715 = lineGap / 2 + (i * (squareSize + lineGap));
3718 for (j = 0; j < BOARD_WIDTH + 1; j++) {
3719 gridSegments[j + i].y1 = 0;
3720 gridSegments[j + i].y2 =
3721 lineGap + BOARD_HEIGHT * (squareSize + lineGap);
3722 gridSegments[j + i].x1 = gridSegments[j + i].x2
3723 = lineGap / 2 + (j * (squareSize + lineGap));
3727 static void MenuBarSelect(w, addr, index)
3732 XtActionProc proc = (XtActionProc) addr;
3734 (proc)(NULL, NULL, NULL, NULL);
3737 void CreateMenuBarPopup(parent, name, mb)
3747 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3750 XtSetArg(args[j], XtNleftMargin, 20); j++;
3751 XtSetArg(args[j], XtNrightMargin, 20); j++;
3753 while (mi->string != NULL) {
3754 if (strcmp(mi->string, "----") == 0) {
3755 entry = XtCreateManagedWidget(mi->string, smeLineObjectClass,
3758 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string)));
3759 entry = XtCreateManagedWidget(mi->string, smeBSBObjectClass,
3761 XtAddCallback(entry, XtNcallback,
3762 (XtCallbackProc) MenuBarSelect,
3763 (caddr_t) mi->proc);
3769 Widget CreateMenuBar(mb)
3773 Widget anchor, menuBar;
3775 char menuName[MSG_SIZ];
3778 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
3779 XtSetArg(args[j], XtNvSpace, 0); j++;
3780 XtSetArg(args[j], XtNborderWidth, 0); j++;
3781 menuBar = XtCreateWidget("menuBar", boxWidgetClass,
3782 formWidget, args, j);
3784 while (mb->name != NULL) {
3785 strcpy(menuName, "menu");
3786 strcat(menuName, mb->name);
3788 XtSetArg(args[j], XtNmenuName, XtNewString(menuName)); j++;
3791 shortName[0] = _(mb->name)[0];
3792 shortName[1] = NULLCHAR;
3793 XtSetArg(args[j], XtNlabel, XtNewString(shortName)); j++;
3796 XtSetArg(args[j], XtNlabel, XtNewString(_(mb->name))); j++;
3799 XtSetArg(args[j], XtNborderWidth, 0); j++;
3800 anchor = XtCreateManagedWidget(mb->name, menuButtonWidgetClass,
3802 CreateMenuBarPopup(menuBar, menuName, mb);
3808 Widget CreateButtonBar(mi)
3812 Widget button, buttonBar;
3816 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
3818 XtSetArg(args[j], XtNhSpace, 0); j++;
3820 XtSetArg(args[j], XtNborderWidth, 0); j++;
3821 XtSetArg(args[j], XtNvSpace, 0); j++;
3822 buttonBar = XtCreateWidget("buttonBar", boxWidgetClass,
3823 formWidget, args, j);
3825 while (mi->string != NULL) {
3828 XtSetArg(args[j], XtNinternalWidth, 2); j++;
3829 XtSetArg(args[j], XtNborderWidth, 0); j++;
3831 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string))); j++;
3832 button = XtCreateManagedWidget(mi->string, commandWidgetClass,
3833 buttonBar, args, j);
3834 XtAddCallback(button, XtNcallback,
3835 (XtCallbackProc) MenuBarSelect,
3836 (caddr_t) mi->proc);
3843 CreatePieceMenu(name, color)
3850 ChessSquare selection;
3852 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3853 boardWidget, args, 0);
3855 for (i = 0; i < PIECE_MENU_SIZE; i++) {
3856 String item = pieceMenuStrings[color][i];
3858 if (strcmp(item, "----") == 0) {
3859 entry = XtCreateManagedWidget(item, smeLineObjectClass,
3862 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
3863 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3865 selection = pieceMenuTranslation[color][i];
3866 XtAddCallback(entry, XtNcallback,
3867 (XtCallbackProc) PieceMenuSelect,
3868 (caddr_t) selection);
3869 if (selection == WhitePawn || selection == BlackPawn) {
3870 XtSetArg(args[0], XtNpopupOnEntry, entry);
3871 XtSetValues(menu, args, 1);
3884 ChessSquare selection;
3886 // whitePieceMenu = CreatePieceMenu("menuW", 0);
3887 // blackPieceMenu = CreatePieceMenu("menuB", 1);
3889 // XtRegisterGrabAction(PieceMenuPopup, True,
3890 // (unsigned)(ButtonPressMask|ButtonReleaseMask),
3891 // GrabModeAsync, GrabModeAsync);
3893 // XtSetArg(args[0], XtNlabel, _("Drop"));
3894 // dropMenu = XtCreatePopupShell("menuD", simpleMenuWidgetClass,
3895 // boardWidget, args, 1);
3896 // for (i = 0; i < DROP_MENU_SIZE; i++) {
3897 // String item = dropMenuStrings[i];
3899 // if (strcmp(item, "----") == 0) {
3900 // entry = XtCreateManagedWidget(item, smeLineObjectClass,
3901 // dropMenu, NULL, 0);
3903 // XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
3904 // entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3905 // dropMenu, args, 1);
3906 // selection = dropMenuTranslation[i];
3907 // XtAddCallback(entry, XtNcallback,
3908 // (XtCallbackProc) DropMenuSelect,
3909 // (caddr_t) selection);
3914 void SetupDropMenu()
3922 for (i=0; i<sizeof(dmEnables)/sizeof(DropMenuEnables); i++) {
3923 entry = XtNameToWidget(dropMenu, dmEnables[i].widget);
3924 p = strchr(gameMode == IcsPlayingWhite ? white_holding : black_holding,
3925 dmEnables[i].piece);
3926 XtSetSensitive(entry, p != NULL || !appData.testLegality
3927 /*!!temp:*/ || (gameInfo.variant == VariantCrazyhouse
3928 && !appData.icsActive));
3930 while (p && *p++ == dmEnables[i].piece) count++;
3931 snprintf(label, sizeof(label), "%s %d", dmEnables[i].widget, count);
3933 XtSetArg(args[j], XtNlabel, label); j++;
3934 XtSetValues(entry, args, j);
3938 void PieceMenuPopup(w, event, params, num_params)
3942 Cardinal *num_params;
3945 if (event->type != ButtonPress) return;
3946 if (errorUp) ErrorPopDown();
3950 whichMenu = params[0];
3952 case IcsPlayingWhite:
3953 case IcsPlayingBlack:
3955 case MachinePlaysWhite:
3956 case MachinePlaysBlack:
3957 if (appData.testLegality &&
3958 gameInfo.variant != VariantBughouse &&
3959 gameInfo.variant != VariantCrazyhouse) return;
3961 whichMenu = "menuD";
3967 if (((pmFromX = EventToSquare(event->xbutton.x, BOARD_WIDTH)) < 0) ||
3968 ((pmFromY = EventToSquare(event->xbutton.y, BOARD_HEIGHT)) < 0)) {
3969 pmFromX = pmFromY = -1;
3973 pmFromX = BOARD_WIDTH - 1 - pmFromX;
3975 pmFromY = BOARD_HEIGHT - 1 - pmFromY;
3977 XtPopupSpringLoaded(XtNameToWidget(boardWidget, whichMenu));
3980 static void PieceMenuSelect(w, piece, junk)
3985 if (pmFromX < 0 || pmFromY < 0) return;
3986 EditPositionMenuEvent(piece, pmFromX, pmFromY);
3989 static void DropMenuSelect(w, piece, junk)
3994 if (pmFromX < 0 || pmFromY < 0) return;
3995 DropMenuEvent(piece, pmFromX, pmFromY);
3998 void WhiteClock(w, event, prms, nprms)
4004 if (gameMode == EditPosition || gameMode == IcsExamining) {
4005 SetWhiteToPlayEvent();
4006 } else if (gameMode == IcsPlayingBlack || gameMode == MachinePlaysWhite) {
4011 void BlackClock(w, event, prms, nprms)
4017 if (gameMode == EditPosition || gameMode == IcsExamining) {
4018 SetBlackToPlayEvent();
4019 } else if (gameMode == IcsPlayingWhite || gameMode == MachinePlaysBlack) {
4026 * If the user selects on a border boundary, return -1; if off the board,
4027 * return -2. Otherwise map the event coordinate to the square.
4029 int EventToSquare(x, limit)
4037 if ((x % (squareSize + lineGap)) >= squareSize)
4039 x /= (squareSize + lineGap);
4045 static void do_flash_delay(msec)
4051 static void drawHighlight(file, rank, gc)
4057 if (lineGap == 0 || appData.blindfold) return;
4060 x = lineGap/2 + ((BOARD_WIDTH-1)-file) *
4061 (squareSize + lineGap);
4062 y = lineGap/2 + rank * (squareSize + lineGap);
4064 x = lineGap/2 + file * (squareSize + lineGap);
4065 y = lineGap/2 + ((BOARD_HEIGHT-1)-rank) *
4066 (squareSize + lineGap);
4069 XDrawRectangle(xDisplay, xBoardWindow, gc, x, y,
4070 squareSize+lineGap, squareSize+lineGap);
4073 int hi1X = -1, hi1Y = -1, hi2X = -1, hi2Y = -1;
4074 int pm1X = -1, pm1Y = -1, pm2X = -1, pm2Y = -1;
4077 SetHighlights(fromX, fromY, toX, toY)
4078 int fromX, fromY, toX, toY;
4080 if (hi1X != fromX || hi1Y != fromY) {
4081 if (hi1X >= 0 && hi1Y >= 0) {
4082 drawHighlight(hi1X, hi1Y, lineGC);
4084 if (fromX >= 0 && fromY >= 0) {
4085 drawHighlight(fromX, fromY, highlineGC);
4088 if (hi2X != toX || hi2Y != toY) {
4089 if (hi2X >= 0 && hi2Y >= 0) {
4090 drawHighlight(hi2X, hi2Y, lineGC);
4092 if (toX >= 0 && toY >= 0) {
4093 drawHighlight(toX, toY, highlineGC);
4105 SetHighlights(-1, -1, -1, -1);
4110 SetPremoveHighlights(fromX, fromY, toX, toY)
4111 int fromX, fromY, toX, toY;
4113 if (pm1X != fromX || pm1Y != fromY) {
4114 if (pm1X >= 0 && pm1Y >= 0) {
4115 drawHighlight(pm1X, pm1Y, lineGC);
4117 if (fromX >= 0 && fromY >= 0) {
4118 drawHighlight(fromX, fromY, prelineGC);
4121 if (pm2X != toX || pm2Y != toY) {
4122 if (pm2X >= 0 && pm2Y >= 0) {
4123 drawHighlight(pm2X, pm2Y, lineGC);
4125 if (toX >= 0 && toY >= 0) {
4126 drawHighlight(toX, toY, prelineGC);
4136 ClearPremoveHighlights()
4138 SetPremoveHighlights(-1, -1, -1, -1);
4141 static void BlankSquare(x, y, color, piece, dest)
4146 if (useImages && useImageSqs) {
4150 pb = SVGLightSquare;
4155 case 2: /* neutral */
4157 pb = SVGNeutralSquare;
4160 gdk_draw_pixbuf(GDK_WINDOW(GUI_Board->window),NULL,pb,0,0,x,y,-1,-1, GDK_RGB_DITHER_NORMAL, 0, 0);
4165 gc = gdk_gc_new(GDK_WINDOW(GUI_Board->window));
4169 // gc = lightSquareGC;
4173 gdk_gc_set_rgb_fg_color(gc, &tmp);
4176 // gc = darkSquareGC;
4180 gdk_gc_set_rgb_fg_color(gc, &tmp);
4182 case 2: /* neutral */
4184 // gc = jailSquareGC;
4188 gdk_gc_set_rgb_fg_color(gc, &tmp);
4191 gdk_draw_rectangle(GDK_WINDOW(GUI_Board->window),gc,1,x,y,squareSize,squareSize);
4197 I split out the routines to draw a piece so that I could
4198 make a generic flash routine.
4200 static void monoDrawPiece_1bit(piece, square_color, x, y, dest)
4202 int square_color, x, y;
4205 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
4206 switch (square_color) {
4208 case 2: /* neutral */
4210 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
4211 ? *pieceToOutline(piece)
4212 : *pieceToSolid(piece),
4213 dest, bwPieceGC, 0, 0,
4214 squareSize, squareSize, x, y);
4217 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
4218 ? *pieceToSolid(piece)
4219 : *pieceToOutline(piece),
4220 dest, wbPieceGC, 0, 0,
4221 squareSize, squareSize, x, y);
4226 static void monoDrawPiece(piece, square_color, x, y, dest)
4228 int square_color, x, y;
4231 switch (square_color) {
4233 case 2: /* neutral */
4235 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
4236 ? *pieceToOutline(piece)
4237 : *pieceToSolid(piece),
4238 dest, bwPieceGC, 0, 0,
4239 squareSize, squareSize, x, y, 1);
4242 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
4243 ? *pieceToSolid(piece)
4244 : *pieceToOutline(piece),
4245 dest, wbPieceGC, 0, 0,
4246 squareSize, squareSize, x, y, 1);
4251 static void colorDrawPiece(piece, square_color, x, y, dest)
4253 int square_color, x, y;
4256 if(pieceToSolid(piece) == NULL) return; // [HGM] bitmaps: make it non-fatal if we have no bitmap;
4257 switch (square_color) {
4259 XCopyPlane(xDisplay, *pieceToSolid(piece),
4260 dest, (int) piece < (int) BlackPawn
4261 ? wlPieceGC : blPieceGC, 0, 0,
4262 squareSize, squareSize, x, y, 1);
4265 XCopyPlane(xDisplay, *pieceToSolid(piece),
4266 dest, (int) piece < (int) BlackPawn
4267 ? wdPieceGC : bdPieceGC, 0, 0,
4268 squareSize, squareSize, x, y, 1);
4270 case 2: /* neutral */
4272 XCopyPlane(xDisplay, *pieceToSolid(piece),
4273 dest, (int) piece < (int) BlackPawn
4274 ? wjPieceGC : bjPieceGC, 0, 0,
4275 squareSize, squareSize, x, y, 1);
4280 static void colorDrawPieceImage(piece, square_color, x, y, dest)
4282 int square_color, x, y;
4287 switch (square_color) {
4289 case 2: /* neutral */
4291 if ((int)piece < (int) BlackPawn) {
4299 if ((int)piece < (int) BlackPawn) {
4307 XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
4308 dest, wlPieceGC, 0, 0,
4309 squareSize, squareSize, x, y);
4312 typedef void (*DrawFunc)();
4314 DrawFunc ChooseDrawFunc()
4316 if (appData.monoMode) {
4317 if (DefaultDepth(xDisplay, xScreen) == 1) {
4318 return monoDrawPiece_1bit;
4320 return monoDrawPiece;
4324 return colorDrawPieceImage;
4326 return colorDrawPiece;
4330 /* [HR] determine square color depending on chess variant. */
4331 static int SquareColor(row, column)
4336 if (gameInfo.variant == VariantXiangqi) {
4337 if (column >= 3 && column <= 5 && row >= 0 && row <= 2) {
4339 } else if (column >= 3 && column <= 5 && row >= 7 && row <= 9) {
4341 } else if (row <= 4) {
4347 square_color = ((column + row) % 2) == 1;
4350 /* [hgm] holdings: next line makes all holdings squares light */
4351 if(column < BOARD_LEFT || column >= BOARD_RGHT) square_color = 1;
4353 return square_color;
4356 void DrawSquare(row, column, piece, do_flash)
4357 int row, column, do_flash;
4360 int square_color, x, y, direction, font_ascent, font_descent;
4363 XCharStruct overall;
4367 /* Calculate delay in milliseconds (2-delays per complete flash) */
4368 flash_delay = 500 / appData.flashRate;
4371 x = lineGap + ((BOARD_WIDTH-1)-column) *
4372 (squareSize + lineGap);
4373 y = lineGap + row * (squareSize + lineGap);
4375 x = lineGap + column * (squareSize + lineGap);
4376 y = lineGap + ((BOARD_HEIGHT-1)-row) *
4377 (squareSize + lineGap);
4380 square_color = SquareColor(row, column);
4382 if ( // [HGM] holdings: blank out area between board and holdings
4383 column == BOARD_LEFT-1 || column == BOARD_RGHT
4384 || (column == BOARD_LEFT-2 && row < BOARD_HEIGHT-gameInfo.holdingsSize)
4385 || (column == BOARD_RGHT+1 && row >= gameInfo.holdingsSize) ) {
4386 BlankSquare(x, y, 2, EmptySquare, xBoardWindow);
4388 // [HGM] print piece counts next to holdings
4389 string[1] = NULLCHAR;
4390 if (column == (flipView ? BOARD_LEFT-1 : BOARD_RGHT) && piece > 1 ) {
4391 string[0] = '0' + piece;
4392 XTextExtents(countFontStruct, string, 1, &direction,
4393 &font_ascent, &font_descent, &overall);
4394 if (appData.monoMode) {
4395 XDrawImageString(xDisplay, xBoardWindow, countGC,
4396 x + squareSize - overall.width - 2,
4397 y + font_ascent + 1, string, 1);
4399 XDrawString(xDisplay, xBoardWindow, countGC,
4400 x + squareSize - overall.width - 2,
4401 y + font_ascent + 1, string, 1);
4404 if (column == (flipView ? BOARD_RGHT : BOARD_LEFT-1) && piece > 1) {
4405 string[0] = '0' + piece;
4406 XTextExtents(countFontStruct, string, 1, &direction,
4407 &font_ascent, &font_descent, &overall);
4408 if (appData.monoMode) {
4409 XDrawImageString(xDisplay, xBoardWindow, countGC,
4410 x + 2, y + font_ascent + 1, string, 1);
4412 XDrawString(xDisplay, xBoardWindow, countGC,
4413 x + 2, y + font_ascent + 1, string, 1);
4417 if (piece == EmptySquare || appData.blindfold) {
4418 BlankSquare(x, y, square_color, piece, xBoardWindow);
4420 drawfunc = ChooseDrawFunc();
4421 if (do_flash && appData.flashCount > 0) {
4422 for (i=0; i<appData.flashCount; ++i) {
4424 drawfunc(piece, square_color, x, y, xBoardWindow);
4425 XSync(xDisplay, False);
4426 do_flash_delay(flash_delay);
4428 BlankSquare(x, y, square_color, piece, xBoardWindow);
4429 XSync(xDisplay, False);
4430 do_flash_delay(flash_delay);
4433 drawfunc(piece, square_color, x, y, xBoardWindow);
4437 string[1] = NULLCHAR;
4438 if (appData.showCoords && row == (flipView ? BOARD_HEIGHT-1 : 0)
4439 && column >= BOARD_LEFT && column < BOARD_RGHT) {
4440 string[0] = 'a' + column - BOARD_LEFT;
4441 XTextExtents(coordFontStruct, string, 1, &direction,
4442 &font_ascent, &font_descent, &overall);
4443 if (appData.monoMode) {
4444 XDrawImageString(xDisplay, xBoardWindow, coordGC,
4445 x + squareSize - overall.width - 2,
4446 y + squareSize - font_descent - 1, string, 1);
4448 XDrawString(xDisplay, xBoardWindow, coordGC,
4449 x + squareSize - overall.width - 2,
4450 y + squareSize - font_descent - 1, string, 1);
4453 if (appData.showCoords && column == (flipView ? BOARD_RGHT-1 : BOARD_LEFT)) {
4454 string[0] = ONE + row;
4455 XTextExtents(coordFontStruct, string, 1, &direction,
4456 &font_ascent, &font_descent, &overall);
4457 if (appData.monoMode) {
4458 XDrawImageString(xDisplay, xBoardWindow, coordGC,
4459 x + 2, y + font_ascent + 1, string, 1);
4461 XDrawString(xDisplay, xBoardWindow, coordGC,
4462 x + 2, y + font_ascent + 1, string, 1);
4468 /* Returns 1 if there are "too many" differences between b1 and b2
4469 (i.e. more than 1 move was made) */
4470 static int too_many_diffs(b1, b2)
4476 for (i=0; i<BOARD_HEIGHT; ++i) {
4477 for (j=0; j<BOARD_WIDTH; ++j) {
4478 if (b1[i][j] != b2[i][j]) {
4479 if (++c > 4) /* Castling causes 4 diffs */
4488 /* Matrix describing castling maneuvers */
4489 /* Row, ColRookFrom, ColKingFrom, ColRookTo, ColKingTo */
4490 static int castling_matrix[4][5] = {
4491 { 0, 0, 4, 3, 2 }, /* 0-0-0, white */
4492 { 0, 7, 4, 5, 6 }, /* 0-0, white */
4493 { 7, 0, 4, 3, 2 }, /* 0-0-0, black */
4494 { 7, 7, 4, 5, 6 } /* 0-0, black */
4497 /* Checks whether castling occurred. If it did, *rrow and *rcol
4498 are set to the destination (row,col) of the rook that moved.
4500 Returns 1 if castling occurred, 0 if not.
4502 Note: Only handles a max of 1 castling move, so be sure
4503 to call too_many_diffs() first.
4505 static int check_castle_draw(newb, oldb, rrow, rcol)
4512 /* For each type of castling... */
4513 for (i=0; i<4; ++i) {
4514 r = castling_matrix[i];
4516 /* Check the 4 squares involved in the castling move */
4518 for (j=1; j<=4; ++j) {
4519 if (newb[r[0]][r[j]] == oldb[r[0]][r[j]]) {
4526 /* All 4 changed, so it must be a castling move */
4535 static int damage[BOARD_SIZE][BOARD_SIZE];
4538 * event handler for redrawing the board
4540 void DrawPosition( repaint, board)
4541 /*Boolean*/int repaint;
4545 static int lastFlipView = 0;
4546 static int lastBoardValid = 0;
4547 static Board lastBoard;
4551 printf ("DEBUG: in draw position\n");
4554 if (board == NULL) {
4555 if (!lastBoardValid) return;
4558 if (!lastBoardValid || lastFlipView != flipView) {
4559 XtSetArg(args[0], XtNleftBitmap, (flipView ? xMarkPixmap : None));
4560 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flip View"),
4565 * It would be simpler to clear the window with XClearWindow()
4566 * but this causes a very distracting flicker.
4569 printf ("DEBUG: in draw position 0.1\n");
4572 if (!repaint && lastBoardValid && lastFlipView == flipView) {
4574 printf ("DEBUG: in draw position 0.1a\n");
4575 /* If too much changes (begin observing new game, etc.), don't
4577 do_flash = too_many_diffs(board, lastBoard) ? 0 : 1;
4579 /* Special check for castling so we don't flash both the king
4580 and the rook (just flash the king). */
4582 if (check_castle_draw(board, lastBoard, &rrow, &rcol)) {
4583 /* Draw rook with NO flashing. King will be drawn flashing later */
4584 DrawSquare(rrow, rcol, board[rrow][rcol], 0);
4585 lastBoard[rrow][rcol] = board[rrow][rcol];
4589 /* First pass -- Draw (newly) empty squares and repair damage.
4590 This prevents you from having a piece show up twice while it
4591 is flashing on its new square */
4592 for (i = 0; i < BOARD_HEIGHT; i++)
4593 for (j = 0; j < BOARD_WIDTH; j++)
4594 if ((board[i][j] != lastBoard[i][j] && board[i][j] == EmptySquare)
4596 DrawSquare(i, j, board[i][j], 0);
4597 damage[i][j] = False;
4600 /* Second pass -- Draw piece(s) in new position and flash them */
4601 for (i = 0; i < BOARD_HEIGHT; i++)
4602 for (j = 0; j < BOARD_WIDTH; j++)
4603 if (board[i][j] != lastBoard[i][j]) {
4604 DrawSquare(i, j, board[i][j], do_flash);
4609 /* todo move GC to setupgc */
4610 GdkGC *gtklineGC=NULL;
4613 gtklineGC = gdk_gc_new(GDK_WINDOW(GUI_Board->window));
4618 gdk_gc_set_rgb_fg_color(gtklineGC, &tmp);
4623 gdk_gc_set_rgb_bg_color(gtklineGC, &tmp);
4625 gdk_draw_segments(GUI_Board->window,gtklineGC,
4626 gridSegments, BOARD_HEIGHT + BOARD_WIDTH + 2 );
4629 for (i = 0; i < BOARD_HEIGHT; i++)
4630 for (j = 0; j < BOARD_WIDTH; j++) {
4631 DrawSquare(i, j, board[i][j], 0);
4632 damage[i][j] = False;
4636 CopyBoard(lastBoard, board);
4638 lastFlipView = flipView;
4640 /* Draw highlights */
4641 if (pm1X >= 0 && pm1Y >= 0) {
4642 drawHighlight(pm1X, pm1Y, prelineGC);
4644 if (pm2X >= 0 && pm2Y >= 0) {
4645 drawHighlight(pm2X, pm2Y, prelineGC);
4647 if (hi1X >= 0 && hi1Y >= 0) {
4648 drawHighlight(hi1X, hi1Y, highlineGC);
4650 if (hi2X >= 0 && hi2Y >= 0) {
4651 drawHighlight(hi2X, hi2Y, highlineGC);
4654 /* If piece being dragged around board, must redraw that too */
4657 // XSync(xDisplay, False);
4662 * event handler for redrawing the board
4664 void DrawPositionProc(w, event, prms, nprms)
4670 DrawPosition(True, NULL);
4675 * event handler for parsing user moves
4677 // [HGM] This routine will need quite some reworking. Although the backend still supports the old
4678 // way of doing things, by calling UserMoveEvent() to test the legality of the move and then perform
4679 // it at the end, and doing all kind of preliminary tests here (e.g. to weed out self-captures), it
4680 // should be made to use the new way, of calling UserMoveTest early to determine the legality of the
4681 // move, (which will weed out the illegal selfcaptures and moves into the holdings, and flag promotions),
4682 // and at the end FinishMove() to perform the move after optional promotion popups.
4683 // For now I patched it to allow self-capture with King, and suppress clicks between board and holdings.
4684 void HandleUserMove(w, event, prms, nprms)
4691 Boolean saveAnimate;
4692 static int second = 0;
4694 if (w != boardWidget || errorExitStatus != -1) return;
4696 if (event->type == ButtonPress) ErrorPopDown();
4699 if (event->type == ButtonPress) {
4700 XtPopdown(promotionShell);
4701 XtDestroyWidget(promotionShell);
4702 promotionUp = False;
4710 x = EventToSquare(event->xbutton.x, BOARD_WIDTH);
4711 y = EventToSquare(event->xbutton.y, BOARD_HEIGHT);
4712 if (!flipView && y >= 0) {
4713 y = BOARD_HEIGHT - 1 - y;
4715 if (flipView && x >= 0) {
4716 x = BOARD_WIDTH - 1 - x;
4719 /* [HGM] holdings: next 5 lines: ignore all clicks between board and holdings */
4720 if(event->type == ButtonPress
4721 && ( x == BOARD_LEFT-1 || x == BOARD_RGHT
4722 || x == BOARD_LEFT-2 && y < BOARD_HEIGHT-gameInfo.holdingsSize
4723 || x == BOARD_RGHT+1 && y >= gameInfo.holdingsSize) )
4727 if (event->type == ButtonPress) {
4729 if (OKToStartUserMove(x, y)) {
4733 DragPieceBegin(event->xbutton.x, event->xbutton.y);
4734 if (appData.highlightDragging) {
4735 SetHighlights(x, y, -1, -1);
4743 if (event->type == ButtonPress && gameMode != EditPosition &&
4748 /* Check if clicking again on the same color piece */
4749 fromP = boards[currentMove][fromY][fromX];
4750 toP = boards[currentMove][y][x];
4751 if ((WhitePawn <= fromP && fromP < WhiteKing && // [HGM] this test should go, as UserMoveTest now does it.
4752 WhitePawn <= toP && toP <= WhiteKing) || // For now I made it less critical by exempting King
4753 (BlackPawn <= fromP && fromP < BlackKing && // moves, to not interfere with FRC castlings.
4754 BlackPawn <= toP && toP <= BlackKing)) {
4755 /* Clicked again on same color piece -- changed his mind */
4756 second = (x == fromX && y == fromY);
4757 if (appData.highlightDragging) {
4758 SetHighlights(x, y, -1, -1);
4762 if (OKToStartUserMove(x, y)) {
4765 DragPieceBegin(event->xbutton.x, event->xbutton.y);
4771 if (event->type == ButtonRelease && x == fromX && y == fromY) {
4772 DragPieceEnd(event->xbutton.x, event->xbutton.y);
4773 if (appData.animateDragging) {
4774 /* Undo animation damage if any */
4775 DrawPosition(FALSE, NULL);
4778 /* Second up/down in same square; just abort move */
4783 ClearPremoveHighlights();
4785 /* First upclick in same square; start click-click mode */
4786 SetHighlights(x, y, -1, -1);
4791 /* Completed move */
4794 saveAnimate = appData.animate;
4795 if (event->type == ButtonPress) {
4796 /* Finish clickclick move */
4797 if (appData.animate || appData.highlightLastMove) {
4798 SetHighlights(fromX, fromY, toX, toY);
4803 /* Finish drag move */
4804 if (appData.highlightLastMove) {
4805 SetHighlights(fromX, fromY, toX, toY);
4809 DragPieceEnd(event->xbutton.x, event->xbutton.y);
4810 /* Don't animate move and drag both */
4811 appData.animate = FALSE;
4813 if (IsPromotion(fromX, fromY, toX, toY)) {
4814 if (appData.alwaysPromoteToQueen) {
4815 UserMoveEvent(fromX, fromY, toX, toY, 'q');
4816 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
4817 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
4820 SetHighlights(fromX, fromY, toX, toY);
4824 UserMoveEvent(fromX, fromY, toX, toY, NULLCHAR);
4825 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
4826 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
4829 appData.animate = saveAnimate;
4830 if (appData.animate || appData.animateDragging) {
4831 /* Undo animation damage if needed */
4832 DrawPosition(FALSE, NULL);
4836 void AnimateUserMove (Widget w, XEvent * event,
4837 String * params, Cardinal * nParams)
4839 DragPieceMove(event->xmotion.x, event->xmotion.y);
4842 Widget CommentCreate(name, text, mutable, callback, lines)
4844 int /*Boolean*/ mutable;
4845 XtCallbackProc callback;
4849 Widget shell, layout, form, edit, b_ok, b_cancel, b_clear, b_close, b_edit;
4854 XtSetArg(args[j], XtNwidth, &bw_width); j++;
4855 XtGetValues(boardWidget, args, j);
4858 XtSetArg(args[j], XtNresizable, True); j++;
4861 XtCreatePopupShell(name, topLevelShellWidgetClass,
4862 shellWidget, args, j);
4865 XtCreatePopupShell(name, transientShellWidgetClass,
4866 shellWidget, args, j);
4869 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
4870 layoutArgs, XtNumber(layoutArgs));
4872 XtCreateManagedWidget("form", formWidgetClass, layout,
4873 formArgs, XtNumber(formArgs));
4877 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
4878 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
4880 XtSetArg(args[j], XtNstring, text); j++;
4881 XtSetArg(args[j], XtNtop, XtChainTop); j++;
4882 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4883 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4884 XtSetArg(args[j], XtNright, XtChainRight); j++;
4885 XtSetArg(args[j], XtNresizable, True); j++;
4886 XtSetArg(args[j], XtNwidth, bw_width); j++; /*force wider than buttons*/
4888 XtSetArg(args[j], XtNscrollVertical, XawtextScrollWhenNeeded); j++;
4890 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
4891 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
4893 XtSetArg(args[j], XtNautoFill, True); j++;
4894 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
4896 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
4900 XtSetArg(args[j], XtNfromVert, edit); j++;
4901 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4902 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4903 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4904 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4906 XtCreateManagedWidget(_("ok"), commandWidgetClass, form, args, j);
4907 XtAddCallback(b_ok, XtNcallback, callback, (XtPointer) 0);
4910 XtSetArg(args[j], XtNfromVert, edit); j++;
4911 XtSetArg(args[j], XtNfromHoriz, b_ok); j++;
4912 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4913 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4914 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4915 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4917 XtCreateManagedWidget(_("cancel"), commandWidgetClass, form, args, j);
4918 XtAddCallback(b_cancel, XtNcallback, callback, (XtPointer) 0);
4921 XtSetArg(args[j], XtNfromVert, edit); j++;
4922 XtSetArg(args[j], XtNfromHoriz, b_cancel); j++;
4923 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4924 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4925 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4926 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4928 XtCreateManagedWidget(_("clear"), commandWidgetClass, form, args, j);
4929 XtAddCallback(b_clear, XtNcallback, callback, (XtPointer) 0);
4932 XtSetArg(args[j], XtNfromVert, edit); j++;
4933 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4934 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4935 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4936 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4938 XtCreateManagedWidget(_("close"), commandWidgetClass, form, args, j);
4939 XtAddCallback(b_close, XtNcallback, callback, (XtPointer) 0);
4942 XtSetArg(args[j], XtNfromVert, edit); j++;
4943 XtSetArg(args[j], XtNfromHoriz, b_close); j++;
4944 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4945 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4946 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4947 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4949 XtCreateManagedWidget(_("edit"), commandWidgetClass, form, args, j);
4950 XtAddCallback(b_edit, XtNcallback, callback, (XtPointer) 0);
4953 XtRealizeWidget(shell);
4955 if (commentX == -1) {
4958 Dimension pw_height;
4959 Dimension ew_height;
4962 XtSetArg(args[j], XtNheight, &ew_height); j++;
4963 XtGetValues(edit, args, j);
4966 XtSetArg(args[j], XtNheight, &pw_height); j++;
4967 XtGetValues(shell, args, j);
4968 commentH = pw_height + (lines - 1) * ew_height;
4969 commentW = bw_width - 16;
4971 XSync(xDisplay, False);
4973 /* This code seems to tickle an X bug if it is executed too soon
4974 after xboard starts up. The coordinates get transformed as if
4975 the main window was positioned at (0, 0).
4977 XtTranslateCoords(shellWidget,
4978 (bw_width - commentW) / 2, 0 - commentH / 2,
4979 &commentX, &commentY);
4981 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
4982 RootWindowOfScreen(XtScreen(shellWidget)),
4983 (bw_width - commentW) / 2, 0 - commentH / 2,
4988 if (commentY < 0) commentY = 0; /*avoid positioning top offscreen*/
4991 XtSetArg(args[j], XtNheight, commentH); j++;
4992 XtSetArg(args[j], XtNwidth, commentW); j++;
4993 XtSetArg(args[j], XtNx, commentX); j++;
4994 XtSetArg(args[j], XtNy, commentY); j++;
4995 XtSetValues(shell, args, j);
4996 XtSetKeyboardFocus(shell, edit);
5001 /* Used for analysis window and ICS input window */
5002 Widget MiscCreate(name, text, mutable, callback, lines)
5004 int /*Boolean*/ mutable;
5005 XtCallbackProc callback;
5009 Widget shell, layout, form, edit;
5011 Dimension bw_width, pw_height, ew_height, w, h;
5017 XtSetArg(args[j], XtNresizable, True); j++;
5020 XtCreatePopupShell(name, topLevelShellWidgetClass,
5021 shellWidget, args, j);
5024 XtCreatePopupShell(name, transientShellWidgetClass,
5025 shellWidget, args, j);
5028 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
5029 layoutArgs, XtNumber(layoutArgs));
5031 XtCreateManagedWidget("form", formWidgetClass, layout,
5032 formArgs, XtNumber(formArgs));
5036 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
5037 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
5039 XtSetArg(args[j], XtNstring, text); j++;
5040 XtSetArg(args[j], XtNtop, XtChainTop); j++;
5041 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5042 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5043 XtSetArg(args[j], XtNright, XtChainRight); j++;
5044 XtSetArg(args[j], XtNresizable, True); j++;
5046 XtSetArg(args[j], XtNscrollVertical, XawtextScrollWhenNeeded); j++;
5048 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
5049 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
5051 XtSetArg(args[j], XtNautoFill, True); j++;
5052 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
5054 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
5056 XtRealizeWidget(shell);
5059 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5060 XtGetValues(boardWidget, args, j);
5063 XtSetArg(args[j], XtNheight, &ew_height); j++;
5064 XtGetValues(edit, args, j);
5067 XtSetArg(args[j], XtNheight, &pw_height); j++;
5068 XtGetValues(shell, args, j);
5069 h = pw_height + (lines - 1) * ew_height;
5072 XSync(xDisplay, False);
5074 /* This code seems to tickle an X bug if it is executed too soon
5075 after xboard starts up. The coordinates get transformed as if
5076 the main window was positioned at (0, 0).
5078 XtTranslateCoords(shellWidget, (bw_width - w) / 2, 0 - h / 2, &x, &y);
5080 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
5081 RootWindowOfScreen(XtScreen(shellWidget)),
5082 (bw_width - w) / 2, 0 - h / 2, &xx, &yy, &junk);
5086 if (y < 0) y = 0; /*avoid positioning top offscreen*/
5089 XtSetArg(args[j], XtNheight, h); j++;
5090 XtSetArg(args[j], XtNwidth, w); j++;
5091 XtSetArg(args[j], XtNx, x); j++;
5092 XtSetArg(args[j], XtNy, y); j++;
5093 XtSetValues(shell, args, j);
5099 static int savedIndex; /* gross that this is global */
5101 void EditCommentPopUp(index, title, text)
5110 if (text == NULL) text = "";
5112 if (editShell == NULL) {
5114 CommentCreate(title, text, True, EditCommentCallback, 4);
5115 XtRealizeWidget(editShell);
5116 CatchDeleteWindow(editShell, "EditCommentPopDown");
5118 edit = XtNameToWidget(editShell, "*form.text");
5120 XtSetArg(args[j], XtNstring, text); j++;
5121 XtSetValues(edit, args, j);
5123 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5124 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5125 XtSetValues(editShell, args, j);
5128 XtPopup(editShell, XtGrabNone);
5132 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
5133 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
5137 void EditCommentCallback(w, client_data, call_data)
5139 XtPointer client_data, call_data;
5147 XtSetArg(args[j], XtNlabel, &name); j++;
5148 XtGetValues(w, args, j);
5150 if (strcmp(name, _("ok")) == 0) {
5151 edit = XtNameToWidget(editShell, "*form.text");
5153 XtSetArg(args[j], XtNstring, &val); j++;
5154 XtGetValues(edit, args, j);
5155 ReplaceComment(savedIndex, val);
5156 EditCommentPopDown();
5157 } else if (strcmp(name, _("cancel")) == 0) {
5158 EditCommentPopDown();
5159 } else if (strcmp(name, _("clear")) == 0) {
5160 edit = XtNameToWidget(editShell, "*form.text");
5161 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
5162 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
5166 void EditCommentPopDown()
5171 if (!editUp) return;
5173 XtSetArg(args[j], XtNx, &commentX); j++;
5174 XtSetArg(args[j], XtNy, &commentY); j++;
5175 XtSetArg(args[j], XtNheight, &commentH); j++;
5176 XtSetArg(args[j], XtNwidth, &commentW); j++;
5177 XtGetValues(editShell, args, j);
5178 XtPopdown(editShell);
5181 XtSetArg(args[j], XtNleftBitmap, None); j++;
5182 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
5186 void ICSInputBoxPopUp()
5191 char *title = _("ICS Input");
5194 if (ICSInputShell == NULL) {
5195 ICSInputShell = MiscCreate(title, "", True, NULL, 1);
5196 tr = XtParseTranslationTable(ICSInputTranslations);
5197 edit = XtNameToWidget(ICSInputShell, "*form.text");
5198 XtOverrideTranslations(edit, tr);
5199 XtRealizeWidget(ICSInputShell);
5200 CatchDeleteWindow(ICSInputShell, "ICSInputBoxPopDown");
5203 edit = XtNameToWidget(ICSInputShell, "*form.text");
5205 XtSetArg(args[j], XtNstring, ""); j++;
5206 XtSetValues(edit, args, j);
5208 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5209 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5210 XtSetValues(ICSInputShell, args, j);
5213 XtPopup(ICSInputShell, XtGrabNone);
5214 XtSetKeyboardFocus(ICSInputShell, edit);
5216 ICSInputBoxUp = True;
5218 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
5219 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
5223 void ICSInputSendText()
5230 edit = XtNameToWidget(ICSInputShell, "*form.text");
5232 XtSetArg(args[j], XtNstring, &val); j++;
5233 XtGetValues(edit, args, j);
5234 SendMultiLineToICS(val);
5235 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
5236 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
5239 void ICSInputBoxPopDown()
5244 if (!ICSInputBoxUp) return;
5246 XtPopdown(ICSInputShell);
5247 ICSInputBoxUp = False;
5249 XtSetArg(args[j], XtNleftBitmap, None); j++;
5250 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
5254 void CommentPopUp(title, text)
5261 if (commentShell == NULL) {
5263 CommentCreate(title, text, False, CommentCallback, 4);
5264 XtRealizeWidget(commentShell);
5265 CatchDeleteWindow(commentShell, "CommentPopDown");
5267 edit = XtNameToWidget(commentShell, "*form.text");
5269 XtSetArg(args[j], XtNstring, text); j++;
5270 XtSetValues(edit, args, j);
5272 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5273 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5274 XtSetValues(commentShell, args, j);
5277 XtPopup(commentShell, XtGrabNone);
5278 XSync(xDisplay, False);
5283 void AnalysisPopUp(title, text)
5290 if (analysisShell == NULL) {
5291 analysisShell = MiscCreate(title, text, False, NULL, 4);
5292 XtRealizeWidget(analysisShell);
5293 CatchDeleteWindow(analysisShell, "AnalysisPopDown");
5296 edit = XtNameToWidget(analysisShell, "*form.text");
5298 XtSetArg(args[j], XtNstring, text); j++;
5299 XtSetValues(edit, args, j);
5301 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5302 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5303 XtSetValues(analysisShell, args, j);
5307 XtPopup(analysisShell, XtGrabNone);
5309 XSync(xDisplay, False);
5314 void CommentCallback(w, client_data, call_data)
5316 XtPointer client_data, call_data;
5323 XtSetArg(args[j], XtNlabel, &name); j++;
5324 XtGetValues(w, args, j);
5326 if (strcmp(name, _("close")) == 0) {
5328 } else if (strcmp(name, _("edit")) == 0) {
5335 void CommentPopDown()
5340 if (!commentUp) return;
5342 XtSetArg(args[j], XtNx, &commentX); j++;
5343 XtSetArg(args[j], XtNy, &commentY); j++;
5344 XtSetArg(args[j], XtNwidth, &commentW); j++;
5345 XtSetArg(args[j], XtNheight, &commentH); j++;
5346 XtGetValues(commentShell, args, j);
5347 XtPopdown(commentShell);
5348 XSync(xDisplay, False);
5352 void AnalysisPopDown()
5354 if (!analysisUp) return;
5355 XtPopdown(analysisShell);
5356 XSync(xDisplay, False);
5358 if (appData.icsEngineAnalyze) ExitAnalyzeMode(); /* [DM] icsEngineAnalyze */
5362 void FileNamePopUp(label, def, proc, openMode)
5369 Widget popup, layout, dialog, edit;
5375 fileProc = proc; /* I can't see a way not */
5376 fileOpenMode = openMode; /* to use globals here */
5379 XtSetArg(args[i], XtNresizable, True); i++;
5380 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
5381 XtSetArg(args[i], XtNtitle, XtNewString(_("File name prompt"))); i++;
5382 fileNameShell = popup =
5383 XtCreatePopupShell("File name prompt", transientShellWidgetClass,
5384 shellWidget, args, i);
5387 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
5388 layoutArgs, XtNumber(layoutArgs));
5391 XtSetArg(args[i], XtNlabel, label); i++;
5392 XtSetArg(args[i], XtNvalue, def); i++;
5393 XtSetArg(args[i], XtNborderWidth, 0); i++;
5394 dialog = XtCreateManagedWidget("fileName", dialogWidgetClass,
5397 XawDialogAddButton(dialog, _("ok"), FileNameCallback, (XtPointer) dialog);
5398 XawDialogAddButton(dialog, _("cancel"), FileNameCallback,
5399 (XtPointer) dialog);
5401 XtRealizeWidget(popup);
5402 CatchDeleteWindow(popup, "FileNamePopDown");
5404 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
5405 &x, &y, &win_x, &win_y, &mask);
5407 XtSetArg(args[0], XtNx, x - 10);
5408 XtSetArg(args[1], XtNy, y - 30);
5409 XtSetValues(popup, args, 2);
5411 XtPopup(popup, XtGrabExclusive);
5414 edit = XtNameToWidget(dialog, "*value");
5415 XtSetKeyboardFocus(popup, edit);
5418 void FileNamePopDown()
5420 if (!filenameUp) return;
5421 XtPopdown(fileNameShell);
5422 XtDestroyWidget(fileNameShell);
5427 void FileNameCallback(w, client_data, call_data)
5429 XtPointer client_data, call_data;
5434 XtSetArg(args[0], XtNlabel, &name);
5435 XtGetValues(w, args, 1);
5437 if (strcmp(name, _("cancel")) == 0) {
5442 FileNameAction(w, NULL, NULL, NULL);
5445 void FileNameAction(w, event, prms, nprms)
5457 name = XawDialogGetValueString(w = XtParent(w));
5459 if ((name != NULL) && (*name != NULLCHAR)) {
5461 XtPopdown(w = XtParent(XtParent(w)));
5465 p = strrchr(buf, ' ');
5472 fullname = ExpandPathName(buf);
5474 ErrorPopUp(_("Error"), _("Can't open file"), FALSE);
5477 f = fopen(fullname, fileOpenMode);
5479 DisplayError(_("Failed to open file"), errno);
5481 (void) (*fileProc)(f, index, buf);
5488 XtPopdown(w = XtParent(XtParent(w)));
5494 void PromotionPopUp()
5497 Widget dialog, layout;
5499 Dimension bw_width, pw_width;
5503 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5504 XtGetValues(boardWidget, args, j);
5507 XtSetArg(args[j], XtNresizable, True); j++;
5508 XtSetArg(args[j], XtNtitle, XtNewString(_("Promotion"))); j++;
5510 XtCreatePopupShell("Promotion", transientShellWidgetClass,
5511 shellWidget, args, j);
5513 XtCreateManagedWidget(layoutName, formWidgetClass, promotionShell,
5514 layoutArgs, XtNumber(layoutArgs));
5517 XtSetArg(args[j], XtNlabel, _("Promote to what?")); j++;
5518 XtSetArg(args[j], XtNborderWidth, 0); j++;
5519 dialog = XtCreateManagedWidget("promotion", dialogWidgetClass,
5522 if(gameInfo.variant != VariantShogi) {
5523 XawDialogAddButton(dialog, _("Queen"), PromotionCallback,
5524 (XtPointer) dialog);
5525 XawDialogAddButton(dialog, _("Rook"), PromotionCallback,
5526 (XtPointer) dialog);
5527 XawDialogAddButton(dialog, _("Bishop"), PromotionCallback,
5528 (XtPointer) dialog);
5529 XawDialogAddButton(dialog, _("Knight"), PromotionCallback,
5530 (XtPointer) dialog);
5531 if (!appData.testLegality || gameInfo.variant == VariantSuicide ||
5532 gameInfo.variant == VariantGiveaway) {
5533 XawDialogAddButton(dialog, _("King"), PromotionCallback,
5534 (XtPointer) dialog);
5536 if(gameInfo.variant == VariantCapablanca ||
5537 gameInfo.variant == VariantGothic ||
5538 gameInfo.variant == VariantCapaRandom) {
5539 XawDialogAddButton(dialog, _("Archbishop"), PromotionCallback,
5540 (XtPointer) dialog);
5541 XawDialogAddButton(dialog, _("Chancellor"), PromotionCallback,
5542 (XtPointer) dialog);
5544 } else // [HGM] shogi
5546 XawDialogAddButton(dialog, _("Promote"), PromotionCallback,
5547 (XtPointer) dialog);
5548 XawDialogAddButton(dialog, _("Defer"), PromotionCallback,
5549 (XtPointer) dialog);
5551 XawDialogAddButton(dialog, _("cancel"), PromotionCallback,
5552 (XtPointer) dialog);
5554 XtRealizeWidget(promotionShell);
5555 CatchDeleteWindow(promotionShell, "PromotionPopDown");
5558 XtSetArg(args[j], XtNwidth, &pw_width); j++;
5559 XtGetValues(promotionShell, args, j);
5561 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
5562 lineGap + squareSize/3 +
5563 ((toY == BOARD_HEIGHT-1) ^ (flipView) ?
5564 0 : 6*(squareSize + lineGap)), &x, &y);
5567 XtSetArg(args[j], XtNx, x); j++;
5568 XtSetArg(args[j], XtNy, y); j++;
5569 XtSetValues(promotionShell, args, j);
5571 XtPopup(promotionShell, XtGrabNone);
5576 void PromotionPopDown()
5578 if (!promotionUp) return;
5579 XtPopdown(promotionShell);
5580 XtDestroyWidget(promotionShell);
5581 promotionUp = False;
5584 void PromotionCallback(w, client_data, call_data)
5586 XtPointer client_data, call_data;
5592 XtSetArg(args[0], XtNlabel, &name);
5593 XtGetValues(w, args, 1);
5597 if (fromX == -1) return;
5599 if (strcmp(name, _("cancel")) == 0) {
5603 } else if (strcmp(name, _("Knight")) == 0) {
5605 } else if (strcmp(name, _("Promote")) == 0) {
5607 } else if (strcmp(name, _("Defer")) == 0) {
5610 promoChar = ToLower(name[0]);
5613 UserMoveEvent(fromX, fromY, toX, toY, promoChar);
5615 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
5616 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
5621 void ErrorCallback(w, client_data, call_data)
5623 XtPointer client_data, call_data;
5626 XtPopdown(w = XtParent(XtParent(XtParent(w))));
5628 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
5634 if (!errorUp) return;
5636 XtPopdown(errorShell);
5637 XtDestroyWidget(errorShell);
5638 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
5641 void ErrorPopUp(title, label, modal)
5642 char *title, *label;
5647 printf ("DEBUG: error %s %s\n\n",title,label);
5649 dialog = gtk_message_dialog_new(GTK_WINDOW(GUI_Window),
5650 GTK_DIALOG_DESTROY_WITH_PARENT,
5655 gtk_window_set_title(GTK_WINDOW(dialog),(gchar *) title);
5658 gtk_dialog_run(GTK_DIALOG(dialog));
5659 gtk_widget_destroy(GTK_WIDGET(dialog));
5663 g_signal_connect_swapped (dialog, "response",
5664 G_CALLBACK (ErrorPopDownProc),
5667 gtk_widget_show(GTK_WIDGET(dialog));
5671 /* Disable all user input other than deleting the window */
5672 static int frozen = 0;
5676 /* Grab by a widget that doesn't accept input */
5677 // XtAddGrab(messageWidget, TRUE, FALSE);
5681 /* Undo a FreezeUI */
5684 if (!frozen) return;
5685 XtRemoveGrab(messageWidget);
5689 char *ModeToWidgetName(mode)
5693 case BeginningOfGame:
5694 if (appData.icsActive)
5695 return "menuMode.ICS Client";
5696 else if (appData.noChessProgram ||
5697 *appData.cmailGameName != NULLCHAR)
5698 return "menuMode.Edit Game";
5700 return "menuMode.Machine Black";
5701 case MachinePlaysBlack:
5702 return "menuMode.Machine Black";
5703 case MachinePlaysWhite:
5704 return "menuMode.Machine White";
5706 return "menuMode.Analysis Mode";
5708 return "menuMode.Analyze File";
5709 case TwoMachinesPlay:
5710 return "menuMode.Two Machines";
5712 return "menuMode.Edit Game";
5713 case PlayFromGameFile:
5714 return "menuFile.Load Game";
5716 return "menuMode.Edit Position";
5718 return "menuMode.Training";
5719 case IcsPlayingWhite:
5720 case IcsPlayingBlack:
5724 return "menuMode.ICS Client";
5731 void ModeHighlight()
5734 static int oldPausing = FALSE;
5735 static GameMode oldmode = (GameMode) -1;
5738 if (!boardWidget || !XtIsRealized(boardWidget)) return;
5740 if (pausing != oldPausing) {
5741 oldPausing = pausing;
5743 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5745 XtSetArg(args[0], XtNleftBitmap, None);
5747 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Pause"),
5750 if (appData.showButtonBar) {
5753 XtSetArg(args[0], XtNbackground, buttonForegroundPixel);
5754 XtSetArg(args[1], XtNforeground, buttonBackgroundPixel);
5756 XtSetArg(args[0], XtNbackground, buttonBackgroundPixel);
5757 XtSetArg(args[1], XtNforeground, buttonForegroundPixel);
5760 /* Always toggle, don't set. Previous code messes up when
5761 invoked while the button is pressed, as releasing it
5762 toggles the state again. */
5765 XtSetArg(args[0], XtNbackground, &oldbg);
5766 XtSetArg(args[1], XtNforeground, &oldfg);
5767 XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON),
5769 XtSetArg(args[0], XtNbackground, oldfg);
5770 XtSetArg(args[1], XtNforeground, oldbg);
5773 XtSetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
5777 wname = ModeToWidgetName(oldmode);
5778 if (wname != NULL) {
5779 XtSetArg(args[0], XtNleftBitmap, None);
5780 XtSetValues(XtNameToWidget(menuBarWidget, wname), args, 1);
5782 wname = ModeToWidgetName(gameMode);
5783 if (wname != NULL) {
5784 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5785 XtSetValues(XtNameToWidget(menuBarWidget, wname), args, 1);
5789 /* Maybe all the enables should be handled here, not just this one */
5790 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Training"),
5791 gameMode == Training || gameMode == PlayFromGameFile);
5796 * Button/menu procedures
5799 int LoadGamePopUp(f, gameNumber, title)
5804 cmailMsgLoaded = FALSE;
5805 if (gameNumber == 0) {
5806 int error = GameListBuild(f);
5808 DisplayError(_("Cannot build game list"), error);
5809 } else if (!ListEmpty(&gameList) &&
5810 ((ListGame *) gameList.tailPred)->number > 1) {
5811 GameListPopUp(f, title);
5817 return LoadGame(f, gameNumber, title, FALSE);
5821 void LoadNextPositionProc(w, event, prms, nprms)
5830 void LoadPrevPositionProc(w, event, prms, nprms)
5839 void ReloadPositionProc(w, event, prms, nprms)
5848 void LoadPositionProc(w, event, prms, nprms)
5854 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
5857 FileNamePopUp(_("Load position file name?"), "", LoadPosition, "rb");
5860 void SaveGameProc(w, event, prms, nprms)
5866 FileNamePopUp(_("Save game file name?"),
5867 DefaultFileName(appData.oldSaveStyle ? "game" : "pgn"),
5871 void SavePositionProc(w, event, prms, nprms)
5877 FileNamePopUp(_("Save position file name?"),
5878 DefaultFileName(appData.oldSaveStyle ? "pos" : "fen"),
5882 void ReloadCmailMsgProc(w, event, prms, nprms)
5888 ReloadCmailMsgEvent(FALSE);
5891 void MailMoveProc(w, event, prms, nprms)
5900 /* this variable is shared between CopyPositionProc and SendPositionSelection */
5901 static char *selected_fen_position=NULL;
5904 SendPositionSelection(Widget w, Atom *selection, Atom *target,
5905 Atom *type_return, XtPointer *value_return,
5906 unsigned long *length_return, int *format_return)
5908 char *selection_tmp;
5910 if (!selected_fen_position) return False; /* should never happen */
5911 if (*target == XA_STRING){
5912 /* note: since no XtSelectionDoneProc was registered, Xt will
5913 * automatically call XtFree on the value returned. So have to
5914 * make a copy of it allocated with XtMalloc */
5915 selection_tmp= XtMalloc(strlen(selected_fen_position)+16);
5916 strcpy(selection_tmp, selected_fen_position);
5918 *value_return=selection_tmp;
5919 *length_return=strlen(selection_tmp);
5920 *type_return=XA_STRING;
5921 *format_return = 8; /* bits per byte */
5928 /* note: when called from menu all parameters are NULL, so no clue what the
5929 * Widget which was clicked on was, or what the click event was
5931 void CopyPositionProc(w, event, prms, nprms)
5939 if (selected_fen_position) free(selected_fen_position);
5940 selected_fen_position = (char *)PositionToFEN(currentMove, NULL);
5941 if (!selected_fen_position) return;
5942 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
5944 SendPositionSelection,
5945 NULL/* lose_ownership_proc */ ,
5946 NULL/* transfer_done_proc */);
5948 free(selected_fen_position);
5949 selected_fen_position=NULL;
5953 /* function called when the data to Paste is ready */
5955 PastePositionCB(Widget w, XtPointer client_data, Atom *selection,
5956 Atom *type, XtPointer value, unsigned long *len, int *format)
5959 if (value==NULL || *len==0) return; /* nothing had been selected to copy */
5960 fenstr[*len]='\0'; /* normally this string is terminated, but be safe */
5961 EditPositionPasteFEN(fenstr);
5965 /* called when Paste Position button is pressed,
5966 * all parameters will be NULL */
5967 void PastePositionProc(w, event, prms, nprms)
5973 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
5974 /* (XtSelectionCallbackProc) */ PastePositionCB,
5975 NULL, /* client_data passed to PastePositionCB */
5977 /* better to use the time field from the event that triggered the
5978 * call to this function, but that isn't trivial to get
5986 SendGameSelection(Widget w, Atom *selection, Atom *target,
5987 Atom *type_return, XtPointer *value_return,
5988 unsigned long *length_return, int *format_return)
5990 char *selection_tmp;
5992 if (*target == XA_STRING){
5993 FILE* f = fopen(gameCopyFilename, "r");
5996 if (f == NULL) return False;
6000 selection_tmp = XtMalloc(len + 1);
6001 count = fread(selection_tmp, 1, len, f);
6003 XtFree(selection_tmp);
6006 selection_tmp[len] = NULLCHAR;
6007 *value_return = selection_tmp;
6008 *length_return = len;
6009 *type_return = XA_STRING;
6010 *format_return = 8; /* bits per byte */
6017 /* note: when called from menu all parameters are NULL, so no clue what the
6018 * Widget which was clicked on was, or what the click event was
6020 void CopyGameProc(w, event, prms, nprms)
6028 ret = SaveGameToFile(gameCopyFilename, FALSE);
6031 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
6034 NULL/* lose_ownership_proc */ ,
6035 NULL/* transfer_done_proc */);
6038 /* function called when the data to Paste is ready */
6040 PasteGameCB(Widget w, XtPointer client_data, Atom *selection,
6041 Atom *type, XtPointer value, unsigned long *len, int *format)
6044 if (value == NULL || *len == 0) {
6045 return; /* nothing had been selected to copy */
6047 f = fopen(gamePasteFilename, "w");
6049 DisplayError(_("Can't open temp file"), errno);
6052 fwrite(value, 1, *len, f);
6055 LoadGameFromFile(gamePasteFilename, 0, gamePasteFilename, TRUE);
6058 /* called when Paste Game button is pressed,
6059 * all parameters will be NULL */
6060 void PasteGameProc(w, event, prms, nprms)
6066 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
6067 /* (XtSelectionCallbackProc) */ PasteGameCB,
6068 NULL, /* client_data passed to PasteGameCB */
6070 /* better to use the time field from the event that triggered the
6071 * call to this function, but that isn't trivial to get
6081 SaveGameProc(NULL, NULL, NULL, NULL);
6084 void MachineBlackProc(w, event, prms, nprms)
6090 MachineBlackEvent();
6093 void MachineWhiteProc(w, event, prms, nprms)
6099 MachineWhiteEvent();
6102 void AnalyzeModeProc(w, event, prms, nprms)
6110 if (!first.analysisSupport) {
6111 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
6112 DisplayError(buf, 0);
6115 /* [DM] icsEngineAnalyze [HGM] This is horrible code; reverse the gameMode and isEngineAnalyze tests! */
6116 if (appData.icsActive) {
6117 if (gameMode != IcsObserving) {
6118 sprintf(buf,_("You are not observing a game"));
6119 DisplayError(buf, 0);
6121 if (appData.icsEngineAnalyze) {
6122 if (appData.debugMode)
6123 fprintf(debugFP, _("Found unexpected active ICS engine analyze \n"));
6129 /* if enable, use want disable icsEngineAnalyze */
6130 if (appData.icsEngineAnalyze) {
6135 appData.icsEngineAnalyze = TRUE;
6136 if (appData.debugMode)
6137 fprintf(debugFP, _("ICS engine analyze starting... \n"));
6139 if (!appData.showThinking)
6140 ShowThinkingProc(w,event,prms,nprms);
6145 void AnalyzeFileProc(w, event, prms, nprms)
6151 if (!first.analysisSupport) {
6153 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
6154 DisplayError(buf, 0);
6159 if (!appData.showThinking)
6160 ShowThinkingProc(w,event,prms,nprms);
6163 FileNamePopUp(_("File to analyze"), "", LoadGamePopUp, "rb");
6164 AnalysisPeriodicEvent(1);
6167 void TwoMachinesProc(w, event, prms, nprms)
6176 void IcsClientProc(w, event, prms, nprms)
6185 void EditGameProc(w, event, prms, nprms)
6194 void EditPositionProc(w, event, prms, nprms)
6200 EditPositionEvent();
6203 void TrainingProc(w, event, prms, nprms)
6212 void EditCommentProc(w, event, prms, nprms)
6219 EditCommentPopDown();
6225 void IcsInputBoxProc(w, event, prms, nprms)
6231 if (ICSInputBoxUp) {
6232 ICSInputBoxPopDown();
6238 void AcceptProc(w, event, prms, nprms)
6247 void DeclineProc(w, event, prms, nprms)
6256 void RematchProc(w, event, prms, nprms)
6265 void CallFlagProc(w, event, prms, nprms)
6274 void DrawProc(w, event, prms, nprms)
6283 void AbortProc(w, event, prms, nprms)
6292 void AdjournProc(w, event, prms, nprms)
6301 void ResignProc(w, event, prms, nprms)
6310 void AdjuWhiteProc(w, event, prms, nprms)
6316 UserAdjudicationEvent(+1);
6319 void AdjuBlackProc(w, event, prms, nprms)
6325 UserAdjudicationEvent(-1);
6328 void AdjuDrawProc(w, event, prms, nprms)
6334 UserAdjudicationEvent(0);
6337 void EnterKeyProc(w, event, prms, nprms)
6343 if (ICSInputBoxUp == True)
6347 void StopObservingProc(w, event, prms, nprms)
6353 StopObservingEvent();
6356 void StopExaminingProc(w, event, prms, nprms)
6362 StopExaminingEvent();
6366 void ForwardProc(w, event, prms, nprms)
6376 void BackwardProc(w, event, prms, nprms)
6385 void ToStartProc(w, event, prms, nprms)
6394 void ToEndProc(w, event, prms, nprms)
6403 void RevertProc(w, event, prms, nprms)
6412 void TruncateGameProc(w, event, prms, nprms)
6418 TruncateGameEvent();
6420 void RetractMoveProc(w, event, prms, nprms)
6429 void MoveNowProc(w, event, prms, nprms)
6439 void AlwaysQueenProc(w, event, prms, nprms)
6447 appData.alwaysPromoteToQueen = !appData.alwaysPromoteToQueen;
6449 if (appData.alwaysPromoteToQueen) {
6450 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6452 XtSetArg(args[0], XtNleftBitmap, None);
6454 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
6458 void AnimateDraggingProc(w, event, prms, nprms)
6466 appData.animateDragging = !appData.animateDragging;
6468 if (appData.animateDragging) {
6469 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6472 XtSetArg(args[0], XtNleftBitmap, None);
6474 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Dragging"),
6478 void AnimateMovingProc(w, event, prms, nprms)
6486 appData.animate = !appData.animate;
6488 if (appData.animate) {
6489 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6492 XtSetArg(args[0], XtNleftBitmap, None);
6494 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
6498 void AutocommProc(w, event, prms, nprms)
6506 appData.autoComment = !appData.autoComment;
6508 if (appData.autoComment) {
6509 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6511 XtSetArg(args[0], XtNleftBitmap, None);
6513 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
6518 void AutoflagProc(w, event, prms, nprms)
6526 appData.autoCallFlag = !appData.autoCallFlag;
6528 if (appData.autoCallFlag) {
6529 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6531 XtSetArg(args[0], XtNleftBitmap, None);
6533 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
6537 void AutoflipProc(w, event, prms, nprms)
6545 appData.autoFlipView = !appData.autoFlipView;
6547 if (appData.autoFlipView) {
6548 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6550 XtSetArg(args[0], XtNleftBitmap, None);
6552 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flip View"),
6556 void AutobsProc(w, event, prms, nprms)
6564 appData.autoObserve = !appData.autoObserve;
6566 if (appData.autoObserve) {
6567 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6569 XtSetArg(args[0], XtNleftBitmap, None);
6571 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
6575 void AutoraiseProc(w, event, prms, nprms)
6583 appData.autoRaiseBoard = !appData.autoRaiseBoard;
6585 if (appData.autoRaiseBoard) {
6586 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6588 XtSetArg(args[0], XtNleftBitmap, None);
6590 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Raise Board"),
6594 void AutosaveProc(w, event, prms, nprms)
6602 appData.autoSaveGames = !appData.autoSaveGames;
6604 if (appData.autoSaveGames) {
6605 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6607 XtSetArg(args[0], XtNleftBitmap, None);
6609 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
6613 void BlindfoldProc(w, event, prms, nprms)
6621 appData.blindfold = !appData.blindfold;
6623 if (appData.blindfold) {
6624 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6626 XtSetArg(args[0], XtNleftBitmap, None);
6628 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Blindfold"),
6631 DrawPosition(True, NULL);
6634 void TestLegalityProc(w, event, prms, nprms)
6642 appData.testLegality = !appData.testLegality;
6644 if (appData.testLegality) {
6645 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6647 XtSetArg(args[0], XtNleftBitmap, None);
6649 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Test Legality"),
6654 void FlashMovesProc(w, event, prms, nprms)
6662 if (appData.flashCount == 0) {
6663 appData.flashCount = 3;
6665 appData.flashCount = -appData.flashCount;
6668 if (appData.flashCount > 0) {
6669 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6671 XtSetArg(args[0], XtNleftBitmap, None);
6673 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flash Moves"),
6677 void FlipViewProc(w, event, prms, nprms)
6683 flipView = !flipView;
6684 DrawPosition(True, NULL);
6687 void GetMoveListProc(w, event, prms, nprms)
6695 appData.getMoveList = !appData.getMoveList;
6697 if (appData.getMoveList) {
6698 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6701 XtSetArg(args[0], XtNleftBitmap, None);
6703 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
6708 void HighlightDraggingProc(w, event, prms, nprms)
6716 appData.highlightDragging = !appData.highlightDragging;
6718 if (appData.highlightDragging) {
6719 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6721 XtSetArg(args[0], XtNleftBitmap, None);
6723 XtSetValues(XtNameToWidget(menuBarWidget,
6724 "menuOptions.Highlight Dragging"), args, 1);
6728 void HighlightLastMoveProc(w, event, prms, nprms)
6736 appData.highlightLastMove = !appData.highlightLastMove;
6738 if (appData.highlightLastMove) {
6739 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6741 XtSetArg(args[0], XtNleftBitmap, None);
6743 XtSetValues(XtNameToWidget(menuBarWidget,
6744 "menuOptions.Highlight Last Move"), args, 1);
6747 void IcsAlarmProc(w, event, prms, nprms)
6755 appData.icsAlarm = !appData.icsAlarm;
6757 if (appData.icsAlarm) {
6758 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6760 XtSetArg(args[0], XtNleftBitmap, None);
6762 XtSetValues(XtNameToWidget(menuBarWidget,
6763 "menuOptions.ICS Alarm"), args, 1);
6766 void MoveSoundProc(w, event, prms, nprms)
6774 appData.ringBellAfterMoves = !appData.ringBellAfterMoves;
6776 if (appData.ringBellAfterMoves) {
6777 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6779 XtSetArg(args[0], XtNleftBitmap, None);
6781 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
6786 void OldSaveStyleProc(w, event, prms, nprms)
6794 appData.oldSaveStyle = !appData.oldSaveStyle;
6796 if (appData.oldSaveStyle) {
6797 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6799 XtSetArg(args[0], XtNleftBitmap, None);
6801 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Old Save Style"),
6805 void PeriodicUpdatesProc(w, event, prms, nprms)
6813 PeriodicUpdatesEvent(!appData.periodicUpdates);
6815 if (appData.periodicUpdates) {
6816 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6818 XtSetArg(args[0], XtNleftBitmap, None);
6820 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Periodic Updates"),
6824 void PonderNextMoveProc(w, event, prms, nprms)
6832 PonderNextMoveEvent(!appData.ponderNextMove);
6834 if (appData.ponderNextMove) {
6835 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6837 XtSetArg(args[0], XtNleftBitmap, None);
6839 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Ponder Next Move"),
6843 void PopupExitMessageProc(w, event, prms, nprms)
6851 appData.popupExitMessage = !appData.popupExitMessage;
6853 if (appData.popupExitMessage) {
6854 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6856 XtSetArg(args[0], XtNleftBitmap, None);
6858 XtSetValues(XtNameToWidget(menuBarWidget,
6859 "menuOptions.Popup Exit Message"), args, 1);
6862 void PopupMoveErrorsProc(w, event, prms, nprms)
6870 appData.popupMoveErrors = !appData.popupMoveErrors;
6872 if (appData.popupMoveErrors) {
6873 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6875 XtSetArg(args[0], XtNleftBitmap, None);
6877 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Popup Move Errors"),
6881 void PremoveProc(w, event, prms, nprms)
6889 appData.premove = !appData.premove;
6891 if (appData.premove) {
6892 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6894 XtSetArg(args[0], XtNleftBitmap, None);
6896 XtSetValues(XtNameToWidget(menuBarWidget,
6897 "menuOptions.Premove"), args, 1);
6900 void QuietPlayProc(w, event, prms, nprms)
6908 appData.quietPlay = !appData.quietPlay;
6910 if (appData.quietPlay) {
6911 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6913 XtSetArg(args[0], XtNleftBitmap, None);
6915 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Quiet Play"),
6919 void ShowThinkingProc(w, event, prms, nprms)
6927 appData.showThinking = !appData.showThinking; // [HGM] thinking: tken out of ShowThinkingEvent
6928 ShowThinkingEvent();
6930 // [HGM] thinking: currently no suc menu item; replaced by Hide Thinking (From Human)
6931 if (appData.showThinking) {
6932 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6934 XtSetArg(args[0], XtNleftBitmap, None);
6936 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Thinking"),
6941 void HideThinkingProc(w, event, prms, nprms)
6949 appData.hideThinkingFromHuman = !appData.hideThinkingFromHuman; // [HGM] thinking: tken out of ShowThinkingEvent
6950 ShowThinkingEvent();
6952 if (appData.hideThinkingFromHuman) {
6953 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6955 XtSetArg(args[0], XtNleftBitmap, None);
6957 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
6961 void InfoProc(w, event, prms, nprms)
6968 snprintf(buf, sizeof(buf), "xterm -e info --directory %s --directory . -f %s &",
6973 void ManProc(w, event, prms, nprms)
6981 if (nprms && *nprms > 0)
6985 snprintf(buf, sizeof(buf), "xterm -e man %s &", name);
6989 void HintProc(w, event, prms, nprms)
6998 void BookProc(w, event, prms, nprms)
7007 void DebugProc(w, event, prms, nprms)
7013 appData.debugMode = !appData.debugMode;
7016 void AboutGameProc(w, event, prms, nprms)
7025 void NothingProc(w, event, prms, nprms)
7034 void Iconify(w, event, prms, nprms)
7043 XtSetArg(args[0], XtNiconic, True);
7044 XtSetValues(shellWidget, args, 1);
7047 void DisplayMessage(message, extMessage)
7048 gchar *message, *extMessage;
7055 snprintf(buf, sizeof(buf), "%s %s", message, extMessage);
7058 message = extMessage;
7062 printf("TODO: message %s\n",message);
7063 gtk_label_set_text( GTK_LABEL(gtk_builder_get_object (builder, "Messages")),message);
7066 void DisplayTitle(text)
7071 char title[MSG_SIZ];
7074 if (text == NULL) text = "";
7076 if (appData.titleInWindow) {
7078 XtSetArg(args[i], XtNlabel, text); i++;
7079 XtSetValues(titleWidget, args, i);
7082 if (*text != NULLCHAR) {
7084 strcpy(title, text);
7085 } else if (appData.icsActive) {
7086 snprintf(icon, sizeof(icon), "%s", appData.icsHost);
7087 snprintf(title, sizeof(title), "%s: %s", programName, appData.icsHost);
7088 } else if (appData.cmailGameName[0] != NULLCHAR) {
7089 snprintf(icon, sizeof(icon), "%s", "CMail");
7090 snprintf(title,sizeof(title), "%s: %s", programName, "CMail");
7092 // [HGM] license: This stuff should really be done in back-end, but WinBoard already had a pop-up for it
7093 } else if (gameInfo.variant == VariantGothic) {
7094 strcpy(icon, programName);
7095 strcpy(title, GOTHIC);
7098 } else if (gameInfo.variant == VariantFalcon) {
7099 strcpy(icon, programName);
7100 strcpy(title, FALCON);
7102 } else if (appData.noChessProgram) {
7103 strcpy(icon, programName);
7104 strcpy(title, programName);
7106 strcpy(icon, first.tidy);
7107 snprintf(title,sizeof(title), "%s: %s", programName, first.tidy);
7110 XtSetArg(args[i], XtNiconName, (XtArgVal) icon); i++;
7111 XtSetArg(args[i], XtNtitle, (XtArgVal) title); i++;
7112 XtSetValues(shellWidget, args, i);
7116 void DisplayError(message, error)
7123 if (appData.debugMode || appData.matchMode) {
7124 fprintf(stderr, "%s: %s\n", programName, message);
7127 if (appData.debugMode || appData.matchMode) {
7128 fprintf(stderr, "%s: %s: %s\n",
7129 programName, message, strerror(error));
7131 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
7134 ErrorPopUp(_("Error"), message, FALSE);
7138 void DisplayMoveError(message)
7143 DrawPosition(FALSE, NULL);
7144 if (appData.debugMode || appData.matchMode) {
7145 fprintf(stderr, "%s: %s\n", programName, message);
7147 if (appData.popupMoveErrors) {
7148 ErrorPopUp(_("Error"), message, FALSE);
7150 DisplayMessage(message, "");
7155 void DisplayFatalError(message, error, status)
7161 errorExitStatus = status;
7163 fprintf(stderr, "%s: %s\n", programName, message);
7165 fprintf(stderr, "%s: %s: %s\n",
7166 programName, message, strerror(error));
7167 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
7170 if (appData.popupExitMessage && boardWidget && XtIsRealized(boardWidget)) {
7171 ErrorPopUp(status ? _("Fatal Error") : _("Exiting"), message, TRUE);
7177 void DisplayInformation(message)
7181 ErrorPopUp(_("Information"), message, TRUE);
7184 void DisplayNote(message)
7188 ErrorPopUp(_("Note"), message, FALSE);
7192 NullXErrorCheck(dpy, error_event)
7194 XErrorEvent *error_event;
7199 void DisplayIcsInteractionTitle(message)
7202 if (oldICSInteractionTitle == NULL) {
7203 /* Magic to find the old window title, adapted from vim */
7204 char *wina = getenv("WINDOWID");
7206 Window win = (Window) atoi(wina);
7207 Window root, parent, *children;
7208 unsigned int nchildren;
7209 int (*oldHandler)() = XSetErrorHandler(NullXErrorCheck);
7211 if (XFetchName(xDisplay, win, &oldICSInteractionTitle)) break;
7212 if (!XQueryTree(xDisplay, win, &root, &parent,
7213 &children, &nchildren)) break;
7214 if (children) XFree((void *)children);
7215 if (parent == root || parent == 0) break;
7218 XSetErrorHandler(oldHandler);
7220 if (oldICSInteractionTitle == NULL) {
7221 oldICSInteractionTitle = "xterm";
7224 printf("\033]0;%s\007", message);
7228 char pendingReplyPrefix[MSG_SIZ];
7229 ProcRef pendingReplyPR;
7231 void AskQuestionProc(w, event, prms, nprms)
7238 fprintf(stderr, _("AskQuestionProc needed 4 parameters, got %d\n"),
7242 AskQuestionEvent(prms[0], prms[1], prms[2], prms[3]);
7245 void AskQuestionPopDown()
7247 if (!askQuestionUp) return;
7248 XtPopdown(askQuestionShell);
7249 XtDestroyWidget(askQuestionShell);
7250 askQuestionUp = False;
7253 void AskQuestionReplyAction(w, event, prms, nprms)
7263 reply = XawDialogGetValueString(w = XtParent(w));
7264 strcpy(buf, pendingReplyPrefix);
7265 if (*buf) strcat(buf, " ");
7268 OutputToProcess(pendingReplyPR, buf, strlen(buf), &err);
7269 AskQuestionPopDown();
7271 if (err) DisplayFatalError(_("Error writing to chess program"), err, 0);
7274 void AskQuestionCallback(w, client_data, call_data)
7276 XtPointer client_data, call_data;
7281 XtSetArg(args[0], XtNlabel, &name);
7282 XtGetValues(w, args, 1);
7284 if (strcmp(name, _("cancel")) == 0) {
7285 AskQuestionPopDown();
7287 AskQuestionReplyAction(w, NULL, NULL, NULL);
7291 void AskQuestion(title, question, replyPrefix, pr)
7292 char *title, *question, *replyPrefix;
7296 Widget popup, layout, dialog, edit;
7302 strcpy(pendingReplyPrefix, replyPrefix);
7303 pendingReplyPR = pr;
7306 XtSetArg(args[i], XtNresizable, True); i++;
7307 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
7308 askQuestionShell = popup =
7309 XtCreatePopupShell(title, transientShellWidgetClass,
7310 shellWidget, args, i);
7313 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
7314 layoutArgs, XtNumber(layoutArgs));
7317 XtSetArg(args[i], XtNlabel, question); i++;
7318 XtSetArg(args[i], XtNvalue, ""); i++;
7319 XtSetArg(args[i], XtNborderWidth, 0); i++;
7320 dialog = XtCreateManagedWidget("question", dialogWidgetClass,
7323 XawDialogAddButton(dialog, _("enter"), AskQuestionCallback,
7324 (XtPointer) dialog);
7325 XawDialogAddButton(dialog, _("cancel"), AskQuestionCallback,
7326 (XtPointer) dialog);
7328 XtRealizeWidget(popup);
7329 CatchDeleteWindow(popup, "AskQuestionPopDown");
7331 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
7332 &x, &y, &win_x, &win_y, &mask);
7334 XtSetArg(args[0], XtNx, x - 10);
7335 XtSetArg(args[1], XtNy, y - 30);
7336 XtSetValues(popup, args, 2);
7338 XtPopup(popup, XtGrabExclusive);
7339 askQuestionUp = True;
7341 edit = XtNameToWidget(dialog, "*value");
7342 XtSetKeyboardFocus(popup, edit);
7350 if (*name == NULLCHAR) {
7352 } else if (strcmp(name, "$") == 0) {
7353 putc(BELLCHAR, stderr);
7356 snprintf(buf, sizeof(buf), "%s '%s' &", appData.soundProgram, name);
7364 PlaySound(appData.soundMove);
7370 PlaySound(appData.soundIcsWin);
7376 PlaySound(appData.soundIcsLoss);
7382 PlaySound(appData.soundIcsDraw);
7386 PlayIcsUnfinishedSound()
7388 PlaySound(appData.soundIcsUnfinished);
7394 PlaySound(appData.soundIcsAlarm);
7400 system("stty echo");
7406 system("stty -echo");
7410 Colorize(cc, continuation)
7415 int count, outCount, error;
7417 if (textColors[(int)cc].bg > 0) {
7418 if (textColors[(int)cc].fg > 0) {
7419 sprintf(buf, "\033[0;%d;%d;%dm", textColors[(int)cc].attr,
7420 textColors[(int)cc].fg, textColors[(int)cc].bg);
7422 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
7423 textColors[(int)cc].bg);
7426 if (textColors[(int)cc].fg > 0) {
7427 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
7428 textColors[(int)cc].fg);
7430 sprintf(buf, "\033[0;%dm", textColors[(int)cc].attr);
7433 count = strlen(buf);
7434 outCount = OutputToProcess(NoProc, buf, count, &error);
7435 if (outCount < count) {
7436 DisplayFatalError(_("Error writing to display"), error, 1);
7439 if (continuation) return;
7442 PlaySound(appData.soundShout);
7445 PlaySound(appData.soundSShout);
7448 PlaySound(appData.soundChannel1);
7451 PlaySound(appData.soundChannel);
7454 PlaySound(appData.soundKibitz);
7457 PlaySound(appData.soundTell);
7459 case ColorChallenge:
7460 PlaySound(appData.soundChallenge);
7463 PlaySound(appData.soundRequest);
7466 PlaySound(appData.soundSeek);
7477 return getpwuid(getuid())->pw_name;
7480 static char *ExpandPathName(path)
7483 static char static_buf[2000];
7484 char *d, *s, buf[2000];
7490 while (*s && isspace(*s))
7499 if (*(s+1) == '/') {
7500 strcpy(d, getpwuid(getuid())->pw_dir);
7505 *strchr(buf, '/') = 0;
7506 pwd = getpwnam(buf);
7509 fprintf(stderr, _("ERROR: Unknown user %s (in path %s)\n"),
7513 strcpy(d, pwd->pw_dir);
7514 strcat(d, strchr(s+1, '/'));
7525 static char host_name[MSG_SIZ];
7527 #if HAVE_GETHOSTNAME
7528 gethostname(host_name, MSG_SIZ);
7530 #else /* not HAVE_GETHOSTNAME */
7531 # if HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H
7532 sysinfo(SI_HOSTNAME, host_name, MSG_SIZ);
7534 # else /* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
7536 # endif/* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
7537 #endif /* not HAVE_GETHOSTNAME */
7540 XtIntervalId delayedEventTimerXID = 0;
7541 DelayedEventCallback delayedEventCallback = 0;
7546 delayedEventTimerXID = 0;
7547 delayedEventCallback();
7551 ScheduleDelayedEvent(cb, millisec)
7552 DelayedEventCallback cb; long millisec;
7554 delayedEventCallback = cb;
7555 delayedEventTimerXID =
7556 XtAppAddTimeOut(appContext, millisec,
7557 (XtTimerCallbackProc) FireDelayedEvent, (XtPointer) 0);
7560 DelayedEventCallback
7563 if (delayedEventTimerXID) {
7564 return delayedEventCallback;
7571 CancelDelayedEvent()
7573 if (delayedEventTimerXID) {
7574 XtRemoveTimeOut(delayedEventTimerXID);
7575 delayedEventTimerXID = 0;
7579 XtIntervalId loadGameTimerXID = 0;
7581 int LoadGameTimerRunning()
7583 return loadGameTimerXID != 0;
7586 int StopLoadGameTimer()
7588 if (loadGameTimerXID != 0) {
7589 XtRemoveTimeOut(loadGameTimerXID);
7590 loadGameTimerXID = 0;
7598 LoadGameTimerCallback(arg, id)
7602 loadGameTimerXID = 0;
7607 StartLoadGameTimer(millisec)
7611 XtAppAddTimeOut(appContext, millisec,
7612 (XtTimerCallbackProc) LoadGameTimerCallback,
7616 XtIntervalId analysisClockXID = 0;
7619 AnalysisClockCallback(arg, id)
7623 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile
7624 || appData.icsEngineAnalyze) { // [DM]
7625 AnalysisPeriodicEvent(0);
7626 StartAnalysisClock();
7631 StartAnalysisClock()
7634 XtAppAddTimeOut(appContext, 2000,
7635 (XtTimerCallbackProc) AnalysisClockCallback,
7639 XtIntervalId clockTimerXID = 0;
7641 int ClockTimerRunning()
7643 return clockTimerXID != 0;
7646 int StopClockTimer()
7648 if (clockTimerXID != 0) {
7649 XtRemoveTimeOut(clockTimerXID);
7658 ClockTimerCallback(arg, id)
7667 StartClockTimer(millisec)
7671 XtAppAddTimeOut(appContext, millisec,
7672 (XtTimerCallbackProc) ClockTimerCallback,
7677 DisplayTimerLabel(w, color, timer, highlight)
7686 if (appData.clockMode) {
7687 sprintf(buf, "%s: %s", color, TimeString(timer));
7689 sprintf(buf, "%s ", color);
7691 gtk_label_set_text(GTK_LABEL(w),buf);
7693 /* check for low time warning */
7694 // Pixel foregroundOrWarningColor = timerForegroundPixel;
7697 // appData.lowTimeWarning &&
7698 // (timer / 1000) < appData.icsAlarmTime)
7699 // foregroundOrWarningColor = lowTimeWarningColor;
7701 // if (appData.clockMode) {
7702 // sprintf(buf, "%s: %s", color, TimeString(timer));
7703 // XtSetArg(args[0], XtNlabel, buf);
7705 // sprintf(buf, "%s ", color);
7706 // XtSetArg(args[0], XtNlabel, buf);
7711 // XtSetArg(args[1], XtNbackground, foregroundOrWarningColor);
7712 // XtSetArg(args[2], XtNforeground, timerBackgroundPixel);
7714 // XtSetArg(args[1], XtNbackground, timerBackgroundPixel);
7715 // XtSetArg(args[2], XtNforeground, foregroundOrWarningColor);
7718 // XtSetValues(w, args, 3);
7723 DisplayWhiteClock(timeRemaining, highlight)
7727 if(appData.noGUI) return;
7729 DisplayTimerLabel(GUI_Whiteclock, _("White"), timeRemaining, highlight);
7730 if (highlight && WindowIcon == BlackIcon) {
7731 WindowIcon = WhiteIcon;
7732 gtk_window_set_icon(GTK_WINDOW(GUI_Window),WindowIcon);
7737 DisplayBlackClock(timeRemaining, highlight)
7741 if(appData.noGUI) return;
7742 DisplayTimerLabel(GUI_Blackclock, _("Black"), timeRemaining, highlight);
7743 if (highlight && WindowIcon == WhiteIcon) {
7744 WindowIcon = BlackIcon;
7745 gtk_window_set_icon(GTK_WINDOW(GUI_Window),WindowIcon);
7763 int StartChildProcess(cmdLine, dir, pr)
7770 int to_prog[2], from_prog[2];
7774 if (appData.debugMode) {
7775 fprintf(stderr, "StartChildProcess (dir=\"%s\") %s\n",dir, cmdLine);
7778 /* We do NOT feed the cmdLine to the shell; we just
7779 parse it into blank-separated arguments in the
7780 most simple-minded way possible.
7783 strcpy(buf, cmdLine);
7788 if (p == NULL) break;
7793 SetUpChildIO(to_prog, from_prog);
7795 if ((pid = fork()) == 0) {
7797 // [HGM] PSWBTM: made order resistant against case where fd of created pipe was 0 or 1
7798 close(to_prog[1]); // first close the unused pipe ends
7799 close(from_prog[0]);
7800 dup2(to_prog[0], 0); // to_prog was created first, nd is the only one to use 0 or 1
7801 dup2(from_prog[1], 1);
7802 if(to_prog[0] >= 2) close(to_prog[0]); // if 0 or 1, the dup2 already cosed the original
7803 close(from_prog[1]); // and closing again loses one of the pipes!
7804 if(fileno(stderr) >= 2) // better safe than sorry...
7805 dup2(1, fileno(stderr)); /* force stderr to the pipe */
7807 if (dir[0] != NULLCHAR && chdir(dir) != 0) {
7812 nice(appData.niceEngines); // [HGM] nice: adjust priority of engine proc
7814 execvp(argv[0], argv);
7816 /* If we get here, exec failed */
7821 /* Parent process */
7823 close(from_prog[1]);
7825 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7828 cp->fdFrom = from_prog[0];
7829 cp->fdTo = to_prog[1];
7834 // [HGM] kill: implement the 'hard killing' of AS's Winboard_x
7835 static RETSIGTYPE AlarmCallBack(int n)
7841 DestroyChildProcess(pr, signalType)
7845 ChildProc *cp = (ChildProc *) pr;
7847 if (cp->kind != CPReal) return;
7849 if (signalType == 10) { // [HGM] kill: if it does not terminate in 3 sec, kill
7850 signal(SIGALRM, AlarmCallBack);
7852 if(wait((int *) 0) == -1) { // process does not terminate on its own accord
7853 kill(cp->pid, SIGKILL); // kill it forcefully
7854 wait((int *) 0); // and wait again
7858 kill(cp->pid, signalType == 9 ? SIGKILL : SIGTERM); // [HGM] kill: use hard kill if so requested
7860 /* Process is exiting either because of the kill or because of
7861 a quit command sent by the backend; either way, wait for it to die.
7870 InterruptChildProcess(pr)
7873 ChildProc *cp = (ChildProc *) pr;
7875 if (cp->kind != CPReal) return;
7876 (void) kill(cp->pid, SIGINT); /* stop it thinking */
7879 int OpenTelnet(host, port, pr)
7884 char cmdLine[MSG_SIZ];
7886 if (port[0] == NULLCHAR) {
7887 snprintf(cmdLine, sizeof(cmdLine), "%s %s", appData.telnetProgram, host);
7889 snprintf(cmdLine, sizeof(cmdLine), "%s %s %s", appData.telnetProgram, host, port);
7891 return StartChildProcess(cmdLine, "", pr);
7894 int OpenTCP(host, port, pr)
7900 DisplayFatalError(_("Socket support is not configured in"), 0, 2);
7901 #else /* !OMIT_SOCKETS */
7903 struct sockaddr_in sa;
7905 unsigned short uport;
7908 if ((s = socket(AF_INET, SOCK_STREAM, 6)) < 0) {
7912 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
7913 sa.sin_family = AF_INET;
7914 sa.sin_addr.s_addr = INADDR_ANY;
7915 uport = (unsigned short) 0;
7916 sa.sin_port = htons(uport);
7917 if (bind(s, (struct sockaddr *) &sa, sizeof(struct sockaddr_in)) < 0) {
7921 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
7922 if (!(hp = gethostbyname(host))) {
7924 if (sscanf(host, "%d.%d.%d.%d", &b0, &b1, &b2, &b3) == 4) {
7925 hp = (struct hostent *) calloc(1, sizeof(struct hostent));
7926 hp->h_addrtype = AF_INET;
7928 hp->h_addr_list = (char **) calloc(2, sizeof(char *));
7929 hp->h_addr_list[0] = (char *) malloc(4);
7930 hp->h_addr_list[0][0] = b0;
7931 hp->h_addr_list[0][1] = b1;
7932 hp->h_addr_list[0][2] = b2;
7933 hp->h_addr_list[0][3] = b3;
7938 sa.sin_family = hp->h_addrtype;
7939 uport = (unsigned short) atoi(port);
7940 sa.sin_port = htons(uport);
7941 memcpy((char *) &sa.sin_addr, hp->h_addr, hp->h_length);
7943 if (connect(s, (struct sockaddr *) &sa,
7944 sizeof(struct sockaddr_in)) < 0) {
7948 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7955 #endif /* !OMIT_SOCKETS */
7960 int OpenCommPort(name, pr)
7967 fd = open(name, 2, 0);
7968 if (fd < 0) return errno;
7970 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7980 int OpenLoopback(pr)
7986 SetUpChildIO(to, from);
7988 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7991 cp->fdFrom = to[0]; /* note not from[0]; we are doing a loopback */
7998 int OpenRcmd(host, user, cmd, pr)
7999 char *host, *user, *cmd;
8002 DisplayFatalError(_("internal rcmd not implemented for Unix"), 0, 1);
8006 #define INPUT_SOURCE_BUF_SIZE 8192
8015 char buf[INPUT_SOURCE_BUF_SIZE];
8020 DoInputCallback(closure, source, xid)
8025 InputSource *is = (InputSource *) closure;
8030 if (is->lineByLine) {
8031 count = read(is->fd, is->unused,
8032 INPUT_SOURCE_BUF_SIZE - (is->unused - is->buf));
8034 (is->func)(is, is->closure, is->buf, count, count ? errno : 0);
8037 is->unused += count;
8039 while (p < is->unused) {
8040 q = memchr(p, '\n', is->unused - p);
8041 if (q == NULL) break;
8043 (is->func)(is, is->closure, p, q - p, 0);
8047 while (p < is->unused) {
8052 count = read(is->fd, is->buf, INPUT_SOURCE_BUF_SIZE);
8057 (is->func)(is, is->closure, is->buf, count, error);
8061 InputSourceRef AddInputSource(pr, lineByLine, func, closure)
8068 ChildProc *cp = (ChildProc *) pr;
8070 is = (InputSource *) calloc(1, sizeof(InputSource));
8071 is->lineByLine = lineByLine;
8075 is->fd = fileno(stdin);
8077 is->kind = cp->kind;
8078 is->fd = cp->fdFrom;
8081 is->unused = is->buf;
8084 is->xid = XtAppAddInput(appContext, is->fd,
8085 (XtPointer) (XtInputReadMask),
8086 (XtInputCallbackProc) DoInputCallback,
8088 is->closure = closure;
8089 return (InputSourceRef) is;
8093 RemoveInputSource(isr)
8096 InputSource *is = (InputSource *) isr;
8098 if (is->xid == 0) return;
8099 XtRemoveInput(is->xid);
8103 int OutputToProcess(pr, message, count, outError)
8109 ChildProc *cp = (ChildProc *) pr;
8113 outCount = fwrite(message, 1, count, stdout);
8115 outCount = write(cp->fdTo, message, count);
8125 /* Output message to process, with "ms" milliseconds of delay
8126 between each character. This is needed when sending the logon
8127 script to ICC, which for some reason doesn't like the
8128 instantaneous send. */
8129 int OutputToProcessDelayed(pr, message, count, outError, msdelay)
8136 ChildProc *cp = (ChildProc *) pr;
8141 r = write(cp->fdTo, message++, 1);
8154 /**** Animation code by Hugh Fisher, DCS, ANU.
8156 Known problem: if a window overlapping the board is
8157 moved away while a piece is being animated underneath,
8158 the newly exposed area won't be updated properly.
8159 I can live with this.
8161 Known problem: if you look carefully at the animation
8162 of pieces in mono mode, they are being drawn as solid
8163 shapes without interior detail while moving. Fixing
8164 this would be a major complication for minimal return.
8167 /* Masks for XPM pieces. Black and white pieces can have
8168 different shapes, but in the interest of retaining my
8169 sanity pieces must have the same outline on both light
8170 and dark squares, and all pieces must use the same
8171 background square colors/images. */
8173 static int xpmDone = 0;
8176 CreateAnimMasks (pieceDepth)
8183 unsigned long plane;
8186 /* Need a bitmap just to get a GC with right depth */
8187 buf = XCreatePixmap(xDisplay, xBoardWindow,
8189 values.foreground = 1;
8190 values.background = 0;
8191 /* Don't use XtGetGC, not read only */
8192 maskGC = XCreateGC(xDisplay, buf,
8193 GCForeground | GCBackground, &values);
8194 XFreePixmap(xDisplay, buf);
8196 buf = XCreatePixmap(xDisplay, xBoardWindow,
8197 squareSize, squareSize, pieceDepth);
8198 values.foreground = XBlackPixel(xDisplay, xScreen);
8199 values.background = XWhitePixel(xDisplay, xScreen);
8200 bufGC = XCreateGC(xDisplay, buf,
8201 GCForeground | GCBackground, &values);
8203 for (piece = WhitePawn; piece <= BlackKing; piece++) {
8204 /* Begin with empty mask */
8205 if(!xpmDone) // [HGM] pieces: keep using existing
8206 xpmMask[piece] = XCreatePixmap(xDisplay, xBoardWindow,
8207 squareSize, squareSize, 1);
8208 XSetFunction(xDisplay, maskGC, GXclear);
8209 XFillRectangle(xDisplay, xpmMask[piece], maskGC,
8210 0, 0, squareSize, squareSize);
8212 /* Take a copy of the piece */
8217 XSetFunction(xDisplay, bufGC, GXcopy);
8218 XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % (int)BlackPawn],
8220 0, 0, squareSize, squareSize, 0, 0);
8222 /* XOR the background (light) over the piece */
8223 XSetFunction(xDisplay, bufGC, GXxor);
8225 XCopyArea(xDisplay, xpmLightSquare, buf, bufGC,
8226 0, 0, squareSize, squareSize, 0, 0);
8228 XSetForeground(xDisplay, bufGC, lightSquareColor);
8229 XFillRectangle(xDisplay, buf, bufGC, 0, 0, squareSize, squareSize);
8232 /* We now have an inverted piece image with the background
8233 erased. Construct mask by just selecting all the non-zero
8234 pixels - no need to reconstruct the original image. */
8235 XSetFunction(xDisplay, maskGC, GXor);
8237 /* Might be quicker to download an XImage and create bitmap
8238 data from it rather than this N copies per piece, but it
8239 only takes a fraction of a second and there is a much
8240 longer delay for loading the pieces. */
8241 for (n = 0; n < pieceDepth; n ++) {
8242 XCopyPlane(xDisplay, buf, xpmMask[piece], maskGC,
8243 0, 0, squareSize, squareSize,
8249 XFreePixmap(xDisplay, buf);
8250 XFreeGC(xDisplay, bufGC);
8251 XFreeGC(xDisplay, maskGC);
8255 InitAnimState (anim, info)
8257 XWindowAttributes * info;
8262 /* Each buffer is square size, same depth as window */
8263 anim->saveBuf = XCreatePixmap(xDisplay, xBoardWindow,
8264 squareSize, squareSize, info->depth);
8265 anim->newBuf = XCreatePixmap(xDisplay, xBoardWindow,
8266 squareSize, squareSize, info->depth);
8268 /* Create a plain GC for blitting */
8269 mask = GCForeground | GCBackground | GCFunction |
8270 GCPlaneMask | GCGraphicsExposures;
8271 values.foreground = XBlackPixel(xDisplay, xScreen);
8272 values.background = XWhitePixel(xDisplay, xScreen);
8273 values.function = GXcopy;
8274 values.plane_mask = AllPlanes;
8275 values.graphics_exposures = False;
8276 anim->blitGC = XCreateGC(xDisplay, xBoardWindow, mask, &values);
8278 /* Piece will be copied from an existing context at
8279 the start of each new animation/drag. */
8280 anim->pieceGC = XCreateGC(xDisplay, xBoardWindow, 0, &values);
8282 /* Outline will be a read-only copy of an existing */
8283 anim->outlineGC = None;
8289 static VariantClass old = (VariantClass) -1; // [HGM] pieces: redo every time variant changes
8290 XWindowAttributes info;
8292 if (xpmDone && gameInfo.variant == old) return;
8293 if(xpmDone) old = gameInfo.variant; // first time pieces might not be created yet
8294 // XGetWindowAttributes(xDisplay, xBoardWindow, &info);
8296 InitAnimState(&game, &info);
8297 InitAnimState(&player, &info);
8299 /* For XPM pieces, we need bitmaps to use as masks. */
8301 CreateAnimMasks(info.depth);
8307 static Boolean frameWaiting;
8309 static RETSIGTYPE FrameAlarm (sig)
8312 frameWaiting = False;
8313 /* In case System-V style signals. Needed?? */
8314 signal(SIGALRM, FrameAlarm);
8321 struct itimerval delay;
8323 XSync(xDisplay, False);
8326 frameWaiting = True;
8327 signal(SIGALRM, FrameAlarm);
8328 delay.it_interval.tv_sec =
8329 delay.it_value.tv_sec = time / 1000;
8330 delay.it_interval.tv_usec =
8331 delay.it_value.tv_usec = (time % 1000) * 1000;
8332 setitimer(ITIMER_REAL, &delay, NULL);
8334 /* Ugh -- busy-wait! --tpm */
8335 while (frameWaiting);
8337 while (frameWaiting) pause();
8339 delay.it_interval.tv_sec = delay.it_value.tv_sec = 0;
8340 delay.it_interval.tv_usec = delay.it_value.tv_usec = 0;
8341 setitimer(ITIMER_REAL, &delay, NULL);
8351 XSync(xDisplay, False);
8353 usleep(time * 1000);
8358 /* Convert board position to corner of screen rect and color */
8361 ScreenSquare(column, row, pt, color)
8362 int column; int row; XPoint * pt; int * color;
8365 pt->x = lineGap + ((BOARD_WIDTH-1)-column) * (squareSize + lineGap);
8366 pt->y = lineGap + row * (squareSize + lineGap);
8368 pt->x = lineGap + column * (squareSize + lineGap);
8369 pt->y = lineGap + ((BOARD_HEIGHT-1)-row) * (squareSize + lineGap);
8371 *color = SquareColor(row, column);
8374 /* Convert window coords to square */
8377 BoardSquare(x, y, column, row)
8378 int x; int y; int * column; int * row;
8380 *column = EventToSquare(x, BOARD_WIDTH);
8381 if (flipView && *column >= 0)
8382 *column = BOARD_WIDTH - 1 - *column;
8383 *row = EventToSquare(y, BOARD_HEIGHT);
8384 if (!flipView && *row >= 0)
8385 *row = BOARD_HEIGHT - 1 - *row;
8390 #undef Max /* just in case */
8392 #define Max(a, b) ((a) > (b) ? (a) : (b))
8393 #define Min(a, b) ((a) < (b) ? (a) : (b))
8396 SetRect(rect, x, y, width, height)
8397 XRectangle * rect; int x; int y; int width; int height;
8401 rect->width = width;
8402 rect->height = height;
8405 /* Test if two frames overlap. If they do, return
8406 intersection rect within old and location of
8407 that rect within new. */
8410 Intersect(old, new, size, area, pt)
8411 XPoint * old; XPoint * new;
8412 int size; XRectangle * area; XPoint * pt;
8414 if (old->x > new->x + size || new->x > old->x + size ||
8415 old->y > new->y + size || new->y > old->y + size) {
8418 SetRect(area, Max(new->x - old->x, 0), Max(new->y - old->y, 0),
8419 size - abs(old->x - new->x), size - abs(old->y - new->y));
8420 pt->x = Max(old->x - new->x, 0);
8421 pt->y = Max(old->y - new->y, 0);
8426 /* For two overlapping frames, return the rect(s)
8427 in the old that do not intersect with the new. */
8430 CalcUpdateRects(old, new, size, update, nUpdates)
8431 XPoint * old; XPoint * new; int size;
8432 XRectangle update[]; int * nUpdates;
8436 /* If old = new (shouldn't happen) then nothing to draw */
8437 if (old->x == new->x && old->y == new->y) {
8441 /* Work out what bits overlap. Since we know the rects
8442 are the same size we don't need a full intersect calc. */
8444 /* Top or bottom edge? */
8445 if (new->y > old->y) {
8446 SetRect(&(update[count]), old->x, old->y, size, new->y - old->y);
8448 } else if (old->y > new->y) {
8449 SetRect(&(update[count]), old->x, old->y + size - (old->y - new->y),
8450 size, old->y - new->y);
8453 /* Left or right edge - don't overlap any update calculated above. */
8454 if (new->x > old->x) {
8455 SetRect(&(update[count]), old->x, Max(new->y, old->y),
8456 new->x - old->x, size - abs(new->y - old->y));
8458 } else if (old->x > new->x) {
8459 SetRect(&(update[count]), new->x + size, Max(new->y, old->y),
8460 old->x - new->x, size - abs(new->y - old->y));
8467 /* Generate a series of frame coords from start->mid->finish.
8468 The movement rate doubles until the half way point is
8469 reached, then halves back down to the final destination,
8470 which gives a nice slow in/out effect. The algorithmn
8471 may seem to generate too many intermediates for short
8472 moves, but remember that the purpose is to attract the
8473 viewers attention to the piece about to be moved and
8474 then to where it ends up. Too few frames would be less
8478 Tween(start, mid, finish, factor, frames, nFrames)
8479 XPoint * start; XPoint * mid;
8480 XPoint * finish; int factor;
8481 XPoint frames[]; int * nFrames;
8483 int fraction, n, count;
8487 /* Slow in, stepping 1/16th, then 1/8th, ... */
8489 for (n = 0; n < factor; n++)
8491 for (n = 0; n < factor; n++) {
8492 frames[count].x = start->x + (mid->x - start->x) / fraction;
8493 frames[count].y = start->y + (mid->y - start->y) / fraction;
8495 fraction = fraction / 2;
8499 frames[count] = *mid;
8502 /* Slow out, stepping 1/2, then 1/4, ... */
8504 for (n = 0; n < factor; n++) {
8505 frames[count].x = finish->x - (finish->x - mid->x) / fraction;
8506 frames[count].y = finish->y - (finish->y - mid->y) / fraction;
8508 fraction = fraction * 2;
8513 /* Draw a piece on the screen without disturbing what's there */
8516 SelectGCMask(piece, clip, outline, mask)
8517 ChessSquare piece; GC * clip; GC * outline; Pixmap * mask;
8521 /* Bitmap for piece being moved. */
8522 if (appData.monoMode) {
8523 *mask = *pieceToSolid(piece);
8524 } else if (useImages) {
8526 *mask = xpmMask[piece];
8528 *mask = ximMaskPm[piece];
8531 *mask = *pieceToSolid(piece);
8534 /* GC for piece being moved. Square color doesn't matter, but
8535 since it gets modified we make a copy of the original. */
8537 if (appData.monoMode)
8542 if (appData.monoMode)
8547 XCopyGC(xDisplay, source, 0xFFFFFFFF, *clip);
8549 /* Outline only used in mono mode and is not modified */
8551 *outline = bwPieceGC;
8553 *outline = wbPieceGC;
8557 OverlayPiece(piece, clip, outline, dest)
8558 ChessSquare piece; GC clip; GC outline; Drawable dest;
8563 /* Draw solid rectangle which will be clipped to shape of piece */
8564 XFillRectangle(xDisplay, dest, clip,
8565 0, 0, squareSize, squareSize);
8566 if (appData.monoMode)
8567 /* Also draw outline in contrasting color for black
8568 on black / white on white cases */
8569 XCopyPlane(xDisplay, *pieceToOutline(piece), dest, outline,
8570 0, 0, squareSize, squareSize, 0, 0, 1);
8572 /* Copy the piece */
8577 XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
8579 0, 0, squareSize, squareSize,
8584 /* Animate the movement of a single piece */
8587 BeginAnimation(anim, piece, startColor, start)
8595 /* The old buffer is initialised with the start square (empty) */
8596 BlankSquare(0, 0, startColor, EmptySquare, anim->saveBuf);
8597 anim->prevFrame = *start;
8599 /* The piece will be drawn using its own bitmap as a matte */
8600 SelectGCMask(piece, &anim->pieceGC, &anim->outlineGC, &mask);
8601 XSetClipMask(xDisplay, anim->pieceGC, mask);
8605 AnimationFrame(anim, frame, piece)
8610 XRectangle updates[4];
8615 /* Save what we are about to draw into the new buffer */
8616 XCopyArea(xDisplay, xBoardWindow, anim->newBuf, anim->blitGC,
8617 frame->x, frame->y, squareSize, squareSize,
8620 /* Erase bits of the previous frame */
8621 if (Intersect(&anim->prevFrame, frame, squareSize, &overlap, &pt)) {
8622 /* Where the new frame overlapped the previous,
8623 the contents in newBuf are wrong. */
8624 XCopyArea(xDisplay, anim->saveBuf, anim->newBuf, anim->blitGC,
8625 overlap.x, overlap.y,
8626 overlap.width, overlap.height,
8628 /* Repaint the areas in the old that don't overlap new */
8629 CalcUpdateRects(&anim->prevFrame, frame, squareSize, updates, &count);
8630 for (i = 0; i < count; i++)
8631 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
8632 updates[i].x - anim->prevFrame.x,
8633 updates[i].y - anim->prevFrame.y,
8634 updates[i].width, updates[i].height,
8635 updates[i].x, updates[i].y);
8637 /* Easy when no overlap */
8638 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
8639 0, 0, squareSize, squareSize,
8640 anim->prevFrame.x, anim->prevFrame.y);
8643 /* Save this frame for next time round */
8644 XCopyArea(xDisplay, anim->newBuf, anim->saveBuf, anim->blitGC,
8645 0, 0, squareSize, squareSize,
8647 anim->prevFrame = *frame;
8649 /* Draw piece over original screen contents, not current,
8650 and copy entire rect. Wipes out overlapping piece images. */
8651 OverlayPiece(piece, anim->pieceGC, anim->outlineGC, anim->newBuf);
8652 XCopyArea(xDisplay, anim->newBuf, xBoardWindow, anim->blitGC,
8653 0, 0, squareSize, squareSize,
8654 frame->x, frame->y);
8658 EndAnimation (anim, finish)
8662 XRectangle updates[4];
8667 /* The main code will redraw the final square, so we
8668 only need to erase the bits that don't overlap. */
8669 if (Intersect(&anim->prevFrame, finish, squareSize, &overlap, &pt)) {
8670 CalcUpdateRects(&anim->prevFrame, finish, squareSize, updates, &count);
8671 for (i = 0; i < count; i++)
8672 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
8673 updates[i].x - anim->prevFrame.x,
8674 updates[i].y - anim->prevFrame.y,
8675 updates[i].width, updates[i].height,
8676 updates[i].x, updates[i].y);
8678 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
8679 0, 0, squareSize, squareSize,
8680 anim->prevFrame.x, anim->prevFrame.y);
8685 FrameSequence(anim, piece, startColor, start, finish, frames, nFrames)
8687 ChessSquare piece; int startColor;
8688 XPoint * start; XPoint * finish;
8689 XPoint frames[]; int nFrames;
8693 BeginAnimation(anim, piece, startColor, start);
8694 for (n = 0; n < nFrames; n++) {
8695 AnimationFrame(anim, &(frames[n]), piece);
8696 FrameDelay(appData.animSpeed);
8698 EndAnimation(anim, finish);
8701 /* Main control logic for deciding what to animate and how */
8704 AnimateMove(board, fromX, fromY, toX, toY)
8713 XPoint start, finish, mid;
8714 XPoint frames[kFactor * 2 + 1];
8715 int nFrames, startColor, endColor;
8717 /* Are we animating? */
8718 if (!appData.animate || appData.blindfold)
8721 if(board[toY][toX] == WhiteRook && board[fromY][fromX] == WhiteKing ||
8722 board[toY][toX] == BlackRook && board[fromY][fromX] == BlackKing)
8723 return; // [HGM] FRC: no animtion of FRC castlings, as to-square is not true to-square
8725 if (fromY < 0 || fromX < 0 || toX < 0 || toY < 0) return;
8726 piece = board[fromY][fromX];
8727 if (piece >= EmptySquare) return;
8732 hop = (piece == WhiteKnight || piece == BlackKnight);
8735 if (appData.debugMode) {
8736 fprintf(debugFP, hop ? _("AnimateMove: piece %d hops from %d,%d to %d,%d \n") :
8737 _("AnimateMove: piece %d slides from %d,%d to %d,%d \n"),
8738 piece, fromX, fromY, toX, toY); }
8740 ScreenSquare(fromX, fromY, &start, &startColor);
8741 ScreenSquare(toX, toY, &finish, &endColor);
8744 /* Knight: make diagonal movement then straight */
8745 if (abs(toY - fromY) < abs(toX - fromX)) {
8746 mid.x = start.x + (finish.x - start.x) / 2;
8750 mid.y = start.y + (finish.y - start.y) / 2;
8753 mid.x = start.x + (finish.x - start.x) / 2;
8754 mid.y = start.y + (finish.y - start.y) / 2;
8757 /* Don't use as many frames for very short moves */
8758 if (abs(toY - fromY) + abs(toX - fromX) <= 2)
8759 Tween(&start, &mid, &finish, kFactor - 1, frames, &nFrames);
8761 Tween(&start, &mid, &finish, kFactor, frames, &nFrames);
8762 FrameSequence(&game, piece, startColor, &start, &finish, frames, nFrames);
8764 /* Be sure end square is redrawn */
8765 damage[toY][toX] = True;
8769 DragPieceBegin(x, y)
8772 int boardX, boardY, color;
8775 /* Are we animating? */
8776 if (!appData.animateDragging || appData.blindfold)
8779 /* Figure out which square we start in and the
8780 mouse position relative to top left corner. */
8781 BoardSquare(x, y, &boardX, &boardY);
8782 player.startBoardX = boardX;
8783 player.startBoardY = boardY;
8784 ScreenSquare(boardX, boardY, &corner, &color);
8785 player.startSquare = corner;
8786 player.startColor = color;
8788 /* Start from exactly where the piece is. This can be confusing
8789 if you start dragging far from the center of the square; most
8790 or all of the piece can be over a different square from the one
8791 the mouse pointer is in. */
8792 player.mouseDelta.x = x - corner.x;
8793 player.mouseDelta.y = y - corner.y;
8795 /* As soon as we start dragging, the piece will jump slightly to
8796 be centered over the mouse pointer. */
8797 player.mouseDelta.x = squareSize/2;
8798 player.mouseDelta.y = squareSize/2;
8800 /* Initialise animation */
8801 player.dragPiece = PieceForSquare(boardX, boardY);
8803 if (player.dragPiece >= 0 && player.dragPiece < EmptySquare) {
8804 player.dragActive = True;
8805 BeginAnimation(&player, player.dragPiece, color, &corner);
8806 /* Mark this square as needing to be redrawn. Note that
8807 we don't remove the piece though, since logically (ie
8808 as seen by opponent) the move hasn't been made yet. */
8809 if(boardX == BOARD_RGHT+1 && PieceForSquare(boardX-1, boardY) > 1 ||
8810 boardX == BOARD_LEFT-2 && PieceForSquare(boardX+1, boardY) > 1)
8811 XCopyArea(xDisplay, xBoardWindow, player.saveBuf, player.blitGC,
8812 corner.x, corner.y, squareSize, squareSize,
8813 0, 0); // [HGM] zh: unstack in stead of grab
8814 damage[boardY][boardX] = True;
8816 player.dragActive = False;
8826 /* Are we animating? */
8827 if (!appData.animateDragging || appData.blindfold)
8831 if (! player.dragActive)
8833 /* Move piece, maintaining same relative position
8834 of mouse within square */
8835 corner.x = x - player.mouseDelta.x;
8836 corner.y = y - player.mouseDelta.y;
8837 AnimationFrame(&player, &corner, player.dragPiece);
8839 if (appData.highlightDragging) {
8841 BoardSquare(x, y, &boardX, &boardY);
8842 SetHighlights(fromX, fromY, boardX, boardY);
8851 int boardX, boardY, color;
8854 /* Are we animating? */
8855 if (!appData.animateDragging || appData.blindfold)
8859 if (! player.dragActive)
8861 /* Last frame in sequence is square piece is
8862 placed on, which may not match mouse exactly. */
8863 BoardSquare(x, y, &boardX, &boardY);
8864 ScreenSquare(boardX, boardY, &corner, &color);
8865 EndAnimation(&player, &corner);
8867 /* Be sure end square is redrawn */
8868 damage[boardY][boardX] = True;
8870 /* This prevents weird things happening with fast successive
8871 clicks which on my Sun at least can cause motion events
8872 without corresponding press/release. */
8873 player.dragActive = False;
8876 /* Handle expose event while piece being dragged */
8881 if (!player.dragActive || appData.blindfold)
8884 /* What we're doing: logically, the move hasn't been made yet,
8885 so the piece is still in it's original square. But visually
8886 it's being dragged around the board. So we erase the square
8887 that the piece is on and draw it at the last known drag point. */
8888 BlankSquare(player.startSquare.x, player.startSquare.y,
8889 player.startColor, EmptySquare, xBoardWindow);
8890 AnimationFrame(&player, &player.prevFrame, player.dragPiece);
8891 damage[player.startBoardY][player.startBoardX] = TRUE;
8895 SetProgramStats( FrontEndProgramStats * stats )
8898 // [HGM] done, but perhaps backend should call this directly?
8899 EngineOutputUpdate( stats );