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"
185 #include "bitmaps/icon_white.bm"
186 #include "bitmaps/icon_black.bm"
187 #include "bitmaps/checkmark.bm"
189 #include "frontend.h"
194 #include "xgamelist.h"
195 #include "xhistory.h"
196 #include "xedittags.h"
199 // must be moved to xengineoutput.h
201 void EngineOutputProc P((Widget w, XEvent *event,
202 String *prms, Cardinal *nprms));
204 void EngineOutputPopDown();
211 #define usleep(t) _sleep2(((t)+500)/1000)
215 # define _(s) gettext (s)
216 # define N_(s) gettext_noop (s)
232 int main P((int argc, char **argv));
233 RETSIGTYPE CmailSigHandler P((int sig));
234 RETSIGTYPE IntSigHandler P((int sig));
235 void CreateGCs P((void));
236 void CreateXIMPieces P((void));
237 void CreateXPMPieces P((void));
238 void CreatePieces P((void));
239 void CreatePieceMenus P((void));
240 Widget CreateMenuBar P((Menu *mb));
241 Widget CreateButtonBar P ((MenuItem *mi));
242 char *FindFont P((char *pattern, int targetPxlSize));
243 void PieceMenuPopup P((Widget w, XEvent *event,
244 String *params, Cardinal *num_params));
245 static void PieceMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
246 static void DropMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
247 void ReadBitmap P((Pixmap *pm, String name, unsigned char bits[],
248 u_int wreq, u_int hreq));
249 void CreateGrid P((void));
250 int EventToSquare P((int x, int limit));
251 void DrawSquare P((int row, int column, ChessSquare piece, int do_flash));
252 void EventProc P((Widget widget, caddr_t unused, XEvent *event));
253 void HandleUserMove P((Widget w, XEvent *event,
254 String *prms, Cardinal *nprms));
255 void AnimateUserMove P((Widget w, XEvent * event,
256 String * params, Cardinal * nParams));
257 void WhiteClock P((Widget w, XEvent *event,
258 String *prms, Cardinal *nprms));
259 void BlackClock P((Widget w, XEvent *event,
260 String *prms, Cardinal *nprms));
261 void DrawPositionProc P((Widget w, XEvent *event,
262 String *prms, Cardinal *nprms));
263 void XDrawPosition P((Widget w, /*Boolean*/int repaint,
265 void CommentPopUp P((char *title, char *label));
266 void CommentPopDown P((void));
267 void CommentCallback P((Widget w, XtPointer client_data,
268 XtPointer call_data));
269 void ICSInputBoxPopUp P((void));
270 void ICSInputBoxPopDown P((void));
271 void FileNamePopUp P((char *label, char *def,
272 FileProc proc, char *openMode));
273 void FileNamePopDown P((void));
274 void FileNameCallback P((Widget w, XtPointer client_data,
275 XtPointer call_data));
276 void FileNameAction P((Widget w, XEvent *event,
277 String *prms, Cardinal *nprms));
278 void AskQuestionReplyAction P((Widget w, XEvent *event,
279 String *prms, Cardinal *nprms));
280 void AskQuestionProc P((Widget w, XEvent *event,
281 String *prms, Cardinal *nprms));
282 void AskQuestionPopDown P((void));
283 void PromotionPopUp P((void));
284 void PromotionPopDown P((void));
285 void PromotionCallback P((Widget w, XtPointer client_data,
286 XtPointer call_data));
287 void EditCommentPopDown P((void));
288 void EditCommentCallback P((Widget w, XtPointer client_data,
289 XtPointer call_data));
290 void SelectCommand P((Widget w, XtPointer client_data, XtPointer call_data));
291 void ResetProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
292 void LoadGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
293 void LoadNextGameProc P((Widget w, XEvent *event, String *prms,
295 void LoadPrevGameProc P((Widget w, XEvent *event, String *prms,
297 void ReloadGameProc P((Widget w, XEvent *event, String *prms,
299 void LoadPositionProc P((Widget w, XEvent *event,
300 String *prms, Cardinal *nprms));
301 void LoadNextPositionProc P((Widget w, XEvent *event, String *prms,
303 void LoadPrevPositionProc P((Widget w, XEvent *event, String *prms,
305 void ReloadPositionProc P((Widget w, XEvent *event, String *prms,
307 void CopyPositionProc P((Widget w, XEvent *event, String *prms,
309 void PastePositionProc P((Widget w, XEvent *event, String *prms,
311 void CopyGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
312 void PasteGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
313 void SaveGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
314 void SavePositionProc P((Widget w, XEvent *event,
315 String *prms, Cardinal *nprms));
316 void MailMoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
317 void ReloadCmailMsgProc P((Widget w, XEvent *event, String *prms,
319 void QuitProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
320 void PauseProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
321 void MachineBlackProc P((Widget w, XEvent *event, String *prms,
323 void MachineWhiteProc P((Widget w, XEvent *event,
324 String *prms, Cardinal *nprms));
325 void AnalyzeModeProc P((Widget w, XEvent *event,
326 String *prms, Cardinal *nprms));
327 void AnalyzeFileProc P((Widget w, XEvent *event,
328 String *prms, Cardinal *nprms));
329 void TwoMachinesProc P((Widget w, XEvent *event, String *prms,
331 void IcsClientProc P((Widget w, XEvent *event, String *prms,
333 void EditGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
334 void EditPositionProc P((Widget w, XEvent *event,
335 String *prms, Cardinal *nprms));
336 void TrainingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
337 void EditCommentProc P((Widget w, XEvent *event,
338 String *prms, Cardinal *nprms));
339 void IcsInputBoxProc P((Widget w, XEvent *event,
340 String *prms, Cardinal *nprms));
341 void AcceptProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
342 void DeclineProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
343 void RematchProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
344 void CallFlagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
345 void DrawProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
346 void AbortProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
347 void AdjournProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
348 void ResignProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
349 void AdjuWhiteProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
350 void AdjuBlackProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
351 void AdjuDrawProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
352 void EnterKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
353 void StopObservingProc P((Widget w, XEvent *event, String *prms,
355 void StopExaminingProc P((Widget w, XEvent *event, String *prms,
357 void BackwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
358 void ForwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
359 void ToStartProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
360 void ToEndProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
361 void RevertProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
362 void TruncateGameProc P((Widget w, XEvent *event, String *prms,
364 void RetractMoveProc P((Widget w, XEvent *event, String *prms,
366 void MoveNowProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
367 void AlwaysQueenProc P((Widget w, XEvent *event, String *prms,
369 void AnimateDraggingProc P((Widget w, XEvent *event, String *prms,
371 void AnimateMovingProc P((Widget w, XEvent *event, String *prms,
373 void AutocommProc P((Widget w, XEvent *event, String *prms,
375 void AutoflagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
376 void AutoflipProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
377 void AutobsProc P((Widget w, XEvent *event, String *prms,
379 void AutoraiseProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
380 void AutosaveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
381 void BlindfoldProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
382 void FlashMovesProc P((Widget w, XEvent *event, String *prms,
384 void FlipViewProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
385 void GetMoveListProc P((Widget w, XEvent *event, String *prms,
387 void HighlightDraggingProc P((Widget w, XEvent *event, String *prms,
389 void HighlightLastMoveProc P((Widget w, XEvent *event, String *prms,
391 void MoveSoundProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
392 void IcsAlarmProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
393 void OldSaveStyleProc P((Widget w, XEvent *event, String *prms,
395 void PeriodicUpdatesProc P((Widget w, XEvent *event, String *prms,
397 void PonderNextMoveProc P((Widget w, XEvent *event, String *prms,
399 void PopupMoveErrorsProc P((Widget w, XEvent *event, String *prms,
401 void PopupExitMessageProc P((Widget w, XEvent *event, String *prms,
403 void PremoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
404 void QuietPlayProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
405 void ShowCoordsProc P((Widget w, XEvent *event, String *prms,
407 void ShowThinkingProc P((Widget w, XEvent *event, String *prms,
409 void HideThinkingProc P((Widget w, XEvent *event, String *prms,
411 void TestLegalityProc P((Widget w, XEvent *event, String *prms,
413 void InfoProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
414 void ManProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
415 void HintProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
416 void BookProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
417 void AboutGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
418 void AboutProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
419 void DebugProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
420 void NothingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
421 void Iconify P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
422 void DisplayMove P((int moveNumber));
423 void DisplayTitle P((char *title));
424 void ICSInitScript P((void));
425 int LoadGamePopUp P((FILE *f, int gameNumber, char *title));
426 void ErrorPopUp P((char *title, char *text, int modal));
427 void ErrorPopDown P((void));
428 static char *ExpandPathName P((char *path));
429 static void CreateAnimVars P((void));
430 static void DragPieceBegin P((int x, int y));
431 static void DragPieceMove P((int x, int y));
432 static void DragPieceEnd P((int x, int y));
433 static void DrawDragPiece P((void));
434 char *ModeToWidgetName P((GameMode mode));
435 void EngineOutputUpdate( FrontEndProgramStats * stats );
436 void ShuffleMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
437 void EngineMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
438 void UciMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
439 void TimeControlProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
440 void NewVariantProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
441 void FirstSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
442 void SecondSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
443 void ShufflePopDown P(());
444 void EnginePopDown P(());
445 void UciPopDown P(());
446 void TimeControlPopDown P(());
447 void NewVariantPopDown P(());
448 void SettingsPopDown P(());
450 * XBoard depends on Xt R4 or higher
452 int xtVersion = XtSpecificationRelease;
457 Pixel lightSquareColor, darkSquareColor, whitePieceColor, blackPieceColor,
458 jailSquareColor, highlightSquareColor, premoveHighlightColor;
459 Pixel lowTimeWarningColor;
460 GC lightSquareGC, darkSquareGC, jailSquareGC, lineGC, wdPieceGC, wlPieceGC,
461 bdPieceGC, blPieceGC, wbPieceGC, bwPieceGC, coordGC, highlineGC,
462 wjPieceGC, bjPieceGC, prelineGC, countGC;
463 Pixmap iconPixmap, wIconPixmap, bIconPixmap, xMarkPixmap;
464 Widget shellWidget, layoutWidget, formWidget, boardWidget, messageWidget,
465 whiteTimerWidget, blackTimerWidget, titleWidget, widgetList[16],
466 commentShell, promotionShell, whitePieceMenu, blackPieceMenu, dropMenu,
467 menuBarWidget, buttonBarWidget, editShell, errorShell, analysisShell,
468 ICSInputShell, fileNameShell, askQuestionShell;
469 XSegment gridSegments[(BOARD_SIZE + 1) * 2];
470 XSegment jailGridSegments[(BOARD_SIZE + 3) * 2];
471 Font clockFontID, coordFontID, countFontID;
472 XFontStruct *clockFontStruct, *coordFontStruct, *countFontStruct;
473 XtAppContext appContext;
475 char *oldICSInteractionTitle;
479 char installDir[] = "."; // [HGM] UCI: needed for UCI; probably needs run-time initializtion
481 Position commentX = -1, commentY = -1;
482 Dimension commentW, commentH;
484 int squareSize, smallLayout = 0, tinyLayout = 0,
485 marginW, marginH, // [HGM] for run-time resizing
486 fromX = -1, fromY = -1, toX, toY, commentUp = False, analysisUp = False,
487 ICSInputBoxUp = False, askQuestionUp = False,
488 filenameUp = False, promotionUp = False, pmFromX = -1, pmFromY = -1,
489 editUp = False, errorUp = False, errorExitStatus = -1, lineGap;
490 Pixel timerForegroundPixel, timerBackgroundPixel;
491 Pixel buttonForegroundPixel, buttonBackgroundPixel;
492 char *chessDir, *programName, *programVersion,
493 *gameCopyFilename, *gamePasteFilename;
497 Pixmap pieceBitmap[2][(int)BlackPawn];
498 Pixmap pieceBitmap2[2][(int)BlackPawn+4]; /* [HGM] pieces */
499 Pixmap xpmPieceBitmap[4][(int)BlackPawn]; /* LL, LD, DL, DD actually used*/
500 Pixmap xpmPieceBitmap2[4][(int)BlackPawn+4]; /* LL, LD, DL, DD set to select from */
501 Pixmap xpmLightSquare, xpmDarkSquare, xpmJailSquare;
502 int useImages, useImageSqs;
503 XImage *ximPieceBitmap[4][(int)BlackPawn+4]; /* LL, LD, DL, DD */
504 Pixmap ximMaskPm[(int)BlackPawn]; /* clipmasks, used for XIM pieces */
505 Pixmap ximMaskPm2[(int)BlackPawn+4]; /* clipmasks, used for XIM pieces */
506 XImage *ximLightSquare, *ximDarkSquare;
509 #define pieceToSolid(piece) &pieceBitmap[SOLID][(piece) % (int)BlackPawn]
510 #define pieceToOutline(piece) &pieceBitmap[OUTLINE][(piece) % (int)BlackPawn]
512 #define White(piece) ((int)(piece) < (int)BlackPawn)
514 /* Variables for doing smooth animation. This whole thing
515 would be much easier if the board was double-buffered,
516 but that would require a fairly major rewrite. */
521 GC blitGC, pieceGC, outlineGC;
522 XPoint startSquare, prevFrame, mouseDelta;
526 int startBoardX, startBoardY;
529 /* There can be two pieces being animated at once: a player
530 can begin dragging a piece before the remote opponent has moved. */
532 static AnimState game, player;
534 /* Bitmaps for use as masks when drawing XPM pieces.
535 Need one for each black and white piece. */
536 static Pixmap xpmMask[BlackKing + 1];
538 /* This magic number is the number of intermediate frames used
539 in each half of the animation. For short moves it's reduced
540 by 1. The total number of frames will be factor * 2 + 1. */
543 SizeDefaults sizeDefaults[] = SIZE_DEFAULTS;
545 MenuItem fileMenu[] = {
546 {N_("New Game"), ResetProc},
547 {N_("New Shuffle Game ..."), ShuffleMenuProc},
548 {N_("New Variant ..."), NewVariantProc}, // [HGM] variant: not functional yet
549 {"----", NothingProc},
550 {N_("Load Game"), LoadGameProc},
551 {N_("Load Next Game"), LoadNextGameProc},
552 {N_("Load Previous Game"), LoadPrevGameProc},
553 {N_("Reload Same Game"), ReloadGameProc},
554 {N_("Save Game"), SaveGameProc},
555 {"----", NothingProc},
556 {N_("Copy Game"), CopyGameProc},
557 {N_("Paste Game"), PasteGameProc},
558 {"----", NothingProc},
559 {N_("Load Position"), LoadPositionProc},
560 {N_("Load Next Position"), LoadNextPositionProc},
561 {N_("Load Previous Position"), LoadPrevPositionProc},
562 {N_("Reload Same Position"), ReloadPositionProc},
563 {N_("Save Position"), SavePositionProc},
564 {"----", NothingProc},
565 {N_("Copy Position"), CopyPositionProc},
566 {N_("Paste Position"), PastePositionProc},
567 {"----", NothingProc},
568 {N_("Mail Move"), MailMoveProc},
569 {N_("Reload CMail Message"), ReloadCmailMsgProc},
570 {"----", NothingProc},
571 {N_("Exit"), QuitProc},
575 MenuItem modeMenu[] = {
576 {N_("Machine White"), MachineWhiteProc},
577 {N_("Machine Black"), MachineBlackProc},
578 {N_("Two Machines"), TwoMachinesProc},
579 {N_("Analysis Mode"), AnalyzeModeProc},
580 {N_("Analyze File"), AnalyzeFileProc },
581 {N_("ICS Client"), IcsClientProc},
582 {N_("Edit Game"), EditGameProc},
583 {N_("Edit Position"), EditPositionProc},
584 {N_("Training"), TrainingProc},
585 {"----", NothingProc},
586 {N_("Show Engine Output"), EngineOutputProc},
587 {N_("Show Evaluation Graph"), NothingProc}, // [HGM] evalgr: not functional yet
588 {N_("Show Game List"), ShowGameListProc},
589 {"Show Move History", HistoryShowProc}, // [HGM] hist: activate 4.2.7 code
590 {"----", NothingProc},
591 {N_("Edit Tags"), EditTagsProc},
592 {N_("Edit Comment"), EditCommentProc},
593 {N_("ICS Input Box"), IcsInputBoxProc},
594 {N_("Pause"), PauseProc},
598 MenuItem actionMenu[] = {
599 {N_("Accept"), AcceptProc},
600 {N_("Decline"), DeclineProc},
601 {N_("Rematch"), RematchProc},
602 {"----", NothingProc},
603 {N_("Call Flag"), CallFlagProc},
604 {N_("Draw"), DrawProc},
605 {N_("Adjourn"), AdjournProc},
606 {N_("Abort"), AbortProc},
607 {N_("Resign"), ResignProc},
608 {"----", NothingProc},
609 {N_("Stop Observing"), StopObservingProc},
610 {N_("Stop Examining"), StopExaminingProc},
611 {"----", NothingProc},
612 {N_("Adjudicate to White"), AdjuWhiteProc},
613 {N_("Adjudicate to Black"), AdjuBlackProc},
614 {N_("Adjudicate Draw"), AdjuDrawProc},
618 MenuItem stepMenu[] = {
619 {N_("Backward"), BackwardProc},
620 {N_("Forward"), ForwardProc},
621 {N_("Back to Start"), ToStartProc},
622 {N_("Forward to End"), ToEndProc},
623 {N_("Revert"), RevertProc},
624 {N_("Truncate Game"), TruncateGameProc},
625 {"----", NothingProc},
626 {N_("Move Now"), MoveNowProc},
627 {N_("Retract Move"), RetractMoveProc},
631 MenuItem optionsMenu[] = {
632 {N_("Flip View"), FlipViewProc},
633 {"----", NothingProc},
634 {N_("Adjudications ..."), EngineMenuProc},
635 {N_("General Settings ..."), UciMenuProc},
636 {N_("Engine #1 Settings ..."), FirstSettingsProc},
637 {N_("Engine #2 Settings ..."), SecondSettingsProc},
638 {N_("Time Control ..."), TimeControlProc},
639 {"----", NothingProc},
640 {N_("Always Queen"), AlwaysQueenProc},
641 {N_("Animate Dragging"), AnimateDraggingProc},
642 {N_("Animate Moving"), AnimateMovingProc},
643 {N_("Auto Comment"), AutocommProc},
644 {N_("Auto Flag"), AutoflagProc},
645 {N_("Auto Flip View"), AutoflipProc},
646 {N_("Auto Observe"), AutobsProc},
647 {N_("Auto Raise Board"), AutoraiseProc},
648 {N_("Auto Save"), AutosaveProc},
649 {N_("Blindfold"), BlindfoldProc},
650 {N_("Flash Moves"), FlashMovesProc},
651 {N_("Get Move List"), GetMoveListProc},
653 {N_("Highlight Dragging"), HighlightDraggingProc},
655 {N_("Highlight Last Move"), HighlightLastMoveProc},
656 {N_("Move Sound"), MoveSoundProc},
657 {N_("ICS Alarm"), IcsAlarmProc},
658 {N_("Old Save Style"), OldSaveStyleProc},
659 {N_("Periodic Updates"), PeriodicUpdatesProc},
660 {N_("Ponder Next Move"), PonderNextMoveProc},
661 {N_("Popup Exit Message"), PopupExitMessageProc},
662 {N_("Popup Move Errors"), PopupMoveErrorsProc},
663 {N_("Premove"), PremoveProc},
664 {N_("Quiet Play"), QuietPlayProc},
665 {N_("Show Coords"), ShowCoordsProc},
666 {N_("Hide Thinking"), HideThinkingProc},
667 {N_("Test Legality"), TestLegalityProc},
671 MenuItem helpMenu[] = {
672 {N_("Info XBoard"), InfoProc},
673 {N_("Man XBoard"), ManProc},
674 {"----", NothingProc},
675 {N_("Hint"), HintProc},
676 {N_("Book"), BookProc},
677 {"----", NothingProc},
678 {N_("About XBoard"), AboutProc},
683 {N_("File"), fileMenu},
684 {N_("Mode"), modeMenu},
685 {N_("Action"), actionMenu},
686 {N_("Step"), stepMenu},
687 {N_("Options"), optionsMenu},
688 {N_("Help"), helpMenu},
692 #define PAUSE_BUTTON N_("P")
693 MenuItem buttonBar[] = {
696 {PAUSE_BUTTON, PauseProc},
702 #define PIECE_MENU_SIZE 18
703 String pieceMenuStrings[2][PIECE_MENU_SIZE] = {
704 { N_("White"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
705 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
706 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
707 N_("Empty square"), N_("Clear board") },
708 { N_("Black"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
709 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
710 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
711 N_("Empty square"), N_("Clear board") }
713 /* must be in same order as PieceMenuStrings! */
714 ChessSquare pieceMenuTranslation[2][PIECE_MENU_SIZE] = {
715 { WhitePlay, (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
716 WhiteRook, WhiteQueen, WhiteKing, (ChessSquare) 0, WhiteAlfil,
717 WhiteCannon, WhiteAngel, WhiteMarshall, (ChessSquare) 0,
718 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
719 { BlackPlay, (ChessSquare) 0, BlackPawn, BlackKnight, BlackBishop,
720 BlackRook, BlackQueen, BlackKing, (ChessSquare) 0, BlackAlfil,
721 BlackCannon, BlackAngel, BlackMarshall, (ChessSquare) 0,
722 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
725 #define DROP_MENU_SIZE 6
726 String dropMenuStrings[DROP_MENU_SIZE] = {
727 "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"), N_("Queen")
729 /* must be in same order as PieceMenuStrings! */
730 ChessSquare dropMenuTranslation[DROP_MENU_SIZE] = {
731 (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
732 WhiteRook, WhiteQueen
740 DropMenuEnables dmEnables[] = {
758 { XtNborderWidth, 0 },
759 { XtNdefaultDistance, 0 },
763 { XtNborderWidth, 0 },
764 { XtNresizable, (XtArgVal) True },
768 { XtNborderWidth, 0 },
774 { XtNjustify, (XtArgVal) XtJustifyRight },
775 { XtNlabel, (XtArgVal) "..." },
776 { XtNresizable, (XtArgVal) True },
777 { XtNresize, (XtArgVal) False }
780 Arg messageArgs[] = {
781 { XtNjustify, (XtArgVal) XtJustifyLeft },
782 { XtNlabel, (XtArgVal) "..." },
783 { XtNresizable, (XtArgVal) True },
784 { XtNresize, (XtArgVal) False }
788 { XtNborderWidth, 0 },
789 { XtNjustify, (XtArgVal) XtJustifyLeft }
792 XtResource clientResources[] = {
793 { "whitePieceColor", "whitePieceColor", XtRString, sizeof(String),
794 XtOffset(AppDataPtr, whitePieceColor), XtRString,
796 { "blackPieceColor", "blackPieceColor", XtRString, sizeof(String),
797 XtOffset(AppDataPtr, blackPieceColor), XtRString,
799 { "lightSquareColor", "lightSquareColor", XtRString,
800 sizeof(String), XtOffset(AppDataPtr, lightSquareColor),
801 XtRString, LIGHT_SQUARE_COLOR },
802 { "darkSquareColor", "darkSquareColor", XtRString, sizeof(String),
803 XtOffset(AppDataPtr, darkSquareColor), XtRString,
805 { "highlightSquareColor", "highlightSquareColor", XtRString,
806 sizeof(String), XtOffset(AppDataPtr, highlightSquareColor),
807 XtRString, HIGHLIGHT_SQUARE_COLOR },
808 { "premoveHighlightColor", "premoveHighlightColor", XtRString,
809 sizeof(String), XtOffset(AppDataPtr, premoveHighlightColor),
810 XtRString, PREMOVE_HIGHLIGHT_COLOR },
811 { "movesPerSession", "movesPerSession", XtRInt, sizeof(int),
812 XtOffset(AppDataPtr, movesPerSession), XtRImmediate,
813 (XtPointer) MOVES_PER_SESSION },
814 { "timeIncrement", "timeIncrement", XtRInt, sizeof(int),
815 XtOffset(AppDataPtr, timeIncrement), XtRImmediate,
816 (XtPointer) TIME_INCREMENT },
817 { "initString", "initString", XtRString, sizeof(String),
818 XtOffset(AppDataPtr, initString), XtRString, INIT_STRING },
819 { "secondInitString", "secondInitString", XtRString, sizeof(String),
820 XtOffset(AppDataPtr, secondInitString), XtRString, INIT_STRING },
821 { "firstComputerString", "firstComputerString", XtRString,
822 sizeof(String), XtOffset(AppDataPtr, firstComputerString), XtRString,
824 { "secondComputerString", "secondComputerString", XtRString,
825 sizeof(String), XtOffset(AppDataPtr, secondComputerString), XtRString,
827 { "firstChessProgram", "firstChessProgram", XtRString,
828 sizeof(String), XtOffset(AppDataPtr, firstChessProgram),
829 XtRString, FIRST_CHESS_PROGRAM },
830 { "secondChessProgram", "secondChessProgram", XtRString,
831 sizeof(String), XtOffset(AppDataPtr, secondChessProgram),
832 XtRString, SECOND_CHESS_PROGRAM },
833 { "firstPlaysBlack", "firstPlaysBlack", XtRBoolean,
834 sizeof(Boolean), XtOffset(AppDataPtr, firstPlaysBlack),
835 XtRImmediate, (XtPointer) False },
836 { "noChessProgram", "noChessProgram", XtRBoolean,
837 sizeof(Boolean), XtOffset(AppDataPtr, noChessProgram),
838 XtRImmediate, (XtPointer) False },
839 { "firstHost", "firstHost", XtRString, sizeof(String),
840 XtOffset(AppDataPtr, firstHost), XtRString, FIRST_HOST },
841 { "secondHost", "secondHost", XtRString, sizeof(String),
842 XtOffset(AppDataPtr, secondHost), XtRString, SECOND_HOST },
843 { "firstDirectory", "firstDirectory", XtRString, sizeof(String),
844 XtOffset(AppDataPtr, firstDirectory), XtRString, "." },
845 { "secondDirectory", "secondDirectory", XtRString, sizeof(String),
846 XtOffset(AppDataPtr, secondDirectory), XtRString, "." },
847 { "bitmapDirectory", "bitmapDirectory", XtRString,
848 sizeof(String), XtOffset(AppDataPtr, bitmapDirectory),
850 { "remoteShell", "remoteShell", XtRString, sizeof(String),
851 XtOffset(AppDataPtr, remoteShell), XtRString, REMOTE_SHELL },
852 { "remoteUser", "remoteUser", XtRString, sizeof(String),
853 XtOffset(AppDataPtr, remoteUser), XtRString, "" },
854 { "timeDelay", "timeDelay", XtRFloat, sizeof(float),
855 XtOffset(AppDataPtr, timeDelay), XtRString,
856 (XtPointer) TIME_DELAY_QUOTE },
857 { "timeControl", "timeControl", XtRString, sizeof(String),
858 XtOffset(AppDataPtr, timeControl), XtRString,
859 (XtPointer) TIME_CONTROL },
860 { "internetChessServerMode", "internetChessServerMode",
861 XtRBoolean, sizeof(Boolean),
862 XtOffset(AppDataPtr, icsActive), XtRImmediate,
864 { "internetChessServerHost", "internetChessServerHost",
865 XtRString, sizeof(String),
866 XtOffset(AppDataPtr, icsHost),
867 XtRString, (XtPointer) ICS_HOST },
868 { "internetChessServerPort", "internetChessServerPort",
869 XtRString, sizeof(String),
870 XtOffset(AppDataPtr, icsPort), XtRString,
871 (XtPointer) ICS_PORT },
872 { "internetChessServerCommPort", "internetChessServerCommPort",
873 XtRString, sizeof(String),
874 XtOffset(AppDataPtr, icsCommPort), XtRString,
876 { "internetChessServerLogonScript", "internetChessServerLogonScript",
877 XtRString, sizeof(String),
878 XtOffset(AppDataPtr, icsLogon), XtRString,
880 { "internetChessServerHelper", "internetChessServerHelper",
881 XtRString, sizeof(String),
882 XtOffset(AppDataPtr, icsHelper), XtRString, "" },
883 { "internetChessServerInputBox", "internetChessServerInputBox",
884 XtRBoolean, sizeof(Boolean),
885 XtOffset(AppDataPtr, icsInputBox), XtRImmediate,
887 { "icsAlarm", "icsAlarm",
888 XtRBoolean, sizeof(Boolean),
889 XtOffset(AppDataPtr, icsAlarm), XtRImmediate,
891 { "icsAlarmTime", "icsAlarmTime",
893 XtOffset(AppDataPtr, icsAlarmTime), XtRImmediate,
895 { "useTelnet", "useTelnet", XtRBoolean, sizeof(Boolean),
896 XtOffset(AppDataPtr, useTelnet), XtRImmediate,
898 { "telnetProgram", "telnetProgram", XtRString, sizeof(String),
899 XtOffset(AppDataPtr, telnetProgram), XtRString, TELNET_PROGRAM },
900 { "gateway", "gateway", XtRString, sizeof(String),
901 XtOffset(AppDataPtr, gateway), XtRString, "" },
902 { "loadGameFile", "loadGameFile", XtRString, sizeof(String),
903 XtOffset(AppDataPtr, loadGameFile), XtRString, "" },
904 { "loadGameIndex", "loadGameIndex",
906 XtOffset(AppDataPtr, loadGameIndex), XtRImmediate,
908 { "saveGameFile", "saveGameFile", XtRString, sizeof(String),
909 XtOffset(AppDataPtr, saveGameFile), XtRString, "" },
910 { "autoRaiseBoard", "autoRaiseBoard", XtRBoolean,
911 sizeof(Boolean), XtOffset(AppDataPtr, autoRaiseBoard),
912 XtRImmediate, (XtPointer) True },
913 { "autoSaveGames", "autoSaveGames", XtRBoolean,
914 sizeof(Boolean), XtOffset(AppDataPtr, autoSaveGames),
915 XtRImmediate, (XtPointer) False },
916 { "blindfold", "blindfold", XtRBoolean,
917 sizeof(Boolean), XtOffset(AppDataPtr, blindfold),
918 XtRImmediate, (XtPointer) False },
919 { "loadPositionFile", "loadPositionFile", XtRString,
920 sizeof(String), XtOffset(AppDataPtr, loadPositionFile),
922 { "loadPositionIndex", "loadPositionIndex",
924 XtOffset(AppDataPtr, loadPositionIndex), XtRImmediate,
926 { "savePositionFile", "savePositionFile", XtRString,
927 sizeof(String), XtOffset(AppDataPtr, savePositionFile),
929 { "matchMode", "matchMode", XtRBoolean, sizeof(Boolean),
930 XtOffset(AppDataPtr, matchMode), XtRImmediate, (XtPointer) False },
931 { "matchGames", "matchGames", XtRInt, sizeof(int),
932 XtOffset(AppDataPtr, matchGames), XtRImmediate,
934 { "monoMode", "monoMode", XtRBoolean, sizeof(Boolean),
935 XtOffset(AppDataPtr, monoMode), XtRImmediate,
937 { "debugMode", "debugMode", XtRBoolean, sizeof(Boolean),
938 XtOffset(AppDataPtr, debugMode), XtRImmediate,
940 { "clockMode", "clockMode", XtRBoolean, sizeof(Boolean),
941 XtOffset(AppDataPtr, clockMode), XtRImmediate,
943 { "boardSize", "boardSize", XtRString, sizeof(String),
944 XtOffset(AppDataPtr, boardSize), XtRString, "" },
945 { "searchTime", "searchTime", XtRString, sizeof(String),
946 XtOffset(AppDataPtr, searchTime), XtRString,
948 { "searchDepth", "searchDepth", XtRInt, sizeof(int),
949 XtOffset(AppDataPtr, searchDepth), XtRImmediate,
951 { "showCoords", "showCoords", XtRBoolean, sizeof(Boolean),
952 XtOffset(AppDataPtr, showCoords), XtRImmediate,
954 { "showJail", "showJail", XtRInt, sizeof(int),
955 XtOffset(AppDataPtr, showJail), XtRImmediate,
957 { "showThinking", "showThinking", XtRBoolean, sizeof(Boolean),
958 XtOffset(AppDataPtr, showThinking), XtRImmediate,
960 { "ponderNextMove", "ponderNextMove", XtRBoolean, sizeof(Boolean),
961 XtOffset(AppDataPtr, ponderNextMove), XtRImmediate,
963 { "periodicUpdates", "periodicUpdates", XtRBoolean, sizeof(Boolean),
964 XtOffset(AppDataPtr, periodicUpdates), XtRImmediate,
966 { "clockFont", "clockFont", XtRString, sizeof(String),
967 XtOffset(AppDataPtr, clockFont), XtRString, CLOCK_FONT },
968 { "coordFont", "coordFont", XtRString, sizeof(String),
969 XtOffset(AppDataPtr, coordFont), XtRString, COORD_FONT },
970 { "font", "font", XtRString, sizeof(String),
971 XtOffset(AppDataPtr, font), XtRString, DEFAULT_FONT },
972 { "ringBellAfterMoves", "ringBellAfterMoves",
973 XtRBoolean, sizeof(Boolean),
974 XtOffset(AppDataPtr, ringBellAfterMoves),
975 XtRImmediate, (XtPointer) False },
976 { "autoCallFlag", "autoCallFlag", XtRBoolean,
977 sizeof(Boolean), XtOffset(AppDataPtr, autoCallFlag),
978 XtRImmediate, (XtPointer) False },
979 { "autoFlipView", "autoFlipView", XtRBoolean,
980 sizeof(Boolean), XtOffset(AppDataPtr, autoFlipView),
981 XtRImmediate, (XtPointer) True },
982 { "autoObserve", "autoObserve", XtRBoolean,
983 sizeof(Boolean), XtOffset(AppDataPtr, autoObserve),
984 XtRImmediate, (XtPointer) False },
985 { "autoComment", "autoComment", XtRBoolean,
986 sizeof(Boolean), XtOffset(AppDataPtr, autoComment),
987 XtRImmediate, (XtPointer) False },
988 { "getMoveList", "getMoveList", XtRBoolean,
989 sizeof(Boolean), XtOffset(AppDataPtr, getMoveList),
990 XtRImmediate, (XtPointer) True },
992 { "highlightDragging", "highlightDragging", XtRBoolean,
993 sizeof(Boolean), XtOffset(AppDataPtr, highlightDragging),
994 XtRImmediate, (XtPointer) False },
996 { "highlightLastMove", "highlightLastMove", XtRBoolean,
997 sizeof(Boolean), XtOffset(AppDataPtr, highlightLastMove),
998 XtRImmediate, (XtPointer) False },
999 { "premove", "premove", XtRBoolean,
1000 sizeof(Boolean), XtOffset(AppDataPtr, premove),
1001 XtRImmediate, (XtPointer) True },
1002 { "testLegality", "testLegality", XtRBoolean,
1003 sizeof(Boolean), XtOffset(AppDataPtr, testLegality),
1004 XtRImmediate, (XtPointer) True },
1005 { "flipView", "flipView", XtRBoolean,
1006 sizeof(Boolean), XtOffset(AppDataPtr, flipView),
1007 XtRImmediate, (XtPointer) False },
1008 { "cmail", "cmailGameName", XtRString, sizeof(String),
1009 XtOffset(AppDataPtr, cmailGameName), XtRString, "" },
1010 { "alwaysPromoteToQueen", "alwaysPromoteToQueen", XtRBoolean,
1011 sizeof(Boolean), XtOffset(AppDataPtr, alwaysPromoteToQueen),
1012 XtRImmediate, (XtPointer) False },
1013 { "oldSaveStyle", "oldSaveStyle", XtRBoolean,
1014 sizeof(Boolean), XtOffset(AppDataPtr, oldSaveStyle),
1015 XtRImmediate, (XtPointer) False },
1016 { "quietPlay", "quietPlay", XtRBoolean,
1017 sizeof(Boolean), XtOffset(AppDataPtr, quietPlay),
1018 XtRImmediate, (XtPointer) False },
1019 { "titleInWindow", "titleInWindow", XtRBoolean,
1020 sizeof(Boolean), XtOffset(AppDataPtr, titleInWindow),
1021 XtRImmediate, (XtPointer) False },
1022 { "localLineEditing", "localLineEditing", XtRBoolean,
1023 sizeof(Boolean), XtOffset(AppDataPtr, localLineEditing),
1024 XtRImmediate, (XtPointer) True }, /* not implemented, must be True */
1026 { "zippyTalk", "zippyTalk", XtRBoolean,
1027 sizeof(Boolean), XtOffset(AppDataPtr, zippyTalk),
1028 XtRImmediate, (XtPointer) ZIPPY_TALK },
1029 { "zippyPlay", "zippyPlay", XtRBoolean,
1030 sizeof(Boolean), XtOffset(AppDataPtr, zippyPlay),
1031 XtRImmediate, (XtPointer) ZIPPY_PLAY },
1032 { "zippyLines", "zippyLines", XtRString, sizeof(String),
1033 XtOffset(AppDataPtr, zippyLines), XtRString, ZIPPY_LINES },
1034 { "zippyPinhead", "zippyPinhead", XtRString, sizeof(String),
1035 XtOffset(AppDataPtr, zippyPinhead), XtRString, ZIPPY_PINHEAD },
1036 { "zippyPassword", "zippyPassword", XtRString, sizeof(String),
1037 XtOffset(AppDataPtr, zippyPassword), XtRString, ZIPPY_PASSWORD },
1038 { "zippyPassword2", "zippyPassword2", XtRString, sizeof(String),
1039 XtOffset(AppDataPtr, zippyPassword2), XtRString, ZIPPY_PASSWORD2 },
1040 { "zippyWrongPassword", "zippyWrongPassword", XtRString, sizeof(String),
1041 XtOffset(AppDataPtr, zippyWrongPassword), XtRString,
1042 ZIPPY_WRONG_PASSWORD },
1043 { "zippyAcceptOnly", "zippyAcceptOnly", XtRString, sizeof(String),
1044 XtOffset(AppDataPtr, zippyAcceptOnly), XtRString, ZIPPY_ACCEPT_ONLY },
1045 { "zippyUseI", "zippyUseI", XtRBoolean,
1046 sizeof(Boolean), XtOffset(AppDataPtr, zippyUseI),
1047 XtRImmediate, (XtPointer) ZIPPY_USE_I },
1048 { "zippyBughouse", "zippyBughouse", XtRInt,
1049 sizeof(int), XtOffset(AppDataPtr, zippyBughouse),
1050 XtRImmediate, (XtPointer) ZIPPY_BUGHOUSE },
1051 { "zippyNoplayCrafty", "zippyNoplayCrafty", XtRBoolean,
1052 sizeof(Boolean), XtOffset(AppDataPtr, zippyNoplayCrafty),
1053 XtRImmediate, (XtPointer) ZIPPY_NOPLAY_CRAFTY },
1054 { "zippyGameEnd", "zippyGameEnd", XtRString, sizeof(String),
1055 XtOffset(AppDataPtr, zippyGameEnd), XtRString, ZIPPY_GAME_END },
1056 { "zippyGameStart", "zippyGameStart", XtRString, sizeof(String),
1057 XtOffset(AppDataPtr, zippyGameStart), XtRString, ZIPPY_GAME_START },
1058 { "zippyAdjourn", "zippyAdjourn", XtRBoolean,
1059 sizeof(Boolean), XtOffset(AppDataPtr, zippyAdjourn),
1060 XtRImmediate, (XtPointer) ZIPPY_ADJOURN },
1061 { "zippyAbort", "zippyAbort", XtRBoolean,
1062 sizeof(Boolean), XtOffset(AppDataPtr, zippyAbort),
1063 XtRImmediate, (XtPointer) ZIPPY_ABORT },
1064 { "zippyVariants", "zippyVariants", XtRString, sizeof(String),
1065 XtOffset(AppDataPtr, zippyVariants), XtRString, ZIPPY_VARIANTS },
1066 { "zippyMaxGames", "zippyMaxGames", XtRInt, sizeof(int),
1067 XtOffset(AppDataPtr, zippyMaxGames), XtRImmediate,
1068 (XtPointer) ZIPPY_MAX_GAMES },
1069 { "zippyReplayTimeout", "zippyReplayTimeout", XtRInt, sizeof(int),
1070 XtOffset(AppDataPtr, zippyReplayTimeout), XtRImmediate,
1071 (XtPointer) ZIPPY_REPLAY_TIMEOUT },
1072 { "zippyShortGame", "zippyShortGame", XtRInt, sizeof(int),
1073 XtOffset(AppDataPtr, zippyShortGame), XtRImmediate,
1076 { "flashCount", "flashCount", XtRInt, sizeof(int),
1077 XtOffset(AppDataPtr, flashCount), XtRImmediate,
1078 (XtPointer) FLASH_COUNT },
1079 { "flashRate", "flashRate", XtRInt, sizeof(int),
1080 XtOffset(AppDataPtr, flashRate), XtRImmediate,
1081 (XtPointer) FLASH_RATE },
1082 { "pixmapDirectory", "pixmapDirectory", XtRString,
1083 sizeof(String), XtOffset(AppDataPtr, pixmapDirectory),
1085 { "msLoginDelay", "msLoginDelay", XtRInt, sizeof(int),
1086 XtOffset(AppDataPtr, msLoginDelay), XtRImmediate,
1087 (XtPointer) MS_LOGIN_DELAY },
1088 { "colorizeMessages", "colorizeMessages", XtRBoolean,
1089 sizeof(Boolean), XtOffset(AppDataPtr, colorize),
1090 XtRImmediate, (XtPointer) False },
1091 { "colorShout", "colorShout", XtRString,
1092 sizeof(String), XtOffset(AppDataPtr, colorShout),
1093 XtRString, COLOR_SHOUT },
1094 { "colorSShout", "colorSShout", XtRString,
1095 sizeof(String), XtOffset(AppDataPtr, colorSShout),
1096 XtRString, COLOR_SSHOUT },
1097 { "colorChannel1", "colorChannel1", XtRString,
1098 sizeof(String), XtOffset(AppDataPtr, colorChannel1),
1099 XtRString, COLOR_CHANNEL1 },
1100 { "colorChannel", "colorChannel", XtRString,
1101 sizeof(String), XtOffset(AppDataPtr, colorChannel),
1102 XtRString, COLOR_CHANNEL },
1103 { "colorKibitz", "colorKibitz", XtRString,
1104 sizeof(String), XtOffset(AppDataPtr, colorKibitz),
1105 XtRString, COLOR_KIBITZ },
1106 { "colorTell", "colorTell", XtRString,
1107 sizeof(String), XtOffset(AppDataPtr, colorTell),
1108 XtRString, COLOR_TELL },
1109 { "colorChallenge", "colorChallenge", XtRString,
1110 sizeof(String), XtOffset(AppDataPtr, colorChallenge),
1111 XtRString, COLOR_CHALLENGE },
1112 { "colorRequest", "colorRequest", XtRString,
1113 sizeof(String), XtOffset(AppDataPtr, colorRequest),
1114 XtRString, COLOR_REQUEST },
1115 { "colorSeek", "colorSeek", XtRString,
1116 sizeof(String), XtOffset(AppDataPtr, colorSeek),
1117 XtRString, COLOR_SEEK },
1118 { "colorNormal", "colorNormal", XtRString,
1119 sizeof(String), XtOffset(AppDataPtr, colorNormal),
1120 XtRString, COLOR_NORMAL },
1121 { "soundProgram", "soundProgram", XtRString,
1122 sizeof(String), XtOffset(AppDataPtr, soundProgram),
1123 XtRString, "play" },
1124 { "soundShout", "soundShout", XtRString,
1125 sizeof(String), XtOffset(AppDataPtr, soundShout),
1127 { "soundSShout", "soundSShout", XtRString,
1128 sizeof(String), XtOffset(AppDataPtr, soundSShout),
1130 { "soundChannel1", "soundChannel1", XtRString,
1131 sizeof(String), XtOffset(AppDataPtr, soundChannel1),
1133 { "soundChannel", "soundChannel", XtRString,
1134 sizeof(String), XtOffset(AppDataPtr, soundChannel),
1136 { "soundKibitz", "soundKibitz", XtRString,
1137 sizeof(String), XtOffset(AppDataPtr, soundKibitz),
1139 { "soundTell", "soundTell", XtRString,
1140 sizeof(String), XtOffset(AppDataPtr, soundTell),
1142 { "soundChallenge", "soundChallenge", XtRString,
1143 sizeof(String), XtOffset(AppDataPtr, soundChallenge),
1145 { "soundRequest", "soundRequest", XtRString,
1146 sizeof(String), XtOffset(AppDataPtr, soundRequest),
1148 { "soundSeek", "soundSeek", XtRString,
1149 sizeof(String), XtOffset(AppDataPtr, soundSeek),
1151 { "soundMove", "soundMove", XtRString,
1152 sizeof(String), XtOffset(AppDataPtr, soundMove),
1154 { "soundIcsWin", "soundIcsWin", XtRString,
1155 sizeof(String), XtOffset(AppDataPtr, soundIcsWin),
1157 { "soundIcsLoss", "soundIcsLoss", XtRString,
1158 sizeof(String), XtOffset(AppDataPtr, soundIcsLoss),
1160 { "soundIcsDraw", "soundIcsDraw", XtRString,
1161 sizeof(String), XtOffset(AppDataPtr, soundIcsDraw),
1163 { "soundIcsUnfinished", "soundIcsUnfinished", XtRString,
1164 sizeof(String), XtOffset(AppDataPtr, soundIcsUnfinished),
1166 { "soundIcsAlarm", "soundIcsAlarm", XtRString,
1167 sizeof(String), XtOffset(AppDataPtr, soundIcsAlarm),
1169 { "reuseFirst", "reuseFirst", XtRBoolean,
1170 sizeof(Boolean), XtOffset(AppDataPtr, reuseFirst),
1171 XtRImmediate, (XtPointer) True },
1172 { "reuseSecond", "reuseSecond", XtRBoolean,
1173 sizeof(Boolean), XtOffset(AppDataPtr, reuseSecond),
1174 XtRImmediate, (XtPointer) True },
1175 { "animateDragging", "animateDragging", XtRBoolean,
1176 sizeof(Boolean), XtOffset(AppDataPtr, animateDragging),
1177 XtRImmediate, (XtPointer) True },
1178 { "animateMoving", "animateMoving", XtRBoolean,
1179 sizeof(Boolean), XtOffset(AppDataPtr, animate),
1180 XtRImmediate, (XtPointer) True },
1181 { "animateSpeed", "animateSpeed", XtRInt,
1182 sizeof(int), XtOffset(AppDataPtr, animSpeed),
1183 XtRImmediate, (XtPointer)10 },
1184 { "popupExitMessage", "popupExitMessage", XtRBoolean,
1185 sizeof(Boolean), XtOffset(AppDataPtr, popupExitMessage),
1186 XtRImmediate, (XtPointer) True },
1187 { "popupMoveErrors", "popupMoveErrors", XtRBoolean,
1188 sizeof(Boolean), XtOffset(AppDataPtr, popupMoveErrors),
1189 XtRImmediate, (XtPointer) False },
1190 { "fontSizeTolerance", "fontSizeTolerance", XtRInt,
1191 sizeof(int), XtOffset(AppDataPtr, fontSizeTolerance),
1192 XtRImmediate, (XtPointer)4 },
1193 { "initialMode", "initialMode", XtRString,
1194 sizeof(String), XtOffset(AppDataPtr, initialMode),
1195 XtRImmediate, (XtPointer) "" },
1196 { "variant", "variant", XtRString,
1197 sizeof(String), XtOffset(AppDataPtr, variant),
1198 XtRImmediate, (XtPointer) "normal" },
1199 { "firstProtocolVersion", "firstProtocolVersion", XtRInt,
1200 sizeof(int), XtOffset(AppDataPtr, firstProtocolVersion),
1201 XtRImmediate, (XtPointer)PROTOVER },
1202 { "secondProtocolVersion", "secondProtocolVersion", XtRInt,
1203 sizeof(int), XtOffset(AppDataPtr, secondProtocolVersion),
1204 XtRImmediate, (XtPointer)PROTOVER },
1205 { "showButtonBar", "showButtonBar", XtRBoolean,
1206 sizeof(Boolean), XtOffset(AppDataPtr, showButtonBar),
1207 XtRImmediate, (XtPointer) True },
1208 { "lowTimeWarningColor", "lowTimeWarningColor", XtRString,
1209 sizeof(String), XtOffset(AppDataPtr, lowTimeWarningColor),
1210 XtRString, COLOR_LOWTIMEWARNING },
1211 { "lowTimeWarning", "lowTimeWarning", XtRBoolean,
1212 sizeof(Boolean), XtOffset(AppDataPtr, lowTimeWarning),
1213 XtRImmediate, (XtPointer) False },
1214 {"icsEngineAnalyze", "icsEngineAnalyze", XtRBoolean, /* [DM] icsEngineAnalyze */
1215 sizeof(Boolean), XtOffset(AppDataPtr, icsEngineAnalyze),
1216 XtRImmediate, (XtPointer) False },
1217 { "firstScoreAbs", "firstScoreAbs", XtRBoolean,
1218 sizeof(Boolean), XtOffset(AppDataPtr, firstScoreIsAbsolute),
1219 XtRImmediate, (XtPointer) False },
1220 { "secondScoreAbs", "secondScoreAbs", XtRBoolean,
1221 sizeof(Boolean), XtOffset(AppDataPtr, secondScoreIsAbsolute),
1222 XtRImmediate, (XtPointer) False },
1223 { "pgnExtendedInfo", "pgnExtendedInfo", XtRBoolean,
1224 sizeof(Boolean), XtOffset(AppDataPtr, saveExtendedInfoInPGN),
1225 XtRImmediate, (XtPointer) False },
1226 { "hideThinkingFromHuman", "hideThinkingFromHuman", XtRBoolean,
1227 sizeof(Boolean), XtOffset(AppDataPtr, hideThinkingFromHuman),
1228 XtRImmediate, (XtPointer) True },
1229 { "adjudicateLossThreshold", "adjudicateLossThreshold", XtRInt,
1230 sizeof(int), XtOffset(AppDataPtr, adjudicateLossThreshold),
1231 XtRImmediate, (XtPointer) 0},
1232 { "adjudicateDrawMoves", "adjudicateDrawMoves", XtRInt,
1233 sizeof(int), XtOffset(AppDataPtr, adjudicateDrawMoves),
1234 XtRImmediate, (XtPointer) 0},
1235 { "pgnEventHeader", "pgnEventHeader", XtRString,
1236 sizeof(String), XtOffset(AppDataPtr, pgnEventHeader),
1237 XtRImmediate, (XtPointer) "Computer Chess Game" },
1238 { "defaultFrcPosition", "defaultFrcPositon", XtRInt,
1239 sizeof(int), XtOffset(AppDataPtr, defaultFrcPosition),
1240 XtRImmediate, (XtPointer) -1},
1241 { "gameListTags", "gameListTags", XtRString,
1242 sizeof(String), XtOffset(AppDataPtr, gameListTags),
1243 XtRImmediate, (XtPointer) GLT_DEFAULT_TAGS },
1245 // [HGM] 4.3.xx options
1246 { "boardWidth", "boardWidth", XtRInt,
1247 sizeof(int), XtOffset(AppDataPtr, NrFiles),
1248 XtRImmediate, (XtPointer) -1},
1249 { "boardHeight", "boardHeight", XtRInt,
1250 sizeof(int), XtOffset(AppDataPtr, NrRanks),
1251 XtRImmediate, (XtPointer) -1},
1252 { "matchPause", "matchPause", XtRInt,
1253 sizeof(int), XtOffset(AppDataPtr, matchPause),
1254 XtRImmediate, (XtPointer) 10000},
1255 { "holdingsSize", "holdingsSize", XtRInt,
1256 sizeof(int), XtOffset(AppDataPtr, holdingsSize),
1257 XtRImmediate, (XtPointer) -1},
1258 { "flipBlack", "flipBlack", XtRBoolean,
1259 sizeof(Boolean), XtOffset(AppDataPtr, upsideDown),
1260 XtRImmediate, (XtPointer) False},
1261 { "allWhite", "allWhite", XtRBoolean,
1262 sizeof(Boolean), XtOffset(AppDataPtr, allWhite),
1263 XtRImmediate, (XtPointer) False},
1264 { "pieceToCharTable", "pieceToCharTable", XtRString,
1265 sizeof(String), XtOffset(AppDataPtr, pieceToCharTable),
1266 XtRImmediate, (XtPointer) 0},
1267 { "alphaRank", "alphaRank", XtRBoolean,
1268 sizeof(Boolean), XtOffset(AppDataPtr, alphaRank),
1269 XtRImmediate, (XtPointer) False},
1270 { "testClaims", "testClaims", XtRBoolean,
1271 sizeof(Boolean), XtOffset(AppDataPtr, testClaims),
1272 XtRImmediate, (XtPointer) True},
1273 { "checkMates", "checkMates", XtRBoolean,
1274 sizeof(Boolean), XtOffset(AppDataPtr, checkMates),
1275 XtRImmediate, (XtPointer) True},
1276 { "materialDraws", "materialDraws", XtRBoolean,
1277 sizeof(Boolean), XtOffset(AppDataPtr, materialDraws),
1278 XtRImmediate, (XtPointer) True},
1279 { "trivialDraws", "trivialDraws", XtRBoolean,
1280 sizeof(Boolean), XtOffset(AppDataPtr, trivialDraws),
1281 XtRImmediate, (XtPointer) False},
1282 { "ruleMoves", "ruleMoves", XtRInt,
1283 sizeof(int), XtOffset(AppDataPtr, ruleMoves),
1284 XtRImmediate, (XtPointer) 51},
1285 { "repeatsToDraw", "repeatsToDraw", XtRInt,
1286 sizeof(int), XtOffset(AppDataPtr, drawRepeats),
1287 XtRImmediate, (XtPointer) 6},
1288 { "engineDebugOutput", "engineDebugOutput", XtRInt,
1289 sizeof(int), XtOffset(AppDataPtr, engineComments),
1290 XtRImmediate, (XtPointer) 1},
1291 { "userName", "userName", XtRString,
1292 sizeof(int), XtOffset(AppDataPtr, userName),
1293 XtRImmediate, (XtPointer) 0},
1294 { "autoKibitz", "autoKibitz", XtRBoolean,
1295 sizeof(Boolean), XtOffset(AppDataPtr, autoKibitz),
1296 XtRImmediate, (XtPointer) False},
1297 { "firstTimeOdds", "firstTimeOdds", XtRInt,
1298 sizeof(int), XtOffset(AppDataPtr, firstTimeOdds),
1299 XtRImmediate, (XtPointer) 1},
1300 { "secondTimeOdds", "secondTimeOdds", XtRInt,
1301 sizeof(int), XtOffset(AppDataPtr, secondTimeOdds),
1302 XtRImmediate, (XtPointer) 1},
1303 { "timeOddsMode", "timeOddsMode", XtRInt,
1304 sizeof(int), XtOffset(AppDataPtr, timeOddsMode),
1305 XtRImmediate, (XtPointer) 0},
1306 { "firstAccumulateTC", "firstAccumulateTC", XtRInt,
1307 sizeof(int), XtOffset(AppDataPtr, firstAccumulateTC),
1308 XtRImmediate, (XtPointer) 1},
1309 { "secondAccumulateTC", "secondAccumulateTC", XtRInt,
1310 sizeof(int), XtOffset(AppDataPtr, secondAccumulateTC),
1311 XtRImmediate, (XtPointer) 1},
1312 { "firstNPS", "firstNPS", XtRInt,
1313 sizeof(int), XtOffset(AppDataPtr, firstNPS),
1314 XtRImmediate, (XtPointer) -1},
1315 { "secondNPS", "secondNPS", XtRInt,
1316 sizeof(int), XtOffset(AppDataPtr, secondNPS),
1317 XtRImmediate, (XtPointer) -1},
1318 { "serverMoves", "serverMoves", XtRString,
1319 sizeof(String), XtOffset(AppDataPtr, serverMovesName),
1320 XtRImmediate, (XtPointer) 0},
1321 { "serverPause", "serverPause", XtRInt,
1322 sizeof(int), XtOffset(AppDataPtr, serverPause),
1323 XtRImmediate, (XtPointer) 0},
1324 { "suppressLoadMoves", "suppressLoadMoves", XtRBoolean,
1325 sizeof(Boolean), XtOffset(AppDataPtr, suppressLoadMoves),
1326 XtRImmediate, (XtPointer) False},
1327 { "userName", "userName", XtRString,
1328 sizeof(String), XtOffset(AppDataPtr, userName),
1329 XtRImmediate, (XtPointer) 0},
1330 { "egtFormats", "egtFormats", XtRString,
1331 sizeof(String), XtOffset(AppDataPtr, egtFormats),
1332 XtRImmediate, (XtPointer) 0},
1333 { "rewindIndex", "rewindIndex", XtRInt,
1334 sizeof(int), XtOffset(AppDataPtr, rewindIndex),
1335 XtRImmediate, (XtPointer) 0},
1336 { "sameColorGames", "sameColorGames", XtRInt,
1337 sizeof(int), XtOffset(AppDataPtr, sameColorGames),
1338 XtRImmediate, (XtPointer) 0},
1339 { "smpCores", "smpCores", XtRInt,
1340 sizeof(int), XtOffset(AppDataPtr, smpCores),
1341 XtRImmediate, (XtPointer) 1},
1342 { "niceEngines", "niceEngines", XtRInt,
1343 sizeof(int), XtOffset(AppDataPtr, niceEngines),
1344 XtRImmediate, (XtPointer) 0},
1345 { "nameOfDebugFile", "nameOfDebugFile", XtRString,
1346 sizeof(String), XtOffset(AppDataPtr, nameOfDebugFile),
1347 XtRImmediate, (XtPointer) "xboard.debug"},
1348 { "engineDebugOutput", "engineDebugOutput", XtRInt,
1349 sizeof(int), XtOffset(AppDataPtr, engineComments),
1350 XtRImmediate, (XtPointer) 1},
1351 { "noGUI", "noGUI", XtRBoolean,
1352 sizeof(Boolean), XtOffset(AppDataPtr, noGUI),
1353 XtRImmediate, (XtPointer) 0},
1354 { "firstOptions", "firstOptions", XtRString,
1355 sizeof(String), XtOffset(AppDataPtr, firstOptions),
1356 XtRImmediate, (XtPointer) "" },
1357 { "secondOptions", "secondOptions", XtRString,
1358 sizeof(String), XtOffset(AppDataPtr, secondOptions),
1359 XtRImmediate, (XtPointer) "" },
1360 { "firstNeedsNoncompliantFEN", "firstNeedsNoncompliantFEN", XtRString,
1361 sizeof(String), XtOffset(AppDataPtr, fenOverride1),
1362 XtRImmediate, (XtPointer) 0 },
1363 { "secondNeedsNoncompliantFEN", "secondNeedsNoncompliantFEN", XtRString,
1364 sizeof(String), XtOffset(AppDataPtr, fenOverride2),
1365 XtRImmediate, (XtPointer) 0 },
1367 // [HGM] Winboard_x UCI options
1368 { "firstIsUCI", "firstIsUCI", XtRBoolean,
1369 sizeof(Boolean), XtOffset(AppDataPtr, firstIsUCI),
1370 XtRImmediate, (XtPointer) False},
1371 { "secondIsUCI", "secondIsUCI", XtRBoolean,
1372 sizeof(Boolean), XtOffset(AppDataPtr, secondIsUCI),
1373 XtRImmediate, (XtPointer) False},
1374 { "firstHasOwnBookUCI", "firstHasOwnBookUCI", XtRBoolean,
1375 sizeof(Boolean), XtOffset(AppDataPtr, firstHasOwnBookUCI),
1376 XtRImmediate, (XtPointer) True},
1377 { "secondHasOwnBookUCI", "secondHasOwnBookUCI", XtRBoolean,
1378 sizeof(Boolean), XtOffset(AppDataPtr, secondHasOwnBookUCI),
1379 XtRImmediate, (XtPointer) True},
1380 { "usePolyglotBook", "usePolyglotBook", XtRBoolean,
1381 sizeof(Boolean), XtOffset(AppDataPtr, usePolyglotBook),
1382 XtRImmediate, (XtPointer) False},
1383 { "defaultHashSize", "defaultHashSize", XtRInt,
1384 sizeof(int), XtOffset(AppDataPtr, defaultHashSize),
1385 XtRImmediate, (XtPointer) 64},
1386 { "defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XtRInt,
1387 sizeof(int), XtOffset(AppDataPtr, defaultCacheSizeEGTB),
1388 XtRImmediate, (XtPointer) 4},
1389 { "polyglotDir", "polyglotDir", XtRString,
1390 sizeof(String), XtOffset(AppDataPtr, polyglotDir),
1391 XtRImmediate, (XtPointer) "." },
1392 { "polyglotBook", "polyglotBook", XtRString,
1393 sizeof(String), XtOffset(AppDataPtr, polyglotBook),
1394 XtRImmediate, (XtPointer) "" },
1395 { "defaultPathEGTB", "defaultPathEGTB", XtRString,
1396 sizeof(String), XtOffset(AppDataPtr, defaultPathEGTB),
1397 XtRImmediate, (XtPointer) "/usr/local/share/egtb"},
1398 { "delayBeforeQuit", "delayBeforeQuit", XtRInt,
1399 sizeof(int), XtOffset(AppDataPtr, delayBeforeQuit),
1400 XtRImmediate, (XtPointer) 0},
1401 { "delayAfterQuit", "delayAfterQuit", XtRInt,
1402 sizeof(int), XtOffset(AppDataPtr, delayAfterQuit),
1403 XtRImmediate, (XtPointer) 0},
1404 { "keepAlive", "keepAlive", XtRInt,
1405 sizeof(int), XtOffset(AppDataPtr, keepAlive),
1406 XtRImmediate, (XtPointer) 0},
1407 { "forceIllegalMoves", "forceIllegalMoves", XtRBoolean,
1408 sizeof(Boolean), XtOffset(AppDataPtr, forceIllegal),
1409 XtRImmediate, (XtPointer) False},
1412 XrmOptionDescRec shellOptions[] = {
1413 { "-whitePieceColor", "whitePieceColor", XrmoptionSepArg, NULL },
1414 { "-blackPieceColor", "blackPieceColor", XrmoptionSepArg, NULL },
1415 { "-lightSquareColor", "lightSquareColor", XrmoptionSepArg, NULL },
1416 { "-darkSquareColor", "darkSquareColor", XrmoptionSepArg, NULL },
1417 { "-highlightSquareColor", "highlightSquareColor", XrmoptionSepArg, NULL },
1418 { "-premoveHighlightColor", "premoveHighlightColor", XrmoptionSepArg,NULL},
1419 { "-movesPerSession", "movesPerSession", XrmoptionSepArg, NULL },
1420 { "-mps", "movesPerSession", XrmoptionSepArg, NULL },
1421 { "-timeIncrement", "timeIncrement", XrmoptionSepArg, NULL },
1422 { "-inc", "timeIncrement", XrmoptionSepArg, NULL },
1423 { "-initString", "initString", XrmoptionSepArg, NULL },
1424 { "-firstInitString", "initString", XrmoptionSepArg, NULL },
1425 { "-secondInitString", "secondInitString", XrmoptionSepArg, NULL },
1426 { "-firstComputerString", "firstComputerString", XrmoptionSepArg, NULL },
1427 { "-secondComputerString", "secondComputerString", XrmoptionSepArg, NULL },
1428 { "-firstChessProgram", "firstChessProgram", XrmoptionSepArg, NULL },
1429 { "-fcp", "firstChessProgram", XrmoptionSepArg, NULL },
1430 { "-secondChessProgram", "secondChessProgram", XrmoptionSepArg, NULL },
1431 { "-scp", "secondChessProgram", XrmoptionSepArg, NULL },
1432 { "-firstPlaysBlack", "firstPlaysBlack", XrmoptionSepArg, NULL },
1433 { "-fb", "firstPlaysBlack", XrmoptionNoArg, "True" },
1434 { "-xfb", "firstPlaysBlack", XrmoptionNoArg, "False" },
1435 { "-noChessProgram", "noChessProgram", XrmoptionSepArg, NULL },
1436 { "-ncp", "noChessProgram", XrmoptionNoArg, "True" },
1437 { "-xncp", "noChessProgram", XrmoptionNoArg, "False" },
1438 { "-firstHost", "firstHost", XrmoptionSepArg, NULL },
1439 { "-fh", "firstHost", XrmoptionSepArg, NULL },
1440 { "-secondHost", "secondHost", XrmoptionSepArg, NULL },
1441 { "-sh", "secondHost", XrmoptionSepArg, NULL },
1442 { "-firstDirectory", "firstDirectory", XrmoptionSepArg, NULL },
1443 { "-fd", "firstDirectory", XrmoptionSepArg, NULL },
1444 { "-secondDirectory", "secondDirectory", XrmoptionSepArg, NULL },
1445 { "-sd", "secondDirectory", XrmoptionSepArg, NULL },
1446 { "-bitmapDirectory", "bitmapDirectory", XrmoptionSepArg, NULL },
1447 { "-bm", "bitmapDirectory", XrmoptionSepArg, NULL },
1448 { "-remoteShell", "remoteShell", XrmoptionSepArg, NULL },
1449 { "-rsh", "remoteShell", XrmoptionSepArg, NULL },
1450 { "-remoteUser", "remoteUser", XrmoptionSepArg, NULL },
1451 { "-ruser", "remoteUser", XrmoptionSepArg, NULL },
1452 { "-timeDelay", "timeDelay", XrmoptionSepArg, NULL },
1453 { "-td", "timeDelay", XrmoptionSepArg, NULL },
1454 { "-timeControl", "timeControl", XrmoptionSepArg, NULL },
1455 { "-tc", "timeControl", XrmoptionSepArg, NULL },
1456 { "-internetChessServerMode", "internetChessServerMode",
1457 XrmoptionSepArg, NULL },
1458 { "-ics", "internetChessServerMode", XrmoptionNoArg, "True" },
1459 { "-xics", "internetChessServerMode", XrmoptionNoArg, "False" },
1460 { "-internetChessServerHost", "internetChessServerHost",
1461 XrmoptionSepArg, NULL },
1462 { "-icshost", "internetChessServerHost", XrmoptionSepArg, NULL },
1463 { "-internetChessServerPort", "internetChessServerPort",
1464 XrmoptionSepArg, NULL },
1465 { "-icsport", "internetChessServerPort", XrmoptionSepArg, NULL },
1466 { "-internetChessServerCommPort", "internetChessServerCommPort",
1467 XrmoptionSepArg, NULL },
1468 { "-icscomm", "internetChessServerCommPort", XrmoptionSepArg, NULL },
1469 { "-internetChessServerLogonScript", "internetChessServerLogonScript",
1470 XrmoptionSepArg, NULL },
1471 { "-icslogon", "internetChessServerLogonScript", XrmoptionSepArg, NULL },
1472 { "-internetChessServerHelper", "internetChessServerHelper",
1473 XrmoptionSepArg, NULL },
1474 { "-icshelper", "internetChessServerHelper", XrmoptionSepArg, NULL },
1475 { "-internetChessServerInputBox", "internetChessServerInputBox",
1476 XrmoptionSepArg, NULL },
1477 { "-icsinput", "internetChessServerInputBox", XrmoptionNoArg, "True" },
1478 { "-xicsinput", "internetChessServerInputBox", XrmoptionNoArg, "False" },
1479 { "-icsAlarm", "icsAlarm", XrmoptionSepArg, NULL },
1480 { "-alarm", "icsAlarm", XrmoptionNoArg, "True" },
1481 { "-xalarm", "icsAlarm", XrmoptionNoArg, "False" },
1482 { "-icsAlarmTime", "icsAlarmTime", XrmoptionSepArg, NULL },
1483 { "-useTelnet", "useTelnet", XrmoptionSepArg, NULL },
1484 { "-telnet", "useTelnet", XrmoptionNoArg, "True" },
1485 { "-xtelnet", "useTelnet", XrmoptionNoArg, "False" },
1486 { "-telnetProgram", "telnetProgram", XrmoptionSepArg, NULL },
1487 { "-gateway", "gateway", XrmoptionSepArg, NULL },
1488 { "-loadGameFile", "loadGameFile", XrmoptionSepArg, NULL },
1489 { "-lgf", "loadGameFile", XrmoptionSepArg, NULL },
1490 { "-loadGameIndex", "loadGameIndex", XrmoptionSepArg, NULL },
1491 { "-lgi", "loadGameIndex", XrmoptionSepArg, NULL },
1492 { "-saveGameFile", "saveGameFile", XrmoptionSepArg, NULL },
1493 { "-sgf", "saveGameFile", XrmoptionSepArg, NULL },
1494 { "-autoSaveGames", "autoSaveGames", XrmoptionSepArg, NULL },
1495 { "-autosave", "autoSaveGames", XrmoptionNoArg, "True" },
1496 { "-xautosave", "autoSaveGames", XrmoptionNoArg, "False" },
1497 { "-autoRaiseBoard", "autoRaiseBoard", XrmoptionSepArg, NULL },
1498 { "-autoraise", "autoRaiseBoard", XrmoptionNoArg, "True" },
1499 { "-xautoraise", "autoRaiseBoard", XrmoptionNoArg, "False" },
1500 { "-blindfold", "blindfold", XrmoptionSepArg, NULL },
1501 { "-blind", "blindfold", XrmoptionNoArg, "True" },
1502 { "-xblind", "blindfold", XrmoptionNoArg, "False" },
1503 { "-loadPositionFile", "loadPositionFile", XrmoptionSepArg, NULL },
1504 { "-lpf", "loadPositionFile", XrmoptionSepArg, NULL },
1505 { "-loadPositionIndex", "loadPositionIndex", XrmoptionSepArg, NULL },
1506 { "-lpi", "loadPositionIndex", XrmoptionSepArg, NULL },
1507 { "-savePositionFile", "savePositionFile", XrmoptionSepArg, NULL },
1508 { "-spf", "savePositionFile", XrmoptionSepArg, NULL },
1509 { "-matchMode", "matchMode", XrmoptionSepArg, NULL },
1510 { "-mm", "matchMode", XrmoptionNoArg, "True" },
1511 { "-xmm", "matchMode", XrmoptionNoArg, "False" },
1512 { "-matchGames", "matchGames", XrmoptionSepArg, NULL },
1513 { "-mg", "matchGames", XrmoptionSepArg, NULL },
1514 { "-monoMode", "monoMode", XrmoptionSepArg, NULL },
1515 { "-mono", "monoMode", XrmoptionNoArg, "True" },
1516 { "-xmono", "monoMode", XrmoptionNoArg, "False" },
1517 { "-debugMode", "debugMode", XrmoptionSepArg, NULL },
1518 { "-debug", "debugMode", XrmoptionNoArg, "True" },
1519 { "-xdebug", "debugMode", XrmoptionNoArg, "False" },
1520 { "-clockMode", "clockMode", XrmoptionSepArg, NULL },
1521 { "-clock", "clockMode", XrmoptionNoArg, "True" },
1522 { "-xclock", "clockMode", XrmoptionNoArg, "False" },
1523 { "-boardSize", "boardSize", XrmoptionSepArg, NULL },
1524 { "-size", "boardSize", XrmoptionSepArg, NULL },
1525 { "-searchTime", "searchTime", XrmoptionSepArg, NULL },
1526 { "-st", "searchTime", XrmoptionSepArg, NULL },
1527 { "-searchDepth", "searchDepth", XrmoptionSepArg, NULL },
1528 { "-depth", "searchDepth", XrmoptionSepArg, NULL },
1529 { "-showCoords", "showCoords", XrmoptionSepArg, NULL },
1530 { "-coords", "showCoords", XrmoptionNoArg, "True" },
1531 { "-xcoords", "showCoords", XrmoptionNoArg, "False" },
1533 { "-showJail", "showJail", XrmoptionSepArg, NULL },
1534 { "-jail", "showJail", XrmoptionNoArg, "1" },
1535 { "-sidejail", "showJail", XrmoptionNoArg, "2" },
1536 { "-xjail", "showJail", XrmoptionNoArg, "0" },
1538 { "-showThinking", "showThinking", XrmoptionSepArg, NULL },
1539 { "-thinking", "showThinking", XrmoptionNoArg, "True" },
1540 { "-xthinking", "showThinking", XrmoptionNoArg, "False" },
1541 { "-ponderNextMove", "ponderNextMove", XrmoptionSepArg, NULL },
1542 { "-ponder", "ponderNextMove", XrmoptionNoArg, "True" },
1543 { "-xponder", "ponderNextMove", XrmoptionNoArg, "False" },
1544 { "-periodicUpdates", "periodicUpdates", XrmoptionSepArg, NULL },
1545 { "-periodic", "periodicUpdates", XrmoptionNoArg, "True" },
1546 { "-xperiodic", "periodicUpdates", XrmoptionNoArg, "False" },
1547 { "-clockFont", "clockFont", XrmoptionSepArg, NULL },
1548 { "-coordFont", "coordFont", XrmoptionSepArg, NULL },
1549 { "-font", "font", XrmoptionSepArg, NULL },
1550 { "-ringBellAfterMoves", "ringBellAfterMoves", XrmoptionSepArg, NULL },
1551 { "-bell", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1552 { "-xbell", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1553 { "-movesound", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1554 { "-xmovesound", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1555 { "-autoCallFlag", "autoCallFlag", XrmoptionSepArg, NULL },
1556 { "-autoflag", "autoCallFlag", XrmoptionNoArg, "True" },
1557 { "-xautoflag", "autoCallFlag", XrmoptionNoArg, "False" },
1558 { "-autoFlipView", "autoFlipView", XrmoptionSepArg, NULL },
1559 { "-autoflip", "autoFlipView", XrmoptionNoArg, "True" },
1560 { "-xautoflip", "autoFlipView", XrmoptionNoArg, "False" },
1561 { "-autoObserve", "autoObserve", XrmoptionSepArg, NULL },
1562 { "-autobs", "autoObserve", XrmoptionNoArg, "True" },
1563 { "-xautobs", "autoObserve", XrmoptionNoArg, "False" },
1564 { "-autoComment", "autoComment", XrmoptionSepArg, NULL },
1565 { "-autocomm", "autoComment", XrmoptionNoArg, "True" },
1566 { "-xautocomm", "autoComment", XrmoptionNoArg, "False" },
1567 { "-getMoveList", "getMoveList", XrmoptionSepArg, NULL },
1568 { "-moves", "getMoveList", XrmoptionNoArg, "True" },
1569 { "-xmoves", "getMoveList", XrmoptionNoArg, "False" },
1571 { "-highlightDragging", "highlightDragging", XrmoptionSepArg, NULL },
1572 { "-highdrag", "highlightDragging", XrmoptionNoArg, "True" },
1573 { "-xhighdrag", "highlightDragging", XrmoptionNoArg, "False" },
1575 { "-highlightLastMove", "highlightLastMove", XrmoptionSepArg, NULL },
1576 { "-highlight", "highlightLastMove", XrmoptionNoArg, "True" },
1577 { "-xhighlight", "highlightLastMove", XrmoptionNoArg, "False" },
1578 { "-premove", "premove", XrmoptionSepArg, NULL },
1579 { "-pre", "premove", XrmoptionNoArg, "True" },
1580 { "-xpre", "premove", XrmoptionNoArg, "False" },
1581 { "-testLegality", "testLegality", XrmoptionSepArg, NULL },
1582 { "-legal", "testLegality", XrmoptionNoArg, "True" },
1583 { "-xlegal", "testLegality", XrmoptionNoArg, "False" },
1584 { "-flipView", "flipView", XrmoptionSepArg, NULL },
1585 { "-flip", "flipView", XrmoptionNoArg, "True" },
1586 { "-xflip", "flipView", XrmoptionNoArg, "False" },
1587 { "-cmail", "cmailGameName", XrmoptionSepArg, NULL },
1588 { "-alwaysPromoteToQueen", "alwaysPromoteToQueen",
1589 XrmoptionSepArg, NULL },
1590 { "-queen", "alwaysPromoteToQueen", XrmoptionNoArg, "True" },
1591 { "-xqueen", "alwaysPromoteToQueen", XrmoptionNoArg, "False" },
1592 { "-oldSaveStyle", "oldSaveStyle", XrmoptionSepArg, NULL },
1593 { "-oldsave", "oldSaveStyle", XrmoptionNoArg, "True" },
1594 { "-xoldsave", "oldSaveStyle", XrmoptionNoArg, "False" },
1595 { "-quietPlay", "quietPlay", XrmoptionSepArg, NULL },
1596 { "-quiet", "quietPlay", XrmoptionNoArg, "True" },
1597 { "-xquiet", "quietPlay", XrmoptionNoArg, "False" },
1598 { "-titleInWindow", "titleInWindow", XrmoptionSepArg, NULL },
1599 { "-title", "titleInWindow", XrmoptionNoArg, "True" },
1600 { "-xtitle", "titleInWindow", XrmoptionNoArg, "False" },
1602 { "-zippyTalk", "zippyTalk", XrmoptionSepArg, NULL },
1603 { "-zt", "zippyTalk", XrmoptionNoArg, "True" },
1604 { "-xzt", "zippyTalk", XrmoptionNoArg, "False" },
1605 { "-zippyPlay", "zippyPlay", XrmoptionSepArg, NULL },
1606 { "-zp", "zippyPlay", XrmoptionNoArg, "True" },
1607 { "-xzp", "zippyPlay", XrmoptionNoArg, "False" },
1608 { "-zippyLines", "zippyLines", XrmoptionSepArg, NULL },
1609 { "-zippyPinhead", "zippyPinhead", XrmoptionSepArg, NULL },
1610 { "-zippyPassword", "zippyPassword", XrmoptionSepArg, NULL },
1611 { "-zippyPassword2", "zippyPassword2", XrmoptionSepArg, NULL },
1612 { "-zippyWrongPassword", "zippyWrongPassword", XrmoptionSepArg, NULL },
1613 { "-zippyAcceptOnly", "zippyAcceptOnly", XrmoptionSepArg, NULL },
1614 { "-zippyUseI", "zippyUseI", XrmoptionSepArg, NULL },
1615 { "-zui", "zippyUseI", XrmoptionNoArg, "True" },
1616 { "-xzui", "zippyUseI", XrmoptionNoArg, "False" },
1617 { "-zippyBughouse", "zippyBughouse", XrmoptionSepArg, NULL },
1618 { "-zippyNoplayCrafty", "zippyNoplayCrafty", XrmoptionSepArg, NULL },
1619 { "-znc", "zippyNoplayCrafty", XrmoptionNoArg, "True" },
1620 { "-xznc", "zippyNoplayCrafty", XrmoptionNoArg, "False" },
1621 { "-zippyGameEnd", "zippyGameEnd", XrmoptionSepArg, NULL },
1622 { "-zippyGameStart", "zippyGameStart", XrmoptionSepArg, NULL },
1623 { "-zippyAdjourn", "zippyAdjourn", XrmoptionSepArg, NULL },
1624 { "-zadj", "zippyAdjourn", XrmoptionNoArg, "True" },
1625 { "-xzadj", "zippyAdjourn", XrmoptionNoArg, "False" },
1626 { "-zippyAbort", "zippyAbort", XrmoptionSepArg, NULL },
1627 { "-zab", "zippyAbort", XrmoptionNoArg, "True" },
1628 { "-xzab", "zippyAbort", XrmoptionNoArg, "False" },
1629 { "-zippyVariants", "zippyVariants", XrmoptionSepArg, NULL },
1630 { "-zippyMaxGames", "zippyMaxGames", XrmoptionSepArg, NULL },
1631 { "-zippyReplayTimeout", "zippyReplayTimeout", XrmoptionSepArg, NULL },
1632 { "-zippyShortGame", "zippyShortGame", XrmoptionSepArg, NULL },
1634 { "-flashCount", "flashCount", XrmoptionSepArg, NULL },
1635 { "-flash", "flashCount", XrmoptionNoArg, "3" },
1636 { "-xflash", "flashCount", XrmoptionNoArg, "0" },
1637 { "-flashRate", "flashRate", XrmoptionSepArg, NULL },
1638 { "-pixmapDirectory", "pixmapDirectory", XrmoptionSepArg, NULL },
1639 { "-msLoginDelay", "msLoginDelay", XrmoptionSepArg, NULL },
1640 { "-pixmap", "pixmapDirectory", XrmoptionSepArg, NULL },
1641 { "-colorizeMessages", "colorizeMessages", XrmoptionSepArg, NULL },
1642 { "-colorize", "colorizeMessages", XrmoptionNoArg, "True" },
1643 { "-xcolorize", "colorizeMessages", XrmoptionNoArg, "False" },
1644 { "-colorShout", "colorShout", XrmoptionSepArg, NULL },
1645 { "-colorSShout", "colorSShout", XrmoptionSepArg, NULL },
1646 { "-colorCShout", "colorSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1647 { "-colorChannel1", "colorChannel1", XrmoptionSepArg, NULL },
1648 { "-colorChannel", "colorChannel", XrmoptionSepArg, NULL },
1649 { "-colorKibitz", "colorKibitz", XrmoptionSepArg, NULL },
1650 { "-colorTell", "colorTell", XrmoptionSepArg, NULL },
1651 { "-colorChallenge", "colorChallenge", XrmoptionSepArg, NULL },
1652 { "-colorRequest", "colorRequest", XrmoptionSepArg, NULL },
1653 { "-colorSeek", "colorSeek", XrmoptionSepArg, NULL },
1654 { "-colorNormal", "colorNormal", XrmoptionSepArg, NULL },
1655 { "-soundProgram", "soundProgram", XrmoptionSepArg, NULL },
1656 { "-soundShout", "soundShout", XrmoptionSepArg, NULL },
1657 { "-soundSShout", "soundSShout", XrmoptionSepArg, NULL },
1658 { "-soundCShout", "soundSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1659 { "-soundChannel1", "soundChannel1", XrmoptionSepArg, NULL },
1660 { "-soundChannel", "soundChannel", XrmoptionSepArg, NULL },
1661 { "-soundKibitz", "soundKibitz", XrmoptionSepArg, NULL },
1662 { "-soundTell", "soundTell", XrmoptionSepArg, NULL },
1663 { "-soundChallenge", "soundChallenge", XrmoptionSepArg, NULL },
1664 { "-soundRequest", "soundRequest", XrmoptionSepArg, NULL },
1665 { "-soundSeek", "soundSeek", XrmoptionSepArg, NULL },
1666 { "-soundMove", "soundMove", XrmoptionSepArg, NULL },
1667 { "-soundIcsWin", "soundIcsWin", XrmoptionSepArg, NULL },
1668 { "-soundIcsLoss", "soundIcsLoss", XrmoptionSepArg, NULL },
1669 { "-soundIcsDraw", "soundIcsDraw", XrmoptionSepArg, NULL },
1670 { "-soundIcsUnfinished", "soundIcsUnfinished", XrmoptionSepArg, NULL },
1671 { "-soundIcsAlarm", "soundIcsAlarm", XrmoptionSepArg, NULL },
1672 { "-reuseFirst", "reuseFirst", XrmoptionSepArg, NULL },
1673 { "-reuseChessPrograms", "reuseFirst", XrmoptionSepArg, NULL }, /*compat*/
1674 { "-reuse", "reuseFirst", XrmoptionNoArg, "True" },
1675 { "-xreuse", "reuseFirst", XrmoptionNoArg, "False" },
1676 { "-reuseSecond", "reuseSecond", XrmoptionSepArg, NULL },
1677 { "-reuse2", "reuseSecond", XrmoptionNoArg, "True" },
1678 { "-xreuse2", "reuseSecond", XrmoptionNoArg, "False" },
1679 { "-animateMoving", "animateMoving", XrmoptionSepArg, NULL },
1680 { "-animate", "animateMoving", XrmoptionNoArg, "True" },
1681 { "-xanimate", "animateMoving", XrmoptionNoArg, "False" },
1682 { "-animateDragging", "animateDragging", XrmoptionSepArg, NULL },
1683 { "-drag", "animateDragging", XrmoptionNoArg, "True" },
1684 { "-xdrag", "animateDragging", XrmoptionNoArg, "False" },
1685 { "-animateSpeed", "animateSpeed", XrmoptionSepArg, NULL },
1686 { "-popupExitMessage", "popupExitMessage", XrmoptionSepArg, NULL },
1687 { "-exit", "popupExitMessage", XrmoptionNoArg, "True" },
1688 { "-xexit", "popupExitMessage", XrmoptionNoArg, "False" },
1689 { "-popupMoveErrors", "popupMoveErrors", XrmoptionSepArg, NULL },
1690 { "-popup", "popupMoveErrors", XrmoptionNoArg, "True" },
1691 { "-xpopup", "popupMoveErrors", XrmoptionNoArg, "False" },
1692 { "-fontSizeTolerance", "fontSizeTolerance", XrmoptionSepArg, NULL },
1693 { "-initialMode", "initialMode", XrmoptionSepArg, NULL },
1694 { "-mode", "initialMode", XrmoptionSepArg, NULL },
1695 { "-variant", "variant", XrmoptionSepArg, NULL },
1696 { "-firstProtocolVersion", "firstProtocolVersion", XrmoptionSepArg, NULL },
1697 { "-secondProtocolVersion","secondProtocolVersion",XrmoptionSepArg, NULL },
1698 { "-showButtonBar", "showButtonBar", XrmoptionSepArg, NULL },
1699 { "-buttons", "showButtonBar", XrmoptionNoArg, "True" },
1700 { "-xbuttons", "showButtonBar", XrmoptionNoArg, "False" },
1701 { "-lowTimeWarningColor", "lowTimeWarningColor", XrmoptionSepArg, NULL },
1702 { "-lowTimeWarning", "lowTimeWarning", XrmoptionSepArg, NULL },
1703 /* [AS,HR] New features */
1704 { "-firstScoreAbs", "firstScoreAbs", XrmoptionSepArg, NULL },
1705 { "-secondScoreAbs", "secondScoreAbs", XrmoptionSepArg, NULL },
1706 { "-pgnExtendedInfo", "pgnExtendedInfo", XrmoptionSepArg, NULL },
1707 { "-hideThinkingFromHuman", "hideThinkingFromHuman", XrmoptionSepArg, NULL },
1708 { "-adjudicateLossThreshold", "adjudicateLossThreshold", XrmoptionSepArg, NULL },
1709 { "-adjudicateDrawMoves", "adjudicateDrawMoves", XrmoptionSepArg, NULL },
1710 { "-pgnEventHeader", "pgnEventHeader", XrmoptionSepArg, NULL },
1711 { "-firstIsUCI", "firstIsUCI", XrmoptionSepArg, NULL },
1712 { "-secondIsUCI", "secondIsUCI", XrmoptionSepArg, NULL },
1713 { "-fUCI", "firstIsUCI", XrmoptionNoArg, "True" },
1714 { "-sUCI", "secondIsUCI", XrmoptionNoArg, "True" },
1715 { "-firstHasOwnBookUCI", "firstHasOwnBookUCI", XrmoptionSepArg, NULL },
1716 { "-secondHasOwnBookUCI", "secondHasOwnBookUCI", XrmoptionSepArg, NULL },
1717 { "-fNoOwnBookUCI", "firstHasOwnBookUCI", XrmoptionNoArg, "False" },
1718 { "-sNoOwnBookUCI", "secondHasOwnBookUCI", XrmoptionNoArg, "False" },
1719 { "-firstXBook", "firstHasOwnBookUCI", XrmoptionNoArg, "False" },
1720 { "-secondXBook", "secondHasOwnBookUCI", XrmoptionNoArg, "False" },
1721 { "-polyglotDir", "polyglotDir", XrmoptionSepArg, NULL },
1722 { "-usePolyglotBook", "usePolyglotBook", XrmoptionSepArg, NULL },
1723 { "-polyglotBook", "polyglotBook", XrmoptionSepArg, NULL },
1724 { "-defaultHashSize", "defaultHashSize", XrmoptionSepArg, NULL },
1725 { "-defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XrmoptionSepArg, NULL },
1726 { "-defaultPathEGTB", "defaultPathEGTB", XrmoptionSepArg, NULL },
1727 { "-defaultFrcPosition", "defaultFrcPosition", XrmoptionSepArg, NULL },
1728 { "-gameListTags", "gameListTags", XrmoptionSepArg, NULL },
1729 // [HGM] I am sure AS added many more options, but we have to fish them out, from the list in winboard.c
1731 /* [HGM,HR] User-selectable board size */
1732 { "-boardWidth", "boardWidth", XrmoptionSepArg, NULL },
1733 { "-boardHeight", "boardHeight", XrmoptionSepArg, NULL },
1734 { "-matchPause", "matchPause", XrmoptionSepArg, NULL },
1736 /* [HGM] new arguments of 4.3.xx. All except first three are back-end options, which should work immediately */
1737 { "-holdingsSize", "holdingsSize", XrmoptionSepArg, NULL }, // requires extensive front-end changes to work
1738 { "-flipBlack", "flipBlack", XrmoptionSepArg, NULL }, // requires front-end changes to work
1739 { "-allWhite", "allWhite", XrmoptionSepArg, NULL }, // requires front-end changes to work
1740 { "-pieceToCharTable", "pieceToCharTable", XrmoptionSepArg, NULL },
1741 { "-alphaRank", "alphaRank", XrmoptionSepArg, NULL },
1742 { "-testClaims", "testClaims", XrmoptionSepArg, NULL },
1743 { "-checkMates", "checkMates", XrmoptionSepArg, NULL },
1744 { "-materialDraws", "materialDraws", XrmoptionSepArg, NULL },
1745 { "-trivialDraws", "trivialDraws", XrmoptionSepArg, NULL },
1746 { "-ruleMoves", "ruleMoves", XrmoptionSepArg, NULL },
1747 { "-repeatsToDraw", "repeatsToDraw", XrmoptionSepArg, NULL },
1748 { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL },
1749 { "-userName", "userName", XrmoptionSepArg, NULL },
1750 { "-autoKibitz", "autoKibitz", XrmoptionNoArg, "True" },
1751 { "-firstTimeOdds", "firstTimeOdds", XrmoptionSepArg, NULL },
1752 { "-secondTimeOdds", "secondTimeOdds", XrmoptionSepArg, NULL },
1753 { "-timeOddsMode", "timeOddsMode", XrmoptionSepArg, NULL },
1754 { "-firstAccumulateTC", "firstAccumulateTC", XrmoptionSepArg, NULL },
1755 { "-secondAccumulateTC", "secondAccumulateTC", XrmoptionSepArg, NULL },
1756 { "-firstNPS", "firstNPS", XrmoptionSepArg, NULL },
1757 { "-secondNPS", "secondNPS", XrmoptionSepArg, NULL },
1758 { "-serverMoves", "serverMoves", XrmoptionSepArg, NULL },
1759 { "-serverPause", "serverPause", XrmoptionSepArg, NULL },
1760 { "-suppressLoadMoves", "suppressLoadMoves", XrmoptionSepArg, NULL },
1761 { "-egtFormats", "egtFormats", XrmoptionSepArg, NULL },
1762 { "-userName", "userName", XrmoptionSepArg, NULL },
1763 { "-smpCores", "smpCores", XrmoptionSepArg, NULL },
1764 { "-sameColorGames", "sameColorGames", XrmoptionSepArg, NULL },
1765 { "-rewindIndex", "rewindIndex", XrmoptionSepArg, NULL },
1766 { "-niceEngines", "niceEngines", XrmoptionSepArg, NULL },
1767 { "-delayBeforeQuit", "delayBeforeQuit", XrmoptionSepArg, NULL },
1768 { "-delayAfterQuit", "delayAfterQuit", XrmoptionSepArg, NULL },
1769 { "-nameOfDebugFile", "nameOfDebugFile", XrmoptionSepArg, NULL },
1770 { "-debugFile", "nameOfDebugFile", XrmoptionSepArg, NULL },
1771 { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL },
1772 { "-noGUI", "noGUI", XrmoptionNoArg, "True" },
1773 { "-firstOptions", "firstOptions", XrmoptionSepArg, NULL },
1774 { "-secondOptions", "secondOptions", XrmoptionSepArg, NULL },
1775 { "-firstNeedsNoncompliantFEN", "firstNeedsNoncompliantFEN", XrmoptionSepArg, NULL },
1776 { "-secondNeedsNoncompliantFEN", "secondNeedsNoncompliantFEN", XrmoptionSepArg, NULL },
1777 { "-keepAlive", "keepAlive", XrmoptionSepArg, NULL },
1778 { "-forceIllegalMoves", "forceIllegalMoves", XrmoptionNoArg, "True" },
1782 XtActionsRec boardActions[] = {
1783 { "DrawPosition", DrawPositionProc },
1784 { "HandleUserMove", HandleUserMove },
1785 { "AnimateUserMove", AnimateUserMove },
1786 { "FileNameAction", FileNameAction },
1787 { "AskQuestionProc", AskQuestionProc },
1788 { "AskQuestionReplyAction", AskQuestionReplyAction },
1789 { "PieceMenuPopup", PieceMenuPopup },
1790 { "WhiteClock", WhiteClock },
1791 { "BlackClock", BlackClock },
1792 { "Iconify", Iconify },
1793 { "ResetProc", ResetProc },
1794 { "LoadGameProc", LoadGameProc },
1795 { "LoadNextGameProc", LoadNextGameProc },
1796 { "LoadPrevGameProc", LoadPrevGameProc },
1797 { "LoadSelectedProc", LoadSelectedProc },
1798 { "ReloadGameProc", ReloadGameProc },
1799 { "LoadPositionProc", LoadPositionProc },
1800 { "LoadNextPositionProc", LoadNextPositionProc },
1801 { "LoadPrevPositionProc", LoadPrevPositionProc },
1802 { "ReloadPositionProc", ReloadPositionProc },
1803 { "CopyPositionProc", CopyPositionProc },
1804 { "PastePositionProc", PastePositionProc },
1805 { "CopyGameProc", CopyGameProc },
1806 { "PasteGameProc", PasteGameProc },
1807 { "SaveGameProc", SaveGameProc },
1808 { "SavePositionProc", SavePositionProc },
1809 { "MailMoveProc", MailMoveProc },
1810 { "ReloadCmailMsgProc", ReloadCmailMsgProc },
1811 { "QuitProc", QuitProc },
1812 { "MachineWhiteProc", MachineWhiteProc },
1813 { "MachineBlackProc", MachineBlackProc },
1814 { "AnalysisModeProc", AnalyzeModeProc },
1815 { "AnalyzeFileProc", AnalyzeFileProc },
1816 { "TwoMachinesProc", TwoMachinesProc },
1817 { "IcsClientProc", IcsClientProc },
1818 { "EditGameProc", EditGameProc },
1819 { "EditPositionProc", EditPositionProc },
1820 { "TrainingProc", EditPositionProc },
1821 { "EngineOutputProc", EngineOutputProc}, // [HGM] Winboard_x engine-output window
1822 { "ShowGameListProc", ShowGameListProc },
1823 { "ShowMoveListProc", HistoryShowProc},
1824 { "EditTagsProc", EditCommentProc },
1825 { "EditCommentProc", EditCommentProc },
1826 { "IcsAlarmProc", IcsAlarmProc },
1827 { "IcsInputBoxProc", IcsInputBoxProc },
1828 { "PauseProc", PauseProc },
1829 { "AcceptProc", AcceptProc },
1830 { "DeclineProc", DeclineProc },
1831 { "RematchProc", RematchProc },
1832 { "CallFlagProc", CallFlagProc },
1833 { "DrawProc", DrawProc },
1834 { "AdjournProc", AdjournProc },
1835 { "AbortProc", AbortProc },
1836 { "ResignProc", ResignProc },
1837 { "AdjuWhiteProc", AdjuWhiteProc },
1838 { "AdjuBlackProc", AdjuBlackProc },
1839 { "AdjuDrawProc", AdjuDrawProc },
1840 { "EnterKeyProc", EnterKeyProc },
1841 { "StopObservingProc", StopObservingProc },
1842 { "StopExaminingProc", StopExaminingProc },
1843 { "BackwardProc", BackwardProc },
1844 { "ForwardProc", ForwardProc },
1845 { "ToStartProc", ToStartProc },
1846 { "ToEndProc", ToEndProc },
1847 { "RevertProc", RevertProc },
1848 { "TruncateGameProc", TruncateGameProc },
1849 { "MoveNowProc", MoveNowProc },
1850 { "RetractMoveProc", RetractMoveProc },
1851 { "AlwaysQueenProc", AlwaysQueenProc },
1852 { "AnimateDraggingProc", AnimateDraggingProc },
1853 { "AnimateMovingProc", AnimateMovingProc },
1854 { "AutoflagProc", AutoflagProc },
1855 { "AutoflipProc", AutoflipProc },
1856 { "AutobsProc", AutobsProc },
1857 { "AutoraiseProc", AutoraiseProc },
1858 { "AutosaveProc", AutosaveProc },
1859 { "BlindfoldProc", BlindfoldProc },
1860 { "FlashMovesProc", FlashMovesProc },
1861 { "FlipViewProc", FlipViewProc },
1862 { "GetMoveListProc", GetMoveListProc },
1864 { "HighlightDraggingProc", HighlightDraggingProc },
1866 { "HighlightLastMoveProc", HighlightLastMoveProc },
1867 { "IcsAlarmProc", IcsAlarmProc },
1868 { "MoveSoundProc", MoveSoundProc },
1869 { "OldSaveStyleProc", OldSaveStyleProc },
1870 { "PeriodicUpdatesProc", PeriodicUpdatesProc },
1871 { "PonderNextMoveProc", PonderNextMoveProc },
1872 { "PopupExitMessageProc", PopupExitMessageProc },
1873 { "PopupMoveErrorsProc", PopupMoveErrorsProc },
1874 { "PremoveProc", PremoveProc },
1875 { "QuietPlayProc", QuietPlayProc },
1876 { "ShowCoordsProc", ShowCoordsProc },
1877 { "ShowThinkingProc", ShowThinkingProc },
1878 { "HideThinkingProc", HideThinkingProc },
1879 { "TestLegalityProc", TestLegalityProc },
1880 { "InfoProc", InfoProc },
1881 { "ManProc", ManProc },
1882 { "HintProc", HintProc },
1883 { "BookProc", BookProc },
1884 { "AboutGameProc", AboutGameProc },
1885 { "AboutProc", AboutProc },
1886 { "DebugProc", DebugProc },
1887 { "NothingProc", NothingProc },
1888 { "CommentPopDown", (XtActionProc) CommentPopDown },
1889 { "EditCommentPopDown", (XtActionProc) EditCommentPopDown },
1890 { "TagsPopDown", (XtActionProc) TagsPopDown },
1891 { "ErrorPopDown", (XtActionProc) ErrorPopDown },
1892 { "ICSInputBoxPopDown", (XtActionProc) ICSInputBoxPopDown },
1893 { "AnalysisPopDown", (XtActionProc) AnalysisPopDown },
1894 { "FileNamePopDown", (XtActionProc) FileNamePopDown },
1895 { "AskQuestionPopDown", (XtActionProc) AskQuestionPopDown },
1896 { "GameListPopDown", (XtActionProc) GameListPopDown },
1897 { "PromotionPopDown", (XtActionProc) PromotionPopDown },
1898 { "HistoryPopDown", (XtActionProc) HistoryPopDown },
1899 { "EngineOutputPopDown", (XtActionProc) EngineOutputPopDown },
1900 { "ShufflePopDown", (XtActionProc) ShufflePopDown },
1901 { "EnginePopDown", (XtActionProc) EnginePopDown },
1902 { "UciPopDown", (XtActionProc) UciPopDown },
1903 { "TimeControlPopDown", (XtActionProc) TimeControlPopDown },
1904 { "NewVariantPopDown", (XtActionProc) NewVariantPopDown },
1905 { "SettingsPopDown", (XtActionProc) SettingsPopDown },
1908 char globalTranslations[] =
1909 ":<Key>R: ResignProc() \n \
1910 :<Key>r: ResetProc() \n \
1911 :<Key>g: LoadGameProc() \n \
1912 :<Key>N: LoadNextGameProc() \n \
1913 :<Key>P: LoadPrevGameProc() \n \
1914 :<Key>Q: QuitProc() \n \
1915 :<Key>F: ToEndProc() \n \
1916 :<Key>f: ForwardProc() \n \
1917 :<Key>B: ToStartProc() \n \
1918 :<Key>b: BackwardProc() \n \
1919 :<Key>p: PauseProc() \n \
1920 :<Key>d: DrawProc() \n \
1921 :<Key>t: CallFlagProc() \n \
1922 :<Key>i: Iconify() \n \
1923 :<Key>c: Iconify() \n \
1924 :<Key>v: FlipViewProc() \n \
1925 <KeyDown>Control_L: BackwardProc() \n \
1926 <KeyUp>Control_L: ForwardProc() \n \
1927 <KeyDown>Control_R: BackwardProc() \n \
1928 <KeyUp>Control_R: ForwardProc() \n \
1929 Shift<Key>1: AskQuestionProc(\"Direct command\",\
1930 \"Send to chess program:\",,1) \n \
1931 Shift<Key>2: AskQuestionProc(\"Direct command\",\
1932 \"Send to second chess program:\",,2) \n";
1934 char boardTranslations[] =
1935 "<Btn1Down>: HandleUserMove() \n \
1936 <Btn1Up>: HandleUserMove() \n \
1937 <Btn1Motion>: AnimateUserMove() \n \
1938 Shift<Btn2Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD)\
1939 PieceMenuPopup(menuB) \n \
1940 Any<Btn2Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD) \
1941 PieceMenuPopup(menuW) \n \
1942 Shift<Btn3Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD)\
1943 PieceMenuPopup(menuW) \n \
1944 Any<Btn3Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD) \
1945 PieceMenuPopup(menuB) \n";
1947 char whiteTranslations[] = "<BtnDown>: WhiteClock()\n";
1948 char blackTranslations[] = "<BtnDown>: BlackClock()\n";
1950 char ICSInputTranslations[] =
1951 "<Key>Return: EnterKeyProc() \n";
1953 String xboardResources[] = {
1954 "*fileName*value.translations: #override\\n <Key>Return: FileNameAction()",
1955 "*question*value.translations: #override\\n <Key>Return: AskQuestionReplyAction()",
1956 "*errorpopup*translations: #override\\n <Key>Return: ErrorPopDown()",
1961 /* Max possible square size */
1962 #define MAXSQSIZE 256
1964 static int xpm_avail[MAXSQSIZE];
1966 #ifdef HAVE_DIR_STRUCT
1968 /* Extract piece size from filename */
1970 xpm_getsize(name, len, ext)
1981 if ((p=strchr(name, '.')) == NULL ||
1982 StrCaseCmp(p+1, ext) != 0)
1988 while (*p && isdigit(*p))
1995 /* Setup xpm_avail */
1997 xpm_getavail(dirname, ext)
2005 for (i=0; i<MAXSQSIZE; ++i)
2008 if (appData.debugMode)
2009 fprintf(stderr, "XPM dir:%s:ext:%s:\n", dirname, ext);
2011 dir = opendir(dirname);
2014 fprintf(stderr, _("%s: Can't access XPM directory %s\n"),
2015 programName, dirname);
2019 while ((ent=readdir(dir)) != NULL) {
2020 i = xpm_getsize(ent->d_name, NAMLEN(ent), ext);
2021 if (i > 0 && i < MAXSQSIZE)
2031 xpm_print_avail(fp, ext)
2037 fprintf(fp, _("Available `%s' sizes:\n"), ext);
2038 for (i=1; i<MAXSQSIZE; ++i) {
2044 /* Return XPM piecesize closest to size */
2046 xpm_closest_to(dirname, size, ext)
2052 int sm_diff = MAXSQSIZE;
2056 xpm_getavail(dirname, ext);
2058 if (appData.debugMode)
2059 xpm_print_avail(stderr, ext);
2061 for (i=1; i<MAXSQSIZE; ++i) {
2064 diff = (diff<0) ? -diff : diff;
2065 if (diff < sm_diff) {
2073 fprintf(stderr, _("Error: No `%s' files!\n"), ext);
2079 #else /* !HAVE_DIR_STRUCT */
2080 /* If we are on a system without a DIR struct, we can't
2081 read the directory, so we can't collect a list of
2082 filenames, etc., so we can't do any size-fitting. */
2084 xpm_closest_to(dirname, size, ext)
2089 fprintf(stderr, _("\
2090 Warning: No DIR structure found on this system --\n\
2091 Unable to autosize for XPM/XIM pieces.\n\
2092 Please report this error to frankm@hiwaay.net.\n\
2093 Include system type & operating system in message.\n"));
2096 #endif /* HAVE_DIR_STRUCT */
2098 static char *cnames[9] = { "black", "red", "green", "yellow", "blue",
2099 "magenta", "cyan", "white" };
2103 TextColors textColors[(int)NColorClasses];
2105 /* String is: "fg, bg, attr". Which is 0, 1, 2 */
2107 parse_color(str, which)
2111 char *p, buf[100], *d;
2114 if (strlen(str) > 99) /* watch bounds on buf */
2119 for (i=0; i<which; ++i) {
2126 /* Could be looking at something like:
2128 .. in which case we want to stop on a comma also */
2129 while (*p && *p != ',' && !isalpha(*p) && !isdigit(*p))
2133 return -1; /* Use default for empty field */
2136 if (which == 2 || isdigit(*p))
2139 while (*p && isalpha(*p))
2144 for (i=0; i<8; ++i) {
2145 if (!StrCaseCmp(buf, cnames[i]))
2146 return which? (i+40) : (i+30);
2148 if (!StrCaseCmp(buf, "default")) return -1;
2150 fprintf(stderr, _("%s: unrecognized color %s\n"), programName, buf);
2155 parse_cpair(cc, str)
2159 if ((textColors[(int)cc].fg=parse_color(str, 0)) == -2) {
2160 fprintf(stderr, _("%s: can't parse foreground color in `%s'\n"),
2165 /* bg and attr are optional */
2166 textColors[(int)cc].bg = parse_color(str, 1);
2167 if ((textColors[(int)cc].attr = parse_color(str, 2)) < 0) {
2168 textColors[(int)cc].attr = 0;
2174 /* Arrange to catch delete-window events */
2175 Atom wm_delete_window;
2177 CatchDeleteWindow(Widget w, String procname)
2180 XSetWMProtocols(xDisplay, XtWindow(w), &wm_delete_window, 1);
2181 snprintf(buf, sizeof(buf), "<Message>WM_PROTOCOLS: %s() \n", procname);
2182 XtAugmentTranslations(w, XtParseTranslationTable(buf));
2189 XtSetArg(args[0], XtNiconic, False);
2190 XtSetValues(shellWidget, args, 1);
2192 XtPopup(shellWidget, XtGrabNone); /* Raise if lowered */
2196 // eventually, all layout determining code should go into a subroutine, but until then IDSIZE remains undefined
2198 #define BoardSize int
2199 void InitDrawingSizes(BoardSize boardSize, int flags)
2200 { // [HGM] resize is functional now, but for board format changes only (nr of ranks, files)
2201 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
2203 XtGeometryResult gres;
2206 if(!formWidget) return;
2209 * Enable shell resizing.
2211 shellArgs[0].value = (XtArgVal) &w;
2212 shellArgs[1].value = (XtArgVal) &h;
2213 XtGetValues(shellWidget, shellArgs, 2);
2215 shellArgs[4].value = 2*w; shellArgs[2].value = 10;
2216 shellArgs[5].value = 2*h; shellArgs[3].value = 10;
2217 XtSetValues(shellWidget, &shellArgs[2], 4);
2219 XtSetArg(args[0], XtNdefaultDistance, &sep);
2220 XtGetValues(formWidget, args, 1);
2222 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2223 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2226 XtSetArg(args[0], XtNwidth, boardWidth);
2227 XtSetArg(args[1], XtNheight, boardHeight);
2228 XtSetValues(boardWidget, args, 2);
2230 timerWidth = (boardWidth - sep) / 2;
2231 XtSetArg(args[0], XtNwidth, timerWidth);
2232 XtSetValues(whiteTimerWidget, args, 1);
2233 XtSetValues(blackTimerWidget, args, 1);
2235 XawFormDoLayout(formWidget, False);
2237 if (appData.titleInWindow) {
2239 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2240 XtSetArg(args[i], XtNheight, &h); i++;
2241 XtGetValues(titleWidget, args, i);
2243 w = boardWidth - 2*bor;
2245 XtSetArg(args[0], XtNwidth, &w);
2246 XtGetValues(menuBarWidget, args, 1);
2247 w = boardWidth - w - sep - 2*bor - 2; // WIDTH_FUDGE
2250 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
2251 if (gres != XtGeometryYes && appData.debugMode) {
2253 _("%s: titleWidget geometry error %d %d %d %d %d\n"),
2254 programName, gres, w, h, wr, hr);
2258 XawFormDoLayout(formWidget, True);
2261 * Inhibit shell resizing.
2263 shellArgs[0].value = w = (XtArgVal) boardWidth + marginW;
2264 shellArgs[1].value = h = (XtArgVal) boardHeight + marginH;
2265 shellArgs[4].value = shellArgs[2].value = w;
2266 shellArgs[5].value = shellArgs[3].value = h;
2267 XtSetValues(shellWidget, &shellArgs[0], 6);
2269 // [HGM] pieces: tailor piece bitmaps to needs of specific variant
2272 for(i=0; i<4; i++) {
2274 for(p=0; p<=(int)WhiteKing; p++)
2275 xpmPieceBitmap[i][p] = xpmPieceBitmap2[i][p]; // defaults
2276 if(gameInfo.variant == VariantShogi) {
2277 xpmPieceBitmap[i][(int)WhiteCannon] = xpmPieceBitmap2[i][(int)WhiteKing+1];
2278 xpmPieceBitmap[i][(int)WhiteNightrider] = xpmPieceBitmap2[i][(int)WhiteKing+2];
2279 xpmPieceBitmap[i][(int)WhiteSilver] = xpmPieceBitmap2[i][(int)WhiteKing+3];
2280 xpmPieceBitmap[i][(int)WhiteGrasshopper] = xpmPieceBitmap2[i][(int)WhiteKing+4];
2281 xpmPieceBitmap[i][(int)WhiteQueen] = xpmPieceBitmap2[i][(int)WhiteLance];
2284 if(gameInfo.variant == VariantGothic) {
2285 xpmPieceBitmap[i][(int)WhiteMarshall] = xpmPieceBitmap2[i][(int)WhiteSilver];
2289 // [HGM] why are thee ximMasks used at all? the ximPieceBitmaps seem to be never used!
2290 for(p=0; p<=(int)WhiteKing; p++)
2291 ximMaskPm[p] = ximMaskPm2[p]; // defaults
2292 if(gameInfo.variant == VariantShogi) {
2293 ximMaskPm[(int)WhiteCannon] = ximMaskPm2[(int)WhiteKing+1];
2294 ximMaskPm[(int)WhiteNightrider] = ximMaskPm2[(int)WhiteKing+2];
2295 ximMaskPm[(int)WhiteSilver] = ximMaskPm2[(int)WhiteKing+3];
2296 ximMaskPm[(int)WhiteGrasshopper] = ximMaskPm2[(int)WhiteKing+4];
2297 ximMaskPm[(int)WhiteQueen] = ximMaskPm2[(int)WhiteLance];
2300 if(gameInfo.variant == VariantGothic) {
2301 ximMaskPm[(int)WhiteMarshall] = ximMaskPm2[(int)WhiteSilver];
2307 for(i=0; i<2; i++) {
2309 for(p=0; p<=(int)WhiteKing; p++)
2310 pieceBitmap[i][p] = pieceBitmap2[i][p]; // defaults
2311 if(gameInfo.variant == VariantShogi) {
2312 pieceBitmap[i][(int)WhiteCannon] = pieceBitmap2[i][(int)WhiteKing+1];
2313 pieceBitmap[i][(int)WhiteNightrider] = pieceBitmap2[i][(int)WhiteKing+2];
2314 pieceBitmap[i][(int)WhiteSilver] = pieceBitmap2[i][(int)WhiteKing+3];
2315 pieceBitmap[i][(int)WhiteGrasshopper] = pieceBitmap2[i][(int)WhiteKing+4];
2316 pieceBitmap[i][(int)WhiteQueen] = pieceBitmap2[i][(int)WhiteLance];
2319 if(gameInfo.variant == VariantGothic) {
2320 pieceBitmap[i][(int)WhiteMarshall] = pieceBitmap2[i][(int)WhiteSilver];
2331 void EscapeExpand(char *p, char *q)
2332 { // [HGM] initstring: routine to shape up string arguments
2333 while(*p++ = *q++) if(p[-1] == '\\')
2335 case 'n': p[-1] = '\n'; break;
2336 case 'r': p[-1] = '\r'; break;
2337 case 't': p[-1] = '\t'; break;
2338 case '\\': p[-1] = '\\'; break;
2339 case 0: *p = 0; return;
2340 default: p[-1] = q[-1]; break;
2349 int i, j, clockFontPxlSize, coordFontPxlSize, fontPxlSize;
2350 XSetWindowAttributes window_attributes;
2352 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
2353 XrmValue vFrom, vTo;
2354 XtGeometryResult gres;
2357 int forceMono = False;
2360 // [HGM] before anything else, expand any indirection files amongst options
2361 char *argvCopy[1000]; // 1000 seems enough
2362 char newArgs[10000]; // holds actual characters
2365 srandom(time(0)); // [HGM] book: make random truly random
2368 for(i=0; i<argc; i++) {
2369 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2370 //fprintf(stderr, "arg %s\n", argv[i]);
2371 if(argv[i][0] != '@') argvCopy[j++] = argv[i]; else {
2373 FILE *f = fopen(argv[i]+1, "rb");
2374 if(f == NULL) { fprintf(stderr, _("ignore %s\n"), argv[i]); continue; } // do not expand non-existing
2375 argvCopy[j++] = newArgs + k; // get ready for first argument from file
2376 while((c = fgetc(f)) != EOF) { // each line of file inserts 1 argument in the list
2378 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2379 newArgs[k++] = 0; // terminate current arg
2380 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2381 argvCopy[j++] = newArgs + k; // get ready for next
2383 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2396 if(appData.debugMode,1) { // OK, appData is not initialized here yet...
2397 for(i=0; i<argc; i++) fprintf(stderr, "argv[%2d] = '%s'\n", i, argv[i]);
2402 setbuf(stdout, NULL);
2403 setbuf(stderr, NULL);
2406 programName = strrchr(argv[0], '/');
2407 if (programName == NULL)
2408 programName = argv[0];
2413 XtSetLanguageProc(NULL, NULL, NULL);
2414 bindtextdomain(PACKAGE, LOCALEDIR);
2415 textdomain(PACKAGE);
2419 XtAppInitialize(&appContext, "XBoard", shellOptions,
2420 XtNumber(shellOptions),
2421 &argc, argv, xboardResources, NULL, 0);
2423 fprintf(stderr, _("%s: unrecognized argument %s\n"),
2424 programName, argv[1]);
2425 fprintf(stderr, "Recognized options:\n");
2426 for(i = 0; i < XtNumber(shellOptions); i++) {
2427 j = fprintf(stderr, " %s%s", shellOptions[i].option,
2428 (shellOptions[i].argKind == XrmoptionSepArg
2430 if (++i < XtNumber(shellOptions)) {
2431 fprintf(stderr, "%*c%s%s\n", 40 - j, ' ',
2432 shellOptions[i].option,
2433 (shellOptions[i].argKind == XrmoptionSepArg
2436 fprintf(stderr, "\n");
2443 if (p == NULL) p = "/tmp";
2444 i = strlen(p) + strlen("/.xboardXXXXXx.pgn") + 1;
2445 gameCopyFilename = (char*) malloc(i);
2446 gamePasteFilename = (char*) malloc(i);
2447 snprintf(gameCopyFilename,i, "%s/.xboard%05uc.pgn", p, getpid());
2448 snprintf(gamePasteFilename,i, "%s/.xboard%05up.pgn", p, getpid());
2450 XtGetApplicationResources(shellWidget, (XtPointer) &appData,
2451 clientResources, XtNumber(clientResources),
2454 { // [HGM] initstring: kludge to fix bad bug. expand '\n' characters in init string and computer string.
2455 static char buf[MSG_SIZ];
2456 EscapeExpand(buf, appData.initString);
2457 appData.initString = strdup(buf);
2458 EscapeExpand(buf, appData.secondInitString);
2459 appData.secondInitString = strdup(buf);
2460 EscapeExpand(buf, appData.firstComputerString);
2461 appData.firstComputerString = strdup(buf);
2462 EscapeExpand(buf, appData.secondComputerString);
2463 appData.secondComputerString = strdup(buf);
2466 if ((chessDir = (char *) getenv("CHESSDIR")) == NULL) {
2469 if (chdir(chessDir) != 0) {
2470 fprintf(stderr, _("%s: can't cd to CHESSDIR: "), programName);
2476 if (appData.debugMode && appData.nameOfDebugFile && strcmp(appData.nameOfDebugFile, "stderr")) {
2477 /* [DM] debug info to file [HGM] make the filename a command-line option, and allow it to remain stderr */
2478 if ((debugFP = fopen(appData.nameOfDebugFile, "w")) == NULL) {
2479 printf(_("Failed to open file '%s'\n"), appData.nameOfDebugFile);
2482 setbuf(debugFP, NULL);
2485 /* [HGM,HR] make sure board size is acceptable */
2486 if(appData.NrFiles > BOARD_SIZE ||
2487 appData.NrRanks > BOARD_SIZE )
2488 DisplayFatalError(_("Recompile with BOARD_SIZE > 12, to support this size"), 0, 2);
2491 /* This feature does not work; animation needs a rewrite */
2492 appData.highlightDragging = FALSE;
2496 xDisplay = XtDisplay(shellWidget);
2497 xScreen = DefaultScreen(xDisplay);
2498 wm_delete_window = XInternAtom(xDisplay, "WM_DELETE_WINDOW", True);
2500 gameInfo.variant = StringToVariant(appData.variant);
2501 InitPosition(FALSE);
2504 * Determine boardSize
2506 gameInfo.boardWidth = gameInfo.boardHeight = 8; // [HGM] boardsize: make sure we start as 8x8
2509 // [HGM] as long as we have not created the possibility to change size while running, start with requested size
2510 gameInfo.boardWidth = appData.NrFiles > 0 ? appData.NrFiles : 8;
2511 gameInfo.boardHeight = appData.NrRanks > 0 ? appData.NrRanks : 8;
2512 gameInfo.holdingsWidth = appData.holdingsSize > 0 ? 2 : 0;
2517 InitDrawingSizes(-1, 0); // [HGM] initsize: make this into a subroutine
2519 if (isdigit(appData.boardSize[0])) {
2520 i = sscanf(appData.boardSize, "%d,%d,%d,%d,%d,%d,%d", &squareSize,
2521 &lineGap, &clockFontPxlSize, &coordFontPxlSize,
2522 &fontPxlSize, &smallLayout, &tinyLayout);
2524 fprintf(stderr, _("%s: bad boardSize syntax %s\n"),
2525 programName, appData.boardSize);
2529 /* Find some defaults; use the nearest known size */
2530 SizeDefaults *szd, *nearest;
2531 int distance = 99999;
2532 nearest = szd = sizeDefaults;
2533 while (szd->name != NULL) {
2534 if (abs(szd->squareSize - squareSize) < distance) {
2536 distance = abs(szd->squareSize - squareSize);
2537 if (distance == 0) break;
2541 if (i < 2) lineGap = nearest->lineGap;
2542 if (i < 3) clockFontPxlSize = nearest->clockFontPxlSize;
2543 if (i < 4) coordFontPxlSize = nearest->coordFontPxlSize;
2544 if (i < 5) fontPxlSize = nearest->fontPxlSize;
2545 if (i < 6) smallLayout = nearest->smallLayout;
2546 if (i < 7) tinyLayout = nearest->tinyLayout;
2549 SizeDefaults *szd = sizeDefaults;
2550 if (*appData.boardSize == NULLCHAR) {
2551 while (DisplayWidth(xDisplay, xScreen) < szd->minScreenSize ||
2552 DisplayHeight(xDisplay, xScreen) < szd->minScreenSize) {
2555 if (szd->name == NULL) szd--;
2557 while (szd->name != NULL &&
2558 StrCaseCmp(szd->name, appData.boardSize) != 0) szd++;
2559 if (szd->name == NULL) {
2560 fprintf(stderr, _("%s: unrecognized boardSize name %s\n"),
2561 programName, appData.boardSize);
2565 squareSize = szd->squareSize;
2566 lineGap = szd->lineGap;
2567 clockFontPxlSize = szd->clockFontPxlSize;
2568 coordFontPxlSize = szd->coordFontPxlSize;
2569 fontPxlSize = szd->fontPxlSize;
2570 smallLayout = szd->smallLayout;
2571 tinyLayout = szd->tinyLayout;
2574 /* Now, using squareSize as a hint, find a good XPM/XIM set size */
2575 if (strlen(appData.pixmapDirectory) > 0) {
2576 p = ExpandPathName(appData.pixmapDirectory);
2578 fprintf(stderr, _("Error expanding path name \"%s\"\n"),
2579 appData.pixmapDirectory);
2582 if (appData.debugMode) {
2583 fprintf(stderr, _("\
2584 XBoard square size (hint): %d\n\
2585 %s fulldir:%s:\n"), squareSize, IMAGE_EXT, p);
2587 squareSize = xpm_closest_to(p, squareSize, IMAGE_EXT);
2588 if (appData.debugMode) {
2589 fprintf(stderr, _("Closest %s size: %d\n"), IMAGE_EXT, squareSize);
2593 /* [HR] height treated separately (hacked) */
2594 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2595 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2596 if (appData.showJail == 1) {
2597 /* Jail on top and bottom */
2598 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2599 XtSetArg(boardArgs[2], XtNheight,
2600 boardHeight + 2*(lineGap + squareSize));
2601 } else if (appData.showJail == 2) {
2603 XtSetArg(boardArgs[1], XtNwidth,
2604 boardWidth + 2*(lineGap + squareSize));
2605 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2608 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2609 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2613 * Determine what fonts to use.
2615 appData.clockFont = FindFont(appData.clockFont, clockFontPxlSize);
2616 clockFontID = XLoadFont(xDisplay, appData.clockFont);
2617 clockFontStruct = XQueryFont(xDisplay, clockFontID);
2618 appData.coordFont = FindFont(appData.coordFont, coordFontPxlSize);
2619 coordFontID = XLoadFont(xDisplay, appData.coordFont);
2620 coordFontStruct = XQueryFont(xDisplay, coordFontID);
2621 appData.font = FindFont(appData.font, fontPxlSize);
2622 countFontID = XLoadFont(xDisplay, appData.coordFont); // [HGM] holdings
2623 countFontStruct = XQueryFont(xDisplay, countFontID);
2624 // appData.font = FindFont(appData.font, fontPxlSize);
2626 xdb = XtDatabase(xDisplay);
2627 XrmPutStringResource(&xdb, "*font", appData.font);
2630 * Detect if there are not enough colors available and adapt.
2632 if (DefaultDepth(xDisplay, xScreen) <= 2) {
2633 appData.monoMode = True;
2636 if (!appData.monoMode) {
2637 vFrom.addr = (caddr_t) appData.lightSquareColor;
2638 vFrom.size = strlen(appData.lightSquareColor);
2639 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2640 if (vTo.addr == NULL) {
2641 appData.monoMode = True;
2644 lightSquareColor = *(Pixel *) vTo.addr;
2647 if (!appData.monoMode) {
2648 vFrom.addr = (caddr_t) appData.darkSquareColor;
2649 vFrom.size = strlen(appData.darkSquareColor);
2650 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2651 if (vTo.addr == NULL) {
2652 appData.monoMode = True;
2655 darkSquareColor = *(Pixel *) vTo.addr;
2658 if (!appData.monoMode) {
2659 vFrom.addr = (caddr_t) appData.whitePieceColor;
2660 vFrom.size = strlen(appData.whitePieceColor);
2661 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2662 if (vTo.addr == NULL) {
2663 appData.monoMode = True;
2666 whitePieceColor = *(Pixel *) vTo.addr;
2669 if (!appData.monoMode) {
2670 vFrom.addr = (caddr_t) appData.blackPieceColor;
2671 vFrom.size = strlen(appData.blackPieceColor);
2672 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2673 if (vTo.addr == NULL) {
2674 appData.monoMode = True;
2677 blackPieceColor = *(Pixel *) vTo.addr;
2681 if (!appData.monoMode) {
2682 vFrom.addr = (caddr_t) appData.highlightSquareColor;
2683 vFrom.size = strlen(appData.highlightSquareColor);
2684 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2685 if (vTo.addr == NULL) {
2686 appData.monoMode = True;
2689 highlightSquareColor = *(Pixel *) vTo.addr;
2693 if (!appData.monoMode) {
2694 vFrom.addr = (caddr_t) appData.premoveHighlightColor;
2695 vFrom.size = strlen(appData.premoveHighlightColor);
2696 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2697 if (vTo.addr == NULL) {
2698 appData.monoMode = True;
2701 premoveHighlightColor = *(Pixel *) vTo.addr;
2706 fprintf(stderr, _("%s: too few colors available; trying monochrome mode\n"),
2709 if (appData.bitmapDirectory == NULL ||
2710 appData.bitmapDirectory[0] == NULLCHAR)
2711 appData.bitmapDirectory = DEF_BITMAP_DIR;
2714 if (appData.lowTimeWarning && !appData.monoMode) {
2715 vFrom.addr = (caddr_t) appData.lowTimeWarningColor;
2716 vFrom.size = strlen(appData.lowTimeWarningColor);
2717 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2718 if (vTo.addr == NULL)
2719 appData.monoMode = True;
2721 lowTimeWarningColor = *(Pixel *) vTo.addr;
2724 if (appData.monoMode && appData.debugMode) {
2725 fprintf(stderr, _("white pixel = 0x%lx, black pixel = 0x%lx\n"),
2726 (unsigned long) XWhitePixel(xDisplay, xScreen),
2727 (unsigned long) XBlackPixel(xDisplay, xScreen));
2730 if (parse_cpair(ColorShout, appData.colorShout) < 0 ||
2731 parse_cpair(ColorSShout, appData.colorSShout) < 0 ||
2732 parse_cpair(ColorChannel1, appData.colorChannel1) < 0 ||
2733 parse_cpair(ColorChannel, appData.colorChannel) < 0 ||
2734 parse_cpair(ColorKibitz, appData.colorKibitz) < 0 ||
2735 parse_cpair(ColorTell, appData.colorTell) < 0 ||
2736 parse_cpair(ColorChallenge, appData.colorChallenge) < 0 ||
2737 parse_cpair(ColorRequest, appData.colorRequest) < 0 ||
2738 parse_cpair(ColorSeek, appData.colorSeek) < 0 ||
2739 parse_cpair(ColorNormal, appData.colorNormal) < 0)
2741 if (appData.colorize) {
2743 _("%s: can't parse color names; disabling colorization\n"),
2746 appData.colorize = FALSE;
2748 textColors[ColorNone].fg = textColors[ColorNone].bg = -1;
2749 textColors[ColorNone].attr = 0;
2751 XtAppAddActions(appContext, boardActions, XtNumber(boardActions));
2757 layoutName = "tinyLayout";
2758 } else if (smallLayout) {
2759 layoutName = "smallLayout";
2761 layoutName = "normalLayout";
2763 /* Outer layoutWidget is there only to provide a name for use in
2764 resources that depend on the layout style */
2766 XtCreateManagedWidget(layoutName, formWidgetClass, shellWidget,
2767 layoutArgs, XtNumber(layoutArgs));
2769 XtCreateManagedWidget("form", formWidgetClass, layoutWidget,
2770 formArgs, XtNumber(formArgs));
2771 XtSetArg(args[0], XtNdefaultDistance, &sep);
2772 XtGetValues(formWidget, args, 1);
2775 widgetList[j++] = menuBarWidget = CreateMenuBar(menuBar);
2776 XtSetArg(args[0], XtNtop, XtChainTop);
2777 XtSetArg(args[1], XtNbottom, XtChainTop);
2778 XtSetValues(menuBarWidget, args, 2);
2780 widgetList[j++] = whiteTimerWidget =
2781 XtCreateWidget("whiteTime", labelWidgetClass,
2782 formWidget, timerArgs, XtNumber(timerArgs));
2783 XtSetArg(args[0], XtNfont, clockFontStruct);
2784 XtSetArg(args[1], XtNtop, XtChainTop);
2785 XtSetArg(args[2], XtNbottom, XtChainTop);
2786 XtSetValues(whiteTimerWidget, args, 3);
2788 widgetList[j++] = blackTimerWidget =
2789 XtCreateWidget("blackTime", labelWidgetClass,
2790 formWidget, timerArgs, XtNumber(timerArgs));
2791 XtSetArg(args[0], XtNfont, clockFontStruct);
2792 XtSetArg(args[1], XtNtop, XtChainTop);
2793 XtSetArg(args[2], XtNbottom, XtChainTop);
2794 XtSetValues(blackTimerWidget, args, 3);
2796 if (appData.titleInWindow) {
2797 widgetList[j++] = titleWidget =
2798 XtCreateWidget("title", labelWidgetClass, formWidget,
2799 titleArgs, XtNumber(titleArgs));
2800 XtSetArg(args[0], XtNtop, XtChainTop);
2801 XtSetArg(args[1], XtNbottom, XtChainTop);
2802 XtSetValues(titleWidget, args, 2);
2805 if (appData.showButtonBar) {
2806 widgetList[j++] = buttonBarWidget = CreateButtonBar(buttonBar);
2807 XtSetArg(args[0], XtNleft, XtChainRight); // [HGM] glue to right window edge
2808 XtSetArg(args[1], XtNright, XtChainRight); // for good run-time sizing
2809 XtSetArg(args[2], XtNtop, XtChainTop);
2810 XtSetArg(args[3], XtNbottom, XtChainTop);
2811 XtSetValues(buttonBarWidget, args, 4);
2814 widgetList[j++] = messageWidget =
2815 XtCreateWidget("message", labelWidgetClass, formWidget,
2816 messageArgs, XtNumber(messageArgs));
2817 XtSetArg(args[0], XtNtop, XtChainTop);
2818 XtSetArg(args[1], XtNbottom, XtChainTop);
2819 XtSetValues(messageWidget, args, 2);
2821 widgetList[j++] = boardWidget =
2822 XtCreateWidget("board", widgetClass, formWidget, boardArgs,
2823 XtNumber(boardArgs));
2825 XtManageChildren(widgetList, j);
2827 timerWidth = (boardWidth - sep) / 2;
2828 XtSetArg(args[0], XtNwidth, timerWidth);
2829 XtSetValues(whiteTimerWidget, args, 1);
2830 XtSetValues(blackTimerWidget, args, 1);
2832 XtSetArg(args[0], XtNbackground, &timerBackgroundPixel);
2833 XtSetArg(args[1], XtNforeground, &timerForegroundPixel);
2834 XtGetValues(whiteTimerWidget, args, 2);
2836 if (appData.showButtonBar) {
2837 XtSetArg(args[0], XtNbackground, &buttonBackgroundPixel);
2838 XtSetArg(args[1], XtNforeground, &buttonForegroundPixel);
2839 XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
2843 * formWidget uses these constraints but they are stored
2847 XtSetArg(args[i], XtNfromHoriz, 0); i++;
2848 XtSetValues(menuBarWidget, args, i);
2849 if (appData.titleInWindow) {
2852 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2853 XtSetValues(whiteTimerWidget, args, i);
2855 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2856 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2857 XtSetValues(blackTimerWidget, args, i);
2859 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2860 XtSetArg(args[i], XtNjustify, XtJustifyLeft); i++;
2861 XtSetValues(titleWidget, args, i);
2863 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2864 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2865 XtSetValues(messageWidget, args, i);
2866 if (appData.showButtonBar) {
2868 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2869 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2870 XtSetValues(buttonBarWidget, args, i);
2874 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2875 XtSetValues(whiteTimerWidget, args, i);
2877 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2878 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2879 XtSetValues(blackTimerWidget, args, i);
2881 XtSetArg(args[i], XtNfromHoriz, menuBarWidget); i++;
2882 XtSetValues(titleWidget, args, i);
2884 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2885 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2886 XtSetValues(messageWidget, args, i);
2887 if (appData.showButtonBar) {
2889 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2890 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2891 XtSetValues(buttonBarWidget, args, i);
2896 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2897 XtSetValues(whiteTimerWidget, args, i);
2899 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2900 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2901 XtSetValues(blackTimerWidget, args, i);
2903 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2904 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2905 XtSetValues(messageWidget, args, i);
2906 if (appData.showButtonBar) {
2908 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2909 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2910 XtSetValues(buttonBarWidget, args, i);
2914 XtSetArg(args[0], XtNfromVert, messageWidget);
2915 XtSetArg(args[1], XtNtop, XtChainTop);
2916 XtSetArg(args[2], XtNbottom, XtChainBottom);
2917 XtSetArg(args[3], XtNleft, XtChainLeft);
2918 XtSetArg(args[4], XtNright, XtChainRight);
2919 XtSetValues(boardWidget, args, 5);
2921 XtRealizeWidget(shellWidget);
2924 * Correct the width of the message and title widgets.
2925 * It is not known why some systems need the extra fudge term.
2926 * The value "2" is probably larger than needed.
2928 XawFormDoLayout(formWidget, False);
2930 #define WIDTH_FUDGE 2
2932 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2933 XtSetArg(args[i], XtNheight, &h); i++;
2934 XtGetValues(messageWidget, args, i);
2935 if (appData.showButtonBar) {
2937 XtSetArg(args[i], XtNwidth, &w); i++;
2938 XtGetValues(buttonBarWidget, args, i);
2939 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2941 w = boardWidth - 2*bor + 1; /*!! +1 compensates for kludge below */
2944 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2945 if (gres != XtGeometryYes && appData.debugMode) {
2946 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2947 programName, gres, w, h, wr, hr);
2950 /* !! Horrible hack to work around bug in XFree86 4.0.1 (X11R6.4.3) */
2951 /* The size used for the child widget in layout lags one resize behind
2952 its true size, so we resize a second time, 1 pixel smaller. Yeech! */
2954 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2955 if (gres != XtGeometryYes && appData.debugMode) {
2956 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2957 programName, gres, w, h, wr, hr);
2960 XtSetArg(args[0], XtNleft, XtChainLeft); // [HGM] glue ends for good run-time sizing
2961 XtSetArg(args[1], XtNright, XtChainRight);
2962 XtSetValues(messageWidget, args, 2);
2964 if (appData.titleInWindow) {
2966 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2967 XtSetArg(args[i], XtNheight, &h); i++;
2968 XtGetValues(titleWidget, args, i);
2970 w = boardWidth - 2*bor;
2972 XtSetArg(args[0], XtNwidth, &w);
2973 XtGetValues(menuBarWidget, args, 1);
2974 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2977 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
2978 if (gres != XtGeometryYes && appData.debugMode) {
2980 _("%s: titleWidget geometry error %d %d %d %d %d\n"),
2981 programName, gres, w, h, wr, hr);
2984 XawFormDoLayout(formWidget, True);
2986 xBoardWindow = XtWindow(boardWidget);
2988 // [HGM] it seems the layout code ends here, but perhaps the color stuff is size independent and would
2989 // not need to go into InitDrawingSizes().
2993 * Create X checkmark bitmap and initialize option menu checks.
2995 ReadBitmap(&xMarkPixmap, "checkmark.bm",
2996 checkmark_bits, checkmark_width, checkmark_height);
2997 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
2998 if (appData.alwaysPromoteToQueen) {
2999 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
3002 if (appData.animateDragging) {
3003 XtSetValues(XtNameToWidget(menuBarWidget,
3004 "menuOptions.Animate Dragging"),
3007 if (appData.animate) {
3008 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
3011 if (appData.autoComment) {
3012 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
3015 if (appData.autoCallFlag) {
3016 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
3019 if (appData.autoFlipView) {
3020 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Auto Flip View"),
3023 if (appData.autoObserve) {
3024 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
3027 if (appData.autoRaiseBoard) {
3028 XtSetValues(XtNameToWidget(menuBarWidget,
3029 "menuOptions.Auto Raise Board"), args, 1);
3031 if (appData.autoSaveGames) {
3032 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
3035 if (appData.saveGameFile[0] != NULLCHAR) {
3036 /* Can't turn this off from menu */
3037 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
3039 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
3043 if (appData.blindfold) {
3044 XtSetValues(XtNameToWidget(menuBarWidget,
3045 "menuOptions.Blindfold"), args, 1);
3047 if (appData.flashCount > 0) {
3048 XtSetValues(XtNameToWidget(menuBarWidget,
3049 "menuOptions.Flash Moves"),
3052 if (appData.getMoveList) {
3053 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
3057 if (appData.highlightDragging) {
3058 XtSetValues(XtNameToWidget(menuBarWidget,
3059 "menuOptions.Highlight Dragging"),
3063 if (appData.highlightLastMove) {
3064 XtSetValues(XtNameToWidget(menuBarWidget,
3065 "menuOptions.Highlight Last Move"),
3068 if (appData.icsAlarm) {
3069 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.ICS Alarm"),
3072 if (appData.ringBellAfterMoves) {
3073 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
3076 if (appData.oldSaveStyle) {
3077 XtSetValues(XtNameToWidget(menuBarWidget,
3078 "menuOptions.Old Save Style"), args, 1);
3080 if (appData.periodicUpdates) {
3081 XtSetValues(XtNameToWidget(menuBarWidget,
3082 "menuOptions.Periodic Updates"), args, 1);
3084 if (appData.ponderNextMove) {
3085 XtSetValues(XtNameToWidget(menuBarWidget,
3086 "menuOptions.Ponder Next Move"), args, 1);
3088 if (appData.popupExitMessage) {
3089 XtSetValues(XtNameToWidget(menuBarWidget,
3090 "menuOptions.Popup Exit Message"), args, 1);
3092 if (appData.popupMoveErrors) {
3093 XtSetValues(XtNameToWidget(menuBarWidget,
3094 "menuOptions.Popup Move Errors"), args, 1);
3096 if (appData.premove) {
3097 XtSetValues(XtNameToWidget(menuBarWidget,
3098 "menuOptions.Premove"), args, 1);
3100 if (appData.quietPlay) {
3101 XtSetValues(XtNameToWidget(menuBarWidget,
3102 "menuOptions.Quiet Play"), args, 1);
3104 if (appData.showCoords) {
3105 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
3108 if (appData.hideThinkingFromHuman) {
3109 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
3112 if (appData.testLegality) {
3113 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Test Legality"),
3120 ReadBitmap(&wIconPixmap, "icon_white.bm",
3121 icon_white_bits, icon_white_width, icon_white_height);
3122 ReadBitmap(&bIconPixmap, "icon_black.bm",
3123 icon_black_bits, icon_black_width, icon_black_height);
3124 iconPixmap = wIconPixmap;
3126 XtSetArg(args[i], XtNiconPixmap, iconPixmap); i++;
3127 XtSetValues(shellWidget, args, i);
3130 * Create a cursor for the board widget.
3132 window_attributes.cursor = XCreateFontCursor(xDisplay, XC_hand2);
3133 XChangeWindowAttributes(xDisplay, xBoardWindow,
3134 CWCursor, &window_attributes);
3137 * Inhibit shell resizing.
3139 shellArgs[0].value = (XtArgVal) &w;
3140 shellArgs[1].value = (XtArgVal) &h;
3141 XtGetValues(shellWidget, shellArgs, 2);
3142 shellArgs[4].value = shellArgs[2].value = w;
3143 shellArgs[5].value = shellArgs[3].value = h;
3144 XtSetValues(shellWidget, &shellArgs[2], 4);
3145 marginW = w - boardWidth; // [HGM] needed to set new shellWidget size when we resize board
3146 marginH = h - boardHeight;
3148 CatchDeleteWindow(shellWidget, "QuitProc");
3153 if (appData.bitmapDirectory[0] != NULLCHAR) {
3160 /* Create regular pieces */
3161 if (!useImages) CreatePieces();
3166 if (appData.animate || appData.animateDragging)
3169 XtAugmentTranslations(formWidget,
3170 XtParseTranslationTable(globalTranslations));
3171 XtAugmentTranslations(boardWidget,
3172 XtParseTranslationTable(boardTranslations));
3173 XtAugmentTranslations(whiteTimerWidget,
3174 XtParseTranslationTable(whiteTranslations));
3175 XtAugmentTranslations(blackTimerWidget,
3176 XtParseTranslationTable(blackTranslations));
3178 /* Why is the following needed on some versions of X instead
3179 * of a translation? */
3180 XtAddEventHandler(boardWidget, ExposureMask, False,
3181 (XtEventHandler) EventProc, NULL);
3186 if (errorExitStatus == -1) {
3187 if (appData.icsActive) {
3188 /* We now wait until we see "login:" from the ICS before
3189 sending the logon script (problems with timestamp otherwise) */
3190 /*ICSInitScript();*/
3191 if (appData.icsInputBox) ICSInputBoxPopUp();
3194 signal(SIGINT, IntSigHandler);
3195 signal(SIGTERM, IntSigHandler);
3196 if (*appData.cmailGameName != NULLCHAR) {
3197 signal(SIGUSR1, CmailSigHandler);
3200 gameInfo.boardWidth = 0; // [HGM] pieces: kludge to ensure InitPosition() calls InitDrawingSizes()
3203 XtAppMainLoop(appContext);
3204 if (appData.debugMode) fclose(debugFP); // [DM] debug
3211 if (appData.icsActive && oldICSInteractionTitle != NULL) {
3212 DisplayIcsInteractionTitle(oldICSInteractionTitle);
3214 unlink(gameCopyFilename);
3215 unlink(gamePasteFilename);
3226 CmailSigHandler(sig)
3232 signal(SIGUSR1, SIG_IGN); /* suspend handler */
3234 /* Activate call-back function CmailSigHandlerCallBack() */
3235 OutputToProcess(cmailPR, (char *)(&dummy), sizeof(int), &error);
3237 signal(SIGUSR1, CmailSigHandler); /* re-activate handler */
3241 CmailSigHandlerCallBack(isr, closure, message, count, error)
3249 ReloadCmailMsgEvent(TRUE); /* Reload cmail msg */
3251 /**** end signal code ****/
3261 f = fopen(appData.icsLogon, "r");
3267 strcat(buf, appData.icsLogon);
3268 f = fopen(buf, "r");
3272 ProcessICSInitScript(f);
3279 EditCommentPopDown();
3290 SetMenuEnables(enab)
3294 if (!menuBarWidget) return;
3295 while (enab->name != NULL) {
3296 w = XtNameToWidget(menuBarWidget, enab->name);
3298 DisplayError(enab->name, 0);
3300 XtSetSensitive(w, enab->value);
3306 Enables icsEnables[] = {
3307 { "menuFile.Mail Move", False },
3308 { "menuFile.Reload CMail Message", False },
3309 { "menuMode.Machine Black", False },
3310 { "menuMode.Machine White", False },
3311 { "menuMode.Analysis Mode", False },
3312 { "menuMode.Analyze File", False },
3313 { "menuMode.Two Machines", False },
3315 { "menuHelp.Hint", False },
3316 { "menuHelp.Book", False },
3317 { "menuStep.Move Now", False },
3318 { "menuOptions.Periodic Updates", False },
3319 { "menuOptions.Hide Thinking", False },
3320 { "menuOptions.Ponder Next Move", False },
3325 Enables ncpEnables[] = {
3326 { "menuFile.Mail Move", False },
3327 { "menuFile.Reload CMail Message", False },
3328 { "menuMode.Machine White", False },
3329 { "menuMode.Machine Black", False },
3330 { "menuMode.Analysis Mode", False },
3331 { "menuMode.Analyze File", False },
3332 { "menuMode.Two Machines", False },
3333 { "menuMode.ICS Client", False },
3334 { "menuMode.ICS Input Box", False },
3335 { "Action", False },
3336 { "menuStep.Revert", False },
3337 { "menuStep.Move Now", False },
3338 { "menuStep.Retract Move", False },
3339 { "menuOptions.Auto Comment", False },
3340 { "menuOptions.Auto Flag", False },
3341 { "menuOptions.Auto Flip View", False },
3342 { "menuOptions.Auto Observe", False },
3343 { "menuOptions.Auto Raise Board", False },
3344 { "menuOptions.Get Move List", False },
3345 { "menuOptions.ICS Alarm", False },
3346 { "menuOptions.Move Sound", False },
3347 { "menuOptions.Quiet Play", False },
3348 { "menuOptions.Hide Thinking", False },
3349 { "menuOptions.Periodic Updates", False },
3350 { "menuOptions.Ponder Next Move", False },
3351 { "menuHelp.Hint", False },
3352 { "menuHelp.Book", False },
3356 Enables gnuEnables[] = {
3357 { "menuMode.ICS Client", False },
3358 { "menuMode.ICS Input Box", False },
3359 { "menuAction.Accept", False },
3360 { "menuAction.Decline", False },
3361 { "menuAction.Rematch", False },
3362 { "menuAction.Adjourn", False },
3363 { "menuAction.Stop Examining", False },
3364 { "menuAction.Stop Observing", False },
3365 { "menuStep.Revert", False },
3366 { "menuOptions.Auto Comment", False },
3367 { "menuOptions.Auto Observe", False },
3368 { "menuOptions.Auto Raise Board", False },
3369 { "menuOptions.Get Move List", False },
3370 { "menuOptions.Premove", False },
3371 { "menuOptions.Quiet Play", False },
3373 /* The next two options rely on SetCmailMode being called *after* */
3374 /* SetGNUMode so that when GNU is being used to give hints these */
3375 /* menu options are still available */
3377 { "menuFile.Mail Move", False },
3378 { "menuFile.Reload CMail Message", False },
3382 Enables cmailEnables[] = {
3384 { "menuAction.Call Flag", False },
3385 { "menuAction.Draw", True },
3386 { "menuAction.Adjourn", False },
3387 { "menuAction.Abort", False },
3388 { "menuAction.Stop Observing", False },
3389 { "menuAction.Stop Examining", False },
3390 { "menuFile.Mail Move", True },
3391 { "menuFile.Reload CMail Message", True },
3395 Enables trainingOnEnables[] = {
3396 { "menuMode.Edit Comment", False },
3397 { "menuMode.Pause", False },
3398 { "menuStep.Forward", False },
3399 { "menuStep.Backward", False },
3400 { "menuStep.Forward to End", False },
3401 { "menuStep.Back to Start", False },
3402 { "menuStep.Move Now", False },
3403 { "menuStep.Truncate Game", False },
3407 Enables trainingOffEnables[] = {
3408 { "menuMode.Edit Comment", True },
3409 { "menuMode.Pause", True },
3410 { "menuStep.Forward", True },
3411 { "menuStep.Backward", True },
3412 { "menuStep.Forward to End", True },
3413 { "menuStep.Back to Start", True },
3414 { "menuStep.Move Now", True },
3415 { "menuStep.Truncate Game", True },
3419 Enables machineThinkingEnables[] = {
3420 { "menuFile.Load Game", False },
3421 { "menuFile.Load Next Game", False },
3422 { "menuFile.Load Previous Game", False },
3423 { "menuFile.Reload Same Game", False },
3424 { "menuFile.Paste Game", False },
3425 { "menuFile.Load Position", False },
3426 { "menuFile.Load Next Position", False },
3427 { "menuFile.Load Previous Position", False },
3428 { "menuFile.Reload Same Position", False },
3429 { "menuFile.Paste Position", False },
3430 { "menuMode.Machine White", False },
3431 { "menuMode.Machine Black", False },
3432 { "menuMode.Two Machines", False },
3433 { "menuStep.Retract Move", False },
3437 Enables userThinkingEnables[] = {
3438 { "menuFile.Load Game", True },
3439 { "menuFile.Load Next Game", True },
3440 { "menuFile.Load Previous Game", True },
3441 { "menuFile.Reload Same Game", True },
3442 { "menuFile.Paste Game", True },
3443 { "menuFile.Load Position", True },
3444 { "menuFile.Load Next Position", True },
3445 { "menuFile.Load Previous Position", True },
3446 { "menuFile.Reload Same Position", True },
3447 { "menuFile.Paste Position", True },
3448 { "menuMode.Machine White", True },
3449 { "menuMode.Machine Black", True },
3450 { "menuMode.Two Machines", True },
3451 { "menuStep.Retract Move", True },
3457 SetMenuEnables(icsEnables);
3460 if (appData.zippyPlay && !appData.noChessProgram) /* [DM] icsEngineAnalyze */
3461 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Analysis Mode"), True);
3468 SetMenuEnables(ncpEnables);
3474 SetMenuEnables(gnuEnables);
3480 SetMenuEnables(cmailEnables);
3486 SetMenuEnables(trainingOnEnables);
3487 if (appData.showButtonBar) {
3488 XtSetSensitive(buttonBarWidget, False);
3494 SetTrainingModeOff()
3496 SetMenuEnables(trainingOffEnables);
3497 if (appData.showButtonBar) {
3498 XtSetSensitive(buttonBarWidget, True);
3503 SetUserThinkingEnables()
3505 if (appData.noChessProgram) return;
3506 SetMenuEnables(userThinkingEnables);
3510 SetMachineThinkingEnables()
3512 if (appData.noChessProgram) return;
3513 SetMenuEnables(machineThinkingEnables);
3515 case MachinePlaysBlack:
3516 case MachinePlaysWhite:
3517 case TwoMachinesPlay:
3518 XtSetSensitive(XtNameToWidget(menuBarWidget,
3519 ModeToWidgetName(gameMode)), True);
3526 #define Abs(n) ((n)<0 ? -(n) : (n))
3529 * Find a font that matches "pattern" that is as close as
3530 * possible to the targetPxlSize. Prefer fonts that are k
3531 * pixels smaller to fonts that are k pixels larger. The
3532 * pattern must be in the X Consortium standard format,
3533 * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".
3534 * The return value should be freed with XtFree when no
3537 char *FindFont(pattern, targetPxlSize)
3541 char **fonts, *p, *best, *scalable, *scalableTail;
3542 int i, j, nfonts, minerr, err, pxlSize;
3545 char **missing_list;
3547 char *def_string, *base_fnt_lst, strInt[3];
3549 XFontStruct **fnt_list;
3551 base_fnt_lst = calloc(1, strlen(pattern) + 3);
3552 sprintf(strInt, "%d", targetPxlSize);
3553 p = strstr(pattern, "--");
3554 strncpy(base_fnt_lst, pattern, p - pattern + 2);
3555 strcat(base_fnt_lst, strInt);
3556 strcat(base_fnt_lst, strchr(p + 2, '-'));
3558 if ((fntSet = XCreateFontSet(xDisplay,
3562 &def_string)) == NULL) {
3564 fprintf(stderr, _("Unable to create font set.\n"));
3568 nfonts = XFontsOfFontSet(fntSet, &fnt_list, &fonts);
3570 fonts = XListFonts(xDisplay, pattern, 999999, &nfonts);
3572 fprintf(stderr, _("%s: no fonts match pattern %s\n"),
3573 programName, pattern);
3581 for (i=0; i<nfonts; i++) {
3584 if (*p != '-') continue;
3586 if (*p == NULLCHAR) break;
3587 if (*p++ == '-') j++;
3589 if (j < 7) continue;
3592 scalable = fonts[i];
3595 err = pxlSize - targetPxlSize;
3596 if (Abs(err) < Abs(minerr) ||
3597 (minerr > 0 && err < 0 && -err == minerr)) {
3603 if (scalable && Abs(minerr) > appData.fontSizeTolerance) {
3604 /* If the error is too big and there is a scalable font,
3605 use the scalable font. */
3606 int headlen = scalableTail - scalable;
3607 p = (char *) XtMalloc(strlen(scalable) + 10);
3608 while (isdigit(*scalableTail)) scalableTail++;
3609 sprintf(p, "%.*s%d%s", headlen, scalable, targetPxlSize, scalableTail);
3611 p = (char *) XtMalloc(strlen(best) + 1);
3614 if (appData.debugMode) {
3615 fprintf(debugFP, _("resolved %s at pixel size %d\n to %s\n"),
3616 pattern, targetPxlSize, p);
3619 if (missing_count > 0)
3620 XFreeStringList(missing_list);
3621 XFreeFontSet(xDisplay, fntSet);
3623 XFreeFontNames(fonts);
3630 XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
3631 | GCBackground | GCFunction | GCPlaneMask;
3632 XGCValues gc_values;
3635 gc_values.plane_mask = AllPlanes;
3636 gc_values.line_width = lineGap;
3637 gc_values.line_style = LineSolid;
3638 gc_values.function = GXcopy;
3640 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3641 gc_values.background = XBlackPixel(xDisplay, xScreen);
3642 lineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3644 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3645 gc_values.background = XWhitePixel(xDisplay, xScreen);
3646 coordGC = XtGetGC(shellWidget, value_mask, &gc_values);
3647 XSetFont(xDisplay, coordGC, coordFontID);
3649 // [HGM] make font for holdings counts (white on black0
3650 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3651 gc_values.background = XBlackPixel(xDisplay, xScreen);
3652 countGC = XtGetGC(shellWidget, value_mask, &gc_values);
3653 XSetFont(xDisplay, countGC, countFontID);
3655 if (appData.monoMode) {
3656 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3657 gc_values.background = XWhitePixel(xDisplay, xScreen);
3658 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3660 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3661 gc_values.background = XBlackPixel(xDisplay, xScreen);
3662 lightSquareGC = wbPieceGC
3663 = XtGetGC(shellWidget, value_mask, &gc_values);
3665 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3666 gc_values.background = XWhitePixel(xDisplay, xScreen);
3667 darkSquareGC = bwPieceGC
3668 = XtGetGC(shellWidget, value_mask, &gc_values);
3670 if (DefaultDepth(xDisplay, xScreen) == 1) {
3671 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
3672 gc_values.function = GXcopyInverted;
3673 copyInvertedGC = XtGetGC(shellWidget, value_mask, &gc_values);
3674 gc_values.function = GXcopy;
3675 if (XBlackPixel(xDisplay, xScreen) == 1) {
3676 bwPieceGC = darkSquareGC;
3677 wbPieceGC = copyInvertedGC;
3679 bwPieceGC = copyInvertedGC;
3680 wbPieceGC = lightSquareGC;
3684 gc_values.foreground = highlightSquareColor;
3685 gc_values.background = highlightSquareColor;
3686 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3688 gc_values.foreground = premoveHighlightColor;
3689 gc_values.background = premoveHighlightColor;
3690 prelineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3692 gc_values.foreground = lightSquareColor;
3693 gc_values.background = darkSquareColor;
3694 lightSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3696 gc_values.foreground = darkSquareColor;
3697 gc_values.background = lightSquareColor;
3698 darkSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3700 gc_values.foreground = jailSquareColor;
3701 gc_values.background = jailSquareColor;
3702 jailSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3704 gc_values.foreground = whitePieceColor;
3705 gc_values.background = darkSquareColor;
3706 wdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3708 gc_values.foreground = whitePieceColor;
3709 gc_values.background = lightSquareColor;
3710 wlPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3712 gc_values.foreground = whitePieceColor;
3713 gc_values.background = jailSquareColor;
3714 wjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3716 gc_values.foreground = blackPieceColor;
3717 gc_values.background = darkSquareColor;
3718 bdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3720 gc_values.foreground = blackPieceColor;
3721 gc_values.background = lightSquareColor;
3722 blPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3724 gc_values.foreground = blackPieceColor;
3725 gc_values.background = jailSquareColor;
3726 bjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3730 void loadXIM(xim, xmask, filename, dest, mask)
3743 fp = fopen(filename, "rb");
3745 fprintf(stderr, _("%s: error loading XIM!\n"), programName);
3752 for (y=0; y<h; ++y) {
3753 for (x=0; x<h; ++x) {
3758 XPutPixel(xim, x, y, blackPieceColor);
3760 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3763 XPutPixel(xim, x, y, darkSquareColor);
3765 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3768 XPutPixel(xim, x, y, whitePieceColor);
3770 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3773 XPutPixel(xim, x, y, lightSquareColor);
3775 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3781 /* create Pixmap of piece */
3782 *dest = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3784 XPutImage(xDisplay, *dest, lightSquareGC, xim,
3787 /* create Pixmap of clipmask
3788 Note: We assume the white/black pieces have the same
3789 outline, so we make only 6 masks. This is okay
3790 since the XPM clipmask routines do the same. */
3792 temp = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3794 XPutImage(xDisplay, temp, lightSquareGC, xmask,
3797 /* now create the 1-bit version */
3798 *mask = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3801 values.foreground = 1;
3802 values.background = 0;
3804 /* Don't use XtGetGC, not read only */
3805 maskGC = XCreateGC(xDisplay, *mask,
3806 GCForeground | GCBackground, &values);
3807 XCopyPlane(xDisplay, temp, *mask, maskGC,
3808 0, 0, squareSize, squareSize, 0, 0, 1);
3809 XFreePixmap(xDisplay, temp);
3814 char pieceBitmapNames[] = "pnbrqfeacwmohijgdvlsukpnsl";
3816 void CreateXIMPieces()
3821 static char *ximkind[] = { "ll", "ld", "dl", "dd" };
3826 /* The XSynchronize calls were copied from CreatePieces.
3827 Not sure if needed, but can't hurt */
3828 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3831 /* temp needed by loadXIM() */
3832 ximtemp = XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3833 0, 0, ss, ss, AllPlanes, XYPixmap);
3835 if (strlen(appData.pixmapDirectory) == 0) {
3839 if (appData.monoMode) {
3840 DisplayFatalError(_("XIM pieces cannot be used in monochrome mode"),
3844 fprintf(stderr, _("\nLoading XIMs...\n"));
3846 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3847 fprintf(stderr, "%d", piece+1);
3848 for (kind=0; kind<4; kind++) {
3849 fprintf(stderr, ".");
3850 snprintf(buf, sizeof(buf), "%s/%s%c%s%u.xim",
3851 ExpandPathName(appData.pixmapDirectory),
3852 piece <= (int) WhiteKing ? "" : "w",
3853 pieceBitmapNames[piece],
3855 ximPieceBitmap[kind][piece] =
3856 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3857 0, 0, ss, ss, AllPlanes, XYPixmap);
3858 if (appData.debugMode)
3859 fprintf(stderr, _("(File:%s:) "), buf);
3860 loadXIM(ximPieceBitmap[kind][piece],
3862 &(xpmPieceBitmap2[kind][piece]),
3863 &(ximMaskPm2[piece]));
3864 if(piece <= (int)WhiteKing)
3865 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3867 fprintf(stderr," ");
3869 /* Load light and dark squares */
3870 /* If the LSQ and DSQ pieces don't exist, we will
3871 draw them with solid squares. */
3872 snprintf(buf,sizeof(buf), "%s/lsq%u.xim", ExpandPathName(appData.pixmapDirectory), ss);
3873 if (access(buf, 0) != 0) {
3877 fprintf(stderr, _("light square "));
3879 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3880 0, 0, ss, ss, AllPlanes, XYPixmap);
3881 if (appData.debugMode)
3882 fprintf(stderr, _("(File:%s:) "), buf);
3884 loadXIM(ximLightSquare, NULL, buf, &xpmLightSquare, NULL);
3885 fprintf(stderr, _("dark square "));
3886 snprintf(buf,sizeof(buf), "%s/dsq%u.xim",
3887 ExpandPathName(appData.pixmapDirectory), ss);
3888 if (appData.debugMode)
3889 fprintf(stderr, _("(File:%s:) "), buf);
3891 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3892 0, 0, ss, ss, AllPlanes, XYPixmap);
3893 loadXIM(ximDarkSquare, NULL, buf, &xpmDarkSquare, NULL);
3894 xpmJailSquare = xpmLightSquare;
3896 fprintf(stderr, _("Done.\n"));
3898 XSynchronize(xDisplay, False); /* Work-around for xlib/xt buffering bug */
3902 void CreateXPMPieces()
3906 u_int ss = squareSize;
3908 static char *xpmkind[] = { "ll", "ld", "dl", "dd" };
3909 XpmColorSymbol symbols[4];
3912 /* Apparently some versions of Xpm don't define XpmFormat at all --tpm */
3913 if (appData.debugMode) {
3914 fprintf(stderr, "XPM Library Version: %d.%d%c\n",
3915 XpmFormat, XpmVersion, (char)('a' + XpmRevision - 1));
3919 /* The XSynchronize calls were copied from CreatePieces.
3920 Not sure if needed, but can't hurt */
3921 XSynchronize(xDisplay, True); /* Work-around for xlib/xt buffering bug */
3923 /* Setup translations so piece colors match square colors */
3924 symbols[0].name = "light_piece";
3925 symbols[0].value = appData.whitePieceColor;
3926 symbols[1].name = "dark_piece";
3927 symbols[1].value = appData.blackPieceColor;
3928 symbols[2].name = "light_square";
3929 symbols[2].value = appData.lightSquareColor;
3930 symbols[3].name = "dark_square";
3931 symbols[3].value = appData.darkSquareColor;
3933 attr.valuemask = XpmColorSymbols;
3934 attr.colorsymbols = symbols;
3935 attr.numsymbols = 4;
3937 if (appData.monoMode) {
3938 DisplayFatalError(_("XPM pieces cannot be used in monochrome mode"),
3942 if (strlen(appData.pixmapDirectory) == 0) {
3943 XpmPieces* pieces = builtInXpms;
3946 while (pieces->size != squareSize && pieces->size) pieces++;
3947 if (!pieces->size) {
3948 fprintf(stderr, _("No builtin XPM pieces of size %d\n"), squareSize);
3951 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3952 for (kind=0; kind<4; kind++) {
3954 if ((r=XpmCreatePixmapFromData(xDisplay, xBoardWindow,
3955 pieces->xpm[piece][kind],
3956 &(xpmPieceBitmap2[kind][piece]),
3957 NULL, &attr)) != 0) {
3958 fprintf(stderr, _("Error %d loading XPM image \"%s\"\n"),
3962 if(piece <= (int) WhiteKing)
3963 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3967 xpmJailSquare = xpmLightSquare;
3971 fprintf(stderr, _("\nLoading XPMs...\n"));
3974 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3975 fprintf(stderr, "%d ", piece+1);
3976 for (kind=0; kind<4; kind++) {
3977 snprintf(buf, sizeof(buf), "%s/%s%c%s%u.xpm",
3978 ExpandPathName(appData.pixmapDirectory),
3979 piece > (int) WhiteKing ? "w" : "",
3980 pieceBitmapNames[piece],
3982 if (appData.debugMode) {
3983 fprintf(stderr, _("(File:%s:) "), buf);
3985 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3986 &(xpmPieceBitmap2[kind][piece]),
3987 NULL, &attr)) != 0) {
3988 if(piece != (int)WhiteKing && piece > (int)WhiteQueen) {
3989 // [HGM] missing: read of unorthodox piece failed; substitute King.
3990 snprintf(buf, sizeof(buf), "%s/k%s%u.xpm",
3991 ExpandPathName(appData.pixmapDirectory),
3993 if (appData.debugMode) {
3994 fprintf(stderr, _("(Replace by File:%s:) "), buf);
3996 r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3997 &(xpmPieceBitmap2[kind][piece]),
4001 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"),
4006 if(piece <= (int) WhiteKing)
4007 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
4010 /* Load light and dark squares */
4011 /* If the LSQ and DSQ pieces don't exist, we will
4012 draw them with solid squares. */
4013 fprintf(stderr, _("light square "));
4014 snprintf(buf, sizeof(buf), "%s/lsq%u.xpm", ExpandPathName(appData.pixmapDirectory), ss);
4015 if (access(buf, 0) != 0) {
4019 if (appData.debugMode)
4020 fprintf(stderr, _("(File:%s:) "), buf);
4022 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
4023 &xpmLightSquare, NULL, &attr)) != 0) {
4024 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
4027 fprintf(stderr, _("dark square "));
4028 snprintf(buf, sizeof(buf), "%s/dsq%u.xpm",
4029 ExpandPathName(appData.pixmapDirectory), ss);
4030 if (appData.debugMode) {
4031 fprintf(stderr, _("(File:%s:) "), buf);
4033 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
4034 &xpmDarkSquare, NULL, &attr)) != 0) {
4035 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
4039 xpmJailSquare = xpmLightSquare;
4040 fprintf(stderr, _("Done.\n"));
4042 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
4045 #endif /* HAVE_LIBXPM */
4048 /* No built-in bitmaps */
4053 u_int ss = squareSize;
4055 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
4058 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
4059 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
4060 sprintf(buf, "%s%c%u%c.bm", piece > (int)WhiteKing ? "w" : "",
4061 pieceBitmapNames[piece],
4062 ss, kind == SOLID ? 's' : 'o');
4063 ReadBitmap(&pieceBitmap2[kind][piece], buf, NULL, ss, ss);
4064 if(piece <= (int)WhiteKing)
4065 pieceBitmap[kind][piece] = pieceBitmap2[kind][piece];
4069 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
4073 /* With built-in bitmaps */
4076 BuiltInBits* bib = builtInBits;
4079 u_int ss = squareSize;
4081 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
4084 while (bib->squareSize != ss && bib->squareSize != 0) bib++;
4086 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
4087 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
4088 sprintf(buf, "%s%c%u%c.bm", piece > (int)WhiteKing ? "w" : "",
4089 pieceBitmapNames[piece],
4090 ss, kind == SOLID ? 's' : 'o');
4091 ReadBitmap(&pieceBitmap2[kind][piece], buf,
4092 bib->bits[kind][piece], ss, ss);
4093 if(piece <= (int)WhiteKing)
4094 pieceBitmap[kind][piece] = pieceBitmap2[kind][piece];
4098 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
4103 void ReadBitmap(pm, name, bits, wreq, hreq)
4106 unsigned char bits[];
4112 char msg[MSG_SIZ], fullname[MSG_SIZ];
4114 if (*appData.bitmapDirectory != NULLCHAR) {
4115 strcpy(fullname, appData.bitmapDirectory);
4116 strcat(fullname, "/");
4117 strcat(fullname, name);
4118 errcode = XReadBitmapFile(xDisplay, xBoardWindow, fullname,
4119 &w, &h, pm, &x_hot, &y_hot);
4120 fprintf(stderr, "load %s\n", name);
4121 if (errcode != BitmapSuccess) {
4123 case BitmapOpenFailed:
4124 snprintf(msg, sizeof(msg), _("Can't open bitmap file %s"), fullname);
4126 case BitmapFileInvalid:
4127 snprintf(msg, sizeof(msg), _("Invalid bitmap in file %s"), fullname);
4129 case BitmapNoMemory:
4130 snprintf(msg, sizeof(msg), _("Ran out of memory reading bitmap file %s"),
4134 snprintf(msg, sizeof(msg), _("Unknown XReadBitmapFile error %d on file %s"),
4138 fprintf(stderr, _("%s: %s...using built-in\n"),
4140 } else if (w != wreq || h != hreq) {
4142 _("%s: Bitmap %s is %dx%d, not %dx%d...using built-in\n"),
4143 programName, fullname, w, h, wreq, hreq);
4150 fprintf(stderr, _("%s: No built-in bitmap for %s; giving up\n"),
4154 ; // [HGM] bitmaps: make it non-fatal if we have no bitmap;
4156 *pm = XCreateBitmapFromData(xDisplay, xBoardWindow, (char *) bits,
4165 if (lineGap == 0) return;
4167 /* [HR] Split this into 2 loops for non-square boards. */
4169 for (i = 0; i < BOARD_HEIGHT + 1; i++) {
4170 gridSegments[i].x1 = 0;
4171 gridSegments[i].x2 =
4172 lineGap + BOARD_WIDTH * (squareSize + lineGap);
4173 gridSegments[i].y1 = gridSegments[i].y2
4174 = lineGap / 2 + (i * (squareSize + lineGap));
4177 for (j = 0; j < BOARD_WIDTH + 1; j++) {
4178 gridSegments[j + i].y1 = 0;
4179 gridSegments[j + i].y2 =
4180 lineGap + BOARD_HEIGHT * (squareSize + lineGap);
4181 gridSegments[j + i].x1 = gridSegments[j + i].x2
4182 = lineGap / 2 + (j * (squareSize + lineGap));
4186 static void MenuBarSelect(w, addr, index)
4191 XtActionProc proc = (XtActionProc) addr;
4193 (proc)(NULL, NULL, NULL, NULL);
4196 void CreateMenuBarPopup(parent, name, mb)
4206 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
4209 XtSetArg(args[j], XtNleftMargin, 20); j++;
4210 XtSetArg(args[j], XtNrightMargin, 20); j++;
4212 while (mi->string != NULL) {
4213 if (strcmp(mi->string, "----") == 0) {
4214 entry = XtCreateManagedWidget(mi->string, smeLineObjectClass,
4217 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string)));
4218 entry = XtCreateManagedWidget(mi->string, smeBSBObjectClass,
4220 XtAddCallback(entry, XtNcallback,
4221 (XtCallbackProc) MenuBarSelect,
4222 (caddr_t) mi->proc);
4228 Widget CreateMenuBar(mb)
4232 Widget anchor, menuBar;
4234 char menuName[MSG_SIZ];
4237 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
4238 XtSetArg(args[j], XtNvSpace, 0); j++;
4239 XtSetArg(args[j], XtNborderWidth, 0); j++;
4240 menuBar = XtCreateWidget("menuBar", boxWidgetClass,
4241 formWidget, args, j);
4243 while (mb->name != NULL) {
4244 strcpy(menuName, "menu");
4245 strcat(menuName, mb->name);
4247 XtSetArg(args[j], XtNmenuName, XtNewString(menuName)); j++;
4250 shortName[0] = _(mb->name)[0];
4251 shortName[1] = NULLCHAR;
4252 XtSetArg(args[j], XtNlabel, XtNewString(shortName)); j++;
4255 XtSetArg(args[j], XtNlabel, XtNewString(_(mb->name))); j++;
4258 XtSetArg(args[j], XtNborderWidth, 0); j++;
4259 anchor = XtCreateManagedWidget(mb->name, menuButtonWidgetClass,
4261 CreateMenuBarPopup(menuBar, menuName, mb);
4267 Widget CreateButtonBar(mi)
4271 Widget button, buttonBar;
4275 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
4277 XtSetArg(args[j], XtNhSpace, 0); j++;
4279 XtSetArg(args[j], XtNborderWidth, 0); j++;
4280 XtSetArg(args[j], XtNvSpace, 0); j++;
4281 buttonBar = XtCreateWidget("buttonBar", boxWidgetClass,
4282 formWidget, args, j);
4284 while (mi->string != NULL) {
4287 XtSetArg(args[j], XtNinternalWidth, 2); j++;
4288 XtSetArg(args[j], XtNborderWidth, 0); j++;
4290 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string))); j++;
4291 button = XtCreateManagedWidget(mi->string, commandWidgetClass,
4292 buttonBar, args, j);
4293 XtAddCallback(button, XtNcallback,
4294 (XtCallbackProc) MenuBarSelect,
4295 (caddr_t) mi->proc);
4302 CreatePieceMenu(name, color)
4309 ChessSquare selection;
4311 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
4312 boardWidget, args, 0);
4314 for (i = 0; i < PIECE_MENU_SIZE; i++) {
4315 String item = pieceMenuStrings[color][i];
4317 if (strcmp(item, "----") == 0) {
4318 entry = XtCreateManagedWidget(item, smeLineObjectClass,
4321 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
4322 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
4324 selection = pieceMenuTranslation[color][i];
4325 XtAddCallback(entry, XtNcallback,
4326 (XtCallbackProc) PieceMenuSelect,
4327 (caddr_t) selection);
4328 if (selection == WhitePawn || selection == BlackPawn) {
4329 XtSetArg(args[0], XtNpopupOnEntry, entry);
4330 XtSetValues(menu, args, 1);
4343 ChessSquare selection;
4345 whitePieceMenu = CreatePieceMenu("menuW", 0);
4346 blackPieceMenu = CreatePieceMenu("menuB", 1);
4348 XtRegisterGrabAction(PieceMenuPopup, True,
4349 (unsigned)(ButtonPressMask|ButtonReleaseMask),
4350 GrabModeAsync, GrabModeAsync);
4352 XtSetArg(args[0], XtNlabel, _("Drop"));
4353 dropMenu = XtCreatePopupShell("menuD", simpleMenuWidgetClass,
4354 boardWidget, args, 1);
4355 for (i = 0; i < DROP_MENU_SIZE; i++) {
4356 String item = dropMenuStrings[i];
4358 if (strcmp(item, "----") == 0) {
4359 entry = XtCreateManagedWidget(item, smeLineObjectClass,
4362 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
4363 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
4365 selection = dropMenuTranslation[i];
4366 XtAddCallback(entry, XtNcallback,
4367 (XtCallbackProc) DropMenuSelect,
4368 (caddr_t) selection);
4373 void SetupDropMenu()
4381 for (i=0; i<sizeof(dmEnables)/sizeof(DropMenuEnables); i++) {
4382 entry = XtNameToWidget(dropMenu, dmEnables[i].widget);
4383 p = strchr(gameMode == IcsPlayingWhite ? white_holding : black_holding,
4384 dmEnables[i].piece);
4385 XtSetSensitive(entry, p != NULL || !appData.testLegality
4386 /*!!temp:*/ || (gameInfo.variant == VariantCrazyhouse
4387 && !appData.icsActive));
4389 while (p && *p++ == dmEnables[i].piece) count++;
4390 snprintf(label, sizeof(label), "%s %d", dmEnables[i].widget, count);
4392 XtSetArg(args[j], XtNlabel, label); j++;
4393 XtSetValues(entry, args, j);
4397 void PieceMenuPopup(w, event, params, num_params)
4401 Cardinal *num_params;
4404 if (event->type != ButtonPress) return;
4405 if (errorUp) ErrorPopDown();
4409 whichMenu = params[0];
4411 case IcsPlayingWhite:
4412 case IcsPlayingBlack:
4414 case MachinePlaysWhite:
4415 case MachinePlaysBlack:
4416 if (appData.testLegality &&
4417 gameInfo.variant != VariantBughouse &&
4418 gameInfo.variant != VariantCrazyhouse) return;
4420 whichMenu = "menuD";
4426 if (((pmFromX = EventToSquare(event->xbutton.x, BOARD_WIDTH)) < 0) ||
4427 ((pmFromY = EventToSquare(event->xbutton.y, BOARD_HEIGHT)) < 0)) {
4428 pmFromX = pmFromY = -1;
4432 pmFromX = BOARD_WIDTH - 1 - pmFromX;
4434 pmFromY = BOARD_HEIGHT - 1 - pmFromY;
4436 XtPopupSpringLoaded(XtNameToWidget(boardWidget, whichMenu));
4439 static void PieceMenuSelect(w, piece, junk)
4444 if (pmFromX < 0 || pmFromY < 0) return;
4445 EditPositionMenuEvent(piece, pmFromX, pmFromY);
4448 static void DropMenuSelect(w, piece, junk)
4453 if (pmFromX < 0 || pmFromY < 0) return;
4454 DropMenuEvent(piece, pmFromX, pmFromY);
4457 void WhiteClock(w, event, prms, nprms)
4463 if (gameMode == EditPosition || gameMode == IcsExamining) {
4464 SetWhiteToPlayEvent();
4465 } else if (gameMode == IcsPlayingBlack || gameMode == MachinePlaysWhite) {
4470 void BlackClock(w, event, prms, nprms)
4476 if (gameMode == EditPosition || gameMode == IcsExamining) {
4477 SetBlackToPlayEvent();
4478 } else if (gameMode == IcsPlayingWhite || gameMode == MachinePlaysBlack) {
4485 * If the user selects on a border boundary, return -1; if off the board,
4486 * return -2. Otherwise map the event coordinate to the square.
4488 int EventToSquare(x, limit)
4496 if ((x % (squareSize + lineGap)) >= squareSize)
4498 x /= (squareSize + lineGap);
4504 static void do_flash_delay(msec)
4510 static void drawHighlight(file, rank, gc)
4516 if (lineGap == 0 || appData.blindfold) return;
4519 x = lineGap/2 + ((BOARD_WIDTH-1)-file) *
4520 (squareSize + lineGap);
4521 y = lineGap/2 + rank * (squareSize + lineGap);
4523 x = lineGap/2 + file * (squareSize + lineGap);
4524 y = lineGap/2 + ((BOARD_HEIGHT-1)-rank) *
4525 (squareSize + lineGap);
4528 XDrawRectangle(xDisplay, xBoardWindow, gc, x, y,
4529 squareSize+lineGap, squareSize+lineGap);
4532 int hi1X = -1, hi1Y = -1, hi2X = -1, hi2Y = -1;
4533 int pm1X = -1, pm1Y = -1, pm2X = -1, pm2Y = -1;
4536 SetHighlights(fromX, fromY, toX, toY)
4537 int fromX, fromY, toX, toY;
4539 if (hi1X != fromX || hi1Y != fromY) {
4540 if (hi1X >= 0 && hi1Y >= 0) {
4541 drawHighlight(hi1X, hi1Y, lineGC);
4543 if (fromX >= 0 && fromY >= 0) {
4544 drawHighlight(fromX, fromY, highlineGC);
4547 if (hi2X != toX || hi2Y != toY) {
4548 if (hi2X >= 0 && hi2Y >= 0) {
4549 drawHighlight(hi2X, hi2Y, lineGC);
4551 if (toX >= 0 && toY >= 0) {
4552 drawHighlight(toX, toY, highlineGC);
4564 SetHighlights(-1, -1, -1, -1);
4569 SetPremoveHighlights(fromX, fromY, toX, toY)
4570 int fromX, fromY, toX, toY;
4572 if (pm1X != fromX || pm1Y != fromY) {
4573 if (pm1X >= 0 && pm1Y >= 0) {
4574 drawHighlight(pm1X, pm1Y, lineGC);
4576 if (fromX >= 0 && fromY >= 0) {
4577 drawHighlight(fromX, fromY, prelineGC);
4580 if (pm2X != toX || pm2Y != toY) {
4581 if (pm2X >= 0 && pm2Y >= 0) {
4582 drawHighlight(pm2X, pm2Y, lineGC);
4584 if (toX >= 0 && toY >= 0) {
4585 drawHighlight(toX, toY, prelineGC);
4595 ClearPremoveHighlights()
4597 SetPremoveHighlights(-1, -1, -1, -1);
4600 static void BlankSquare(x, y, color, piece, dest)
4605 if (useImages && useImageSqs) {
4609 pm = xpmLightSquare;
4614 case 2: /* neutral */
4619 XCopyArea(xDisplay, pm, dest, wlPieceGC, 0, 0,
4620 squareSize, squareSize, x, y);
4630 case 2: /* neutral */
4635 XFillRectangle(xDisplay, dest, gc, x, y, squareSize, squareSize);
4640 I split out the routines to draw a piece so that I could
4641 make a generic flash routine.
4643 static void monoDrawPiece_1bit(piece, square_color, x, y, dest)
4645 int square_color, x, y;
4648 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
4649 switch (square_color) {
4651 case 2: /* neutral */
4653 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
4654 ? *pieceToOutline(piece)
4655 : *pieceToSolid(piece),
4656 dest, bwPieceGC, 0, 0,
4657 squareSize, squareSize, x, y);
4660 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
4661 ? *pieceToSolid(piece)
4662 : *pieceToOutline(piece),
4663 dest, wbPieceGC, 0, 0,
4664 squareSize, squareSize, x, y);
4669 static void monoDrawPiece(piece, square_color, x, y, dest)
4671 int square_color, x, y;
4674 switch (square_color) {
4676 case 2: /* neutral */
4678 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
4679 ? *pieceToOutline(piece)
4680 : *pieceToSolid(piece),
4681 dest, bwPieceGC, 0, 0,
4682 squareSize, squareSize, x, y, 1);
4685 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
4686 ? *pieceToSolid(piece)
4687 : *pieceToOutline(piece),
4688 dest, wbPieceGC, 0, 0,
4689 squareSize, squareSize, x, y, 1);
4694 static void colorDrawPiece(piece, square_color, x, y, dest)
4696 int square_color, x, y;
4699 if(pieceToSolid(piece) == NULL) return; // [HGM] bitmaps: make it non-fatal if we have no bitmap;
4700 switch (square_color) {
4702 XCopyPlane(xDisplay, *pieceToSolid(piece),
4703 dest, (int) piece < (int) BlackPawn
4704 ? wlPieceGC : blPieceGC, 0, 0,
4705 squareSize, squareSize, x, y, 1);
4708 XCopyPlane(xDisplay, *pieceToSolid(piece),
4709 dest, (int) piece < (int) BlackPawn
4710 ? wdPieceGC : bdPieceGC, 0, 0,
4711 squareSize, squareSize, x, y, 1);
4713 case 2: /* neutral */
4715 XCopyPlane(xDisplay, *pieceToSolid(piece),
4716 dest, (int) piece < (int) BlackPawn
4717 ? wjPieceGC : bjPieceGC, 0, 0,
4718 squareSize, squareSize, x, y, 1);
4723 static void colorDrawPieceImage(piece, square_color, x, y, dest)
4725 int square_color, x, y;
4730 switch (square_color) {
4732 case 2: /* neutral */
4734 if ((int)piece < (int) BlackPawn) {
4742 if ((int)piece < (int) BlackPawn) {
4750 XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
4751 dest, wlPieceGC, 0, 0,
4752 squareSize, squareSize, x, y);
4755 typedef void (*DrawFunc)();
4757 DrawFunc ChooseDrawFunc()
4759 if (appData.monoMode) {
4760 if (DefaultDepth(xDisplay, xScreen) == 1) {
4761 return monoDrawPiece_1bit;
4763 return monoDrawPiece;
4767 return colorDrawPieceImage;
4769 return colorDrawPiece;
4773 /* [HR] determine square color depending on chess variant. */
4774 static int SquareColor(row, column)
4779 if (gameInfo.variant == VariantXiangqi) {
4780 if (column >= 3 && column <= 5 && row >= 0 && row <= 2) {
4782 } else if (column >= 3 && column <= 5 && row >= 7 && row <= 9) {
4784 } else if (row <= 4) {
4790 square_color = ((column + row) % 2) == 1;
4793 /* [hgm] holdings: next line makes all holdings squares light */
4794 if(column < BOARD_LEFT || column >= BOARD_RGHT) square_color = 1;
4796 return square_color;
4799 void DrawSquare(row, column, piece, do_flash)
4800 int row, column, do_flash;
4803 int square_color, x, y, direction, font_ascent, font_descent;
4806 XCharStruct overall;
4810 /* Calculate delay in milliseconds (2-delays per complete flash) */
4811 flash_delay = 500 / appData.flashRate;
4814 x = lineGap + ((BOARD_WIDTH-1)-column) *
4815 (squareSize + lineGap);
4816 y = lineGap + row * (squareSize + lineGap);
4818 x = lineGap + column * (squareSize + lineGap);
4819 y = lineGap + ((BOARD_HEIGHT-1)-row) *
4820 (squareSize + lineGap);
4823 square_color = SquareColor(row, column);
4825 if ( // [HGM] holdings: blank out area between board and holdings
4826 column == BOARD_LEFT-1 || column == BOARD_RGHT
4827 || (column == BOARD_LEFT-2 && row < BOARD_HEIGHT-gameInfo.holdingsSize)
4828 || (column == BOARD_RGHT+1 && row >= gameInfo.holdingsSize) ) {
4829 BlankSquare(x, y, 2, EmptySquare, xBoardWindow);
4831 // [HGM] print piece counts next to holdings
4832 string[1] = NULLCHAR;
4833 if (column == (flipView ? BOARD_LEFT-1 : BOARD_RGHT) && piece > 1 ) {
4834 string[0] = '0' + piece;
4835 XTextExtents(countFontStruct, string, 1, &direction,
4836 &font_ascent, &font_descent, &overall);
4837 if (appData.monoMode) {
4838 XDrawImageString(xDisplay, xBoardWindow, countGC,
4839 x + squareSize - overall.width - 2,
4840 y + font_ascent + 1, string, 1);
4842 XDrawString(xDisplay, xBoardWindow, countGC,
4843 x + squareSize - overall.width - 2,
4844 y + font_ascent + 1, string, 1);
4847 if (column == (flipView ? BOARD_RGHT : BOARD_LEFT-1) && piece > 1) {
4848 string[0] = '0' + piece;
4849 XTextExtents(countFontStruct, string, 1, &direction,
4850 &font_ascent, &font_descent, &overall);
4851 if (appData.monoMode) {
4852 XDrawImageString(xDisplay, xBoardWindow, countGC,
4853 x + 2, y + font_ascent + 1, string, 1);
4855 XDrawString(xDisplay, xBoardWindow, countGC,
4856 x + 2, y + font_ascent + 1, string, 1);
4860 if (piece == EmptySquare || appData.blindfold) {
4861 BlankSquare(x, y, square_color, piece, xBoardWindow);
4863 drawfunc = ChooseDrawFunc();
4864 if (do_flash && appData.flashCount > 0) {
4865 for (i=0; i<appData.flashCount; ++i) {
4867 drawfunc(piece, square_color, x, y, xBoardWindow);
4868 XSync(xDisplay, False);
4869 do_flash_delay(flash_delay);
4871 BlankSquare(x, y, square_color, piece, xBoardWindow);
4872 XSync(xDisplay, False);
4873 do_flash_delay(flash_delay);
4876 drawfunc(piece, square_color, x, y, xBoardWindow);
4880 string[1] = NULLCHAR;
4881 if (appData.showCoords && row == (flipView ? BOARD_HEIGHT-1 : 0)
4882 && column >= BOARD_LEFT && column < BOARD_RGHT) {
4883 string[0] = 'a' + column - BOARD_LEFT;
4884 XTextExtents(coordFontStruct, string, 1, &direction,
4885 &font_ascent, &font_descent, &overall);
4886 if (appData.monoMode) {
4887 XDrawImageString(xDisplay, xBoardWindow, coordGC,
4888 x + squareSize - overall.width - 2,
4889 y + squareSize - font_descent - 1, string, 1);
4891 XDrawString(xDisplay, xBoardWindow, coordGC,
4892 x + squareSize - overall.width - 2,
4893 y + squareSize - font_descent - 1, string, 1);
4896 if (appData.showCoords && column == (flipView ? BOARD_RGHT-1 : BOARD_LEFT)) {
4897 string[0] = ONE + row;
4898 XTextExtents(coordFontStruct, string, 1, &direction,
4899 &font_ascent, &font_descent, &overall);
4900 if (appData.monoMode) {
4901 XDrawImageString(xDisplay, xBoardWindow, coordGC,
4902 x + 2, y + font_ascent + 1, string, 1);
4904 XDrawString(xDisplay, xBoardWindow, coordGC,
4905 x + 2, y + font_ascent + 1, string, 1);
4911 /* Why is this needed on some versions of X? */
4912 void EventProc(widget, unused, event)
4917 if (!XtIsRealized(widget))
4920 switch (event->type) {
4922 if (event->xexpose.count > 0) return; /* no clipping is done */
4923 XDrawPosition(widget, True, NULL);
4931 void DrawPosition(fullRedraw, board)
4932 /*Boolean*/int fullRedraw;
4935 XDrawPosition(boardWidget, fullRedraw, board);
4938 /* Returns 1 if there are "too many" differences between b1 and b2
4939 (i.e. more than 1 move was made) */
4940 static int too_many_diffs(b1, b2)
4946 for (i=0; i<BOARD_HEIGHT; ++i) {
4947 for (j=0; j<BOARD_WIDTH; ++j) {
4948 if (b1[i][j] != b2[i][j]) {
4949 if (++c > 4) /* Castling causes 4 diffs */
4958 /* Matrix describing castling maneuvers */
4959 /* Row, ColRookFrom, ColKingFrom, ColRookTo, ColKingTo */
4960 static int castling_matrix[4][5] = {
4961 { 0, 0, 4, 3, 2 }, /* 0-0-0, white */
4962 { 0, 7, 4, 5, 6 }, /* 0-0, white */
4963 { 7, 0, 4, 3, 2 }, /* 0-0-0, black */
4964 { 7, 7, 4, 5, 6 } /* 0-0, black */
4967 /* Checks whether castling occurred. If it did, *rrow and *rcol
4968 are set to the destination (row,col) of the rook that moved.
4970 Returns 1 if castling occurred, 0 if not.
4972 Note: Only handles a max of 1 castling move, so be sure
4973 to call too_many_diffs() first.
4975 static int check_castle_draw(newb, oldb, rrow, rcol)
4982 /* For each type of castling... */
4983 for (i=0; i<4; ++i) {
4984 r = castling_matrix[i];
4986 /* Check the 4 squares involved in the castling move */
4988 for (j=1; j<=4; ++j) {
4989 if (newb[r[0]][r[j]] == oldb[r[0]][r[j]]) {
4996 /* All 4 changed, so it must be a castling move */
5005 static int damage[BOARD_SIZE][BOARD_SIZE];
5008 * event handler for redrawing the board
5010 void XDrawPosition(w, repaint, board)
5012 /*Boolean*/int repaint;
5016 static int lastFlipView = 0;
5017 static int lastBoardValid = 0;
5018 static Board lastBoard;
5022 if (board == NULL) {
5023 if (!lastBoardValid) return;
5026 if (!lastBoardValid || lastFlipView != flipView) {
5027 XtSetArg(args[0], XtNleftBitmap, (flipView ? xMarkPixmap : None));
5028 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flip View"),
5033 * It would be simpler to clear the window with XClearWindow()
5034 * but this causes a very distracting flicker.
5037 if (!repaint && lastBoardValid && lastFlipView == flipView) {
5039 /* If too much changes (begin observing new game, etc.), don't
5041 do_flash = too_many_diffs(board, lastBoard) ? 0 : 1;
5043 /* Special check for castling so we don't flash both the king
5044 and the rook (just flash the king). */
5046 if (check_castle_draw(board, lastBoard, &rrow, &rcol)) {
5047 /* Draw rook with NO flashing. King will be drawn flashing later */
5048 DrawSquare(rrow, rcol, board[rrow][rcol], 0);
5049 lastBoard[rrow][rcol] = board[rrow][rcol];
5053 /* First pass -- Draw (newly) empty squares and repair damage.
5054 This prevents you from having a piece show up twice while it
5055 is flashing on its new square */
5056 for (i = 0; i < BOARD_HEIGHT; i++)
5057 for (j = 0; j < BOARD_WIDTH; j++)
5058 if ((board[i][j] != lastBoard[i][j] && board[i][j] == EmptySquare)
5060 DrawSquare(i, j, board[i][j], 0);
5061 damage[i][j] = False;
5064 /* Second pass -- Draw piece(s) in new position and flash them */
5065 for (i = 0; i < BOARD_HEIGHT; i++)
5066 for (j = 0; j < BOARD_WIDTH; j++)
5067 if (board[i][j] != lastBoard[i][j]) {
5068 DrawSquare(i, j, board[i][j], do_flash);
5072 XDrawSegments(xDisplay, xBoardWindow, lineGC,
5073 gridSegments, BOARD_HEIGHT + BOARD_WIDTH + 2);
5075 for (i = 0; i < BOARD_HEIGHT; i++)
5076 for (j = 0; j < BOARD_WIDTH; j++) {
5077 DrawSquare(i, j, board[i][j], 0);
5078 damage[i][j] = False;
5082 CopyBoard(lastBoard, board);
5084 lastFlipView = flipView;
5086 /* Draw highlights */
5087 if (pm1X >= 0 && pm1Y >= 0) {
5088 drawHighlight(pm1X, pm1Y, prelineGC);
5090 if (pm2X >= 0 && pm2Y >= 0) {
5091 drawHighlight(pm2X, pm2Y, prelineGC);
5093 if (hi1X >= 0 && hi1Y >= 0) {
5094 drawHighlight(hi1X, hi1Y, highlineGC);
5096 if (hi2X >= 0 && hi2Y >= 0) {
5097 drawHighlight(hi2X, hi2Y, highlineGC);
5100 /* If piece being dragged around board, must redraw that too */
5103 XSync(xDisplay, False);
5108 * event handler for redrawing the board
5110 void DrawPositionProc(w, event, prms, nprms)
5116 XDrawPosition(w, True, NULL);
5121 * event handler for parsing user moves
5123 // [HGM] This routine will need quite some reworking. Although the backend still supports the old
5124 // way of doing things, by calling UserMoveEvent() to test the legality of the move and then perform
5125 // it at the end, and doing all kind of preliminary tests here (e.g. to weed out self-captures), it
5126 // should be made to use the new way, of calling UserMoveTest early to determine the legality of the
5127 // move, (which will weed out the illegal selfcaptures and moves into the holdings, and flag promotions),
5128 // and at the end FinishMove() to perform the move after optional promotion popups.
5129 // For now I patched it to allow self-capture with King, and suppress clicks between board and holdings.
5130 void HandleUserMove(w, event, prms, nprms)
5137 Boolean saveAnimate;
5138 static int second = 0, promotionChoice = 0;
5141 if (w != boardWidget || errorExitStatus != -1) return;
5143 x = EventToSquare(event->xbutton.x, BOARD_WIDTH);
5144 y = EventToSquare(event->xbutton.y, BOARD_HEIGHT);
5145 if (!flipView && y >= 0) {
5146 y = BOARD_HEIGHT - 1 - y;
5148 if (flipView && x >= 0) {
5149 x = BOARD_WIDTH - 1 - x;
5152 if(promotionChoice) { // we are waiting for a click to indicate promotion piece
5153 if(event->type == ButtonRelease) return; // ignore upclick of click-click destination
5154 promotionChoice = FALSE; // only one chance: if click not OK it is interpreted as cancel
5155 if(appData.debugMode) fprintf(debugFP, "promotion click, x=%d, y=%d\n", x, y);
5156 if(gameInfo.holdingsWidth &&
5157 (WhiteOnMove(currentMove)
5158 ? x == BOARD_WIDTH-1 && y < gameInfo.holdingsSize && y > 0
5159 : x == 0 && y >= BOARD_HEIGHT - gameInfo.holdingsSize && y < BOARD_HEIGHT-1) ) {
5160 // click in right holdings, for determining promotion piece
5161 ChessSquare p = boards[currentMove][y][x];
5162 if(appData.debugMode) fprintf(debugFP, "square contains %d\n", (int)p);
5163 if(p != EmptySquare) {
5164 FinishMove(NormalMove, fromX, fromY, toX, toY, ToLower(PieceToChar(p)));
5169 DrawPosition(FALSE, boards[currentMove]);
5172 if (event->type == ButtonPress) ErrorPopDown();
5175 if (event->type == ButtonPress) {
5176 XtPopdown(promotionShell);
5177 XtDestroyWidget(promotionShell);
5178 promotionUp = False;
5186 /* [HGM] holdings: next 5 lines: ignore all clicks between board and holdings */
5187 if(event->type == ButtonPress
5188 && ( x == BOARD_LEFT-1 || x == BOARD_RGHT
5189 || x == BOARD_LEFT-2 && y < BOARD_HEIGHT-gameInfo.holdingsSize
5190 || x == BOARD_RGHT+1 && y >= gameInfo.holdingsSize) )
5194 if (event->type == ButtonPress) {
5195 /* First square, prepare to drag */
5196 if (OKToStartUserMove(x, y)) {
5200 DragPieceBegin(event->xbutton.x, event->xbutton.y);
5201 if (appData.highlightDragging) {
5202 SetHighlights(x, y, -1, -1);
5210 if (event->type == ButtonRelease && x == fromX && y == fromY) {
5211 /* Click on single square in stead of drag-drop */
5212 DragPieceEnd(event->xbutton.x, event->xbutton.y);
5213 if (appData.animateDragging) {
5214 /* Undo animation damage if any */
5215 DrawPosition(FALSE, NULL);
5218 /* Second up/down in same square; just abort move */
5223 ClearPremoveHighlights();
5225 /* First upclick in same square; start click-click mode */
5226 SetHighlights(x, y, -1, -1);
5231 moveType = UserMoveTest(fromX, fromY, x, y, NULLCHAR, event->type == ButtonRelease);
5233 if (moveType == Comment) { // kludge for indicating capture-own on Press
5234 /* Clicked again on same color piece -- changed his mind */
5235 /* note that re-clicking same square always hits same color piece */
5236 second = (x == fromX && y == fromY);
5237 if (appData.highlightDragging) {
5238 SetHighlights(x, y, -1, -1);
5242 if (OKToStartUserMove(x, y)) {
5245 DragPieceBegin(event->xbutton.x, event->xbutton.y);
5250 if(moveType == AmbiguousMove) { // kludge to indicate edit-position move
5253 DragPieceEnd(event->xbutton.x, event->xbutton.y);
5254 DrawPosition(FALSE, boards[currentMove]);
5258 /* Complete move; (x,y) is now different from (fromX, fromY) on both Press and Release */
5261 saveAnimate = appData.animate;
5262 if (event->type == ButtonPress) {
5263 /* Finish clickclick move */
5264 if (appData.animate || appData.highlightLastMove) {
5265 SetHighlights(fromX, fromY, toX, toY);
5270 /* Finish drag move */
5271 if (appData.highlightLastMove) {
5272 SetHighlights(fromX, fromY, toX, toY);
5276 DragPieceEnd(event->xbutton.x, event->xbutton.y);
5277 /* Don't animate move and drag both */
5278 appData.animate = FALSE;
5280 if (moveType == WhitePromotionKnight || moveType == BlackPromotionKnight ||
5281 (moveType == WhitePromotionQueen || moveType == BlackPromotionQueen) &&
5282 appData.alwaysPromoteToQueen) { // promotion, but no choice
5283 FinishMove(moveType, fromX, fromY, toX, toY, 'q');
5285 if (moveType == WhitePromotionQueen || moveType == BlackPromotionQueen ) {
5286 SetHighlights(fromX, fromY, toX, toY);
5287 if(gameInfo.variant == VariantSuper || gameInfo.variant == VariantGreat) {
5288 // [HGM] super: promotion to captured piece selected from holdings
5289 ChessSquare p = boards[currentMove][fromY][fromX], q = boards[currentMove][toY][toX];
5290 promotionChoice = TRUE;
5291 // kludge follows to temporarily execute move on display, without promoting yet
5292 boards[currentMove][fromY][fromX] = EmptySquare; // move Pawn to 8th rank
5293 boards[currentMove][toY][toX] = p;
5294 DrawPosition(FALSE, boards[currentMove]);
5295 boards[currentMove][fromY][fromX] = p; // take back, but display stays
5296 boards[currentMove][toY][toX] = q;
5297 DisplayMessage("Click in holdings to choose piece", "");
5301 goto skipClearingFrom; // the skipped stuff is done asynchronously by PromotionCallback
5303 if(moveType != ImpossibleMove) { // valid move, but no promotion
5304 FinishMove(moveType, fromX, fromY, toX, toY, NULLCHAR);
5305 } else { // invalid move; could have set premove
5308 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
5309 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
5312 appData.animate = saveAnimate;
5313 if (appData.animate || appData.animateDragging) {
5314 /* Undo animation damage if needed */
5315 DrawPosition(FALSE, NULL);
5319 void AnimateUserMove (Widget w, XEvent * event,
5320 String * params, Cardinal * nParams)
5322 DragPieceMove(event->xmotion.x, event->xmotion.y);
5325 Widget CommentCreate(name, text, mutable, callback, lines)
5327 int /*Boolean*/ mutable;
5328 XtCallbackProc callback;
5332 Widget shell, layout, form, edit, b_ok, b_cancel, b_clear, b_close, b_edit;
5337 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5338 XtGetValues(boardWidget, args, j);
5341 XtSetArg(args[j], XtNresizable, True); j++;
5344 XtCreatePopupShell(name, topLevelShellWidgetClass,
5345 shellWidget, args, j);
5348 XtCreatePopupShell(name, transientShellWidgetClass,
5349 shellWidget, args, j);
5352 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
5353 layoutArgs, XtNumber(layoutArgs));
5355 XtCreateManagedWidget("form", formWidgetClass, layout,
5356 formArgs, XtNumber(formArgs));
5360 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
5361 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
5363 XtSetArg(args[j], XtNstring, text); j++;
5364 XtSetArg(args[j], XtNtop, XtChainTop); j++;
5365 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5366 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5367 XtSetArg(args[j], XtNright, XtChainRight); j++;
5368 XtSetArg(args[j], XtNresizable, True); j++;
5369 XtSetArg(args[j], XtNwidth, bw_width); j++; /*force wider than buttons*/
5371 XtSetArg(args[j], XtNscrollVertical, XawtextScrollWhenNeeded); j++;
5373 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
5374 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
5376 XtSetArg(args[j], XtNautoFill, True); j++;
5377 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
5379 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
5383 XtSetArg(args[j], XtNfromVert, edit); j++;
5384 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5385 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5386 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5387 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5389 XtCreateManagedWidget(_("ok"), commandWidgetClass, form, args, j);
5390 XtAddCallback(b_ok, XtNcallback, callback, (XtPointer) 0);
5393 XtSetArg(args[j], XtNfromVert, edit); j++;
5394 XtSetArg(args[j], XtNfromHoriz, b_ok); j++;
5395 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5396 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5397 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5398 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5400 XtCreateManagedWidget(_("cancel"), commandWidgetClass, form, args, j);
5401 XtAddCallback(b_cancel, XtNcallback, callback, (XtPointer) 0);
5404 XtSetArg(args[j], XtNfromVert, edit); j++;
5405 XtSetArg(args[j], XtNfromHoriz, b_cancel); j++;
5406 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5407 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5408 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5409 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5411 XtCreateManagedWidget(_("clear"), commandWidgetClass, form, args, j);
5412 XtAddCallback(b_clear, XtNcallback, callback, (XtPointer) 0);
5415 XtSetArg(args[j], XtNfromVert, edit); j++;
5416 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5417 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5418 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5419 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5421 XtCreateManagedWidget(_("close"), commandWidgetClass, form, args, j);
5422 XtAddCallback(b_close, XtNcallback, callback, (XtPointer) 0);
5425 XtSetArg(args[j], XtNfromVert, edit); j++;
5426 XtSetArg(args[j], XtNfromHoriz, b_close); j++;
5427 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5428 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5429 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5430 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5432 XtCreateManagedWidget(_("edit"), commandWidgetClass, form, args, j);
5433 XtAddCallback(b_edit, XtNcallback, callback, (XtPointer) 0);
5436 XtRealizeWidget(shell);
5438 if (commentX == -1) {
5441 Dimension pw_height;
5442 Dimension ew_height;
5445 XtSetArg(args[j], XtNheight, &ew_height); j++;
5446 XtGetValues(edit, args, j);
5449 XtSetArg(args[j], XtNheight, &pw_height); j++;
5450 XtGetValues(shell, args, j);
5451 commentH = pw_height + (lines - 1) * ew_height;
5452 commentW = bw_width - 16;
5454 XSync(xDisplay, False);
5456 /* This code seems to tickle an X bug if it is executed too soon
5457 after xboard starts up. The coordinates get transformed as if
5458 the main window was positioned at (0, 0).
5460 XtTranslateCoords(shellWidget,
5461 (bw_width - commentW) / 2, 0 - commentH / 2,
5462 &commentX, &commentY);
5464 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
5465 RootWindowOfScreen(XtScreen(shellWidget)),
5466 (bw_width - commentW) / 2, 0 - commentH / 2,
5471 if (commentY < 0) commentY = 0; /*avoid positioning top offscreen*/
5474 XtSetArg(args[j], XtNheight, commentH); j++;
5475 XtSetArg(args[j], XtNwidth, commentW); j++;
5476 XtSetArg(args[j], XtNx, commentX); j++;
5477 XtSetArg(args[j], XtNy, commentY); j++;
5478 XtSetValues(shell, args, j);
5479 XtSetKeyboardFocus(shell, edit);
5484 /* Used for analysis window and ICS input window */
5485 Widget MiscCreate(name, text, mutable, callback, lines)
5487 int /*Boolean*/ mutable;
5488 XtCallbackProc callback;
5492 Widget shell, layout, form, edit;
5494 Dimension bw_width, pw_height, ew_height, w, h;
5500 XtSetArg(args[j], XtNresizable, True); j++;
5503 XtCreatePopupShell(name, topLevelShellWidgetClass,
5504 shellWidget, args, j);
5507 XtCreatePopupShell(name, transientShellWidgetClass,
5508 shellWidget, args, j);
5511 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
5512 layoutArgs, XtNumber(layoutArgs));
5514 XtCreateManagedWidget("form", formWidgetClass, layout,
5515 formArgs, XtNumber(formArgs));
5519 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
5520 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
5522 XtSetArg(args[j], XtNstring, text); j++;
5523 XtSetArg(args[j], XtNtop, XtChainTop); j++;
5524 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5525 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5526 XtSetArg(args[j], XtNright, XtChainRight); j++;
5527 XtSetArg(args[j], XtNresizable, True); j++;
5529 XtSetArg(args[j], XtNscrollVertical, XawtextScrollWhenNeeded); j++;
5531 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
5532 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
5534 XtSetArg(args[j], XtNautoFill, True); j++;
5535 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
5537 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
5539 XtRealizeWidget(shell);
5542 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5543 XtGetValues(boardWidget, args, j);
5546 XtSetArg(args[j], XtNheight, &ew_height); j++;
5547 XtGetValues(edit, args, j);
5550 XtSetArg(args[j], XtNheight, &pw_height); j++;
5551 XtGetValues(shell, args, j);
5552 h = pw_height + (lines - 1) * ew_height;
5555 XSync(xDisplay, False);
5557 /* This code seems to tickle an X bug if it is executed too soon
5558 after xboard starts up. The coordinates get transformed as if
5559 the main window was positioned at (0, 0).
5561 XtTranslateCoords(shellWidget, (bw_width - w) / 2, 0 - h / 2, &x, &y);
5563 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
5564 RootWindowOfScreen(XtScreen(shellWidget)),
5565 (bw_width - w) / 2, 0 - h / 2, &xx, &yy, &junk);
5569 if (y < 0) y = 0; /*avoid positioning top offscreen*/
5572 XtSetArg(args[j], XtNheight, h); j++;
5573 XtSetArg(args[j], XtNwidth, w); j++;
5574 XtSetArg(args[j], XtNx, x); j++;
5575 XtSetArg(args[j], XtNy, y); j++;
5576 XtSetValues(shell, args, j);
5582 static int savedIndex; /* gross that this is global */
5584 void EditCommentPopUp(index, title, text)
5593 if (text == NULL) text = "";
5595 if (editShell == NULL) {
5597 CommentCreate(title, text, True, EditCommentCallback, 4);
5598 XtRealizeWidget(editShell);
5599 CatchDeleteWindow(editShell, "EditCommentPopDown");
5601 edit = XtNameToWidget(editShell, "*form.text");
5603 XtSetArg(args[j], XtNstring, text); j++;
5604 XtSetValues(edit, args, j);
5606 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5607 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5608 XtSetValues(editShell, args, j);
5611 XtPopup(editShell, XtGrabNone);
5615 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
5616 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
5620 void EditCommentCallback(w, client_data, call_data)
5622 XtPointer client_data, call_data;
5630 XtSetArg(args[j], XtNlabel, &name); j++;
5631 XtGetValues(w, args, j);
5633 if (strcmp(name, _("ok")) == 0) {
5634 edit = XtNameToWidget(editShell, "*form.text");
5636 XtSetArg(args[j], XtNstring, &val); j++;
5637 XtGetValues(edit, args, j);
5638 ReplaceComment(savedIndex, val);
5639 EditCommentPopDown();
5640 } else if (strcmp(name, _("cancel")) == 0) {
5641 EditCommentPopDown();
5642 } else if (strcmp(name, _("clear")) == 0) {
5643 edit = XtNameToWidget(editShell, "*form.text");
5644 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
5645 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
5649 void EditCommentPopDown()
5654 if (!editUp) return;
5656 XtSetArg(args[j], XtNx, &commentX); j++;
5657 XtSetArg(args[j], XtNy, &commentY); j++;
5658 XtSetArg(args[j], XtNheight, &commentH); j++;
5659 XtSetArg(args[j], XtNwidth, &commentW); j++;
5660 XtGetValues(editShell, args, j);
5661 XtPopdown(editShell);
5664 XtSetArg(args[j], XtNleftBitmap, None); j++;
5665 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
5669 void ICSInputBoxPopUp()
5674 char *title = _("ICS Input");
5677 if (ICSInputShell == NULL) {
5678 ICSInputShell = MiscCreate(title, "", True, NULL, 1);
5679 tr = XtParseTranslationTable(ICSInputTranslations);
5680 edit = XtNameToWidget(ICSInputShell, "*form.text");
5681 XtOverrideTranslations(edit, tr);
5682 XtRealizeWidget(ICSInputShell);
5683 CatchDeleteWindow(ICSInputShell, "ICSInputBoxPopDown");
5686 edit = XtNameToWidget(ICSInputShell, "*form.text");
5688 XtSetArg(args[j], XtNstring, ""); j++;
5689 XtSetValues(edit, args, j);
5691 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5692 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5693 XtSetValues(ICSInputShell, args, j);
5696 XtPopup(ICSInputShell, XtGrabNone);
5697 XtSetKeyboardFocus(ICSInputShell, edit);
5699 ICSInputBoxUp = True;
5701 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
5702 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
5706 void ICSInputSendText()
5713 edit = XtNameToWidget(ICSInputShell, "*form.text");
5715 XtSetArg(args[j], XtNstring, &val); j++;
5716 XtGetValues(edit, args, j);
5717 SendMultiLineToICS(val);
5718 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
5719 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
5722 void ICSInputBoxPopDown()
5727 if (!ICSInputBoxUp) return;
5729 XtPopdown(ICSInputShell);
5730 ICSInputBoxUp = False;
5732 XtSetArg(args[j], XtNleftBitmap, None); j++;
5733 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
5737 void CommentPopUp(title, text)
5744 if (commentShell == NULL) {
5746 CommentCreate(title, text, False, CommentCallback, 4);
5747 XtRealizeWidget(commentShell);
5748 CatchDeleteWindow(commentShell, "CommentPopDown");
5750 edit = XtNameToWidget(commentShell, "*form.text");
5752 XtSetArg(args[j], XtNstring, text); j++;
5753 XtSetValues(edit, args, j);
5755 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5756 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5757 XtSetValues(commentShell, args, j);
5760 XtPopup(commentShell, XtGrabNone);
5761 XSync(xDisplay, False);
5766 void AnalysisPopUp(title, text)
5773 if (analysisShell == NULL) {
5774 analysisShell = MiscCreate(title, text, False, NULL, 4);
5775 XtRealizeWidget(analysisShell);
5776 CatchDeleteWindow(analysisShell, "AnalysisPopDown");
5779 edit = XtNameToWidget(analysisShell, "*form.text");
5781 XtSetArg(args[j], XtNstring, text); j++;
5782 XtSetValues(edit, args, j);
5784 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5785 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5786 XtSetValues(analysisShell, args, j);
5790 XtPopup(analysisShell, XtGrabNone);
5792 XSync(xDisplay, False);
5797 void CommentCallback(w, client_data, call_data)
5799 XtPointer client_data, call_data;
5806 XtSetArg(args[j], XtNlabel, &name); j++;
5807 XtGetValues(w, args, j);
5809 if (strcmp(name, _("close")) == 0) {
5811 } else if (strcmp(name, _("edit")) == 0) {
5818 void CommentPopDown()
5823 if (!commentUp) return;
5825 XtSetArg(args[j], XtNx, &commentX); j++;
5826 XtSetArg(args[j], XtNy, &commentY); j++;
5827 XtSetArg(args[j], XtNwidth, &commentW); j++;
5828 XtSetArg(args[j], XtNheight, &commentH); j++;
5829 XtGetValues(commentShell, args, j);
5830 XtPopdown(commentShell);
5831 XSync(xDisplay, False);
5835 void AnalysisPopDown()
5837 if (!analysisUp) return;
5838 XtPopdown(analysisShell);
5839 XSync(xDisplay, False);
5841 if (appData.icsEngineAnalyze) ExitAnalyzeMode(); /* [DM] icsEngineAnalyze */
5845 void FileNamePopUp(label, def, proc, openMode)
5852 Widget popup, layout, dialog, edit;
5858 fileProc = proc; /* I can't see a way not */
5859 fileOpenMode = openMode; /* to use globals here */
5862 XtSetArg(args[i], XtNresizable, True); i++;
5863 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
5864 XtSetArg(args[i], XtNtitle, XtNewString(_("File name prompt"))); i++;
5865 fileNameShell = popup =
5866 XtCreatePopupShell("File name prompt", transientShellWidgetClass,
5867 shellWidget, args, i);
5870 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
5871 layoutArgs, XtNumber(layoutArgs));
5874 XtSetArg(args[i], XtNlabel, label); i++;
5875 XtSetArg(args[i], XtNvalue, def); i++;
5876 XtSetArg(args[i], XtNborderWidth, 0); i++;
5877 dialog = XtCreateManagedWidget("fileName", dialogWidgetClass,
5880 XawDialogAddButton(dialog, _("ok"), FileNameCallback, (XtPointer) dialog);
5881 XawDialogAddButton(dialog, _("cancel"), FileNameCallback,
5882 (XtPointer) dialog);
5884 XtRealizeWidget(popup);
5885 CatchDeleteWindow(popup, "FileNamePopDown");
5887 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
5888 &x, &y, &win_x, &win_y, &mask);
5890 XtSetArg(args[0], XtNx, x - 10);
5891 XtSetArg(args[1], XtNy, y - 30);
5892 XtSetValues(popup, args, 2);
5894 XtPopup(popup, XtGrabExclusive);
5897 edit = XtNameToWidget(dialog, "*value");
5898 XtSetKeyboardFocus(popup, edit);
5901 void FileNamePopDown()
5903 if (!filenameUp) return;
5904 XtPopdown(fileNameShell);
5905 XtDestroyWidget(fileNameShell);
5910 void FileNameCallback(w, client_data, call_data)
5912 XtPointer client_data, call_data;
5917 XtSetArg(args[0], XtNlabel, &name);
5918 XtGetValues(w, args, 1);
5920 if (strcmp(name, _("cancel")) == 0) {
5925 FileNameAction(w, NULL, NULL, NULL);
5928 void FileNameAction(w, event, prms, nprms)
5940 name = XawDialogGetValueString(w = XtParent(w));
5942 if ((name != NULL) && (*name != NULLCHAR)) {
5944 XtPopdown(w = XtParent(XtParent(w)));
5948 p = strrchr(buf, ' ');
5955 fullname = ExpandPathName(buf);
5957 ErrorPopUp(_("Error"), _("Can't open file"), FALSE);
5960 f = fopen(fullname, fileOpenMode);
5962 DisplayError(_("Failed to open file"), errno);
5964 (void) (*fileProc)(f, index, buf);
5971 XtPopdown(w = XtParent(XtParent(w)));
5977 void PromotionPopUp()
5980 Widget dialog, layout;
5982 Dimension bw_width, pw_width;
5986 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5987 XtGetValues(boardWidget, args, j);
5990 XtSetArg(args[j], XtNresizable, True); j++;
5991 XtSetArg(args[j], XtNtitle, XtNewString(_("Promotion"))); j++;
5993 XtCreatePopupShell("Promotion", transientShellWidgetClass,
5994 shellWidget, args, j);
5996 XtCreateManagedWidget(layoutName, formWidgetClass, promotionShell,
5997 layoutArgs, XtNumber(layoutArgs));
6000 XtSetArg(args[j], XtNlabel, _("Promote to what?")); j++;
6001 XtSetArg(args[j], XtNborderWidth, 0); j++;
6002 dialog = XtCreateManagedWidget("promotion", dialogWidgetClass,
6005 if(gameInfo.variant != VariantShogi) {
6006 XawDialogAddButton(dialog, _("Queen"), PromotionCallback,
6007 (XtPointer) dialog);
6008 XawDialogAddButton(dialog, _("Rook"), PromotionCallback,
6009 (XtPointer) dialog);
6010 XawDialogAddButton(dialog, _("Bishop"), PromotionCallback,
6011 (XtPointer) dialog);
6012 XawDialogAddButton(dialog, _("Knight"), PromotionCallback,
6013 (XtPointer) dialog);
6014 if (!appData.testLegality || gameInfo.variant == VariantSuicide ||
6015 gameInfo.variant == VariantGiveaway) {
6016 XawDialogAddButton(dialog, _("King"), PromotionCallback,
6017 (XtPointer) dialog);
6019 if(gameInfo.variant == VariantCapablanca ||
6020 gameInfo.variant == VariantGothic ||
6021 gameInfo.variant == VariantCapaRandom) {
6022 XawDialogAddButton(dialog, _("Archbishop"), PromotionCallback,
6023 (XtPointer) dialog);
6024 XawDialogAddButton(dialog, _("Chancellor"), PromotionCallback,
6025 (XtPointer) dialog);
6027 } else // [HGM] shogi
6029 XawDialogAddButton(dialog, _("Promote"), PromotionCallback,
6030 (XtPointer) dialog);
6031 XawDialogAddButton(dialog, _("Defer"), PromotionCallback,
6032 (XtPointer) dialog);
6034 XawDialogAddButton(dialog, _("cancel"), PromotionCallback,
6035 (XtPointer) dialog);
6037 XtRealizeWidget(promotionShell);
6038 CatchDeleteWindow(promotionShell, "PromotionPopDown");
6041 XtSetArg(args[j], XtNwidth, &pw_width); j++;
6042 XtGetValues(promotionShell, args, j);
6044 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
6045 lineGap + squareSize/3 +
6046 ((toY == BOARD_HEIGHT-1) ^ (flipView) ?
6047 0 : 6*(squareSize + lineGap)), &x, &y);
6050 XtSetArg(args[j], XtNx, x); j++;
6051 XtSetArg(args[j], XtNy, y); j++;
6052 XtSetValues(promotionShell, args, j);
6054 XtPopup(promotionShell, XtGrabNone);
6059 void PromotionPopDown()
6061 if (!promotionUp) return;
6062 XtPopdown(promotionShell);
6063 XtDestroyWidget(promotionShell);
6064 promotionUp = False;
6067 void PromotionCallback(w, client_data, call_data)
6069 XtPointer client_data, call_data;
6075 XtSetArg(args[0], XtNlabel, &name);
6076 XtGetValues(w, args, 1);
6080 if (fromX == -1) return;
6082 if (strcmp(name, _("cancel")) == 0) {
6086 } else if (strcmp(name, _("Knight")) == 0) {
6088 } else if (strcmp(name, _("Promote")) == 0) {
6090 } else if (strcmp(name, _("Defer")) == 0) {
6093 promoChar = ToLower(name[0]);
6096 FinishMove(NormalMove, fromX, fromY, toX, toY, promoChar);
6098 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
6099 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
6104 void ErrorCallback(w, client_data, call_data)
6106 XtPointer client_data, call_data;
6109 XtPopdown(w = XtParent(XtParent(XtParent(w))));
6111 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
6117 if (!errorUp) return;
6119 XtPopdown(errorShell);
6120 XtDestroyWidget(errorShell);
6121 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
6124 void ErrorPopUp(title, label, modal)
6125 char *title, *label;
6129 Widget dialog, layout;
6133 Dimension bw_width, pw_width;
6134 Dimension pw_height;
6138 XtSetArg(args[i], XtNresizable, True); i++;
6139 XtSetArg(args[i], XtNtitle, title); i++;
6141 XtCreatePopupShell("errorpopup", transientShellWidgetClass,
6142 shellWidget, args, i);
6144 XtCreateManagedWidget(layoutName, formWidgetClass, errorShell,
6145 layoutArgs, XtNumber(layoutArgs));
6148 XtSetArg(args[i], XtNlabel, label); i++;
6149 XtSetArg(args[i], XtNborderWidth, 0); i++;
6150 dialog = XtCreateManagedWidget("dialog", dialogWidgetClass,
6153 XawDialogAddButton(dialog, _("ok"), ErrorCallback, (XtPointer) dialog);
6155 XtRealizeWidget(errorShell);
6156 CatchDeleteWindow(errorShell, "ErrorPopDown");
6159 XtSetArg(args[i], XtNwidth, &bw_width); i++;
6160 XtGetValues(boardWidget, args, i);
6162 XtSetArg(args[i], XtNwidth, &pw_width); i++;
6163 XtSetArg(args[i], XtNheight, &pw_height); i++;
6164 XtGetValues(errorShell, args, i);
6167 /* This code seems to tickle an X bug if it is executed too soon
6168 after xboard starts up. The coordinates get transformed as if
6169 the main window was positioned at (0, 0).
6171 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
6172 0 - pw_height + squareSize / 3, &x, &y);
6174 XTranslateCoordinates(xDisplay, XtWindow(boardWidget),
6175 RootWindowOfScreen(XtScreen(boardWidget)),
6176 (bw_width - pw_width) / 2,
6177 0 - pw_height + squareSize / 3, &xx, &yy, &junk);
6181 if (y < 0) y = 0; /*avoid positioning top offscreen*/
6184 XtSetArg(args[i], XtNx, x); i++;
6185 XtSetArg(args[i], XtNy, y); i++;
6186 XtSetValues(errorShell, args, i);
6189 XtPopup(errorShell, modal ? XtGrabExclusive : XtGrabNone);
6192 /* Disable all user input other than deleting the window */
6193 static int frozen = 0;
6197 /* Grab by a widget that doesn't accept input */
6198 XtAddGrab(messageWidget, TRUE, FALSE);
6202 /* Undo a FreezeUI */
6205 if (!frozen) return;
6206 XtRemoveGrab(messageWidget);
6210 char *ModeToWidgetName(mode)
6214 case BeginningOfGame:
6215 if (appData.icsActive)
6216 return "menuMode.ICS Client";
6217 else if (appData.noChessProgram ||
6218 *appData.cmailGameName != NULLCHAR)
6219 return "menuMode.Edit Game";
6221 return "menuMode.Machine Black";
6222 case MachinePlaysBlack:
6223 return "menuMode.Machine Black";
6224 case MachinePlaysWhite:
6225 return "menuMode.Machine White";
6227 return "menuMode.Analysis Mode";
6229 return "menuMode.Analyze File";
6230 case TwoMachinesPlay:
6231 return "menuMode.Two Machines";
6233 return "menuMode.Edit Game";
6234 case PlayFromGameFile:
6235 return "menuFile.Load Game";
6237 return "menuMode.Edit Position";
6239 return "menuMode.Training";
6240 case IcsPlayingWhite:
6241 case IcsPlayingBlack:
6245 return "menuMode.ICS Client";
6252 void ModeHighlight()
6255 static int oldPausing = FALSE;
6256 static GameMode oldmode = (GameMode) -1;
6259 if (!boardWidget || !XtIsRealized(boardWidget)) return;
6261 if (pausing != oldPausing) {
6262 oldPausing = pausing;
6264 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6266 XtSetArg(args[0], XtNleftBitmap, None);
6268 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Pause"),
6271 if (appData.showButtonBar) {
6274 XtSetArg(args[0], XtNbackground, buttonForegroundPixel);
6275 XtSetArg(args[1], XtNforeground, buttonBackgroundPixel);
6277 XtSetArg(args[0], XtNbackground, buttonBackgroundPixel);
6278 XtSetArg(args[1], XtNforeground, buttonForegroundPixel);
6281 /* Always toggle, don't set. Previous code messes up when
6282 invoked while the button is pressed, as releasing it
6283 toggles the state again. */
6286 XtSetArg(args[0], XtNbackground, &oldbg);
6287 XtSetArg(args[1], XtNforeground, &oldfg);
6288 XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON),
6290 XtSetArg(args[0], XtNbackground, oldfg);
6291 XtSetArg(args[1], XtNforeground, oldbg);
6294 XtSetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
6298 wname = ModeToWidgetName(oldmode);
6299 if (wname != NULL) {
6300 XtSetArg(args[0], XtNleftBitmap, None);
6301 XtSetValues(XtNameToWidget(menuBarWidget, wname), args, 1);
6303 wname = ModeToWidgetName(gameMode);
6304 if (wname != NULL) {
6305 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6306 XtSetValues(XtNameToWidget(menuBarWidget, wname), args, 1);
6310 /* Maybe all the enables should be handled here, not just this one */
6311 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Training"),
6312 gameMode == Training || gameMode == PlayFromGameFile);
6317 * Button/menu procedures
6319 void ResetProc(w, event, prms, nprms)
6329 int LoadGamePopUp(f, gameNumber, title)
6334 cmailMsgLoaded = FALSE;
6335 if (gameNumber == 0) {
6336 int error = GameListBuild(f);
6338 DisplayError(_("Cannot build game list"), error);
6339 } else if (!ListEmpty(&gameList) &&
6340 ((ListGame *) gameList.tailPred)->number > 1) {
6341 GameListPopUp(f, title);
6347 return LoadGame(f, gameNumber, title, FALSE);
6350 void LoadGameProc(w, event, prms, nprms)
6356 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
6359 FileNamePopUp(_("Load game file name?"), "", LoadGamePopUp, "rb");
6362 void LoadNextGameProc(w, event, prms, nprms)
6371 void LoadPrevGameProc(w, event, prms, nprms)
6380 void ReloadGameProc(w, event, prms, nprms)
6389 void LoadNextPositionProc(w, event, prms, nprms)
6398 void LoadPrevPositionProc(w, event, prms, nprms)
6407 void ReloadPositionProc(w, event, prms, nprms)
6416 void LoadPositionProc(w, event, prms, nprms)
6422 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
6425 FileNamePopUp(_("Load position file name?"), "", LoadPosition, "rb");
6428 void SaveGameProc(w, event, prms, nprms)
6434 FileNamePopUp(_("Save game file name?"),
6435 DefaultFileName(appData.oldSaveStyle ? "game" : "pgn"),
6439 void SavePositionProc(w, event, prms, nprms)
6445 FileNamePopUp(_("Save position file name?"),
6446 DefaultFileName(appData.oldSaveStyle ? "pos" : "fen"),
6450 void ReloadCmailMsgProc(w, event, prms, nprms)
6456 ReloadCmailMsgEvent(FALSE);
6459 void MailMoveProc(w, event, prms, nprms)
6468 /* this variable is shared between CopyPositionProc and SendPositionSelection */
6469 static char *selected_fen_position=NULL;
6472 SendPositionSelection(Widget w, Atom *selection, Atom *target,
6473 Atom *type_return, XtPointer *value_return,
6474 unsigned long *length_return, int *format_return)
6476 char *selection_tmp;
6478 if (!selected_fen_position) return False; /* should never happen */
6479 if (*target == XA_STRING){
6480 /* note: since no XtSelectionDoneProc was registered, Xt will
6481 * automatically call XtFree on the value returned. So have to
6482 * make a copy of it allocated with XtMalloc */
6483 selection_tmp= XtMalloc(strlen(selected_fen_position)+16);
6484 strcpy(selection_tmp, selected_fen_position);
6486 *value_return=selection_tmp;
6487 *length_return=strlen(selection_tmp);
6488 *type_return=XA_STRING;
6489 *format_return = 8; /* bits per byte */
6496 /* note: when called from menu all parameters are NULL, so no clue what the
6497 * Widget which was clicked on was, or what the click event was
6499 void CopyPositionProc(w, event, prms, nprms)
6507 if (selected_fen_position) free(selected_fen_position);
6508 selected_fen_position = (char *)PositionToFEN(currentMove, NULL);
6509 if (!selected_fen_position) return;
6510 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
6512 SendPositionSelection,
6513 NULL/* lose_ownership_proc */ ,
6514 NULL/* transfer_done_proc */);
6516 free(selected_fen_position);
6517 selected_fen_position=NULL;
6521 /* function called when the data to Paste is ready */
6523 PastePositionCB(Widget w, XtPointer client_data, Atom *selection,
6524 Atom *type, XtPointer value, unsigned long *len, int *format)
6527 if (value==NULL || *len==0) return; /* nothing had been selected to copy */
6528 fenstr[*len]='\0'; /* normally this string is terminated, but be safe */
6529 EditPositionPasteFEN(fenstr);
6533 /* called when Paste Position button is pressed,
6534 * all parameters will be NULL */
6535 void PastePositionProc(w, event, prms, nprms)
6541 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
6542 /* (XtSelectionCallbackProc) */ PastePositionCB,
6543 NULL, /* client_data passed to PastePositionCB */
6545 /* better to use the time field from the event that triggered the
6546 * call to this function, but that isn't trivial to get
6554 SendGameSelection(Widget w, Atom *selection, Atom *target,
6555 Atom *type_return, XtPointer *value_return,
6556 unsigned long *length_return, int *format_return)
6558 char *selection_tmp;
6560 if (*target == XA_STRING){
6561 FILE* f = fopen(gameCopyFilename, "r");
6564 if (f == NULL) return False;
6568 selection_tmp = XtMalloc(len + 1);
6569 count = fread(selection_tmp, 1, len, f);
6571 XtFree(selection_tmp);
6574 selection_tmp[len] = NULLCHAR;
6575 *value_return = selection_tmp;
6576 *length_return = len;
6577 *type_return = XA_STRING;
6578 *format_return = 8; /* bits per byte */
6585 /* note: when called from menu all parameters are NULL, so no clue what the
6586 * Widget which was clicked on was, or what the click event was
6588 void CopyGameProc(w, event, prms, nprms)
6596 ret = SaveGameToFile(gameCopyFilename, FALSE);
6599 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
6602 NULL/* lose_ownership_proc */ ,
6603 NULL/* transfer_done_proc */);
6606 /* function called when the data to Paste is ready */
6608 PasteGameCB(Widget w, XtPointer client_data, Atom *selection,
6609 Atom *type, XtPointer value, unsigned long *len, int *format)
6612 if (value == NULL || *len == 0) {
6613 return; /* nothing had been selected to copy */
6615 f = fopen(gamePasteFilename, "w");
6617 DisplayError(_("Can't open temp file"), errno);
6620 fwrite(value, 1, *len, f);
6623 LoadGameFromFile(gamePasteFilename, 0, gamePasteFilename, TRUE);
6626 /* called when Paste Game button is pressed,
6627 * all parameters will be NULL */
6628 void PasteGameProc(w, event, prms, nprms)
6634 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
6635 /* (XtSelectionCallbackProc) */ PasteGameCB,
6636 NULL, /* client_data passed to PasteGameCB */
6638 /* better to use the time field from the event that triggered the
6639 * call to this function, but that isn't trivial to get
6649 SaveGameProc(NULL, NULL, NULL, NULL);
6653 void QuitProc(w, event, prms, nprms)
6662 void PauseProc(w, event, prms, nprms)
6672 void MachineBlackProc(w, event, prms, nprms)
6678 MachineBlackEvent();
6681 void MachineWhiteProc(w, event, prms, nprms)
6687 MachineWhiteEvent();
6690 void AnalyzeModeProc(w, event, prms, nprms)
6698 if (!first.analysisSupport) {
6699 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
6700 DisplayError(buf, 0);
6703 /* [DM] icsEngineAnalyze [HGM] This is horrible code; reverse the gameMode and isEngineAnalyze tests! */
6704 if (appData.icsActive) {
6705 if (gameMode != IcsObserving) {
6706 sprintf(buf,_("You are not observing a game"));
6707 DisplayError(buf, 0);
6709 if (appData.icsEngineAnalyze) {
6710 if (appData.debugMode)
6711 fprintf(debugFP, _("Found unexpected active ICS engine analyze \n"));
6717 /* if enable, use want disable icsEngineAnalyze */
6718 if (appData.icsEngineAnalyze) {
6723 appData.icsEngineAnalyze = TRUE;
6724 if (appData.debugMode)
6725 fprintf(debugFP, _("ICS engine analyze starting... \n"));
6727 if (!appData.showThinking)
6728 ShowThinkingProc(w,event,prms,nprms);
6733 void AnalyzeFileProc(w, event, prms, nprms)
6739 if (!first.analysisSupport) {
6741 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
6742 DisplayError(buf, 0);
6747 if (!appData.showThinking)
6748 ShowThinkingProc(w,event,prms,nprms);
6751 FileNamePopUp(_("File to analyze"), "", LoadGamePopUp, "rb");
6752 AnalysisPeriodicEvent(1);
6755 void TwoMachinesProc(w, event, prms, nprms)
6764 void IcsClientProc(w, event, prms, nprms)
6773 void EditGameProc(w, event, prms, nprms)
6782 void EditPositionProc(w, event, prms, nprms)
6788 EditPositionEvent();
6791 void TrainingProc(w, event, prms, nprms)
6800 void EditCommentProc(w, event, prms, nprms)
6807 EditCommentPopDown();
6813 void IcsInputBoxProc(w, event, prms, nprms)
6819 if (ICSInputBoxUp) {
6820 ICSInputBoxPopDown();
6826 void AcceptProc(w, event, prms, nprms)
6835 void DeclineProc(w, event, prms, nprms)
6844 void RematchProc(w, event, prms, nprms)
6853 void CallFlagProc(w, event, prms, nprms)
6862 void DrawProc(w, event, prms, nprms)
6871 void AbortProc(w, event, prms, nprms)
6880 void AdjournProc(w, event, prms, nprms)
6889 void ResignProc(w, event, prms, nprms)
6898 void AdjuWhiteProc(w, event, prms, nprms)
6904 UserAdjudicationEvent(+1);
6907 void AdjuBlackProc(w, event, prms, nprms)
6913 UserAdjudicationEvent(-1);
6916 void AdjuDrawProc(w, event, prms, nprms)
6922 UserAdjudicationEvent(0);
6925 void EnterKeyProc(w, event, prms, nprms)
6931 if (ICSInputBoxUp == True)
6935 void StopObservingProc(w, event, prms, nprms)
6941 StopObservingEvent();
6944 void StopExaminingProc(w, event, prms, nprms)
6950 StopExaminingEvent();
6954 void ForwardProc(w, event, prms, nprms)
6964 void BackwardProc(w, event, prms, nprms)
6973 void ToStartProc(w, event, prms, nprms)
6982 void ToEndProc(w, event, prms, nprms)
6991 void RevertProc(w, event, prms, nprms)
7000 void TruncateGameProc(w, event, prms, nprms)
7006 TruncateGameEvent();
7008 void RetractMoveProc(w, event, prms, nprms)
7017 void MoveNowProc(w, event, prms, nprms)
7027 void AlwaysQueenProc(w, event, prms, nprms)
7035 appData.alwaysPromoteToQueen = !appData.alwaysPromoteToQueen;
7037 if (appData.alwaysPromoteToQueen) {
7038 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7040 XtSetArg(args[0], XtNleftBitmap, None);
7042 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
7046 void AnimateDraggingProc(w, event, prms, nprms)
7054 appData.animateDragging = !appData.animateDragging;
7056 if (appData.animateDragging) {
7057 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7060 XtSetArg(args[0], XtNleftBitmap, None);
7062 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Dragging"),
7066 void AnimateMovingProc(w, event, prms, nprms)
7074 appData.animate = !appData.animate;
7076 if (appData.animate) {
7077 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7080 XtSetArg(args[0], XtNleftBitmap, None);
7082 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
7086 void AutocommProc(w, event, prms, nprms)
7094 appData.autoComment = !appData.autoComment;
7096 if (appData.autoComment) {
7097 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7099 XtSetArg(args[0], XtNleftBitmap, None);
7101 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
7106 void AutoflagProc(w, event, prms, nprms)
7114 appData.autoCallFlag = !appData.autoCallFlag;
7116 if (appData.autoCallFlag) {
7117 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7119 XtSetArg(args[0], XtNleftBitmap, None);
7121 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
7125 void AutoflipProc(w, event, prms, nprms)
7133 appData.autoFlipView = !appData.autoFlipView;
7135 if (appData.autoFlipView) {
7136 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7138 XtSetArg(args[0], XtNleftBitmap, None);
7140 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flip View"),
7144 void AutobsProc(w, event, prms, nprms)
7152 appData.autoObserve = !appData.autoObserve;
7154 if (appData.autoObserve) {
7155 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7157 XtSetArg(args[0], XtNleftBitmap, None);
7159 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
7163 void AutoraiseProc(w, event, prms, nprms)
7171 appData.autoRaiseBoard = !appData.autoRaiseBoard;
7173 if (appData.autoRaiseBoard) {
7174 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7176 XtSetArg(args[0], XtNleftBitmap, None);
7178 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Raise Board"),
7182 void AutosaveProc(w, event, prms, nprms)
7190 appData.autoSaveGames = !appData.autoSaveGames;
7192 if (appData.autoSaveGames) {
7193 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7195 XtSetArg(args[0], XtNleftBitmap, None);
7197 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
7201 void BlindfoldProc(w, event, prms, nprms)
7209 appData.blindfold = !appData.blindfold;
7211 if (appData.blindfold) {
7212 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7214 XtSetArg(args[0], XtNleftBitmap, None);
7216 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Blindfold"),
7219 DrawPosition(True, NULL);
7222 void TestLegalityProc(w, event, prms, nprms)
7230 appData.testLegality = !appData.testLegality;
7232 if (appData.testLegality) {
7233 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7235 XtSetArg(args[0], XtNleftBitmap, None);
7237 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Test Legality"),
7242 void FlashMovesProc(w, event, prms, nprms)
7250 if (appData.flashCount == 0) {
7251 appData.flashCount = 3;
7253 appData.flashCount = -appData.flashCount;
7256 if (appData.flashCount > 0) {
7257 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7259 XtSetArg(args[0], XtNleftBitmap, None);
7261 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flash Moves"),
7265 void FlipViewProc(w, event, prms, nprms)
7271 flipView = !flipView;
7272 DrawPosition(True, NULL);
7275 void GetMoveListProc(w, event, prms, nprms)
7283 appData.getMoveList = !appData.getMoveList;
7285 if (appData.getMoveList) {
7286 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7289 XtSetArg(args[0], XtNleftBitmap, None);
7291 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
7296 void HighlightDraggingProc(w, event, prms, nprms)
7304 appData.highlightDragging = !appData.highlightDragging;
7306 if (appData.highlightDragging) {
7307 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7309 XtSetArg(args[0], XtNleftBitmap, None);
7311 XtSetValues(XtNameToWidget(menuBarWidget,
7312 "menuOptions.Highlight Dragging"), args, 1);
7316 void HighlightLastMoveProc(w, event, prms, nprms)
7324 appData.highlightLastMove = !appData.highlightLastMove;
7326 if (appData.highlightLastMove) {
7327 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7329 XtSetArg(args[0], XtNleftBitmap, None);
7331 XtSetValues(XtNameToWidget(menuBarWidget,
7332 "menuOptions.Highlight Last Move"), args, 1);
7335 void IcsAlarmProc(w, event, prms, nprms)
7343 appData.icsAlarm = !appData.icsAlarm;
7345 if (appData.icsAlarm) {
7346 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7348 XtSetArg(args[0], XtNleftBitmap, None);
7350 XtSetValues(XtNameToWidget(menuBarWidget,
7351 "menuOptions.ICS Alarm"), args, 1);
7354 void MoveSoundProc(w, event, prms, nprms)
7362 appData.ringBellAfterMoves = !appData.ringBellAfterMoves;
7364 if (appData.ringBellAfterMoves) {
7365 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7367 XtSetArg(args[0], XtNleftBitmap, None);
7369 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
7374 void OldSaveStyleProc(w, event, prms, nprms)
7382 appData.oldSaveStyle = !appData.oldSaveStyle;
7384 if (appData.oldSaveStyle) {
7385 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7387 XtSetArg(args[0], XtNleftBitmap, None);
7389 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Old Save Style"),
7393 void PeriodicUpdatesProc(w, event, prms, nprms)
7401 PeriodicUpdatesEvent(!appData.periodicUpdates);
7403 if (appData.periodicUpdates) {
7404 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7406 XtSetArg(args[0], XtNleftBitmap, None);
7408 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Periodic Updates"),
7412 void PonderNextMoveProc(w, event, prms, nprms)
7420 PonderNextMoveEvent(!appData.ponderNextMove);
7422 if (appData.ponderNextMove) {
7423 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7425 XtSetArg(args[0], XtNleftBitmap, None);
7427 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Ponder Next Move"),
7431 void PopupExitMessageProc(w, event, prms, nprms)
7439 appData.popupExitMessage = !appData.popupExitMessage;
7441 if (appData.popupExitMessage) {
7442 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7444 XtSetArg(args[0], XtNleftBitmap, None);
7446 XtSetValues(XtNameToWidget(menuBarWidget,
7447 "menuOptions.Popup Exit Message"), args, 1);
7450 void PopupMoveErrorsProc(w, event, prms, nprms)
7458 appData.popupMoveErrors = !appData.popupMoveErrors;
7460 if (appData.popupMoveErrors) {
7461 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7463 XtSetArg(args[0], XtNleftBitmap, None);
7465 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Popup Move Errors"),
7469 void PremoveProc(w, event, prms, nprms)
7477 appData.premove = !appData.premove;
7479 if (appData.premove) {
7480 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7482 XtSetArg(args[0], XtNleftBitmap, None);
7484 XtSetValues(XtNameToWidget(menuBarWidget,
7485 "menuOptions.Premove"), args, 1);
7488 void QuietPlayProc(w, event, prms, nprms)
7496 appData.quietPlay = !appData.quietPlay;
7498 if (appData.quietPlay) {
7499 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7501 XtSetArg(args[0], XtNleftBitmap, None);
7503 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Quiet Play"),
7507 void ShowCoordsProc(w, event, prms, nprms)
7515 appData.showCoords = !appData.showCoords;
7517 if (appData.showCoords) {
7518 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7520 XtSetArg(args[0], XtNleftBitmap, None);
7522 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
7525 DrawPosition(True, NULL);
7528 void ShowThinkingProc(w, event, prms, nprms)
7536 appData.showThinking = !appData.showThinking; // [HGM] thinking: tken out of ShowThinkingEvent
7537 ShowThinkingEvent();
7539 // [HGM] thinking: currently no suc menu item; replaced by Hide Thinking (From Human)
7540 if (appData.showThinking) {
7541 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7543 XtSetArg(args[0], XtNleftBitmap, None);
7545 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Thinking"),
7550 void HideThinkingProc(w, event, prms, nprms)
7558 appData.hideThinkingFromHuman = !appData.hideThinkingFromHuman; // [HGM] thinking: tken out of ShowThinkingEvent
7559 ShowThinkingEvent();
7561 if (appData.hideThinkingFromHuman) {
7562 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7564 XtSetArg(args[0], XtNleftBitmap, None);
7566 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
7570 void InfoProc(w, event, prms, nprms)
7577 snprintf(buf, sizeof(buf), "xterm -e info --directory %s --directory . -f %s &",
7582 void ManProc(w, event, prms, nprms)
7590 if (nprms && *nprms > 0)
7594 snprintf(buf, sizeof(buf), "xterm -e man %s &", name);
7598 void HintProc(w, event, prms, nprms)
7607 void BookProc(w, event, prms, nprms)
7616 void AboutProc(w, event, prms, nprms)
7624 char *zippy = " (with Zippy code)";
7628 snprintf(buf, sizeof(buf), "%s%s\n\n%s\n%s\n%s\n\n%s%s\n%s",
7629 programVersion, zippy,
7630 "Copyright 1991 Digital Equipment Corporation",
7631 "Enhancements Copyright 1992-2009 Free Software Foundation",
7632 "Enhancements Copyright 2005 Alessandro Scotti",
7633 PACKAGE, " is free software and carries NO WARRANTY;",
7634 "see the file COPYING for more information.");
7635 ErrorPopUp(_("About XBoard"), buf, FALSE);
7638 void DebugProc(w, event, prms, nprms)
7644 appData.debugMode = !appData.debugMode;
7647 void AboutGameProc(w, event, prms, nprms)
7656 void NothingProc(w, event, prms, nprms)
7665 void Iconify(w, event, prms, nprms)
7674 XtSetArg(args[0], XtNiconic, True);
7675 XtSetValues(shellWidget, args, 1);
7678 void DisplayMessage(message, extMessage)
7679 char *message, *extMessage;
7681 /* display a message in the message widget */
7690 snprintf(buf, sizeof(buf), "%s %s", message, extMessage);
7695 message = extMessage;
7699 /* need to test if messageWidget already exists, since this function
7700 can also be called during the startup, if for example a Xresource
7701 is not set up correctly */
7704 XtSetArg(arg, XtNlabel, message);
7705 XtSetValues(messageWidget, &arg, 1);
7711 void DisplayTitle(text)
7716 char title[MSG_SIZ];
7719 if (text == NULL) text = "";
7721 if (appData.titleInWindow) {
7723 XtSetArg(args[i], XtNlabel, text); i++;
7724 XtSetValues(titleWidget, args, i);
7727 if (*text != NULLCHAR) {
7729 strcpy(title, text);
7730 } else if (appData.icsActive) {
7731 snprintf(icon, sizeof(icon), "%s", appData.icsHost);
7732 snprintf(title, sizeof(title), "%s: %s", programName, appData.icsHost);
7733 } else if (appData.cmailGameName[0] != NULLCHAR) {
7734 snprintf(icon, sizeof(icon), "%s", "CMail");
7735 snprintf(title,sizeof(title), "%s: %s", programName, "CMail");
7737 // [HGM] license: This stuff should really be done in back-end, but WinBoard already had a pop-up for it
7738 } else if (gameInfo.variant == VariantGothic) {
7739 strcpy(icon, programName);
7740 strcpy(title, GOTHIC);
7743 } else if (gameInfo.variant == VariantFalcon) {
7744 strcpy(icon, programName);
7745 strcpy(title, FALCON);
7747 } else if (appData.noChessProgram) {
7748 strcpy(icon, programName);
7749 strcpy(title, programName);
7751 strcpy(icon, first.tidy);
7752 snprintf(title,sizeof(title), "%s: %s", programName, first.tidy);
7755 XtSetArg(args[i], XtNiconName, (XtArgVal) icon); i++;
7756 XtSetArg(args[i], XtNtitle, (XtArgVal) title); i++;
7757 XtSetValues(shellWidget, args, i);
7761 void DisplayError(message, error)
7768 if (appData.debugMode || appData.matchMode) {
7769 fprintf(stderr, "%s: %s\n", programName, message);
7772 if (appData.debugMode || appData.matchMode) {
7773 fprintf(stderr, "%s: %s: %s\n",
7774 programName, message, strerror(error));
7776 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
7779 ErrorPopUp(_("Error"), message, FALSE);
7783 void DisplayMoveError(message)
7788 DrawPosition(FALSE, NULL);
7789 if (appData.debugMode || appData.matchMode) {
7790 fprintf(stderr, "%s: %s\n", programName, message);
7792 if (appData.popupMoveErrors) {
7793 ErrorPopUp(_("Error"), message, FALSE);
7795 DisplayMessage(message, "");
7800 void DisplayFatalError(message, error, status)
7806 errorExitStatus = status;
7808 fprintf(stderr, "%s: %s\n", programName, message);
7810 fprintf(stderr, "%s: %s: %s\n",
7811 programName, message, strerror(error));
7812 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
7815 if (appData.popupExitMessage && boardWidget && XtIsRealized(boardWidget)) {
7816 ErrorPopUp(status ? _("Fatal Error") : _("Exiting"), message, TRUE);
7822 void DisplayInformation(message)
7826 ErrorPopUp(_("Information"), message, TRUE);
7829 void DisplayNote(message)
7833 ErrorPopUp(_("Note"), message, FALSE);
7837 NullXErrorCheck(dpy, error_event)
7839 XErrorEvent *error_event;
7844 void DisplayIcsInteractionTitle(message)
7847 if (oldICSInteractionTitle == NULL) {
7848 /* Magic to find the old window title, adapted from vim */
7849 char *wina = getenv("WINDOWID");
7851 Window win = (Window) atoi(wina);
7852 Window root, parent, *children;
7853 unsigned int nchildren;
7854 int (*oldHandler)() = XSetErrorHandler(NullXErrorCheck);
7856 if (XFetchName(xDisplay, win, &oldICSInteractionTitle)) break;
7857 if (!XQueryTree(xDisplay, win, &root, &parent,
7858 &children, &nchildren)) break;
7859 if (children) XFree((void *)children);
7860 if (parent == root || parent == 0) break;
7863 XSetErrorHandler(oldHandler);
7865 if (oldICSInteractionTitle == NULL) {
7866 oldICSInteractionTitle = "xterm";
7869 printf("\033]0;%s\007", message);
7873 char pendingReplyPrefix[MSG_SIZ];
7874 ProcRef pendingReplyPR;
7876 void AskQuestionProc(w, event, prms, nprms)
7883 fprintf(stderr, _("AskQuestionProc needed 4 parameters, got %d\n"),
7887 AskQuestionEvent(prms[0], prms[1], prms[2], prms[3]);
7890 void AskQuestionPopDown()
7892 if (!askQuestionUp) return;
7893 XtPopdown(askQuestionShell);
7894 XtDestroyWidget(askQuestionShell);
7895 askQuestionUp = False;
7898 void AskQuestionReplyAction(w, event, prms, nprms)
7908 reply = XawDialogGetValueString(w = XtParent(w));
7909 strcpy(buf, pendingReplyPrefix);
7910 if (*buf) strcat(buf, " ");
7913 OutputToProcess(pendingReplyPR, buf, strlen(buf), &err);
7914 AskQuestionPopDown();
7916 if (err) DisplayFatalError(_("Error writing to chess program"), err, 0);
7919 void AskQuestionCallback(w, client_data, call_data)
7921 XtPointer client_data, call_data;
7926 XtSetArg(args[0], XtNlabel, &name);
7927 XtGetValues(w, args, 1);
7929 if (strcmp(name, _("cancel")) == 0) {
7930 AskQuestionPopDown();
7932 AskQuestionReplyAction(w, NULL, NULL, NULL);
7936 void AskQuestion(title, question, replyPrefix, pr)
7937 char *title, *question, *replyPrefix;
7941 Widget popup, layout, dialog, edit;
7947 strcpy(pendingReplyPrefix, replyPrefix);
7948 pendingReplyPR = pr;
7951 XtSetArg(args[i], XtNresizable, True); i++;
7952 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
7953 askQuestionShell = popup =
7954 XtCreatePopupShell(title, transientShellWidgetClass,
7955 shellWidget, args, i);
7958 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
7959 layoutArgs, XtNumber(layoutArgs));
7962 XtSetArg(args[i], XtNlabel, question); i++;
7963 XtSetArg(args[i], XtNvalue, ""); i++;
7964 XtSetArg(args[i], XtNborderWidth, 0); i++;
7965 dialog = XtCreateManagedWidget("question", dialogWidgetClass,
7968 XawDialogAddButton(dialog, _("enter"), AskQuestionCallback,
7969 (XtPointer) dialog);
7970 XawDialogAddButton(dialog, _("cancel"), AskQuestionCallback,
7971 (XtPointer) dialog);
7973 XtRealizeWidget(popup);
7974 CatchDeleteWindow(popup, "AskQuestionPopDown");
7976 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
7977 &x, &y, &win_x, &win_y, &mask);
7979 XtSetArg(args[0], XtNx, x - 10);
7980 XtSetArg(args[1], XtNy, y - 30);
7981 XtSetValues(popup, args, 2);
7983 XtPopup(popup, XtGrabExclusive);
7984 askQuestionUp = True;
7986 edit = XtNameToWidget(dialog, "*value");
7987 XtSetKeyboardFocus(popup, edit);
7995 if (*name == NULLCHAR) {
7997 } else if (strcmp(name, "$") == 0) {
7998 putc(BELLCHAR, stderr);
8001 snprintf(buf, sizeof(buf), "%s '%s' &", appData.soundProgram, name);
8009 PlaySound(appData.soundMove);
8015 PlaySound(appData.soundIcsWin);
8021 PlaySound(appData.soundIcsLoss);
8027 PlaySound(appData.soundIcsDraw);
8031 PlayIcsUnfinishedSound()
8033 PlaySound(appData.soundIcsUnfinished);
8039 PlaySound(appData.soundIcsAlarm);
8045 system("stty echo");
8051 system("stty -echo");
8055 Colorize(cc, continuation)
8060 int count, outCount, error;
8062 if (textColors[(int)cc].bg > 0) {
8063 if (textColors[(int)cc].fg > 0) {
8064 sprintf(buf, "\033[0;%d;%d;%dm", textColors[(int)cc].attr,
8065 textColors[(int)cc].fg, textColors[(int)cc].bg);
8067 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
8068 textColors[(int)cc].bg);
8071 if (textColors[(int)cc].fg > 0) {
8072 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
8073 textColors[(int)cc].fg);
8075 sprintf(buf, "\033[0;%dm", textColors[(int)cc].attr);
8078 count = strlen(buf);
8079 outCount = OutputToProcess(NoProc, buf, count, &error);
8080 if (outCount < count) {
8081 DisplayFatalError(_("Error writing to display"), error, 1);
8084 if (continuation) return;
8087 PlaySound(appData.soundShout);
8090 PlaySound(appData.soundSShout);
8093 PlaySound(appData.soundChannel1);
8096 PlaySound(appData.soundChannel);
8099 PlaySound(appData.soundKibitz);
8102 PlaySound(appData.soundTell);
8104 case ColorChallenge:
8105 PlaySound(appData.soundChallenge);
8108 PlaySound(appData.soundRequest);
8111 PlaySound(appData.soundSeek);
8122 return getpwuid(getuid())->pw_name;
8125 static char *ExpandPathName(path)
8128 static char static_buf[2000];
8129 char *d, *s, buf[2000];
8135 while (*s && isspace(*s))
8144 if (*(s+1) == '/') {
8145 strcpy(d, getpwuid(getuid())->pw_dir);
8150 *strchr(buf, '/') = 0;
8151 pwd = getpwnam(buf);
8154 fprintf(stderr, _("ERROR: Unknown user %s (in path %s)\n"),
8158 strcpy(d, pwd->pw_dir);
8159 strcat(d, strchr(s+1, '/'));
8170 static char host_name[MSG_SIZ];
8172 #if HAVE_GETHOSTNAME
8173 gethostname(host_name, MSG_SIZ);
8175 #else /* not HAVE_GETHOSTNAME */
8176 # if HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H
8177 sysinfo(SI_HOSTNAME, host_name, MSG_SIZ);
8179 # else /* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
8181 # endif/* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
8182 #endif /* not HAVE_GETHOSTNAME */
8185 XtIntervalId delayedEventTimerXID = 0;
8186 DelayedEventCallback delayedEventCallback = 0;
8191 delayedEventTimerXID = 0;
8192 delayedEventCallback();
8196 ScheduleDelayedEvent(cb, millisec)
8197 DelayedEventCallback cb; long millisec;
8199 if(delayedEventTimerXID && delayedEventCallback == cb)
8200 // [HGM] alive: replace, rather than add or flush identical event
8201 XtRemoveTimeOut(delayedEventTimerXID);
8202 delayedEventCallback = cb;
8203 delayedEventTimerXID =
8204 XtAppAddTimeOut(appContext, millisec,
8205 (XtTimerCallbackProc) FireDelayedEvent, (XtPointer) 0);
8208 DelayedEventCallback
8211 if (delayedEventTimerXID) {
8212 return delayedEventCallback;
8219 CancelDelayedEvent()
8221 if (delayedEventTimerXID) {
8222 XtRemoveTimeOut(delayedEventTimerXID);
8223 delayedEventTimerXID = 0;
8227 XtIntervalId loadGameTimerXID = 0;
8229 int LoadGameTimerRunning()
8231 return loadGameTimerXID != 0;
8234 int StopLoadGameTimer()
8236 if (loadGameTimerXID != 0) {
8237 XtRemoveTimeOut(loadGameTimerXID);
8238 loadGameTimerXID = 0;
8246 LoadGameTimerCallback(arg, id)
8250 loadGameTimerXID = 0;
8255 StartLoadGameTimer(millisec)
8259 XtAppAddTimeOut(appContext, millisec,
8260 (XtTimerCallbackProc) LoadGameTimerCallback,
8264 XtIntervalId analysisClockXID = 0;
8267 AnalysisClockCallback(arg, id)
8271 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile
8272 || appData.icsEngineAnalyze) { // [DM]
8273 AnalysisPeriodicEvent(0);
8274 StartAnalysisClock();
8279 StartAnalysisClock()
8282 XtAppAddTimeOut(appContext, 2000,
8283 (XtTimerCallbackProc) AnalysisClockCallback,
8287 XtIntervalId clockTimerXID = 0;
8289 int ClockTimerRunning()
8291 return clockTimerXID != 0;
8294 int StopClockTimer()
8296 if (clockTimerXID != 0) {
8297 XtRemoveTimeOut(clockTimerXID);
8306 ClockTimerCallback(arg, id)
8315 StartClockTimer(millisec)
8319 XtAppAddTimeOut(appContext, millisec,
8320 (XtTimerCallbackProc) ClockTimerCallback,
8325 DisplayTimerLabel(w, color, timer, highlight)
8334 /* check for low time warning */
8335 Pixel foregroundOrWarningColor = timerForegroundPixel;
8338 appData.lowTimeWarning &&
8339 (timer / 1000) < appData.icsAlarmTime)
8340 foregroundOrWarningColor = lowTimeWarningColor;
8342 if (appData.clockMode) {
8343 sprintf(buf, "%s: %s", color, TimeString(timer));
8344 XtSetArg(args[0], XtNlabel, buf);
8346 sprintf(buf, "%s ", color);
8347 XtSetArg(args[0], XtNlabel, buf);
8352 XtSetArg(args[1], XtNbackground, foregroundOrWarningColor);
8353 XtSetArg(args[2], XtNforeground, timerBackgroundPixel);
8355 XtSetArg(args[1], XtNbackground, timerBackgroundPixel);
8356 XtSetArg(args[2], XtNforeground, foregroundOrWarningColor);
8359 XtSetValues(w, args, 3);
8363 DisplayWhiteClock(timeRemaining, highlight)
8369 if(appData.noGUI) return;
8370 DisplayTimerLabel(whiteTimerWidget, _("White"), timeRemaining, highlight);
8371 if (highlight && iconPixmap == bIconPixmap) {
8372 iconPixmap = wIconPixmap;
8373 XtSetArg(args[0], XtNiconPixmap, iconPixmap);
8374 XtSetValues(shellWidget, args, 1);
8379 DisplayBlackClock(timeRemaining, highlight)
8385 if(appData.noGUI) return;
8386 DisplayTimerLabel(blackTimerWidget, _("Black"), timeRemaining, highlight);
8387 if (highlight && iconPixmap == wIconPixmap) {
8388 iconPixmap = bIconPixmap;
8389 XtSetArg(args[0], XtNiconPixmap, iconPixmap);
8390 XtSetValues(shellWidget, args, 1);
8408 int StartChildProcess(cmdLine, dir, pr)
8415 int to_prog[2], from_prog[2];
8419 if (appData.debugMode) {
8420 fprintf(stderr, "StartChildProcess (dir=\"%s\") %s\n",dir, cmdLine);
8423 /* We do NOT feed the cmdLine to the shell; we just
8424 parse it into blank-separated arguments in the
8425 most simple-minded way possible.
8428 strcpy(buf, cmdLine);
8433 if (p == NULL) break;
8438 SetUpChildIO(to_prog, from_prog);
8440 if ((pid = fork()) == 0) {
8442 // [HGM] PSWBTM: made order resistant against case where fd of created pipe was 0 or 1
8443 close(to_prog[1]); // first close the unused pipe ends
8444 close(from_prog[0]);
8445 dup2(to_prog[0], 0); // to_prog was created first, nd is the only one to use 0 or 1
8446 dup2(from_prog[1], 1);
8447 if(to_prog[0] >= 2) close(to_prog[0]); // if 0 or 1, the dup2 already cosed the original
8448 close(from_prog[1]); // and closing again loses one of the pipes!
8449 if(fileno(stderr) >= 2) // better safe than sorry...
8450 dup2(1, fileno(stderr)); /* force stderr to the pipe */
8452 if (dir[0] != NULLCHAR && chdir(dir) != 0) {
8457 nice(appData.niceEngines); // [HGM] nice: adjust priority of engine proc
8459 execvp(argv[0], argv);
8461 /* If we get here, exec failed */
8466 /* Parent process */
8468 close(from_prog[1]);
8470 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8473 cp->fdFrom = from_prog[0];
8474 cp->fdTo = to_prog[1];
8479 // [HGM] kill: implement the 'hard killing' of AS's Winboard_x
8480 static RETSIGTYPE AlarmCallBack(int n)
8486 DestroyChildProcess(pr, signalType)
8490 ChildProc *cp = (ChildProc *) pr;
8492 if (cp->kind != CPReal) return;
8494 if (signalType == 10) { // [HGM] kill: if it does not terminate in 3 sec, kill
8495 signal(SIGALRM, AlarmCallBack);
8497 if(wait((int *) 0) == -1) { // process does not terminate on its own accord
8498 kill(cp->pid, SIGKILL); // kill it forcefully
8499 wait((int *) 0); // and wait again
8503 kill(cp->pid, signalType == 9 ? SIGKILL : SIGTERM); // [HGM] kill: use hard kill if so requested
8505 /* Process is exiting either because of the kill or because of
8506 a quit command sent by the backend; either way, wait for it to die.
8515 InterruptChildProcess(pr)
8518 ChildProc *cp = (ChildProc *) pr;
8520 if (cp->kind != CPReal) return;
8521 (void) kill(cp->pid, SIGINT); /* stop it thinking */
8524 int OpenTelnet(host, port, pr)
8529 char cmdLine[MSG_SIZ];
8531 if (port[0] == NULLCHAR) {
8532 snprintf(cmdLine, sizeof(cmdLine), "%s %s", appData.telnetProgram, host);
8534 snprintf(cmdLine, sizeof(cmdLine), "%s %s %s", appData.telnetProgram, host, port);
8536 return StartChildProcess(cmdLine, "", pr);
8539 int OpenTCP(host, port, pr)
8545 DisplayFatalError(_("Socket support is not configured in"), 0, 2);
8546 #else /* !OMIT_SOCKETS */
8548 struct sockaddr_in sa;
8550 unsigned short uport;
8553 if ((s = socket(AF_INET, SOCK_STREAM, 6)) < 0) {
8557 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
8558 sa.sin_family = AF_INET;
8559 sa.sin_addr.s_addr = INADDR_ANY;
8560 uport = (unsigned short) 0;
8561 sa.sin_port = htons(uport);
8562 if (bind(s, (struct sockaddr *) &sa, sizeof(struct sockaddr_in)) < 0) {
8566 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
8567 if (!(hp = gethostbyname(host))) {
8569 if (sscanf(host, "%d.%d.%d.%d", &b0, &b1, &b2, &b3) == 4) {
8570 hp = (struct hostent *) calloc(1, sizeof(struct hostent));
8571 hp->h_addrtype = AF_INET;
8573 hp->h_addr_list = (char **) calloc(2, sizeof(char *));
8574 hp->h_addr_list[0] = (char *) malloc(4);
8575 hp->h_addr_list[0][0] = b0;
8576 hp->h_addr_list[0][1] = b1;
8577 hp->h_addr_list[0][2] = b2;
8578 hp->h_addr_list[0][3] = b3;
8583 sa.sin_family = hp->h_addrtype;
8584 uport = (unsigned short) atoi(port);
8585 sa.sin_port = htons(uport);
8586 memcpy((char *) &sa.sin_addr, hp->h_addr, hp->h_length);
8588 if (connect(s, (struct sockaddr *) &sa,
8589 sizeof(struct sockaddr_in)) < 0) {
8593 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8600 #endif /* !OMIT_SOCKETS */
8605 int OpenCommPort(name, pr)
8612 fd = open(name, 2, 0);
8613 if (fd < 0) return errno;
8615 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8625 int OpenLoopback(pr)
8631 SetUpChildIO(to, from);
8633 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8636 cp->fdFrom = to[0]; /* note not from[0]; we are doing a loopback */
8643 int OpenRcmd(host, user, cmd, pr)
8644 char *host, *user, *cmd;
8647 DisplayFatalError(_("internal rcmd not implemented for Unix"), 0, 1);
8651 #define INPUT_SOURCE_BUF_SIZE 8192
8660 char buf[INPUT_SOURCE_BUF_SIZE];
8665 DoInputCallback(closure, source, xid)
8670 InputSource *is = (InputSource *) closure;
8675 if (is->lineByLine) {
8676 count = read(is->fd, is->unused,
8677 INPUT_SOURCE_BUF_SIZE - (is->unused - is->buf));
8679 (is->func)(is, is->closure, is->buf, count, count ? errno : 0);
8682 is->unused += count;
8684 while (p < is->unused) {
8685 q = memchr(p, '\n', is->unused - p);
8686 if (q == NULL) break;
8688 (is->func)(is, is->closure, p, q - p, 0);
8692 while (p < is->unused) {
8697 count = read(is->fd, is->buf, INPUT_SOURCE_BUF_SIZE);
8702 (is->func)(is, is->closure, is->buf, count, error);
8706 InputSourceRef AddInputSource(pr, lineByLine, func, closure)
8713 ChildProc *cp = (ChildProc *) pr;
8715 is = (InputSource *) calloc(1, sizeof(InputSource));
8716 is->lineByLine = lineByLine;
8720 is->fd = fileno(stdin);
8722 is->kind = cp->kind;
8723 is->fd = cp->fdFrom;
8726 is->unused = is->buf;
8729 is->xid = XtAppAddInput(appContext, is->fd,
8730 (XtPointer) (XtInputReadMask),
8731 (XtInputCallbackProc) DoInputCallback,
8733 is->closure = closure;
8734 return (InputSourceRef) is;
8738 RemoveInputSource(isr)
8741 InputSource *is = (InputSource *) isr;
8743 if (is->xid == 0) return;
8744 XtRemoveInput(is->xid);
8748 int OutputToProcess(pr, message, count, outError)
8754 ChildProc *cp = (ChildProc *) pr;
8758 outCount = fwrite(message, 1, count, stdout);
8760 outCount = write(cp->fdTo, message, count);
8770 /* Output message to process, with "ms" milliseconds of delay
8771 between each character. This is needed when sending the logon
8772 script to ICC, which for some reason doesn't like the
8773 instantaneous send. */
8774 int OutputToProcessDelayed(pr, message, count, outError, msdelay)
8781 ChildProc *cp = (ChildProc *) pr;
8786 r = write(cp->fdTo, message++, 1);
8799 /**** Animation code by Hugh Fisher, DCS, ANU.
8801 Known problem: if a window overlapping the board is
8802 moved away while a piece is being animated underneath,
8803 the newly exposed area won't be updated properly.
8804 I can live with this.
8806 Known problem: if you look carefully at the animation
8807 of pieces in mono mode, they are being drawn as solid
8808 shapes without interior detail while moving. Fixing
8809 this would be a major complication for minimal return.
8812 /* Masks for XPM pieces. Black and white pieces can have
8813 different shapes, but in the interest of retaining my
8814 sanity pieces must have the same outline on both light
8815 and dark squares, and all pieces must use the same
8816 background square colors/images. */
8818 static int xpmDone = 0;
8821 CreateAnimMasks (pieceDepth)
8828 unsigned long plane;
8831 /* Need a bitmap just to get a GC with right depth */
8832 buf = XCreatePixmap(xDisplay, xBoardWindow,
8834 values.foreground = 1;
8835 values.background = 0;
8836 /* Don't use XtGetGC, not read only */
8837 maskGC = XCreateGC(xDisplay, buf,
8838 GCForeground | GCBackground, &values);
8839 XFreePixmap(xDisplay, buf);
8841 buf = XCreatePixmap(xDisplay, xBoardWindow,
8842 squareSize, squareSize, pieceDepth);
8843 values.foreground = XBlackPixel(xDisplay, xScreen);
8844 values.background = XWhitePixel(xDisplay, xScreen);
8845 bufGC = XCreateGC(xDisplay, buf,
8846 GCForeground | GCBackground, &values);
8848 for (piece = WhitePawn; piece <= BlackKing; piece++) {
8849 /* Begin with empty mask */
8850 if(!xpmDone) // [HGM] pieces: keep using existing
8851 xpmMask[piece] = XCreatePixmap(xDisplay, xBoardWindow,
8852 squareSize, squareSize, 1);
8853 XSetFunction(xDisplay, maskGC, GXclear);
8854 XFillRectangle(xDisplay, xpmMask[piece], maskGC,
8855 0, 0, squareSize, squareSize);
8857 /* Take a copy of the piece */
8862 XSetFunction(xDisplay, bufGC, GXcopy);
8863 XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % (int)BlackPawn],
8865 0, 0, squareSize, squareSize, 0, 0);
8867 /* XOR the background (light) over the piece */
8868 XSetFunction(xDisplay, bufGC, GXxor);
8870 XCopyArea(xDisplay, xpmLightSquare, buf, bufGC,
8871 0, 0, squareSize, squareSize, 0, 0);
8873 XSetForeground(xDisplay, bufGC, lightSquareColor);
8874 XFillRectangle(xDisplay, buf, bufGC, 0, 0, squareSize, squareSize);
8877 /* We now have an inverted piece image with the background
8878 erased. Construct mask by just selecting all the non-zero
8879 pixels - no need to reconstruct the original image. */
8880 XSetFunction(xDisplay, maskGC, GXor);
8882 /* Might be quicker to download an XImage and create bitmap
8883 data from it rather than this N copies per piece, but it
8884 only takes a fraction of a second and there is a much
8885 longer delay for loading the pieces. */
8886 for (n = 0; n < pieceDepth; n ++) {
8887 XCopyPlane(xDisplay, buf, xpmMask[piece], maskGC,
8888 0, 0, squareSize, squareSize,
8894 XFreePixmap(xDisplay, buf);
8895 XFreeGC(xDisplay, bufGC);
8896 XFreeGC(xDisplay, maskGC);
8900 InitAnimState (anim, info)
8902 XWindowAttributes * info;
8907 /* Each buffer is square size, same depth as window */
8908 anim->saveBuf = XCreatePixmap(xDisplay, xBoardWindow,
8909 squareSize, squareSize, info->depth);
8910 anim->newBuf = XCreatePixmap(xDisplay, xBoardWindow,
8911 squareSize, squareSize, info->depth);
8913 /* Create a plain GC for blitting */
8914 mask = GCForeground | GCBackground | GCFunction |
8915 GCPlaneMask | GCGraphicsExposures;
8916 values.foreground = XBlackPixel(xDisplay, xScreen);
8917 values.background = XWhitePixel(xDisplay, xScreen);
8918 values.function = GXcopy;
8919 values.plane_mask = AllPlanes;
8920 values.graphics_exposures = False;
8921 anim->blitGC = XCreateGC(xDisplay, xBoardWindow, mask, &values);
8923 /* Piece will be copied from an existing context at
8924 the start of each new animation/drag. */
8925 anim->pieceGC = XCreateGC(xDisplay, xBoardWindow, 0, &values);
8927 /* Outline will be a read-only copy of an existing */
8928 anim->outlineGC = None;
8934 static VariantClass old = (VariantClass) -1; // [HGM] pieces: redo every time variant changes
8935 XWindowAttributes info;
8937 if (xpmDone && gameInfo.variant == old) return;
8938 if(xpmDone) old = gameInfo.variant; // first time pieces might not be created yet
8939 XGetWindowAttributes(xDisplay, xBoardWindow, &info);
8941 InitAnimState(&game, &info);
8942 InitAnimState(&player, &info);
8944 /* For XPM pieces, we need bitmaps to use as masks. */
8946 CreateAnimMasks(info.depth);
8952 static Boolean frameWaiting;
8954 static RETSIGTYPE FrameAlarm (sig)
8957 frameWaiting = False;
8958 /* In case System-V style signals. Needed?? */
8959 signal(SIGALRM, FrameAlarm);
8966 struct itimerval delay;
8968 XSync(xDisplay, False);
8971 frameWaiting = True;
8972 signal(SIGALRM, FrameAlarm);
8973 delay.it_interval.tv_sec =
8974 delay.it_value.tv_sec = time / 1000;
8975 delay.it_interval.tv_usec =
8976 delay.it_value.tv_usec = (time % 1000) * 1000;
8977 setitimer(ITIMER_REAL, &delay, NULL);
8979 /* Ugh -- busy-wait! --tpm */
8980 while (frameWaiting);
8982 while (frameWaiting) pause();
8984 delay.it_interval.tv_sec = delay.it_value.tv_sec = 0;
8985 delay.it_interval.tv_usec = delay.it_value.tv_usec = 0;
8986 setitimer(ITIMER_REAL, &delay, NULL);
8996 XSync(xDisplay, False);
8998 usleep(time * 1000);
9003 /* Convert board position to corner of screen rect and color */
9006 ScreenSquare(column, row, pt, color)
9007 int column; int row; XPoint * pt; int * color;
9010 pt->x = lineGap + ((BOARD_WIDTH-1)-column) * (squareSize + lineGap);
9011 pt->y = lineGap + row * (squareSize + lineGap);
9013 pt->x = lineGap + column * (squareSize + lineGap);
9014 pt->y = lineGap + ((BOARD_HEIGHT-1)-row) * (squareSize + lineGap);
9016 *color = SquareColor(row, column);
9019 /* Convert window coords to square */
9022 BoardSquare(x, y, column, row)
9023 int x; int y; int * column; int * row;
9025 *column = EventToSquare(x, BOARD_WIDTH);
9026 if (flipView && *column >= 0)
9027 *column = BOARD_WIDTH - 1 - *column;
9028 *row = EventToSquare(y, BOARD_HEIGHT);
9029 if (!flipView && *row >= 0)
9030 *row = BOARD_HEIGHT - 1 - *row;
9035 #undef Max /* just in case */
9037 #define Max(a, b) ((a) > (b) ? (a) : (b))
9038 #define Min(a, b) ((a) < (b) ? (a) : (b))
9041 SetRect(rect, x, y, width, height)
9042 XRectangle * rect; int x; int y; int width; int height;
9046 rect->width = width;
9047 rect->height = height;
9050 /* Test if two frames overlap. If they do, return
9051 intersection rect within old and location of
9052 that rect within new. */
9055 Intersect(old, new, size, area, pt)
9056 XPoint * old; XPoint * new;
9057 int size; XRectangle * area; XPoint * pt;
9059 if (old->x > new->x + size || new->x > old->x + size ||
9060 old->y > new->y + size || new->y > old->y + size) {
9063 SetRect(area, Max(new->x - old->x, 0), Max(new->y - old->y, 0),
9064 size - abs(old->x - new->x), size - abs(old->y - new->y));
9065 pt->x = Max(old->x - new->x, 0);
9066 pt->y = Max(old->y - new->y, 0);
9071 /* For two overlapping frames, return the rect(s)
9072 in the old that do not intersect with the new. */
9075 CalcUpdateRects(old, new, size, update, nUpdates)
9076 XPoint * old; XPoint * new; int size;
9077 XRectangle update[]; int * nUpdates;
9081 /* If old = new (shouldn't happen) then nothing to draw */
9082 if (old->x == new->x && old->y == new->y) {
9086 /* Work out what bits overlap. Since we know the rects
9087 are the same size we don't need a full intersect calc. */
9089 /* Top or bottom edge? */
9090 if (new->y > old->y) {
9091 SetRect(&(update[count]), old->x, old->y, size, new->y - old->y);
9093 } else if (old->y > new->y) {
9094 SetRect(&(update[count]), old->x, old->y + size - (old->y - new->y),
9095 size, old->y - new->y);
9098 /* Left or right edge - don't overlap any update calculated above. */
9099 if (new->x > old->x) {
9100 SetRect(&(update[count]), old->x, Max(new->y, old->y),
9101 new->x - old->x, size - abs(new->y - old->y));
9103 } else if (old->x > new->x) {
9104 SetRect(&(update[count]), new->x + size, Max(new->y, old->y),
9105 old->x - new->x, size - abs(new->y - old->y));
9112 /* Generate a series of frame coords from start->mid->finish.
9113 The movement rate doubles until the half way point is
9114 reached, then halves back down to the final destination,
9115 which gives a nice slow in/out effect. The algorithmn
9116 may seem to generate too many intermediates for short
9117 moves, but remember that the purpose is to attract the
9118 viewers attention to the piece about to be moved and
9119 then to where it ends up. Too few frames would be less
9123 Tween(start, mid, finish, factor, frames, nFrames)
9124 XPoint * start; XPoint * mid;
9125 XPoint * finish; int factor;
9126 XPoint frames[]; int * nFrames;
9128 int fraction, n, count;
9132 /* Slow in, stepping 1/16th, then 1/8th, ... */
9134 for (n = 0; n < factor; n++)
9136 for (n = 0; n < factor; n++) {
9137 frames[count].x = start->x + (mid->x - start->x) / fraction;
9138 frames[count].y = start->y + (mid->y - start->y) / fraction;
9140 fraction = fraction / 2;
9144 frames[count] = *mid;
9147 /* Slow out, stepping 1/2, then 1/4, ... */
9149 for (n = 0; n < factor; n++) {
9150 frames[count].x = finish->x - (finish->x - mid->x) / fraction;
9151 frames[count].y = finish->y - (finish->y - mid->y) / fraction;
9153 fraction = fraction * 2;
9158 /* Draw a piece on the screen without disturbing what's there */
9161 SelectGCMask(piece, clip, outline, mask)
9162 ChessSquare piece; GC * clip; GC * outline; Pixmap * mask;
9166 /* Bitmap for piece being moved. */
9167 if (appData.monoMode) {
9168 *mask = *pieceToSolid(piece);
9169 } else if (useImages) {
9171 *mask = xpmMask[piece];
9173 *mask = ximMaskPm[piece];
9176 *mask = *pieceToSolid(piece);
9179 /* GC for piece being moved. Square color doesn't matter, but
9180 since it gets modified we make a copy of the original. */
9182 if (appData.monoMode)
9187 if (appData.monoMode)
9192 XCopyGC(xDisplay, source, 0xFFFFFFFF, *clip);
9194 /* Outline only used in mono mode and is not modified */
9196 *outline = bwPieceGC;
9198 *outline = wbPieceGC;
9202 OverlayPiece(piece, clip, outline, dest)
9203 ChessSquare piece; GC clip; GC outline; Drawable dest;
9208 /* Draw solid rectangle which will be clipped to shape of piece */
9209 XFillRectangle(xDisplay, dest, clip,
9210 0, 0, squareSize, squareSize);
9211 if (appData.monoMode)
9212 /* Also draw outline in contrasting color for black
9213 on black / white on white cases */
9214 XCopyPlane(xDisplay, *pieceToOutline(piece), dest, outline,
9215 0, 0, squareSize, squareSize, 0, 0, 1);
9217 /* Copy the piece */
9222 XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
9224 0, 0, squareSize, squareSize,
9229 /* Animate the movement of a single piece */
9232 BeginAnimation(anim, piece, startColor, start)
9240 /* The old buffer is initialised with the start square (empty) */
9241 BlankSquare(0, 0, startColor, EmptySquare, anim->saveBuf);
9242 anim->prevFrame = *start;
9244 /* The piece will be drawn using its own bitmap as a matte */
9245 SelectGCMask(piece, &anim->pieceGC, &anim->outlineGC, &mask);
9246 XSetClipMask(xDisplay, anim->pieceGC, mask);
9250 AnimationFrame(anim, frame, piece)
9255 XRectangle updates[4];
9260 /* Save what we are about to draw into the new buffer */
9261 XCopyArea(xDisplay, xBoardWindow, anim->newBuf, anim->blitGC,
9262 frame->x, frame->y, squareSize, squareSize,
9265 /* Erase bits of the previous frame */
9266 if (Intersect(&anim->prevFrame, frame, squareSize, &overlap, &pt)) {
9267 /* Where the new frame overlapped the previous,
9268 the contents in newBuf are wrong. */
9269 XCopyArea(xDisplay, anim->saveBuf, anim->newBuf, anim->blitGC,
9270 overlap.x, overlap.y,
9271 overlap.width, overlap.height,
9273 /* Repaint the areas in the old that don't overlap new */
9274 CalcUpdateRects(&anim->prevFrame, frame, squareSize, updates, &count);
9275 for (i = 0; i < count; i++)
9276 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9277 updates[i].x - anim->prevFrame.x,
9278 updates[i].y - anim->prevFrame.y,
9279 updates[i].width, updates[i].height,
9280 updates[i].x, updates[i].y);
9282 /* Easy when no overlap */
9283 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9284 0, 0, squareSize, squareSize,
9285 anim->prevFrame.x, anim->prevFrame.y);
9288 /* Save this frame for next time round */
9289 XCopyArea(xDisplay, anim->newBuf, anim->saveBuf, anim->blitGC,
9290 0, 0, squareSize, squareSize,
9292 anim->prevFrame = *frame;
9294 /* Draw piece over original screen contents, not current,
9295 and copy entire rect. Wipes out overlapping piece images. */
9296 OverlayPiece(piece, anim->pieceGC, anim->outlineGC, anim->newBuf);
9297 XCopyArea(xDisplay, anim->newBuf, xBoardWindow, anim->blitGC,
9298 0, 0, squareSize, squareSize,
9299 frame->x, frame->y);
9303 EndAnimation (anim, finish)
9307 XRectangle updates[4];
9312 /* The main code will redraw the final square, so we
9313 only need to erase the bits that don't overlap. */
9314 if (Intersect(&anim->prevFrame, finish, squareSize, &overlap, &pt)) {
9315 CalcUpdateRects(&anim->prevFrame, finish, squareSize, updates, &count);
9316 for (i = 0; i < count; i++)
9317 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9318 updates[i].x - anim->prevFrame.x,
9319 updates[i].y - anim->prevFrame.y,
9320 updates[i].width, updates[i].height,
9321 updates[i].x, updates[i].y);
9323 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9324 0, 0, squareSize, squareSize,
9325 anim->prevFrame.x, anim->prevFrame.y);
9330 FrameSequence(anim, piece, startColor, start, finish, frames, nFrames)
9332 ChessSquare piece; int startColor;
9333 XPoint * start; XPoint * finish;
9334 XPoint frames[]; int nFrames;
9338 BeginAnimation(anim, piece, startColor, start);
9339 for (n = 0; n < nFrames; n++) {
9340 AnimationFrame(anim, &(frames[n]), piece);
9341 FrameDelay(appData.animSpeed);
9343 EndAnimation(anim, finish);
9346 /* Main control logic for deciding what to animate and how */
9349 AnimateMove(board, fromX, fromY, toX, toY)
9358 XPoint start, finish, mid;
9359 XPoint frames[kFactor * 2 + 1];
9360 int nFrames, startColor, endColor;
9362 /* Are we animating? */
9363 if (!appData.animate || appData.blindfold)
9366 if(board[toY][toX] == WhiteRook && board[fromY][fromX] == WhiteKing ||
9367 board[toY][toX] == BlackRook && board[fromY][fromX] == BlackKing)
9368 return; // [HGM] FRC: no animtion of FRC castlings, as to-square is not true to-square
9370 if (fromY < 0 || fromX < 0 || toX < 0 || toY < 0) return;
9371 piece = board[fromY][fromX];
9372 if (piece >= EmptySquare) return;
9377 hop = (piece == WhiteKnight || piece == BlackKnight);
9380 if (appData.debugMode) {
9381 fprintf(debugFP, hop ? _("AnimateMove: piece %d hops from %d,%d to %d,%d \n") :
9382 _("AnimateMove: piece %d slides from %d,%d to %d,%d \n"),
9383 piece, fromX, fromY, toX, toY); }
9385 ScreenSquare(fromX, fromY, &start, &startColor);
9386 ScreenSquare(toX, toY, &finish, &endColor);
9389 /* Knight: make diagonal movement then straight */
9390 if (abs(toY - fromY) < abs(toX - fromX)) {
9391 mid.x = start.x + (finish.x - start.x) / 2;
9395 mid.y = start.y + (finish.y - start.y) / 2;
9398 mid.x = start.x + (finish.x - start.x) / 2;
9399 mid.y = start.y + (finish.y - start.y) / 2;
9402 /* Don't use as many frames for very short moves */
9403 if (abs(toY - fromY) + abs(toX - fromX) <= 2)
9404 Tween(&start, &mid, &finish, kFactor - 1, frames, &nFrames);
9406 Tween(&start, &mid, &finish, kFactor, frames, &nFrames);
9407 FrameSequence(&game, piece, startColor, &start, &finish, frames, nFrames);
9409 /* Be sure end square is redrawn */
9410 damage[toY][toX] = True;
9414 DragPieceBegin(x, y)
9417 int boardX, boardY, color;
9420 /* Are we animating? */
9421 if (!appData.animateDragging || appData.blindfold)
9424 /* Figure out which square we start in and the
9425 mouse position relative to top left corner. */
9426 BoardSquare(x, y, &boardX, &boardY);
9427 player.startBoardX = boardX;
9428 player.startBoardY = boardY;
9429 ScreenSquare(boardX, boardY, &corner, &color);
9430 player.startSquare = corner;
9431 player.startColor = color;
9433 /* Start from exactly where the piece is. This can be confusing
9434 if you start dragging far from the center of the square; most
9435 or all of the piece can be over a different square from the one
9436 the mouse pointer is in. */
9437 player.mouseDelta.x = x - corner.x;
9438 player.mouseDelta.y = y - corner.y;
9440 /* As soon as we start dragging, the piece will jump slightly to
9441 be centered over the mouse pointer. */
9442 player.mouseDelta.x = squareSize/2;
9443 player.mouseDelta.y = squareSize/2;
9445 /* Initialise animation */
9446 player.dragPiece = PieceForSquare(boardX, boardY);
9448 if (player.dragPiece >= 0 && player.dragPiece < EmptySquare) {
9449 player.dragActive = True;
9450 BeginAnimation(&player, player.dragPiece, color, &corner);
9451 /* Mark this square as needing to be redrawn. Note that
9452 we don't remove the piece though, since logically (ie
9453 as seen by opponent) the move hasn't been made yet. */
9454 if(boardX == BOARD_RGHT+1 && PieceForSquare(boardX-1, boardY) > 1 ||
9455 boardX == BOARD_LEFT-2 && PieceForSquare(boardX+1, boardY) > 1)
9456 XCopyArea(xDisplay, xBoardWindow, player.saveBuf, player.blitGC,
9457 corner.x, corner.y, squareSize, squareSize,
9458 0, 0); // [HGM] zh: unstack in stead of grab
9459 damage[boardY][boardX] = True;
9461 player.dragActive = False;
9471 /* Are we animating? */
9472 if (!appData.animateDragging || appData.blindfold)
9476 if (! player.dragActive)
9478 /* Move piece, maintaining same relative position
9479 of mouse within square */
9480 corner.x = x - player.mouseDelta.x;
9481 corner.y = y - player.mouseDelta.y;
9482 AnimationFrame(&player, &corner, player.dragPiece);
9484 if (appData.highlightDragging) {
9486 BoardSquare(x, y, &boardX, &boardY);
9487 SetHighlights(fromX, fromY, boardX, boardY);
9496 int boardX, boardY, color;
9499 /* Are we animating? */
9500 if (!appData.animateDragging || appData.blindfold)
9504 if (! player.dragActive)
9506 /* Last frame in sequence is square piece is
9507 placed on, which may not match mouse exactly. */
9508 BoardSquare(x, y, &boardX, &boardY);
9509 ScreenSquare(boardX, boardY, &corner, &color);
9510 EndAnimation(&player, &corner);
9512 /* Be sure end square is redrawn */
9513 damage[boardY][boardX] = True;
9515 /* This prevents weird things happening with fast successive
9516 clicks which on my Sun at least can cause motion events
9517 without corresponding press/release. */
9518 player.dragActive = False;
9521 /* Handle expose event while piece being dragged */
9526 if (!player.dragActive || appData.blindfold)
9529 /* What we're doing: logically, the move hasn't been made yet,
9530 so the piece is still in it's original square. But visually
9531 it's being dragged around the board. So we erase the square
9532 that the piece is on and draw it at the last known drag point. */
9533 BlankSquare(player.startSquare.x, player.startSquare.y,
9534 player.startColor, EmptySquare, xBoardWindow);
9535 AnimationFrame(&player, &player.prevFrame, player.dragPiece);
9536 damage[player.startBoardY][player.startBoardX] = TRUE;
9540 SetProgramStats( FrontEndProgramStats * stats )
9543 // [HGM] done, but perhaps backend should call this directly?
9544 EngineOutputUpdate( stats );