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));
2140 /* this should raise the board to the top */
2141 gtk_window_present(GTK_WINDOW(GUI_Window));
2146 // eventually, all layout determining code should go into a subroutine, but until then IDSIZE remains undefined
2148 #define BoardSize int
2149 void InitDrawingSizes(BoardSize boardSize, int flags)
2150 { // [HGM] resize is functional now, but for board format changes only (nr of ranks, files)
2151 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
2153 XtGeometryResult gres;
2156 if(!formWidget) return;
2159 * Enable shell resizing.
2161 // shellArgs[0].value = (XtArgVal) &w;
2162 // shellArgs[1].value = (XtArgVal) &h;
2163 // XtGetValues(shellWidget, shellArgs, 2);
2165 // shellArgs[4].value = 2*w; shellArgs[2].value = 10;
2166 // shellArgs[5].value = 2*h; shellArgs[3].value = 10;
2167 // XtSetValues(shellWidget, &shellArgs[2], 4);
2169 // XtSetArg(args[0], XtNdefaultDistance, &sep);
2170 // XtGetValues(formWidget, args, 1);
2172 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2173 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2176 // XtSetArg(args[0], XtNwidth, boardWidth);
2177 // XtSetArg(args[1], XtNheight, boardHeight);
2178 // XtSetValues(boardWidget, args, 2);
2180 timerWidth = (boardWidth - sep) / 2;
2181 // XtSetArg(args[0], XtNwidth, timerWidth);
2182 // XtSetValues(whiteTimerWidget, args, 1);
2183 // XtSetValues(blackTimerWidget, args, 1);
2185 // XawFormDoLayout(formWidget, False);
2187 if (appData.titleInWindow) {
2189 // XtSetArg(args[i], XtNborderWidth, &bor); i++;
2190 // XtSetArg(args[i], XtNheight, &h); i++;
2191 // XtGetValues(titleWidget, args, i);
2193 w = boardWidth - 2*bor;
2195 // XtSetArg(args[0], XtNwidth, &w);
2196 // XtGetValues(menuBarWidget, args, 1);
2197 w = boardWidth - w - sep - 2*bor - 2; // WIDTH_FUDGE
2200 // gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
2201 // if (gres != XtGeometryYes && appData.debugMode) {
2203 // _("%s: titleWidget geometry error %d %d %d %d %d\n"),
2204 // programName, gres, w, h, wr, hr);
2208 // XawFormDoLayout(formWidget, True);
2211 * Inhibit shell resizing.
2213 shellArgs[0].value = w = (XtArgVal) boardWidth + marginW;
2214 shellArgs[1].value = h = (XtArgVal) boardHeight + marginH;
2215 shellArgs[4].value = shellArgs[2].value = w;
2216 shellArgs[5].value = shellArgs[3].value = h;
2217 // XtSetValues(shellWidget, &shellArgs[0], 6);
2219 // [HGM] pieces: tailor piece bitmaps to needs of specific variant
2222 for(i=0; i<4; i++) {
2224 for(p=0; p<=(int)WhiteKing; p++)
2225 xpmPieceBitmap[i][p] = xpmPieceBitmap2[i][p]; // defaults
2226 if(gameInfo.variant == VariantShogi) {
2227 xpmPieceBitmap[i][(int)WhiteCannon] = xpmPieceBitmap2[i][(int)WhiteKing+1];
2228 xpmPieceBitmap[i][(int)WhiteNightrider] = xpmPieceBitmap2[i][(int)WhiteKing+2];
2229 xpmPieceBitmap[i][(int)WhiteSilver] = xpmPieceBitmap2[i][(int)WhiteKing+3];
2230 xpmPieceBitmap[i][(int)WhiteGrasshopper] = xpmPieceBitmap2[i][(int)WhiteKing+4];
2231 xpmPieceBitmap[i][(int)WhiteQueen] = xpmPieceBitmap2[i][(int)WhiteLance];
2234 if(gameInfo.variant == VariantGothic) {
2235 xpmPieceBitmap[i][(int)WhiteMarshall] = xpmPieceBitmap2[i][(int)WhiteSilver];
2239 // [HGM] why are thee ximMasks used at all? the ximPieceBitmaps seem to be never used!
2240 for(p=0; p<=(int)WhiteKing; p++)
2241 ximMaskPm[p] = ximMaskPm2[p]; // defaults
2242 if(gameInfo.variant == VariantShogi) {
2243 ximMaskPm[(int)WhiteCannon] = ximMaskPm2[(int)WhiteKing+1];
2244 ximMaskPm[(int)WhiteNightrider] = ximMaskPm2[(int)WhiteKing+2];
2245 ximMaskPm[(int)WhiteSilver] = ximMaskPm2[(int)WhiteKing+3];
2246 ximMaskPm[(int)WhiteGrasshopper] = ximMaskPm2[(int)WhiteKing+4];
2247 ximMaskPm[(int)WhiteQueen] = ximMaskPm2[(int)WhiteLance];
2250 if(gameInfo.variant == VariantGothic) {
2251 ximMaskPm[(int)WhiteMarshall] = ximMaskPm2[i][(int)WhiteSilver];
2257 for(i=0; i<2; i++) {
2259 for(p=0; p<=(int)WhiteKing; p++)
2260 pieceBitmap[i][p] = pieceBitmap2[i][p]; // defaults
2261 if(gameInfo.variant == VariantShogi) {
2262 pieceBitmap[i][(int)WhiteCannon] = pieceBitmap2[i][(int)WhiteKing+1];
2263 pieceBitmap[i][(int)WhiteNightrider] = pieceBitmap2[i][(int)WhiteKing+2];
2264 pieceBitmap[i][(int)WhiteSilver] = pieceBitmap2[i][(int)WhiteKing+3];
2265 pieceBitmap[i][(int)WhiteGrasshopper] = pieceBitmap2[i][(int)WhiteKing+4];
2266 pieceBitmap[i][(int)WhiteQueen] = pieceBitmap2[i][(int)WhiteLance];
2269 if(gameInfo.variant == VariantGothic) {
2270 pieceBitmap[i][(int)WhiteMarshall] = pieceBitmap2[i][(int)WhiteSilver];
2286 int i, j, clockFontPxlSize, coordFontPxlSize, fontPxlSize;
2287 XSetWindowAttributes window_attributes;
2289 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
2290 XrmValue vFrom, vTo;
2291 XtGeometryResult gres;
2294 int forceMono = False;
2297 // [HGM] before anything else, expand any indirection files amongst options
2298 char *argvCopy[1000]; // 1000 seems enough
2299 char newArgs[10000]; // holds actual characters
2302 srandom(time(0)); // [HGM] book: make random truly random
2305 for(i=0; i<argc; i++) {
2306 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2307 //fprintf(stderr, "arg %s\n", argv[i]);
2308 if(argv[i][0] != '@') argvCopy[j++] = argv[i]; else {
2310 FILE *f = fopen(argv[i]+1, "rb");
2311 if(f == NULL) { fprintf(stderr, _("ignore %s\n"), argv[i]); continue; } // do not expand non-existing
2312 argvCopy[j++] = newArgs + k; // get ready for first argument from file
2313 while((c = fgetc(f)) != EOF) { // each line of file inserts 1 argument in the list
2315 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2316 newArgs[k++] = 0; // terminate current arg
2317 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2318 argvCopy[j++] = newArgs + k; // get ready for next
2320 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2333 if(appData.debugMode,1) { // OK, appData is not initialized here yet...
2334 for(i=0; i<argc; i++) fprintf(stderr, "argv[%2d] = '%s'\n", i, argv[i]);
2340 setbuf(stdout, NULL);
2341 setbuf(stderr, NULL);
2344 programName = strrchr(argv[0], '/');
2345 if (programName == NULL)
2346 programName = argv[0];
2351 XtSetLanguageProc(NULL, NULL, NULL);
2352 bindtextdomain(PACKAGE, LOCALEDIR);
2353 textdomain(PACKAGE);
2357 XtAppInitialize(&appContext, "XBoard", shellOptions,
2358 XtNumber(shellOptions),
2359 &argc, argv, xboardResources, NULL, 0);
2361 gtk_init (&argc, &argv);
2363 /* parse glade file */
2365 builder = gtk_builder_new ();
2366 gtk_builder_add_from_file (builder, "gtk-interface.xml", NULL);
2368 GUI_Window = GTK_WIDGET (gtk_builder_get_object (builder, "MainWindow"));
2369 if(!GUI_Window) printf("Error: gtk_builder didn't work!\n");
2370 GUI_Board = GTK_WIDGET (gtk_builder_get_object (builder, "Board"));
2371 if(!GUI_Board) printf("Error: gtk_builder didn't work!\n");
2372 GUI_Whiteclock = GTK_WIDGET (gtk_builder_get_object (builder, "WhiteClock"));
2373 if(!GUI_Whiteclock) printf("Error: gtk_builder didn't work!\n");
2374 GUI_Blackclock = GTK_WIDGET (gtk_builder_get_object (builder, "BlackClock"));
2375 if(!GUI_Blackclock) printf("Error: gtk_builder didn't work!\n");
2377 gtk_builder_connect_signals (builder, NULL);
2378 // don't unref the builder, since we use it to get references to widgets
2379 // g_object_unref (G_OBJECT (builder));
2381 printf("DEBUG:finished building gtk\n");
2382 /* end parse glade file */
2385 fprintf(stderr, _("%s: unrecognized argument %s\n"),
2386 programName, argv[1]);
2387 fprintf(stderr, "Recognized options:\n");
2388 for(i = 0; i < XtNumber(shellOptions); i++) {
2389 j = fprintf(stderr, " %s%s", shellOptions[i].option,
2390 (shellOptions[i].argKind == XrmoptionSepArg
2392 if (i++ < XtNumber(shellOptions)) {
2393 fprintf(stderr, "%*c%s%s\n", 40 - j, ' ',
2394 shellOptions[i].option,
2395 (shellOptions[i].argKind == XrmoptionSepArg
2398 fprintf(stderr, "\n");
2404 if ((chessDir = (char *) getenv("CHESSDIR")) == NULL) {
2407 if (chdir(chessDir) != 0) {
2408 fprintf(stderr, _("%s: can't cd to CHESSDIR: "), programName);
2415 if (p == NULL) p = "/tmp";
2416 i = strlen(p) + strlen("/.xboardXXXXXx.pgn") + 1;
2417 gameCopyFilename = (char*) malloc(i);
2418 gamePasteFilename = (char*) malloc(i);
2419 snprintf(gameCopyFilename,i, "%s/.xboard%05uc.pgn", p, getpid());
2420 snprintf(gamePasteFilename,i, "%s/.xboard%05up.pgn", p, getpid());
2422 XtGetApplicationResources(shellWidget, (XtPointer) &appData,
2423 clientResources, XtNumber(clientResources),
2426 if (appData.debugMode && appData.nameOfDebugFile && strcmp(appData.nameOfDebugFile, "stderr")) {
2427 /* [DM] debug info to file [HGM] make the filename a command-line option, and allow it to remain stderr */
2428 if ((debugFP = fopen(appData.nameOfDebugFile, "w")) == NULL) {
2429 printf(_("Failed to open file '%s'\n"), appData.nameOfDebugFile);
2432 setbuf(debugFP, NULL);
2435 /* [HGM,HR] make sure board size is acceptable */
2436 if(appData.NrFiles > BOARD_SIZE ||
2437 appData.NrRanks > BOARD_SIZE )
2438 DisplayFatalError(_("Recompile with BOARD_SIZE > 12, to support this size"), 0, 2);
2441 /* This feature does not work; animation needs a rewrite */
2442 appData.highlightDragging = FALSE;
2446 xDisplay = XtDisplay(shellWidget);
2447 xScreen = DefaultScreen(xDisplay);
2448 wm_delete_window = XInternAtom(xDisplay, "WM_DELETE_WINDOW", True);
2450 gameInfo.variant = StringToVariant(appData.variant);
2451 InitPosition(FALSE);
2454 * Determine boardSize
2456 gameInfo.boardWidth = gameInfo.boardHeight = 8; // [HGM] boardsize: make sure we start as 8x8
2459 // [HGM] as long as we have not created the possibility to change size while running, start with requested size
2460 gameInfo.boardWidth = appData.NrFiles > 0 ? appData.NrFiles : 8;
2461 gameInfo.boardHeight = appData.NrRanks > 0 ? appData.NrRanks : 8;
2462 gameInfo.holdingsWidth = appData.holdingsSize > 0 ? 2 : 0;
2467 InitDrawingSizes(-1, 0); // [HGM] initsize: make this into a subroutine
2469 if (isdigit(appData.boardSize[0])) {
2470 i = sscanf(appData.boardSize, "%d,%d,%d,%d,%d,%d,%d", &squareSize,
2471 &lineGap, &clockFontPxlSize, &coordFontPxlSize,
2472 &fontPxlSize, &smallLayout, &tinyLayout);
2474 fprintf(stderr, _("%s: bad boardSize syntax %s\n"),
2475 programName, appData.boardSize);
2479 /* Find some defaults; use the nearest known size */
2480 SizeDefaults *szd, *nearest;
2481 int distance = 99999;
2482 nearest = szd = sizeDefaults;
2483 while (szd->name != NULL) {
2484 if (abs(szd->squareSize - squareSize) < distance) {
2486 distance = abs(szd->squareSize - squareSize);
2487 if (distance == 0) break;
2491 if (i < 2) lineGap = nearest->lineGap;
2492 if (i < 3) clockFontPxlSize = nearest->clockFontPxlSize;
2493 if (i < 4) coordFontPxlSize = nearest->coordFontPxlSize;
2494 if (i < 5) fontPxlSize = nearest->fontPxlSize;
2495 if (i < 6) smallLayout = nearest->smallLayout;
2496 if (i < 7) tinyLayout = nearest->tinyLayout;
2499 SizeDefaults *szd = sizeDefaults;
2500 if (*appData.boardSize == NULLCHAR) {
2501 while (DisplayWidth(xDisplay, xScreen) < szd->minScreenSize ||
2502 DisplayHeight(xDisplay, xScreen) < szd->minScreenSize) {
2505 if (szd->name == NULL) szd--;
2507 while (szd->name != NULL &&
2508 StrCaseCmp(szd->name, appData.boardSize) != 0) szd++;
2509 if (szd->name == NULL) {
2510 fprintf(stderr, _("%s: unrecognized boardSize name %s\n"),
2511 programName, appData.boardSize);
2515 squareSize = szd->squareSize;
2516 lineGap = szd->lineGap;
2517 clockFontPxlSize = szd->clockFontPxlSize;
2518 coordFontPxlSize = szd->coordFontPxlSize;
2519 fontPxlSize = szd->fontPxlSize;
2520 smallLayout = szd->smallLayout;
2521 tinyLayout = szd->tinyLayout;
2524 /* Now, using squareSize as a hint, find a good XPM/XIM set size */
2525 if (strlen(appData.pixmapDirectory) > 0) {
2526 p = ExpandPathName(appData.pixmapDirectory);
2528 fprintf(stderr, _("Error expanding path name \"%s\"\n"),
2529 appData.pixmapDirectory);
2532 if (appData.debugMode) {
2533 fprintf(stderr, _("\
2534 XBoard square size (hint): %d\n\
2535 %s fulldir:%s:\n"), squareSize, IMAGE_EXT, p);
2537 squareSize = xpm_closest_to(p, squareSize, IMAGE_EXT);
2538 if (appData.debugMode) {
2539 fprintf(stderr, _("Closest %s size: %d\n"), IMAGE_EXT, squareSize);
2543 /* [HR] height treated separately (hacked) */
2544 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2545 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2546 if (appData.showJail == 1) {
2547 /* Jail on top and bottom */
2548 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2549 XtSetArg(boardArgs[2], XtNheight,
2550 boardHeight + 2*(lineGap + squareSize));
2551 } else if (appData.showJail == 2) {
2553 XtSetArg(boardArgs[1], XtNwidth,
2554 boardWidth + 2*(lineGap + squareSize));
2555 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2558 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2559 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2563 * Determine what fonts to use.
2565 appData.clockFont = FindFont(appData.clockFont, clockFontPxlSize);
2566 clockFontID = XLoadFont(xDisplay, appData.clockFont);
2567 clockFontStruct = XQueryFont(xDisplay, clockFontID);
2568 appData.coordFont = FindFont(appData.coordFont, coordFontPxlSize);
2569 coordFontID = XLoadFont(xDisplay, appData.coordFont);
2570 coordFontStruct = XQueryFont(xDisplay, coordFontID);
2571 appData.font = FindFont(appData.font, fontPxlSize);
2572 countFontID = XLoadFont(xDisplay, appData.coordFont); // [HGM] holdings
2573 countFontStruct = XQueryFont(xDisplay, countFontID);
2574 // appData.font = FindFont(appData.font, fontPxlSize);
2576 xdb = XtDatabase(xDisplay);
2577 XrmPutStringResource(&xdb, "*font", appData.font);
2580 * Detect if there are not enough colors available and adapt.
2582 if (DefaultDepth(xDisplay, xScreen) <= 2) {
2583 appData.monoMode = True;
2586 if (!appData.monoMode) {
2587 vFrom.addr = (caddr_t) appData.lightSquareColor;
2588 vFrom.size = strlen(appData.lightSquareColor);
2589 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2590 if (vTo.addr == NULL) {
2591 appData.monoMode = True;
2594 lightSquareColor = *(Pixel *) vTo.addr;
2597 if (!appData.monoMode) {
2598 vFrom.addr = (caddr_t) appData.darkSquareColor;
2599 vFrom.size = strlen(appData.darkSquareColor);
2600 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2601 if (vTo.addr == NULL) {
2602 appData.monoMode = True;
2605 darkSquareColor = *(Pixel *) vTo.addr;
2608 if (!appData.monoMode) {
2609 vFrom.addr = (caddr_t) appData.whitePieceColor;
2610 vFrom.size = strlen(appData.whitePieceColor);
2611 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2612 if (vTo.addr == NULL) {
2613 appData.monoMode = True;
2616 whitePieceColor = *(Pixel *) vTo.addr;
2619 if (!appData.monoMode) {
2620 vFrom.addr = (caddr_t) appData.blackPieceColor;
2621 vFrom.size = strlen(appData.blackPieceColor);
2622 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2623 if (vTo.addr == NULL) {
2624 appData.monoMode = True;
2627 blackPieceColor = *(Pixel *) vTo.addr;
2631 if (!appData.monoMode) {
2632 vFrom.addr = (caddr_t) appData.highlightSquareColor;
2633 vFrom.size = strlen(appData.highlightSquareColor);
2634 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2635 if (vTo.addr == NULL) {
2636 appData.monoMode = True;
2639 highlightSquareColor = *(Pixel *) vTo.addr;
2643 if (!appData.monoMode) {
2644 vFrom.addr = (caddr_t) appData.premoveHighlightColor;
2645 vFrom.size = strlen(appData.premoveHighlightColor);
2646 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2647 if (vTo.addr == NULL) {
2648 appData.monoMode = True;
2651 premoveHighlightColor = *(Pixel *) vTo.addr;
2656 fprintf(stderr, _("%s: too few colors available; trying monochrome mode\n"),
2659 if (appData.bitmapDirectory == NULL ||
2660 appData.bitmapDirectory[0] == NULLCHAR)
2661 appData.bitmapDirectory = DEF_BITMAP_DIR;
2664 if (appData.lowTimeWarning && !appData.monoMode) {
2665 vFrom.addr = (caddr_t) appData.lowTimeWarningColor;
2666 vFrom.size = strlen(appData.lowTimeWarningColor);
2667 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2668 if (vTo.addr == NULL)
2669 appData.monoMode = True;
2671 lowTimeWarningColor = *(Pixel *) vTo.addr;
2674 if (appData.monoMode && appData.debugMode) {
2675 fprintf(stderr, _("white pixel = 0x%lx, black pixel = 0x%lx\n"),
2676 (unsigned long) XWhitePixel(xDisplay, xScreen),
2677 (unsigned long) XBlackPixel(xDisplay, xScreen));
2680 if (parse_cpair(ColorShout, appData.colorShout) < 0 ||
2681 parse_cpair(ColorSShout, appData.colorSShout) < 0 ||
2682 parse_cpair(ColorChannel1, appData.colorChannel1) < 0 ||
2683 parse_cpair(ColorChannel, appData.colorChannel) < 0 ||
2684 parse_cpair(ColorKibitz, appData.colorKibitz) < 0 ||
2685 parse_cpair(ColorTell, appData.colorTell) < 0 ||
2686 parse_cpair(ColorChallenge, appData.colorChallenge) < 0 ||
2687 parse_cpair(ColorRequest, appData.colorRequest) < 0 ||
2688 parse_cpair(ColorSeek, appData.colorSeek) < 0 ||
2689 parse_cpair(ColorNormal, appData.colorNormal) < 0)
2691 if (appData.colorize) {
2693 _("%s: can't parse color names; disabling colorization\n"),
2696 appData.colorize = FALSE;
2698 textColors[ColorNone].fg = textColors[ColorNone].bg = -1;
2699 textColors[ColorNone].attr = 0;
2701 printf("DEBUG: I'm here 0\n");
2703 // XtAppAddActions(appContext, boardActions, XtNumber(boardActions));
2709 layoutName = "tinyLayout";
2710 } else if (smallLayout) {
2711 layoutName = "smallLayout";
2713 layoutName = "normalLayout";
2715 /* Outer layoutWidget is there only to provide a name for use in
2716 resources that depend on the layout style */
2718 XtCreateManagedWidget(layoutName, formWidgetClass, shellWidget,
2719 layoutArgs, XtNumber(layoutArgs));
2721 XtCreateManagedWidget("form", formWidgetClass, layoutWidget,
2722 formArgs, XtNumber(formArgs));
2723 XtSetArg(args[0], XtNdefaultDistance, &sep);
2724 XtGetValues(formWidget, args, 1);
2727 widgetList[j++] = menuBarWidget = CreateMenuBar(menuBar);
2728 XtSetArg(args[0], XtNtop, XtChainTop);
2729 XtSetArg(args[1], XtNbottom, XtChainTop);
2730 XtSetValues(menuBarWidget, args, 2);
2732 widgetList[j++] = whiteTimerWidget =
2733 XtCreateWidget("whiteTime", labelWidgetClass,
2734 formWidget, timerArgs, XtNumber(timerArgs));
2735 XtSetArg(args[0], XtNfont, clockFontStruct);
2736 XtSetArg(args[1], XtNtop, XtChainTop);
2737 XtSetArg(args[2], XtNbottom, XtChainTop);
2738 XtSetValues(whiteTimerWidget, args, 3);
2740 widgetList[j++] = blackTimerWidget =
2741 XtCreateWidget("blackTime", labelWidgetClass,
2742 formWidget, timerArgs, XtNumber(timerArgs));
2743 XtSetArg(args[0], XtNfont, clockFontStruct);
2744 XtSetArg(args[1], XtNtop, XtChainTop);
2745 XtSetArg(args[2], XtNbottom, XtChainTop);
2746 XtSetValues(blackTimerWidget, args, 3);
2747 printf("DEBUG: I'm here 1\n");
2749 if (appData.titleInWindow) {
2750 widgetList[j++] = titleWidget =
2751 XtCreateWidget("title", labelWidgetClass, formWidget,
2752 titleArgs, XtNumber(titleArgs));
2753 XtSetArg(args[0], XtNtop, XtChainTop);
2754 XtSetArg(args[1], XtNbottom, XtChainTop);
2755 XtSetValues(titleWidget, args, 2);
2758 if (appData.showButtonBar) {
2759 widgetList[j++] = buttonBarWidget = CreateButtonBar(buttonBar);
2760 XtSetArg(args[0], XtNleft, XtChainRight); // [HGM] glue to right window edge
2761 XtSetArg(args[1], XtNright, XtChainRight); // for good run-time sizing
2762 XtSetArg(args[2], XtNtop, XtChainTop);
2763 XtSetArg(args[3], XtNbottom, XtChainTop);
2764 XtSetValues(buttonBarWidget, args, 4);
2767 // widgetList[j++] = messageWidget =
2768 // XtCreateWidget("message", labelWidgetClass, formWidget,
2769 // messageArgs, XtNumber(messageArgs));
2770 // XtSetArg(args[0], XtNtop, XtChainTop);
2771 // XtSetArg(args[1], XtNbottom, XtChainTop);
2772 // XtSetValues(messageWidget, args, 2);
2774 // widgetList[j++] = boardWidget =
2775 // XtCreateWidget("board", widgetClass, formWidget, boardArgs,
2776 // XtNumber(boardArgs));
2778 // XtManageChildren(widgetList, j);
2780 // timerWidth = (boardWidth - sep) / 2;
2781 // XtSetArg(args[0], XtNwidth, timerWidth);
2782 // XtSetValues(whiteTimerWidget, args, 1);
2783 // XtSetValues(blackTimerWidget, args, 1);
2785 // XtSetArg(args[0], XtNbackground, &timerBackgroundPixel);
2786 // XtSetArg(args[1], XtNforeground, &timerForegroundPixel);
2787 // XtGetValues(whiteTimerWidget, args, 2);
2789 // if (appData.showButtonBar) {
2790 // XtSetArg(args[0], XtNbackground, &buttonBackgroundPixel);
2791 // XtSetArg(args[1], XtNforeground, &buttonForegroundPixel);
2792 // XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
2797 * gtk set properties of widgets
2800 /* set board size */
2801 gtk_widget_set_size_request(GTK_WIDGET(GUI_Board),
2802 boardWidth,boardHeight);
2804 /* end gtk set properties of widgets */
2806 printf("DEBUG: made it.\n");
2809 * formWidget uses these constraints but they are stored
2813 // XtSetArg(args[i], XtNfromHoriz, 0); i++;
2814 // XtSetValues(menuBarWidget, args, i);
2815 // if (appData.titleInWindow) {
2816 // if (smallLayout) {
2817 // printf("DEBUG: made it a.\n");
2819 // XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2820 // XtSetValues(whiteTimerWidget, args, i);
2822 // XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2823 // XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2824 // XtSetValues(blackTimerWidget, args, i);
2826 // XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2827 // XtSetArg(args[i], XtNjustify, XtJustifyLeft); i++;
2828 // XtSetValues(titleWidget, args, i);
2830 // XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2831 // XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2832 // XtSetValues(messageWidget, args, i);
2833 // if (appData.showButtonBar) {
2835 // XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2836 // XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2837 // XtSetValues(buttonBarWidget, args, i);
2840 // printf("DEBUG: made it b.\n");
2842 // XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2843 // XtSetValues(whiteTimerWidget, args, i);
2845 // XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2846 // XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2847 // XtSetValues(blackTimerWidget, args, i);
2849 // XtSetArg(args[i], XtNfromHoriz, menuBarWidget); i++;
2850 // XtSetValues(titleWidget, args, i);
2852 // XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2853 // XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2854 // XtSetValues(messageWidget, args, i);
2855 // if (appData.showButtonBar) {
2857 // XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2858 // XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2859 // XtSetValues(buttonBarWidget, args, i);
2862 // } else { printf("DEBUG: made it c.\n");
2865 // XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2866 // XtSetValues(whiteTimerWidget, args, i);
2868 // XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2869 // XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2870 // XtSetValues(blackTimerWidget, args, i);
2872 // XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2873 // XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2874 // XtSetValues(messageWidget, args, i);
2875 // if (appData.showButtonBar) {
2877 // XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2878 // XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2879 // XtSetValues(buttonBarWidget, args, i);
2882 // printf("DEBUG: made it 1.\n");
2884 // XtSetArg(args[0], XtNfromVert, messageWidget);
2885 // XtSetArg(args[1], XtNtop, XtChainTop);
2886 // XtSetArg(args[2], XtNbottom, XtChainBottom);
2887 // XtSetArg(args[3], XtNleft, XtChainLeft);
2888 // XtSetArg(args[4], XtNright, XtChainRight);
2889 // XtSetValues(boardWidget, args, 5);
2891 // XtRealizeWidget(shellWidget);
2893 printf("DEBUG: made it 2.\n");
2896 * Correct the width of the message and title widgets.
2897 * It is not known why some systems need the extra fudge term.
2898 * The value "2" is probably larger than needed.
2900 // XawFormDoLayout(formWidget, False);
2902 #define WIDTH_FUDGE 2
2904 // XtSetArg(args[i], XtNborderWidth, &bor); i++;
2905 // XtSetArg(args[i], XtNheight, &h); i++;
2906 // XtGetValues(messageWidget, args, i);
2907 if (appData.showButtonBar) {
2909 // XtSetArg(args[i], XtNwidth, &w); i++;
2910 // XtGetValues(buttonBarWidget, args, i);
2911 // w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2913 // w = boardWidth - 2*bor + 1; /*!! +1 compensates for kludge below */
2916 // gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2917 if (gres != XtGeometryYes && appData.debugMode) {
2918 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2919 programName, gres, w, h, wr, hr);
2922 /* !! Horrible hack to work around bug in XFree86 4.0.1 (X11R6.4.3) */
2923 /* The size used for the child widget in layout lags one resize behind
2924 its true size, so we resize a second time, 1 pixel smaller. Yeech! */
2926 // gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2927 if (gres != XtGeometryYes && appData.debugMode) {
2928 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2929 programName, gres, w, h, wr, hr);
2932 // XtSetArg(args[0], XtNleft, XtChainLeft); // [HGM] glue ends for good run-time sizing
2933 // XtSetArg(args[1], XtNright, XtChainRight);
2934 // XtSetValues(messageWidget, args, 2);
2936 if (appData.titleInWindow) {
2938 // XtSetArg(args[i], XtNborderWidth, &bor); i++;
2939 // XtSetArg(args[i], XtNheight, &h); i++;
2940 // XtGetValues(titleWidget, args, i);
2942 w = boardWidth - 2*bor;
2944 // XtSetArg(args[0], XtNwidth, &w);
2945 // XtGetValues(menuBarWidget, args, 1);
2946 // w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2949 // gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
2950 if (gres != XtGeometryYes && appData.debugMode) {
2952 _("%s: titleWidget geometry error %d %d %d %d %d\n"),
2953 programName, gres, w, h, wr, hr);
2956 // XawFormDoLayout(formWidget, True);
2958 // xBoardWindow = XtWindow(boardWidget);
2960 // [HGM] it seems the layout code ends here, but perhaps the color stuff is size independent and would
2961 // not need to go into InitDrawingSizes().
2964 if (appData.alwaysPromoteToQueen) {
2965 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Always Queen")),TRUE);
2967 if (appData.animateDragging) {
2968 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Animate Dragging")),TRUE);
2970 if (appData.animate) {
2971 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Animate Moving")),TRUE);
2973 if (appData.autoComment) {
2974 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Comment")),TRUE);
2976 if (appData.autoCallFlag) {
2977 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Flag")),TRUE);
2979 if (appData.autoFlipView) {
2980 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Flip View")),TRUE);
2982 if (appData.autoObserve) {
2983 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Observe")),TRUE);
2985 if (appData.autoRaiseBoard) {
2986 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Raise Board")),TRUE);
2988 if (appData.autoSaveGames) {
2989 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Save")),TRUE);
2991 if (appData.saveGameFile[0] != NULLCHAR) {
2992 /* Can't turn this off from menu */
2993 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Save")),TRUE);
2994 gtk_action_set_sensitive(GTK_ACTION (gtk_builder_get_object (builder, "menuOptions.Auto Save")),FALSE);
2996 if (appData.blindfold) {
2997 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Blindfold")),TRUE);
2999 if (appData.flashCount > 0) {
3000 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Flash Moves")),TRUE);
3002 if (appData.getMoveList) {
3003 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Get Move List")),TRUE);
3006 if (appData.highlightDragging) {
3007 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Highlight Dragging")),TRUE);
3010 if (appData.highlightLastMove) {
3011 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Highlight Last Move")),TRUE);
3013 if (appData.icsAlarm) {
3014 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.ICS Alarm")),TRUE);
3016 if (appData.ringBellAfterMoves) {
3017 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Move Sound")),TRUE);
3019 if (appData.oldSaveStyle) {
3020 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Old Save Style")),TRUE);
3022 if (appData.periodicUpdates) {
3023 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Periodic Updates")),TRUE);
3025 if (appData.ponderNextMove) {
3026 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Ponder Next Move")),TRUE);
3028 if (appData.popupExitMessage) {
3029 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Popup Exit Message")),TRUE);
3031 if (appData.popupMoveErrors) {
3032 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Popup Move Errors")),TRUE);
3034 if (appData.premove) {
3035 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Premove")),TRUE);
3037 if (appData.quietPlay) {
3038 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Quit Play")),TRUE);
3040 if (appData.showCoords) {
3041 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Show Coords")),TRUE);
3043 if (appData.showThinking) {
3044 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Show Thinking")),TRUE);
3046 if (appData.testLegality) {
3047 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Test Legality")),TRUE);
3053 // ReadBitmap(&wIconPixmap, "icon_white.bm",
3054 // icon_white_bits, icon_white_width, icon_white_height);
3055 // ReadBitmap(&bIconPixmap, "icon_black.bm",
3056 // icon_black_bits, icon_black_width, icon_black_height);
3057 // iconPixmap = wIconPixmap;
3059 // XtSetArg(args[i], XtNiconPixmap, iconPixmap); i++;
3060 // XtSetValues(shellWidget, args, i);
3063 printf("DEBUG: creating svgs.\n");
3065 /* load square colors */
3066 SVGLightSquare = load_pixbuf("svg/LightSquare.svg");
3067 SVGDarkSquare = load_pixbuf("svg/DarkSquare.svg");
3068 SVGNeutralSquare = load_pixbuf("svg/NeutralSquare.svg");
3070 /* use two icons to indicate if it is white's or black's turn */
3071 WhiteIcon = load_pixbuf("svg/icon_white.svg");
3072 BlackIcon = load_pixbuf("svg/icon_black.svg");
3073 WindowIcon = WhiteIcon;
3074 gtk_window_set_icon(GTK_WINDOW(GUI_Window),WindowIcon);
3076 /* do resizing to a fixed aspect ratio */
3078 hints.min_aspect = 0.8;
3079 hints.max_aspect = 0.8;
3080 gtk_window_set_geometry_hints (GTK_WINDOW (GUI_Window),
3081 GTK_WIDGET (GUI_Window),
3085 /* realize window */
3086 gtk_widget_show (GUI_Window);
3094 if (appData.animate || appData.animateDragging)
3097 printf("DEBUG: created stuff.\n");
3100 // XtAugmentTranslations(formWidget,
3101 // XtParseTranslationTable(globalTranslations));
3102 // XtAugmentTranslations(boardWidget,
3103 // XtParseTranslationTable(boardTranslations));
3104 // XtAugmentTranslations(whiteTimerWidget,
3105 // XtParseTranslationTable(whiteTranslations));
3106 // XtAugmentTranslations(blackTimerWidget,
3107 // XtParseTranslationTable(blackTranslations));
3111 printf("DEBUG: back end initiated.\n");
3113 if (errorExitStatus == -1) {
3114 if (appData.icsActive) {
3115 /* We now wait until we see "login:" from the ICS before
3116 sending the logon script (problems with timestamp otherwise) */
3117 /*ICSInitScript();*/
3118 if (appData.icsInputBox) ICSInputBoxPopUp();
3121 signal(SIGINT, IntSigHandler);
3122 signal(SIGTERM, IntSigHandler);
3123 if (*appData.cmailGameName != NULLCHAR) {
3124 signal(SIGUSR1, CmailSigHandler);
3127 gameInfo.boardWidth = 0; // [HGM] pieces: kludge to ensure InitPosition() calls InitDrawingSizes()
3131 * Create a cursor for the board widget.
3132 * (This needs to be called after the window has been created to have access to board-window)
3135 BoardCursor = gdk_cursor_new(GDK_HAND2);
3136 gdk_window_set_cursor(GUI_Board->window, BoardCursor);
3137 gdk_cursor_destroy(BoardCursor);
3140 printf("DEBUG: going into main.\n");
3144 if (appData.debugMode) fclose(debugFP); // [DM] debug
3151 if (appData.icsActive && oldICSInteractionTitle != NULL) {
3152 DisplayIcsInteractionTitle(oldICSInteractionTitle);
3154 unlink(gameCopyFilename);
3155 unlink(gamePasteFilename);
3166 CmailSigHandler(sig)
3172 signal(SIGUSR1, SIG_IGN); /* suspend handler */
3174 /* Activate call-back function CmailSigHandlerCallBack() */
3175 OutputToProcess(cmailPR, (char *)(&dummy), sizeof(int), &error);
3177 signal(SIGUSR1, CmailSigHandler); /* re-activate handler */
3181 CmailSigHandlerCallBack(isr, closure, message, count, error)
3189 ReloadCmailMsgEvent(TRUE); /* Reload cmail msg */
3191 /**** end signal code ****/
3201 f = fopen(appData.icsLogon, "r");
3207 strcat(buf, appData.icsLogon);
3208 f = fopen(buf, "r");
3212 ProcessICSInitScript(f);
3219 EditCommentPopDown();
3230 SetMenuEnables(enab)
3235 if (!builder) return;
3236 while (enab->name != NULL) {
3237 o = gtk_builder_get_object(builder, enab->name);
3238 if(GTK_IS_WIDGET(o))
3239 gtk_widget_set_sensitive(GTK_WIDGET (o),enab->value);
3242 if(GTK_IS_ACTION(o))
3243 gtk_action_set_sensitive(GTK_ACTION (o),enab->value);
3245 DisplayError(enab->name, 0);
3251 Enables icsEnables[] = {
3252 { "menuFile.Mail Move", False },
3253 { "menuFile.Reload CMail Message", False },
3254 { "menuMode.Machine Black", False },
3255 { "menuMode.Machine White", False },
3256 { "menuMode.Analysis Mode", False },
3257 { "menuMode.Analyze File", False },
3258 { "menuMode.Two Machines", False },
3260 { "menuHelp.Hint", False },
3261 { "menuHelp.Book", False },
3262 { "menuStep.Move Now", False },
3263 { "menuOptions.Periodic Updates", False },
3264 { "menuOptions.Hide Thinking", False },
3265 { "menuOptions.Ponder Next Move", False },
3270 Enables ncpEnables[] = {
3271 { "menuFile.Mail Move", False },
3272 { "menuFile.Reload CMail Message", False },
3273 { "menuMode.Machine White", False },
3274 { "menuMode.Machine Black", False },
3275 { "menuMode.Analysis Mode", False },
3276 { "menuMode.Analyze File", False },
3277 { "menuMode.Two Machines", False },
3278 { "menuMode.ICS Client", False },
3279 { "menuMode.ICS Input Box", False },
3280 { "Action", False },
3281 { "menuStep.Revert", False },
3282 { "menuStep.Move Now", False },
3283 { "menuStep.Retract Move", False },
3284 { "menuOptions.Auto Comment", False },
3285 { "menuOptions.Auto Flag", False },
3286 { "menuOptions.Auto Flip View", False },
3287 { "menuOptions.Auto Observe", False },
3288 { "menuOptions.Auto Raise Board", False },
3289 { "menuOptions.Get Move List", False },
3290 { "menuOptions.ICS Alarm", False },
3291 { "menuOptions.Move Sound", False },
3292 { "menuOptions.Quiet Play", False },
3293 { "menuOptions.Hide Thinking", False },
3294 { "menuOptions.Periodic Updates", False },
3295 { "menuOptions.Ponder Next Move", False },
3296 { "menuHelp.Hint", False },
3297 { "menuHelp.Book", False },
3301 Enables gnuEnables[] = {
3302 { "menuMode.ICS Client", False },
3303 { "menuMode.ICS Input Box", False },
3304 { "menuAction.Accept", False },
3305 { "menuAction.Decline", False },
3306 { "menuAction.Rematch", False },
3307 { "menuAction.Adjourn", False },
3308 { "menuAction.Stop Examining", False },
3309 { "menuAction.Stop Observing", False },
3310 { "menuStep.Revert", False },
3311 { "menuOptions.Auto Comment", False },
3312 { "menuOptions.Auto Observe", False },
3313 { "menuOptions.Auto Raise Board", False },
3314 { "menuOptions.Get Move List", False },
3315 { "menuOptions.Premove", False },
3316 { "menuOptions.Quiet Play", False },
3318 /* The next two options rely on SetCmailMode being called *after* */
3319 /* SetGNUMode so that when GNU is being used to give hints these */
3320 /* menu options are still available */
3322 { "menuFile.Mail Move", False },
3323 { "menuFile.Reload CMail Message", False },
3327 Enables cmailEnables[] = {
3329 { "menuAction.Call Flag", False },
3330 { "menuAction.Draw", True },
3331 { "menuAction.Adjourn", False },
3332 { "menuAction.Abort", False },
3333 { "menuAction.Stop Observing", False },
3334 { "menuAction.Stop Examining", False },
3335 { "menuFile.Mail Move", True },
3336 { "menuFile.Reload CMail Message", True },
3340 Enables trainingOnEnables[] = {
3341 { "menuMode.Edit Comment", False },
3342 { "menuMode.Pause", False },
3343 { "menuStep.Forward", False },
3344 { "menuStep.Backward", False },
3345 { "menuStep.Forward to End", False },
3346 { "menuStep.Back to Start", False },
3347 { "menuStep.Move Now", False },
3348 { "menuStep.Truncate Game", False },
3352 Enables trainingOffEnables[] = {
3353 { "menuMode.Edit Comment", True },
3354 { "menuMode.Pause", True },
3355 { "menuStep.Forward", True },
3356 { "menuStep.Backward", True },
3357 { "menuStep.Forward to End", True },
3358 { "menuStep.Back to Start", True },
3359 { "menuStep.Move Now", True },
3360 { "menuStep.Truncate Game", True },
3364 Enables machineThinkingEnables[] = {
3365 { "menuFile.Load Game", False },
3366 { "menuFile.Load Next Game", False },
3367 { "menuFile.Load Previous Game", False },
3368 { "menuFile.Reload Same Game", False },
3369 { "menuFile.Paste Game", False },
3370 { "menuFile.Load Position", False },
3371 { "menuFile.Load Next Position", False },
3372 { "menuFile.Load Previous Position", False },
3373 { "menuFile.Reload Same Position", False },
3374 { "menuFile.Paste Position", False },
3375 { "menuMode.Machine White", False },
3376 { "menuMode.Machine Black", False },
3377 { "menuMode.Two Machines", False },
3378 { "menuStep.Retract Move", False },
3382 Enables userThinkingEnables[] = {
3383 { "menuFile.Load Game", True },
3384 { "menuFile.Load Next Game", True },
3385 { "menuFile.Load Previous Game", True },
3386 { "menuFile.Reload Same Game", True },
3387 { "menuFile.Paste Game", True },
3388 { "menuFile.Load Position", True },
3389 { "menuFile.Load Next Position", True },
3390 { "menuFile.Load Previous Position", True },
3391 { "menuFile.Reload Same Position", True },
3392 { "menuFile.Paste Position", True },
3393 { "menuMode.Machine White", True },
3394 { "menuMode.Machine Black", True },
3395 { "menuMode.Two Machines", True },
3396 { "menuStep.Retract Move", True },
3402 SetMenuEnables(icsEnables);
3405 if (appData.zippyPlay && !appData.noChessProgram) /* [DM] icsEngineAnalyze */
3406 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Analysis Mode"), True);
3413 SetMenuEnables(ncpEnables);
3419 SetMenuEnables(gnuEnables);
3425 SetMenuEnables(cmailEnables);
3431 SetMenuEnables(trainingOnEnables);
3432 if (appData.showButtonBar) {
3433 XtSetSensitive(buttonBarWidget, False);
3439 SetTrainingModeOff()
3441 SetMenuEnables(trainingOffEnables);
3442 if (appData.showButtonBar) {
3443 XtSetSensitive(buttonBarWidget, True);
3448 SetUserThinkingEnables()
3450 if (appData.noChessProgram) return;
3451 SetMenuEnables(userThinkingEnables);
3455 SetMachineThinkingEnables()
3457 if (appData.noChessProgram) return;
3458 SetMenuEnables(machineThinkingEnables);
3460 case MachinePlaysBlack:
3461 case MachinePlaysWhite:
3462 case TwoMachinesPlay:
3463 XtSetSensitive(XtNameToWidget(menuBarWidget,
3464 ModeToWidgetName(gameMode)), True);
3471 #define Abs(n) ((n)<0 ? -(n) : (n))
3474 * Find a font that matches "pattern" that is as close as
3475 * possible to the targetPxlSize. Prefer fonts that are k
3476 * pixels smaller to fonts that are k pixels larger. The
3477 * pattern must be in the X Consortium standard format,
3478 * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".
3479 * The return value should be freed with XtFree when no
3482 char *FindFont(pattern, targetPxlSize)
3486 char **fonts, *p, *best, *scalable, *scalableTail;
3487 int i, j, nfonts, minerr, err, pxlSize;
3490 char **missing_list;
3492 char *def_string, *base_fnt_lst, strInt[3];
3494 XFontStruct **fnt_list;
3496 base_fnt_lst = calloc(1, strlen(pattern) + 3);
3497 sprintf(strInt, "%d", targetPxlSize);
3498 p = strstr(pattern, "--");
3499 strncpy(base_fnt_lst, pattern, p - pattern + 2);
3500 strcat(base_fnt_lst, strInt);
3501 strcat(base_fnt_lst, strchr(p + 2, '-'));
3503 if ((fntSet = XCreateFontSet(xDisplay,
3507 &def_string)) == NULL) {
3509 fprintf(stderr, _("Unable to create font set.\n"));
3513 nfonts = XFontsOfFontSet(fntSet, &fnt_list, &fonts);
3515 fonts = XListFonts(xDisplay, pattern, 999999, &nfonts);
3517 fprintf(stderr, _("%s: no fonts match pattern %s\n"),
3518 programName, pattern);
3526 for (i=0; i<nfonts; i++) {
3529 if (*p != '-') continue;
3531 if (*p == NULLCHAR) break;
3532 if (*p++ == '-') j++;
3534 if (j < 7) continue;
3537 scalable = fonts[i];
3540 err = pxlSize - targetPxlSize;
3541 if (Abs(err) < Abs(minerr) ||
3542 (minerr > 0 && err < 0 && -err == minerr)) {
3548 if (scalable && Abs(minerr) > appData.fontSizeTolerance) {
3549 /* If the error is too big and there is a scalable font,
3550 use the scalable font. */
3551 int headlen = scalableTail - scalable;
3552 p = (char *) XtMalloc(strlen(scalable) + 10);
3553 while (isdigit(*scalableTail)) scalableTail++;
3554 sprintf(p, "%.*s%d%s", headlen, scalable, targetPxlSize, scalableTail);
3556 p = (char *) XtMalloc(strlen(best) + 1);
3559 if (appData.debugMode) {
3560 fprintf(debugFP, _("resolved %s at pixel size %d\n to %s\n"),
3561 pattern, targetPxlSize, p);
3564 if (missing_count > 0)
3565 XFreeStringList(missing_list);
3566 XFreeFontSet(xDisplay, fntSet);
3568 XFreeFontNames(fonts);
3575 XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
3576 | GCBackground | GCFunction | GCPlaneMask;
3577 XGCValues gc_values;
3580 gc_values.plane_mask = AllPlanes;
3581 gc_values.line_width = lineGap;
3582 gc_values.line_style = LineSolid;
3583 gc_values.function = GXcopy;
3585 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3586 gc_values.background = XBlackPixel(xDisplay, xScreen);
3587 lineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3589 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3590 gc_values.background = XWhitePixel(xDisplay, xScreen);
3591 coordGC = XtGetGC(shellWidget, value_mask, &gc_values);
3592 XSetFont(xDisplay, coordGC, coordFontID);
3594 // [HGM] make font for holdings counts (white on black0
3595 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3596 gc_values.background = XBlackPixel(xDisplay, xScreen);
3597 countGC = XtGetGC(shellWidget, value_mask, &gc_values);
3598 XSetFont(xDisplay, countGC, countFontID);
3600 if (appData.monoMode) {
3601 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3602 gc_values.background = XWhitePixel(xDisplay, xScreen);
3603 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3605 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3606 gc_values.background = XBlackPixel(xDisplay, xScreen);
3607 lightSquareGC = wbPieceGC
3608 = XtGetGC(shellWidget, value_mask, &gc_values);
3610 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3611 gc_values.background = XWhitePixel(xDisplay, xScreen);
3612 darkSquareGC = bwPieceGC
3613 = XtGetGC(shellWidget, value_mask, &gc_values);
3615 if (DefaultDepth(xDisplay, xScreen) == 1) {
3616 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
3617 gc_values.function = GXcopyInverted;
3618 copyInvertedGC = XtGetGC(shellWidget, value_mask, &gc_values);
3619 gc_values.function = GXcopy;
3620 if (XBlackPixel(xDisplay, xScreen) == 1) {
3621 bwPieceGC = darkSquareGC;
3622 wbPieceGC = copyInvertedGC;
3624 bwPieceGC = copyInvertedGC;
3625 wbPieceGC = lightSquareGC;
3629 gc_values.foreground = highlightSquareColor;
3630 gc_values.background = highlightSquareColor;
3631 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3633 gc_values.foreground = premoveHighlightColor;
3634 gc_values.background = premoveHighlightColor;
3635 prelineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3637 gc_values.foreground = lightSquareColor;
3638 gc_values.background = darkSquareColor;
3639 lightSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3641 gc_values.foreground = darkSquareColor;
3642 gc_values.background = lightSquareColor;
3643 darkSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3645 gc_values.foreground = jailSquareColor;
3646 gc_values.background = jailSquareColor;
3647 jailSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3649 gc_values.foreground = whitePieceColor;
3650 gc_values.background = darkSquareColor;
3651 wdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3653 gc_values.foreground = whitePieceColor;
3654 gc_values.background = lightSquareColor;
3655 wlPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3657 gc_values.foreground = whitePieceColor;
3658 gc_values.background = jailSquareColor;
3659 wjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3661 gc_values.foreground = blackPieceColor;
3662 gc_values.background = darkSquareColor;
3663 bdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3665 gc_values.foreground = blackPieceColor;
3666 gc_values.background = lightSquareColor;
3667 blPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3669 gc_values.foreground = blackPieceColor;
3670 gc_values.background = jailSquareColor;
3671 bjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3678 WhitePawn, WhiteKnight, WhiteBishop, WhiteRook, WhiteQueen, WhiteKing,
3679 BlackPawn, BlackKnight, BlackBishop, BlackRook, BlackQueen, BlackKing,
3682 SVGpieces[WhitePawn] = load_pixbuf("svg/WhitePawn.svg");
3683 SVGpieces[WhiteKnight] = load_pixbuf("svg/WhiteKnight.svg");
3684 SVGpieces[WhiteBishop] = load_pixbuf("svg/WhiteBishop.svg");
3685 SVGpieces[WhiteRook] = load_pixbuf("svg/WhiteRook.svg");
3686 SVGpieces[WhiteQueen] = load_pixbuf("svg/WhiteQueen.svg");
3687 SVGpieces[WhiteKing] = load_pixbuf("svg/WhiteKing.svg");
3689 SVGpieces[BlackPawn] = load_pixbuf("svg/BlackPawn.svg");
3690 SVGpieces[BlackKnight] = load_pixbuf("svg/BlackKnight.svg");
3691 SVGpieces[BlackBishop] = load_pixbuf("svg/BlackBishop.svg");
3692 SVGpieces[BlackRook] = load_pixbuf("svg/BlackRook.svg");
3693 SVGpieces[BlackQueen] = load_pixbuf("svg/BlackQueen.svg");
3694 SVGpieces[BlackKing] = load_pixbuf("svg/BlackKing.svg");
3704 if (lineGap == 0) return;
3706 /* [HR] Split this into 2 loops for non-square boards. */
3708 for (i = 0; i < BOARD_HEIGHT + 1; i++) {
3709 gridSegments[i].x1 = 0;
3710 gridSegments[i].x2 =
3711 lineGap + BOARD_WIDTH * (squareSize + lineGap);
3712 gridSegments[i].y1 = gridSegments[i].y2
3713 = lineGap / 2 + (i * (squareSize + lineGap));
3716 for (j = 0; j < BOARD_WIDTH + 1; j++) {
3717 gridSegments[j + i].y1 = 0;
3718 gridSegments[j + i].y2 =
3719 lineGap + BOARD_HEIGHT * (squareSize + lineGap);
3720 gridSegments[j + i].x1 = gridSegments[j + i].x2
3721 = lineGap / 2 + (j * (squareSize + lineGap));
3725 static void MenuBarSelect(w, addr, index)
3730 XtActionProc proc = (XtActionProc) addr;
3732 (proc)(NULL, NULL, NULL, NULL);
3735 void CreateMenuBarPopup(parent, name, mb)
3745 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3748 XtSetArg(args[j], XtNleftMargin, 20); j++;
3749 XtSetArg(args[j], XtNrightMargin, 20); j++;
3751 while (mi->string != NULL) {
3752 if (strcmp(mi->string, "----") == 0) {
3753 entry = XtCreateManagedWidget(mi->string, smeLineObjectClass,
3756 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string)));
3757 entry = XtCreateManagedWidget(mi->string, smeBSBObjectClass,
3759 XtAddCallback(entry, XtNcallback,
3760 (XtCallbackProc) MenuBarSelect,
3761 (caddr_t) mi->proc);
3767 Widget CreateMenuBar(mb)
3771 Widget anchor, menuBar;
3773 char menuName[MSG_SIZ];
3776 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
3777 XtSetArg(args[j], XtNvSpace, 0); j++;
3778 XtSetArg(args[j], XtNborderWidth, 0); j++;
3779 menuBar = XtCreateWidget("menuBar", boxWidgetClass,
3780 formWidget, args, j);
3782 while (mb->name != NULL) {
3783 strcpy(menuName, "menu");
3784 strcat(menuName, mb->name);
3786 XtSetArg(args[j], XtNmenuName, XtNewString(menuName)); j++;
3789 shortName[0] = _(mb->name)[0];
3790 shortName[1] = NULLCHAR;
3791 XtSetArg(args[j], XtNlabel, XtNewString(shortName)); j++;
3794 XtSetArg(args[j], XtNlabel, XtNewString(_(mb->name))); j++;
3797 XtSetArg(args[j], XtNborderWidth, 0); j++;
3798 anchor = XtCreateManagedWidget(mb->name, menuButtonWidgetClass,
3800 CreateMenuBarPopup(menuBar, menuName, mb);
3806 Widget CreateButtonBar(mi)
3810 Widget button, buttonBar;
3814 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
3816 XtSetArg(args[j], XtNhSpace, 0); j++;
3818 XtSetArg(args[j], XtNborderWidth, 0); j++;
3819 XtSetArg(args[j], XtNvSpace, 0); j++;
3820 buttonBar = XtCreateWidget("buttonBar", boxWidgetClass,
3821 formWidget, args, j);
3823 while (mi->string != NULL) {
3826 XtSetArg(args[j], XtNinternalWidth, 2); j++;
3827 XtSetArg(args[j], XtNborderWidth, 0); j++;
3829 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string))); j++;
3830 button = XtCreateManagedWidget(mi->string, commandWidgetClass,
3831 buttonBar, args, j);
3832 XtAddCallback(button, XtNcallback,
3833 (XtCallbackProc) MenuBarSelect,
3834 (caddr_t) mi->proc);
3841 CreatePieceMenu(name, color)
3848 ChessSquare selection;
3850 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3851 boardWidget, args, 0);
3853 for (i = 0; i < PIECE_MENU_SIZE; i++) {
3854 String item = pieceMenuStrings[color][i];
3856 if (strcmp(item, "----") == 0) {
3857 entry = XtCreateManagedWidget(item, smeLineObjectClass,
3860 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
3861 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3863 selection = pieceMenuTranslation[color][i];
3864 XtAddCallback(entry, XtNcallback,
3865 (XtCallbackProc) PieceMenuSelect,
3866 (caddr_t) selection);
3867 if (selection == WhitePawn || selection == BlackPawn) {
3868 XtSetArg(args[0], XtNpopupOnEntry, entry);
3869 XtSetValues(menu, args, 1);
3882 ChessSquare selection;
3884 // whitePieceMenu = CreatePieceMenu("menuW", 0);
3885 // blackPieceMenu = CreatePieceMenu("menuB", 1);
3887 // XtRegisterGrabAction(PieceMenuPopup, True,
3888 // (unsigned)(ButtonPressMask|ButtonReleaseMask),
3889 // GrabModeAsync, GrabModeAsync);
3891 // XtSetArg(args[0], XtNlabel, _("Drop"));
3892 // dropMenu = XtCreatePopupShell("menuD", simpleMenuWidgetClass,
3893 // boardWidget, args, 1);
3894 // for (i = 0; i < DROP_MENU_SIZE; i++) {
3895 // String item = dropMenuStrings[i];
3897 // if (strcmp(item, "----") == 0) {
3898 // entry = XtCreateManagedWidget(item, smeLineObjectClass,
3899 // dropMenu, NULL, 0);
3901 // XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
3902 // entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3903 // dropMenu, args, 1);
3904 // selection = dropMenuTranslation[i];
3905 // XtAddCallback(entry, XtNcallback,
3906 // (XtCallbackProc) DropMenuSelect,
3907 // (caddr_t) selection);
3912 void SetupDropMenu()
3920 for (i=0; i<sizeof(dmEnables)/sizeof(DropMenuEnables); i++) {
3921 entry = XtNameToWidget(dropMenu, dmEnables[i].widget);
3922 p = strchr(gameMode == IcsPlayingWhite ? white_holding : black_holding,
3923 dmEnables[i].piece);
3924 XtSetSensitive(entry, p != NULL || !appData.testLegality
3925 /*!!temp:*/ || (gameInfo.variant == VariantCrazyhouse
3926 && !appData.icsActive));
3928 while (p && *p++ == dmEnables[i].piece) count++;
3929 snprintf(label, sizeof(label), "%s %d", dmEnables[i].widget, count);
3931 XtSetArg(args[j], XtNlabel, label); j++;
3932 XtSetValues(entry, args, j);
3936 void PieceMenuPopup(w, event, params, num_params)
3940 Cardinal *num_params;
3943 if (event->type != ButtonPress) return;
3944 if (errorUp) ErrorPopDown();
3948 whichMenu = params[0];
3950 case IcsPlayingWhite:
3951 case IcsPlayingBlack:
3953 case MachinePlaysWhite:
3954 case MachinePlaysBlack:
3955 if (appData.testLegality &&
3956 gameInfo.variant != VariantBughouse &&
3957 gameInfo.variant != VariantCrazyhouse) return;
3959 whichMenu = "menuD";
3965 if (((pmFromX = EventToSquare(event->xbutton.x, BOARD_WIDTH)) < 0) ||
3966 ((pmFromY = EventToSquare(event->xbutton.y, BOARD_HEIGHT)) < 0)) {
3967 pmFromX = pmFromY = -1;
3971 pmFromX = BOARD_WIDTH - 1 - pmFromX;
3973 pmFromY = BOARD_HEIGHT - 1 - pmFromY;
3975 XtPopupSpringLoaded(XtNameToWidget(boardWidget, whichMenu));
3978 static void PieceMenuSelect(w, piece, junk)
3983 if (pmFromX < 0 || pmFromY < 0) return;
3984 EditPositionMenuEvent(piece, pmFromX, pmFromY);
3987 static void DropMenuSelect(w, piece, junk)
3992 if (pmFromX < 0 || pmFromY < 0) return;
3993 DropMenuEvent(piece, pmFromX, pmFromY);
3996 void WhiteClock(w, event, prms, nprms)
4002 if (gameMode == EditPosition || gameMode == IcsExamining) {
4003 SetWhiteToPlayEvent();
4004 } else if (gameMode == IcsPlayingBlack || gameMode == MachinePlaysWhite) {
4009 void BlackClock(w, event, prms, nprms)
4015 if (gameMode == EditPosition || gameMode == IcsExamining) {
4016 SetBlackToPlayEvent();
4017 } else if (gameMode == IcsPlayingWhite || gameMode == MachinePlaysBlack) {
4024 * If the user selects on a border boundary, return -1; if off the board,
4025 * return -2. Otherwise map the event coordinate to the square.
4027 int EventToSquare(x, limit)
4035 if ((x % (squareSize + lineGap)) >= squareSize)
4037 x /= (squareSize + lineGap);
4043 static void do_flash_delay(msec)
4049 static void drawHighlight(file, rank, gc)
4055 if (lineGap == 0 || appData.blindfold) return;
4058 x = lineGap/2 + ((BOARD_WIDTH-1)-file) *
4059 (squareSize + lineGap);
4060 y = lineGap/2 + rank * (squareSize + lineGap);
4062 x = lineGap/2 + file * (squareSize + lineGap);
4063 y = lineGap/2 + ((BOARD_HEIGHT-1)-rank) *
4064 (squareSize + lineGap);
4067 XDrawRectangle(xDisplay, xBoardWindow, gc, x, y,
4068 squareSize+lineGap, squareSize+lineGap);
4071 int hi1X = -1, hi1Y = -1, hi2X = -1, hi2Y = -1;
4072 int pm1X = -1, pm1Y = -1, pm2X = -1, pm2Y = -1;
4075 SetHighlights(fromX, fromY, toX, toY)
4076 int fromX, fromY, toX, toY;
4078 if (hi1X != fromX || hi1Y != fromY) {
4079 if (hi1X >= 0 && hi1Y >= 0) {
4080 drawHighlight(hi1X, hi1Y, lineGC);
4082 if (fromX >= 0 && fromY >= 0) {
4083 drawHighlight(fromX, fromY, highlineGC);
4086 if (hi2X != toX || hi2Y != toY) {
4087 if (hi2X >= 0 && hi2Y >= 0) {
4088 drawHighlight(hi2X, hi2Y, lineGC);
4090 if (toX >= 0 && toY >= 0) {
4091 drawHighlight(toX, toY, highlineGC);
4103 SetHighlights(-1, -1, -1, -1);
4108 SetPremoveHighlights(fromX, fromY, toX, toY)
4109 int fromX, fromY, toX, toY;
4111 if (pm1X != fromX || pm1Y != fromY) {
4112 if (pm1X >= 0 && pm1Y >= 0) {
4113 drawHighlight(pm1X, pm1Y, lineGC);
4115 if (fromX >= 0 && fromY >= 0) {
4116 drawHighlight(fromX, fromY, prelineGC);
4119 if (pm2X != toX || pm2Y != toY) {
4120 if (pm2X >= 0 && pm2Y >= 0) {
4121 drawHighlight(pm2X, pm2Y, lineGC);
4123 if (toX >= 0 && toY >= 0) {
4124 drawHighlight(toX, toY, prelineGC);
4134 ClearPremoveHighlights()
4136 SetPremoveHighlights(-1, -1, -1, -1);
4139 static void BlankSquare(x, y, color, piece, dest)
4144 if (useImages && useImageSqs) {
4148 pb = SVGLightSquare;
4153 case 2: /* neutral */
4155 pb = SVGNeutralSquare;
4158 gdk_draw_pixbuf(GDK_WINDOW(GUI_Board->window),NULL,pb,0,0,x,y,-1,-1, GDK_RGB_DITHER_NORMAL, 0, 0);
4163 gc = gdk_gc_new(GDK_WINDOW(GUI_Board->window));
4167 // gc = lightSquareGC;
4171 gdk_gc_set_rgb_fg_color(gc, &tmp);
4174 // gc = darkSquareGC;
4178 gdk_gc_set_rgb_fg_color(gc, &tmp);
4180 case 2: /* neutral */
4182 // gc = jailSquareGC;
4186 gdk_gc_set_rgb_fg_color(gc, &tmp);
4189 gdk_draw_rectangle(GDK_WINDOW(GUI_Board->window),gc,1,x,y,squareSize,squareSize);
4195 I split out the routines to draw a piece so that I could
4196 make a generic flash routine.
4198 static void monoDrawPiece_1bit(piece, square_color, x, y, dest)
4200 int square_color, x, y;
4203 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
4204 switch (square_color) {
4206 case 2: /* neutral */
4208 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
4209 ? *pieceToOutline(piece)
4210 : *pieceToSolid(piece),
4211 dest, bwPieceGC, 0, 0,
4212 squareSize, squareSize, x, y);
4215 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
4216 ? *pieceToSolid(piece)
4217 : *pieceToOutline(piece),
4218 dest, wbPieceGC, 0, 0,
4219 squareSize, squareSize, x, y);
4224 static void monoDrawPiece(piece, square_color, x, y, dest)
4226 int square_color, x, y;
4229 switch (square_color) {
4231 case 2: /* neutral */
4233 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
4234 ? *pieceToOutline(piece)
4235 : *pieceToSolid(piece),
4236 dest, bwPieceGC, 0, 0,
4237 squareSize, squareSize, x, y, 1);
4240 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
4241 ? *pieceToSolid(piece)
4242 : *pieceToOutline(piece),
4243 dest, wbPieceGC, 0, 0,
4244 squareSize, squareSize, x, y, 1);
4249 static void colorDrawPiece(piece, square_color, x, y, dest)
4251 int square_color, x, y;
4254 gdk_draw_pixbuf(GDK_WINDOW(GUI_Board->window),NULL,GDK_PIXBUF(SVGpieces[piece]),0,0,x,y,-1,-1, GDK_RGB_DITHER_NORMAL, 0, 0);
4257 // if(pieceToSolid(piece) == NULL) return; // [HGM] bitmaps: make it non-fatal if we have no bitmap;
4258 // switch (square_color) {
4259 // case 1: /* light */
4260 // XCopyPlane(xDisplay, *pieceToSolid(piece),
4261 // dest, (int) piece < (int) BlackPawn
4262 // ? wlPieceGC : blPieceGC, 0, 0,
4263 // squareSize, squareSize, x, y, 1);
4265 // case 0: /* dark */
4266 // XCopyPlane(xDisplay, *pieceToSolid(piece),
4267 // dest, (int) piece < (int) BlackPawn
4268 // ? wdPieceGC : bdPieceGC, 0, 0,
4269 // squareSize, squareSize, x, y, 1);
4271 // case 2: /* neutral */
4273 // XCopyPlane(xDisplay, *pieceToSolid(piece),
4274 // dest, (int) piece < (int) BlackPawn
4275 // ? wjPieceGC : bjPieceGC, 0, 0,
4276 // squareSize, squareSize, x, y, 1);
4281 static void colorDrawPieceImage(piece, square_color, x, y, dest)
4283 int square_color, x, y;
4288 switch (square_color) {
4290 case 2: /* neutral */
4292 if ((int)piece < (int) BlackPawn) {
4300 if ((int)piece < (int) BlackPawn) {
4308 XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
4309 dest, wlPieceGC, 0, 0,
4310 squareSize, squareSize, x, y);
4313 typedef void (*DrawFunc)();
4315 DrawFunc ChooseDrawFunc()
4317 if (appData.monoMode) {
4318 if (DefaultDepth(xDisplay, xScreen) == 1) {
4319 return monoDrawPiece_1bit;
4321 return monoDrawPiece;
4325 return colorDrawPieceImage;
4327 return colorDrawPiece;
4331 /* [HR] determine square color depending on chess variant. */
4332 static int SquareColor(row, column)
4337 if (gameInfo.variant == VariantXiangqi) {
4338 if (column >= 3 && column <= 5 && row >= 0 && row <= 2) {
4340 } else if (column >= 3 && column <= 5 && row >= 7 && row <= 9) {
4342 } else if (row <= 4) {
4348 square_color = ((column + row) % 2) == 1;
4351 /* [hgm] holdings: next line makes all holdings squares light */
4352 if(column < BOARD_LEFT || column >= BOARD_RGHT) square_color = 1;
4354 return square_color;
4357 void DrawSquare(row, column, piece, do_flash)
4358 int row, column, do_flash;
4361 int square_color, x, y, direction, font_ascent, font_descent;
4364 XCharStruct overall;
4368 /* Calculate delay in milliseconds (2-delays per complete flash) */
4369 flash_delay = 500 / appData.flashRate;
4372 x = lineGap + ((BOARD_WIDTH-1)-column) *
4373 (squareSize + lineGap);
4374 y = lineGap + row * (squareSize + lineGap);
4376 x = lineGap + column * (squareSize + lineGap);
4377 y = lineGap + ((BOARD_HEIGHT-1)-row) *
4378 (squareSize + lineGap);
4381 square_color = SquareColor(row, column);
4383 if ( // [HGM] holdings: blank out area between board and holdings
4384 column == BOARD_LEFT-1 || column == BOARD_RGHT
4385 || (column == BOARD_LEFT-2 && row < BOARD_HEIGHT-gameInfo.holdingsSize)
4386 || (column == BOARD_RGHT+1 && row >= gameInfo.holdingsSize) ) {
4387 BlankSquare(x, y, 2, EmptySquare, xBoardWindow);
4389 // [HGM] print piece counts next to holdings
4390 string[1] = NULLCHAR;
4391 if (column == (flipView ? BOARD_LEFT-1 : BOARD_RGHT) && piece > 1 ) {
4392 string[0] = '0' + piece;
4393 XTextExtents(countFontStruct, string, 1, &direction,
4394 &font_ascent, &font_descent, &overall);
4395 if (appData.monoMode) {
4396 XDrawImageString(xDisplay, xBoardWindow, countGC,
4397 x + squareSize - overall.width - 2,
4398 y + font_ascent + 1, string, 1);
4400 XDrawString(xDisplay, xBoardWindow, countGC,
4401 x + squareSize - overall.width - 2,
4402 y + font_ascent + 1, string, 1);
4405 if (column == (flipView ? BOARD_RGHT : BOARD_LEFT-1) && piece > 1) {
4406 string[0] = '0' + piece;
4407 XTextExtents(countFontStruct, string, 1, &direction,
4408 &font_ascent, &font_descent, &overall);
4409 if (appData.monoMode) {
4410 XDrawImageString(xDisplay, xBoardWindow, countGC,
4411 x + 2, y + font_ascent + 1, string, 1);
4413 XDrawString(xDisplay, xBoardWindow, countGC,
4414 x + 2, y + font_ascent + 1, string, 1);
4418 if (piece == EmptySquare || appData.blindfold) {
4419 BlankSquare(x, y, square_color, piece, xBoardWindow);
4421 drawfunc = ChooseDrawFunc();
4422 if (do_flash && appData.flashCount > 0) {
4423 for (i=0; i<appData.flashCount; ++i) {
4425 drawfunc(piece, square_color, x, y, xBoardWindow);
4426 XSync(xDisplay, False);
4427 do_flash_delay(flash_delay);
4429 BlankSquare(x, y, square_color, piece, xBoardWindow);
4430 XSync(xDisplay, False);
4431 do_flash_delay(flash_delay);
4434 drawfunc(piece, square_color, x, y, xBoardWindow);
4438 string[1] = NULLCHAR;
4439 if (appData.showCoords && row == (flipView ? BOARD_HEIGHT-1 : 0)
4440 && column >= BOARD_LEFT && column < BOARD_RGHT) {
4441 string[0] = 'a' + column - BOARD_LEFT;
4442 XTextExtents(coordFontStruct, string, 1, &direction,
4443 &font_ascent, &font_descent, &overall);
4444 if (appData.monoMode) {
4445 XDrawImageString(xDisplay, xBoardWindow, coordGC,
4446 x + squareSize - overall.width - 2,
4447 y + squareSize - font_descent - 1, string, 1);
4449 XDrawString(xDisplay, xBoardWindow, coordGC,
4450 x + squareSize - overall.width - 2,
4451 y + squareSize - font_descent - 1, string, 1);
4454 if (appData.showCoords && column == (flipView ? BOARD_RGHT-1 : BOARD_LEFT)) {
4455 string[0] = ONE + row;
4456 XTextExtents(coordFontStruct, string, 1, &direction,
4457 &font_ascent, &font_descent, &overall);
4458 if (appData.monoMode) {
4459 XDrawImageString(xDisplay, xBoardWindow, coordGC,
4460 x + 2, y + font_ascent + 1, string, 1);
4462 XDrawString(xDisplay, xBoardWindow, coordGC,
4463 x + 2, y + font_ascent + 1, string, 1);
4469 /* Returns 1 if there are "too many" differences between b1 and b2
4470 (i.e. more than 1 move was made) */
4471 static int too_many_diffs(b1, b2)
4477 for (i=0; i<BOARD_HEIGHT; ++i) {
4478 for (j=0; j<BOARD_WIDTH; ++j) {
4479 if (b1[i][j] != b2[i][j]) {
4480 if (++c > 4) /* Castling causes 4 diffs */
4489 /* Matrix describing castling maneuvers */
4490 /* Row, ColRookFrom, ColKingFrom, ColRookTo, ColKingTo */
4491 static int castling_matrix[4][5] = {
4492 { 0, 0, 4, 3, 2 }, /* 0-0-0, white */
4493 { 0, 7, 4, 5, 6 }, /* 0-0, white */
4494 { 7, 0, 4, 3, 2 }, /* 0-0-0, black */
4495 { 7, 7, 4, 5, 6 } /* 0-0, black */
4498 /* Checks whether castling occurred. If it did, *rrow and *rcol
4499 are set to the destination (row,col) of the rook that moved.
4501 Returns 1 if castling occurred, 0 if not.
4503 Note: Only handles a max of 1 castling move, so be sure
4504 to call too_many_diffs() first.
4506 static int check_castle_draw(newb, oldb, rrow, rcol)
4513 /* For each type of castling... */
4514 for (i=0; i<4; ++i) {
4515 r = castling_matrix[i];
4517 /* Check the 4 squares involved in the castling move */
4519 for (j=1; j<=4; ++j) {
4520 if (newb[r[0]][r[j]] == oldb[r[0]][r[j]]) {
4527 /* All 4 changed, so it must be a castling move */
4536 static int damage[BOARD_SIZE][BOARD_SIZE];
4539 * event handler for redrawing the board
4541 void DrawPosition( repaint, board)
4542 /*Boolean*/int repaint;
4546 static int lastFlipView = 0;
4547 static int lastBoardValid = 0;
4548 static Board lastBoard;
4552 printf ("DEBUG: in draw position\n");
4555 if (board == NULL) {
4556 if (!lastBoardValid) return;
4559 if (!lastBoardValid || lastFlipView != flipView) {
4560 XtSetArg(args[0], XtNleftBitmap, (flipView ? xMarkPixmap : None));
4561 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flip View"),
4566 * It would be simpler to clear the window with XClearWindow()
4567 * but this causes a very distracting flicker.
4570 printf ("DEBUG: in draw position 0.1\n");
4573 if (!repaint && lastBoardValid && lastFlipView == flipView) {
4575 printf ("DEBUG: in draw position 0.1a\n");
4576 /* If too much changes (begin observing new game, etc.), don't
4578 do_flash = too_many_diffs(board, lastBoard) ? 0 : 1;
4580 /* Special check for castling so we don't flash both the king
4581 and the rook (just flash the king). */
4583 if (check_castle_draw(board, lastBoard, &rrow, &rcol)) {
4584 /* Draw rook with NO flashing. King will be drawn flashing later */
4585 DrawSquare(rrow, rcol, board[rrow][rcol], 0);
4586 lastBoard[rrow][rcol] = board[rrow][rcol];
4590 /* First pass -- Draw (newly) empty squares and repair damage.
4591 This prevents you from having a piece show up twice while it
4592 is flashing on its new square */
4593 for (i = 0; i < BOARD_HEIGHT; i++)
4594 for (j = 0; j < BOARD_WIDTH; j++)
4595 if ((board[i][j] != lastBoard[i][j] && board[i][j] == EmptySquare)
4597 DrawSquare(i, j, board[i][j], 0);
4598 damage[i][j] = False;
4601 /* Second pass -- Draw piece(s) in new position and flash them */
4602 for (i = 0; i < BOARD_HEIGHT; i++)
4603 for (j = 0; j < BOARD_WIDTH; j++)
4604 if (board[i][j] != lastBoard[i][j]) {
4605 DrawSquare(i, j, board[i][j], do_flash);
4610 /* todo move GC to setupgc */
4611 GdkGC *gtklineGC=NULL;
4614 gtklineGC = gdk_gc_new(GDK_WINDOW(GUI_Board->window));
4619 gdk_gc_set_rgb_fg_color(gtklineGC, &tmp);
4624 gdk_gc_set_rgb_bg_color(gtklineGC, &tmp);
4626 gdk_draw_segments(GUI_Board->window,gtklineGC,
4627 gridSegments, BOARD_HEIGHT + BOARD_WIDTH + 2 );
4630 for (i = 0; i < BOARD_HEIGHT; i++)
4631 for (j = 0; j < BOARD_WIDTH; j++) {
4632 DrawSquare(i, j, board[i][j], 0);
4633 damage[i][j] = False;
4637 CopyBoard(lastBoard, board);
4639 lastFlipView = flipView;
4641 /* Draw highlights */
4642 if (pm1X >= 0 && pm1Y >= 0) {
4643 drawHighlight(pm1X, pm1Y, prelineGC);
4645 if (pm2X >= 0 && pm2Y >= 0) {
4646 drawHighlight(pm2X, pm2Y, prelineGC);
4648 if (hi1X >= 0 && hi1Y >= 0) {
4649 drawHighlight(hi1X, hi1Y, highlineGC);
4651 if (hi2X >= 0 && hi2Y >= 0) {
4652 drawHighlight(hi2X, hi2Y, highlineGC);
4655 /* If piece being dragged around board, must redraw that too */
4658 // XSync(xDisplay, False);
4663 * event handler for redrawing the board
4665 void DrawPositionProc(w, event, prms, nprms)
4671 DrawPosition(True, NULL);
4676 * event handler for parsing user moves
4678 // [HGM] This routine will need quite some reworking. Although the backend still supports the old
4679 // way of doing things, by calling UserMoveEvent() to test the legality of the move and then perform
4680 // it at the end, and doing all kind of preliminary tests here (e.g. to weed out self-captures), it
4681 // should be made to use the new way, of calling UserMoveTest early to determine the legality of the
4682 // move, (which will weed out the illegal selfcaptures and moves into the holdings, and flag promotions),
4683 // and at the end FinishMove() to perform the move after optional promotion popups.
4684 // For now I patched it to allow self-capture with King, and suppress clicks between board and holdings.
4685 void HandleUserMove(w, event, prms, nprms)
4692 Boolean saveAnimate;
4693 static int second = 0;
4695 if (w != boardWidget || errorExitStatus != -1) return;
4697 if (event->type == ButtonPress) ErrorPopDown();
4700 if (event->type == ButtonPress) {
4701 XtPopdown(promotionShell);
4702 XtDestroyWidget(promotionShell);
4703 promotionUp = False;
4711 x = EventToSquare(event->xbutton.x, BOARD_WIDTH);
4712 y = EventToSquare(event->xbutton.y, BOARD_HEIGHT);
4713 if (!flipView && y >= 0) {
4714 y = BOARD_HEIGHT - 1 - y;
4716 if (flipView && x >= 0) {
4717 x = BOARD_WIDTH - 1 - x;
4720 /* [HGM] holdings: next 5 lines: ignore all clicks between board and holdings */
4721 if(event->type == ButtonPress
4722 && ( x == BOARD_LEFT-1 || x == BOARD_RGHT
4723 || x == BOARD_LEFT-2 && y < BOARD_HEIGHT-gameInfo.holdingsSize
4724 || x == BOARD_RGHT+1 && y >= gameInfo.holdingsSize) )
4728 if (event->type == ButtonPress) {
4730 if (OKToStartUserMove(x, y)) {
4734 DragPieceBegin(event->xbutton.x, event->xbutton.y);
4735 if (appData.highlightDragging) {
4736 SetHighlights(x, y, -1, -1);
4744 if (event->type == ButtonPress && gameMode != EditPosition &&
4749 /* Check if clicking again on the same color piece */
4750 fromP = boards[currentMove][fromY][fromX];
4751 toP = boards[currentMove][y][x];
4752 if ((WhitePawn <= fromP && fromP < WhiteKing && // [HGM] this test should go, as UserMoveTest now does it.
4753 WhitePawn <= toP && toP <= WhiteKing) || // For now I made it less critical by exempting King
4754 (BlackPawn <= fromP && fromP < BlackKing && // moves, to not interfere with FRC castlings.
4755 BlackPawn <= toP && toP <= BlackKing)) {
4756 /* Clicked again on same color piece -- changed his mind */
4757 second = (x == fromX && y == fromY);
4758 if (appData.highlightDragging) {
4759 SetHighlights(x, y, -1, -1);
4763 if (OKToStartUserMove(x, y)) {
4766 DragPieceBegin(event->xbutton.x, event->xbutton.y);
4772 if (event->type == ButtonRelease && x == fromX && y == fromY) {
4773 DragPieceEnd(event->xbutton.x, event->xbutton.y);
4774 if (appData.animateDragging) {
4775 /* Undo animation damage if any */
4776 DrawPosition(FALSE, NULL);
4779 /* Second up/down in same square; just abort move */
4784 ClearPremoveHighlights();
4786 /* First upclick in same square; start click-click mode */
4787 SetHighlights(x, y, -1, -1);
4792 /* Completed move */
4795 saveAnimate = appData.animate;
4796 if (event->type == ButtonPress) {
4797 /* Finish clickclick move */
4798 if (appData.animate || appData.highlightLastMove) {
4799 SetHighlights(fromX, fromY, toX, toY);
4804 /* Finish drag move */
4805 if (appData.highlightLastMove) {
4806 SetHighlights(fromX, fromY, toX, toY);
4810 DragPieceEnd(event->xbutton.x, event->xbutton.y);
4811 /* Don't animate move and drag both */
4812 appData.animate = FALSE;
4814 if (IsPromotion(fromX, fromY, toX, toY)) {
4815 if (appData.alwaysPromoteToQueen) {
4816 UserMoveEvent(fromX, fromY, toX, toY, 'q');
4817 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
4818 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
4821 SetHighlights(fromX, fromY, toX, toY);
4825 UserMoveEvent(fromX, fromY, toX, toY, NULLCHAR);
4826 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
4827 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
4830 appData.animate = saveAnimate;
4831 if (appData.animate || appData.animateDragging) {
4832 /* Undo animation damage if needed */
4833 DrawPosition(FALSE, NULL);
4837 void AnimateUserMove (Widget w, XEvent * event,
4838 String * params, Cardinal * nParams)
4840 DragPieceMove(event->xmotion.x, event->xmotion.y);
4843 Widget CommentCreate(name, text, mutable, callback, lines)
4845 int /*Boolean*/ mutable;
4846 XtCallbackProc callback;
4850 Widget shell, layout, form, edit, b_ok, b_cancel, b_clear, b_close, b_edit;
4855 XtSetArg(args[j], XtNwidth, &bw_width); j++;
4856 XtGetValues(boardWidget, args, j);
4859 XtSetArg(args[j], XtNresizable, True); j++;
4862 XtCreatePopupShell(name, topLevelShellWidgetClass,
4863 shellWidget, args, j);
4866 XtCreatePopupShell(name, transientShellWidgetClass,
4867 shellWidget, args, j);
4870 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
4871 layoutArgs, XtNumber(layoutArgs));
4873 XtCreateManagedWidget("form", formWidgetClass, layout,
4874 formArgs, XtNumber(formArgs));
4878 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
4879 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
4881 XtSetArg(args[j], XtNstring, text); j++;
4882 XtSetArg(args[j], XtNtop, XtChainTop); j++;
4883 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4884 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4885 XtSetArg(args[j], XtNright, XtChainRight); j++;
4886 XtSetArg(args[j], XtNresizable, True); j++;
4887 XtSetArg(args[j], XtNwidth, bw_width); j++; /*force wider than buttons*/
4889 XtSetArg(args[j], XtNscrollVertical, XawtextScrollWhenNeeded); j++;
4891 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
4892 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
4894 XtSetArg(args[j], XtNautoFill, True); j++;
4895 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
4897 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
4901 XtSetArg(args[j], XtNfromVert, edit); j++;
4902 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4903 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4904 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4905 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4907 XtCreateManagedWidget(_("ok"), commandWidgetClass, form, args, j);
4908 XtAddCallback(b_ok, XtNcallback, callback, (XtPointer) 0);
4911 XtSetArg(args[j], XtNfromVert, edit); j++;
4912 XtSetArg(args[j], XtNfromHoriz, b_ok); j++;
4913 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4914 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4915 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4916 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4918 XtCreateManagedWidget(_("cancel"), commandWidgetClass, form, args, j);
4919 XtAddCallback(b_cancel, XtNcallback, callback, (XtPointer) 0);
4922 XtSetArg(args[j], XtNfromVert, edit); j++;
4923 XtSetArg(args[j], XtNfromHoriz, b_cancel); j++;
4924 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4925 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4926 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4927 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4929 XtCreateManagedWidget(_("clear"), commandWidgetClass, form, args, j);
4930 XtAddCallback(b_clear, XtNcallback, callback, (XtPointer) 0);
4933 XtSetArg(args[j], XtNfromVert, edit); j++;
4934 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4935 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4936 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4937 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4939 XtCreateManagedWidget(_("close"), commandWidgetClass, form, args, j);
4940 XtAddCallback(b_close, XtNcallback, callback, (XtPointer) 0);
4943 XtSetArg(args[j], XtNfromVert, edit); j++;
4944 XtSetArg(args[j], XtNfromHoriz, b_close); j++;
4945 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4946 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4947 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4948 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4950 XtCreateManagedWidget(_("edit"), commandWidgetClass, form, args, j);
4951 XtAddCallback(b_edit, XtNcallback, callback, (XtPointer) 0);
4954 XtRealizeWidget(shell);
4956 if (commentX == -1) {
4959 Dimension pw_height;
4960 Dimension ew_height;
4963 XtSetArg(args[j], XtNheight, &ew_height); j++;
4964 XtGetValues(edit, args, j);
4967 XtSetArg(args[j], XtNheight, &pw_height); j++;
4968 XtGetValues(shell, args, j);
4969 commentH = pw_height + (lines - 1) * ew_height;
4970 commentW = bw_width - 16;
4972 XSync(xDisplay, False);
4974 /* This code seems to tickle an X bug if it is executed too soon
4975 after xboard starts up. The coordinates get transformed as if
4976 the main window was positioned at (0, 0).
4978 XtTranslateCoords(shellWidget,
4979 (bw_width - commentW) / 2, 0 - commentH / 2,
4980 &commentX, &commentY);
4982 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
4983 RootWindowOfScreen(XtScreen(shellWidget)),
4984 (bw_width - commentW) / 2, 0 - commentH / 2,
4989 if (commentY < 0) commentY = 0; /*avoid positioning top offscreen*/
4992 XtSetArg(args[j], XtNheight, commentH); j++;
4993 XtSetArg(args[j], XtNwidth, commentW); j++;
4994 XtSetArg(args[j], XtNx, commentX); j++;
4995 XtSetArg(args[j], XtNy, commentY); j++;
4996 XtSetValues(shell, args, j);
4997 XtSetKeyboardFocus(shell, edit);
5002 /* Used for analysis window and ICS input window */
5003 Widget MiscCreate(name, text, mutable, callback, lines)
5005 int /*Boolean*/ mutable;
5006 XtCallbackProc callback;
5010 Widget shell, layout, form, edit;
5012 Dimension bw_width, pw_height, ew_height, w, h;
5018 XtSetArg(args[j], XtNresizable, True); j++;
5021 XtCreatePopupShell(name, topLevelShellWidgetClass,
5022 shellWidget, args, j);
5025 XtCreatePopupShell(name, transientShellWidgetClass,
5026 shellWidget, args, j);
5029 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
5030 layoutArgs, XtNumber(layoutArgs));
5032 XtCreateManagedWidget("form", formWidgetClass, layout,
5033 formArgs, XtNumber(formArgs));
5037 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
5038 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
5040 XtSetArg(args[j], XtNstring, text); j++;
5041 XtSetArg(args[j], XtNtop, XtChainTop); j++;
5042 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5043 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5044 XtSetArg(args[j], XtNright, XtChainRight); j++;
5045 XtSetArg(args[j], XtNresizable, True); j++;
5047 XtSetArg(args[j], XtNscrollVertical, XawtextScrollWhenNeeded); j++;
5049 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
5050 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
5052 XtSetArg(args[j], XtNautoFill, True); j++;
5053 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
5055 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
5057 XtRealizeWidget(shell);
5060 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5061 XtGetValues(boardWidget, args, j);
5064 XtSetArg(args[j], XtNheight, &ew_height); j++;
5065 XtGetValues(edit, args, j);
5068 XtSetArg(args[j], XtNheight, &pw_height); j++;
5069 XtGetValues(shell, args, j);
5070 h = pw_height + (lines - 1) * ew_height;
5073 XSync(xDisplay, False);
5075 /* This code seems to tickle an X bug if it is executed too soon
5076 after xboard starts up. The coordinates get transformed as if
5077 the main window was positioned at (0, 0).
5079 XtTranslateCoords(shellWidget, (bw_width - w) / 2, 0 - h / 2, &x, &y);
5081 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
5082 RootWindowOfScreen(XtScreen(shellWidget)),
5083 (bw_width - w) / 2, 0 - h / 2, &xx, &yy, &junk);
5087 if (y < 0) y = 0; /*avoid positioning top offscreen*/
5090 XtSetArg(args[j], XtNheight, h); j++;
5091 XtSetArg(args[j], XtNwidth, w); j++;
5092 XtSetArg(args[j], XtNx, x); j++;
5093 XtSetArg(args[j], XtNy, y); j++;
5094 XtSetValues(shell, args, j);
5100 static int savedIndex; /* gross that this is global */
5102 void EditCommentPopUp(index, title, text)
5111 if (text == NULL) text = "";
5113 if (editShell == NULL) {
5115 CommentCreate(title, text, True, EditCommentCallback, 4);
5116 XtRealizeWidget(editShell);
5117 CatchDeleteWindow(editShell, "EditCommentPopDown");
5119 edit = XtNameToWidget(editShell, "*form.text");
5121 XtSetArg(args[j], XtNstring, text); j++;
5122 XtSetValues(edit, args, j);
5124 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5125 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5126 XtSetValues(editShell, args, j);
5129 XtPopup(editShell, XtGrabNone);
5133 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
5134 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
5138 void EditCommentCallback(w, client_data, call_data)
5140 XtPointer client_data, call_data;
5148 XtSetArg(args[j], XtNlabel, &name); j++;
5149 XtGetValues(w, args, j);
5151 if (strcmp(name, _("ok")) == 0) {
5152 edit = XtNameToWidget(editShell, "*form.text");
5154 XtSetArg(args[j], XtNstring, &val); j++;
5155 XtGetValues(edit, args, j);
5156 ReplaceComment(savedIndex, val);
5157 EditCommentPopDown();
5158 } else if (strcmp(name, _("cancel")) == 0) {
5159 EditCommentPopDown();
5160 } else if (strcmp(name, _("clear")) == 0) {
5161 edit = XtNameToWidget(editShell, "*form.text");
5162 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
5163 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
5167 void EditCommentPopDown()
5172 if (!editUp) return;
5174 XtSetArg(args[j], XtNx, &commentX); j++;
5175 XtSetArg(args[j], XtNy, &commentY); j++;
5176 XtSetArg(args[j], XtNheight, &commentH); j++;
5177 XtSetArg(args[j], XtNwidth, &commentW); j++;
5178 XtGetValues(editShell, args, j);
5179 XtPopdown(editShell);
5182 XtSetArg(args[j], XtNleftBitmap, None); j++;
5183 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
5187 void ICSInputBoxPopUp()
5192 char *title = _("ICS Input");
5195 if (ICSInputShell == NULL) {
5196 ICSInputShell = MiscCreate(title, "", True, NULL, 1);
5197 tr = XtParseTranslationTable(ICSInputTranslations);
5198 edit = XtNameToWidget(ICSInputShell, "*form.text");
5199 XtOverrideTranslations(edit, tr);
5200 XtRealizeWidget(ICSInputShell);
5201 CatchDeleteWindow(ICSInputShell, "ICSInputBoxPopDown");
5204 edit = XtNameToWidget(ICSInputShell, "*form.text");
5206 XtSetArg(args[j], XtNstring, ""); j++;
5207 XtSetValues(edit, args, j);
5209 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5210 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5211 XtSetValues(ICSInputShell, args, j);
5214 XtPopup(ICSInputShell, XtGrabNone);
5215 XtSetKeyboardFocus(ICSInputShell, edit);
5217 ICSInputBoxUp = True;
5219 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
5220 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
5224 void ICSInputSendText()
5231 edit = XtNameToWidget(ICSInputShell, "*form.text");
5233 XtSetArg(args[j], XtNstring, &val); j++;
5234 XtGetValues(edit, args, j);
5235 SendMultiLineToICS(val);
5236 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
5237 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
5240 void ICSInputBoxPopDown()
5245 if (!ICSInputBoxUp) return;
5247 XtPopdown(ICSInputShell);
5248 ICSInputBoxUp = False;
5250 XtSetArg(args[j], XtNleftBitmap, None); j++;
5251 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
5255 void CommentPopUp(title, text)
5262 if (commentShell == NULL) {
5264 CommentCreate(title, text, False, CommentCallback, 4);
5265 XtRealizeWidget(commentShell);
5266 CatchDeleteWindow(commentShell, "CommentPopDown");
5268 edit = XtNameToWidget(commentShell, "*form.text");
5270 XtSetArg(args[j], XtNstring, text); j++;
5271 XtSetValues(edit, args, j);
5273 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5274 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5275 XtSetValues(commentShell, args, j);
5278 XtPopup(commentShell, XtGrabNone);
5279 XSync(xDisplay, False);
5284 void AnalysisPopUp(title, text)
5291 if (analysisShell == NULL) {
5292 analysisShell = MiscCreate(title, text, False, NULL, 4);
5293 XtRealizeWidget(analysisShell);
5294 CatchDeleteWindow(analysisShell, "AnalysisPopDown");
5297 edit = XtNameToWidget(analysisShell, "*form.text");
5299 XtSetArg(args[j], XtNstring, text); j++;
5300 XtSetValues(edit, args, j);
5302 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5303 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5304 XtSetValues(analysisShell, args, j);
5308 XtPopup(analysisShell, XtGrabNone);
5310 XSync(xDisplay, False);
5315 void CommentCallback(w, client_data, call_data)
5317 XtPointer client_data, call_data;
5324 XtSetArg(args[j], XtNlabel, &name); j++;
5325 XtGetValues(w, args, j);
5327 if (strcmp(name, _("close")) == 0) {
5329 } else if (strcmp(name, _("edit")) == 0) {
5336 void CommentPopDown()
5341 if (!commentUp) return;
5343 XtSetArg(args[j], XtNx, &commentX); j++;
5344 XtSetArg(args[j], XtNy, &commentY); j++;
5345 XtSetArg(args[j], XtNwidth, &commentW); j++;
5346 XtSetArg(args[j], XtNheight, &commentH); j++;
5347 XtGetValues(commentShell, args, j);
5348 XtPopdown(commentShell);
5349 XSync(xDisplay, False);
5353 void AnalysisPopDown()
5355 if (!analysisUp) return;
5356 XtPopdown(analysisShell);
5357 XSync(xDisplay, False);
5359 if (appData.icsEngineAnalyze) ExitAnalyzeMode(); /* [DM] icsEngineAnalyze */
5363 void FileNamePopUp(label, def, proc, openMode)
5370 Widget popup, layout, dialog, edit;
5376 fileProc = proc; /* I can't see a way not */
5377 fileOpenMode = openMode; /* to use globals here */
5380 XtSetArg(args[i], XtNresizable, True); i++;
5381 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
5382 XtSetArg(args[i], XtNtitle, XtNewString(_("File name prompt"))); i++;
5383 fileNameShell = popup =
5384 XtCreatePopupShell("File name prompt", transientShellWidgetClass,
5385 shellWidget, args, i);
5388 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
5389 layoutArgs, XtNumber(layoutArgs));
5392 XtSetArg(args[i], XtNlabel, label); i++;
5393 XtSetArg(args[i], XtNvalue, def); i++;
5394 XtSetArg(args[i], XtNborderWidth, 0); i++;
5395 dialog = XtCreateManagedWidget("fileName", dialogWidgetClass,
5398 XawDialogAddButton(dialog, _("ok"), FileNameCallback, (XtPointer) dialog);
5399 XawDialogAddButton(dialog, _("cancel"), FileNameCallback,
5400 (XtPointer) dialog);
5402 XtRealizeWidget(popup);
5403 CatchDeleteWindow(popup, "FileNamePopDown");
5405 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
5406 &x, &y, &win_x, &win_y, &mask);
5408 XtSetArg(args[0], XtNx, x - 10);
5409 XtSetArg(args[1], XtNy, y - 30);
5410 XtSetValues(popup, args, 2);
5412 XtPopup(popup, XtGrabExclusive);
5415 edit = XtNameToWidget(dialog, "*value");
5416 XtSetKeyboardFocus(popup, edit);
5419 void FileNamePopDown()
5421 if (!filenameUp) return;
5422 XtPopdown(fileNameShell);
5423 XtDestroyWidget(fileNameShell);
5428 void FileNameCallback(w, client_data, call_data)
5430 XtPointer client_data, call_data;
5435 XtSetArg(args[0], XtNlabel, &name);
5436 XtGetValues(w, args, 1);
5438 if (strcmp(name, _("cancel")) == 0) {
5443 FileNameAction(w, NULL, NULL, NULL);
5446 void FileNameAction(w, event, prms, nprms)
5458 name = XawDialogGetValueString(w = XtParent(w));
5460 if ((name != NULL) && (*name != NULLCHAR)) {
5462 XtPopdown(w = XtParent(XtParent(w)));
5466 p = strrchr(buf, ' ');
5473 fullname = ExpandPathName(buf);
5475 ErrorPopUp(_("Error"), _("Can't open file"), FALSE);
5478 f = fopen(fullname, fileOpenMode);
5480 DisplayError(_("Failed to open file"), errno);
5482 (void) (*fileProc)(f, index, buf);
5489 XtPopdown(w = XtParent(XtParent(w)));
5495 void PromotionPopUp()
5498 Widget dialog, layout;
5500 Dimension bw_width, pw_width;
5504 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5505 XtGetValues(boardWidget, args, j);
5508 XtSetArg(args[j], XtNresizable, True); j++;
5509 XtSetArg(args[j], XtNtitle, XtNewString(_("Promotion"))); j++;
5511 XtCreatePopupShell("Promotion", transientShellWidgetClass,
5512 shellWidget, args, j);
5514 XtCreateManagedWidget(layoutName, formWidgetClass, promotionShell,
5515 layoutArgs, XtNumber(layoutArgs));
5518 XtSetArg(args[j], XtNlabel, _("Promote to what?")); j++;
5519 XtSetArg(args[j], XtNborderWidth, 0); j++;
5520 dialog = XtCreateManagedWidget("promotion", dialogWidgetClass,
5523 if(gameInfo.variant != VariantShogi) {
5524 XawDialogAddButton(dialog, _("Queen"), PromotionCallback,
5525 (XtPointer) dialog);
5526 XawDialogAddButton(dialog, _("Rook"), PromotionCallback,
5527 (XtPointer) dialog);
5528 XawDialogAddButton(dialog, _("Bishop"), PromotionCallback,
5529 (XtPointer) dialog);
5530 XawDialogAddButton(dialog, _("Knight"), PromotionCallback,
5531 (XtPointer) dialog);
5532 if (!appData.testLegality || gameInfo.variant == VariantSuicide ||
5533 gameInfo.variant == VariantGiveaway) {
5534 XawDialogAddButton(dialog, _("King"), PromotionCallback,
5535 (XtPointer) dialog);
5537 if(gameInfo.variant == VariantCapablanca ||
5538 gameInfo.variant == VariantGothic ||
5539 gameInfo.variant == VariantCapaRandom) {
5540 XawDialogAddButton(dialog, _("Archbishop"), PromotionCallback,
5541 (XtPointer) dialog);
5542 XawDialogAddButton(dialog, _("Chancellor"), PromotionCallback,
5543 (XtPointer) dialog);
5545 } else // [HGM] shogi
5547 XawDialogAddButton(dialog, _("Promote"), PromotionCallback,
5548 (XtPointer) dialog);
5549 XawDialogAddButton(dialog, _("Defer"), PromotionCallback,
5550 (XtPointer) dialog);
5552 XawDialogAddButton(dialog, _("cancel"), PromotionCallback,
5553 (XtPointer) dialog);
5555 XtRealizeWidget(promotionShell);
5556 CatchDeleteWindow(promotionShell, "PromotionPopDown");
5559 XtSetArg(args[j], XtNwidth, &pw_width); j++;
5560 XtGetValues(promotionShell, args, j);
5562 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
5563 lineGap + squareSize/3 +
5564 ((toY == BOARD_HEIGHT-1) ^ (flipView) ?
5565 0 : 6*(squareSize + lineGap)), &x, &y);
5568 XtSetArg(args[j], XtNx, x); j++;
5569 XtSetArg(args[j], XtNy, y); j++;
5570 XtSetValues(promotionShell, args, j);
5572 XtPopup(promotionShell, XtGrabNone);
5577 void PromotionPopDown()
5579 if (!promotionUp) return;
5580 XtPopdown(promotionShell);
5581 XtDestroyWidget(promotionShell);
5582 promotionUp = False;
5585 void PromotionCallback(w, client_data, call_data)
5587 XtPointer client_data, call_data;
5593 XtSetArg(args[0], XtNlabel, &name);
5594 XtGetValues(w, args, 1);
5598 if (fromX == -1) return;
5600 if (strcmp(name, _("cancel")) == 0) {
5604 } else if (strcmp(name, _("Knight")) == 0) {
5606 } else if (strcmp(name, _("Promote")) == 0) {
5608 } else if (strcmp(name, _("Defer")) == 0) {
5611 promoChar = ToLower(name[0]);
5614 UserMoveEvent(fromX, fromY, toX, toY, promoChar);
5616 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
5617 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
5622 void ErrorCallback(w, client_data, call_data)
5624 XtPointer client_data, call_data;
5627 XtPopdown(w = XtParent(XtParent(XtParent(w))));
5629 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
5635 if (!errorUp) return;
5637 XtPopdown(errorShell);
5638 XtDestroyWidget(errorShell);
5639 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
5642 void ErrorPopUp(title, label, modal)
5643 char *title, *label;
5648 printf ("DEBUG: error %s %s\n\n",title,label);
5650 dialog = gtk_message_dialog_new(GTK_WINDOW(GUI_Window),
5651 GTK_DIALOG_DESTROY_WITH_PARENT,
5656 gtk_window_set_title(GTK_WINDOW(dialog),(gchar *) title);
5659 gtk_dialog_run(GTK_DIALOG(dialog));
5660 gtk_widget_destroy(GTK_WIDGET(dialog));
5664 g_signal_connect_swapped (dialog, "response",
5665 G_CALLBACK (ErrorPopDownProc),
5668 gtk_widget_show(GTK_WIDGET(dialog));
5672 /* Disable all user input other than deleting the window */
5673 static int frozen = 0;
5677 /* Grab by a widget that doesn't accept input */
5678 // XtAddGrab(messageWidget, TRUE, FALSE);
5682 /* Undo a FreezeUI */
5685 if (!frozen) return;
5686 XtRemoveGrab(messageWidget);
5690 char *ModeToWidgetName(mode)
5694 case BeginningOfGame:
5695 if (appData.icsActive)
5696 return "menuMode.ICS Client";
5697 else if (appData.noChessProgram ||
5698 *appData.cmailGameName != NULLCHAR)
5699 return "menuMode.Edit Game";
5701 return "menuMode.Machine Black";
5702 case MachinePlaysBlack:
5703 return "menuMode.Machine Black";
5704 case MachinePlaysWhite:
5705 return "menuMode.Machine White";
5707 return "menuMode.Analysis Mode";
5709 return "menuMode.Analyze File";
5710 case TwoMachinesPlay:
5711 return "menuMode.Two Machines";
5713 return "menuMode.Edit Game";
5714 case PlayFromGameFile:
5715 return "menuFile.Load Game";
5717 return "menuMode.Edit Position";
5719 return "menuMode.Training";
5720 case IcsPlayingWhite:
5721 case IcsPlayingBlack:
5725 return "menuMode.ICS Client";
5732 void ModeHighlight()
5734 static int oldPausing = FALSE;
5735 static GameMode oldmode = (GameMode) -1;
5738 // todo this toggling of the pause button doesn't seem to work?
5739 // e.g. select pause from buttonbar doesn't activate menumode.pause
5741 // fprintf(stderr,"DEBUG: oldmode %d newmode %d oldpause %d newpause %d\n",oldmode,gameMode,oldPausing,pausing);
5744 // if (!boardWidget || !XtIsRealized(boardWidget)) return;
5746 if (pausing != oldPausing) {
5747 oldPausing = pausing;
5748 gtk_button_set_relief(GTK_BUTTON (gtk_builder_get_object (builder, "menuMode.Pause")),pausing?GTK_RELIEF_NORMAL:GTK_RELIEF_NONE);
5749 /* toggle background color in showbuttonbar */
5750 if (appData.showButtonBar) {
5752 gtk_button_pressed(GTK_BUTTON (gtk_builder_get_object (builder, "buttonbar.Pause")));
5754 gtk_button_released(GTK_BUTTON (gtk_builder_get_object (builder, "buttonbar.Pause")));
5759 wname = ModeToWidgetName(oldmode);
5761 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, wname)),True);
5765 /* Maybe all the enables should be handled here, not just this one */
5766 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuMode.Training")),
5767 gameMode == Training || gameMode == PlayFromGameFile);
5772 * Button/menu procedures
5775 int LoadGamePopUp(f, gameNumber, title)
5780 cmailMsgLoaded = FALSE;
5781 if (gameNumber == 0) {
5782 int error = GameListBuild(f);
5784 DisplayError(_("Cannot build game list"), error);
5785 } else if (!ListEmpty(&gameList) &&
5786 ((ListGame *) gameList.tailPred)->number > 1) {
5787 GameListPopUp(f, title);
5793 return LoadGame(f, gameNumber, title, FALSE);
5797 void LoadNextPositionProc(w, event, prms, nprms)
5806 void LoadPrevPositionProc(w, event, prms, nprms)
5815 void ReloadPositionProc(w, event, prms, nprms)
5824 void LoadPositionProc(w, event, prms, nprms)
5830 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
5833 FileNamePopUp(_("Load position file name?"), "", LoadPosition, "rb");
5836 void SaveGameProc(w, event, prms, nprms)
5842 FileNamePopUp(_("Save game file name?"),
5843 DefaultFileName(appData.oldSaveStyle ? "game" : "pgn"),
5847 void SavePositionProc(w, event, prms, nprms)
5853 FileNamePopUp(_("Save position file name?"),
5854 DefaultFileName(appData.oldSaveStyle ? "pos" : "fen"),
5858 void ReloadCmailMsgProc(w, event, prms, nprms)
5864 ReloadCmailMsgEvent(FALSE);
5867 void MailMoveProc(w, event, prms, nprms)
5876 /* this variable is shared between CopyPositionProc and SendPositionSelection */
5877 static char *selected_fen_position=NULL;
5880 SendPositionSelection(Widget w, Atom *selection, Atom *target,
5881 Atom *type_return, XtPointer *value_return,
5882 unsigned long *length_return, int *format_return)
5884 char *selection_tmp;
5886 if (!selected_fen_position) return False; /* should never happen */
5887 if (*target == XA_STRING){
5888 /* note: since no XtSelectionDoneProc was registered, Xt will
5889 * automatically call XtFree on the value returned. So have to
5890 * make a copy of it allocated with XtMalloc */
5891 selection_tmp= XtMalloc(strlen(selected_fen_position)+16);
5892 strcpy(selection_tmp, selected_fen_position);
5894 *value_return=selection_tmp;
5895 *length_return=strlen(selection_tmp);
5896 *type_return=XA_STRING;
5897 *format_return = 8; /* bits per byte */
5904 /* note: when called from menu all parameters are NULL, so no clue what the
5905 * Widget which was clicked on was, or what the click event was
5907 void CopyPositionProc(w, event, prms, nprms)
5915 if (selected_fen_position) free(selected_fen_position);
5916 selected_fen_position = (char *)PositionToFEN(currentMove, NULL);
5917 if (!selected_fen_position) return;
5918 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
5920 SendPositionSelection,
5921 NULL/* lose_ownership_proc */ ,
5922 NULL/* transfer_done_proc */);
5924 free(selected_fen_position);
5925 selected_fen_position=NULL;
5929 /* function called when the data to Paste is ready */
5931 PastePositionCB(Widget w, XtPointer client_data, Atom *selection,
5932 Atom *type, XtPointer value, unsigned long *len, int *format)
5935 if (value==NULL || *len==0) return; /* nothing had been selected to copy */
5936 fenstr[*len]='\0'; /* normally this string is terminated, but be safe */
5937 EditPositionPasteFEN(fenstr);
5941 /* called when Paste Position button is pressed,
5942 * all parameters will be NULL */
5943 void PastePositionProc(w, event, prms, nprms)
5949 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
5950 /* (XtSelectionCallbackProc) */ PastePositionCB,
5951 NULL, /* client_data passed to PastePositionCB */
5953 /* better to use the time field from the event that triggered the
5954 * call to this function, but that isn't trivial to get
5962 SendGameSelection(Widget w, Atom *selection, Atom *target,
5963 Atom *type_return, XtPointer *value_return,
5964 unsigned long *length_return, int *format_return)
5966 char *selection_tmp;
5968 if (*target == XA_STRING){
5969 FILE* f = fopen(gameCopyFilename, "r");
5972 if (f == NULL) return False;
5976 selection_tmp = XtMalloc(len + 1);
5977 count = fread(selection_tmp, 1, len, f);
5979 XtFree(selection_tmp);
5982 selection_tmp[len] = NULLCHAR;
5983 *value_return = selection_tmp;
5984 *length_return = len;
5985 *type_return = XA_STRING;
5986 *format_return = 8; /* bits per byte */
5993 /* note: when called from menu all parameters are NULL, so no clue what the
5994 * Widget which was clicked on was, or what the click event was
5996 void CopyGameProc(w, event, prms, nprms)
6004 ret = SaveGameToFile(gameCopyFilename, FALSE);
6007 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
6010 NULL/* lose_ownership_proc */ ,
6011 NULL/* transfer_done_proc */);
6014 /* function called when the data to Paste is ready */
6016 PasteGameCB(Widget w, XtPointer client_data, Atom *selection,
6017 Atom *type, XtPointer value, unsigned long *len, int *format)
6020 if (value == NULL || *len == 0) {
6021 return; /* nothing had been selected to copy */
6023 f = fopen(gamePasteFilename, "w");
6025 DisplayError(_("Can't open temp file"), errno);
6028 fwrite(value, 1, *len, f);
6031 LoadGameFromFile(gamePasteFilename, 0, gamePasteFilename, TRUE);
6034 /* called when Paste Game button is pressed,
6035 * all parameters will be NULL */
6036 void PasteGameProc(w, event, prms, nprms)
6042 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
6043 /* (XtSelectionCallbackProc) */ PasteGameCB,
6044 NULL, /* client_data passed to PasteGameCB */
6046 /* better to use the time field from the event that triggered the
6047 * call to this function, but that isn't trivial to get
6057 SaveGameProc(NULL, NULL, NULL, NULL);
6060 void MachineBlackProc(w, event, prms, nprms)
6066 MachineBlackEvent();
6069 void MachineWhiteProc(w, event, prms, nprms)
6075 MachineWhiteEvent();
6078 void AnalyzeModeProc(w, event, prms, nprms)
6086 if (!first.analysisSupport) {
6087 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
6088 DisplayError(buf, 0);
6091 /* [DM] icsEngineAnalyze [HGM] This is horrible code; reverse the gameMode and isEngineAnalyze tests! */
6092 if (appData.icsActive) {
6093 if (gameMode != IcsObserving) {
6094 sprintf(buf,_("You are not observing a game"));
6095 DisplayError(buf, 0);
6097 if (appData.icsEngineAnalyze) {
6098 if (appData.debugMode)
6099 fprintf(debugFP, _("Found unexpected active ICS engine analyze \n"));
6105 /* if enable, use want disable icsEngineAnalyze */
6106 if (appData.icsEngineAnalyze) {
6111 appData.icsEngineAnalyze = TRUE;
6112 if (appData.debugMode)
6113 fprintf(debugFP, _("ICS engine analyze starting... \n"));
6115 if (!appData.showThinking)
6116 ShowThinkingProc(w,event,prms,nprms);
6121 void AnalyzeFileProc(w, event, prms, nprms)
6127 if (!first.analysisSupport) {
6129 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
6130 DisplayError(buf, 0);
6135 if (!appData.showThinking)
6136 ShowThinkingProc(w,event,prms,nprms);
6139 FileNamePopUp(_("File to analyze"), "", LoadGamePopUp, "rb");
6140 AnalysisPeriodicEvent(1);
6143 void TwoMachinesProc(w, event, prms, nprms)
6152 void IcsClientProc(w, event, prms, nprms)
6161 void EditGameProc(w, event, prms, nprms)
6170 void EditPositionProc(w, event, prms, nprms)
6176 EditPositionEvent();
6179 void TrainingProc(w, event, prms, nprms)
6188 void EditCommentProc(w, event, prms, nprms)
6195 EditCommentPopDown();
6201 void IcsInputBoxProc(w, event, prms, nprms)
6207 if (ICSInputBoxUp) {
6208 ICSInputBoxPopDown();
6214 void AcceptProc(w, event, prms, nprms)
6223 void DeclineProc(w, event, prms, nprms)
6232 void RematchProc(w, event, prms, nprms)
6241 void CallFlagProc(w, event, prms, nprms)
6250 void DrawProc(w, event, prms, nprms)
6259 void AbortProc(w, event, prms, nprms)
6268 void AdjournProc(w, event, prms, nprms)
6277 void ResignProc(w, event, prms, nprms)
6286 void AdjuWhiteProc(w, event, prms, nprms)
6292 UserAdjudicationEvent(+1);
6295 void AdjuBlackProc(w, event, prms, nprms)
6301 UserAdjudicationEvent(-1);
6304 void AdjuDrawProc(w, event, prms, nprms)
6310 UserAdjudicationEvent(0);
6313 void EnterKeyProc(w, event, prms, nprms)
6319 if (ICSInputBoxUp == True)
6323 void StopObservingProc(w, event, prms, nprms)
6329 StopObservingEvent();
6332 void StopExaminingProc(w, event, prms, nprms)
6338 StopExaminingEvent();
6342 void ForwardProc(w, event, prms, nprms)
6352 void BackwardProc(w, event, prms, nprms)
6361 void ToStartProc(w, event, prms, nprms)
6370 void ToEndProc(w, event, prms, nprms)
6379 void RevertProc(w, event, prms, nprms)
6388 void TruncateGameProc(w, event, prms, nprms)
6394 TruncateGameEvent();
6396 void RetractMoveProc(w, event, prms, nprms)
6405 void MoveNowProc(w, event, prms, nprms)
6415 void AlwaysQueenProc(w, event, prms, nprms)
6423 appData.alwaysPromoteToQueen = !appData.alwaysPromoteToQueen;
6425 if (appData.alwaysPromoteToQueen) {
6426 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6428 XtSetArg(args[0], XtNleftBitmap, None);
6430 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
6434 void AnimateDraggingProc(w, event, prms, nprms)
6442 appData.animateDragging = !appData.animateDragging;
6444 if (appData.animateDragging) {
6445 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6448 XtSetArg(args[0], XtNleftBitmap, None);
6450 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Dragging"),
6454 void AnimateMovingProc(w, event, prms, nprms)
6462 appData.animate = !appData.animate;
6464 if (appData.animate) {
6465 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6468 XtSetArg(args[0], XtNleftBitmap, None);
6470 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
6474 void AutocommProc(w, event, prms, nprms)
6482 appData.autoComment = !appData.autoComment;
6484 if (appData.autoComment) {
6485 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6487 XtSetArg(args[0], XtNleftBitmap, None);
6489 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
6494 void AutoflagProc(w, event, prms, nprms)
6502 appData.autoCallFlag = !appData.autoCallFlag;
6504 if (appData.autoCallFlag) {
6505 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6507 XtSetArg(args[0], XtNleftBitmap, None);
6509 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
6513 void AutoflipProc(w, event, prms, nprms)
6521 appData.autoFlipView = !appData.autoFlipView;
6523 if (appData.autoFlipView) {
6524 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6526 XtSetArg(args[0], XtNleftBitmap, None);
6528 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flip View"),
6532 void AutobsProc(w, event, prms, nprms)
6540 appData.autoObserve = !appData.autoObserve;
6542 if (appData.autoObserve) {
6543 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6545 XtSetArg(args[0], XtNleftBitmap, None);
6547 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
6551 void AutoraiseProc(w, event, prms, nprms)
6559 appData.autoRaiseBoard = !appData.autoRaiseBoard;
6561 if (appData.autoRaiseBoard) {
6562 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6564 XtSetArg(args[0], XtNleftBitmap, None);
6566 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Raise Board"),
6570 void AutosaveProc(w, event, prms, nprms)
6578 appData.autoSaveGames = !appData.autoSaveGames;
6580 if (appData.autoSaveGames) {
6581 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6583 XtSetArg(args[0], XtNleftBitmap, None);
6585 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
6589 void BlindfoldProc(w, event, prms, nprms)
6597 appData.blindfold = !appData.blindfold;
6599 if (appData.blindfold) {
6600 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6602 XtSetArg(args[0], XtNleftBitmap, None);
6604 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Blindfold"),
6607 DrawPosition(True, NULL);
6610 void TestLegalityProc(w, event, prms, nprms)
6618 appData.testLegality = !appData.testLegality;
6620 if (appData.testLegality) {
6621 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6623 XtSetArg(args[0], XtNleftBitmap, None);
6625 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Test Legality"),
6630 void FlashMovesProc(w, event, prms, nprms)
6638 if (appData.flashCount == 0) {
6639 appData.flashCount = 3;
6641 appData.flashCount = -appData.flashCount;
6644 if (appData.flashCount > 0) {
6645 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6647 XtSetArg(args[0], XtNleftBitmap, None);
6649 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flash Moves"),
6653 void FlipViewProc(w, event, prms, nprms)
6659 flipView = !flipView;
6660 DrawPosition(True, NULL);
6663 void GetMoveListProc(w, event, prms, nprms)
6671 appData.getMoveList = !appData.getMoveList;
6673 if (appData.getMoveList) {
6674 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6677 XtSetArg(args[0], XtNleftBitmap, None);
6679 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
6684 void HighlightDraggingProc(w, event, prms, nprms)
6692 appData.highlightDragging = !appData.highlightDragging;
6694 if (appData.highlightDragging) {
6695 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6697 XtSetArg(args[0], XtNleftBitmap, None);
6699 XtSetValues(XtNameToWidget(menuBarWidget,
6700 "menuOptions.Highlight Dragging"), args, 1);
6704 void HighlightLastMoveProc(w, event, prms, nprms)
6712 appData.highlightLastMove = !appData.highlightLastMove;
6714 if (appData.highlightLastMove) {
6715 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6717 XtSetArg(args[0], XtNleftBitmap, None);
6719 XtSetValues(XtNameToWidget(menuBarWidget,
6720 "menuOptions.Highlight Last Move"), args, 1);
6723 void IcsAlarmProc(w, event, prms, nprms)
6731 appData.icsAlarm = !appData.icsAlarm;
6733 if (appData.icsAlarm) {
6734 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6736 XtSetArg(args[0], XtNleftBitmap, None);
6738 XtSetValues(XtNameToWidget(menuBarWidget,
6739 "menuOptions.ICS Alarm"), args, 1);
6742 void MoveSoundProc(w, event, prms, nprms)
6750 appData.ringBellAfterMoves = !appData.ringBellAfterMoves;
6752 if (appData.ringBellAfterMoves) {
6753 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6755 XtSetArg(args[0], XtNleftBitmap, None);
6757 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
6762 void OldSaveStyleProc(w, event, prms, nprms)
6770 appData.oldSaveStyle = !appData.oldSaveStyle;
6772 if (appData.oldSaveStyle) {
6773 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6775 XtSetArg(args[0], XtNleftBitmap, None);
6777 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Old Save Style"),
6781 void PeriodicUpdatesProc(w, event, prms, nprms)
6789 PeriodicUpdatesEvent(!appData.periodicUpdates);
6791 if (appData.periodicUpdates) {
6792 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6794 XtSetArg(args[0], XtNleftBitmap, None);
6796 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Periodic Updates"),
6800 void PonderNextMoveProc(w, event, prms, nprms)
6808 PonderNextMoveEvent(!appData.ponderNextMove);
6810 if (appData.ponderNextMove) {
6811 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6813 XtSetArg(args[0], XtNleftBitmap, None);
6815 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Ponder Next Move"),
6819 void PopupExitMessageProc(w, event, prms, nprms)
6827 appData.popupExitMessage = !appData.popupExitMessage;
6829 if (appData.popupExitMessage) {
6830 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6832 XtSetArg(args[0], XtNleftBitmap, None);
6834 XtSetValues(XtNameToWidget(menuBarWidget,
6835 "menuOptions.Popup Exit Message"), args, 1);
6838 void PopupMoveErrorsProc(w, event, prms, nprms)
6846 appData.popupMoveErrors = !appData.popupMoveErrors;
6848 if (appData.popupMoveErrors) {
6849 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6851 XtSetArg(args[0], XtNleftBitmap, None);
6853 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Popup Move Errors"),
6857 void PremoveProc(w, event, prms, nprms)
6865 appData.premove = !appData.premove;
6867 if (appData.premove) {
6868 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6870 XtSetArg(args[0], XtNleftBitmap, None);
6872 XtSetValues(XtNameToWidget(menuBarWidget,
6873 "menuOptions.Premove"), args, 1);
6876 void QuietPlayProc(w, event, prms, nprms)
6884 appData.quietPlay = !appData.quietPlay;
6886 if (appData.quietPlay) {
6887 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6889 XtSetArg(args[0], XtNleftBitmap, None);
6891 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Quiet Play"),
6895 void ShowThinkingProc(w, event, prms, nprms)
6903 appData.showThinking = !appData.showThinking; // [HGM] thinking: tken out of ShowThinkingEvent
6904 ShowThinkingEvent();
6906 // [HGM] thinking: currently no suc menu item; replaced by Hide Thinking (From Human)
6907 if (appData.showThinking) {
6908 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6910 XtSetArg(args[0], XtNleftBitmap, None);
6912 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Thinking"),
6917 void HideThinkingProc(w, event, prms, nprms)
6925 appData.hideThinkingFromHuman = !appData.hideThinkingFromHuman; // [HGM] thinking: tken out of ShowThinkingEvent
6926 ShowThinkingEvent();
6928 if (appData.hideThinkingFromHuman) {
6929 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6931 XtSetArg(args[0], XtNleftBitmap, None);
6933 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
6937 void InfoProc(w, event, prms, nprms)
6944 snprintf(buf, sizeof(buf), "xterm -e info --directory %s --directory . -f %s &",
6949 void ManProc(w, event, prms, nprms)
6957 if (nprms && *nprms > 0)
6961 snprintf(buf, sizeof(buf), "xterm -e man %s &", name);
6965 void HintProc(w, event, prms, nprms)
6974 void BookProc(w, event, prms, nprms)
6983 void DebugProc(w, event, prms, nprms)
6989 appData.debugMode = !appData.debugMode;
6992 void AboutGameProc(w, event, prms, nprms)
7001 void NothingProc(w, event, prms, nprms)
7010 void Iconify(w, event, prms, nprms)
7019 XtSetArg(args[0], XtNiconic, True);
7020 XtSetValues(shellWidget, args, 1);
7023 void DisplayMessage(message, extMessage)
7024 gchar *message, *extMessage;
7031 snprintf(buf, sizeof(buf), "%s %s", message, extMessage);
7034 message = extMessage;
7038 printf("TODO: message %s\n",message);
7039 gtk_label_set_text( GTK_LABEL(gtk_builder_get_object (builder, "Messages")),message);
7042 void DisplayTitle(text)
7047 char title[MSG_SIZ];
7050 if (text == NULL) text = "";
7052 if (appData.titleInWindow) {
7054 XtSetArg(args[i], XtNlabel, text); i++;
7055 XtSetValues(titleWidget, args, i);
7058 if (*text != NULLCHAR) {
7060 strcpy(title, text);
7061 } else if (appData.icsActive) {
7062 snprintf(icon, sizeof(icon), "%s", appData.icsHost);
7063 snprintf(title, sizeof(title), "%s: %s", programName, appData.icsHost);
7064 } else if (appData.cmailGameName[0] != NULLCHAR) {
7065 snprintf(icon, sizeof(icon), "%s", "CMail");
7066 snprintf(title,sizeof(title), "%s: %s", programName, "CMail");
7068 // [HGM] license: This stuff should really be done in back-end, but WinBoard already had a pop-up for it
7069 } else if (gameInfo.variant == VariantGothic) {
7070 strcpy(icon, programName);
7071 strcpy(title, GOTHIC);
7074 } else if (gameInfo.variant == VariantFalcon) {
7075 strcpy(icon, programName);
7076 strcpy(title, FALCON);
7078 } else if (appData.noChessProgram) {
7079 strcpy(icon, programName);
7080 strcpy(title, programName);
7082 strcpy(icon, first.tidy);
7083 snprintf(title,sizeof(title), "%s: %s", programName, first.tidy);
7086 XtSetArg(args[i], XtNiconName, (XtArgVal) icon); i++;
7087 XtSetArg(args[i], XtNtitle, (XtArgVal) title); i++;
7088 XtSetValues(shellWidget, args, i);
7092 void DisplayError(message, error)
7099 if (appData.debugMode || appData.matchMode) {
7100 fprintf(stderr, "%s: %s\n", programName, message);
7103 if (appData.debugMode || appData.matchMode) {
7104 fprintf(stderr, "%s: %s: %s\n",
7105 programName, message, strerror(error));
7107 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
7110 ErrorPopUp(_("Error"), message, FALSE);
7114 void DisplayMoveError(message)
7119 DrawPosition(FALSE, NULL);
7120 if (appData.debugMode || appData.matchMode) {
7121 fprintf(stderr, "%s: %s\n", programName, message);
7123 if (appData.popupMoveErrors) {
7124 ErrorPopUp(_("Error"), message, FALSE);
7126 DisplayMessage(message, "");
7131 void DisplayFatalError(message, error, status)
7137 errorExitStatus = status;
7139 fprintf(stderr, "%s: %s\n", programName, message);
7141 fprintf(stderr, "%s: %s: %s\n",
7142 programName, message, strerror(error));
7143 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
7146 if (appData.popupExitMessage && boardWidget && XtIsRealized(boardWidget)) {
7147 ErrorPopUp(status ? _("Fatal Error") : _("Exiting"), message, TRUE);
7153 void DisplayInformation(message)
7157 ErrorPopUp(_("Information"), message, TRUE);
7160 void DisplayNote(message)
7164 ErrorPopUp(_("Note"), message, FALSE);
7168 NullXErrorCheck(dpy, error_event)
7170 XErrorEvent *error_event;
7175 void DisplayIcsInteractionTitle(message)
7178 if (oldICSInteractionTitle == NULL) {
7179 /* Magic to find the old window title, adapted from vim */
7180 char *wina = getenv("WINDOWID");
7182 Window win = (Window) atoi(wina);
7183 Window root, parent, *children;
7184 unsigned int nchildren;
7185 int (*oldHandler)() = XSetErrorHandler(NullXErrorCheck);
7187 if (XFetchName(xDisplay, win, &oldICSInteractionTitle)) break;
7188 if (!XQueryTree(xDisplay, win, &root, &parent,
7189 &children, &nchildren)) break;
7190 if (children) XFree((void *)children);
7191 if (parent == root || parent == 0) break;
7194 XSetErrorHandler(oldHandler);
7196 if (oldICSInteractionTitle == NULL) {
7197 oldICSInteractionTitle = "xterm";
7200 printf("\033]0;%s\007", message);
7204 char pendingReplyPrefix[MSG_SIZ];
7205 ProcRef pendingReplyPR;
7207 void AskQuestionProc(w, event, prms, nprms)
7214 fprintf(stderr, _("AskQuestionProc needed 4 parameters, got %d\n"),
7218 AskQuestionEvent(prms[0], prms[1], prms[2], prms[3]);
7221 void AskQuestionPopDown()
7223 if (!askQuestionUp) return;
7224 XtPopdown(askQuestionShell);
7225 XtDestroyWidget(askQuestionShell);
7226 askQuestionUp = False;
7229 void AskQuestionReplyAction(w, event, prms, nprms)
7239 reply = XawDialogGetValueString(w = XtParent(w));
7240 strcpy(buf, pendingReplyPrefix);
7241 if (*buf) strcat(buf, " ");
7244 OutputToProcess(pendingReplyPR, buf, strlen(buf), &err);
7245 AskQuestionPopDown();
7247 if (err) DisplayFatalError(_("Error writing to chess program"), err, 0);
7250 void AskQuestionCallback(w, client_data, call_data)
7252 XtPointer client_data, call_data;
7257 XtSetArg(args[0], XtNlabel, &name);
7258 XtGetValues(w, args, 1);
7260 if (strcmp(name, _("cancel")) == 0) {
7261 AskQuestionPopDown();
7263 AskQuestionReplyAction(w, NULL, NULL, NULL);
7267 void AskQuestion(title, question, replyPrefix, pr)
7268 char *title, *question, *replyPrefix;
7272 Widget popup, layout, dialog, edit;
7278 strcpy(pendingReplyPrefix, replyPrefix);
7279 pendingReplyPR = pr;
7282 XtSetArg(args[i], XtNresizable, True); i++;
7283 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
7284 askQuestionShell = popup =
7285 XtCreatePopupShell(title, transientShellWidgetClass,
7286 shellWidget, args, i);
7289 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
7290 layoutArgs, XtNumber(layoutArgs));
7293 XtSetArg(args[i], XtNlabel, question); i++;
7294 XtSetArg(args[i], XtNvalue, ""); i++;
7295 XtSetArg(args[i], XtNborderWidth, 0); i++;
7296 dialog = XtCreateManagedWidget("question", dialogWidgetClass,
7299 XawDialogAddButton(dialog, _("enter"), AskQuestionCallback,
7300 (XtPointer) dialog);
7301 XawDialogAddButton(dialog, _("cancel"), AskQuestionCallback,
7302 (XtPointer) dialog);
7304 XtRealizeWidget(popup);
7305 CatchDeleteWindow(popup, "AskQuestionPopDown");
7307 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
7308 &x, &y, &win_x, &win_y, &mask);
7310 XtSetArg(args[0], XtNx, x - 10);
7311 XtSetArg(args[1], XtNy, y - 30);
7312 XtSetValues(popup, args, 2);
7314 XtPopup(popup, XtGrabExclusive);
7315 askQuestionUp = True;
7317 edit = XtNameToWidget(dialog, "*value");
7318 XtSetKeyboardFocus(popup, edit);
7326 if (*name == NULLCHAR) {
7328 } else if (strcmp(name, "$") == 0) {
7329 putc(BELLCHAR, stderr);
7332 snprintf(buf, sizeof(buf), "%s '%s' &", appData.soundProgram, name);
7340 PlaySound(appData.soundMove);
7346 PlaySound(appData.soundIcsWin);
7352 PlaySound(appData.soundIcsLoss);
7358 PlaySound(appData.soundIcsDraw);
7362 PlayIcsUnfinishedSound()
7364 PlaySound(appData.soundIcsUnfinished);
7370 PlaySound(appData.soundIcsAlarm);
7376 system("stty echo");
7382 system("stty -echo");
7386 Colorize(cc, continuation)
7391 int count, outCount, error;
7393 if (textColors[(int)cc].bg > 0) {
7394 if (textColors[(int)cc].fg > 0) {
7395 sprintf(buf, "\033[0;%d;%d;%dm", textColors[(int)cc].attr,
7396 textColors[(int)cc].fg, textColors[(int)cc].bg);
7398 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
7399 textColors[(int)cc].bg);
7402 if (textColors[(int)cc].fg > 0) {
7403 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
7404 textColors[(int)cc].fg);
7406 sprintf(buf, "\033[0;%dm", textColors[(int)cc].attr);
7409 count = strlen(buf);
7410 outCount = OutputToProcess(NoProc, buf, count, &error);
7411 if (outCount < count) {
7412 DisplayFatalError(_("Error writing to display"), error, 1);
7415 if (continuation) return;
7418 PlaySound(appData.soundShout);
7421 PlaySound(appData.soundSShout);
7424 PlaySound(appData.soundChannel1);
7427 PlaySound(appData.soundChannel);
7430 PlaySound(appData.soundKibitz);
7433 PlaySound(appData.soundTell);
7435 case ColorChallenge:
7436 PlaySound(appData.soundChallenge);
7439 PlaySound(appData.soundRequest);
7442 PlaySound(appData.soundSeek);
7453 return getpwuid(getuid())->pw_name;
7456 static char *ExpandPathName(path)
7459 static char static_buf[2000];
7460 char *d, *s, buf[2000];
7466 while (*s && isspace(*s))
7475 if (*(s+1) == '/') {
7476 strcpy(d, getpwuid(getuid())->pw_dir);
7481 *strchr(buf, '/') = 0;
7482 pwd = getpwnam(buf);
7485 fprintf(stderr, _("ERROR: Unknown user %s (in path %s)\n"),
7489 strcpy(d, pwd->pw_dir);
7490 strcat(d, strchr(s+1, '/'));
7501 static char host_name[MSG_SIZ];
7503 #if HAVE_GETHOSTNAME
7504 gethostname(host_name, MSG_SIZ);
7506 #else /* not HAVE_GETHOSTNAME */
7507 # if HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H
7508 sysinfo(SI_HOSTNAME, host_name, MSG_SIZ);
7510 # else /* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
7512 # endif/* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
7513 #endif /* not HAVE_GETHOSTNAME */
7516 XtIntervalId delayedEventTimerXID = 0;
7517 DelayedEventCallback delayedEventCallback = 0;
7522 delayedEventTimerXID = 0;
7523 delayedEventCallback();
7527 ScheduleDelayedEvent(cb, millisec)
7528 DelayedEventCallback cb; long millisec;
7530 delayedEventCallback = cb;
7531 delayedEventTimerXID =
7532 XtAppAddTimeOut(appContext, millisec,
7533 (XtTimerCallbackProc) FireDelayedEvent, (XtPointer) 0);
7536 DelayedEventCallback
7539 if (delayedEventTimerXID) {
7540 return delayedEventCallback;
7547 CancelDelayedEvent()
7549 if (delayedEventTimerXID) {
7550 XtRemoveTimeOut(delayedEventTimerXID);
7551 delayedEventTimerXID = 0;
7555 XtIntervalId loadGameTimerXID = 0;
7557 int LoadGameTimerRunning()
7559 return loadGameTimerXID != 0;
7562 int StopLoadGameTimer()
7564 if (loadGameTimerXID != 0) {
7565 XtRemoveTimeOut(loadGameTimerXID);
7566 loadGameTimerXID = 0;
7574 LoadGameTimerCallback(arg, id)
7578 loadGameTimerXID = 0;
7583 StartLoadGameTimer(millisec)
7587 XtAppAddTimeOut(appContext, millisec,
7588 (XtTimerCallbackProc) LoadGameTimerCallback,
7592 XtIntervalId analysisClockXID = 0;
7595 AnalysisClockCallback(arg, id)
7599 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile
7600 || appData.icsEngineAnalyze) { // [DM]
7601 AnalysisPeriodicEvent(0);
7602 StartAnalysisClock();
7607 StartAnalysisClock()
7610 XtAppAddTimeOut(appContext, 2000,
7611 (XtTimerCallbackProc) AnalysisClockCallback,
7615 gint clockTimerTag = 0;
7617 int ClockTimerRunning()
7619 return clockTimerTag != 0;
7622 int StopClockTimer()
7624 if (clockTimerTag != 0) {
7625 gtk_timeout_remove(clockTimerTag);
7634 ClockTimerCallback(data)
7643 StartClockTimer(millisec)
7646 clockTimerTag = gtk_timeout_add(millisec,(GtkFunction) ClockTimerCallback,NULL);
7651 DisplayTimerLabel(w, color, timer, highlight)
7660 if (appData.clockMode) {
7661 sprintf(buf, "%s: %s", color, TimeString(timer));
7663 sprintf(buf, "%s ", color);
7665 gtk_label_set_text(GTK_LABEL(w),buf);
7667 /* check for low time warning */
7668 // Pixel foregroundOrWarningColor = timerForegroundPixel;
7671 // appData.lowTimeWarning &&
7672 // (timer / 1000) < appData.icsAlarmTime)
7673 // foregroundOrWarningColor = lowTimeWarningColor;
7675 // if (appData.clockMode) {
7676 // sprintf(buf, "%s: %s", color, TimeString(timer));
7677 // XtSetArg(args[0], XtNlabel, buf);
7679 // sprintf(buf, "%s ", color);
7680 // XtSetArg(args[0], XtNlabel, buf);
7685 // XtSetArg(args[1], XtNbackground, foregroundOrWarningColor);
7686 // XtSetArg(args[2], XtNforeground, timerBackgroundPixel);
7688 // XtSetArg(args[1], XtNbackground, timerBackgroundPixel);
7689 // XtSetArg(args[2], XtNforeground, foregroundOrWarningColor);
7692 // XtSetValues(w, args, 3);
7697 DisplayWhiteClock(timeRemaining, highlight)
7701 if(appData.noGUI) return;
7703 DisplayTimerLabel(GUI_Whiteclock, _("White"), timeRemaining, highlight);
7704 if (highlight && WindowIcon == BlackIcon) {
7705 WindowIcon = WhiteIcon;
7706 gtk_window_set_icon(GTK_WINDOW(GUI_Window),WindowIcon);
7711 DisplayBlackClock(timeRemaining, highlight)
7715 if(appData.noGUI) return;
7716 DisplayTimerLabel(GUI_Blackclock, _("Black"), timeRemaining, highlight);
7717 if (highlight && WindowIcon == WhiteIcon) {
7718 WindowIcon = BlackIcon;
7719 gtk_window_set_icon(GTK_WINDOW(GUI_Window),WindowIcon);
7737 int StartChildProcess(cmdLine, dir, pr)
7744 int to_prog[2], from_prog[2];
7748 if (appData.debugMode) {
7749 fprintf(stderr, "StartChildProcess (dir=\"%s\") %s\n",dir, cmdLine);
7752 /* We do NOT feed the cmdLine to the shell; we just
7753 parse it into blank-separated arguments in the
7754 most simple-minded way possible.
7757 strcpy(buf, cmdLine);
7762 if (p == NULL) break;
7767 SetUpChildIO(to_prog, from_prog);
7769 if ((pid = fork()) == 0) {
7771 // [HGM] PSWBTM: made order resistant against case where fd of created pipe was 0 or 1
7772 close(to_prog[1]); // first close the unused pipe ends
7773 close(from_prog[0]);
7774 dup2(to_prog[0], 0); // to_prog was created first, nd is the only one to use 0 or 1
7775 dup2(from_prog[1], 1);
7776 if(to_prog[0] >= 2) close(to_prog[0]); // if 0 or 1, the dup2 already cosed the original
7777 close(from_prog[1]); // and closing again loses one of the pipes!
7778 if(fileno(stderr) >= 2) // better safe than sorry...
7779 dup2(1, fileno(stderr)); /* force stderr to the pipe */
7781 if (dir[0] != NULLCHAR && chdir(dir) != 0) {
7786 nice(appData.niceEngines); // [HGM] nice: adjust priority of engine proc
7788 execvp(argv[0], argv);
7790 /* If we get here, exec failed */
7795 /* Parent process */
7797 close(from_prog[1]);
7799 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7802 cp->fdFrom = from_prog[0];
7803 cp->fdTo = to_prog[1];
7808 // [HGM] kill: implement the 'hard killing' of AS's Winboard_x
7809 static RETSIGTYPE AlarmCallBack(int n)
7815 DestroyChildProcess(pr, signalType)
7819 ChildProc *cp = (ChildProc *) pr;
7821 if (cp->kind != CPReal) return;
7823 if (signalType == 10) { // [HGM] kill: if it does not terminate in 3 sec, kill
7824 signal(SIGALRM, AlarmCallBack);
7826 if(wait((int *) 0) == -1) { // process does not terminate on its own accord
7827 kill(cp->pid, SIGKILL); // kill it forcefully
7828 wait((int *) 0); // and wait again
7832 kill(cp->pid, signalType == 9 ? SIGKILL : SIGTERM); // [HGM] kill: use hard kill if so requested
7834 /* Process is exiting either because of the kill or because of
7835 a quit command sent by the backend; either way, wait for it to die.
7844 InterruptChildProcess(pr)
7847 ChildProc *cp = (ChildProc *) pr;
7849 if (cp->kind != CPReal) return;
7850 (void) kill(cp->pid, SIGINT); /* stop it thinking */
7853 int OpenTelnet(host, port, pr)
7858 char cmdLine[MSG_SIZ];
7860 if (port[0] == NULLCHAR) {
7861 snprintf(cmdLine, sizeof(cmdLine), "%s %s", appData.telnetProgram, host);
7863 snprintf(cmdLine, sizeof(cmdLine), "%s %s %s", appData.telnetProgram, host, port);
7865 return StartChildProcess(cmdLine, "", pr);
7868 int OpenTCP(host, port, pr)
7874 DisplayFatalError(_("Socket support is not configured in"), 0, 2);
7875 #else /* !OMIT_SOCKETS */
7877 struct sockaddr_in sa;
7879 unsigned short uport;
7882 if ((s = socket(AF_INET, SOCK_STREAM, 6)) < 0) {
7886 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
7887 sa.sin_family = AF_INET;
7888 sa.sin_addr.s_addr = INADDR_ANY;
7889 uport = (unsigned short) 0;
7890 sa.sin_port = htons(uport);
7891 if (bind(s, (struct sockaddr *) &sa, sizeof(struct sockaddr_in)) < 0) {
7895 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
7896 if (!(hp = gethostbyname(host))) {
7898 if (sscanf(host, "%d.%d.%d.%d", &b0, &b1, &b2, &b3) == 4) {
7899 hp = (struct hostent *) calloc(1, sizeof(struct hostent));
7900 hp->h_addrtype = AF_INET;
7902 hp->h_addr_list = (char **) calloc(2, sizeof(char *));
7903 hp->h_addr_list[0] = (char *) malloc(4);
7904 hp->h_addr_list[0][0] = b0;
7905 hp->h_addr_list[0][1] = b1;
7906 hp->h_addr_list[0][2] = b2;
7907 hp->h_addr_list[0][3] = b3;
7912 sa.sin_family = hp->h_addrtype;
7913 uport = (unsigned short) atoi(port);
7914 sa.sin_port = htons(uport);
7915 memcpy((char *) &sa.sin_addr, hp->h_addr, hp->h_length);
7917 if (connect(s, (struct sockaddr *) &sa,
7918 sizeof(struct sockaddr_in)) < 0) {
7922 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7929 #endif /* !OMIT_SOCKETS */
7934 int OpenCommPort(name, pr)
7941 fd = open(name, 2, 0);
7942 if (fd < 0) return errno;
7944 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7954 int OpenLoopback(pr)
7960 SetUpChildIO(to, from);
7962 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7965 cp->fdFrom = to[0]; /* note not from[0]; we are doing a loopback */
7972 int OpenRcmd(host, user, cmd, pr)
7973 char *host, *user, *cmd;
7976 DisplayFatalError(_("internal rcmd not implemented for Unix"), 0, 1);
7980 #define INPUT_SOURCE_BUF_SIZE 8192
7989 char buf[INPUT_SOURCE_BUF_SIZE];
7994 DoInputCallback(closure, source, xid)
7999 InputSource *is = (InputSource *) closure;
8004 if (is->lineByLine) {
8005 count = read(is->fd, is->unused,
8006 INPUT_SOURCE_BUF_SIZE - (is->unused - is->buf));
8008 (is->func)(is, is->closure, is->buf, count, count ? errno : 0);
8011 is->unused += count;
8013 while (p < is->unused) {
8014 q = memchr(p, '\n', is->unused - p);
8015 if (q == NULL) break;
8017 (is->func)(is, is->closure, p, q - p, 0);
8021 while (p < is->unused) {
8026 count = read(is->fd, is->buf, INPUT_SOURCE_BUF_SIZE);
8031 (is->func)(is, is->closure, is->buf, count, error);
8035 InputSourceRef AddInputSource(pr, lineByLine, func, closure)
8042 ChildProc *cp = (ChildProc *) pr;
8044 is = (InputSource *) calloc(1, sizeof(InputSource));
8045 is->lineByLine = lineByLine;
8049 is->fd = fileno(stdin);
8051 is->kind = cp->kind;
8052 is->fd = cp->fdFrom;
8055 is->unused = is->buf;
8058 is->xid = XtAppAddInput(appContext, is->fd,
8059 (XtPointer) (XtInputReadMask),
8060 (XtInputCallbackProc) DoInputCallback,
8062 is->closure = closure;
8063 return (InputSourceRef) is;
8067 RemoveInputSource(isr)
8070 InputSource *is = (InputSource *) isr;
8072 if (is->xid == 0) return;
8073 XtRemoveInput(is->xid);
8077 int OutputToProcess(pr, message, count, outError)
8083 ChildProc *cp = (ChildProc *) pr;
8087 outCount = fwrite(message, 1, count, stdout);
8089 outCount = write(cp->fdTo, message, count);
8099 /* Output message to process, with "ms" milliseconds of delay
8100 between each character. This is needed when sending the logon
8101 script to ICC, which for some reason doesn't like the
8102 instantaneous send. */
8103 int OutputToProcessDelayed(pr, message, count, outError, msdelay)
8110 ChildProc *cp = (ChildProc *) pr;
8115 r = write(cp->fdTo, message++, 1);
8128 /**** Animation code by Hugh Fisher, DCS, ANU.
8130 Known problem: if a window overlapping the board is
8131 moved away while a piece is being animated underneath,
8132 the newly exposed area won't be updated properly.
8133 I can live with this.
8135 Known problem: if you look carefully at the animation
8136 of pieces in mono mode, they are being drawn as solid
8137 shapes without interior detail while moving. Fixing
8138 this would be a major complication for minimal return.
8141 /* Masks for XPM pieces. Black and white pieces can have
8142 different shapes, but in the interest of retaining my
8143 sanity pieces must have the same outline on both light
8144 and dark squares, and all pieces must use the same
8145 background square colors/images. */
8147 static int xpmDone = 0;
8150 CreateAnimMasks (pieceDepth)
8157 unsigned long plane;
8160 /* Need a bitmap just to get a GC with right depth */
8161 buf = XCreatePixmap(xDisplay, xBoardWindow,
8163 values.foreground = 1;
8164 values.background = 0;
8165 /* Don't use XtGetGC, not read only */
8166 maskGC = XCreateGC(xDisplay, buf,
8167 GCForeground | GCBackground, &values);
8168 XFreePixmap(xDisplay, buf);
8170 buf = XCreatePixmap(xDisplay, xBoardWindow,
8171 squareSize, squareSize, pieceDepth);
8172 values.foreground = XBlackPixel(xDisplay, xScreen);
8173 values.background = XWhitePixel(xDisplay, xScreen);
8174 bufGC = XCreateGC(xDisplay, buf,
8175 GCForeground | GCBackground, &values);
8177 for (piece = WhitePawn; piece <= BlackKing; piece++) {
8178 /* Begin with empty mask */
8179 if(!xpmDone) // [HGM] pieces: keep using existing
8180 xpmMask[piece] = XCreatePixmap(xDisplay, xBoardWindow,
8181 squareSize, squareSize, 1);
8182 XSetFunction(xDisplay, maskGC, GXclear);
8183 XFillRectangle(xDisplay, xpmMask[piece], maskGC,
8184 0, 0, squareSize, squareSize);
8186 /* Take a copy of the piece */
8191 XSetFunction(xDisplay, bufGC, GXcopy);
8192 XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % (int)BlackPawn],
8194 0, 0, squareSize, squareSize, 0, 0);
8196 /* XOR the background (light) over the piece */
8197 XSetFunction(xDisplay, bufGC, GXxor);
8199 XCopyArea(xDisplay, xpmLightSquare, buf, bufGC,
8200 0, 0, squareSize, squareSize, 0, 0);
8202 XSetForeground(xDisplay, bufGC, lightSquareColor);
8203 XFillRectangle(xDisplay, buf, bufGC, 0, 0, squareSize, squareSize);
8206 /* We now have an inverted piece image with the background
8207 erased. Construct mask by just selecting all the non-zero
8208 pixels - no need to reconstruct the original image. */
8209 XSetFunction(xDisplay, maskGC, GXor);
8211 /* Might be quicker to download an XImage and create bitmap
8212 data from it rather than this N copies per piece, but it
8213 only takes a fraction of a second and there is a much
8214 longer delay for loading the pieces. */
8215 for (n = 0; n < pieceDepth; n ++) {
8216 XCopyPlane(xDisplay, buf, xpmMask[piece], maskGC,
8217 0, 0, squareSize, squareSize,
8223 XFreePixmap(xDisplay, buf);
8224 XFreeGC(xDisplay, bufGC);
8225 XFreeGC(xDisplay, maskGC);
8229 InitAnimState (anim, info)
8231 XWindowAttributes * info;
8236 /* Each buffer is square size, same depth as window */
8237 anim->saveBuf = XCreatePixmap(xDisplay, xBoardWindow,
8238 squareSize, squareSize, info->depth);
8239 anim->newBuf = XCreatePixmap(xDisplay, xBoardWindow,
8240 squareSize, squareSize, info->depth);
8242 /* Create a plain GC for blitting */
8243 mask = GCForeground | GCBackground | GCFunction |
8244 GCPlaneMask | GCGraphicsExposures;
8245 values.foreground = XBlackPixel(xDisplay, xScreen);
8246 values.background = XWhitePixel(xDisplay, xScreen);
8247 values.function = GXcopy;
8248 values.plane_mask = AllPlanes;
8249 values.graphics_exposures = False;
8250 anim->blitGC = XCreateGC(xDisplay, xBoardWindow, mask, &values);
8252 /* Piece will be copied from an existing context at
8253 the start of each new animation/drag. */
8254 anim->pieceGC = XCreateGC(xDisplay, xBoardWindow, 0, &values);
8256 /* Outline will be a read-only copy of an existing */
8257 anim->outlineGC = None;
8263 static VariantClass old = (VariantClass) -1; // [HGM] pieces: redo every time variant changes
8264 XWindowAttributes info;
8266 if (xpmDone && gameInfo.variant == old) return;
8267 if(xpmDone) old = gameInfo.variant; // first time pieces might not be created yet
8268 // XGetWindowAttributes(xDisplay, xBoardWindow, &info);
8270 InitAnimState(&game, &info);
8271 InitAnimState(&player, &info);
8273 /* For XPM pieces, we need bitmaps to use as masks. */
8275 CreateAnimMasks(info.depth);
8281 static Boolean frameWaiting;
8283 static RETSIGTYPE FrameAlarm (sig)
8286 frameWaiting = False;
8287 /* In case System-V style signals. Needed?? */
8288 signal(SIGALRM, FrameAlarm);
8295 struct itimerval delay;
8297 XSync(xDisplay, False);
8300 frameWaiting = True;
8301 signal(SIGALRM, FrameAlarm);
8302 delay.it_interval.tv_sec =
8303 delay.it_value.tv_sec = time / 1000;
8304 delay.it_interval.tv_usec =
8305 delay.it_value.tv_usec = (time % 1000) * 1000;
8306 setitimer(ITIMER_REAL, &delay, NULL);
8308 /* Ugh -- busy-wait! --tpm */
8309 while (frameWaiting);
8311 while (frameWaiting) pause();
8313 delay.it_interval.tv_sec = delay.it_value.tv_sec = 0;
8314 delay.it_interval.tv_usec = delay.it_value.tv_usec = 0;
8315 setitimer(ITIMER_REAL, &delay, NULL);
8325 XSync(xDisplay, False);
8327 usleep(time * 1000);
8332 /* Convert board position to corner of screen rect and color */
8335 ScreenSquare(column, row, pt, color)
8336 int column; int row; XPoint * pt; int * color;
8339 pt->x = lineGap + ((BOARD_WIDTH-1)-column) * (squareSize + lineGap);
8340 pt->y = lineGap + row * (squareSize + lineGap);
8342 pt->x = lineGap + column * (squareSize + lineGap);
8343 pt->y = lineGap + ((BOARD_HEIGHT-1)-row) * (squareSize + lineGap);
8345 *color = SquareColor(row, column);
8348 /* Convert window coords to square */
8351 BoardSquare(x, y, column, row)
8352 int x; int y; int * column; int * row;
8354 *column = EventToSquare(x, BOARD_WIDTH);
8355 if (flipView && *column >= 0)
8356 *column = BOARD_WIDTH - 1 - *column;
8357 *row = EventToSquare(y, BOARD_HEIGHT);
8358 if (!flipView && *row >= 0)
8359 *row = BOARD_HEIGHT - 1 - *row;
8364 #undef Max /* just in case */
8366 #define Max(a, b) ((a) > (b) ? (a) : (b))
8367 #define Min(a, b) ((a) < (b) ? (a) : (b))
8370 SetRect(rect, x, y, width, height)
8371 XRectangle * rect; int x; int y; int width; int height;
8375 rect->width = width;
8376 rect->height = height;
8379 /* Test if two frames overlap. If they do, return
8380 intersection rect within old and location of
8381 that rect within new. */
8384 Intersect(old, new, size, area, pt)
8385 XPoint * old; XPoint * new;
8386 int size; XRectangle * area; XPoint * pt;
8388 if (old->x > new->x + size || new->x > old->x + size ||
8389 old->y > new->y + size || new->y > old->y + size) {
8392 SetRect(area, Max(new->x - old->x, 0), Max(new->y - old->y, 0),
8393 size - abs(old->x - new->x), size - abs(old->y - new->y));
8394 pt->x = Max(old->x - new->x, 0);
8395 pt->y = Max(old->y - new->y, 0);
8400 /* For two overlapping frames, return the rect(s)
8401 in the old that do not intersect with the new. */
8404 CalcUpdateRects(old, new, size, update, nUpdates)
8405 XPoint * old; XPoint * new; int size;
8406 XRectangle update[]; int * nUpdates;
8410 /* If old = new (shouldn't happen) then nothing to draw */
8411 if (old->x == new->x && old->y == new->y) {
8415 /* Work out what bits overlap. Since we know the rects
8416 are the same size we don't need a full intersect calc. */
8418 /* Top or bottom edge? */
8419 if (new->y > old->y) {
8420 SetRect(&(update[count]), old->x, old->y, size, new->y - old->y);
8422 } else if (old->y > new->y) {
8423 SetRect(&(update[count]), old->x, old->y + size - (old->y - new->y),
8424 size, old->y - new->y);
8427 /* Left or right edge - don't overlap any update calculated above. */
8428 if (new->x > old->x) {
8429 SetRect(&(update[count]), old->x, Max(new->y, old->y),
8430 new->x - old->x, size - abs(new->y - old->y));
8432 } else if (old->x > new->x) {
8433 SetRect(&(update[count]), new->x + size, Max(new->y, old->y),
8434 old->x - new->x, size - abs(new->y - old->y));
8441 /* Generate a series of frame coords from start->mid->finish.
8442 The movement rate doubles until the half way point is
8443 reached, then halves back down to the final destination,
8444 which gives a nice slow in/out effect. The algorithmn
8445 may seem to generate too many intermediates for short
8446 moves, but remember that the purpose is to attract the
8447 viewers attention to the piece about to be moved and
8448 then to where it ends up. Too few frames would be less
8452 Tween(start, mid, finish, factor, frames, nFrames)
8453 XPoint * start; XPoint * mid;
8454 XPoint * finish; int factor;
8455 XPoint frames[]; int * nFrames;
8457 int fraction, n, count;
8461 /* Slow in, stepping 1/16th, then 1/8th, ... */
8463 for (n = 0; n < factor; n++)
8465 for (n = 0; n < factor; n++) {
8466 frames[count].x = start->x + (mid->x - start->x) / fraction;
8467 frames[count].y = start->y + (mid->y - start->y) / fraction;
8469 fraction = fraction / 2;
8473 frames[count] = *mid;
8476 /* Slow out, stepping 1/2, then 1/4, ... */
8478 for (n = 0; n < factor; n++) {
8479 frames[count].x = finish->x - (finish->x - mid->x) / fraction;
8480 frames[count].y = finish->y - (finish->y - mid->y) / fraction;
8482 fraction = fraction * 2;
8487 /* Draw a piece on the screen without disturbing what's there */
8490 SelectGCMask(piece, clip, outline, mask)
8491 ChessSquare piece; GC * clip; GC * outline; Pixmap * mask;
8495 /* Bitmap for piece being moved. */
8496 if (appData.monoMode) {
8497 *mask = *pieceToSolid(piece);
8498 } else if (useImages) {
8500 *mask = xpmMask[piece];
8502 *mask = ximMaskPm[piece];
8505 *mask = *pieceToSolid(piece);
8508 /* GC for piece being moved. Square color doesn't matter, but
8509 since it gets modified we make a copy of the original. */
8511 if (appData.monoMode)
8516 if (appData.monoMode)
8521 XCopyGC(xDisplay, source, 0xFFFFFFFF, *clip);
8523 /* Outline only used in mono mode and is not modified */
8525 *outline = bwPieceGC;
8527 *outline = wbPieceGC;
8531 OverlayPiece(piece, clip, outline, dest)
8532 ChessSquare piece; GC clip; GC outline; Drawable dest;
8537 /* Draw solid rectangle which will be clipped to shape of piece */
8538 XFillRectangle(xDisplay, dest, clip,
8539 0, 0, squareSize, squareSize);
8540 if (appData.monoMode)
8541 /* Also draw outline in contrasting color for black
8542 on black / white on white cases */
8543 XCopyPlane(xDisplay, *pieceToOutline(piece), dest, outline,
8544 0, 0, squareSize, squareSize, 0, 0, 1);
8546 /* Copy the piece */
8551 XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
8553 0, 0, squareSize, squareSize,
8558 /* Animate the movement of a single piece */
8561 BeginAnimation(anim, piece, startColor, start)
8569 /* The old buffer is initialised with the start square (empty) */
8570 BlankSquare(0, 0, startColor, EmptySquare, anim->saveBuf);
8571 anim->prevFrame = *start;
8573 /* The piece will be drawn using its own bitmap as a matte */
8574 SelectGCMask(piece, &anim->pieceGC, &anim->outlineGC, &mask);
8575 XSetClipMask(xDisplay, anim->pieceGC, mask);
8579 AnimationFrame(anim, frame, piece)
8584 XRectangle updates[4];
8589 /* Save what we are about to draw into the new buffer */
8590 XCopyArea(xDisplay, xBoardWindow, anim->newBuf, anim->blitGC,
8591 frame->x, frame->y, squareSize, squareSize,
8594 /* Erase bits of the previous frame */
8595 if (Intersect(&anim->prevFrame, frame, squareSize, &overlap, &pt)) {
8596 /* Where the new frame overlapped the previous,
8597 the contents in newBuf are wrong. */
8598 XCopyArea(xDisplay, anim->saveBuf, anim->newBuf, anim->blitGC,
8599 overlap.x, overlap.y,
8600 overlap.width, overlap.height,
8602 /* Repaint the areas in the old that don't overlap new */
8603 CalcUpdateRects(&anim->prevFrame, frame, squareSize, updates, &count);
8604 for (i = 0; i < count; i++)
8605 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
8606 updates[i].x - anim->prevFrame.x,
8607 updates[i].y - anim->prevFrame.y,
8608 updates[i].width, updates[i].height,
8609 updates[i].x, updates[i].y);
8611 /* Easy when no overlap */
8612 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
8613 0, 0, squareSize, squareSize,
8614 anim->prevFrame.x, anim->prevFrame.y);
8617 /* Save this frame for next time round */
8618 XCopyArea(xDisplay, anim->newBuf, anim->saveBuf, anim->blitGC,
8619 0, 0, squareSize, squareSize,
8621 anim->prevFrame = *frame;
8623 /* Draw piece over original screen contents, not current,
8624 and copy entire rect. Wipes out overlapping piece images. */
8625 OverlayPiece(piece, anim->pieceGC, anim->outlineGC, anim->newBuf);
8626 XCopyArea(xDisplay, anim->newBuf, xBoardWindow, anim->blitGC,
8627 0, 0, squareSize, squareSize,
8628 frame->x, frame->y);
8632 EndAnimation (anim, finish)
8636 XRectangle updates[4];
8641 /* The main code will redraw the final square, so we
8642 only need to erase the bits that don't overlap. */
8643 if (Intersect(&anim->prevFrame, finish, squareSize, &overlap, &pt)) {
8644 CalcUpdateRects(&anim->prevFrame, finish, squareSize, updates, &count);
8645 for (i = 0; i < count; i++)
8646 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
8647 updates[i].x - anim->prevFrame.x,
8648 updates[i].y - anim->prevFrame.y,
8649 updates[i].width, updates[i].height,
8650 updates[i].x, updates[i].y);
8652 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
8653 0, 0, squareSize, squareSize,
8654 anim->prevFrame.x, anim->prevFrame.y);
8659 FrameSequence(anim, piece, startColor, start, finish, frames, nFrames)
8661 ChessSquare piece; int startColor;
8662 XPoint * start; XPoint * finish;
8663 XPoint frames[]; int nFrames;
8667 BeginAnimation(anim, piece, startColor, start);
8668 for (n = 0; n < nFrames; n++) {
8669 AnimationFrame(anim, &(frames[n]), piece);
8670 FrameDelay(appData.animSpeed);
8672 EndAnimation(anim, finish);
8675 /* Main control logic for deciding what to animate and how */
8678 AnimateMove(board, fromX, fromY, toX, toY)
8687 XPoint start, finish, mid;
8688 XPoint frames[kFactor * 2 + 1];
8689 int nFrames, startColor, endColor;
8691 /* Are we animating? */
8692 if (!appData.animate || appData.blindfold)
8695 if(board[toY][toX] == WhiteRook && board[fromY][fromX] == WhiteKing ||
8696 board[toY][toX] == BlackRook && board[fromY][fromX] == BlackKing)
8697 return; // [HGM] FRC: no animtion of FRC castlings, as to-square is not true to-square
8699 if (fromY < 0 || fromX < 0 || toX < 0 || toY < 0) return;
8700 piece = board[fromY][fromX];
8701 if (piece >= EmptySquare) return;
8706 hop = (piece == WhiteKnight || piece == BlackKnight);
8709 if (appData.debugMode) {
8710 fprintf(debugFP, hop ? _("AnimateMove: piece %d hops from %d,%d to %d,%d \n") :
8711 _("AnimateMove: piece %d slides from %d,%d to %d,%d \n"),
8712 piece, fromX, fromY, toX, toY); }
8714 ScreenSquare(fromX, fromY, &start, &startColor);
8715 ScreenSquare(toX, toY, &finish, &endColor);
8718 /* Knight: make diagonal movement then straight */
8719 if (abs(toY - fromY) < abs(toX - fromX)) {
8720 mid.x = start.x + (finish.x - start.x) / 2;
8724 mid.y = start.y + (finish.y - start.y) / 2;
8727 mid.x = start.x + (finish.x - start.x) / 2;
8728 mid.y = start.y + (finish.y - start.y) / 2;
8731 /* Don't use as many frames for very short moves */
8732 if (abs(toY - fromY) + abs(toX - fromX) <= 2)
8733 Tween(&start, &mid, &finish, kFactor - 1, frames, &nFrames);
8735 Tween(&start, &mid, &finish, kFactor, frames, &nFrames);
8736 FrameSequence(&game, piece, startColor, &start, &finish, frames, nFrames);
8738 /* Be sure end square is redrawn */
8739 damage[toY][toX] = True;
8743 DragPieceBegin(x, y)
8746 int boardX, boardY, color;
8749 /* Are we animating? */
8750 if (!appData.animateDragging || appData.blindfold)
8753 /* Figure out which square we start in and the
8754 mouse position relative to top left corner. */
8755 BoardSquare(x, y, &boardX, &boardY);
8756 player.startBoardX = boardX;
8757 player.startBoardY = boardY;
8758 ScreenSquare(boardX, boardY, &corner, &color);
8759 player.startSquare = corner;
8760 player.startColor = color;
8762 /* Start from exactly where the piece is. This can be confusing
8763 if you start dragging far from the center of the square; most
8764 or all of the piece can be over a different square from the one
8765 the mouse pointer is in. */
8766 player.mouseDelta.x = x - corner.x;
8767 player.mouseDelta.y = y - corner.y;
8769 /* As soon as we start dragging, the piece will jump slightly to
8770 be centered over the mouse pointer. */
8771 player.mouseDelta.x = squareSize/2;
8772 player.mouseDelta.y = squareSize/2;
8774 /* Initialise animation */
8775 player.dragPiece = PieceForSquare(boardX, boardY);
8777 if (player.dragPiece >= 0 && player.dragPiece < EmptySquare) {
8778 player.dragActive = True;
8779 BeginAnimation(&player, player.dragPiece, color, &corner);
8780 /* Mark this square as needing to be redrawn. Note that
8781 we don't remove the piece though, since logically (ie
8782 as seen by opponent) the move hasn't been made yet. */
8783 if(boardX == BOARD_RGHT+1 && PieceForSquare(boardX-1, boardY) > 1 ||
8784 boardX == BOARD_LEFT-2 && PieceForSquare(boardX+1, boardY) > 1)
8785 XCopyArea(xDisplay, xBoardWindow, player.saveBuf, player.blitGC,
8786 corner.x, corner.y, squareSize, squareSize,
8787 0, 0); // [HGM] zh: unstack in stead of grab
8788 damage[boardY][boardX] = True;
8790 player.dragActive = False;
8800 /* Are we animating? */
8801 if (!appData.animateDragging || appData.blindfold)
8805 if (! player.dragActive)
8807 /* Move piece, maintaining same relative position
8808 of mouse within square */
8809 corner.x = x - player.mouseDelta.x;
8810 corner.y = y - player.mouseDelta.y;
8811 AnimationFrame(&player, &corner, player.dragPiece);
8813 if (appData.highlightDragging) {
8815 BoardSquare(x, y, &boardX, &boardY);
8816 SetHighlights(fromX, fromY, boardX, boardY);
8825 int boardX, boardY, color;
8828 /* Are we animating? */
8829 if (!appData.animateDragging || appData.blindfold)
8833 if (! player.dragActive)
8835 /* Last frame in sequence is square piece is
8836 placed on, which may not match mouse exactly. */
8837 BoardSquare(x, y, &boardX, &boardY);
8838 ScreenSquare(boardX, boardY, &corner, &color);
8839 EndAnimation(&player, &corner);
8841 /* Be sure end square is redrawn */
8842 damage[boardY][boardX] = True;
8844 /* This prevents weird things happening with fast successive
8845 clicks which on my Sun at least can cause motion events
8846 without corresponding press/release. */
8847 player.dragActive = False;
8850 /* Handle expose event while piece being dragged */
8855 if (!player.dragActive || appData.blindfold)
8858 /* What we're doing: logically, the move hasn't been made yet,
8859 so the piece is still in it's original square. But visually
8860 it's being dragged around the board. So we erase the square
8861 that the piece is on and draw it at the last known drag point. */
8862 BlankSquare(player.startSquare.x, player.startSquare.y,
8863 player.startColor, EmptySquare, xBoardWindow);
8864 AnimationFrame(&player, &player.prevFrame, player.dragPiece);
8865 damage[player.startBoardY][player.startBoardX] = TRUE;
8869 SetProgramStats( FrontEndProgramStats * stats )
8872 // [HGM] done, but perhaps backend should call this directly?
8873 EngineOutputUpdate( stats );