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 { /* left over command line arguments, print out help and exit.
2424 * Use two columns to print help
2426 fprintf(stderr, _("%s: unrecognized argument %s\n"),
2427 programName, argv[1]);
2429 fprintf(stderr, "Recognized options:\n");
2430 for(i = 0; i < XtNumber(shellOptions); i++)
2432 /* print first column */
2433 j = fprintf(stderr, " %s%s", shellOptions[i].option,
2434 (shellOptions[i].argKind == XrmoptionSepArg
2436 /* print second column and end line */
2437 if (++i < XtNumber(shellOptions))
2439 fprintf(stderr, "%*c%s%s\n", 40 - j, ' ',
2440 shellOptions[i].option,
2441 (shellOptions[i].argKind == XrmoptionSepArg
2446 fprintf(stderr, "\n");
2453 if (p == NULL) p = "/tmp";
2454 i = strlen(p) + strlen("/.xboardXXXXXx.pgn") + 1;
2455 gameCopyFilename = (char*) malloc(i);
2456 gamePasteFilename = (char*) malloc(i);
2457 snprintf(gameCopyFilename,i, "%s/.xboard%05uc.pgn", p, getpid());
2458 snprintf(gamePasteFilename,i, "%s/.xboard%05up.pgn", p, getpid());
2460 XtGetApplicationResources(shellWidget, (XtPointer) &appData,
2461 clientResources, XtNumber(clientResources),
2464 { // [HGM] initstring: kludge to fix bad bug. expand '\n' characters in init string and computer string.
2465 static char buf[MSG_SIZ];
2466 EscapeExpand(buf, appData.initString);
2467 appData.initString = strdup(buf);
2468 EscapeExpand(buf, appData.secondInitString);
2469 appData.secondInitString = strdup(buf);
2470 EscapeExpand(buf, appData.firstComputerString);
2471 appData.firstComputerString = strdup(buf);
2472 EscapeExpand(buf, appData.secondComputerString);
2473 appData.secondComputerString = strdup(buf);
2476 if ((chessDir = (char *) getenv("CHESSDIR")) == NULL) {
2479 if (chdir(chessDir) != 0) {
2480 fprintf(stderr, _("%s: can't cd to CHESSDIR: "), programName);
2486 if (appData.debugMode && appData.nameOfDebugFile && strcmp(appData.nameOfDebugFile, "stderr")) {
2487 /* [DM] debug info to file [HGM] make the filename a command-line option, and allow it to remain stderr */
2488 if ((debugFP = fopen(appData.nameOfDebugFile, "w")) == NULL) {
2489 printf(_("Failed to open file '%s'\n"), appData.nameOfDebugFile);
2492 setbuf(debugFP, NULL);
2495 /* [HGM,HR] make sure board size is acceptable */
2496 if(appData.NrFiles > BOARD_SIZE ||
2497 appData.NrRanks > BOARD_SIZE )
2498 DisplayFatalError(_("Recompile with BOARD_SIZE > 12, to support this size"), 0, 2);
2501 /* This feature does not work; animation needs a rewrite */
2502 appData.highlightDragging = FALSE;
2506 xDisplay = XtDisplay(shellWidget);
2507 xScreen = DefaultScreen(xDisplay);
2508 wm_delete_window = XInternAtom(xDisplay, "WM_DELETE_WINDOW", True);
2510 gameInfo.variant = StringToVariant(appData.variant);
2511 InitPosition(FALSE);
2514 * Determine boardSize
2516 gameInfo.boardWidth = gameInfo.boardHeight = 8; // [HGM] boardsize: make sure we start as 8x8
2519 // [HGM] as long as we have not created the possibility to change size while running, start with requested size
2520 gameInfo.boardWidth = appData.NrFiles > 0 ? appData.NrFiles : 8;
2521 gameInfo.boardHeight = appData.NrRanks > 0 ? appData.NrRanks : 8;
2522 gameInfo.holdingsWidth = appData.holdingsSize > 0 ? 2 : 0;
2527 InitDrawingSizes(-1, 0); // [HGM] initsize: make this into a subroutine
2529 if (isdigit(appData.boardSize[0])) {
2530 i = sscanf(appData.boardSize, "%d,%d,%d,%d,%d,%d,%d", &squareSize,
2531 &lineGap, &clockFontPxlSize, &coordFontPxlSize,
2532 &fontPxlSize, &smallLayout, &tinyLayout);
2534 fprintf(stderr, _("%s: bad boardSize syntax %s\n"),
2535 programName, appData.boardSize);
2539 /* Find some defaults; use the nearest known size */
2540 SizeDefaults *szd, *nearest;
2541 int distance = 99999;
2542 nearest = szd = sizeDefaults;
2543 while (szd->name != NULL) {
2544 if (abs(szd->squareSize - squareSize) < distance) {
2546 distance = abs(szd->squareSize - squareSize);
2547 if (distance == 0) break;
2551 if (i < 2) lineGap = nearest->lineGap;
2552 if (i < 3) clockFontPxlSize = nearest->clockFontPxlSize;
2553 if (i < 4) coordFontPxlSize = nearest->coordFontPxlSize;
2554 if (i < 5) fontPxlSize = nearest->fontPxlSize;
2555 if (i < 6) smallLayout = nearest->smallLayout;
2556 if (i < 7) tinyLayout = nearest->tinyLayout;
2559 SizeDefaults *szd = sizeDefaults;
2560 if (*appData.boardSize == NULLCHAR) {
2561 while (DisplayWidth(xDisplay, xScreen) < szd->minScreenSize ||
2562 DisplayHeight(xDisplay, xScreen) < szd->minScreenSize) {
2565 if (szd->name == NULL) szd--;
2567 while (szd->name != NULL &&
2568 StrCaseCmp(szd->name, appData.boardSize) != 0) szd++;
2569 if (szd->name == NULL) {
2570 fprintf(stderr, _("%s: unrecognized boardSize name %s\n"),
2571 programName, appData.boardSize);
2575 squareSize = szd->squareSize;
2576 lineGap = szd->lineGap;
2577 clockFontPxlSize = szd->clockFontPxlSize;
2578 coordFontPxlSize = szd->coordFontPxlSize;
2579 fontPxlSize = szd->fontPxlSize;
2580 smallLayout = szd->smallLayout;
2581 tinyLayout = szd->tinyLayout;
2584 /* Now, using squareSize as a hint, find a good XPM/XIM set size */
2585 if (strlen(appData.pixmapDirectory) > 0) {
2586 p = ExpandPathName(appData.pixmapDirectory);
2588 fprintf(stderr, _("Error expanding path name \"%s\"\n"),
2589 appData.pixmapDirectory);
2592 if (appData.debugMode) {
2593 fprintf(stderr, _("\
2594 XBoard square size (hint): %d\n\
2595 %s fulldir:%s:\n"), squareSize, IMAGE_EXT, p);
2597 squareSize = xpm_closest_to(p, squareSize, IMAGE_EXT);
2598 if (appData.debugMode) {
2599 fprintf(stderr, _("Closest %s size: %d\n"), IMAGE_EXT, squareSize);
2603 /* [HR] height treated separately (hacked) */
2604 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2605 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2606 if (appData.showJail == 1) {
2607 /* Jail on top and bottom */
2608 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2609 XtSetArg(boardArgs[2], XtNheight,
2610 boardHeight + 2*(lineGap + squareSize));
2611 } else if (appData.showJail == 2) {
2613 XtSetArg(boardArgs[1], XtNwidth,
2614 boardWidth + 2*(lineGap + squareSize));
2615 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2618 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2619 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2623 * Determine what fonts to use.
2625 appData.clockFont = FindFont(appData.clockFont, clockFontPxlSize);
2626 clockFontID = XLoadFont(xDisplay, appData.clockFont);
2627 clockFontStruct = XQueryFont(xDisplay, clockFontID);
2628 appData.coordFont = FindFont(appData.coordFont, coordFontPxlSize);
2629 coordFontID = XLoadFont(xDisplay, appData.coordFont);
2630 coordFontStruct = XQueryFont(xDisplay, coordFontID);
2631 appData.font = FindFont(appData.font, fontPxlSize);
2632 countFontID = XLoadFont(xDisplay, appData.coordFont); // [HGM] holdings
2633 countFontStruct = XQueryFont(xDisplay, countFontID);
2634 // appData.font = FindFont(appData.font, fontPxlSize);
2636 xdb = XtDatabase(xDisplay);
2637 XrmPutStringResource(&xdb, "*font", appData.font);
2640 * Detect if there are not enough colors available and adapt.
2642 if (DefaultDepth(xDisplay, xScreen) <= 2) {
2643 appData.monoMode = True;
2646 if (!appData.monoMode) {
2647 vFrom.addr = (caddr_t) appData.lightSquareColor;
2648 vFrom.size = strlen(appData.lightSquareColor);
2649 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2650 if (vTo.addr == NULL) {
2651 appData.monoMode = True;
2654 lightSquareColor = *(Pixel *) vTo.addr;
2657 if (!appData.monoMode) {
2658 vFrom.addr = (caddr_t) appData.darkSquareColor;
2659 vFrom.size = strlen(appData.darkSquareColor);
2660 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2661 if (vTo.addr == NULL) {
2662 appData.monoMode = True;
2665 darkSquareColor = *(Pixel *) vTo.addr;
2668 if (!appData.monoMode) {
2669 vFrom.addr = (caddr_t) appData.whitePieceColor;
2670 vFrom.size = strlen(appData.whitePieceColor);
2671 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2672 if (vTo.addr == NULL) {
2673 appData.monoMode = True;
2676 whitePieceColor = *(Pixel *) vTo.addr;
2679 if (!appData.monoMode) {
2680 vFrom.addr = (caddr_t) appData.blackPieceColor;
2681 vFrom.size = strlen(appData.blackPieceColor);
2682 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2683 if (vTo.addr == NULL) {
2684 appData.monoMode = True;
2687 blackPieceColor = *(Pixel *) vTo.addr;
2691 if (!appData.monoMode) {
2692 vFrom.addr = (caddr_t) appData.highlightSquareColor;
2693 vFrom.size = strlen(appData.highlightSquareColor);
2694 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2695 if (vTo.addr == NULL) {
2696 appData.monoMode = True;
2699 highlightSquareColor = *(Pixel *) vTo.addr;
2703 if (!appData.monoMode) {
2704 vFrom.addr = (caddr_t) appData.premoveHighlightColor;
2705 vFrom.size = strlen(appData.premoveHighlightColor);
2706 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2707 if (vTo.addr == NULL) {
2708 appData.monoMode = True;
2711 premoveHighlightColor = *(Pixel *) vTo.addr;
2716 fprintf(stderr, _("%s: too few colors available; trying monochrome mode\n"),
2719 if (appData.bitmapDirectory == NULL ||
2720 appData.bitmapDirectory[0] == NULLCHAR)
2721 appData.bitmapDirectory = DEF_BITMAP_DIR;
2724 if (appData.lowTimeWarning && !appData.monoMode) {
2725 vFrom.addr = (caddr_t) appData.lowTimeWarningColor;
2726 vFrom.size = strlen(appData.lowTimeWarningColor);
2727 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2728 if (vTo.addr == NULL)
2729 appData.monoMode = True;
2731 lowTimeWarningColor = *(Pixel *) vTo.addr;
2734 if (appData.monoMode && appData.debugMode) {
2735 fprintf(stderr, _("white pixel = 0x%lx, black pixel = 0x%lx\n"),
2736 (unsigned long) XWhitePixel(xDisplay, xScreen),
2737 (unsigned long) XBlackPixel(xDisplay, xScreen));
2740 if (parse_cpair(ColorShout, appData.colorShout) < 0 ||
2741 parse_cpair(ColorSShout, appData.colorSShout) < 0 ||
2742 parse_cpair(ColorChannel1, appData.colorChannel1) < 0 ||
2743 parse_cpair(ColorChannel, appData.colorChannel) < 0 ||
2744 parse_cpair(ColorKibitz, appData.colorKibitz) < 0 ||
2745 parse_cpair(ColorTell, appData.colorTell) < 0 ||
2746 parse_cpair(ColorChallenge, appData.colorChallenge) < 0 ||
2747 parse_cpair(ColorRequest, appData.colorRequest) < 0 ||
2748 parse_cpair(ColorSeek, appData.colorSeek) < 0 ||
2749 parse_cpair(ColorNormal, appData.colorNormal) < 0)
2751 if (appData.colorize) {
2753 _("%s: can't parse color names; disabling colorization\n"),
2756 appData.colorize = FALSE;
2758 textColors[ColorNone].fg = textColors[ColorNone].bg = -1;
2759 textColors[ColorNone].attr = 0;
2761 XtAppAddActions(appContext, boardActions, XtNumber(boardActions));
2767 layoutName = "tinyLayout";
2768 } else if (smallLayout) {
2769 layoutName = "smallLayout";
2771 layoutName = "normalLayout";
2773 /* Outer layoutWidget is there only to provide a name for use in
2774 resources that depend on the layout style */
2776 XtCreateManagedWidget(layoutName, formWidgetClass, shellWidget,
2777 layoutArgs, XtNumber(layoutArgs));
2779 XtCreateManagedWidget("form", formWidgetClass, layoutWidget,
2780 formArgs, XtNumber(formArgs));
2781 XtSetArg(args[0], XtNdefaultDistance, &sep);
2782 XtGetValues(formWidget, args, 1);
2785 widgetList[j++] = menuBarWidget = CreateMenuBar(menuBar);
2786 XtSetArg(args[0], XtNtop, XtChainTop);
2787 XtSetArg(args[1], XtNbottom, XtChainTop);
2788 XtSetValues(menuBarWidget, args, 2);
2790 widgetList[j++] = whiteTimerWidget =
2791 XtCreateWidget("whiteTime", labelWidgetClass,
2792 formWidget, timerArgs, XtNumber(timerArgs));
2793 XtSetArg(args[0], XtNfont, clockFontStruct);
2794 XtSetArg(args[1], XtNtop, XtChainTop);
2795 XtSetArg(args[2], XtNbottom, XtChainTop);
2796 XtSetValues(whiteTimerWidget, args, 3);
2798 widgetList[j++] = blackTimerWidget =
2799 XtCreateWidget("blackTime", labelWidgetClass,
2800 formWidget, timerArgs, XtNumber(timerArgs));
2801 XtSetArg(args[0], XtNfont, clockFontStruct);
2802 XtSetArg(args[1], XtNtop, XtChainTop);
2803 XtSetArg(args[2], XtNbottom, XtChainTop);
2804 XtSetValues(blackTimerWidget, args, 3);
2806 if (appData.titleInWindow) {
2807 widgetList[j++] = titleWidget =
2808 XtCreateWidget("title", labelWidgetClass, formWidget,
2809 titleArgs, XtNumber(titleArgs));
2810 XtSetArg(args[0], XtNtop, XtChainTop);
2811 XtSetArg(args[1], XtNbottom, XtChainTop);
2812 XtSetValues(titleWidget, args, 2);
2815 if (appData.showButtonBar) {
2816 widgetList[j++] = buttonBarWidget = CreateButtonBar(buttonBar);
2817 XtSetArg(args[0], XtNleft, XtChainRight); // [HGM] glue to right window edge
2818 XtSetArg(args[1], XtNright, XtChainRight); // for good run-time sizing
2819 XtSetArg(args[2], XtNtop, XtChainTop);
2820 XtSetArg(args[3], XtNbottom, XtChainTop);
2821 XtSetValues(buttonBarWidget, args, 4);
2824 widgetList[j++] = messageWidget =
2825 XtCreateWidget("message", labelWidgetClass, formWidget,
2826 messageArgs, XtNumber(messageArgs));
2827 XtSetArg(args[0], XtNtop, XtChainTop);
2828 XtSetArg(args[1], XtNbottom, XtChainTop);
2829 XtSetValues(messageWidget, args, 2);
2831 widgetList[j++] = boardWidget =
2832 XtCreateWidget("board", widgetClass, formWidget, boardArgs,
2833 XtNumber(boardArgs));
2835 XtManageChildren(widgetList, j);
2837 timerWidth = (boardWidth - sep) / 2;
2838 XtSetArg(args[0], XtNwidth, timerWidth);
2839 XtSetValues(whiteTimerWidget, args, 1);
2840 XtSetValues(blackTimerWidget, args, 1);
2842 XtSetArg(args[0], XtNbackground, &timerBackgroundPixel);
2843 XtSetArg(args[1], XtNforeground, &timerForegroundPixel);
2844 XtGetValues(whiteTimerWidget, args, 2);
2846 if (appData.showButtonBar) {
2847 XtSetArg(args[0], XtNbackground, &buttonBackgroundPixel);
2848 XtSetArg(args[1], XtNforeground, &buttonForegroundPixel);
2849 XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
2853 * formWidget uses these constraints but they are stored
2857 XtSetArg(args[i], XtNfromHoriz, 0); i++;
2858 XtSetValues(menuBarWidget, args, i);
2859 if (appData.titleInWindow) {
2862 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2863 XtSetValues(whiteTimerWidget, args, i);
2865 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2866 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2867 XtSetValues(blackTimerWidget, args, i);
2869 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2870 XtSetArg(args[i], XtNjustify, XtJustifyLeft); i++;
2871 XtSetValues(titleWidget, args, i);
2873 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2874 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2875 XtSetValues(messageWidget, args, i);
2876 if (appData.showButtonBar) {
2878 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2879 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2880 XtSetValues(buttonBarWidget, args, i);
2884 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2885 XtSetValues(whiteTimerWidget, args, i);
2887 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2888 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2889 XtSetValues(blackTimerWidget, args, i);
2891 XtSetArg(args[i], XtNfromHoriz, menuBarWidget); i++;
2892 XtSetValues(titleWidget, args, i);
2894 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2895 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2896 XtSetValues(messageWidget, args, i);
2897 if (appData.showButtonBar) {
2899 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2900 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2901 XtSetValues(buttonBarWidget, args, i);
2906 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2907 XtSetValues(whiteTimerWidget, args, i);
2909 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2910 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2911 XtSetValues(blackTimerWidget, args, i);
2913 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2914 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2915 XtSetValues(messageWidget, args, i);
2916 if (appData.showButtonBar) {
2918 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2919 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2920 XtSetValues(buttonBarWidget, args, i);
2924 XtSetArg(args[0], XtNfromVert, messageWidget);
2925 XtSetArg(args[1], XtNtop, XtChainTop);
2926 XtSetArg(args[2], XtNbottom, XtChainBottom);
2927 XtSetArg(args[3], XtNleft, XtChainLeft);
2928 XtSetArg(args[4], XtNright, XtChainRight);
2929 XtSetValues(boardWidget, args, 5);
2931 XtRealizeWidget(shellWidget);
2934 * Correct the width of the message and title widgets.
2935 * It is not known why some systems need the extra fudge term.
2936 * The value "2" is probably larger than needed.
2938 XawFormDoLayout(formWidget, False);
2940 #define WIDTH_FUDGE 2
2942 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2943 XtSetArg(args[i], XtNheight, &h); i++;
2944 XtGetValues(messageWidget, args, i);
2945 if (appData.showButtonBar) {
2947 XtSetArg(args[i], XtNwidth, &w); i++;
2948 XtGetValues(buttonBarWidget, args, i);
2949 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2951 w = boardWidth - 2*bor + 1; /*!! +1 compensates for kludge below */
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 /* !! Horrible hack to work around bug in XFree86 4.0.1 (X11R6.4.3) */
2961 /* The size used for the child widget in layout lags one resize behind
2962 its true size, so we resize a second time, 1 pixel smaller. Yeech! */
2964 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2965 if (gres != XtGeometryYes && appData.debugMode) {
2966 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2967 programName, gres, w, h, wr, hr);
2970 XtSetArg(args[0], XtNleft, XtChainLeft); // [HGM] glue ends for good run-time sizing
2971 XtSetArg(args[1], XtNright, XtChainRight);
2972 XtSetValues(messageWidget, args, 2);
2974 if (appData.titleInWindow) {
2976 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2977 XtSetArg(args[i], XtNheight, &h); i++;
2978 XtGetValues(titleWidget, args, i);
2980 w = boardWidth - 2*bor;
2982 XtSetArg(args[0], XtNwidth, &w);
2983 XtGetValues(menuBarWidget, args, 1);
2984 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2987 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
2988 if (gres != XtGeometryYes && appData.debugMode) {
2990 _("%s: titleWidget geometry error %d %d %d %d %d\n"),
2991 programName, gres, w, h, wr, hr);
2994 XawFormDoLayout(formWidget, True);
2996 xBoardWindow = XtWindow(boardWidget);
2998 // [HGM] it seems the layout code ends here, but perhaps the color stuff is size independent and would
2999 // not need to go into InitDrawingSizes().
3003 * Create X checkmark bitmap and initialize option menu checks.
3005 ReadBitmap(&xMarkPixmap, "checkmark.bm",
3006 checkmark_bits, checkmark_width, checkmark_height);
3007 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
3008 if (appData.alwaysPromoteToQueen) {
3009 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
3012 if (appData.animateDragging) {
3013 XtSetValues(XtNameToWidget(menuBarWidget,
3014 "menuOptions.Animate Dragging"),
3017 if (appData.animate) {
3018 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
3021 if (appData.autoComment) {
3022 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
3025 if (appData.autoCallFlag) {
3026 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
3029 if (appData.autoFlipView) {
3030 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Auto Flip View"),
3033 if (appData.autoObserve) {
3034 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
3037 if (appData.autoRaiseBoard) {
3038 XtSetValues(XtNameToWidget(menuBarWidget,
3039 "menuOptions.Auto Raise Board"), args, 1);
3041 if (appData.autoSaveGames) {
3042 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
3045 if (appData.saveGameFile[0] != NULLCHAR) {
3046 /* Can't turn this off from menu */
3047 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
3049 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
3053 if (appData.blindfold) {
3054 XtSetValues(XtNameToWidget(menuBarWidget,
3055 "menuOptions.Blindfold"), args, 1);
3057 if (appData.flashCount > 0) {
3058 XtSetValues(XtNameToWidget(menuBarWidget,
3059 "menuOptions.Flash Moves"),
3062 if (appData.getMoveList) {
3063 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
3067 if (appData.highlightDragging) {
3068 XtSetValues(XtNameToWidget(menuBarWidget,
3069 "menuOptions.Highlight Dragging"),
3073 if (appData.highlightLastMove) {
3074 XtSetValues(XtNameToWidget(menuBarWidget,
3075 "menuOptions.Highlight Last Move"),
3078 if (appData.icsAlarm) {
3079 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.ICS Alarm"),
3082 if (appData.ringBellAfterMoves) {
3083 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
3086 if (appData.oldSaveStyle) {
3087 XtSetValues(XtNameToWidget(menuBarWidget,
3088 "menuOptions.Old Save Style"), args, 1);
3090 if (appData.periodicUpdates) {
3091 XtSetValues(XtNameToWidget(menuBarWidget,
3092 "menuOptions.Periodic Updates"), args, 1);
3094 if (appData.ponderNextMove) {
3095 XtSetValues(XtNameToWidget(menuBarWidget,
3096 "menuOptions.Ponder Next Move"), args, 1);
3098 if (appData.popupExitMessage) {
3099 XtSetValues(XtNameToWidget(menuBarWidget,
3100 "menuOptions.Popup Exit Message"), args, 1);
3102 if (appData.popupMoveErrors) {
3103 XtSetValues(XtNameToWidget(menuBarWidget,
3104 "menuOptions.Popup Move Errors"), args, 1);
3106 if (appData.premove) {
3107 XtSetValues(XtNameToWidget(menuBarWidget,
3108 "menuOptions.Premove"), args, 1);
3110 if (appData.quietPlay) {
3111 XtSetValues(XtNameToWidget(menuBarWidget,
3112 "menuOptions.Quiet Play"), args, 1);
3114 if (appData.showCoords) {
3115 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
3118 if (appData.hideThinkingFromHuman) {
3119 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
3122 if (appData.testLegality) {
3123 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Test Legality"),
3130 ReadBitmap(&wIconPixmap, "icon_white.bm",
3131 icon_white_bits, icon_white_width, icon_white_height);
3132 ReadBitmap(&bIconPixmap, "icon_black.bm",
3133 icon_black_bits, icon_black_width, icon_black_height);
3134 iconPixmap = wIconPixmap;
3136 XtSetArg(args[i], XtNiconPixmap, iconPixmap); i++;
3137 XtSetValues(shellWidget, args, i);
3140 * Create a cursor for the board widget.
3142 window_attributes.cursor = XCreateFontCursor(xDisplay, XC_hand2);
3143 XChangeWindowAttributes(xDisplay, xBoardWindow,
3144 CWCursor, &window_attributes);
3147 * Inhibit shell resizing.
3149 shellArgs[0].value = (XtArgVal) &w;
3150 shellArgs[1].value = (XtArgVal) &h;
3151 XtGetValues(shellWidget, shellArgs, 2);
3152 shellArgs[4].value = shellArgs[2].value = w;
3153 shellArgs[5].value = shellArgs[3].value = h;
3154 XtSetValues(shellWidget, &shellArgs[2], 4);
3155 marginW = w - boardWidth; // [HGM] needed to set new shellWidget size when we resize board
3156 marginH = h - boardHeight;
3158 CatchDeleteWindow(shellWidget, "QuitProc");
3163 if (appData.bitmapDirectory[0] != NULLCHAR) {
3170 /* Create regular pieces */
3171 if (!useImages) CreatePieces();
3176 if (appData.animate || appData.animateDragging)
3179 XtAugmentTranslations(formWidget,
3180 XtParseTranslationTable(globalTranslations));
3181 XtAugmentTranslations(boardWidget,
3182 XtParseTranslationTable(boardTranslations));
3183 XtAugmentTranslations(whiteTimerWidget,
3184 XtParseTranslationTable(whiteTranslations));
3185 XtAugmentTranslations(blackTimerWidget,
3186 XtParseTranslationTable(blackTranslations));
3188 /* Why is the following needed on some versions of X instead
3189 * of a translation? */
3190 XtAddEventHandler(boardWidget, ExposureMask, False,
3191 (XtEventHandler) EventProc, NULL);
3196 if (errorExitStatus == -1) {
3197 if (appData.icsActive) {
3198 /* We now wait until we see "login:" from the ICS before
3199 sending the logon script (problems with timestamp otherwise) */
3200 /*ICSInitScript();*/
3201 if (appData.icsInputBox) ICSInputBoxPopUp();
3204 signal(SIGINT, IntSigHandler);
3205 signal(SIGTERM, IntSigHandler);
3206 if (*appData.cmailGameName != NULLCHAR) {
3207 signal(SIGUSR1, CmailSigHandler);
3210 gameInfo.boardWidth = 0; // [HGM] pieces: kludge to ensure InitPosition() calls InitDrawingSizes()
3213 XtAppMainLoop(appContext);
3214 if (appData.debugMode) fclose(debugFP); // [DM] debug
3221 if (appData.icsActive && oldICSInteractionTitle != NULL) {
3222 DisplayIcsInteractionTitle(oldICSInteractionTitle);
3224 unlink(gameCopyFilename);
3225 unlink(gamePasteFilename);
3236 CmailSigHandler(sig)
3242 signal(SIGUSR1, SIG_IGN); /* suspend handler */
3244 /* Activate call-back function CmailSigHandlerCallBack() */
3245 OutputToProcess(cmailPR, (char *)(&dummy), sizeof(int), &error);
3247 signal(SIGUSR1, CmailSigHandler); /* re-activate handler */
3251 CmailSigHandlerCallBack(isr, closure, message, count, error)
3259 ReloadCmailMsgEvent(TRUE); /* Reload cmail msg */
3261 /**** end signal code ****/
3271 f = fopen(appData.icsLogon, "r");
3277 strcat(buf, appData.icsLogon);
3278 f = fopen(buf, "r");
3282 ProcessICSInitScript(f);
3289 EditCommentPopDown();
3300 SetMenuEnables(enab)
3304 if (!menuBarWidget) return;
3305 while (enab->name != NULL) {
3306 w = XtNameToWidget(menuBarWidget, enab->name);
3308 DisplayError(enab->name, 0);
3310 XtSetSensitive(w, enab->value);
3316 Enables icsEnables[] = {
3317 { "menuFile.Mail Move", False },
3318 { "menuFile.Reload CMail Message", False },
3319 { "menuMode.Machine Black", False },
3320 { "menuMode.Machine White", False },
3321 { "menuMode.Analysis Mode", False },
3322 { "menuMode.Analyze File", False },
3323 { "menuMode.Two Machines", False },
3325 { "menuHelp.Hint", False },
3326 { "menuHelp.Book", False },
3327 { "menuStep.Move Now", False },
3328 { "menuOptions.Periodic Updates", False },
3329 { "menuOptions.Hide Thinking", False },
3330 { "menuOptions.Ponder Next Move", False },
3335 Enables ncpEnables[] = {
3336 { "menuFile.Mail Move", False },
3337 { "menuFile.Reload CMail Message", False },
3338 { "menuMode.Machine White", False },
3339 { "menuMode.Machine Black", False },
3340 { "menuMode.Analysis Mode", False },
3341 { "menuMode.Analyze File", False },
3342 { "menuMode.Two Machines", False },
3343 { "menuMode.ICS Client", False },
3344 { "menuMode.ICS Input Box", False },
3345 { "Action", False },
3346 { "menuStep.Revert", False },
3347 { "menuStep.Move Now", False },
3348 { "menuStep.Retract Move", False },
3349 { "menuOptions.Auto Comment", False },
3350 { "menuOptions.Auto Flag", False },
3351 { "menuOptions.Auto Flip View", False },
3352 { "menuOptions.Auto Observe", False },
3353 { "menuOptions.Auto Raise Board", False },
3354 { "menuOptions.Get Move List", False },
3355 { "menuOptions.ICS Alarm", False },
3356 { "menuOptions.Move Sound", False },
3357 { "menuOptions.Quiet Play", False },
3358 { "menuOptions.Hide Thinking", False },
3359 { "menuOptions.Periodic Updates", False },
3360 { "menuOptions.Ponder Next Move", False },
3361 { "menuHelp.Hint", False },
3362 { "menuHelp.Book", False },
3366 Enables gnuEnables[] = {
3367 { "menuMode.ICS Client", False },
3368 { "menuMode.ICS Input Box", False },
3369 { "menuAction.Accept", False },
3370 { "menuAction.Decline", False },
3371 { "menuAction.Rematch", False },
3372 { "menuAction.Adjourn", False },
3373 { "menuAction.Stop Examining", False },
3374 { "menuAction.Stop Observing", False },
3375 { "menuStep.Revert", False },
3376 { "menuOptions.Auto Comment", False },
3377 { "menuOptions.Auto Observe", False },
3378 { "menuOptions.Auto Raise Board", False },
3379 { "menuOptions.Get Move List", False },
3380 { "menuOptions.Premove", False },
3381 { "menuOptions.Quiet Play", False },
3383 /* The next two options rely on SetCmailMode being called *after* */
3384 /* SetGNUMode so that when GNU is being used to give hints these */
3385 /* menu options are still available */
3387 { "menuFile.Mail Move", False },
3388 { "menuFile.Reload CMail Message", False },
3392 Enables cmailEnables[] = {
3394 { "menuAction.Call Flag", False },
3395 { "menuAction.Draw", True },
3396 { "menuAction.Adjourn", False },
3397 { "menuAction.Abort", False },
3398 { "menuAction.Stop Observing", False },
3399 { "menuAction.Stop Examining", False },
3400 { "menuFile.Mail Move", True },
3401 { "menuFile.Reload CMail Message", True },
3405 Enables trainingOnEnables[] = {
3406 { "menuMode.Edit Comment", False },
3407 { "menuMode.Pause", False },
3408 { "menuStep.Forward", False },
3409 { "menuStep.Backward", False },
3410 { "menuStep.Forward to End", False },
3411 { "menuStep.Back to Start", False },
3412 { "menuStep.Move Now", False },
3413 { "menuStep.Truncate Game", False },
3417 Enables trainingOffEnables[] = {
3418 { "menuMode.Edit Comment", True },
3419 { "menuMode.Pause", True },
3420 { "menuStep.Forward", True },
3421 { "menuStep.Backward", True },
3422 { "menuStep.Forward to End", True },
3423 { "menuStep.Back to Start", True },
3424 { "menuStep.Move Now", True },
3425 { "menuStep.Truncate Game", True },
3429 Enables machineThinkingEnables[] = {
3430 { "menuFile.Load Game", False },
3431 { "menuFile.Load Next Game", False },
3432 { "menuFile.Load Previous Game", False },
3433 { "menuFile.Reload Same Game", False },
3434 { "menuFile.Paste Game", False },
3435 { "menuFile.Load Position", False },
3436 { "menuFile.Load Next Position", False },
3437 { "menuFile.Load Previous Position", False },
3438 { "menuFile.Reload Same Position", False },
3439 { "menuFile.Paste Position", False },
3440 { "menuMode.Machine White", False },
3441 { "menuMode.Machine Black", False },
3442 { "menuMode.Two Machines", False },
3443 { "menuStep.Retract Move", False },
3447 Enables userThinkingEnables[] = {
3448 { "menuFile.Load Game", True },
3449 { "menuFile.Load Next Game", True },
3450 { "menuFile.Load Previous Game", True },
3451 { "menuFile.Reload Same Game", True },
3452 { "menuFile.Paste Game", True },
3453 { "menuFile.Load Position", True },
3454 { "menuFile.Load Next Position", True },
3455 { "menuFile.Load Previous Position", True },
3456 { "menuFile.Reload Same Position", True },
3457 { "menuFile.Paste Position", True },
3458 { "menuMode.Machine White", True },
3459 { "menuMode.Machine Black", True },
3460 { "menuMode.Two Machines", True },
3461 { "menuStep.Retract Move", True },
3467 SetMenuEnables(icsEnables);
3470 if (appData.zippyPlay && !appData.noChessProgram) /* [DM] icsEngineAnalyze */
3471 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Analysis Mode"), True);
3478 SetMenuEnables(ncpEnables);
3484 SetMenuEnables(gnuEnables);
3490 SetMenuEnables(cmailEnables);
3496 SetMenuEnables(trainingOnEnables);
3497 if (appData.showButtonBar) {
3498 XtSetSensitive(buttonBarWidget, False);
3504 SetTrainingModeOff()
3506 SetMenuEnables(trainingOffEnables);
3507 if (appData.showButtonBar) {
3508 XtSetSensitive(buttonBarWidget, True);
3513 SetUserThinkingEnables()
3515 if (appData.noChessProgram) return;
3516 SetMenuEnables(userThinkingEnables);
3520 SetMachineThinkingEnables()
3522 if (appData.noChessProgram) return;
3523 SetMenuEnables(machineThinkingEnables);
3525 case MachinePlaysBlack:
3526 case MachinePlaysWhite:
3527 case TwoMachinesPlay:
3528 XtSetSensitive(XtNameToWidget(menuBarWidget,
3529 ModeToWidgetName(gameMode)), True);
3536 #define Abs(n) ((n)<0 ? -(n) : (n))
3539 * Find a font that matches "pattern" that is as close as
3540 * possible to the targetPxlSize. Prefer fonts that are k
3541 * pixels smaller to fonts that are k pixels larger. The
3542 * pattern must be in the X Consortium standard format,
3543 * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".
3544 * The return value should be freed with XtFree when no
3547 char *FindFont(pattern, targetPxlSize)
3551 char **fonts, *p, *best, *scalable, *scalableTail;
3552 int i, j, nfonts, minerr, err, pxlSize;
3555 char **missing_list;
3557 char *def_string, *base_fnt_lst, strInt[3];
3559 XFontStruct **fnt_list;
3561 base_fnt_lst = calloc(1, strlen(pattern) + 3);
3562 sprintf(strInt, "%d", targetPxlSize);
3563 p = strstr(pattern, "--");
3564 strncpy(base_fnt_lst, pattern, p - pattern + 2);
3565 strcat(base_fnt_lst, strInt);
3566 strcat(base_fnt_lst, strchr(p + 2, '-'));
3568 if ((fntSet = XCreateFontSet(xDisplay,
3572 &def_string)) == NULL) {
3574 fprintf(stderr, _("Unable to create font set.\n"));
3578 nfonts = XFontsOfFontSet(fntSet, &fnt_list, &fonts);
3580 fonts = XListFonts(xDisplay, pattern, 999999, &nfonts);
3582 fprintf(stderr, _("%s: no fonts match pattern %s\n"),
3583 programName, pattern);
3591 for (i=0; i<nfonts; i++) {
3594 if (*p != '-') continue;
3596 if (*p == NULLCHAR) break;
3597 if (*p++ == '-') j++;
3599 if (j < 7) continue;
3602 scalable = fonts[i];
3605 err = pxlSize - targetPxlSize;
3606 if (Abs(err) < Abs(minerr) ||
3607 (minerr > 0 && err < 0 && -err == minerr)) {
3613 if (scalable && Abs(minerr) > appData.fontSizeTolerance) {
3614 /* If the error is too big and there is a scalable font,
3615 use the scalable font. */
3616 int headlen = scalableTail - scalable;
3617 p = (char *) XtMalloc(strlen(scalable) + 10);
3618 while (isdigit(*scalableTail)) scalableTail++;
3619 sprintf(p, "%.*s%d%s", headlen, scalable, targetPxlSize, scalableTail);
3621 p = (char *) XtMalloc(strlen(best) + 1);
3624 if (appData.debugMode) {
3625 fprintf(debugFP, _("resolved %s at pixel size %d\n to %s\n"),
3626 pattern, targetPxlSize, p);
3629 if (missing_count > 0)
3630 XFreeStringList(missing_list);
3631 XFreeFontSet(xDisplay, fntSet);
3633 XFreeFontNames(fonts);
3640 XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
3641 | GCBackground | GCFunction | GCPlaneMask;
3642 XGCValues gc_values;
3645 gc_values.plane_mask = AllPlanes;
3646 gc_values.line_width = lineGap;
3647 gc_values.line_style = LineSolid;
3648 gc_values.function = GXcopy;
3650 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3651 gc_values.background = XBlackPixel(xDisplay, xScreen);
3652 lineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3654 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3655 gc_values.background = XWhitePixel(xDisplay, xScreen);
3656 coordGC = XtGetGC(shellWidget, value_mask, &gc_values);
3657 XSetFont(xDisplay, coordGC, coordFontID);
3659 // [HGM] make font for holdings counts (white on black0
3660 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3661 gc_values.background = XBlackPixel(xDisplay, xScreen);
3662 countGC = XtGetGC(shellWidget, value_mask, &gc_values);
3663 XSetFont(xDisplay, countGC, countFontID);
3665 if (appData.monoMode) {
3666 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3667 gc_values.background = XWhitePixel(xDisplay, xScreen);
3668 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3670 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3671 gc_values.background = XBlackPixel(xDisplay, xScreen);
3672 lightSquareGC = wbPieceGC
3673 = XtGetGC(shellWidget, value_mask, &gc_values);
3675 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3676 gc_values.background = XWhitePixel(xDisplay, xScreen);
3677 darkSquareGC = bwPieceGC
3678 = XtGetGC(shellWidget, value_mask, &gc_values);
3680 if (DefaultDepth(xDisplay, xScreen) == 1) {
3681 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
3682 gc_values.function = GXcopyInverted;
3683 copyInvertedGC = XtGetGC(shellWidget, value_mask, &gc_values);
3684 gc_values.function = GXcopy;
3685 if (XBlackPixel(xDisplay, xScreen) == 1) {
3686 bwPieceGC = darkSquareGC;
3687 wbPieceGC = copyInvertedGC;
3689 bwPieceGC = copyInvertedGC;
3690 wbPieceGC = lightSquareGC;
3694 gc_values.foreground = highlightSquareColor;
3695 gc_values.background = highlightSquareColor;
3696 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3698 gc_values.foreground = premoveHighlightColor;
3699 gc_values.background = premoveHighlightColor;
3700 prelineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3702 gc_values.foreground = lightSquareColor;
3703 gc_values.background = darkSquareColor;
3704 lightSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3706 gc_values.foreground = darkSquareColor;
3707 gc_values.background = lightSquareColor;
3708 darkSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3710 gc_values.foreground = jailSquareColor;
3711 gc_values.background = jailSquareColor;
3712 jailSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3714 gc_values.foreground = whitePieceColor;
3715 gc_values.background = darkSquareColor;
3716 wdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3718 gc_values.foreground = whitePieceColor;
3719 gc_values.background = lightSquareColor;
3720 wlPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3722 gc_values.foreground = whitePieceColor;
3723 gc_values.background = jailSquareColor;
3724 wjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3726 gc_values.foreground = blackPieceColor;
3727 gc_values.background = darkSquareColor;
3728 bdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3730 gc_values.foreground = blackPieceColor;
3731 gc_values.background = lightSquareColor;
3732 blPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3734 gc_values.foreground = blackPieceColor;
3735 gc_values.background = jailSquareColor;
3736 bjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3740 void loadXIM(xim, xmask, filename, dest, mask)
3753 fp = fopen(filename, "rb");
3755 fprintf(stderr, _("%s: error loading XIM!\n"), programName);
3762 for (y=0; y<h; ++y) {
3763 for (x=0; x<h; ++x) {
3768 XPutPixel(xim, x, y, blackPieceColor);
3770 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3773 XPutPixel(xim, x, y, darkSquareColor);
3775 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3778 XPutPixel(xim, x, y, whitePieceColor);
3780 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3783 XPutPixel(xim, x, y, lightSquareColor);
3785 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3791 /* create Pixmap of piece */
3792 *dest = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3794 XPutImage(xDisplay, *dest, lightSquareGC, xim,
3797 /* create Pixmap of clipmask
3798 Note: We assume the white/black pieces have the same
3799 outline, so we make only 6 masks. This is okay
3800 since the XPM clipmask routines do the same. */
3802 temp = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3804 XPutImage(xDisplay, temp, lightSquareGC, xmask,
3807 /* now create the 1-bit version */
3808 *mask = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3811 values.foreground = 1;
3812 values.background = 0;
3814 /* Don't use XtGetGC, not read only */
3815 maskGC = XCreateGC(xDisplay, *mask,
3816 GCForeground | GCBackground, &values);
3817 XCopyPlane(xDisplay, temp, *mask, maskGC,
3818 0, 0, squareSize, squareSize, 0, 0, 1);
3819 XFreePixmap(xDisplay, temp);
3824 char pieceBitmapNames[] = "pnbrqfeacwmohijgdvlsukpnsl";
3826 void CreateXIMPieces()
3831 static char *ximkind[] = { "ll", "ld", "dl", "dd" };
3836 /* The XSynchronize calls were copied from CreatePieces.
3837 Not sure if needed, but can't hurt */
3838 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3841 /* temp needed by loadXIM() */
3842 ximtemp = XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3843 0, 0, ss, ss, AllPlanes, XYPixmap);
3845 if (strlen(appData.pixmapDirectory) == 0) {
3849 if (appData.monoMode) {
3850 DisplayFatalError(_("XIM pieces cannot be used in monochrome mode"),
3854 fprintf(stderr, _("\nLoading XIMs...\n"));
3856 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3857 fprintf(stderr, "%d", piece+1);
3858 for (kind=0; kind<4; kind++) {
3859 fprintf(stderr, ".");
3860 snprintf(buf, sizeof(buf), "%s/%s%c%s%u.xim",
3861 ExpandPathName(appData.pixmapDirectory),
3862 piece <= (int) WhiteKing ? "" : "w",
3863 pieceBitmapNames[piece],
3865 ximPieceBitmap[kind][piece] =
3866 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3867 0, 0, ss, ss, AllPlanes, XYPixmap);
3868 if (appData.debugMode)
3869 fprintf(stderr, _("(File:%s:) "), buf);
3870 loadXIM(ximPieceBitmap[kind][piece],
3872 &(xpmPieceBitmap2[kind][piece]),
3873 &(ximMaskPm2[piece]));
3874 if(piece <= (int)WhiteKing)
3875 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3877 fprintf(stderr," ");
3879 /* Load light and dark squares */
3880 /* If the LSQ and DSQ pieces don't exist, we will
3881 draw them with solid squares. */
3882 snprintf(buf,sizeof(buf), "%s/lsq%u.xim", ExpandPathName(appData.pixmapDirectory), ss);
3883 if (access(buf, 0) != 0) {
3887 fprintf(stderr, _("light square "));
3889 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3890 0, 0, ss, ss, AllPlanes, XYPixmap);
3891 if (appData.debugMode)
3892 fprintf(stderr, _("(File:%s:) "), buf);
3894 loadXIM(ximLightSquare, NULL, buf, &xpmLightSquare, NULL);
3895 fprintf(stderr, _("dark square "));
3896 snprintf(buf,sizeof(buf), "%s/dsq%u.xim",
3897 ExpandPathName(appData.pixmapDirectory), ss);
3898 if (appData.debugMode)
3899 fprintf(stderr, _("(File:%s:) "), buf);
3901 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3902 0, 0, ss, ss, AllPlanes, XYPixmap);
3903 loadXIM(ximDarkSquare, NULL, buf, &xpmDarkSquare, NULL);
3904 xpmJailSquare = xpmLightSquare;
3906 fprintf(stderr, _("Done.\n"));
3908 XSynchronize(xDisplay, False); /* Work-around for xlib/xt buffering bug */
3912 void CreateXPMPieces()
3916 u_int ss = squareSize;
3918 static char *xpmkind[] = { "ll", "ld", "dl", "dd" };
3919 XpmColorSymbol symbols[4];
3922 /* Apparently some versions of Xpm don't define XpmFormat at all --tpm */
3923 if (appData.debugMode) {
3924 fprintf(stderr, "XPM Library Version: %d.%d%c\n",
3925 XpmFormat, XpmVersion, (char)('a' + XpmRevision - 1));
3929 /* The XSynchronize calls were copied from CreatePieces.
3930 Not sure if needed, but can't hurt */
3931 XSynchronize(xDisplay, True); /* Work-around for xlib/xt buffering bug */
3933 /* Setup translations so piece colors match square colors */
3934 symbols[0].name = "light_piece";
3935 symbols[0].value = appData.whitePieceColor;
3936 symbols[1].name = "dark_piece";
3937 symbols[1].value = appData.blackPieceColor;
3938 symbols[2].name = "light_square";
3939 symbols[2].value = appData.lightSquareColor;
3940 symbols[3].name = "dark_square";
3941 symbols[3].value = appData.darkSquareColor;
3943 attr.valuemask = XpmColorSymbols;
3944 attr.colorsymbols = symbols;
3945 attr.numsymbols = 4;
3947 if (appData.monoMode) {
3948 DisplayFatalError(_("XPM pieces cannot be used in monochrome mode"),
3952 if (strlen(appData.pixmapDirectory) == 0) {
3953 XpmPieces* pieces = builtInXpms;
3956 while (pieces->size != squareSize && pieces->size) pieces++;
3957 if (!pieces->size) {
3958 fprintf(stderr, _("No builtin XPM pieces of size %d\n"), squareSize);
3961 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3962 for (kind=0; kind<4; kind++) {
3964 if ((r=XpmCreatePixmapFromData(xDisplay, xBoardWindow,
3965 pieces->xpm[piece][kind],
3966 &(xpmPieceBitmap2[kind][piece]),
3967 NULL, &attr)) != 0) {
3968 fprintf(stderr, _("Error %d loading XPM image \"%s\"\n"),
3972 if(piece <= (int) WhiteKing)
3973 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3977 xpmJailSquare = xpmLightSquare;
3981 fprintf(stderr, _("\nLoading XPMs...\n"));
3984 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3985 fprintf(stderr, "%d ", piece+1);
3986 for (kind=0; kind<4; kind++) {
3987 snprintf(buf, sizeof(buf), "%s/%s%c%s%u.xpm",
3988 ExpandPathName(appData.pixmapDirectory),
3989 piece > (int) WhiteKing ? "w" : "",
3990 pieceBitmapNames[piece],
3992 if (appData.debugMode) {
3993 fprintf(stderr, _("(File:%s:) "), buf);
3995 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3996 &(xpmPieceBitmap2[kind][piece]),
3997 NULL, &attr)) != 0) {
3998 if(piece != (int)WhiteKing && piece > (int)WhiteQueen) {
3999 // [HGM] missing: read of unorthodox piece failed; substitute King.
4000 snprintf(buf, sizeof(buf), "%s/k%s%u.xpm",
4001 ExpandPathName(appData.pixmapDirectory),
4003 if (appData.debugMode) {
4004 fprintf(stderr, _("(Replace by File:%s:) "), buf);
4006 r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
4007 &(xpmPieceBitmap2[kind][piece]),
4011 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"),
4016 if(piece <= (int) WhiteKing)
4017 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
4020 /* Load light and dark squares */
4021 /* If the LSQ and DSQ pieces don't exist, we will
4022 draw them with solid squares. */
4023 fprintf(stderr, _("light square "));
4024 snprintf(buf, sizeof(buf), "%s/lsq%u.xpm", ExpandPathName(appData.pixmapDirectory), ss);
4025 if (access(buf, 0) != 0) {
4029 if (appData.debugMode)
4030 fprintf(stderr, _("(File:%s:) "), buf);
4032 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
4033 &xpmLightSquare, NULL, &attr)) != 0) {
4034 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
4037 fprintf(stderr, _("dark square "));
4038 snprintf(buf, sizeof(buf), "%s/dsq%u.xpm",
4039 ExpandPathName(appData.pixmapDirectory), ss);
4040 if (appData.debugMode) {
4041 fprintf(stderr, _("(File:%s:) "), buf);
4043 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
4044 &xpmDarkSquare, NULL, &attr)) != 0) {
4045 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
4049 xpmJailSquare = xpmLightSquare;
4050 fprintf(stderr, _("Done.\n"));
4052 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
4055 #endif /* HAVE_LIBXPM */
4058 /* No built-in bitmaps */
4063 u_int ss = squareSize;
4065 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
4068 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
4069 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
4070 sprintf(buf, "%s%c%u%c.bm", piece > (int)WhiteKing ? "w" : "",
4071 pieceBitmapNames[piece],
4072 ss, kind == SOLID ? 's' : 'o');
4073 ReadBitmap(&pieceBitmap2[kind][piece], buf, NULL, ss, ss);
4074 if(piece <= (int)WhiteKing)
4075 pieceBitmap[kind][piece] = pieceBitmap2[kind][piece];
4079 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
4083 /* With built-in bitmaps */
4086 BuiltInBits* bib = builtInBits;
4089 u_int ss = squareSize;
4091 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
4094 while (bib->squareSize != ss && bib->squareSize != 0) bib++;
4096 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
4097 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
4098 sprintf(buf, "%s%c%u%c.bm", piece > (int)WhiteKing ? "w" : "",
4099 pieceBitmapNames[piece],
4100 ss, kind == SOLID ? 's' : 'o');
4101 ReadBitmap(&pieceBitmap2[kind][piece], buf,
4102 bib->bits[kind][piece], ss, ss);
4103 if(piece <= (int)WhiteKing)
4104 pieceBitmap[kind][piece] = pieceBitmap2[kind][piece];
4108 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
4113 void ReadBitmap(pm, name, bits, wreq, hreq)
4116 unsigned char bits[];
4122 char msg[MSG_SIZ], fullname[MSG_SIZ];
4124 if (*appData.bitmapDirectory != NULLCHAR) {
4125 strcpy(fullname, appData.bitmapDirectory);
4126 strcat(fullname, "/");
4127 strcat(fullname, name);
4128 errcode = XReadBitmapFile(xDisplay, xBoardWindow, fullname,
4129 &w, &h, pm, &x_hot, &y_hot);
4130 fprintf(stderr, "load %s\n", name);
4131 if (errcode != BitmapSuccess) {
4133 case BitmapOpenFailed:
4134 snprintf(msg, sizeof(msg), _("Can't open bitmap file %s"), fullname);
4136 case BitmapFileInvalid:
4137 snprintf(msg, sizeof(msg), _("Invalid bitmap in file %s"), fullname);
4139 case BitmapNoMemory:
4140 snprintf(msg, sizeof(msg), _("Ran out of memory reading bitmap file %s"),
4144 snprintf(msg, sizeof(msg), _("Unknown XReadBitmapFile error %d on file %s"),
4148 fprintf(stderr, _("%s: %s...using built-in\n"),
4150 } else if (w != wreq || h != hreq) {
4152 _("%s: Bitmap %s is %dx%d, not %dx%d...using built-in\n"),
4153 programName, fullname, w, h, wreq, hreq);
4160 fprintf(stderr, _("%s: No built-in bitmap for %s; giving up\n"),
4164 ; // [HGM] bitmaps: make it non-fatal if we have no bitmap;
4166 *pm = XCreateBitmapFromData(xDisplay, xBoardWindow, (char *) bits,
4175 if (lineGap == 0) return;
4177 /* [HR] Split this into 2 loops for non-square boards. */
4179 for (i = 0; i < BOARD_HEIGHT + 1; i++) {
4180 gridSegments[i].x1 = 0;
4181 gridSegments[i].x2 =
4182 lineGap + BOARD_WIDTH * (squareSize + lineGap);
4183 gridSegments[i].y1 = gridSegments[i].y2
4184 = lineGap / 2 + (i * (squareSize + lineGap));
4187 for (j = 0; j < BOARD_WIDTH + 1; j++) {
4188 gridSegments[j + i].y1 = 0;
4189 gridSegments[j + i].y2 =
4190 lineGap + BOARD_HEIGHT * (squareSize + lineGap);
4191 gridSegments[j + i].x1 = gridSegments[j + i].x2
4192 = lineGap / 2 + (j * (squareSize + lineGap));
4196 static void MenuBarSelect(w, addr, index)
4201 XtActionProc proc = (XtActionProc) addr;
4203 (proc)(NULL, NULL, NULL, NULL);
4206 void CreateMenuBarPopup(parent, name, mb)
4216 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
4219 XtSetArg(args[j], XtNleftMargin, 20); j++;
4220 XtSetArg(args[j], XtNrightMargin, 20); j++;
4222 while (mi->string != NULL) {
4223 if (strcmp(mi->string, "----") == 0) {
4224 entry = XtCreateManagedWidget(mi->string, smeLineObjectClass,
4227 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string)));
4228 entry = XtCreateManagedWidget(mi->string, smeBSBObjectClass,
4230 XtAddCallback(entry, XtNcallback,
4231 (XtCallbackProc) MenuBarSelect,
4232 (caddr_t) mi->proc);
4238 Widget CreateMenuBar(mb)
4242 Widget anchor, menuBar;
4244 char menuName[MSG_SIZ];
4247 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
4248 XtSetArg(args[j], XtNvSpace, 0); j++;
4249 XtSetArg(args[j], XtNborderWidth, 0); j++;
4250 menuBar = XtCreateWidget("menuBar", boxWidgetClass,
4251 formWidget, args, j);
4253 while (mb->name != NULL) {
4254 strcpy(menuName, "menu");
4255 strcat(menuName, mb->name);
4257 XtSetArg(args[j], XtNmenuName, XtNewString(menuName)); j++;
4260 shortName[0] = _(mb->name)[0];
4261 shortName[1] = NULLCHAR;
4262 XtSetArg(args[j], XtNlabel, XtNewString(shortName)); j++;
4265 XtSetArg(args[j], XtNlabel, XtNewString(_(mb->name))); j++;
4268 XtSetArg(args[j], XtNborderWidth, 0); j++;
4269 anchor = XtCreateManagedWidget(mb->name, menuButtonWidgetClass,
4271 CreateMenuBarPopup(menuBar, menuName, mb);
4277 Widget CreateButtonBar(mi)
4281 Widget button, buttonBar;
4285 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
4287 XtSetArg(args[j], XtNhSpace, 0); j++;
4289 XtSetArg(args[j], XtNborderWidth, 0); j++;
4290 XtSetArg(args[j], XtNvSpace, 0); j++;
4291 buttonBar = XtCreateWidget("buttonBar", boxWidgetClass,
4292 formWidget, args, j);
4294 while (mi->string != NULL) {
4297 XtSetArg(args[j], XtNinternalWidth, 2); j++;
4298 XtSetArg(args[j], XtNborderWidth, 0); j++;
4300 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string))); j++;
4301 button = XtCreateManagedWidget(mi->string, commandWidgetClass,
4302 buttonBar, args, j);
4303 XtAddCallback(button, XtNcallback,
4304 (XtCallbackProc) MenuBarSelect,
4305 (caddr_t) mi->proc);
4312 CreatePieceMenu(name, color)
4319 ChessSquare selection;
4321 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
4322 boardWidget, args, 0);
4324 for (i = 0; i < PIECE_MENU_SIZE; i++) {
4325 String item = pieceMenuStrings[color][i];
4327 if (strcmp(item, "----") == 0) {
4328 entry = XtCreateManagedWidget(item, smeLineObjectClass,
4331 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
4332 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
4334 selection = pieceMenuTranslation[color][i];
4335 XtAddCallback(entry, XtNcallback,
4336 (XtCallbackProc) PieceMenuSelect,
4337 (caddr_t) selection);
4338 if (selection == WhitePawn || selection == BlackPawn) {
4339 XtSetArg(args[0], XtNpopupOnEntry, entry);
4340 XtSetValues(menu, args, 1);
4353 ChessSquare selection;
4355 whitePieceMenu = CreatePieceMenu("menuW", 0);
4356 blackPieceMenu = CreatePieceMenu("menuB", 1);
4358 XtRegisterGrabAction(PieceMenuPopup, True,
4359 (unsigned)(ButtonPressMask|ButtonReleaseMask),
4360 GrabModeAsync, GrabModeAsync);
4362 XtSetArg(args[0], XtNlabel, _("Drop"));
4363 dropMenu = XtCreatePopupShell("menuD", simpleMenuWidgetClass,
4364 boardWidget, args, 1);
4365 for (i = 0; i < DROP_MENU_SIZE; i++) {
4366 String item = dropMenuStrings[i];
4368 if (strcmp(item, "----") == 0) {
4369 entry = XtCreateManagedWidget(item, smeLineObjectClass,
4372 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
4373 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
4375 selection = dropMenuTranslation[i];
4376 XtAddCallback(entry, XtNcallback,
4377 (XtCallbackProc) DropMenuSelect,
4378 (caddr_t) selection);
4383 void SetupDropMenu()
4391 for (i=0; i<sizeof(dmEnables)/sizeof(DropMenuEnables); i++) {
4392 entry = XtNameToWidget(dropMenu, dmEnables[i].widget);
4393 p = strchr(gameMode == IcsPlayingWhite ? white_holding : black_holding,
4394 dmEnables[i].piece);
4395 XtSetSensitive(entry, p != NULL || !appData.testLegality
4396 /*!!temp:*/ || (gameInfo.variant == VariantCrazyhouse
4397 && !appData.icsActive));
4399 while (p && *p++ == dmEnables[i].piece) count++;
4400 snprintf(label, sizeof(label), "%s %d", dmEnables[i].widget, count);
4402 XtSetArg(args[j], XtNlabel, label); j++;
4403 XtSetValues(entry, args, j);
4407 void PieceMenuPopup(w, event, params, num_params)
4411 Cardinal *num_params;
4414 if (event->type != ButtonPress) return;
4415 if (errorUp) ErrorPopDown();
4419 whichMenu = params[0];
4421 case IcsPlayingWhite:
4422 case IcsPlayingBlack:
4424 case MachinePlaysWhite:
4425 case MachinePlaysBlack:
4426 if (appData.testLegality &&
4427 gameInfo.variant != VariantBughouse &&
4428 gameInfo.variant != VariantCrazyhouse) return;
4430 whichMenu = "menuD";
4436 if (((pmFromX = EventToSquare(event->xbutton.x, BOARD_WIDTH)) < 0) ||
4437 ((pmFromY = EventToSquare(event->xbutton.y, BOARD_HEIGHT)) < 0)) {
4438 pmFromX = pmFromY = -1;
4442 pmFromX = BOARD_WIDTH - 1 - pmFromX;
4444 pmFromY = BOARD_HEIGHT - 1 - pmFromY;
4446 XtPopupSpringLoaded(XtNameToWidget(boardWidget, whichMenu));
4449 static void PieceMenuSelect(w, piece, junk)
4454 if (pmFromX < 0 || pmFromY < 0) return;
4455 EditPositionMenuEvent(piece, pmFromX, pmFromY);
4458 static void DropMenuSelect(w, piece, junk)
4463 if (pmFromX < 0 || pmFromY < 0) return;
4464 DropMenuEvent(piece, pmFromX, pmFromY);
4467 void WhiteClock(w, event, prms, nprms)
4473 if (gameMode == EditPosition || gameMode == IcsExamining) {
4474 SetWhiteToPlayEvent();
4475 } else if (gameMode == IcsPlayingBlack || gameMode == MachinePlaysWhite) {
4480 void BlackClock(w, event, prms, nprms)
4486 if (gameMode == EditPosition || gameMode == IcsExamining) {
4487 SetBlackToPlayEvent();
4488 } else if (gameMode == IcsPlayingWhite || gameMode == MachinePlaysBlack) {
4495 * If the user selects on a border boundary, return -1; if off the board,
4496 * return -2. Otherwise map the event coordinate to the square.
4498 int EventToSquare(x, limit)
4506 if ((x % (squareSize + lineGap)) >= squareSize)
4508 x /= (squareSize + lineGap);
4514 static void do_flash_delay(msec)
4520 static void drawHighlight(file, rank, gc)
4526 if (lineGap == 0 || appData.blindfold) return;
4529 x = lineGap/2 + ((BOARD_WIDTH-1)-file) *
4530 (squareSize + lineGap);
4531 y = lineGap/2 + rank * (squareSize + lineGap);
4533 x = lineGap/2 + file * (squareSize + lineGap);
4534 y = lineGap/2 + ((BOARD_HEIGHT-1)-rank) *
4535 (squareSize + lineGap);
4538 XDrawRectangle(xDisplay, xBoardWindow, gc, x, y,
4539 squareSize+lineGap, squareSize+lineGap);
4542 int hi1X = -1, hi1Y = -1, hi2X = -1, hi2Y = -1;
4543 int pm1X = -1, pm1Y = -1, pm2X = -1, pm2Y = -1;
4546 SetHighlights(fromX, fromY, toX, toY)
4547 int fromX, fromY, toX, toY;
4549 if (hi1X != fromX || hi1Y != fromY) {
4550 if (hi1X >= 0 && hi1Y >= 0) {
4551 drawHighlight(hi1X, hi1Y, lineGC);
4553 if (fromX >= 0 && fromY >= 0) {
4554 drawHighlight(fromX, fromY, highlineGC);
4557 if (hi2X != toX || hi2Y != toY) {
4558 if (hi2X >= 0 && hi2Y >= 0) {
4559 drawHighlight(hi2X, hi2Y, lineGC);
4561 if (toX >= 0 && toY >= 0) {
4562 drawHighlight(toX, toY, highlineGC);
4574 SetHighlights(-1, -1, -1, -1);
4579 SetPremoveHighlights(fromX, fromY, toX, toY)
4580 int fromX, fromY, toX, toY;
4582 if (pm1X != fromX || pm1Y != fromY) {
4583 if (pm1X >= 0 && pm1Y >= 0) {
4584 drawHighlight(pm1X, pm1Y, lineGC);
4586 if (fromX >= 0 && fromY >= 0) {
4587 drawHighlight(fromX, fromY, prelineGC);
4590 if (pm2X != toX || pm2Y != toY) {
4591 if (pm2X >= 0 && pm2Y >= 0) {
4592 drawHighlight(pm2X, pm2Y, lineGC);
4594 if (toX >= 0 && toY >= 0) {
4595 drawHighlight(toX, toY, prelineGC);
4605 ClearPremoveHighlights()
4607 SetPremoveHighlights(-1, -1, -1, -1);
4610 static void BlankSquare(x, y, color, piece, dest)
4615 if (useImages && useImageSqs) {
4619 pm = xpmLightSquare;
4624 case 2: /* neutral */
4629 XCopyArea(xDisplay, pm, dest, wlPieceGC, 0, 0,
4630 squareSize, squareSize, x, y);
4640 case 2: /* neutral */
4645 XFillRectangle(xDisplay, dest, gc, x, y, squareSize, squareSize);
4650 I split out the routines to draw a piece so that I could
4651 make a generic flash routine.
4653 static void monoDrawPiece_1bit(piece, square_color, x, y, dest)
4655 int square_color, x, y;
4658 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
4659 switch (square_color) {
4661 case 2: /* neutral */
4663 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
4664 ? *pieceToOutline(piece)
4665 : *pieceToSolid(piece),
4666 dest, bwPieceGC, 0, 0,
4667 squareSize, squareSize, x, y);
4670 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
4671 ? *pieceToSolid(piece)
4672 : *pieceToOutline(piece),
4673 dest, wbPieceGC, 0, 0,
4674 squareSize, squareSize, x, y);
4679 static void monoDrawPiece(piece, square_color, x, y, dest)
4681 int square_color, x, y;
4684 switch (square_color) {
4686 case 2: /* neutral */
4688 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
4689 ? *pieceToOutline(piece)
4690 : *pieceToSolid(piece),
4691 dest, bwPieceGC, 0, 0,
4692 squareSize, squareSize, x, y, 1);
4695 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
4696 ? *pieceToSolid(piece)
4697 : *pieceToOutline(piece),
4698 dest, wbPieceGC, 0, 0,
4699 squareSize, squareSize, x, y, 1);
4704 static void colorDrawPiece(piece, square_color, x, y, dest)
4706 int square_color, x, y;
4709 if(pieceToSolid(piece) == NULL) return; // [HGM] bitmaps: make it non-fatal if we have no bitmap;
4710 switch (square_color) {
4712 XCopyPlane(xDisplay, *pieceToSolid(piece),
4713 dest, (int) piece < (int) BlackPawn
4714 ? wlPieceGC : blPieceGC, 0, 0,
4715 squareSize, squareSize, x, y, 1);
4718 XCopyPlane(xDisplay, *pieceToSolid(piece),
4719 dest, (int) piece < (int) BlackPawn
4720 ? wdPieceGC : bdPieceGC, 0, 0,
4721 squareSize, squareSize, x, y, 1);
4723 case 2: /* neutral */
4725 XCopyPlane(xDisplay, *pieceToSolid(piece),
4726 dest, (int) piece < (int) BlackPawn
4727 ? wjPieceGC : bjPieceGC, 0, 0,
4728 squareSize, squareSize, x, y, 1);
4733 static void colorDrawPieceImage(piece, square_color, x, y, dest)
4735 int square_color, x, y;
4740 switch (square_color) {
4742 case 2: /* neutral */
4744 if ((int)piece < (int) BlackPawn) {
4752 if ((int)piece < (int) BlackPawn) {
4760 XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
4761 dest, wlPieceGC, 0, 0,
4762 squareSize, squareSize, x, y);
4765 typedef void (*DrawFunc)();
4767 DrawFunc ChooseDrawFunc()
4769 if (appData.monoMode) {
4770 if (DefaultDepth(xDisplay, xScreen) == 1) {
4771 return monoDrawPiece_1bit;
4773 return monoDrawPiece;
4777 return colorDrawPieceImage;
4779 return colorDrawPiece;
4783 /* [HR] determine square color depending on chess variant. */
4784 static int SquareColor(row, column)
4789 if (gameInfo.variant == VariantXiangqi) {
4790 if (column >= 3 && column <= 5 && row >= 0 && row <= 2) {
4792 } else if (column >= 3 && column <= 5 && row >= 7 && row <= 9) {
4794 } else if (row <= 4) {
4800 square_color = ((column + row) % 2) == 1;
4803 /* [hgm] holdings: next line makes all holdings squares light */
4804 if(column < BOARD_LEFT || column >= BOARD_RGHT) square_color = 1;
4806 return square_color;
4809 void DrawSquare(row, column, piece, do_flash)
4810 int row, column, do_flash;
4813 int square_color, x, y, direction, font_ascent, font_descent;
4816 XCharStruct overall;
4820 /* Calculate delay in milliseconds (2-delays per complete flash) */
4821 flash_delay = 500 / appData.flashRate;
4824 x = lineGap + ((BOARD_WIDTH-1)-column) *
4825 (squareSize + lineGap);
4826 y = lineGap + row * (squareSize + lineGap);
4828 x = lineGap + column * (squareSize + lineGap);
4829 y = lineGap + ((BOARD_HEIGHT-1)-row) *
4830 (squareSize + lineGap);
4833 square_color = SquareColor(row, column);
4835 if ( // [HGM] holdings: blank out area between board and holdings
4836 column == BOARD_LEFT-1 || column == BOARD_RGHT
4837 || (column == BOARD_LEFT-2 && row < BOARD_HEIGHT-gameInfo.holdingsSize)
4838 || (column == BOARD_RGHT+1 && row >= gameInfo.holdingsSize) ) {
4839 BlankSquare(x, y, 2, EmptySquare, xBoardWindow);
4841 // [HGM] print piece counts next to holdings
4842 string[1] = NULLCHAR;
4843 if (column == (flipView ? BOARD_LEFT-1 : BOARD_RGHT) && piece > 1 ) {
4844 string[0] = '0' + piece;
4845 XTextExtents(countFontStruct, string, 1, &direction,
4846 &font_ascent, &font_descent, &overall);
4847 if (appData.monoMode) {
4848 XDrawImageString(xDisplay, xBoardWindow, countGC,
4849 x + squareSize - overall.width - 2,
4850 y + font_ascent + 1, string, 1);
4852 XDrawString(xDisplay, xBoardWindow, countGC,
4853 x + squareSize - overall.width - 2,
4854 y + font_ascent + 1, string, 1);
4857 if (column == (flipView ? BOARD_RGHT : BOARD_LEFT-1) && piece > 1) {
4858 string[0] = '0' + piece;
4859 XTextExtents(countFontStruct, string, 1, &direction,
4860 &font_ascent, &font_descent, &overall);
4861 if (appData.monoMode) {
4862 XDrawImageString(xDisplay, xBoardWindow, countGC,
4863 x + 2, y + font_ascent + 1, string, 1);
4865 XDrawString(xDisplay, xBoardWindow, countGC,
4866 x + 2, y + font_ascent + 1, string, 1);
4870 if (piece == EmptySquare || appData.blindfold) {
4871 BlankSquare(x, y, square_color, piece, xBoardWindow);
4873 drawfunc = ChooseDrawFunc();
4874 if (do_flash && appData.flashCount > 0) {
4875 for (i=0; i<appData.flashCount; ++i) {
4877 drawfunc(piece, square_color, x, y, xBoardWindow);
4878 XSync(xDisplay, False);
4879 do_flash_delay(flash_delay);
4881 BlankSquare(x, y, square_color, piece, xBoardWindow);
4882 XSync(xDisplay, False);
4883 do_flash_delay(flash_delay);
4886 drawfunc(piece, square_color, x, y, xBoardWindow);
4890 string[1] = NULLCHAR;
4891 if (appData.showCoords && row == (flipView ? BOARD_HEIGHT-1 : 0)
4892 && column >= BOARD_LEFT && column < BOARD_RGHT) {
4893 string[0] = 'a' + column - BOARD_LEFT;
4894 XTextExtents(coordFontStruct, string, 1, &direction,
4895 &font_ascent, &font_descent, &overall);
4896 if (appData.monoMode) {
4897 XDrawImageString(xDisplay, xBoardWindow, coordGC,
4898 x + squareSize - overall.width - 2,
4899 y + squareSize - font_descent - 1, string, 1);
4901 XDrawString(xDisplay, xBoardWindow, coordGC,
4902 x + squareSize - overall.width - 2,
4903 y + squareSize - font_descent - 1, string, 1);
4906 if (appData.showCoords && column == (flipView ? BOARD_RGHT-1 : BOARD_LEFT)) {
4907 string[0] = ONE + row;
4908 XTextExtents(coordFontStruct, string, 1, &direction,
4909 &font_ascent, &font_descent, &overall);
4910 if (appData.monoMode) {
4911 XDrawImageString(xDisplay, xBoardWindow, coordGC,
4912 x + 2, y + font_ascent + 1, string, 1);
4914 XDrawString(xDisplay, xBoardWindow, coordGC,
4915 x + 2, y + font_ascent + 1, string, 1);
4921 /* Why is this needed on some versions of X? */
4922 void EventProc(widget, unused, event)
4927 if (!XtIsRealized(widget))
4930 switch (event->type) {
4932 if (event->xexpose.count > 0) return; /* no clipping is done */
4933 XDrawPosition(widget, True, NULL);
4941 void DrawPosition(fullRedraw, board)
4942 /*Boolean*/int fullRedraw;
4945 XDrawPosition(boardWidget, fullRedraw, board);
4948 /* Returns 1 if there are "too many" differences between b1 and b2
4949 (i.e. more than 1 move was made) */
4950 static int too_many_diffs(b1, b2)
4956 for (i=0; i<BOARD_HEIGHT; ++i) {
4957 for (j=0; j<BOARD_WIDTH; ++j) {
4958 if (b1[i][j] != b2[i][j]) {
4959 if (++c > 4) /* Castling causes 4 diffs */
4968 /* Matrix describing castling maneuvers */
4969 /* Row, ColRookFrom, ColKingFrom, ColRookTo, ColKingTo */
4970 static int castling_matrix[4][5] = {
4971 { 0, 0, 4, 3, 2 }, /* 0-0-0, white */
4972 { 0, 7, 4, 5, 6 }, /* 0-0, white */
4973 { 7, 0, 4, 3, 2 }, /* 0-0-0, black */
4974 { 7, 7, 4, 5, 6 } /* 0-0, black */
4977 /* Checks whether castling occurred. If it did, *rrow and *rcol
4978 are set to the destination (row,col) of the rook that moved.
4980 Returns 1 if castling occurred, 0 if not.
4982 Note: Only handles a max of 1 castling move, so be sure
4983 to call too_many_diffs() first.
4985 static int check_castle_draw(newb, oldb, rrow, rcol)
4992 /* For each type of castling... */
4993 for (i=0; i<4; ++i) {
4994 r = castling_matrix[i];
4996 /* Check the 4 squares involved in the castling move */
4998 for (j=1; j<=4; ++j) {
4999 if (newb[r[0]][r[j]] == oldb[r[0]][r[j]]) {
5006 /* All 4 changed, so it must be a castling move */
5015 static int damage[BOARD_SIZE][BOARD_SIZE];
5018 * event handler for redrawing the board
5020 void XDrawPosition(w, repaint, board)
5022 /*Boolean*/int repaint;
5026 static int lastFlipView = 0;
5027 static int lastBoardValid = 0;
5028 static Board lastBoard;
5032 if (board == NULL) {
5033 if (!lastBoardValid) return;
5036 if (!lastBoardValid || lastFlipView != flipView) {
5037 XtSetArg(args[0], XtNleftBitmap, (flipView ? xMarkPixmap : None));
5038 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flip View"),
5043 * It would be simpler to clear the window with XClearWindow()
5044 * but this causes a very distracting flicker.
5047 if (!repaint && lastBoardValid && lastFlipView == flipView) {
5049 /* If too much changes (begin observing new game, etc.), don't
5051 do_flash = too_many_diffs(board, lastBoard) ? 0 : 1;
5053 /* Special check for castling so we don't flash both the king
5054 and the rook (just flash the king). */
5056 if (check_castle_draw(board, lastBoard, &rrow, &rcol)) {
5057 /* Draw rook with NO flashing. King will be drawn flashing later */
5058 DrawSquare(rrow, rcol, board[rrow][rcol], 0);
5059 lastBoard[rrow][rcol] = board[rrow][rcol];
5063 /* First pass -- Draw (newly) empty squares and repair damage.
5064 This prevents you from having a piece show up twice while it
5065 is flashing on its new square */
5066 for (i = 0; i < BOARD_HEIGHT; i++)
5067 for (j = 0; j < BOARD_WIDTH; j++)
5068 if ((board[i][j] != lastBoard[i][j] && board[i][j] == EmptySquare)
5070 DrawSquare(i, j, board[i][j], 0);
5071 damage[i][j] = False;
5074 /* Second pass -- Draw piece(s) in new position and flash them */
5075 for (i = 0; i < BOARD_HEIGHT; i++)
5076 for (j = 0; j < BOARD_WIDTH; j++)
5077 if (board[i][j] != lastBoard[i][j]) {
5078 DrawSquare(i, j, board[i][j], do_flash);
5082 XDrawSegments(xDisplay, xBoardWindow, lineGC,
5083 gridSegments, BOARD_HEIGHT + BOARD_WIDTH + 2);
5085 for (i = 0; i < BOARD_HEIGHT; i++)
5086 for (j = 0; j < BOARD_WIDTH; j++) {
5087 DrawSquare(i, j, board[i][j], 0);
5088 damage[i][j] = False;
5092 CopyBoard(lastBoard, board);
5094 lastFlipView = flipView;
5096 /* Draw highlights */
5097 if (pm1X >= 0 && pm1Y >= 0) {
5098 drawHighlight(pm1X, pm1Y, prelineGC);
5100 if (pm2X >= 0 && pm2Y >= 0) {
5101 drawHighlight(pm2X, pm2Y, prelineGC);
5103 if (hi1X >= 0 && hi1Y >= 0) {
5104 drawHighlight(hi1X, hi1Y, highlineGC);
5106 if (hi2X >= 0 && hi2Y >= 0) {
5107 drawHighlight(hi2X, hi2Y, highlineGC);
5110 /* If piece being dragged around board, must redraw that too */
5113 XSync(xDisplay, False);
5118 * event handler for redrawing the board
5120 void DrawPositionProc(w, event, prms, nprms)
5126 XDrawPosition(w, True, NULL);
5131 * event handler for parsing user moves
5133 // [HGM] This routine will need quite some reworking. Although the backend still supports the old
5134 // way of doing things, by calling UserMoveEvent() to test the legality of the move and then perform
5135 // it at the end, and doing all kind of preliminary tests here (e.g. to weed out self-captures), it
5136 // should be made to use the new way, of calling UserMoveTest early to determine the legality of the
5137 // move, (which will weed out the illegal selfcaptures and moves into the holdings, and flag promotions),
5138 // and at the end FinishMove() to perform the move after optional promotion popups.
5139 // For now I patched it to allow self-capture with King, and suppress clicks between board and holdings.
5140 void HandleUserMove(w, event, prms, nprms)
5147 Boolean saveAnimate;
5148 static int second = 0, promotionChoice = 0;
5151 if (w != boardWidget || errorExitStatus != -1) return;
5153 x = EventToSquare(event->xbutton.x, BOARD_WIDTH);
5154 y = EventToSquare(event->xbutton.y, BOARD_HEIGHT);
5155 if (!flipView && y >= 0) {
5156 y = BOARD_HEIGHT - 1 - y;
5158 if (flipView && x >= 0) {
5159 x = BOARD_WIDTH - 1 - x;
5162 if(promotionChoice) { // we are waiting for a click to indicate promotion piece
5163 if(event->type == ButtonRelease) return; // ignore upclick of click-click destination
5164 promotionChoice = FALSE; // only one chance: if click not OK it is interpreted as cancel
5165 if(appData.debugMode) fprintf(debugFP, "promotion click, x=%d, y=%d\n", x, y);
5166 if(gameInfo.holdingsWidth &&
5167 (WhiteOnMove(currentMove)
5168 ? x == BOARD_WIDTH-1 && y < gameInfo.holdingsSize && y > 0
5169 : x == 0 && y >= BOARD_HEIGHT - gameInfo.holdingsSize && y < BOARD_HEIGHT-1) ) {
5170 // click in right holdings, for determining promotion piece
5171 ChessSquare p = boards[currentMove][y][x];
5172 if(appData.debugMode) fprintf(debugFP, "square contains %d\n", (int)p);
5173 if(p != EmptySquare) {
5174 FinishMove(NormalMove, fromX, fromY, toX, toY, ToLower(PieceToChar(p)));
5179 DrawPosition(FALSE, boards[currentMove]);
5182 if (event->type == ButtonPress) ErrorPopDown();
5185 if (event->type == ButtonPress) {
5186 XtPopdown(promotionShell);
5187 XtDestroyWidget(promotionShell);
5188 promotionUp = False;
5196 /* [HGM] holdings: next 5 lines: ignore all clicks between board and holdings */
5197 if(event->type == ButtonPress
5198 && ( x == BOARD_LEFT-1 || x == BOARD_RGHT
5199 || x == BOARD_LEFT-2 && y < BOARD_HEIGHT-gameInfo.holdingsSize
5200 || x == BOARD_RGHT+1 && y >= gameInfo.holdingsSize) )
5204 if (event->type == ButtonPress) {
5205 /* First square, prepare to drag */
5206 if (OKToStartUserMove(x, y)) {
5210 DragPieceBegin(event->xbutton.x, event->xbutton.y);
5211 if (appData.highlightDragging) {
5212 SetHighlights(x, y, -1, -1);
5220 if (event->type == ButtonRelease && x == fromX && y == fromY) {
5221 /* Click on single square in stead of drag-drop */
5222 DragPieceEnd(event->xbutton.x, event->xbutton.y);
5223 if (appData.animateDragging) {
5224 /* Undo animation damage if any */
5225 DrawPosition(FALSE, NULL);
5228 /* Second up/down in same square; just abort move */
5233 ClearPremoveHighlights();
5235 /* First upclick in same square; start click-click mode */
5236 SetHighlights(x, y, -1, -1);
5241 moveType = UserMoveTest(fromX, fromY, x, y, NULLCHAR, event->type == ButtonRelease);
5243 if (moveType == Comment) { // kludge for indicating capture-own on Press
5244 /* Clicked again on same color piece -- changed his mind */
5245 /* note that re-clicking same square always hits same color piece */
5246 second = (x == fromX && y == fromY);
5247 if (appData.highlightDragging) {
5248 SetHighlights(x, y, -1, -1);
5252 if (OKToStartUserMove(x, y)) {
5255 DragPieceBegin(event->xbutton.x, event->xbutton.y);
5260 if(moveType == AmbiguousMove) { // kludge to indicate edit-position move
5263 DragPieceEnd(event->xbutton.x, event->xbutton.y);
5264 DrawPosition(FALSE, boards[currentMove]);
5268 /* Complete move; (x,y) is now different from (fromX, fromY) on both Press and Release */
5271 saveAnimate = appData.animate;
5272 if (event->type == ButtonPress) {
5273 /* Finish clickclick move */
5274 if (appData.animate || appData.highlightLastMove) {
5275 SetHighlights(fromX, fromY, toX, toY);
5280 /* Finish drag move */
5281 if (appData.highlightLastMove) {
5282 SetHighlights(fromX, fromY, toX, toY);
5286 DragPieceEnd(event->xbutton.x, event->xbutton.y);
5287 /* Don't animate move and drag both */
5288 appData.animate = FALSE;
5290 if (moveType == WhitePromotionKnight || moveType == BlackPromotionKnight ||
5291 (moveType == WhitePromotionQueen || moveType == BlackPromotionQueen) &&
5292 appData.alwaysPromoteToQueen) { // promotion, but no choice
5293 FinishMove(moveType, fromX, fromY, toX, toY, 'q');
5295 if (moveType == WhitePromotionQueen || moveType == BlackPromotionQueen ) {
5296 SetHighlights(fromX, fromY, toX, toY);
5297 if(gameInfo.variant == VariantSuper || gameInfo.variant == VariantGreat) {
5298 // [HGM] super: promotion to captured piece selected from holdings
5299 ChessSquare p = boards[currentMove][fromY][fromX], q = boards[currentMove][toY][toX];
5300 promotionChoice = TRUE;
5301 // kludge follows to temporarily execute move on display, without promoting yet
5302 boards[currentMove][fromY][fromX] = EmptySquare; // move Pawn to 8th rank
5303 boards[currentMove][toY][toX] = p;
5304 DrawPosition(FALSE, boards[currentMove]);
5305 boards[currentMove][fromY][fromX] = p; // take back, but display stays
5306 boards[currentMove][toY][toX] = q;
5307 DisplayMessage("Click in holdings to choose piece", "");
5311 goto skipClearingFrom; // the skipped stuff is done asynchronously by PromotionCallback
5313 if(moveType != ImpossibleMove) { // valid move, but no promotion
5314 FinishMove(moveType, fromX, fromY, toX, toY, NULLCHAR);
5315 } else { // invalid move; could have set premove
5318 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
5319 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
5322 appData.animate = saveAnimate;
5323 if (appData.animate || appData.animateDragging) {
5324 /* Undo animation damage if needed */
5325 DrawPosition(FALSE, NULL);
5329 void AnimateUserMove (Widget w, XEvent * event,
5330 String * params, Cardinal * nParams)
5332 DragPieceMove(event->xmotion.x, event->xmotion.y);
5335 Widget CommentCreate(name, text, mutable, callback, lines)
5337 int /*Boolean*/ mutable;
5338 XtCallbackProc callback;
5342 Widget shell, layout, form, edit, b_ok, b_cancel, b_clear, b_close, b_edit;
5347 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5348 XtGetValues(boardWidget, args, j);
5351 XtSetArg(args[j], XtNresizable, True); j++;
5354 XtCreatePopupShell(name, topLevelShellWidgetClass,
5355 shellWidget, args, j);
5358 XtCreatePopupShell(name, transientShellWidgetClass,
5359 shellWidget, args, j);
5362 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
5363 layoutArgs, XtNumber(layoutArgs));
5365 XtCreateManagedWidget("form", formWidgetClass, layout,
5366 formArgs, XtNumber(formArgs));
5370 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
5371 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
5373 XtSetArg(args[j], XtNstring, text); j++;
5374 XtSetArg(args[j], XtNtop, XtChainTop); j++;
5375 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5376 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5377 XtSetArg(args[j], XtNright, XtChainRight); j++;
5378 XtSetArg(args[j], XtNresizable, True); j++;
5379 XtSetArg(args[j], XtNwidth, bw_width); j++; /*force wider than buttons*/
5381 XtSetArg(args[j], XtNscrollVertical, XawtextScrollWhenNeeded); j++;
5383 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
5384 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
5386 XtSetArg(args[j], XtNautoFill, True); j++;
5387 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
5389 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
5393 XtSetArg(args[j], XtNfromVert, edit); j++;
5394 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5395 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5396 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5397 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5399 XtCreateManagedWidget(_("ok"), commandWidgetClass, form, args, j);
5400 XtAddCallback(b_ok, XtNcallback, callback, (XtPointer) 0);
5403 XtSetArg(args[j], XtNfromVert, edit); j++;
5404 XtSetArg(args[j], XtNfromHoriz, b_ok); j++;
5405 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5406 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5407 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5408 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5410 XtCreateManagedWidget(_("cancel"), commandWidgetClass, form, args, j);
5411 XtAddCallback(b_cancel, XtNcallback, callback, (XtPointer) 0);
5414 XtSetArg(args[j], XtNfromVert, edit); j++;
5415 XtSetArg(args[j], XtNfromHoriz, b_cancel); 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(_("clear"), commandWidgetClass, form, args, j);
5422 XtAddCallback(b_clear, XtNcallback, callback, (XtPointer) 0);
5425 XtSetArg(args[j], XtNfromVert, edit); j++;
5426 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5427 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5428 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5429 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5431 XtCreateManagedWidget(_("close"), commandWidgetClass, form, args, j);
5432 XtAddCallback(b_close, XtNcallback, callback, (XtPointer) 0);
5435 XtSetArg(args[j], XtNfromVert, edit); j++;
5436 XtSetArg(args[j], XtNfromHoriz, b_close); j++;
5437 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5438 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5439 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5440 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5442 XtCreateManagedWidget(_("edit"), commandWidgetClass, form, args, j);
5443 XtAddCallback(b_edit, XtNcallback, callback, (XtPointer) 0);
5446 XtRealizeWidget(shell);
5448 if (commentX == -1) {
5451 Dimension pw_height;
5452 Dimension ew_height;
5455 XtSetArg(args[j], XtNheight, &ew_height); j++;
5456 XtGetValues(edit, args, j);
5459 XtSetArg(args[j], XtNheight, &pw_height); j++;
5460 XtGetValues(shell, args, j);
5461 commentH = pw_height + (lines - 1) * ew_height;
5462 commentW = bw_width - 16;
5464 XSync(xDisplay, False);
5466 /* This code seems to tickle an X bug if it is executed too soon
5467 after xboard starts up. The coordinates get transformed as if
5468 the main window was positioned at (0, 0).
5470 XtTranslateCoords(shellWidget,
5471 (bw_width - commentW) / 2, 0 - commentH / 2,
5472 &commentX, &commentY);
5474 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
5475 RootWindowOfScreen(XtScreen(shellWidget)),
5476 (bw_width - commentW) / 2, 0 - commentH / 2,
5481 if (commentY < 0) commentY = 0; /*avoid positioning top offscreen*/
5484 XtSetArg(args[j], XtNheight, commentH); j++;
5485 XtSetArg(args[j], XtNwidth, commentW); j++;
5486 XtSetArg(args[j], XtNx, commentX); j++;
5487 XtSetArg(args[j], XtNy, commentY); j++;
5488 XtSetValues(shell, args, j);
5489 XtSetKeyboardFocus(shell, edit);
5494 /* Used for analysis window and ICS input window */
5495 Widget MiscCreate(name, text, mutable, callback, lines)
5497 int /*Boolean*/ mutable;
5498 XtCallbackProc callback;
5502 Widget shell, layout, form, edit;
5504 Dimension bw_width, pw_height, ew_height, w, h;
5510 XtSetArg(args[j], XtNresizable, True); j++;
5513 XtCreatePopupShell(name, topLevelShellWidgetClass,
5514 shellWidget, args, j);
5517 XtCreatePopupShell(name, transientShellWidgetClass,
5518 shellWidget, args, j);
5521 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
5522 layoutArgs, XtNumber(layoutArgs));
5524 XtCreateManagedWidget("form", formWidgetClass, layout,
5525 formArgs, XtNumber(formArgs));
5529 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
5530 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
5532 XtSetArg(args[j], XtNstring, text); j++;
5533 XtSetArg(args[j], XtNtop, XtChainTop); j++;
5534 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5535 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5536 XtSetArg(args[j], XtNright, XtChainRight); j++;
5537 XtSetArg(args[j], XtNresizable, True); j++;
5539 XtSetArg(args[j], XtNscrollVertical, XawtextScrollWhenNeeded); j++;
5541 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
5542 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
5544 XtSetArg(args[j], XtNautoFill, True); j++;
5545 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
5547 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
5549 XtRealizeWidget(shell);
5552 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5553 XtGetValues(boardWidget, args, j);
5556 XtSetArg(args[j], XtNheight, &ew_height); j++;
5557 XtGetValues(edit, args, j);
5560 XtSetArg(args[j], XtNheight, &pw_height); j++;
5561 XtGetValues(shell, args, j);
5562 h = pw_height + (lines - 1) * ew_height;
5565 XSync(xDisplay, False);
5567 /* This code seems to tickle an X bug if it is executed too soon
5568 after xboard starts up. The coordinates get transformed as if
5569 the main window was positioned at (0, 0).
5571 XtTranslateCoords(shellWidget, (bw_width - w) / 2, 0 - h / 2, &x, &y);
5573 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
5574 RootWindowOfScreen(XtScreen(shellWidget)),
5575 (bw_width - w) / 2, 0 - h / 2, &xx, &yy, &junk);
5579 if (y < 0) y = 0; /*avoid positioning top offscreen*/
5582 XtSetArg(args[j], XtNheight, h); j++;
5583 XtSetArg(args[j], XtNwidth, w); j++;
5584 XtSetArg(args[j], XtNx, x); j++;
5585 XtSetArg(args[j], XtNy, y); j++;
5586 XtSetValues(shell, args, j);
5592 static int savedIndex; /* gross that this is global */
5594 void EditCommentPopUp(index, title, text)
5603 if (text == NULL) text = "";
5605 if (editShell == NULL) {
5607 CommentCreate(title, text, True, EditCommentCallback, 4);
5608 XtRealizeWidget(editShell);
5609 CatchDeleteWindow(editShell, "EditCommentPopDown");
5611 edit = XtNameToWidget(editShell, "*form.text");
5613 XtSetArg(args[j], XtNstring, text); j++;
5614 XtSetValues(edit, args, j);
5616 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5617 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5618 XtSetValues(editShell, args, j);
5621 XtPopup(editShell, XtGrabNone);
5625 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
5626 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
5630 void EditCommentCallback(w, client_data, call_data)
5632 XtPointer client_data, call_data;
5640 XtSetArg(args[j], XtNlabel, &name); j++;
5641 XtGetValues(w, args, j);
5643 if (strcmp(name, _("ok")) == 0) {
5644 edit = XtNameToWidget(editShell, "*form.text");
5646 XtSetArg(args[j], XtNstring, &val); j++;
5647 XtGetValues(edit, args, j);
5648 ReplaceComment(savedIndex, val);
5649 EditCommentPopDown();
5650 } else if (strcmp(name, _("cancel")) == 0) {
5651 EditCommentPopDown();
5652 } else if (strcmp(name, _("clear")) == 0) {
5653 edit = XtNameToWidget(editShell, "*form.text");
5654 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
5655 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
5659 void EditCommentPopDown()
5664 if (!editUp) return;
5666 XtSetArg(args[j], XtNx, &commentX); j++;
5667 XtSetArg(args[j], XtNy, &commentY); j++;
5668 XtSetArg(args[j], XtNheight, &commentH); j++;
5669 XtSetArg(args[j], XtNwidth, &commentW); j++;
5670 XtGetValues(editShell, args, j);
5671 XtPopdown(editShell);
5674 XtSetArg(args[j], XtNleftBitmap, None); j++;
5675 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
5679 void ICSInputBoxPopUp()
5684 char *title = _("ICS Input");
5687 if (ICSInputShell == NULL) {
5688 ICSInputShell = MiscCreate(title, "", True, NULL, 1);
5689 tr = XtParseTranslationTable(ICSInputTranslations);
5690 edit = XtNameToWidget(ICSInputShell, "*form.text");
5691 XtOverrideTranslations(edit, tr);
5692 XtRealizeWidget(ICSInputShell);
5693 CatchDeleteWindow(ICSInputShell, "ICSInputBoxPopDown");
5696 edit = XtNameToWidget(ICSInputShell, "*form.text");
5698 XtSetArg(args[j], XtNstring, ""); j++;
5699 XtSetValues(edit, args, j);
5701 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5702 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5703 XtSetValues(ICSInputShell, args, j);
5706 XtPopup(ICSInputShell, XtGrabNone);
5707 XtSetKeyboardFocus(ICSInputShell, edit);
5709 ICSInputBoxUp = True;
5711 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
5712 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
5716 void ICSInputSendText()
5723 edit = XtNameToWidget(ICSInputShell, "*form.text");
5725 XtSetArg(args[j], XtNstring, &val); j++;
5726 XtGetValues(edit, args, j);
5727 SendMultiLineToICS(val);
5728 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
5729 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
5732 void ICSInputBoxPopDown()
5737 if (!ICSInputBoxUp) return;
5739 XtPopdown(ICSInputShell);
5740 ICSInputBoxUp = False;
5742 XtSetArg(args[j], XtNleftBitmap, None); j++;
5743 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
5747 void CommentPopUp(title, text)
5754 if (commentShell == NULL) {
5756 CommentCreate(title, text, False, CommentCallback, 4);
5757 XtRealizeWidget(commentShell);
5758 CatchDeleteWindow(commentShell, "CommentPopDown");
5760 edit = XtNameToWidget(commentShell, "*form.text");
5762 XtSetArg(args[j], XtNstring, text); j++;
5763 XtSetValues(edit, args, j);
5765 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5766 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5767 XtSetValues(commentShell, args, j);
5770 XtPopup(commentShell, XtGrabNone);
5771 XSync(xDisplay, False);
5776 void AnalysisPopUp(title, text)
5783 if (analysisShell == NULL) {
5784 analysisShell = MiscCreate(title, text, False, NULL, 4);
5785 XtRealizeWidget(analysisShell);
5786 CatchDeleteWindow(analysisShell, "AnalysisPopDown");
5789 edit = XtNameToWidget(analysisShell, "*form.text");
5791 XtSetArg(args[j], XtNstring, text); j++;
5792 XtSetValues(edit, args, j);
5794 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5795 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5796 XtSetValues(analysisShell, args, j);
5800 XtPopup(analysisShell, XtGrabNone);
5802 XSync(xDisplay, False);
5807 void CommentCallback(w, client_data, call_data)
5809 XtPointer client_data, call_data;
5816 XtSetArg(args[j], XtNlabel, &name); j++;
5817 XtGetValues(w, args, j);
5819 if (strcmp(name, _("close")) == 0) {
5821 } else if (strcmp(name, _("edit")) == 0) {
5828 void CommentPopDown()
5833 if (!commentUp) return;
5835 XtSetArg(args[j], XtNx, &commentX); j++;
5836 XtSetArg(args[j], XtNy, &commentY); j++;
5837 XtSetArg(args[j], XtNwidth, &commentW); j++;
5838 XtSetArg(args[j], XtNheight, &commentH); j++;
5839 XtGetValues(commentShell, args, j);
5840 XtPopdown(commentShell);
5841 XSync(xDisplay, False);
5845 void AnalysisPopDown()
5847 if (!analysisUp) return;
5848 XtPopdown(analysisShell);
5849 XSync(xDisplay, False);
5851 if (appData.icsEngineAnalyze) ExitAnalyzeMode(); /* [DM] icsEngineAnalyze */
5855 void FileNamePopUp(label, def, proc, openMode)
5862 Widget popup, layout, dialog, edit;
5868 fileProc = proc; /* I can't see a way not */
5869 fileOpenMode = openMode; /* to use globals here */
5872 XtSetArg(args[i], XtNresizable, True); i++;
5873 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
5874 XtSetArg(args[i], XtNtitle, XtNewString(_("File name prompt"))); i++;
5875 fileNameShell = popup =
5876 XtCreatePopupShell("File name prompt", transientShellWidgetClass,
5877 shellWidget, args, i);
5880 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
5881 layoutArgs, XtNumber(layoutArgs));
5884 XtSetArg(args[i], XtNlabel, label); i++;
5885 XtSetArg(args[i], XtNvalue, def); i++;
5886 XtSetArg(args[i], XtNborderWidth, 0); i++;
5887 dialog = XtCreateManagedWidget("fileName", dialogWidgetClass,
5890 XawDialogAddButton(dialog, _("ok"), FileNameCallback, (XtPointer) dialog);
5891 XawDialogAddButton(dialog, _("cancel"), FileNameCallback,
5892 (XtPointer) dialog);
5894 XtRealizeWidget(popup);
5895 CatchDeleteWindow(popup, "FileNamePopDown");
5897 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
5898 &x, &y, &win_x, &win_y, &mask);
5900 XtSetArg(args[0], XtNx, x - 10);
5901 XtSetArg(args[1], XtNy, y - 30);
5902 XtSetValues(popup, args, 2);
5904 XtPopup(popup, XtGrabExclusive);
5907 edit = XtNameToWidget(dialog, "*value");
5908 XtSetKeyboardFocus(popup, edit);
5911 void FileNamePopDown()
5913 if (!filenameUp) return;
5914 XtPopdown(fileNameShell);
5915 XtDestroyWidget(fileNameShell);
5920 void FileNameCallback(w, client_data, call_data)
5922 XtPointer client_data, call_data;
5927 XtSetArg(args[0], XtNlabel, &name);
5928 XtGetValues(w, args, 1);
5930 if (strcmp(name, _("cancel")) == 0) {
5935 FileNameAction(w, NULL, NULL, NULL);
5938 void FileNameAction(w, event, prms, nprms)
5950 name = XawDialogGetValueString(w = XtParent(w));
5952 if ((name != NULL) && (*name != NULLCHAR)) {
5954 XtPopdown(w = XtParent(XtParent(w)));
5958 p = strrchr(buf, ' ');
5965 fullname = ExpandPathName(buf);
5967 ErrorPopUp(_("Error"), _("Can't open file"), FALSE);
5970 f = fopen(fullname, fileOpenMode);
5972 DisplayError(_("Failed to open file"), errno);
5974 (void) (*fileProc)(f, index, buf);
5981 XtPopdown(w = XtParent(XtParent(w)));
5987 void PromotionPopUp()
5990 Widget dialog, layout;
5992 Dimension bw_width, pw_width;
5996 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5997 XtGetValues(boardWidget, args, j);
6000 XtSetArg(args[j], XtNresizable, True); j++;
6001 XtSetArg(args[j], XtNtitle, XtNewString(_("Promotion"))); j++;
6003 XtCreatePopupShell("Promotion", transientShellWidgetClass,
6004 shellWidget, args, j);
6006 XtCreateManagedWidget(layoutName, formWidgetClass, promotionShell,
6007 layoutArgs, XtNumber(layoutArgs));
6010 XtSetArg(args[j], XtNlabel, _("Promote to what?")); j++;
6011 XtSetArg(args[j], XtNborderWidth, 0); j++;
6012 dialog = XtCreateManagedWidget("promotion", dialogWidgetClass,
6015 if(gameInfo.variant != VariantShogi) {
6016 XawDialogAddButton(dialog, _("Queen"), PromotionCallback,
6017 (XtPointer) dialog);
6018 XawDialogAddButton(dialog, _("Rook"), PromotionCallback,
6019 (XtPointer) dialog);
6020 XawDialogAddButton(dialog, _("Bishop"), PromotionCallback,
6021 (XtPointer) dialog);
6022 XawDialogAddButton(dialog, _("Knight"), PromotionCallback,
6023 (XtPointer) dialog);
6024 if (!appData.testLegality || gameInfo.variant == VariantSuicide ||
6025 gameInfo.variant == VariantGiveaway) {
6026 XawDialogAddButton(dialog, _("King"), PromotionCallback,
6027 (XtPointer) dialog);
6029 if(gameInfo.variant == VariantCapablanca ||
6030 gameInfo.variant == VariantGothic ||
6031 gameInfo.variant == VariantCapaRandom) {
6032 XawDialogAddButton(dialog, _("Archbishop"), PromotionCallback,
6033 (XtPointer) dialog);
6034 XawDialogAddButton(dialog, _("Chancellor"), PromotionCallback,
6035 (XtPointer) dialog);
6037 } else // [HGM] shogi
6039 XawDialogAddButton(dialog, _("Promote"), PromotionCallback,
6040 (XtPointer) dialog);
6041 XawDialogAddButton(dialog, _("Defer"), PromotionCallback,
6042 (XtPointer) dialog);
6044 XawDialogAddButton(dialog, _("cancel"), PromotionCallback,
6045 (XtPointer) dialog);
6047 XtRealizeWidget(promotionShell);
6048 CatchDeleteWindow(promotionShell, "PromotionPopDown");
6051 XtSetArg(args[j], XtNwidth, &pw_width); j++;
6052 XtGetValues(promotionShell, args, j);
6054 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
6055 lineGap + squareSize/3 +
6056 ((toY == BOARD_HEIGHT-1) ^ (flipView) ?
6057 0 : 6*(squareSize + lineGap)), &x, &y);
6060 XtSetArg(args[j], XtNx, x); j++;
6061 XtSetArg(args[j], XtNy, y); j++;
6062 XtSetValues(promotionShell, args, j);
6064 XtPopup(promotionShell, XtGrabNone);
6069 void PromotionPopDown()
6071 if (!promotionUp) return;
6072 XtPopdown(promotionShell);
6073 XtDestroyWidget(promotionShell);
6074 promotionUp = False;
6077 void PromotionCallback(w, client_data, call_data)
6079 XtPointer client_data, call_data;
6085 XtSetArg(args[0], XtNlabel, &name);
6086 XtGetValues(w, args, 1);
6090 if (fromX == -1) return;
6092 if (strcmp(name, _("cancel")) == 0) {
6096 } else if (strcmp(name, _("Knight")) == 0) {
6098 } else if (strcmp(name, _("Promote")) == 0) {
6100 } else if (strcmp(name, _("Defer")) == 0) {
6103 promoChar = ToLower(name[0]);
6106 FinishMove(NormalMove, fromX, fromY, toX, toY, promoChar);
6108 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
6109 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
6114 void ErrorCallback(w, client_data, call_data)
6116 XtPointer client_data, call_data;
6119 XtPopdown(w = XtParent(XtParent(XtParent(w))));
6121 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
6127 if (!errorUp) return;
6129 XtPopdown(errorShell);
6130 XtDestroyWidget(errorShell);
6131 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
6134 void ErrorPopUp(title, label, modal)
6135 char *title, *label;
6139 Widget dialog, layout;
6143 Dimension bw_width, pw_width;
6144 Dimension pw_height;
6148 XtSetArg(args[i], XtNresizable, True); i++;
6149 XtSetArg(args[i], XtNtitle, title); i++;
6151 XtCreatePopupShell("errorpopup", transientShellWidgetClass,
6152 shellWidget, args, i);
6154 XtCreateManagedWidget(layoutName, formWidgetClass, errorShell,
6155 layoutArgs, XtNumber(layoutArgs));
6158 XtSetArg(args[i], XtNlabel, label); i++;
6159 XtSetArg(args[i], XtNborderWidth, 0); i++;
6160 dialog = XtCreateManagedWidget("dialog", dialogWidgetClass,
6163 XawDialogAddButton(dialog, _("ok"), ErrorCallback, (XtPointer) dialog);
6165 XtRealizeWidget(errorShell);
6166 CatchDeleteWindow(errorShell, "ErrorPopDown");
6169 XtSetArg(args[i], XtNwidth, &bw_width); i++;
6170 XtGetValues(boardWidget, args, i);
6172 XtSetArg(args[i], XtNwidth, &pw_width); i++;
6173 XtSetArg(args[i], XtNheight, &pw_height); i++;
6174 XtGetValues(errorShell, args, i);
6177 /* This code seems to tickle an X bug if it is executed too soon
6178 after xboard starts up. The coordinates get transformed as if
6179 the main window was positioned at (0, 0).
6181 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
6182 0 - pw_height + squareSize / 3, &x, &y);
6184 XTranslateCoordinates(xDisplay, XtWindow(boardWidget),
6185 RootWindowOfScreen(XtScreen(boardWidget)),
6186 (bw_width - pw_width) / 2,
6187 0 - pw_height + squareSize / 3, &xx, &yy, &junk);
6191 if (y < 0) y = 0; /*avoid positioning top offscreen*/
6194 XtSetArg(args[i], XtNx, x); i++;
6195 XtSetArg(args[i], XtNy, y); i++;
6196 XtSetValues(errorShell, args, i);
6199 XtPopup(errorShell, modal ? XtGrabExclusive : XtGrabNone);
6202 /* Disable all user input other than deleting the window */
6203 static int frozen = 0;
6207 /* Grab by a widget that doesn't accept input */
6208 XtAddGrab(messageWidget, TRUE, FALSE);
6212 /* Undo a FreezeUI */
6215 if (!frozen) return;
6216 XtRemoveGrab(messageWidget);
6220 char *ModeToWidgetName(mode)
6224 case BeginningOfGame:
6225 if (appData.icsActive)
6226 return "menuMode.ICS Client";
6227 else if (appData.noChessProgram ||
6228 *appData.cmailGameName != NULLCHAR)
6229 return "menuMode.Edit Game";
6231 return "menuMode.Machine Black";
6232 case MachinePlaysBlack:
6233 return "menuMode.Machine Black";
6234 case MachinePlaysWhite:
6235 return "menuMode.Machine White";
6237 return "menuMode.Analysis Mode";
6239 return "menuMode.Analyze File";
6240 case TwoMachinesPlay:
6241 return "menuMode.Two Machines";
6243 return "menuMode.Edit Game";
6244 case PlayFromGameFile:
6245 return "menuFile.Load Game";
6247 return "menuMode.Edit Position";
6249 return "menuMode.Training";
6250 case IcsPlayingWhite:
6251 case IcsPlayingBlack:
6255 return "menuMode.ICS Client";
6262 void ModeHighlight()
6265 static int oldPausing = FALSE;
6266 static GameMode oldmode = (GameMode) -1;
6269 if (!boardWidget || !XtIsRealized(boardWidget)) return;
6271 if (pausing != oldPausing) {
6272 oldPausing = pausing;
6274 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6276 XtSetArg(args[0], XtNleftBitmap, None);
6278 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Pause"),
6281 if (appData.showButtonBar) {
6284 XtSetArg(args[0], XtNbackground, buttonForegroundPixel);
6285 XtSetArg(args[1], XtNforeground, buttonBackgroundPixel);
6287 XtSetArg(args[0], XtNbackground, buttonBackgroundPixel);
6288 XtSetArg(args[1], XtNforeground, buttonForegroundPixel);
6291 /* Always toggle, don't set. Previous code messes up when
6292 invoked while the button is pressed, as releasing it
6293 toggles the state again. */
6296 XtSetArg(args[0], XtNbackground, &oldbg);
6297 XtSetArg(args[1], XtNforeground, &oldfg);
6298 XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON),
6300 XtSetArg(args[0], XtNbackground, oldfg);
6301 XtSetArg(args[1], XtNforeground, oldbg);
6304 XtSetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
6308 wname = ModeToWidgetName(oldmode);
6309 if (wname != NULL) {
6310 XtSetArg(args[0], XtNleftBitmap, None);
6311 XtSetValues(XtNameToWidget(menuBarWidget, wname), args, 1);
6313 wname = ModeToWidgetName(gameMode);
6314 if (wname != NULL) {
6315 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6316 XtSetValues(XtNameToWidget(menuBarWidget, wname), args, 1);
6320 /* Maybe all the enables should be handled here, not just this one */
6321 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Training"),
6322 gameMode == Training || gameMode == PlayFromGameFile);
6327 * Button/menu procedures
6329 void ResetProc(w, event, prms, nprms)
6339 int LoadGamePopUp(f, gameNumber, title)
6344 cmailMsgLoaded = FALSE;
6345 if (gameNumber == 0) {
6346 int error = GameListBuild(f);
6348 DisplayError(_("Cannot build game list"), error);
6349 } else if (!ListEmpty(&gameList) &&
6350 ((ListGame *) gameList.tailPred)->number > 1) {
6351 GameListPopUp(f, title);
6357 return LoadGame(f, gameNumber, title, FALSE);
6360 void LoadGameProc(w, event, prms, nprms)
6366 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
6369 FileNamePopUp(_("Load game file name?"), "", LoadGamePopUp, "rb");
6372 void LoadNextGameProc(w, event, prms, nprms)
6381 void LoadPrevGameProc(w, event, prms, nprms)
6390 void ReloadGameProc(w, event, prms, nprms)
6399 void LoadNextPositionProc(w, event, prms, nprms)
6408 void LoadPrevPositionProc(w, event, prms, nprms)
6417 void ReloadPositionProc(w, event, prms, nprms)
6426 void LoadPositionProc(w, event, prms, nprms)
6432 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
6435 FileNamePopUp(_("Load position file name?"), "", LoadPosition, "rb");
6438 void SaveGameProc(w, event, prms, nprms)
6444 FileNamePopUp(_("Save game file name?"),
6445 DefaultFileName(appData.oldSaveStyle ? "game" : "pgn"),
6449 void SavePositionProc(w, event, prms, nprms)
6455 FileNamePopUp(_("Save position file name?"),
6456 DefaultFileName(appData.oldSaveStyle ? "pos" : "fen"),
6460 void ReloadCmailMsgProc(w, event, prms, nprms)
6466 ReloadCmailMsgEvent(FALSE);
6469 void MailMoveProc(w, event, prms, nprms)
6478 /* this variable is shared between CopyPositionProc and SendPositionSelection */
6479 static char *selected_fen_position=NULL;
6482 SendPositionSelection(Widget w, Atom *selection, Atom *target,
6483 Atom *type_return, XtPointer *value_return,
6484 unsigned long *length_return, int *format_return)
6486 char *selection_tmp;
6488 if (!selected_fen_position) return False; /* should never happen */
6489 if (*target == XA_STRING){
6490 /* note: since no XtSelectionDoneProc was registered, Xt will
6491 * automatically call XtFree on the value returned. So have to
6492 * make a copy of it allocated with XtMalloc */
6493 selection_tmp= XtMalloc(strlen(selected_fen_position)+16);
6494 strcpy(selection_tmp, selected_fen_position);
6496 *value_return=selection_tmp;
6497 *length_return=strlen(selection_tmp);
6498 *type_return=XA_STRING;
6499 *format_return = 8; /* bits per byte */
6506 /* note: when called from menu all parameters are NULL, so no clue what the
6507 * Widget which was clicked on was, or what the click event was
6509 void CopyPositionProc(w, event, prms, nprms)
6517 if (selected_fen_position) free(selected_fen_position);
6518 selected_fen_position = (char *)PositionToFEN(currentMove, NULL);
6519 if (!selected_fen_position) return;
6520 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
6522 SendPositionSelection,
6523 NULL/* lose_ownership_proc */ ,
6524 NULL/* transfer_done_proc */);
6526 free(selected_fen_position);
6527 selected_fen_position=NULL;
6531 /* function called when the data to Paste is ready */
6533 PastePositionCB(Widget w, XtPointer client_data, Atom *selection,
6534 Atom *type, XtPointer value, unsigned long *len, int *format)
6537 if (value==NULL || *len==0) return; /* nothing had been selected to copy */
6538 fenstr[*len]='\0'; /* normally this string is terminated, but be safe */
6539 EditPositionPasteFEN(fenstr);
6543 /* called when Paste Position button is pressed,
6544 * all parameters will be NULL */
6545 void PastePositionProc(w, event, prms, nprms)
6551 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
6552 /* (XtSelectionCallbackProc) */ PastePositionCB,
6553 NULL, /* client_data passed to PastePositionCB */
6555 /* better to use the time field from the event that triggered the
6556 * call to this function, but that isn't trivial to get
6564 SendGameSelection(Widget w, Atom *selection, Atom *target,
6565 Atom *type_return, XtPointer *value_return,
6566 unsigned long *length_return, int *format_return)
6568 char *selection_tmp;
6570 if (*target == XA_STRING){
6571 FILE* f = fopen(gameCopyFilename, "r");
6574 if (f == NULL) return False;
6578 selection_tmp = XtMalloc(len + 1);
6579 count = fread(selection_tmp, 1, len, f);
6581 XtFree(selection_tmp);
6584 selection_tmp[len] = NULLCHAR;
6585 *value_return = selection_tmp;
6586 *length_return = len;
6587 *type_return = XA_STRING;
6588 *format_return = 8; /* bits per byte */
6595 /* note: when called from menu all parameters are NULL, so no clue what the
6596 * Widget which was clicked on was, or what the click event was
6598 void CopyGameProc(w, event, prms, nprms)
6606 ret = SaveGameToFile(gameCopyFilename, FALSE);
6609 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
6612 NULL/* lose_ownership_proc */ ,
6613 NULL/* transfer_done_proc */);
6616 /* function called when the data to Paste is ready */
6618 PasteGameCB(Widget w, XtPointer client_data, Atom *selection,
6619 Atom *type, XtPointer value, unsigned long *len, int *format)
6622 if (value == NULL || *len == 0) {
6623 return; /* nothing had been selected to copy */
6625 f = fopen(gamePasteFilename, "w");
6627 DisplayError(_("Can't open temp file"), errno);
6630 fwrite(value, 1, *len, f);
6633 LoadGameFromFile(gamePasteFilename, 0, gamePasteFilename, TRUE);
6636 /* called when Paste Game button is pressed,
6637 * all parameters will be NULL */
6638 void PasteGameProc(w, event, prms, nprms)
6644 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
6645 /* (XtSelectionCallbackProc) */ PasteGameCB,
6646 NULL, /* client_data passed to PasteGameCB */
6648 /* better to use the time field from the event that triggered the
6649 * call to this function, but that isn't trivial to get
6659 SaveGameProc(NULL, NULL, NULL, NULL);
6663 void QuitProc(w, event, prms, nprms)
6672 void PauseProc(w, event, prms, nprms)
6682 void MachineBlackProc(w, event, prms, nprms)
6688 MachineBlackEvent();
6691 void MachineWhiteProc(w, event, prms, nprms)
6697 MachineWhiteEvent();
6700 void AnalyzeModeProc(w, event, prms, nprms)
6708 if (!first.analysisSupport) {
6709 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
6710 DisplayError(buf, 0);
6713 /* [DM] icsEngineAnalyze [HGM] This is horrible code; reverse the gameMode and isEngineAnalyze tests! */
6714 if (appData.icsActive) {
6715 if (gameMode != IcsObserving) {
6716 sprintf(buf,_("You are not observing a game"));
6717 DisplayError(buf, 0);
6719 if (appData.icsEngineAnalyze) {
6720 if (appData.debugMode)
6721 fprintf(debugFP, _("Found unexpected active ICS engine analyze \n"));
6727 /* if enable, use want disable icsEngineAnalyze */
6728 if (appData.icsEngineAnalyze) {
6733 appData.icsEngineAnalyze = TRUE;
6734 if (appData.debugMode)
6735 fprintf(debugFP, _("ICS engine analyze starting... \n"));
6737 if (!appData.showThinking)
6738 ShowThinkingProc(w,event,prms,nprms);
6743 void AnalyzeFileProc(w, event, prms, nprms)
6749 if (!first.analysisSupport) {
6751 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
6752 DisplayError(buf, 0);
6757 if (!appData.showThinking)
6758 ShowThinkingProc(w,event,prms,nprms);
6761 FileNamePopUp(_("File to analyze"), "", LoadGamePopUp, "rb");
6762 AnalysisPeriodicEvent(1);
6765 void TwoMachinesProc(w, event, prms, nprms)
6774 void IcsClientProc(w, event, prms, nprms)
6783 void EditGameProc(w, event, prms, nprms)
6792 void EditPositionProc(w, event, prms, nprms)
6798 EditPositionEvent();
6801 void TrainingProc(w, event, prms, nprms)
6810 void EditCommentProc(w, event, prms, nprms)
6817 EditCommentPopDown();
6823 void IcsInputBoxProc(w, event, prms, nprms)
6829 if (ICSInputBoxUp) {
6830 ICSInputBoxPopDown();
6836 void AcceptProc(w, event, prms, nprms)
6845 void DeclineProc(w, event, prms, nprms)
6854 void RematchProc(w, event, prms, nprms)
6863 void CallFlagProc(w, event, prms, nprms)
6872 void DrawProc(w, event, prms, nprms)
6881 void AbortProc(w, event, prms, nprms)
6890 void AdjournProc(w, event, prms, nprms)
6899 void ResignProc(w, event, prms, nprms)
6908 void AdjuWhiteProc(w, event, prms, nprms)
6914 UserAdjudicationEvent(+1);
6917 void AdjuBlackProc(w, event, prms, nprms)
6923 UserAdjudicationEvent(-1);
6926 void AdjuDrawProc(w, event, prms, nprms)
6932 UserAdjudicationEvent(0);
6935 void EnterKeyProc(w, event, prms, nprms)
6941 if (ICSInputBoxUp == True)
6945 void StopObservingProc(w, event, prms, nprms)
6951 StopObservingEvent();
6954 void StopExaminingProc(w, event, prms, nprms)
6960 StopExaminingEvent();
6964 void ForwardProc(w, event, prms, nprms)
6974 void BackwardProc(w, event, prms, nprms)
6983 void ToStartProc(w, event, prms, nprms)
6992 void ToEndProc(w, event, prms, nprms)
7001 void RevertProc(w, event, prms, nprms)
7010 void TruncateGameProc(w, event, prms, nprms)
7016 TruncateGameEvent();
7018 void RetractMoveProc(w, event, prms, nprms)
7027 void MoveNowProc(w, event, prms, nprms)
7037 void AlwaysQueenProc(w, event, prms, nprms)
7045 appData.alwaysPromoteToQueen = !appData.alwaysPromoteToQueen;
7047 if (appData.alwaysPromoteToQueen) {
7048 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7050 XtSetArg(args[0], XtNleftBitmap, None);
7052 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
7056 void AnimateDraggingProc(w, event, prms, nprms)
7064 appData.animateDragging = !appData.animateDragging;
7066 if (appData.animateDragging) {
7067 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7070 XtSetArg(args[0], XtNleftBitmap, None);
7072 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Dragging"),
7076 void AnimateMovingProc(w, event, prms, nprms)
7084 appData.animate = !appData.animate;
7086 if (appData.animate) {
7087 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7090 XtSetArg(args[0], XtNleftBitmap, None);
7092 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
7096 void AutocommProc(w, event, prms, nprms)
7104 appData.autoComment = !appData.autoComment;
7106 if (appData.autoComment) {
7107 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7109 XtSetArg(args[0], XtNleftBitmap, None);
7111 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
7116 void AutoflagProc(w, event, prms, nprms)
7124 appData.autoCallFlag = !appData.autoCallFlag;
7126 if (appData.autoCallFlag) {
7127 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7129 XtSetArg(args[0], XtNleftBitmap, None);
7131 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
7135 void AutoflipProc(w, event, prms, nprms)
7143 appData.autoFlipView = !appData.autoFlipView;
7145 if (appData.autoFlipView) {
7146 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7148 XtSetArg(args[0], XtNleftBitmap, None);
7150 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flip View"),
7154 void AutobsProc(w, event, prms, nprms)
7162 appData.autoObserve = !appData.autoObserve;
7164 if (appData.autoObserve) {
7165 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7167 XtSetArg(args[0], XtNleftBitmap, None);
7169 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
7173 void AutoraiseProc(w, event, prms, nprms)
7181 appData.autoRaiseBoard = !appData.autoRaiseBoard;
7183 if (appData.autoRaiseBoard) {
7184 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7186 XtSetArg(args[0], XtNleftBitmap, None);
7188 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Raise Board"),
7192 void AutosaveProc(w, event, prms, nprms)
7200 appData.autoSaveGames = !appData.autoSaveGames;
7202 if (appData.autoSaveGames) {
7203 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7205 XtSetArg(args[0], XtNleftBitmap, None);
7207 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
7211 void BlindfoldProc(w, event, prms, nprms)
7219 appData.blindfold = !appData.blindfold;
7221 if (appData.blindfold) {
7222 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7224 XtSetArg(args[0], XtNleftBitmap, None);
7226 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Blindfold"),
7229 DrawPosition(True, NULL);
7232 void TestLegalityProc(w, event, prms, nprms)
7240 appData.testLegality = !appData.testLegality;
7242 if (appData.testLegality) {
7243 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7245 XtSetArg(args[0], XtNleftBitmap, None);
7247 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Test Legality"),
7252 void FlashMovesProc(w, event, prms, nprms)
7260 if (appData.flashCount == 0) {
7261 appData.flashCount = 3;
7263 appData.flashCount = -appData.flashCount;
7266 if (appData.flashCount > 0) {
7267 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7269 XtSetArg(args[0], XtNleftBitmap, None);
7271 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flash Moves"),
7275 void FlipViewProc(w, event, prms, nprms)
7281 flipView = !flipView;
7282 DrawPosition(True, NULL);
7285 void GetMoveListProc(w, event, prms, nprms)
7293 appData.getMoveList = !appData.getMoveList;
7295 if (appData.getMoveList) {
7296 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7299 XtSetArg(args[0], XtNleftBitmap, None);
7301 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
7306 void HighlightDraggingProc(w, event, prms, nprms)
7314 appData.highlightDragging = !appData.highlightDragging;
7316 if (appData.highlightDragging) {
7317 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7319 XtSetArg(args[0], XtNleftBitmap, None);
7321 XtSetValues(XtNameToWidget(menuBarWidget,
7322 "menuOptions.Highlight Dragging"), args, 1);
7326 void HighlightLastMoveProc(w, event, prms, nprms)
7334 appData.highlightLastMove = !appData.highlightLastMove;
7336 if (appData.highlightLastMove) {
7337 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7339 XtSetArg(args[0], XtNleftBitmap, None);
7341 XtSetValues(XtNameToWidget(menuBarWidget,
7342 "menuOptions.Highlight Last Move"), args, 1);
7345 void IcsAlarmProc(w, event, prms, nprms)
7353 appData.icsAlarm = !appData.icsAlarm;
7355 if (appData.icsAlarm) {
7356 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7358 XtSetArg(args[0], XtNleftBitmap, None);
7360 XtSetValues(XtNameToWidget(menuBarWidget,
7361 "menuOptions.ICS Alarm"), args, 1);
7364 void MoveSoundProc(w, event, prms, nprms)
7372 appData.ringBellAfterMoves = !appData.ringBellAfterMoves;
7374 if (appData.ringBellAfterMoves) {
7375 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7377 XtSetArg(args[0], XtNleftBitmap, None);
7379 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
7384 void OldSaveStyleProc(w, event, prms, nprms)
7392 appData.oldSaveStyle = !appData.oldSaveStyle;
7394 if (appData.oldSaveStyle) {
7395 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7397 XtSetArg(args[0], XtNleftBitmap, None);
7399 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Old Save Style"),
7403 void PeriodicUpdatesProc(w, event, prms, nprms)
7411 PeriodicUpdatesEvent(!appData.periodicUpdates);
7413 if (appData.periodicUpdates) {
7414 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7416 XtSetArg(args[0], XtNleftBitmap, None);
7418 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Periodic Updates"),
7422 void PonderNextMoveProc(w, event, prms, nprms)
7430 PonderNextMoveEvent(!appData.ponderNextMove);
7432 if (appData.ponderNextMove) {
7433 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7435 XtSetArg(args[0], XtNleftBitmap, None);
7437 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Ponder Next Move"),
7441 void PopupExitMessageProc(w, event, prms, nprms)
7449 appData.popupExitMessage = !appData.popupExitMessage;
7451 if (appData.popupExitMessage) {
7452 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7454 XtSetArg(args[0], XtNleftBitmap, None);
7456 XtSetValues(XtNameToWidget(menuBarWidget,
7457 "menuOptions.Popup Exit Message"), args, 1);
7460 void PopupMoveErrorsProc(w, event, prms, nprms)
7468 appData.popupMoveErrors = !appData.popupMoveErrors;
7470 if (appData.popupMoveErrors) {
7471 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7473 XtSetArg(args[0], XtNleftBitmap, None);
7475 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Popup Move Errors"),
7479 void PremoveProc(w, event, prms, nprms)
7487 appData.premove = !appData.premove;
7489 if (appData.premove) {
7490 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7492 XtSetArg(args[0], XtNleftBitmap, None);
7494 XtSetValues(XtNameToWidget(menuBarWidget,
7495 "menuOptions.Premove"), args, 1);
7498 void QuietPlayProc(w, event, prms, nprms)
7506 appData.quietPlay = !appData.quietPlay;
7508 if (appData.quietPlay) {
7509 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7511 XtSetArg(args[0], XtNleftBitmap, None);
7513 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Quiet Play"),
7517 void ShowCoordsProc(w, event, prms, nprms)
7525 appData.showCoords = !appData.showCoords;
7527 if (appData.showCoords) {
7528 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7530 XtSetArg(args[0], XtNleftBitmap, None);
7532 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
7535 DrawPosition(True, NULL);
7538 void ShowThinkingProc(w, event, prms, nprms)
7546 appData.showThinking = !appData.showThinking; // [HGM] thinking: tken out of ShowThinkingEvent
7547 ShowThinkingEvent();
7549 // [HGM] thinking: currently no suc menu item; replaced by Hide Thinking (From Human)
7550 if (appData.showThinking) {
7551 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7553 XtSetArg(args[0], XtNleftBitmap, None);
7555 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Thinking"),
7560 void HideThinkingProc(w, event, prms, nprms)
7568 appData.hideThinkingFromHuman = !appData.hideThinkingFromHuman; // [HGM] thinking: tken out of ShowThinkingEvent
7569 ShowThinkingEvent();
7571 if (appData.hideThinkingFromHuman) {
7572 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7574 XtSetArg(args[0], XtNleftBitmap, None);
7576 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
7580 void InfoProc(w, event, prms, nprms)
7587 snprintf(buf, sizeof(buf), "xterm -e info --directory %s --directory . -f %s &",
7592 void ManProc(w, event, prms, nprms)
7600 if (nprms && *nprms > 0)
7604 snprintf(buf, sizeof(buf), "xterm -e man %s &", name);
7608 void HintProc(w, event, prms, nprms)
7617 void BookProc(w, event, prms, nprms)
7626 void AboutProc(w, event, prms, nprms)
7634 char *zippy = " (with Zippy code)";
7638 snprintf(buf, sizeof(buf), "%s%s\n\n%s\n%s\n%s\n\n%s%s\n%s",
7639 programVersion, zippy,
7640 "Copyright 1991 Digital Equipment Corporation",
7641 "Enhancements Copyright 1992-2009 Free Software Foundation",
7642 "Enhancements Copyright 2005 Alessandro Scotti",
7643 PACKAGE, " is free software and carries NO WARRANTY;",
7644 "see the file COPYING for more information.");
7645 ErrorPopUp(_("About XBoard"), buf, FALSE);
7648 void DebugProc(w, event, prms, nprms)
7654 appData.debugMode = !appData.debugMode;
7657 void AboutGameProc(w, event, prms, nprms)
7666 void NothingProc(w, event, prms, nprms)
7675 void Iconify(w, event, prms, nprms)
7684 XtSetArg(args[0], XtNiconic, True);
7685 XtSetValues(shellWidget, args, 1);
7688 void DisplayMessage(message, extMessage)
7689 char *message, *extMessage;
7691 /* display a message in the message widget */
7700 snprintf(buf, sizeof(buf), "%s %s", message, extMessage);
7705 message = extMessage;
7709 /* need to test if messageWidget already exists, since this function
7710 can also be called during the startup, if for example a Xresource
7711 is not set up correctly */
7714 XtSetArg(arg, XtNlabel, message);
7715 XtSetValues(messageWidget, &arg, 1);
7721 void DisplayTitle(text)
7726 char title[MSG_SIZ];
7729 if (text == NULL) text = "";
7731 if (appData.titleInWindow) {
7733 XtSetArg(args[i], XtNlabel, text); i++;
7734 XtSetValues(titleWidget, args, i);
7737 if (*text != NULLCHAR) {
7739 strcpy(title, text);
7740 } else if (appData.icsActive) {
7741 snprintf(icon, sizeof(icon), "%s", appData.icsHost);
7742 snprintf(title, sizeof(title), "%s: %s", programName, appData.icsHost);
7743 } else if (appData.cmailGameName[0] != NULLCHAR) {
7744 snprintf(icon, sizeof(icon), "%s", "CMail");
7745 snprintf(title,sizeof(title), "%s: %s", programName, "CMail");
7747 // [HGM] license: This stuff should really be done in back-end, but WinBoard already had a pop-up for it
7748 } else if (gameInfo.variant == VariantGothic) {
7749 strcpy(icon, programName);
7750 strcpy(title, GOTHIC);
7753 } else if (gameInfo.variant == VariantFalcon) {
7754 strcpy(icon, programName);
7755 strcpy(title, FALCON);
7757 } else if (appData.noChessProgram) {
7758 strcpy(icon, programName);
7759 strcpy(title, programName);
7761 strcpy(icon, first.tidy);
7762 snprintf(title,sizeof(title), "%s: %s", programName, first.tidy);
7765 XtSetArg(args[i], XtNiconName, (XtArgVal) icon); i++;
7766 XtSetArg(args[i], XtNtitle, (XtArgVal) title); i++;
7767 XtSetValues(shellWidget, args, i);
7771 void DisplayError(message, error)
7778 if (appData.debugMode || appData.matchMode) {
7779 fprintf(stderr, "%s: %s\n", programName, message);
7782 if (appData.debugMode || appData.matchMode) {
7783 fprintf(stderr, "%s: %s: %s\n",
7784 programName, message, strerror(error));
7786 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
7789 ErrorPopUp(_("Error"), message, FALSE);
7793 void DisplayMoveError(message)
7798 DrawPosition(FALSE, NULL);
7799 if (appData.debugMode || appData.matchMode) {
7800 fprintf(stderr, "%s: %s\n", programName, message);
7802 if (appData.popupMoveErrors) {
7803 ErrorPopUp(_("Error"), message, FALSE);
7805 DisplayMessage(message, "");
7810 void DisplayFatalError(message, error, status)
7816 errorExitStatus = status;
7818 fprintf(stderr, "%s: %s\n", programName, message);
7820 fprintf(stderr, "%s: %s: %s\n",
7821 programName, message, strerror(error));
7822 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
7825 if (appData.popupExitMessage && boardWidget && XtIsRealized(boardWidget)) {
7826 ErrorPopUp(status ? _("Fatal Error") : _("Exiting"), message, TRUE);
7832 void DisplayInformation(message)
7836 ErrorPopUp(_("Information"), message, TRUE);
7839 void DisplayNote(message)
7843 ErrorPopUp(_("Note"), message, FALSE);
7847 NullXErrorCheck(dpy, error_event)
7849 XErrorEvent *error_event;
7854 void DisplayIcsInteractionTitle(message)
7857 if (oldICSInteractionTitle == NULL) {
7858 /* Magic to find the old window title, adapted from vim */
7859 char *wina = getenv("WINDOWID");
7861 Window win = (Window) atoi(wina);
7862 Window root, parent, *children;
7863 unsigned int nchildren;
7864 int (*oldHandler)() = XSetErrorHandler(NullXErrorCheck);
7866 if (XFetchName(xDisplay, win, &oldICSInteractionTitle)) break;
7867 if (!XQueryTree(xDisplay, win, &root, &parent,
7868 &children, &nchildren)) break;
7869 if (children) XFree((void *)children);
7870 if (parent == root || parent == 0) break;
7873 XSetErrorHandler(oldHandler);
7875 if (oldICSInteractionTitle == NULL) {
7876 oldICSInteractionTitle = "xterm";
7879 printf("\033]0;%s\007", message);
7883 char pendingReplyPrefix[MSG_SIZ];
7884 ProcRef pendingReplyPR;
7886 void AskQuestionProc(w, event, prms, nprms)
7893 fprintf(stderr, _("AskQuestionProc needed 4 parameters, got %d\n"),
7897 AskQuestionEvent(prms[0], prms[1], prms[2], prms[3]);
7900 void AskQuestionPopDown()
7902 if (!askQuestionUp) return;
7903 XtPopdown(askQuestionShell);
7904 XtDestroyWidget(askQuestionShell);
7905 askQuestionUp = False;
7908 void AskQuestionReplyAction(w, event, prms, nprms)
7918 reply = XawDialogGetValueString(w = XtParent(w));
7919 strcpy(buf, pendingReplyPrefix);
7920 if (*buf) strcat(buf, " ");
7923 OutputToProcess(pendingReplyPR, buf, strlen(buf), &err);
7924 AskQuestionPopDown();
7926 if (err) DisplayFatalError(_("Error writing to chess program"), err, 0);
7929 void AskQuestionCallback(w, client_data, call_data)
7931 XtPointer client_data, call_data;
7936 XtSetArg(args[0], XtNlabel, &name);
7937 XtGetValues(w, args, 1);
7939 if (strcmp(name, _("cancel")) == 0) {
7940 AskQuestionPopDown();
7942 AskQuestionReplyAction(w, NULL, NULL, NULL);
7946 void AskQuestion(title, question, replyPrefix, pr)
7947 char *title, *question, *replyPrefix;
7951 Widget popup, layout, dialog, edit;
7957 strcpy(pendingReplyPrefix, replyPrefix);
7958 pendingReplyPR = pr;
7961 XtSetArg(args[i], XtNresizable, True); i++;
7962 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
7963 askQuestionShell = popup =
7964 XtCreatePopupShell(title, transientShellWidgetClass,
7965 shellWidget, args, i);
7968 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
7969 layoutArgs, XtNumber(layoutArgs));
7972 XtSetArg(args[i], XtNlabel, question); i++;
7973 XtSetArg(args[i], XtNvalue, ""); i++;
7974 XtSetArg(args[i], XtNborderWidth, 0); i++;
7975 dialog = XtCreateManagedWidget("question", dialogWidgetClass,
7978 XawDialogAddButton(dialog, _("enter"), AskQuestionCallback,
7979 (XtPointer) dialog);
7980 XawDialogAddButton(dialog, _("cancel"), AskQuestionCallback,
7981 (XtPointer) dialog);
7983 XtRealizeWidget(popup);
7984 CatchDeleteWindow(popup, "AskQuestionPopDown");
7986 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
7987 &x, &y, &win_x, &win_y, &mask);
7989 XtSetArg(args[0], XtNx, x - 10);
7990 XtSetArg(args[1], XtNy, y - 30);
7991 XtSetValues(popup, args, 2);
7993 XtPopup(popup, XtGrabExclusive);
7994 askQuestionUp = True;
7996 edit = XtNameToWidget(dialog, "*value");
7997 XtSetKeyboardFocus(popup, edit);
8005 if (*name == NULLCHAR) {
8007 } else if (strcmp(name, "$") == 0) {
8008 putc(BELLCHAR, stderr);
8011 snprintf(buf, sizeof(buf), "%s '%s' &", appData.soundProgram, name);
8019 PlaySound(appData.soundMove);
8025 PlaySound(appData.soundIcsWin);
8031 PlaySound(appData.soundIcsLoss);
8037 PlaySound(appData.soundIcsDraw);
8041 PlayIcsUnfinishedSound()
8043 PlaySound(appData.soundIcsUnfinished);
8049 PlaySound(appData.soundIcsAlarm);
8055 system("stty echo");
8061 system("stty -echo");
8065 Colorize(cc, continuation)
8070 int count, outCount, error;
8072 if (textColors[(int)cc].bg > 0) {
8073 if (textColors[(int)cc].fg > 0) {
8074 sprintf(buf, "\033[0;%d;%d;%dm", textColors[(int)cc].attr,
8075 textColors[(int)cc].fg, textColors[(int)cc].bg);
8077 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
8078 textColors[(int)cc].bg);
8081 if (textColors[(int)cc].fg > 0) {
8082 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
8083 textColors[(int)cc].fg);
8085 sprintf(buf, "\033[0;%dm", textColors[(int)cc].attr);
8088 count = strlen(buf);
8089 outCount = OutputToProcess(NoProc, buf, count, &error);
8090 if (outCount < count) {
8091 DisplayFatalError(_("Error writing to display"), error, 1);
8094 if (continuation) return;
8097 PlaySound(appData.soundShout);
8100 PlaySound(appData.soundSShout);
8103 PlaySound(appData.soundChannel1);
8106 PlaySound(appData.soundChannel);
8109 PlaySound(appData.soundKibitz);
8112 PlaySound(appData.soundTell);
8114 case ColorChallenge:
8115 PlaySound(appData.soundChallenge);
8118 PlaySound(appData.soundRequest);
8121 PlaySound(appData.soundSeek);
8132 return getpwuid(getuid())->pw_name;
8135 static char *ExpandPathName(path)
8138 static char static_buf[2000];
8139 char *d, *s, buf[2000];
8145 while (*s && isspace(*s))
8154 if (*(s+1) == '/') {
8155 strcpy(d, getpwuid(getuid())->pw_dir);
8160 *strchr(buf, '/') = 0;
8161 pwd = getpwnam(buf);
8164 fprintf(stderr, _("ERROR: Unknown user %s (in path %s)\n"),
8168 strcpy(d, pwd->pw_dir);
8169 strcat(d, strchr(s+1, '/'));
8180 static char host_name[MSG_SIZ];
8182 #if HAVE_GETHOSTNAME
8183 gethostname(host_name, MSG_SIZ);
8185 #else /* not HAVE_GETHOSTNAME */
8186 # if HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H
8187 sysinfo(SI_HOSTNAME, host_name, MSG_SIZ);
8189 # else /* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
8191 # endif/* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
8192 #endif /* not HAVE_GETHOSTNAME */
8195 XtIntervalId delayedEventTimerXID = 0;
8196 DelayedEventCallback delayedEventCallback = 0;
8201 delayedEventTimerXID = 0;
8202 delayedEventCallback();
8206 ScheduleDelayedEvent(cb, millisec)
8207 DelayedEventCallback cb; long millisec;
8209 if(delayedEventTimerXID && delayedEventCallback == cb)
8210 // [HGM] alive: replace, rather than add or flush identical event
8211 XtRemoveTimeOut(delayedEventTimerXID);
8212 delayedEventCallback = cb;
8213 delayedEventTimerXID =
8214 XtAppAddTimeOut(appContext, millisec,
8215 (XtTimerCallbackProc) FireDelayedEvent, (XtPointer) 0);
8218 DelayedEventCallback
8221 if (delayedEventTimerXID) {
8222 return delayedEventCallback;
8229 CancelDelayedEvent()
8231 if (delayedEventTimerXID) {
8232 XtRemoveTimeOut(delayedEventTimerXID);
8233 delayedEventTimerXID = 0;
8237 XtIntervalId loadGameTimerXID = 0;
8239 int LoadGameTimerRunning()
8241 return loadGameTimerXID != 0;
8244 int StopLoadGameTimer()
8246 if (loadGameTimerXID != 0) {
8247 XtRemoveTimeOut(loadGameTimerXID);
8248 loadGameTimerXID = 0;
8256 LoadGameTimerCallback(arg, id)
8260 loadGameTimerXID = 0;
8265 StartLoadGameTimer(millisec)
8269 XtAppAddTimeOut(appContext, millisec,
8270 (XtTimerCallbackProc) LoadGameTimerCallback,
8274 XtIntervalId analysisClockXID = 0;
8277 AnalysisClockCallback(arg, id)
8281 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile
8282 || appData.icsEngineAnalyze) { // [DM]
8283 AnalysisPeriodicEvent(0);
8284 StartAnalysisClock();
8289 StartAnalysisClock()
8292 XtAppAddTimeOut(appContext, 2000,
8293 (XtTimerCallbackProc) AnalysisClockCallback,
8297 XtIntervalId clockTimerXID = 0;
8299 int ClockTimerRunning()
8301 return clockTimerXID != 0;
8304 int StopClockTimer()
8306 if (clockTimerXID != 0) {
8307 XtRemoveTimeOut(clockTimerXID);
8316 ClockTimerCallback(arg, id)
8325 StartClockTimer(millisec)
8329 XtAppAddTimeOut(appContext, millisec,
8330 (XtTimerCallbackProc) ClockTimerCallback,
8335 DisplayTimerLabel(w, color, timer, highlight)
8344 /* check for low time warning */
8345 Pixel foregroundOrWarningColor = timerForegroundPixel;
8348 appData.lowTimeWarning &&
8349 (timer / 1000) < appData.icsAlarmTime)
8350 foregroundOrWarningColor = lowTimeWarningColor;
8352 if (appData.clockMode) {
8353 sprintf(buf, "%s: %s", color, TimeString(timer));
8354 XtSetArg(args[0], XtNlabel, buf);
8356 sprintf(buf, "%s ", color);
8357 XtSetArg(args[0], XtNlabel, buf);
8362 XtSetArg(args[1], XtNbackground, foregroundOrWarningColor);
8363 XtSetArg(args[2], XtNforeground, timerBackgroundPixel);
8365 XtSetArg(args[1], XtNbackground, timerBackgroundPixel);
8366 XtSetArg(args[2], XtNforeground, foregroundOrWarningColor);
8369 XtSetValues(w, args, 3);
8373 DisplayWhiteClock(timeRemaining, highlight)
8379 if(appData.noGUI) return;
8380 DisplayTimerLabel(whiteTimerWidget, _("White"), timeRemaining, highlight);
8381 if (highlight && iconPixmap == bIconPixmap) {
8382 iconPixmap = wIconPixmap;
8383 XtSetArg(args[0], XtNiconPixmap, iconPixmap);
8384 XtSetValues(shellWidget, args, 1);
8389 DisplayBlackClock(timeRemaining, highlight)
8395 if(appData.noGUI) return;
8396 DisplayTimerLabel(blackTimerWidget, _("Black"), timeRemaining, highlight);
8397 if (highlight && iconPixmap == wIconPixmap) {
8398 iconPixmap = bIconPixmap;
8399 XtSetArg(args[0], XtNiconPixmap, iconPixmap);
8400 XtSetValues(shellWidget, args, 1);
8418 int StartChildProcess(cmdLine, dir, pr)
8425 int to_prog[2], from_prog[2];
8429 if (appData.debugMode) {
8430 fprintf(stderr, "StartChildProcess (dir=\"%s\") %s\n",dir, cmdLine);
8433 /* We do NOT feed the cmdLine to the shell; we just
8434 parse it into blank-separated arguments in the
8435 most simple-minded way possible.
8438 strcpy(buf, cmdLine);
8443 if (p == NULL) break;
8448 SetUpChildIO(to_prog, from_prog);
8450 if ((pid = fork()) == 0) {
8452 // [HGM] PSWBTM: made order resistant against case where fd of created pipe was 0 or 1
8453 close(to_prog[1]); // first close the unused pipe ends
8454 close(from_prog[0]);
8455 dup2(to_prog[0], 0); // to_prog was created first, nd is the only one to use 0 or 1
8456 dup2(from_prog[1], 1);
8457 if(to_prog[0] >= 2) close(to_prog[0]); // if 0 or 1, the dup2 already cosed the original
8458 close(from_prog[1]); // and closing again loses one of the pipes!
8459 if(fileno(stderr) >= 2) // better safe than sorry...
8460 dup2(1, fileno(stderr)); /* force stderr to the pipe */
8462 if (dir[0] != NULLCHAR && chdir(dir) != 0) {
8467 nice(appData.niceEngines); // [HGM] nice: adjust priority of engine proc
8469 execvp(argv[0], argv);
8471 /* If we get here, exec failed */
8476 /* Parent process */
8478 close(from_prog[1]);
8480 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8483 cp->fdFrom = from_prog[0];
8484 cp->fdTo = to_prog[1];
8489 // [HGM] kill: implement the 'hard killing' of AS's Winboard_x
8490 static RETSIGTYPE AlarmCallBack(int n)
8496 DestroyChildProcess(pr, signalType)
8500 ChildProc *cp = (ChildProc *) pr;
8502 if (cp->kind != CPReal) return;
8504 if (signalType == 10) { // [HGM] kill: if it does not terminate in 3 sec, kill
8505 signal(SIGALRM, AlarmCallBack);
8507 if(wait((int *) 0) == -1) { // process does not terminate on its own accord
8508 kill(cp->pid, SIGKILL); // kill it forcefully
8509 wait((int *) 0); // and wait again
8513 kill(cp->pid, signalType == 9 ? SIGKILL : SIGTERM); // [HGM] kill: use hard kill if so requested
8515 /* Process is exiting either because of the kill or because of
8516 a quit command sent by the backend; either way, wait for it to die.
8525 InterruptChildProcess(pr)
8528 ChildProc *cp = (ChildProc *) pr;
8530 if (cp->kind != CPReal) return;
8531 (void) kill(cp->pid, SIGINT); /* stop it thinking */
8534 int OpenTelnet(host, port, pr)
8539 char cmdLine[MSG_SIZ];
8541 if (port[0] == NULLCHAR) {
8542 snprintf(cmdLine, sizeof(cmdLine), "%s %s", appData.telnetProgram, host);
8544 snprintf(cmdLine, sizeof(cmdLine), "%s %s %s", appData.telnetProgram, host, port);
8546 return StartChildProcess(cmdLine, "", pr);
8549 int OpenTCP(host, port, pr)
8555 DisplayFatalError(_("Socket support is not configured in"), 0, 2);
8556 #else /* !OMIT_SOCKETS */
8558 struct sockaddr_in sa;
8560 unsigned short uport;
8563 if ((s = socket(AF_INET, SOCK_STREAM, 6)) < 0) {
8567 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
8568 sa.sin_family = AF_INET;
8569 sa.sin_addr.s_addr = INADDR_ANY;
8570 uport = (unsigned short) 0;
8571 sa.sin_port = htons(uport);
8572 if (bind(s, (struct sockaddr *) &sa, sizeof(struct sockaddr_in)) < 0) {
8576 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
8577 if (!(hp = gethostbyname(host))) {
8579 if (sscanf(host, "%d.%d.%d.%d", &b0, &b1, &b2, &b3) == 4) {
8580 hp = (struct hostent *) calloc(1, sizeof(struct hostent));
8581 hp->h_addrtype = AF_INET;
8583 hp->h_addr_list = (char **) calloc(2, sizeof(char *));
8584 hp->h_addr_list[0] = (char *) malloc(4);
8585 hp->h_addr_list[0][0] = b0;
8586 hp->h_addr_list[0][1] = b1;
8587 hp->h_addr_list[0][2] = b2;
8588 hp->h_addr_list[0][3] = b3;
8593 sa.sin_family = hp->h_addrtype;
8594 uport = (unsigned short) atoi(port);
8595 sa.sin_port = htons(uport);
8596 memcpy((char *) &sa.sin_addr, hp->h_addr, hp->h_length);
8598 if (connect(s, (struct sockaddr *) &sa,
8599 sizeof(struct sockaddr_in)) < 0) {
8603 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8610 #endif /* !OMIT_SOCKETS */
8615 int OpenCommPort(name, pr)
8622 fd = open(name, 2, 0);
8623 if (fd < 0) return errno;
8625 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8635 int OpenLoopback(pr)
8641 SetUpChildIO(to, from);
8643 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8646 cp->fdFrom = to[0]; /* note not from[0]; we are doing a loopback */
8653 int OpenRcmd(host, user, cmd, pr)
8654 char *host, *user, *cmd;
8657 DisplayFatalError(_("internal rcmd not implemented for Unix"), 0, 1);
8661 #define INPUT_SOURCE_BUF_SIZE 8192
8670 char buf[INPUT_SOURCE_BUF_SIZE];
8675 DoInputCallback(closure, source, xid)
8680 InputSource *is = (InputSource *) closure;
8685 if (is->lineByLine) {
8686 count = read(is->fd, is->unused,
8687 INPUT_SOURCE_BUF_SIZE - (is->unused - is->buf));
8689 (is->func)(is, is->closure, is->buf, count, count ? errno : 0);
8692 is->unused += count;
8694 while (p < is->unused) {
8695 q = memchr(p, '\n', is->unused - p);
8696 if (q == NULL) break;
8698 (is->func)(is, is->closure, p, q - p, 0);
8702 while (p < is->unused) {
8707 count = read(is->fd, is->buf, INPUT_SOURCE_BUF_SIZE);
8712 (is->func)(is, is->closure, is->buf, count, error);
8716 InputSourceRef AddInputSource(pr, lineByLine, func, closure)
8723 ChildProc *cp = (ChildProc *) pr;
8725 is = (InputSource *) calloc(1, sizeof(InputSource));
8726 is->lineByLine = lineByLine;
8730 is->fd = fileno(stdin);
8732 is->kind = cp->kind;
8733 is->fd = cp->fdFrom;
8736 is->unused = is->buf;
8739 is->xid = XtAppAddInput(appContext, is->fd,
8740 (XtPointer) (XtInputReadMask),
8741 (XtInputCallbackProc) DoInputCallback,
8743 is->closure = closure;
8744 return (InputSourceRef) is;
8748 RemoveInputSource(isr)
8751 InputSource *is = (InputSource *) isr;
8753 if (is->xid == 0) return;
8754 XtRemoveInput(is->xid);
8758 int OutputToProcess(pr, message, count, outError)
8764 ChildProc *cp = (ChildProc *) pr;
8768 outCount = fwrite(message, 1, count, stdout);
8770 outCount = write(cp->fdTo, message, count);
8780 /* Output message to process, with "ms" milliseconds of delay
8781 between each character. This is needed when sending the logon
8782 script to ICC, which for some reason doesn't like the
8783 instantaneous send. */
8784 int OutputToProcessDelayed(pr, message, count, outError, msdelay)
8791 ChildProc *cp = (ChildProc *) pr;
8796 r = write(cp->fdTo, message++, 1);
8809 /**** Animation code by Hugh Fisher, DCS, ANU.
8811 Known problem: if a window overlapping the board is
8812 moved away while a piece is being animated underneath,
8813 the newly exposed area won't be updated properly.
8814 I can live with this.
8816 Known problem: if you look carefully at the animation
8817 of pieces in mono mode, they are being drawn as solid
8818 shapes without interior detail while moving. Fixing
8819 this would be a major complication for minimal return.
8822 /* Masks for XPM pieces. Black and white pieces can have
8823 different shapes, but in the interest of retaining my
8824 sanity pieces must have the same outline on both light
8825 and dark squares, and all pieces must use the same
8826 background square colors/images. */
8828 static int xpmDone = 0;
8831 CreateAnimMasks (pieceDepth)
8838 unsigned long plane;
8841 /* Need a bitmap just to get a GC with right depth */
8842 buf = XCreatePixmap(xDisplay, xBoardWindow,
8844 values.foreground = 1;
8845 values.background = 0;
8846 /* Don't use XtGetGC, not read only */
8847 maskGC = XCreateGC(xDisplay, buf,
8848 GCForeground | GCBackground, &values);
8849 XFreePixmap(xDisplay, buf);
8851 buf = XCreatePixmap(xDisplay, xBoardWindow,
8852 squareSize, squareSize, pieceDepth);
8853 values.foreground = XBlackPixel(xDisplay, xScreen);
8854 values.background = XWhitePixel(xDisplay, xScreen);
8855 bufGC = XCreateGC(xDisplay, buf,
8856 GCForeground | GCBackground, &values);
8858 for (piece = WhitePawn; piece <= BlackKing; piece++) {
8859 /* Begin with empty mask */
8860 if(!xpmDone) // [HGM] pieces: keep using existing
8861 xpmMask[piece] = XCreatePixmap(xDisplay, xBoardWindow,
8862 squareSize, squareSize, 1);
8863 XSetFunction(xDisplay, maskGC, GXclear);
8864 XFillRectangle(xDisplay, xpmMask[piece], maskGC,
8865 0, 0, squareSize, squareSize);
8867 /* Take a copy of the piece */
8872 XSetFunction(xDisplay, bufGC, GXcopy);
8873 XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % (int)BlackPawn],
8875 0, 0, squareSize, squareSize, 0, 0);
8877 /* XOR the background (light) over the piece */
8878 XSetFunction(xDisplay, bufGC, GXxor);
8880 XCopyArea(xDisplay, xpmLightSquare, buf, bufGC,
8881 0, 0, squareSize, squareSize, 0, 0);
8883 XSetForeground(xDisplay, bufGC, lightSquareColor);
8884 XFillRectangle(xDisplay, buf, bufGC, 0, 0, squareSize, squareSize);
8887 /* We now have an inverted piece image with the background
8888 erased. Construct mask by just selecting all the non-zero
8889 pixels - no need to reconstruct the original image. */
8890 XSetFunction(xDisplay, maskGC, GXor);
8892 /* Might be quicker to download an XImage and create bitmap
8893 data from it rather than this N copies per piece, but it
8894 only takes a fraction of a second and there is a much
8895 longer delay for loading the pieces. */
8896 for (n = 0; n < pieceDepth; n ++) {
8897 XCopyPlane(xDisplay, buf, xpmMask[piece], maskGC,
8898 0, 0, squareSize, squareSize,
8904 XFreePixmap(xDisplay, buf);
8905 XFreeGC(xDisplay, bufGC);
8906 XFreeGC(xDisplay, maskGC);
8910 InitAnimState (anim, info)
8912 XWindowAttributes * info;
8917 /* Each buffer is square size, same depth as window */
8918 anim->saveBuf = XCreatePixmap(xDisplay, xBoardWindow,
8919 squareSize, squareSize, info->depth);
8920 anim->newBuf = XCreatePixmap(xDisplay, xBoardWindow,
8921 squareSize, squareSize, info->depth);
8923 /* Create a plain GC for blitting */
8924 mask = GCForeground | GCBackground | GCFunction |
8925 GCPlaneMask | GCGraphicsExposures;
8926 values.foreground = XBlackPixel(xDisplay, xScreen);
8927 values.background = XWhitePixel(xDisplay, xScreen);
8928 values.function = GXcopy;
8929 values.plane_mask = AllPlanes;
8930 values.graphics_exposures = False;
8931 anim->blitGC = XCreateGC(xDisplay, xBoardWindow, mask, &values);
8933 /* Piece will be copied from an existing context at
8934 the start of each new animation/drag. */
8935 anim->pieceGC = XCreateGC(xDisplay, xBoardWindow, 0, &values);
8937 /* Outline will be a read-only copy of an existing */
8938 anim->outlineGC = None;
8944 static VariantClass old = (VariantClass) -1; // [HGM] pieces: redo every time variant changes
8945 XWindowAttributes info;
8947 if (xpmDone && gameInfo.variant == old) return;
8948 if(xpmDone) old = gameInfo.variant; // first time pieces might not be created yet
8949 XGetWindowAttributes(xDisplay, xBoardWindow, &info);
8951 InitAnimState(&game, &info);
8952 InitAnimState(&player, &info);
8954 /* For XPM pieces, we need bitmaps to use as masks. */
8956 CreateAnimMasks(info.depth);
8962 static Boolean frameWaiting;
8964 static RETSIGTYPE FrameAlarm (sig)
8967 frameWaiting = False;
8968 /* In case System-V style signals. Needed?? */
8969 signal(SIGALRM, FrameAlarm);
8976 struct itimerval delay;
8978 XSync(xDisplay, False);
8981 frameWaiting = True;
8982 signal(SIGALRM, FrameAlarm);
8983 delay.it_interval.tv_sec =
8984 delay.it_value.tv_sec = time / 1000;
8985 delay.it_interval.tv_usec =
8986 delay.it_value.tv_usec = (time % 1000) * 1000;
8987 setitimer(ITIMER_REAL, &delay, NULL);
8989 /* Ugh -- busy-wait! --tpm */
8990 while (frameWaiting);
8992 while (frameWaiting) pause();
8994 delay.it_interval.tv_sec = delay.it_value.tv_sec = 0;
8995 delay.it_interval.tv_usec = delay.it_value.tv_usec = 0;
8996 setitimer(ITIMER_REAL, &delay, NULL);
9006 XSync(xDisplay, False);
9008 usleep(time * 1000);
9013 /* Convert board position to corner of screen rect and color */
9016 ScreenSquare(column, row, pt, color)
9017 int column; int row; XPoint * pt; int * color;
9020 pt->x = lineGap + ((BOARD_WIDTH-1)-column) * (squareSize + lineGap);
9021 pt->y = lineGap + row * (squareSize + lineGap);
9023 pt->x = lineGap + column * (squareSize + lineGap);
9024 pt->y = lineGap + ((BOARD_HEIGHT-1)-row) * (squareSize + lineGap);
9026 *color = SquareColor(row, column);
9029 /* Convert window coords to square */
9032 BoardSquare(x, y, column, row)
9033 int x; int y; int * column; int * row;
9035 *column = EventToSquare(x, BOARD_WIDTH);
9036 if (flipView && *column >= 0)
9037 *column = BOARD_WIDTH - 1 - *column;
9038 *row = EventToSquare(y, BOARD_HEIGHT);
9039 if (!flipView && *row >= 0)
9040 *row = BOARD_HEIGHT - 1 - *row;
9045 #undef Max /* just in case */
9047 #define Max(a, b) ((a) > (b) ? (a) : (b))
9048 #define Min(a, b) ((a) < (b) ? (a) : (b))
9051 SetRect(rect, x, y, width, height)
9052 XRectangle * rect; int x; int y; int width; int height;
9056 rect->width = width;
9057 rect->height = height;
9060 /* Test if two frames overlap. If they do, return
9061 intersection rect within old and location of
9062 that rect within new. */
9065 Intersect(old, new, size, area, pt)
9066 XPoint * old; XPoint * new;
9067 int size; XRectangle * area; XPoint * pt;
9069 if (old->x > new->x + size || new->x > old->x + size ||
9070 old->y > new->y + size || new->y > old->y + size) {
9073 SetRect(area, Max(new->x - old->x, 0), Max(new->y - old->y, 0),
9074 size - abs(old->x - new->x), size - abs(old->y - new->y));
9075 pt->x = Max(old->x - new->x, 0);
9076 pt->y = Max(old->y - new->y, 0);
9081 /* For two overlapping frames, return the rect(s)
9082 in the old that do not intersect with the new. */
9085 CalcUpdateRects(old, new, size, update, nUpdates)
9086 XPoint * old; XPoint * new; int size;
9087 XRectangle update[]; int * nUpdates;
9091 /* If old = new (shouldn't happen) then nothing to draw */
9092 if (old->x == new->x && old->y == new->y) {
9096 /* Work out what bits overlap. Since we know the rects
9097 are the same size we don't need a full intersect calc. */
9099 /* Top or bottom edge? */
9100 if (new->y > old->y) {
9101 SetRect(&(update[count]), old->x, old->y, size, new->y - old->y);
9103 } else if (old->y > new->y) {
9104 SetRect(&(update[count]), old->x, old->y + size - (old->y - new->y),
9105 size, old->y - new->y);
9108 /* Left or right edge - don't overlap any update calculated above. */
9109 if (new->x > old->x) {
9110 SetRect(&(update[count]), old->x, Max(new->y, old->y),
9111 new->x - old->x, size - abs(new->y - old->y));
9113 } else if (old->x > new->x) {
9114 SetRect(&(update[count]), new->x + size, Max(new->y, old->y),
9115 old->x - new->x, size - abs(new->y - old->y));
9122 /* Generate a series of frame coords from start->mid->finish.
9123 The movement rate doubles until the half way point is
9124 reached, then halves back down to the final destination,
9125 which gives a nice slow in/out effect. The algorithmn
9126 may seem to generate too many intermediates for short
9127 moves, but remember that the purpose is to attract the
9128 viewers attention to the piece about to be moved and
9129 then to where it ends up. Too few frames would be less
9133 Tween(start, mid, finish, factor, frames, nFrames)
9134 XPoint * start; XPoint * mid;
9135 XPoint * finish; int factor;
9136 XPoint frames[]; int * nFrames;
9138 int fraction, n, count;
9142 /* Slow in, stepping 1/16th, then 1/8th, ... */
9144 for (n = 0; n < factor; n++)
9146 for (n = 0; n < factor; n++) {
9147 frames[count].x = start->x + (mid->x - start->x) / fraction;
9148 frames[count].y = start->y + (mid->y - start->y) / fraction;
9150 fraction = fraction / 2;
9154 frames[count] = *mid;
9157 /* Slow out, stepping 1/2, then 1/4, ... */
9159 for (n = 0; n < factor; n++) {
9160 frames[count].x = finish->x - (finish->x - mid->x) / fraction;
9161 frames[count].y = finish->y - (finish->y - mid->y) / fraction;
9163 fraction = fraction * 2;
9168 /* Draw a piece on the screen without disturbing what's there */
9171 SelectGCMask(piece, clip, outline, mask)
9172 ChessSquare piece; GC * clip; GC * outline; Pixmap * mask;
9176 /* Bitmap for piece being moved. */
9177 if (appData.monoMode) {
9178 *mask = *pieceToSolid(piece);
9179 } else if (useImages) {
9181 *mask = xpmMask[piece];
9183 *mask = ximMaskPm[piece];
9186 *mask = *pieceToSolid(piece);
9189 /* GC for piece being moved. Square color doesn't matter, but
9190 since it gets modified we make a copy of the original. */
9192 if (appData.monoMode)
9197 if (appData.monoMode)
9202 XCopyGC(xDisplay, source, 0xFFFFFFFF, *clip);
9204 /* Outline only used in mono mode and is not modified */
9206 *outline = bwPieceGC;
9208 *outline = wbPieceGC;
9212 OverlayPiece(piece, clip, outline, dest)
9213 ChessSquare piece; GC clip; GC outline; Drawable dest;
9218 /* Draw solid rectangle which will be clipped to shape of piece */
9219 XFillRectangle(xDisplay, dest, clip,
9220 0, 0, squareSize, squareSize);
9221 if (appData.monoMode)
9222 /* Also draw outline in contrasting color for black
9223 on black / white on white cases */
9224 XCopyPlane(xDisplay, *pieceToOutline(piece), dest, outline,
9225 0, 0, squareSize, squareSize, 0, 0, 1);
9227 /* Copy the piece */
9232 XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
9234 0, 0, squareSize, squareSize,
9239 /* Animate the movement of a single piece */
9242 BeginAnimation(anim, piece, startColor, start)
9250 /* The old buffer is initialised with the start square (empty) */
9251 BlankSquare(0, 0, startColor, EmptySquare, anim->saveBuf);
9252 anim->prevFrame = *start;
9254 /* The piece will be drawn using its own bitmap as a matte */
9255 SelectGCMask(piece, &anim->pieceGC, &anim->outlineGC, &mask);
9256 XSetClipMask(xDisplay, anim->pieceGC, mask);
9260 AnimationFrame(anim, frame, piece)
9265 XRectangle updates[4];
9270 /* Save what we are about to draw into the new buffer */
9271 XCopyArea(xDisplay, xBoardWindow, anim->newBuf, anim->blitGC,
9272 frame->x, frame->y, squareSize, squareSize,
9275 /* Erase bits of the previous frame */
9276 if (Intersect(&anim->prevFrame, frame, squareSize, &overlap, &pt)) {
9277 /* Where the new frame overlapped the previous,
9278 the contents in newBuf are wrong. */
9279 XCopyArea(xDisplay, anim->saveBuf, anim->newBuf, anim->blitGC,
9280 overlap.x, overlap.y,
9281 overlap.width, overlap.height,
9283 /* Repaint the areas in the old that don't overlap new */
9284 CalcUpdateRects(&anim->prevFrame, frame, squareSize, updates, &count);
9285 for (i = 0; i < count; i++)
9286 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9287 updates[i].x - anim->prevFrame.x,
9288 updates[i].y - anim->prevFrame.y,
9289 updates[i].width, updates[i].height,
9290 updates[i].x, updates[i].y);
9292 /* Easy when no overlap */
9293 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9294 0, 0, squareSize, squareSize,
9295 anim->prevFrame.x, anim->prevFrame.y);
9298 /* Save this frame for next time round */
9299 XCopyArea(xDisplay, anim->newBuf, anim->saveBuf, anim->blitGC,
9300 0, 0, squareSize, squareSize,
9302 anim->prevFrame = *frame;
9304 /* Draw piece over original screen contents, not current,
9305 and copy entire rect. Wipes out overlapping piece images. */
9306 OverlayPiece(piece, anim->pieceGC, anim->outlineGC, anim->newBuf);
9307 XCopyArea(xDisplay, anim->newBuf, xBoardWindow, anim->blitGC,
9308 0, 0, squareSize, squareSize,
9309 frame->x, frame->y);
9313 EndAnimation (anim, finish)
9317 XRectangle updates[4];
9322 /* The main code will redraw the final square, so we
9323 only need to erase the bits that don't overlap. */
9324 if (Intersect(&anim->prevFrame, finish, squareSize, &overlap, &pt)) {
9325 CalcUpdateRects(&anim->prevFrame, finish, squareSize, updates, &count);
9326 for (i = 0; i < count; i++)
9327 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9328 updates[i].x - anim->prevFrame.x,
9329 updates[i].y - anim->prevFrame.y,
9330 updates[i].width, updates[i].height,
9331 updates[i].x, updates[i].y);
9333 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9334 0, 0, squareSize, squareSize,
9335 anim->prevFrame.x, anim->prevFrame.y);
9340 FrameSequence(anim, piece, startColor, start, finish, frames, nFrames)
9342 ChessSquare piece; int startColor;
9343 XPoint * start; XPoint * finish;
9344 XPoint frames[]; int nFrames;
9348 BeginAnimation(anim, piece, startColor, start);
9349 for (n = 0; n < nFrames; n++) {
9350 AnimationFrame(anim, &(frames[n]), piece);
9351 FrameDelay(appData.animSpeed);
9353 EndAnimation(anim, finish);
9356 /* Main control logic for deciding what to animate and how */
9359 AnimateMove(board, fromX, fromY, toX, toY)
9368 XPoint start, finish, mid;
9369 XPoint frames[kFactor * 2 + 1];
9370 int nFrames, startColor, endColor;
9372 /* Are we animating? */
9373 if (!appData.animate || appData.blindfold)
9376 if(board[toY][toX] == WhiteRook && board[fromY][fromX] == WhiteKing ||
9377 board[toY][toX] == BlackRook && board[fromY][fromX] == BlackKing)
9378 return; // [HGM] FRC: no animtion of FRC castlings, as to-square is not true to-square
9380 if (fromY < 0 || fromX < 0 || toX < 0 || toY < 0) return;
9381 piece = board[fromY][fromX];
9382 if (piece >= EmptySquare) return;
9387 hop = (piece == WhiteKnight || piece == BlackKnight);
9390 if (appData.debugMode) {
9391 fprintf(debugFP, hop ? _("AnimateMove: piece %d hops from %d,%d to %d,%d \n") :
9392 _("AnimateMove: piece %d slides from %d,%d to %d,%d \n"),
9393 piece, fromX, fromY, toX, toY); }
9395 ScreenSquare(fromX, fromY, &start, &startColor);
9396 ScreenSquare(toX, toY, &finish, &endColor);
9399 /* Knight: make diagonal movement then straight */
9400 if (abs(toY - fromY) < abs(toX - fromX)) {
9401 mid.x = start.x + (finish.x - start.x) / 2;
9405 mid.y = start.y + (finish.y - start.y) / 2;
9408 mid.x = start.x + (finish.x - start.x) / 2;
9409 mid.y = start.y + (finish.y - start.y) / 2;
9412 /* Don't use as many frames for very short moves */
9413 if (abs(toY - fromY) + abs(toX - fromX) <= 2)
9414 Tween(&start, &mid, &finish, kFactor - 1, frames, &nFrames);
9416 Tween(&start, &mid, &finish, kFactor, frames, &nFrames);
9417 FrameSequence(&game, piece, startColor, &start, &finish, frames, nFrames);
9419 /* Be sure end square is redrawn */
9420 damage[toY][toX] = True;
9424 DragPieceBegin(x, y)
9427 int boardX, boardY, color;
9430 /* Are we animating? */
9431 if (!appData.animateDragging || appData.blindfold)
9434 /* Figure out which square we start in and the
9435 mouse position relative to top left corner. */
9436 BoardSquare(x, y, &boardX, &boardY);
9437 player.startBoardX = boardX;
9438 player.startBoardY = boardY;
9439 ScreenSquare(boardX, boardY, &corner, &color);
9440 player.startSquare = corner;
9441 player.startColor = color;
9443 /* Start from exactly where the piece is. This can be confusing
9444 if you start dragging far from the center of the square; most
9445 or all of the piece can be over a different square from the one
9446 the mouse pointer is in. */
9447 player.mouseDelta.x = x - corner.x;
9448 player.mouseDelta.y = y - corner.y;
9450 /* As soon as we start dragging, the piece will jump slightly to
9451 be centered over the mouse pointer. */
9452 player.mouseDelta.x = squareSize/2;
9453 player.mouseDelta.y = squareSize/2;
9455 /* Initialise animation */
9456 player.dragPiece = PieceForSquare(boardX, boardY);
9458 if (player.dragPiece >= 0 && player.dragPiece < EmptySquare) {
9459 player.dragActive = True;
9460 BeginAnimation(&player, player.dragPiece, color, &corner);
9461 /* Mark this square as needing to be redrawn. Note that
9462 we don't remove the piece though, since logically (ie
9463 as seen by opponent) the move hasn't been made yet. */
9464 if(boardX == BOARD_RGHT+1 && PieceForSquare(boardX-1, boardY) > 1 ||
9465 boardX == BOARD_LEFT-2 && PieceForSquare(boardX+1, boardY) > 1)
9466 XCopyArea(xDisplay, xBoardWindow, player.saveBuf, player.blitGC,
9467 corner.x, corner.y, squareSize, squareSize,
9468 0, 0); // [HGM] zh: unstack in stead of grab
9469 damage[boardY][boardX] = True;
9471 player.dragActive = False;
9481 /* Are we animating? */
9482 if (!appData.animateDragging || appData.blindfold)
9486 if (! player.dragActive)
9488 /* Move piece, maintaining same relative position
9489 of mouse within square */
9490 corner.x = x - player.mouseDelta.x;
9491 corner.y = y - player.mouseDelta.y;
9492 AnimationFrame(&player, &corner, player.dragPiece);
9494 if (appData.highlightDragging) {
9496 BoardSquare(x, y, &boardX, &boardY);
9497 SetHighlights(fromX, fromY, boardX, boardY);
9506 int boardX, boardY, color;
9509 /* Are we animating? */
9510 if (!appData.animateDragging || appData.blindfold)
9514 if (! player.dragActive)
9516 /* Last frame in sequence is square piece is
9517 placed on, which may not match mouse exactly. */
9518 BoardSquare(x, y, &boardX, &boardY);
9519 ScreenSquare(boardX, boardY, &corner, &color);
9520 EndAnimation(&player, &corner);
9522 /* Be sure end square is redrawn */
9523 damage[boardY][boardX] = True;
9525 /* This prevents weird things happening with fast successive
9526 clicks which on my Sun at least can cause motion events
9527 without corresponding press/release. */
9528 player.dragActive = False;
9531 /* Handle expose event while piece being dragged */
9536 if (!player.dragActive || appData.blindfold)
9539 /* What we're doing: logically, the move hasn't been made yet,
9540 so the piece is still in it's original square. But visually
9541 it's being dragged around the board. So we erase the square
9542 that the piece is on and draw it at the last known drag point. */
9543 BlankSquare(player.startSquare.x, player.startSquare.y,
9544 player.startColor, EmptySquare, xBoardWindow);
9545 AnimationFrame(&player, &player.prevFrame, player.dragPiece);
9546 damage[player.startBoardY][player.startBoardX] = TRUE;
9550 SetProgramStats( FrontEndProgramStats * stats )
9553 // [HGM] done, but perhaps backend should call this directly?
9554 EngineOutputUpdate( stats );