2 * xboard.c -- X front end for XBoard
3 * $Id: xboard.c,v 2.2 2003/11/06 07:22:14 mann Exp $
5 * Copyright 1991 by Digital Equipment Corporation, Maynard,
6 * Massachusetts. Enhancements Copyright
7 * 1992-2001,2002,2003,2004,2005,2006,2007,2008,2009 Free Software
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 xpmPieceBitmap[4][(int)BlackPawn]; /* LL, LD, DL, DD */
499 Pixmap xpmLightSquare, xpmDarkSquare, xpmJailSquare;
500 int useImages, useImageSqs;
501 XImage *ximPieceBitmap[4][(int)BlackPawn]; /* LL, LD, DL, DD */
502 Pixmap ximMaskPm[(int)BlackPawn]; /* clipmasks, used for XIM pieces */
503 XImage *ximLightSquare, *ximDarkSquare;
506 #define pieceToSolid(piece) &pieceBitmap[SOLID][((int)(piece)) % (int)BlackPawn]
507 #define pieceToOutline(piece) &pieceBitmap[OUTLINE][((int)(piece)) % (int)BlackPawn]
509 #define White(piece) ((int)(piece) < (int)BlackPawn)
511 /* Variables for doing smooth animation. This whole thing
512 would be much easier if the board was double-buffered,
513 but that would require a fairly major rewrite. */
518 GC blitGC, pieceGC, outlineGC;
519 XPoint startSquare, prevFrame, mouseDelta;
523 int startBoardX, startBoardY;
526 /* There can be two pieces being animated at once: a player
527 can begin dragging a piece before the remote opponent has moved. */
529 static AnimState game, player;
531 /* Bitmaps for use as masks when drawing XPM pieces.
532 Need one for each black and white piece. */
533 static Pixmap xpmMask[BlackKing + 1];
535 /* This magic number is the number of intermediate frames used
536 in each half of the animation. For short moves it's reduced
537 by 1. The total number of frames will be factor * 2 + 1. */
540 SizeDefaults sizeDefaults[] = SIZE_DEFAULTS;
542 MenuItem fileMenu[] = {
543 {N_("New Game"), ResetProc},
544 {N_("New Shuffle Game ..."), ShuffleMenuProc},
545 {N_("New Variant ..."), NewVariantProc}, // [HGM] variant: not functional yet
546 {"----", NothingProc},
547 {N_("Load Game"), LoadGameProc},
548 {N_("Load Next Game"), LoadNextGameProc},
549 {N_("Load Previous Game"), LoadPrevGameProc},
550 {N_("Reload Same Game"), ReloadGameProc},
551 {N_("Save Game"), SaveGameProc},
552 {"----", NothingProc},
553 {N_("Copy Game"), CopyGameProc},
554 {N_("Paste Game"), PasteGameProc},
555 {"----", NothingProc},
556 {N_("Load Position"), LoadPositionProc},
557 {N_("Load Next Position"), LoadNextPositionProc},
558 {N_("Load Previous Position"), LoadPrevPositionProc},
559 {N_("Reload Same Position"), ReloadPositionProc},
560 {N_("Save Position"), SavePositionProc},
561 {"----", NothingProc},
562 {N_("Copy Position"), CopyPositionProc},
563 {N_("Paste Position"), PastePositionProc},
564 {"----", NothingProc},
565 {N_("Mail Move"), MailMoveProc},
566 {N_("Reload CMail Message"), ReloadCmailMsgProc},
567 {"----", NothingProc},
568 {N_("Exit"), QuitProc},
572 MenuItem modeMenu[] = {
573 {N_("Machine White"), MachineWhiteProc},
574 {N_("Machine Black"), MachineBlackProc},
575 {N_("Two Machines"), TwoMachinesProc},
576 {N_("Analysis Mode"), AnalyzeModeProc},
577 {N_("Analyze File"), AnalyzeFileProc },
578 {N_("ICS Client"), IcsClientProc},
579 {N_("Edit Game"), EditGameProc},
580 {N_("Edit Position"), EditPositionProc},
581 {N_("Training"), TrainingProc},
582 {"----", NothingProc},
583 {N_("Show Engine Output"), EngineOutputProc},
584 {N_("Show Evaluation Graph"), NothingProc}, // [HGM] evalgr: not functional yet
585 {N_("Show Game List"), ShowGameListProc},
586 {"Show Move History", HistoryShowProc}, // [HGM] hist: activate 4.2.7 code
587 {"----", NothingProc},
588 {N_("Edit Tags"), EditTagsProc},
589 {N_("Edit Comment"), EditCommentProc},
590 {N_("ICS Input Box"), IcsInputBoxProc},
591 {N_("Pause"), PauseProc},
595 MenuItem actionMenu[] = {
596 {N_("Accept"), AcceptProc},
597 {N_("Decline"), DeclineProc},
598 {N_("Rematch"), RematchProc},
599 {"----", NothingProc},
600 {N_("Call Flag"), CallFlagProc},
601 {N_("Draw"), DrawProc},
602 {N_("Adjourn"), AdjournProc},
603 {N_("Abort"), AbortProc},
604 {N_("Resign"), ResignProc},
605 {"----", NothingProc},
606 {N_("Stop Observing"), StopObservingProc},
607 {N_("Stop Examining"), StopExaminingProc},
608 {"----", NothingProc},
609 {N_("Adjudicate to White"), AdjuWhiteProc},
610 {N_("Adjudicate to Black"), AdjuBlackProc},
611 {N_("Adjudicate Draw"), AdjuDrawProc},
615 MenuItem stepMenu[] = {
616 {N_("Backward"), BackwardProc},
617 {N_("Forward"), ForwardProc},
618 {N_("Back to Start"), ToStartProc},
619 {N_("Forward to End"), ToEndProc},
620 {N_("Revert"), RevertProc},
621 {N_("Truncate Game"), TruncateGameProc},
622 {"----", NothingProc},
623 {N_("Move Now"), MoveNowProc},
624 {N_("Retract Move"), RetractMoveProc},
628 MenuItem optionsMenu[] = {
629 {N_("Flip View"), FlipViewProc},
630 {"----", NothingProc},
631 {N_("Adjudications ..."), EngineMenuProc},
632 {N_("General Settings ..."), UciMenuProc},
633 {N_("Engine #1 Settings ..."), FirstSettingsProc},
634 {N_("Engine #2 Settings ..."), SecondSettingsProc},
635 {N_("Time Control ..."), TimeControlProc},
636 {"----", NothingProc},
637 {N_("Always Queen"), AlwaysQueenProc},
638 {N_("Animate Dragging"), AnimateDraggingProc},
639 {N_("Animate Moving"), AnimateMovingProc},
640 {N_("Auto Comment"), AutocommProc},
641 {N_("Auto Flag"), AutoflagProc},
642 {N_("Auto Flip View"), AutoflipProc},
643 {N_("Auto Observe"), AutobsProc},
644 {N_("Auto Raise Board"), AutoraiseProc},
645 {N_("Auto Save"), AutosaveProc},
646 {N_("Blindfold"), BlindfoldProc},
647 {N_("Flash Moves"), FlashMovesProc},
648 {N_("Get Move List"), GetMoveListProc},
650 {N_("Highlight Dragging"), HighlightDraggingProc},
652 {N_("Highlight Last Move"), HighlightLastMoveProc},
653 {N_("Move Sound"), MoveSoundProc},
654 {N_("ICS Alarm"), IcsAlarmProc},
655 {N_("Old Save Style"), OldSaveStyleProc},
656 {N_("Periodic Updates"), PeriodicUpdatesProc},
657 {N_("Ponder Next Move"), PonderNextMoveProc},
658 {N_("Popup Exit Message"), PopupExitMessageProc},
659 {N_("Popup Move Errors"), PopupMoveErrorsProc},
660 {N_("Premove"), PremoveProc},
661 {N_("Quiet Play"), QuietPlayProc},
662 {N_("Show Coords"), ShowCoordsProc},
663 {N_("Hide Thinking"), HideThinkingProc},
664 {N_("Test Legality"), TestLegalityProc},
668 MenuItem helpMenu[] = {
669 {N_("Info XBoard"), InfoProc},
670 {N_("Man XBoard"), ManProc},
671 {"----", NothingProc},
672 {N_("Hint"), HintProc},
673 {N_("Book"), BookProc},
674 {"----", NothingProc},
675 {N_("About XBoard"), AboutProc},
680 {N_("File"), fileMenu},
681 {N_("Mode"), modeMenu},
682 {N_("Action"), actionMenu},
683 {N_("Step"), stepMenu},
684 {N_("Options"), optionsMenu},
685 {N_("Help"), helpMenu},
689 #define PAUSE_BUTTON N_("P")
690 MenuItem buttonBar[] = {
693 {PAUSE_BUTTON, PauseProc},
699 #define PIECE_MENU_SIZE 11
700 String pieceMenuStrings[2][PIECE_MENU_SIZE] = {
701 { N_("White"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
702 N_("Queen"), N_("King"), "----", N_("Empty square"), N_("Clear board") },
703 { N_("Black"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
704 N_("Queen"), N_("King"), "----", N_("Empty square"), N_("Clear board") },
706 /* must be in same order as PieceMenuStrings! */
707 ChessSquare pieceMenuTranslation[2][PIECE_MENU_SIZE] = {
708 { WhitePlay, (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
709 WhiteRook, WhiteQueen, WhiteKing,
710 (ChessSquare) 0, EmptySquare, ClearBoard },
711 { BlackPlay, (ChessSquare) 0, BlackPawn, BlackKnight, BlackBishop,
712 BlackRook, BlackQueen, BlackKing,
713 (ChessSquare) 0, EmptySquare, ClearBoard },
716 #define DROP_MENU_SIZE 6
717 String dropMenuStrings[DROP_MENU_SIZE] = {
718 "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"), N_("Queen")
720 /* must be in same order as PieceMenuStrings! */
721 ChessSquare dropMenuTranslation[DROP_MENU_SIZE] = {
722 (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
723 WhiteRook, WhiteQueen
731 DropMenuEnables dmEnables[] = {
749 { XtNborderWidth, 0 },
750 { XtNdefaultDistance, 0 },
754 { XtNborderWidth, 0 },
755 { XtNresizable, (XtArgVal) True },
759 { XtNborderWidth, 0 },
765 { XtNjustify, (XtArgVal) XtJustifyRight },
766 { XtNlabel, (XtArgVal) "..." },
767 { XtNresizable, (XtArgVal) True },
768 { XtNresize, (XtArgVal) False }
771 Arg messageArgs[] = {
772 { XtNjustify, (XtArgVal) XtJustifyLeft },
773 { XtNlabel, (XtArgVal) "..." },
774 { XtNresizable, (XtArgVal) True },
775 { XtNresize, (XtArgVal) False }
779 { XtNborderWidth, 0 },
780 { XtNjustify, (XtArgVal) XtJustifyLeft }
783 XtResource clientResources[] = {
784 { "whitePieceColor", "whitePieceColor", XtRString, sizeof(String),
785 XtOffset(AppDataPtr, whitePieceColor), XtRString,
787 { "blackPieceColor", "blackPieceColor", XtRString, sizeof(String),
788 XtOffset(AppDataPtr, blackPieceColor), XtRString,
790 { "lightSquareColor", "lightSquareColor", XtRString,
791 sizeof(String), XtOffset(AppDataPtr, lightSquareColor),
792 XtRString, LIGHT_SQUARE_COLOR },
793 { "darkSquareColor", "darkSquareColor", XtRString, sizeof(String),
794 XtOffset(AppDataPtr, darkSquareColor), XtRString,
796 { "highlightSquareColor", "highlightSquareColor", XtRString,
797 sizeof(String), XtOffset(AppDataPtr, highlightSquareColor),
798 XtRString, HIGHLIGHT_SQUARE_COLOR },
799 { "premoveHighlightColor", "premoveHighlightColor", XtRString,
800 sizeof(String), XtOffset(AppDataPtr, premoveHighlightColor),
801 XtRString, PREMOVE_HIGHLIGHT_COLOR },
802 { "movesPerSession", "movesPerSession", XtRInt, sizeof(int),
803 XtOffset(AppDataPtr, movesPerSession), XtRImmediate,
804 (XtPointer) MOVES_PER_SESSION },
805 { "timeIncrement", "timeIncrement", XtRInt, sizeof(int),
806 XtOffset(AppDataPtr, timeIncrement), XtRImmediate,
807 (XtPointer) TIME_INCREMENT },
808 { "initString", "initString", XtRString, sizeof(String),
809 XtOffset(AppDataPtr, initString), XtRString, INIT_STRING },
810 { "secondInitString", "secondInitString", XtRString, sizeof(String),
811 XtOffset(AppDataPtr, secondInitString), XtRString, INIT_STRING },
812 { "firstComputerString", "firstComputerString", XtRString,
813 sizeof(String), XtOffset(AppDataPtr, firstComputerString), XtRString,
815 { "secondComputerString", "secondComputerString", XtRString,
816 sizeof(String), XtOffset(AppDataPtr, secondComputerString), XtRString,
818 { "firstChessProgram", "firstChessProgram", XtRString,
819 sizeof(String), XtOffset(AppDataPtr, firstChessProgram),
820 XtRString, FIRST_CHESS_PROGRAM },
821 { "secondChessProgram", "secondChessProgram", XtRString,
822 sizeof(String), XtOffset(AppDataPtr, secondChessProgram),
823 XtRString, SECOND_CHESS_PROGRAM },
824 { "firstPlaysBlack", "firstPlaysBlack", XtRBoolean,
825 sizeof(Boolean), XtOffset(AppDataPtr, firstPlaysBlack),
826 XtRImmediate, (XtPointer) False },
827 { "noChessProgram", "noChessProgram", XtRBoolean,
828 sizeof(Boolean), XtOffset(AppDataPtr, noChessProgram),
829 XtRImmediate, (XtPointer) False },
830 { "firstHost", "firstHost", XtRString, sizeof(String),
831 XtOffset(AppDataPtr, firstHost), XtRString, FIRST_HOST },
832 { "secondHost", "secondHost", XtRString, sizeof(String),
833 XtOffset(AppDataPtr, secondHost), XtRString, SECOND_HOST },
834 { "firstDirectory", "firstDirectory", XtRString, sizeof(String),
835 XtOffset(AppDataPtr, firstDirectory), XtRString, "." },
836 { "secondDirectory", "secondDirectory", XtRString, sizeof(String),
837 XtOffset(AppDataPtr, secondDirectory), XtRString, "." },
838 { "bitmapDirectory", "bitmapDirectory", XtRString,
839 sizeof(String), XtOffset(AppDataPtr, bitmapDirectory),
841 { "remoteShell", "remoteShell", XtRString, sizeof(String),
842 XtOffset(AppDataPtr, remoteShell), XtRString, REMOTE_SHELL },
843 { "remoteUser", "remoteUser", XtRString, sizeof(String),
844 XtOffset(AppDataPtr, remoteUser), XtRString, "" },
845 { "timeDelay", "timeDelay", XtRFloat, sizeof(float),
846 XtOffset(AppDataPtr, timeDelay), XtRString,
847 (XtPointer) TIME_DELAY_QUOTE },
848 { "timeControl", "timeControl", XtRString, sizeof(String),
849 XtOffset(AppDataPtr, timeControl), XtRString,
850 (XtPointer) TIME_CONTROL },
851 { "internetChessServerMode", "internetChessServerMode",
852 XtRBoolean, sizeof(Boolean),
853 XtOffset(AppDataPtr, icsActive), XtRImmediate,
855 { "internetChessServerHost", "internetChessServerHost",
856 XtRString, sizeof(String),
857 XtOffset(AppDataPtr, icsHost),
858 XtRString, (XtPointer) ICS_HOST },
859 { "internetChessServerPort", "internetChessServerPort",
860 XtRString, sizeof(String),
861 XtOffset(AppDataPtr, icsPort), XtRString,
862 (XtPointer) ICS_PORT },
863 { "internetChessServerCommPort", "internetChessServerCommPort",
864 XtRString, sizeof(String),
865 XtOffset(AppDataPtr, icsCommPort), XtRString,
867 { "internetChessServerLogonScript", "internetChessServerLogonScript",
868 XtRString, sizeof(String),
869 XtOffset(AppDataPtr, icsLogon), XtRString,
871 { "internetChessServerHelper", "internetChessServerHelper",
872 XtRString, sizeof(String),
873 XtOffset(AppDataPtr, icsHelper), XtRString, "" },
874 { "internetChessServerInputBox", "internetChessServerInputBox",
875 XtRBoolean, sizeof(Boolean),
876 XtOffset(AppDataPtr, icsInputBox), XtRImmediate,
878 { "icsAlarm", "icsAlarm",
879 XtRBoolean, sizeof(Boolean),
880 XtOffset(AppDataPtr, icsAlarm), XtRImmediate,
882 { "icsAlarmTime", "icsAlarmTime",
884 XtOffset(AppDataPtr, icsAlarmTime), XtRImmediate,
886 { "useTelnet", "useTelnet", XtRBoolean, sizeof(Boolean),
887 XtOffset(AppDataPtr, useTelnet), XtRImmediate,
889 { "telnetProgram", "telnetProgram", XtRString, sizeof(String),
890 XtOffset(AppDataPtr, telnetProgram), XtRString, TELNET_PROGRAM },
891 { "gateway", "gateway", XtRString, sizeof(String),
892 XtOffset(AppDataPtr, gateway), XtRString, "" },
893 { "loadGameFile", "loadGameFile", XtRString, sizeof(String),
894 XtOffset(AppDataPtr, loadGameFile), XtRString, "" },
895 { "loadGameIndex", "loadGameIndex",
897 XtOffset(AppDataPtr, loadGameIndex), XtRImmediate,
899 { "saveGameFile", "saveGameFile", XtRString, sizeof(String),
900 XtOffset(AppDataPtr, saveGameFile), XtRString, "" },
901 { "autoRaiseBoard", "autoRaiseBoard", XtRBoolean,
902 sizeof(Boolean), XtOffset(AppDataPtr, autoRaiseBoard),
903 XtRImmediate, (XtPointer) True },
904 { "autoSaveGames", "autoSaveGames", XtRBoolean,
905 sizeof(Boolean), XtOffset(AppDataPtr, autoSaveGames),
906 XtRImmediate, (XtPointer) False },
907 { "blindfold", "blindfold", XtRBoolean,
908 sizeof(Boolean), XtOffset(AppDataPtr, blindfold),
909 XtRImmediate, (XtPointer) False },
910 { "loadPositionFile", "loadPositionFile", XtRString,
911 sizeof(String), XtOffset(AppDataPtr, loadPositionFile),
913 { "loadPositionIndex", "loadPositionIndex",
915 XtOffset(AppDataPtr, loadPositionIndex), XtRImmediate,
917 { "savePositionFile", "savePositionFile", XtRString,
918 sizeof(String), XtOffset(AppDataPtr, savePositionFile),
920 { "matchMode", "matchMode", XtRBoolean, sizeof(Boolean),
921 XtOffset(AppDataPtr, matchMode), XtRImmediate, (XtPointer) False },
922 { "matchGames", "matchGames", XtRInt, sizeof(int),
923 XtOffset(AppDataPtr, matchGames), XtRImmediate,
925 { "monoMode", "monoMode", XtRBoolean, sizeof(Boolean),
926 XtOffset(AppDataPtr, monoMode), XtRImmediate,
928 { "debugMode", "debugMode", XtRBoolean, sizeof(Boolean),
929 XtOffset(AppDataPtr, debugMode), XtRImmediate,
931 { "clockMode", "clockMode", XtRBoolean, sizeof(Boolean),
932 XtOffset(AppDataPtr, clockMode), XtRImmediate,
934 { "boardSize", "boardSize", XtRString, sizeof(String),
935 XtOffset(AppDataPtr, boardSize), XtRString, "" },
936 { "searchTime", "searchTime", XtRString, sizeof(String),
937 XtOffset(AppDataPtr, searchTime), XtRString,
939 { "searchDepth", "searchDepth", XtRInt, sizeof(int),
940 XtOffset(AppDataPtr, searchDepth), XtRImmediate,
942 { "showCoords", "showCoords", XtRBoolean, sizeof(Boolean),
943 XtOffset(AppDataPtr, showCoords), XtRImmediate,
945 { "showJail", "showJail", XtRInt, sizeof(int),
946 XtOffset(AppDataPtr, showJail), XtRImmediate,
948 { "showThinking", "showThinking", XtRBoolean, sizeof(Boolean),
949 XtOffset(AppDataPtr, showThinking), XtRImmediate,
951 { "ponderNextMove", "ponderNextMove", XtRBoolean, sizeof(Boolean),
952 XtOffset(AppDataPtr, ponderNextMove), XtRImmediate,
954 { "periodicUpdates", "periodicUpdates", XtRBoolean, sizeof(Boolean),
955 XtOffset(AppDataPtr, periodicUpdates), XtRImmediate,
957 { "clockFont", "clockFont", XtRString, sizeof(String),
958 XtOffset(AppDataPtr, clockFont), XtRString, CLOCK_FONT },
959 { "coordFont", "coordFont", XtRString, sizeof(String),
960 XtOffset(AppDataPtr, coordFont), XtRString, COORD_FONT },
961 { "font", "font", XtRString, sizeof(String),
962 XtOffset(AppDataPtr, font), XtRString, DEFAULT_FONT },
963 { "ringBellAfterMoves", "ringBellAfterMoves",
964 XtRBoolean, sizeof(Boolean),
965 XtOffset(AppDataPtr, ringBellAfterMoves),
966 XtRImmediate, (XtPointer) False },
967 { "autoCallFlag", "autoCallFlag", XtRBoolean,
968 sizeof(Boolean), XtOffset(AppDataPtr, autoCallFlag),
969 XtRImmediate, (XtPointer) False },
970 { "autoFlipView", "autoFlipView", XtRBoolean,
971 sizeof(Boolean), XtOffset(AppDataPtr, autoFlipView),
972 XtRImmediate, (XtPointer) True },
973 { "autoObserve", "autoObserve", XtRBoolean,
974 sizeof(Boolean), XtOffset(AppDataPtr, autoObserve),
975 XtRImmediate, (XtPointer) False },
976 { "autoComment", "autoComment", XtRBoolean,
977 sizeof(Boolean), XtOffset(AppDataPtr, autoComment),
978 XtRImmediate, (XtPointer) False },
979 { "getMoveList", "getMoveList", XtRBoolean,
980 sizeof(Boolean), XtOffset(AppDataPtr, getMoveList),
981 XtRImmediate, (XtPointer) True },
983 { "highlightDragging", "highlightDragging", XtRBoolean,
984 sizeof(Boolean), XtOffset(AppDataPtr, highlightDragging),
985 XtRImmediate, (XtPointer) False },
987 { "highlightLastMove", "highlightLastMove", XtRBoolean,
988 sizeof(Boolean), XtOffset(AppDataPtr, highlightLastMove),
989 XtRImmediate, (XtPointer) False },
990 { "premove", "premove", XtRBoolean,
991 sizeof(Boolean), XtOffset(AppDataPtr, premove),
992 XtRImmediate, (XtPointer) True },
993 { "testLegality", "testLegality", XtRBoolean,
994 sizeof(Boolean), XtOffset(AppDataPtr, testLegality),
995 XtRImmediate, (XtPointer) True },
996 { "flipView", "flipView", XtRBoolean,
997 sizeof(Boolean), XtOffset(AppDataPtr, flipView),
998 XtRImmediate, (XtPointer) False },
999 { "cmail", "cmailGameName", XtRString, sizeof(String),
1000 XtOffset(AppDataPtr, cmailGameName), XtRString, "" },
1001 { "alwaysPromoteToQueen", "alwaysPromoteToQueen", XtRBoolean,
1002 sizeof(Boolean), XtOffset(AppDataPtr, alwaysPromoteToQueen),
1003 XtRImmediate, (XtPointer) False },
1004 { "oldSaveStyle", "oldSaveStyle", XtRBoolean,
1005 sizeof(Boolean), XtOffset(AppDataPtr, oldSaveStyle),
1006 XtRImmediate, (XtPointer) False },
1007 { "quietPlay", "quietPlay", XtRBoolean,
1008 sizeof(Boolean), XtOffset(AppDataPtr, quietPlay),
1009 XtRImmediate, (XtPointer) False },
1010 { "titleInWindow", "titleInWindow", XtRBoolean,
1011 sizeof(Boolean), XtOffset(AppDataPtr, titleInWindow),
1012 XtRImmediate, (XtPointer) False },
1013 { "localLineEditing", "localLineEditing", XtRBoolean,
1014 sizeof(Boolean), XtOffset(AppDataPtr, localLineEditing),
1015 XtRImmediate, (XtPointer) True }, /* not implemented, must be True */
1017 { "zippyTalk", "zippyTalk", XtRBoolean,
1018 sizeof(Boolean), XtOffset(AppDataPtr, zippyTalk),
1019 XtRImmediate, (XtPointer) ZIPPY_TALK },
1020 { "zippyPlay", "zippyPlay", XtRBoolean,
1021 sizeof(Boolean), XtOffset(AppDataPtr, zippyPlay),
1022 XtRImmediate, (XtPointer) ZIPPY_PLAY },
1023 { "zippyLines", "zippyLines", XtRString, sizeof(String),
1024 XtOffset(AppDataPtr, zippyLines), XtRString, ZIPPY_LINES },
1025 { "zippyPinhead", "zippyPinhead", XtRString, sizeof(String),
1026 XtOffset(AppDataPtr, zippyPinhead), XtRString, ZIPPY_PINHEAD },
1027 { "zippyPassword", "zippyPassword", XtRString, sizeof(String),
1028 XtOffset(AppDataPtr, zippyPassword), XtRString, ZIPPY_PASSWORD },
1029 { "zippyPassword2", "zippyPassword2", XtRString, sizeof(String),
1030 XtOffset(AppDataPtr, zippyPassword2), XtRString, ZIPPY_PASSWORD2 },
1031 { "zippyWrongPassword", "zippyWrongPassword", XtRString, sizeof(String),
1032 XtOffset(AppDataPtr, zippyWrongPassword), XtRString,
1033 ZIPPY_WRONG_PASSWORD },
1034 { "zippyAcceptOnly", "zippyAcceptOnly", XtRString, sizeof(String),
1035 XtOffset(AppDataPtr, zippyAcceptOnly), XtRString, ZIPPY_ACCEPT_ONLY },
1036 { "zippyUseI", "zippyUseI", XtRBoolean,
1037 sizeof(Boolean), XtOffset(AppDataPtr, zippyUseI),
1038 XtRImmediate, (XtPointer) ZIPPY_USE_I },
1039 { "zippyBughouse", "zippyBughouse", XtRInt,
1040 sizeof(int), XtOffset(AppDataPtr, zippyBughouse),
1041 XtRImmediate, (XtPointer) ZIPPY_BUGHOUSE },
1042 { "zippyNoplayCrafty", "zippyNoplayCrafty", XtRBoolean,
1043 sizeof(Boolean), XtOffset(AppDataPtr, zippyNoplayCrafty),
1044 XtRImmediate, (XtPointer) ZIPPY_NOPLAY_CRAFTY },
1045 { "zippyGameEnd", "zippyGameEnd", XtRString, sizeof(String),
1046 XtOffset(AppDataPtr, zippyGameEnd), XtRString, ZIPPY_GAME_END },
1047 { "zippyGameStart", "zippyGameStart", XtRString, sizeof(String),
1048 XtOffset(AppDataPtr, zippyGameStart), XtRString, ZIPPY_GAME_START },
1049 { "zippyAdjourn", "zippyAdjourn", XtRBoolean,
1050 sizeof(Boolean), XtOffset(AppDataPtr, zippyAdjourn),
1051 XtRImmediate, (XtPointer) ZIPPY_ADJOURN },
1052 { "zippyAbort", "zippyAbort", XtRBoolean,
1053 sizeof(Boolean), XtOffset(AppDataPtr, zippyAbort),
1054 XtRImmediate, (XtPointer) ZIPPY_ABORT },
1055 { "zippyVariants", "zippyVariants", XtRString, sizeof(String),
1056 XtOffset(AppDataPtr, zippyVariants), XtRString, ZIPPY_VARIANTS },
1057 { "zippyMaxGames", "zippyMaxGames", XtRInt, sizeof(int),
1058 XtOffset(AppDataPtr, zippyMaxGames), XtRImmediate,
1059 (XtPointer) ZIPPY_MAX_GAMES },
1060 { "zippyReplayTimeout", "zippyReplayTimeout", XtRInt, sizeof(int),
1061 XtOffset(AppDataPtr, zippyReplayTimeout), XtRImmediate,
1062 (XtPointer) ZIPPY_REPLAY_TIMEOUT },
1063 { "zippyShortGame", "zippyShortGame", XtRInt, sizeof(int),
1064 XtOffset(AppDataPtr, zippyShortGame), XtRImmediate,
1067 { "flashCount", "flashCount", XtRInt, sizeof(int),
1068 XtOffset(AppDataPtr, flashCount), XtRImmediate,
1069 (XtPointer) FLASH_COUNT },
1070 { "flashRate", "flashRate", XtRInt, sizeof(int),
1071 XtOffset(AppDataPtr, flashRate), XtRImmediate,
1072 (XtPointer) FLASH_RATE },
1073 { "pixmapDirectory", "pixmapDirectory", XtRString,
1074 sizeof(String), XtOffset(AppDataPtr, pixmapDirectory),
1076 { "msLoginDelay", "msLoginDelay", XtRInt, sizeof(int),
1077 XtOffset(AppDataPtr, msLoginDelay), XtRImmediate,
1078 (XtPointer) MS_LOGIN_DELAY },
1079 { "colorizeMessages", "colorizeMessages", XtRBoolean,
1080 sizeof(Boolean), XtOffset(AppDataPtr, colorize),
1081 XtRImmediate, (XtPointer) False },
1082 { "colorShout", "colorShout", XtRString,
1083 sizeof(String), XtOffset(AppDataPtr, colorShout),
1084 XtRString, COLOR_SHOUT },
1085 { "colorSShout", "colorSShout", XtRString,
1086 sizeof(String), XtOffset(AppDataPtr, colorSShout),
1087 XtRString, COLOR_SSHOUT },
1088 { "colorChannel1", "colorChannel1", XtRString,
1089 sizeof(String), XtOffset(AppDataPtr, colorChannel1),
1090 XtRString, COLOR_CHANNEL1 },
1091 { "colorChannel", "colorChannel", XtRString,
1092 sizeof(String), XtOffset(AppDataPtr, colorChannel),
1093 XtRString, COLOR_CHANNEL },
1094 { "colorKibitz", "colorKibitz", XtRString,
1095 sizeof(String), XtOffset(AppDataPtr, colorKibitz),
1096 XtRString, COLOR_KIBITZ },
1097 { "colorTell", "colorTell", XtRString,
1098 sizeof(String), XtOffset(AppDataPtr, colorTell),
1099 XtRString, COLOR_TELL },
1100 { "colorChallenge", "colorChallenge", XtRString,
1101 sizeof(String), XtOffset(AppDataPtr, colorChallenge),
1102 XtRString, COLOR_CHALLENGE },
1103 { "colorRequest", "colorRequest", XtRString,
1104 sizeof(String), XtOffset(AppDataPtr, colorRequest),
1105 XtRString, COLOR_REQUEST },
1106 { "colorSeek", "colorSeek", XtRString,
1107 sizeof(String), XtOffset(AppDataPtr, colorSeek),
1108 XtRString, COLOR_SEEK },
1109 { "colorNormal", "colorNormal", XtRString,
1110 sizeof(String), XtOffset(AppDataPtr, colorNormal),
1111 XtRString, COLOR_NORMAL },
1112 { "soundProgram", "soundProgram", XtRString,
1113 sizeof(String), XtOffset(AppDataPtr, soundProgram),
1114 XtRString, "play" },
1115 { "soundShout", "soundShout", XtRString,
1116 sizeof(String), XtOffset(AppDataPtr, soundShout),
1118 { "soundSShout", "soundSShout", XtRString,
1119 sizeof(String), XtOffset(AppDataPtr, soundSShout),
1121 { "soundChannel1", "soundChannel1", XtRString,
1122 sizeof(String), XtOffset(AppDataPtr, soundChannel1),
1124 { "soundChannel", "soundChannel", XtRString,
1125 sizeof(String), XtOffset(AppDataPtr, soundChannel),
1127 { "soundKibitz", "soundKibitz", XtRString,
1128 sizeof(String), XtOffset(AppDataPtr, soundKibitz),
1130 { "soundTell", "soundTell", XtRString,
1131 sizeof(String), XtOffset(AppDataPtr, soundTell),
1133 { "soundChallenge", "soundChallenge", XtRString,
1134 sizeof(String), XtOffset(AppDataPtr, soundChallenge),
1136 { "soundRequest", "soundRequest", XtRString,
1137 sizeof(String), XtOffset(AppDataPtr, soundRequest),
1139 { "soundSeek", "soundSeek", XtRString,
1140 sizeof(String), XtOffset(AppDataPtr, soundSeek),
1142 { "soundMove", "soundMove", XtRString,
1143 sizeof(String), XtOffset(AppDataPtr, soundMove),
1145 { "soundIcsWin", "soundIcsWin", XtRString,
1146 sizeof(String), XtOffset(AppDataPtr, soundIcsWin),
1148 { "soundIcsLoss", "soundIcsLoss", XtRString,
1149 sizeof(String), XtOffset(AppDataPtr, soundIcsLoss),
1151 { "soundIcsDraw", "soundIcsDraw", XtRString,
1152 sizeof(String), XtOffset(AppDataPtr, soundIcsDraw),
1154 { "soundIcsUnfinished", "soundIcsUnfinished", XtRString,
1155 sizeof(String), XtOffset(AppDataPtr, soundIcsUnfinished),
1157 { "soundIcsAlarm", "soundIcsAlarm", XtRString,
1158 sizeof(String), XtOffset(AppDataPtr, soundIcsAlarm),
1160 { "reuseFirst", "reuseFirst", XtRBoolean,
1161 sizeof(Boolean), XtOffset(AppDataPtr, reuseFirst),
1162 XtRImmediate, (XtPointer) True },
1163 { "reuseSecond", "reuseSecond", XtRBoolean,
1164 sizeof(Boolean), XtOffset(AppDataPtr, reuseSecond),
1165 XtRImmediate, (XtPointer) True },
1166 { "animateDragging", "animateDragging", XtRBoolean,
1167 sizeof(Boolean), XtOffset(AppDataPtr, animateDragging),
1168 XtRImmediate, (XtPointer) True },
1169 { "animateMoving", "animateMoving", XtRBoolean,
1170 sizeof(Boolean), XtOffset(AppDataPtr, animate),
1171 XtRImmediate, (XtPointer) True },
1172 { "animateSpeed", "animateSpeed", XtRInt,
1173 sizeof(int), XtOffset(AppDataPtr, animSpeed),
1174 XtRImmediate, (XtPointer)10 },
1175 { "popupExitMessage", "popupExitMessage", XtRBoolean,
1176 sizeof(Boolean), XtOffset(AppDataPtr, popupExitMessage),
1177 XtRImmediate, (XtPointer) True },
1178 { "popupMoveErrors", "popupMoveErrors", XtRBoolean,
1179 sizeof(Boolean), XtOffset(AppDataPtr, popupMoveErrors),
1180 XtRImmediate, (XtPointer) False },
1181 { "fontSizeTolerance", "fontSizeTolerance", XtRInt,
1182 sizeof(int), XtOffset(AppDataPtr, fontSizeTolerance),
1183 XtRImmediate, (XtPointer)4 },
1184 { "initialMode", "initialMode", XtRString,
1185 sizeof(String), XtOffset(AppDataPtr, initialMode),
1186 XtRImmediate, (XtPointer) "" },
1187 { "variant", "variant", XtRString,
1188 sizeof(String), XtOffset(AppDataPtr, variant),
1189 XtRImmediate, (XtPointer) "normal" },
1190 { "firstProtocolVersion", "firstProtocolVersion", XtRInt,
1191 sizeof(int), XtOffset(AppDataPtr, firstProtocolVersion),
1192 XtRImmediate, (XtPointer)PROTOVER },
1193 { "secondProtocolVersion", "secondProtocolVersion", XtRInt,
1194 sizeof(int), XtOffset(AppDataPtr, secondProtocolVersion),
1195 XtRImmediate, (XtPointer)PROTOVER },
1196 { "showButtonBar", "showButtonBar", XtRBoolean,
1197 sizeof(Boolean), XtOffset(AppDataPtr, showButtonBar),
1198 XtRImmediate, (XtPointer) True },
1199 { "lowTimeWarningColor", "lowTimeWarningColor", XtRString,
1200 sizeof(String), XtOffset(AppDataPtr, lowTimeWarningColor),
1201 XtRString, COLOR_LOWTIMEWARNING },
1202 { "lowTimeWarning", "lowTimeWarning", XtRBoolean,
1203 sizeof(Boolean), XtOffset(AppDataPtr, lowTimeWarning),
1204 XtRImmediate, (XtPointer) False },
1205 {"icsEngineAnalyze", "icsEngineAnalyze", XtRBoolean, /* [DM] icsEngineAnalyze */
1206 sizeof(Boolean), XtOffset(AppDataPtr, icsEngineAnalyze),
1207 XtRImmediate, (XtPointer) False },
1208 { "firstScoreAbs", "firstScoreAbs", XtRBoolean,
1209 sizeof(Boolean), XtOffset(AppDataPtr, firstScoreIsAbsolute),
1210 XtRImmediate, (XtPointer) False },
1211 { "secondScoreAbs", "secondScoreAbs", XtRBoolean,
1212 sizeof(Boolean), XtOffset(AppDataPtr, secondScoreIsAbsolute),
1213 XtRImmediate, (XtPointer) False },
1214 { "pgnExtendedInfo", "pgnExtendedInfo", XtRBoolean,
1215 sizeof(Boolean), XtOffset(AppDataPtr, saveExtendedInfoInPGN),
1216 XtRImmediate, (XtPointer) False },
1217 { "hideThinkingFromHuman", "hideThinkingFromHuman", XtRBoolean,
1218 sizeof(Boolean), XtOffset(AppDataPtr, hideThinkingFromHuman),
1219 XtRImmediate, (XtPointer) True },
1220 { "adjudicateLossThreshold", "adjudicateLossThreshold", XtRInt,
1221 sizeof(int), XtOffset(AppDataPtr, adjudicateLossThreshold),
1222 XtRImmediate, (XtPointer) 0},
1223 { "pgnEventHeader", "pgnEventHeader", XtRString,
1224 sizeof(String), XtOffset(AppDataPtr, pgnEventHeader),
1225 XtRImmediate, (XtPointer) "Computer Chess Game" },
1226 { "defaultFrcPosition", "defaultFrcPositon", XtRInt,
1227 sizeof(int), XtOffset(AppDataPtr, defaultFrcPosition),
1228 XtRImmediate, (XtPointer) -1},
1229 { "gameListTags", "gameListTags", XtRString,
1230 sizeof(String), XtOffset(AppDataPtr, gameListTags),
1231 XtRImmediate, (XtPointer) GLT_DEFAULT_TAGS },
1233 // [HGM] 4.3.xx options
1234 { "boardWidth", "boardWidth", XtRInt,
1235 sizeof(int), XtOffset(AppDataPtr, NrFiles),
1236 XtRImmediate, (XtPointer) -1},
1237 { "boardHeight", "boardHeight", XtRInt,
1238 sizeof(int), XtOffset(AppDataPtr, NrRanks),
1239 XtRImmediate, (XtPointer) -1},
1240 { "matchPause", "matchPause", XtRInt,
1241 sizeof(int), XtOffset(AppDataPtr, matchPause),
1242 XtRImmediate, (XtPointer) 10000},
1243 { "holdingsSize", "holdingsSize", XtRInt,
1244 sizeof(int), XtOffset(AppDataPtr, holdingsSize),
1245 XtRImmediate, (XtPointer) -1},
1246 { "flipBlack", "flipBlack", XtRBoolean,
1247 sizeof(Boolean), XtOffset(AppDataPtr, upsideDown),
1248 XtRImmediate, (XtPointer) False},
1249 { "allWhite", "allWhite", XtRBoolean,
1250 sizeof(Boolean), XtOffset(AppDataPtr, allWhite),
1251 XtRImmediate, (XtPointer) False},
1252 { "pieceToCharTable", "pieceToCharTable", XtRString,
1253 sizeof(String), XtOffset(AppDataPtr, pieceToCharTable),
1254 XtRImmediate, (XtPointer) 0},
1255 { "alphaRank", "alphaRank", XtRBoolean,
1256 sizeof(Boolean), XtOffset(AppDataPtr, alphaRank),
1257 XtRImmediate, (XtPointer) False},
1258 { "testClaims", "testClaims", XtRBoolean,
1259 sizeof(Boolean), XtOffset(AppDataPtr, testClaims),
1260 XtRImmediate, (XtPointer) True},
1261 { "checkMates", "checkMates", XtRBoolean,
1262 sizeof(Boolean), XtOffset(AppDataPtr, checkMates),
1263 XtRImmediate, (XtPointer) True},
1264 { "materialDraws", "materialDraws", XtRBoolean,
1265 sizeof(Boolean), XtOffset(AppDataPtr, materialDraws),
1266 XtRImmediate, (XtPointer) True},
1267 { "trivialDraws", "trivialDraws", XtRBoolean,
1268 sizeof(Boolean), XtOffset(AppDataPtr, trivialDraws),
1269 XtRImmediate, (XtPointer) False},
1270 { "ruleMoves", "ruleMoves", XtRInt,
1271 sizeof(int), XtOffset(AppDataPtr, ruleMoves),
1272 XtRImmediate, (XtPointer) 51},
1273 { "repeatsToDraw", "repeatsToDraw", XtRInt,
1274 sizeof(int), XtOffset(AppDataPtr, drawRepeats),
1275 XtRImmediate, (XtPointer) 6},
1276 { "engineDebugOutput", "engineDebugOutput", XtRInt,
1277 sizeof(int), XtOffset(AppDataPtr, engineComments),
1278 XtRImmediate, (XtPointer) 1},
1279 { "userName", "userName", XtRString,
1280 sizeof(int), XtOffset(AppDataPtr, userName),
1281 XtRImmediate, (XtPointer) 0},
1282 { "autoKibitz", "autoKibitz", XtRBoolean,
1283 sizeof(Boolean), XtOffset(AppDataPtr, autoKibitz),
1284 XtRImmediate, (XtPointer) False},
1285 { "firstTimeOdds", "firstTimeOdds", XtRInt,
1286 sizeof(int), XtOffset(AppDataPtr, firstTimeOdds),
1287 XtRImmediate, (XtPointer) 1},
1288 { "secondTimeOdds", "secondTimeOdds", XtRInt,
1289 sizeof(int), XtOffset(AppDataPtr, secondTimeOdds),
1290 XtRImmediate, (XtPointer) 1},
1291 { "timeOddsMode", "timeOddsMode", XtRInt,
1292 sizeof(int), XtOffset(AppDataPtr, timeOddsMode),
1293 XtRImmediate, (XtPointer) 0},
1294 { "firstAccumulateTC", "firstAccumulateTC", XtRInt,
1295 sizeof(int), XtOffset(AppDataPtr, firstAccumulateTC),
1296 XtRImmediate, (XtPointer) 1},
1297 { "secondAccumulateTC", "secondAccumulateTC", XtRInt,
1298 sizeof(int), XtOffset(AppDataPtr, secondAccumulateTC),
1299 XtRImmediate, (XtPointer) 1},
1300 { "firstNPS", "firstNPS", XtRInt,
1301 sizeof(int), XtOffset(AppDataPtr, firstNPS),
1302 XtRImmediate, (XtPointer) -1},
1303 { "secondNPS", "secondNPS", XtRInt,
1304 sizeof(int), XtOffset(AppDataPtr, secondNPS),
1305 XtRImmediate, (XtPointer) -1},
1306 { "serverMoves", "serverMoves", XtRString,
1307 sizeof(String), XtOffset(AppDataPtr, serverMovesName),
1308 XtRImmediate, (XtPointer) 0},
1309 { "serverPause", "serverPause", XtRInt,
1310 sizeof(int), XtOffset(AppDataPtr, serverPause),
1311 XtRImmediate, (XtPointer) 0},
1312 { "suppressLoadMoves", "suppressLoadMoves", XtRBoolean,
1313 sizeof(Boolean), XtOffset(AppDataPtr, suppressLoadMoves),
1314 XtRImmediate, (XtPointer) False},
1315 { "userName", "userName", XtRString,
1316 sizeof(String), XtOffset(AppDataPtr, userName),
1317 XtRImmediate, (XtPointer) 0},
1318 { "egtFormats", "egtFormats", XtRString,
1319 sizeof(String), XtOffset(AppDataPtr, egtFormats),
1320 XtRImmediate, (XtPointer) 0},
1321 { "rewindIndex", "rewindIndex", XtRInt,
1322 sizeof(int), XtOffset(AppDataPtr, rewindIndex),
1323 XtRImmediate, (XtPointer) 0},
1324 { "sameColorGames", "sameColorGames", XtRInt,
1325 sizeof(int), XtOffset(AppDataPtr, sameColorGames),
1326 XtRImmediate, (XtPointer) 0},
1327 { "smpCores", "smpCores", XtRInt,
1328 sizeof(int), XtOffset(AppDataPtr, smpCores),
1329 XtRImmediate, (XtPointer) 1},
1330 { "niceEngines", "niceEngines", XtRInt,
1331 sizeof(int), XtOffset(AppDataPtr, niceEngines),
1332 XtRImmediate, (XtPointer) 0},
1333 { "nameOfDebugFile", "nameOfDebugFile", XtRString,
1334 sizeof(String), XtOffset(AppDataPtr, nameOfDebugFile),
1335 XtRImmediate, (XtPointer) "xboard.debug"},
1336 { "engineDebugOutput", "engineDebugOutput", XtRInt,
1337 sizeof(int), XtOffset(AppDataPtr, engineComments),
1338 XtRImmediate, (XtPointer) 0},
1339 { "noGUI", "noGUI", XtRBoolean,
1340 sizeof(Boolean), XtOffset(AppDataPtr, noGUI),
1341 XtRImmediate, (XtPointer) 0},
1342 { "firstOptions", "firstOptions", XtRString,
1343 sizeof(String), XtOffset(AppDataPtr, firstOptions),
1344 XtRImmediate, (XtPointer) "" },
1345 { "secondOptions", "secondOptions", XtRString,
1346 sizeof(String), XtOffset(AppDataPtr, secondOptions),
1347 XtRImmediate, (XtPointer) "" },
1348 { "firstNeedsNoncompliantFEN", "firstNeedsNoncompliantFEN", XtRString,
1349 sizeof(String), XtOffset(AppDataPtr, fenOverride1),
1350 XtRImmediate, (XtPointer) 0 },
1351 { "secondNeedsNoncompliantFEN", "secondNeedsNoncompliantFEN", XtRString,
1352 sizeof(String), XtOffset(AppDataPtr, fenOverride2),
1353 XtRImmediate, (XtPointer) 0 },
1355 // [HGM] Winboard_x UCI options
1356 { "firstIsUCI", "firstIsUCI", XtRBoolean,
1357 sizeof(Boolean), XtOffset(AppDataPtr, firstIsUCI),
1358 XtRImmediate, (XtPointer) False},
1359 { "secondIsUCI", "secondIsUCI", XtRBoolean,
1360 sizeof(Boolean), XtOffset(AppDataPtr, secondIsUCI),
1361 XtRImmediate, (XtPointer) False},
1362 { "firstHasOwnBookUCI", "firstHasOwnBookUCI", XtRBoolean,
1363 sizeof(Boolean), XtOffset(AppDataPtr, firstHasOwnBookUCI),
1364 XtRImmediate, (XtPointer) True},
1365 { "secondHasOwnBookUCI", "secondHasOwnBookUCI", XtRBoolean,
1366 sizeof(Boolean), XtOffset(AppDataPtr, secondHasOwnBookUCI),
1367 XtRImmediate, (XtPointer) True},
1368 { "usePolyglotBook", "usePolyglotBook", XtRBoolean,
1369 sizeof(Boolean), XtOffset(AppDataPtr, usePolyglotBook),
1370 XtRImmediate, (XtPointer) False},
1371 { "defaultHashSize", "defaultHashSize", XtRInt,
1372 sizeof(int), XtOffset(AppDataPtr, defaultHashSize),
1373 XtRImmediate, (XtPointer) 64},
1374 { "defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XtRInt,
1375 sizeof(int), XtOffset(AppDataPtr, defaultCacheSizeEGTB),
1376 XtRImmediate, (XtPointer) 4},
1377 { "polyglotDir", "polyglotDir", XtRString,
1378 sizeof(String), XtOffset(AppDataPtr, polyglotDir),
1379 XtRImmediate, (XtPointer) "." },
1380 { "polyglotBook", "polyglotBook", XtRString,
1381 sizeof(String), XtOffset(AppDataPtr, polyglotBook),
1382 XtRImmediate, (XtPointer) "" },
1383 { "defaultPathEGTB", "defaultPathEGTB", XtRString,
1384 sizeof(String), XtOffset(AppDataPtr, defaultPathEGTB),
1385 XtRImmediate, (XtPointer) "/usr/local/share/egtb"},
1386 { "delayBeforeQuit", "delayBeforeQuit", XtRInt,
1387 sizeof(int), XtOffset(AppDataPtr, delayBeforeQuit),
1388 XtRImmediate, (XtPointer) 0},
1389 { "delayAfterQuit", "delayAfterQuit", XtRInt,
1390 sizeof(int), XtOffset(AppDataPtr, delayAfterQuit),
1391 XtRImmediate, (XtPointer) 0},
1394 XrmOptionDescRec shellOptions[] = {
1395 { "-whitePieceColor", "whitePieceColor", XrmoptionSepArg, NULL },
1396 { "-blackPieceColor", "blackPieceColor", XrmoptionSepArg, NULL },
1397 { "-lightSquareColor", "lightSquareColor", XrmoptionSepArg, NULL },
1398 { "-darkSquareColor", "darkSquareColor", XrmoptionSepArg, NULL },
1399 { "-highlightSquareColor", "highlightSquareColor", XrmoptionSepArg, NULL },
1400 { "-premoveHighlightColor", "premoveHighlightColor", XrmoptionSepArg,NULL},
1401 { "-movesPerSession", "movesPerSession", XrmoptionSepArg, NULL },
1402 { "-mps", "movesPerSession", XrmoptionSepArg, NULL },
1403 { "-timeIncrement", "timeIncrement", XrmoptionSepArg, NULL },
1404 { "-inc", "timeIncrement", XrmoptionSepArg, NULL },
1405 { "-initString", "initString", XrmoptionSepArg, NULL },
1406 { "-firstInitString", "initString", XrmoptionSepArg, NULL },
1407 { "-secondInitString", "secondInitString", XrmoptionSepArg, NULL },
1408 { "-firstComputerString", "firstComputerString", XrmoptionSepArg, NULL },
1409 { "-secondComputerString", "secondComputerString", XrmoptionSepArg, NULL },
1410 { "-firstChessProgram", "firstChessProgram", XrmoptionSepArg, NULL },
1411 { "-fcp", "firstChessProgram", XrmoptionSepArg, NULL },
1412 { "-secondChessProgram", "secondChessProgram", XrmoptionSepArg, NULL },
1413 { "-scp", "secondChessProgram", XrmoptionSepArg, NULL },
1414 { "-firstPlaysBlack", "firstPlaysBlack", XrmoptionSepArg, NULL },
1415 { "-fb", "firstPlaysBlack", XrmoptionNoArg, "True" },
1416 { "-xfb", "firstPlaysBlack", XrmoptionNoArg, "False" },
1417 { "-noChessProgram", "noChessProgram", XrmoptionSepArg, NULL },
1418 { "-ncp", "noChessProgram", XrmoptionNoArg, "True" },
1419 { "-xncp", "noChessProgram", XrmoptionNoArg, "False" },
1420 { "-firstHost", "firstHost", XrmoptionSepArg, NULL },
1421 { "-fh", "firstHost", XrmoptionSepArg, NULL },
1422 { "-secondHost", "secondHost", XrmoptionSepArg, NULL },
1423 { "-sh", "secondHost", XrmoptionSepArg, NULL },
1424 { "-firstDirectory", "firstDirectory", XrmoptionSepArg, NULL },
1425 { "-fd", "firstDirectory", XrmoptionSepArg, NULL },
1426 { "-secondDirectory", "secondDirectory", XrmoptionSepArg, NULL },
1427 { "-sd", "secondDirectory", XrmoptionSepArg, NULL },
1428 { "-bitmapDirectory", "bitmapDirectory", XrmoptionSepArg, NULL },
1429 { "-bm", "bitmapDirectory", XrmoptionSepArg, NULL },
1430 { "-remoteShell", "remoteShell", XrmoptionSepArg, NULL },
1431 { "-rsh", "remoteShell", XrmoptionSepArg, NULL },
1432 { "-remoteUser", "remoteUser", XrmoptionSepArg, NULL },
1433 { "-ruser", "remoteUser", XrmoptionSepArg, NULL },
1434 { "-timeDelay", "timeDelay", XrmoptionSepArg, NULL },
1435 { "-td", "timeDelay", XrmoptionSepArg, NULL },
1436 { "-timeControl", "timeControl", XrmoptionSepArg, NULL },
1437 { "-tc", "timeControl", XrmoptionSepArg, NULL },
1438 { "-internetChessServerMode", "internetChessServerMode",
1439 XrmoptionSepArg, NULL },
1440 { "-ics", "internetChessServerMode", XrmoptionNoArg, "True" },
1441 { "-xics", "internetChessServerMode", XrmoptionNoArg, "False" },
1442 { "-internetChessServerHost", "internetChessServerHost",
1443 XrmoptionSepArg, NULL },
1444 { "-icshost", "internetChessServerHost", XrmoptionSepArg, NULL },
1445 { "-internetChessServerPort", "internetChessServerPort",
1446 XrmoptionSepArg, NULL },
1447 { "-icsport", "internetChessServerPort", XrmoptionSepArg, NULL },
1448 { "-internetChessServerCommPort", "internetChessServerCommPort",
1449 XrmoptionSepArg, NULL },
1450 { "-icscomm", "internetChessServerCommPort", XrmoptionSepArg, NULL },
1451 { "-internetChessServerLogonScript", "internetChessServerLogonScript",
1452 XrmoptionSepArg, NULL },
1453 { "-icslogon", "internetChessServerLogonScript", XrmoptionSepArg, NULL },
1454 { "-internetChessServerHelper", "internetChessServerHelper",
1455 XrmoptionSepArg, NULL },
1456 { "-icshelper", "internetChessServerHelper", XrmoptionSepArg, NULL },
1457 { "-internetChessServerInputBox", "internetChessServerInputBox",
1458 XrmoptionSepArg, NULL },
1459 { "-icsinput", "internetChessServerInputBox", XrmoptionNoArg, "True" },
1460 { "-xicsinput", "internetChessServerInputBox", XrmoptionNoArg, "False" },
1461 { "-icsAlarm", "icsAlarm", XrmoptionSepArg, NULL },
1462 { "-alarm", "icsAlarm", XrmoptionNoArg, "True" },
1463 { "-xalarm", "icsAlarm", XrmoptionNoArg, "False" },
1464 { "-icsAlarmTime", "icsAlarmTime", XrmoptionSepArg, NULL },
1465 { "-useTelnet", "useTelnet", XrmoptionSepArg, NULL },
1466 { "-telnet", "useTelnet", XrmoptionNoArg, "True" },
1467 { "-xtelnet", "useTelnet", XrmoptionNoArg, "False" },
1468 { "-telnetProgram", "telnetProgram", XrmoptionSepArg, NULL },
1469 { "-gateway", "gateway", XrmoptionSepArg, NULL },
1470 { "-loadGameFile", "loadGameFile", XrmoptionSepArg, NULL },
1471 { "-lgf", "loadGameFile", XrmoptionSepArg, NULL },
1472 { "-loadGameIndex", "loadGameIndex", XrmoptionSepArg, NULL },
1473 { "-lgi", "loadGameIndex", XrmoptionSepArg, NULL },
1474 { "-saveGameFile", "saveGameFile", XrmoptionSepArg, NULL },
1475 { "-sgf", "saveGameFile", XrmoptionSepArg, NULL },
1476 { "-autoSaveGames", "autoSaveGames", XrmoptionSepArg, NULL },
1477 { "-autosave", "autoSaveGames", XrmoptionNoArg, "True" },
1478 { "-xautosave", "autoSaveGames", XrmoptionNoArg, "False" },
1479 { "-autoRaiseBoard", "autoRaiseBoard", XrmoptionSepArg, NULL },
1480 { "-autoraise", "autoRaiseBoard", XrmoptionNoArg, "True" },
1481 { "-xautoraise", "autoRaiseBoard", XrmoptionNoArg, "False" },
1482 { "-blindfold", "blindfold", XrmoptionSepArg, NULL },
1483 { "-blind", "blindfold", XrmoptionNoArg, "True" },
1484 { "-xblind", "blindfold", XrmoptionNoArg, "False" },
1485 { "-loadPositionFile", "loadPositionFile", XrmoptionSepArg, NULL },
1486 { "-lpf", "loadPositionFile", XrmoptionSepArg, NULL },
1487 { "-loadPositionIndex", "loadPositionIndex", XrmoptionSepArg, NULL },
1488 { "-lpi", "loadPositionIndex", XrmoptionSepArg, NULL },
1489 { "-savePositionFile", "savePositionFile", XrmoptionSepArg, NULL },
1490 { "-spf", "savePositionFile", XrmoptionSepArg, NULL },
1491 { "-matchMode", "matchMode", XrmoptionSepArg, NULL },
1492 { "-mm", "matchMode", XrmoptionNoArg, "True" },
1493 { "-xmm", "matchMode", XrmoptionNoArg, "False" },
1494 { "-matchGames", "matchGames", XrmoptionSepArg, NULL },
1495 { "-mg", "matchGames", XrmoptionSepArg, NULL },
1496 { "-monoMode", "monoMode", XrmoptionSepArg, NULL },
1497 { "-mono", "monoMode", XrmoptionNoArg, "True" },
1498 { "-xmono", "monoMode", XrmoptionNoArg, "False" },
1499 { "-debugMode", "debugMode", XrmoptionSepArg, NULL },
1500 { "-debug", "debugMode", XrmoptionNoArg, "True" },
1501 { "-xdebug", "debugMode", XrmoptionNoArg, "False" },
1502 { "-clockMode", "clockMode", XrmoptionSepArg, NULL },
1503 { "-clock", "clockMode", XrmoptionNoArg, "True" },
1504 { "-xclock", "clockMode", XrmoptionNoArg, "False" },
1505 { "-boardSize", "boardSize", XrmoptionSepArg, NULL },
1506 { "-size", "boardSize", XrmoptionSepArg, NULL },
1507 { "-searchTime", "searchTime", XrmoptionSepArg, NULL },
1508 { "-st", "searchTime", XrmoptionSepArg, NULL },
1509 { "-searchDepth", "searchDepth", XrmoptionSepArg, NULL },
1510 { "-depth", "searchDepth", XrmoptionSepArg, NULL },
1511 { "-showCoords", "showCoords", XrmoptionSepArg, NULL },
1512 { "-coords", "showCoords", XrmoptionNoArg, "True" },
1513 { "-xcoords", "showCoords", XrmoptionNoArg, "False" },
1515 { "-showJail", "showJail", XrmoptionSepArg, NULL },
1516 { "-jail", "showJail", XrmoptionNoArg, "1" },
1517 { "-sidejail", "showJail", XrmoptionNoArg, "2" },
1518 { "-xjail", "showJail", XrmoptionNoArg, "0" },
1520 { "-showThinking", "showThinking", XrmoptionSepArg, NULL },
1521 { "-thinking", "showThinking", XrmoptionNoArg, "True" },
1522 { "-xthinking", "showThinking", XrmoptionNoArg, "False" },
1523 { "-ponderNextMove", "ponderNextMove", XrmoptionSepArg, NULL },
1524 { "-ponder", "ponderNextMove", XrmoptionNoArg, "True" },
1525 { "-xponder", "ponderNextMove", XrmoptionNoArg, "False" },
1526 { "-periodicUpdates", "periodicUpdates", XrmoptionSepArg, NULL },
1527 { "-periodic", "periodicUpdates", XrmoptionNoArg, "True" },
1528 { "-xperiodic", "periodicUpdates", XrmoptionNoArg, "False" },
1529 { "-clockFont", "clockFont", XrmoptionSepArg, NULL },
1530 { "-coordFont", "coordFont", XrmoptionSepArg, NULL },
1531 { "-font", "font", XrmoptionSepArg, NULL },
1532 { "-ringBellAfterMoves", "ringBellAfterMoves", XrmoptionSepArg, NULL },
1533 { "-bell", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1534 { "-xbell", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1535 { "-movesound", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1536 { "-xmovesound", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1537 { "-autoCallFlag", "autoCallFlag", XrmoptionSepArg, NULL },
1538 { "-autoflag", "autoCallFlag", XrmoptionNoArg, "True" },
1539 { "-xautoflag", "autoCallFlag", XrmoptionNoArg, "False" },
1540 { "-autoFlipView", "autoFlipView", XrmoptionSepArg, NULL },
1541 { "-autoflip", "autoFlipView", XrmoptionNoArg, "True" },
1542 { "-xautoflip", "autoFlipView", XrmoptionNoArg, "False" },
1543 { "-autoObserve", "autoObserve", XrmoptionSepArg, NULL },
1544 { "-autobs", "autoObserve", XrmoptionNoArg, "True" },
1545 { "-xautobs", "autoObserve", XrmoptionNoArg, "False" },
1546 { "-autoComment", "autoComment", XrmoptionSepArg, NULL },
1547 { "-autocomm", "autoComment", XrmoptionNoArg, "True" },
1548 { "-xautocomm", "autoComment", XrmoptionNoArg, "False" },
1549 { "-getMoveList", "getMoveList", XrmoptionSepArg, NULL },
1550 { "-moves", "getMoveList", XrmoptionNoArg, "True" },
1551 { "-xmoves", "getMoveList", XrmoptionNoArg, "False" },
1553 { "-highlightDragging", "highlightDragging", XrmoptionSepArg, NULL },
1554 { "-highdrag", "highlightDragging", XrmoptionNoArg, "True" },
1555 { "-xhighdrag", "highlightDragging", XrmoptionNoArg, "False" },
1557 { "-highlightLastMove", "highlightLastMove", XrmoptionSepArg, NULL },
1558 { "-highlight", "highlightLastMove", XrmoptionNoArg, "True" },
1559 { "-xhighlight", "highlightLastMove", XrmoptionNoArg, "False" },
1560 { "-premove", "premove", XrmoptionSepArg, NULL },
1561 { "-pre", "premove", XrmoptionNoArg, "True" },
1562 { "-xpre", "premove", XrmoptionNoArg, "False" },
1563 { "-testLegality", "testLegality", XrmoptionSepArg, NULL },
1564 { "-legal", "testLegality", XrmoptionNoArg, "True" },
1565 { "-xlegal", "testLegality", XrmoptionNoArg, "False" },
1566 { "-flipView", "flipView", XrmoptionSepArg, NULL },
1567 { "-flip", "flipView", XrmoptionNoArg, "True" },
1568 { "-xflip", "flipView", XrmoptionNoArg, "False" },
1569 { "-cmail", "cmailGameName", XrmoptionSepArg, NULL },
1570 { "-alwaysPromoteToQueen", "alwaysPromoteToQueen",
1571 XrmoptionSepArg, NULL },
1572 { "-queen", "alwaysPromoteToQueen", XrmoptionNoArg, "True" },
1573 { "-xqueen", "alwaysPromoteToQueen", XrmoptionNoArg, "False" },
1574 { "-oldSaveStyle", "oldSaveStyle", XrmoptionSepArg, NULL },
1575 { "-oldsave", "oldSaveStyle", XrmoptionNoArg, "True" },
1576 { "-xoldsave", "oldSaveStyle", XrmoptionNoArg, "False" },
1577 { "-quietPlay", "quietPlay", XrmoptionSepArg, NULL },
1578 { "-quiet", "quietPlay", XrmoptionNoArg, "True" },
1579 { "-xquiet", "quietPlay", XrmoptionNoArg, "False" },
1580 { "-titleInWindow", "titleInWindow", XrmoptionSepArg, NULL },
1581 { "-title", "titleInWindow", XrmoptionNoArg, "True" },
1582 { "-xtitle", "titleInWindow", XrmoptionNoArg, "False" },
1584 { "-zippyTalk", "zippyTalk", XrmoptionSepArg, NULL },
1585 { "-zt", "zippyTalk", XrmoptionNoArg, "True" },
1586 { "-xzt", "zippyTalk", XrmoptionNoArg, "False" },
1587 { "-zippyPlay", "zippyPlay", XrmoptionSepArg, NULL },
1588 { "-zp", "zippyPlay", XrmoptionNoArg, "True" },
1589 { "-xzp", "zippyPlay", XrmoptionNoArg, "False" },
1590 { "-zippyLines", "zippyLines", XrmoptionSepArg, NULL },
1591 { "-zippyPinhead", "zippyPinhead", XrmoptionSepArg, NULL },
1592 { "-zippyPassword", "zippyPassword", XrmoptionSepArg, NULL },
1593 { "-zippyPassword2", "zippyPassword2", XrmoptionSepArg, NULL },
1594 { "-zippyWrongPassword", "zippyWrongPassword", XrmoptionSepArg, NULL },
1595 { "-zippyAcceptOnly", "zippyAcceptOnly", XrmoptionSepArg, NULL },
1596 { "-zippyUseI", "zippyUseI", XrmoptionSepArg, NULL },
1597 { "-zui", "zippyUseI", XrmoptionNoArg, "True" },
1598 { "-xzui", "zippyUseI", XrmoptionNoArg, "False" },
1599 { "-zippyBughouse", "zippyBughouse", XrmoptionSepArg, NULL },
1600 { "-zippyNoplayCrafty", "zippyNoplayCrafty", XrmoptionSepArg, NULL },
1601 { "-znc", "zippyNoplayCrafty", XrmoptionNoArg, "True" },
1602 { "-xznc", "zippyNoplayCrafty", XrmoptionNoArg, "False" },
1603 { "-zippyGameEnd", "zippyGameEnd", XrmoptionSepArg, NULL },
1604 { "-zippyGameStart", "zippyGameStart", XrmoptionSepArg, NULL },
1605 { "-zippyAdjourn", "zippyAdjourn", XrmoptionSepArg, NULL },
1606 { "-zadj", "zippyAdjourn", XrmoptionNoArg, "True" },
1607 { "-xzadj", "zippyAdjourn", XrmoptionNoArg, "False" },
1608 { "-zippyAbort", "zippyAbort", XrmoptionSepArg, NULL },
1609 { "-zab", "zippyAbort", XrmoptionNoArg, "True" },
1610 { "-xzab", "zippyAbort", XrmoptionNoArg, "False" },
1611 { "-zippyVariants", "zippyVariants", XrmoptionSepArg, NULL },
1612 { "-zippyMaxGames", "zippyMaxGames", XrmoptionSepArg, NULL },
1613 { "-zippyReplayTimeout", "zippyReplayTimeout", XrmoptionSepArg, NULL },
1614 { "-zippyShortGame", "zippyShortGame", XrmoptionSepArg, NULL },
1616 { "-flashCount", "flashCount", XrmoptionSepArg, NULL },
1617 { "-flash", "flashCount", XrmoptionNoArg, "3" },
1618 { "-xflash", "flashCount", XrmoptionNoArg, "0" },
1619 { "-flashRate", "flashRate", XrmoptionSepArg, NULL },
1620 { "-pixmapDirectory", "pixmapDirectory", XrmoptionSepArg, NULL },
1621 { "-msLoginDelay", "msLoginDelay", XrmoptionSepArg, NULL },
1622 { "-pixmap", "pixmapDirectory", XrmoptionSepArg, NULL },
1623 { "-colorizeMessages", "colorizeMessages", XrmoptionSepArg, NULL },
1624 { "-colorize", "colorizeMessages", XrmoptionNoArg, "True" },
1625 { "-xcolorize", "colorizeMessages", XrmoptionNoArg, "False" },
1626 { "-colorShout", "colorShout", XrmoptionSepArg, NULL },
1627 { "-colorSShout", "colorSShout", XrmoptionSepArg, NULL },
1628 { "-colorCShout", "colorSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1629 { "-colorChannel1", "colorChannel1", XrmoptionSepArg, NULL },
1630 { "-colorChannel", "colorChannel", XrmoptionSepArg, NULL },
1631 { "-colorKibitz", "colorKibitz", XrmoptionSepArg, NULL },
1632 { "-colorTell", "colorTell", XrmoptionSepArg, NULL },
1633 { "-colorChallenge", "colorChallenge", XrmoptionSepArg, NULL },
1634 { "-colorRequest", "colorRequest", XrmoptionSepArg, NULL },
1635 { "-colorSeek", "colorSeek", XrmoptionSepArg, NULL },
1636 { "-colorNormal", "colorNormal", XrmoptionSepArg, NULL },
1637 { "-soundProgram", "soundProgram", XrmoptionSepArg, NULL },
1638 { "-soundShout", "soundShout", XrmoptionSepArg, NULL },
1639 { "-soundSShout", "soundSShout", XrmoptionSepArg, NULL },
1640 { "-soundCShout", "soundSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1641 { "-soundChannel1", "soundChannel1", XrmoptionSepArg, NULL },
1642 { "-soundChannel", "soundChannel", XrmoptionSepArg, NULL },
1643 { "-soundKibitz", "soundKibitz", XrmoptionSepArg, NULL },
1644 { "-soundTell", "soundTell", XrmoptionSepArg, NULL },
1645 { "-soundChallenge", "soundChallenge", XrmoptionSepArg, NULL },
1646 { "-soundRequest", "soundRequest", XrmoptionSepArg, NULL },
1647 { "-soundSeek", "soundSeek", XrmoptionSepArg, NULL },
1648 { "-soundMove", "soundMove", XrmoptionSepArg, NULL },
1649 { "-soundIcsWin", "soundIcsWin", XrmoptionSepArg, NULL },
1650 { "-soundIcsLoss", "soundIcsLoss", XrmoptionSepArg, NULL },
1651 { "-soundIcsDraw", "soundIcsDraw", XrmoptionSepArg, NULL },
1652 { "-soundIcsUnfinished", "soundIcsUnfinished", XrmoptionSepArg, NULL },
1653 { "-soundIcsAlarm", "soundIcsAlarm", XrmoptionSepArg, NULL },
1654 { "-reuseFirst", "reuseFirst", XrmoptionSepArg, NULL },
1655 { "-reuseChessPrograms", "reuseFirst", XrmoptionSepArg, NULL }, /*compat*/
1656 { "-reuse", "reuseFirst", XrmoptionNoArg, "True" },
1657 { "-xreuse", "reuseFirst", XrmoptionNoArg, "False" },
1658 { "-reuseSecond", "reuseSecond", XrmoptionSepArg, NULL },
1659 { "-reuse2", "reuseSecond", XrmoptionNoArg, "True" },
1660 { "-xreuse2", "reuseSecond", XrmoptionNoArg, "False" },
1661 { "-animateMoving", "animateMoving", XrmoptionSepArg, NULL },
1662 { "-animate", "animateMoving", XrmoptionNoArg, "True" },
1663 { "-xanimate", "animateMoving", XrmoptionNoArg, "False" },
1664 { "-animateDragging", "animateDragging", XrmoptionSepArg, NULL },
1665 { "-drag", "animateDragging", XrmoptionNoArg, "True" },
1666 { "-xdrag", "animateDragging", XrmoptionNoArg, "False" },
1667 { "-animateSpeed", "animateSpeed", XrmoptionSepArg, NULL },
1668 { "-popupExitMessage", "popupExitMessage", XrmoptionSepArg, NULL },
1669 { "-exit", "popupExitMessage", XrmoptionNoArg, "True" },
1670 { "-xexit", "popupExitMessage", XrmoptionNoArg, "False" },
1671 { "-popupMoveErrors", "popupMoveErrors", XrmoptionSepArg, NULL },
1672 { "-popup", "popupMoveErrors", XrmoptionNoArg, "True" },
1673 { "-xpopup", "popupMoveErrors", XrmoptionNoArg, "False" },
1674 { "-fontSizeTolerance", "fontSizeTolerance", XrmoptionSepArg, NULL },
1675 { "-initialMode", "initialMode", XrmoptionSepArg, NULL },
1676 { "-mode", "initialMode", XrmoptionSepArg, NULL },
1677 { "-variant", "variant", XrmoptionSepArg, NULL },
1678 { "-firstProtocolVersion", "firstProtocolVersion", XrmoptionSepArg, NULL },
1679 { "-secondProtocolVersion","secondProtocolVersion",XrmoptionSepArg, NULL },
1680 { "-showButtonBar", "showButtonBar", XrmoptionSepArg, NULL },
1681 { "-buttons", "showButtonBar", XrmoptionNoArg, "True" },
1682 { "-xbuttons", "showButtonBar", XrmoptionNoArg, "False" },
1683 { "-lowTimeWarningColor", "lowTimeWarningColor", XrmoptionSepArg, NULL },
1684 { "-lowTimeWarning", "lowTimeWarning", XrmoptionSepArg, NULL },
1685 /* [AS,HR] New features */
1686 { "-firstScoreAbs", "firstScoreAbs", XrmoptionSepArg, NULL },
1687 { "-secondScoreAbs", "secondScoreAbs", XrmoptionSepArg, NULL },
1688 { "-pgnExtendedInfo", "pgnExtendedInfo", XrmoptionSepArg, NULL },
1689 { "-hideThinkingFromHuman", "hideThinkingFromHuman", XrmoptionSepArg, NULL },
1690 { "-adjudicateLossThreshold", "adjudicateLossThreshold", XrmoptionSepArg, NULL },
1691 { "-pgnEventHeader", "pgnEventHeader", XrmoptionSepArg, NULL },
1692 { "-firstIsUCI", "firstIsUCI", XrmoptionSepArg, NULL },
1693 { "-secondIsUCI", "secondIsUCI", XrmoptionSepArg, NULL },
1694 { "-fUCI", "firstIsUCI", XrmoptionNoArg, "True" },
1695 { "-sUCI", "secondIsUCI", XrmoptionNoArg, "True" },
1696 { "-firstHasOwnBookUCI", "firstHasOwnBookUCI", XrmoptionSepArg, NULL },
1697 { "-secondHasOwnBookUCI", "secondHasOwnBookUCI", XrmoptionSepArg, NULL },
1698 { "-fNoOwnBookUCI", "firstHasOwnBookUCI", XrmoptionNoArg, "False" },
1699 { "-sNoOwnBookUCI", "secondHasOwnBookUCI", XrmoptionNoArg, "False" },
1700 { "-firstXBook", "firstHasOwnBookUCI", XrmoptionNoArg, "False" },
1701 { "-secondXBook", "secondHasOwnBookUCI", XrmoptionNoArg, "False" },
1702 { "-polyglotDir", "polyglotDir", XrmoptionSepArg, NULL },
1703 { "-usePolyglotBook", "usePolyglotBook", XrmoptionSepArg, NULL },
1704 { "-polyglotBook", "polyglotBook", XrmoptionSepArg, NULL },
1705 { "-defaultHashSize", "defaultHashSize", XrmoptionSepArg, NULL },
1706 { "-defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XrmoptionSepArg, NULL },
1707 { "-defaultPathEGTB", "defaultPathEGTB", XrmoptionSepArg, NULL },
1708 { "-defaultFrcPosition", "defaultFrcPosition", XrmoptionSepArg, NULL },
1709 { "-gameListTags", "gameListTags", XrmoptionSepArg, NULL },
1710 // [HGM] I am sure AS added many more options, but we have to fish them out, from the list in winboard.c
1712 /* [HGM,HR] User-selectable board size */
1713 { "-boardWidth", "boardWidth", XrmoptionSepArg, NULL },
1714 { "-boardHeight", "boardHeight", XrmoptionSepArg, NULL },
1715 { "-matchPause", "matchPause", XrmoptionSepArg, NULL },
1717 /* [HGM] new arguments of 4.3.xx. All except first three are back-end options, which should work immediately */
1718 { "-holdingsSize", "holdingsSize", XrmoptionSepArg, NULL }, // requires extensive front-end changes to work
1719 { "-flipBlack", "flipBlack", XrmoptionSepArg, NULL }, // requires front-end changes to work
1720 { "-allWhite", "allWhite", XrmoptionSepArg, NULL }, // requires front-end changes to work
1721 { "-pieceToCharTable", "pieceToCharTable", XrmoptionSepArg, NULL },
1722 { "-alphaRank", "alphaRank", XrmoptionSepArg, NULL },
1723 { "-testClaims", "testClaims", XrmoptionSepArg, NULL },
1724 { "-checkMates", "checkMates", XrmoptionSepArg, NULL },
1725 { "-materialDraws", "materialDraws", XrmoptionSepArg, NULL },
1726 { "-trivialDraws", "trivialDraws", XrmoptionSepArg, NULL },
1727 { "-ruleMoves", "ruleMoves", XrmoptionSepArg, NULL },
1728 { "-repeatsToDraw", "repeatsToDraw", XrmoptionSepArg, NULL },
1729 { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL },
1730 { "-userName", "userName", XrmoptionSepArg, NULL },
1731 { "-autoKibitz", "autoKibitz", XrmoptionNoArg, "True" },
1732 { "-firstTimeOdds", "firstTimeOdds", XrmoptionSepArg, NULL },
1733 { "-secondTimeOdds", "secondTimeOdds", XrmoptionSepArg, NULL },
1734 { "-timeOddsMode", "timeOddsMode", XrmoptionSepArg, NULL },
1735 { "-firstAccumulateTC", "firstAccumulateTC", XrmoptionSepArg, NULL },
1736 { "-secondAccumulateTC", "secondAccumulateTC", XrmoptionSepArg, NULL },
1737 { "-firstNPS", "firstNPS", XrmoptionSepArg, NULL },
1738 { "-secondNPS", "secondNPS", XrmoptionSepArg, NULL },
1739 { "-serverMoves", "serverMoves", XrmoptionSepArg, NULL },
1740 { "-serverPause", "serverPause", XrmoptionSepArg, NULL },
1741 { "-suppressLoadMoves", "suppressLoadMoves", XrmoptionSepArg, NULL },
1742 { "-egtFormats", "egtFormats", XrmoptionSepArg, NULL },
1743 { "-userName", "userName", XrmoptionSepArg, NULL },
1744 { "-smpCores", "smpCores", XrmoptionSepArg, NULL },
1745 { "-sameColorGames", "sameColorGames", XrmoptionSepArg, NULL },
1746 { "-rewindIndex", "rewindIndex", XrmoptionSepArg, NULL },
1747 { "-niceEngines", "niceEngines", XrmoptionSepArg, NULL },
1748 { "-delayBeforeQuit", "delayBeforeQuit", XrmoptionSepArg, NULL },
1749 { "-delayAfterQuit", "delayAfterQuit", XrmoptionSepArg, NULL },
1750 { "-nameOfDebugFile", "nameOfDebugFile", XrmoptionSepArg, NULL },
1751 { "-debugFile", "nameOfDebugFile", XrmoptionSepArg, NULL },
1752 { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL },
1753 { "-noGUI", "noGUI", XrmoptionNoArg, "True" },
1754 { "-firstOptions", "firstOptions", XrmoptionSepArg, NULL },
1755 { "-secondOptions", "secondOptions", XrmoptionSepArg, NULL },
1756 { "-firstNeedsNoncompliantFEN", "firstNeedsNoncompliantFEN", XrmoptionSepArg, NULL },
1757 { "-secondNeedsNoncompliantFEN", "secondNeedsNoncompliantFEN", XrmoptionSepArg, NULL },
1761 XtActionsRec boardActions[] = {
1762 { "DrawPosition", DrawPositionProc },
1763 { "HandleUserMove", HandleUserMove },
1764 { "AnimateUserMove", AnimateUserMove },
1765 { "FileNameAction", FileNameAction },
1766 { "AskQuestionProc", AskQuestionProc },
1767 { "AskQuestionReplyAction", AskQuestionReplyAction },
1768 { "PieceMenuPopup", PieceMenuPopup },
1769 { "WhiteClock", WhiteClock },
1770 { "BlackClock", BlackClock },
1771 { "Iconify", Iconify },
1772 { "ResetProc", ResetProc },
1773 { "LoadGameProc", LoadGameProc },
1774 { "LoadNextGameProc", LoadNextGameProc },
1775 { "LoadPrevGameProc", LoadPrevGameProc },
1776 { "LoadSelectedProc", LoadSelectedProc },
1777 { "ReloadGameProc", ReloadGameProc },
1778 { "LoadPositionProc", LoadPositionProc },
1779 { "LoadNextPositionProc", LoadNextPositionProc },
1780 { "LoadPrevPositionProc", LoadPrevPositionProc },
1781 { "ReloadPositionProc", ReloadPositionProc },
1782 { "CopyPositionProc", CopyPositionProc },
1783 { "PastePositionProc", PastePositionProc },
1784 { "CopyGameProc", CopyGameProc },
1785 { "PasteGameProc", PasteGameProc },
1786 { "SaveGameProc", SaveGameProc },
1787 { "SavePositionProc", SavePositionProc },
1788 { "MailMoveProc", MailMoveProc },
1789 { "ReloadCmailMsgProc", ReloadCmailMsgProc },
1790 { "QuitProc", QuitProc },
1791 { "MachineWhiteProc", MachineWhiteProc },
1792 { "MachineBlackProc", MachineBlackProc },
1793 { "AnalysisModeProc", AnalyzeModeProc },
1794 { "AnalyzeFileProc", AnalyzeFileProc },
1795 { "TwoMachinesProc", TwoMachinesProc },
1796 { "IcsClientProc", IcsClientProc },
1797 { "EditGameProc", EditGameProc },
1798 { "EditPositionProc", EditPositionProc },
1799 { "TrainingProc", EditPositionProc },
1800 { "EngineOutputProc", EngineOutputProc}, // [HGM] Winboard_x engine-output window
1801 { "ShowGameListProc", ShowGameListProc },
1802 { "ShowMoveListProc", HistoryShowProc},
1803 { "EditTagsProc", EditCommentProc },
1804 { "EditCommentProc", EditCommentProc },
1805 { "IcsAlarmProc", IcsAlarmProc },
1806 { "IcsInputBoxProc", IcsInputBoxProc },
1807 { "PauseProc", PauseProc },
1808 { "AcceptProc", AcceptProc },
1809 { "DeclineProc", DeclineProc },
1810 { "RematchProc", RematchProc },
1811 { "CallFlagProc", CallFlagProc },
1812 { "DrawProc", DrawProc },
1813 { "AdjournProc", AdjournProc },
1814 { "AbortProc", AbortProc },
1815 { "ResignProc", ResignProc },
1816 { "AdjuWhiteProc", AdjuWhiteProc },
1817 { "AdjuBlackProc", AdjuBlackProc },
1818 { "AdjuDrawProc", AdjuDrawProc },
1819 { "EnterKeyProc", EnterKeyProc },
1820 { "StopObservingProc", StopObservingProc },
1821 { "StopExaminingProc", StopExaminingProc },
1822 { "BackwardProc", BackwardProc },
1823 { "ForwardProc", ForwardProc },
1824 { "ToStartProc", ToStartProc },
1825 { "ToEndProc", ToEndProc },
1826 { "RevertProc", RevertProc },
1827 { "TruncateGameProc", TruncateGameProc },
1828 { "MoveNowProc", MoveNowProc },
1829 { "RetractMoveProc", RetractMoveProc },
1830 { "AlwaysQueenProc", AlwaysQueenProc },
1831 { "AnimateDraggingProc", AnimateDraggingProc },
1832 { "AnimateMovingProc", AnimateMovingProc },
1833 { "AutoflagProc", AutoflagProc },
1834 { "AutoflipProc", AutoflipProc },
1835 { "AutobsProc", AutobsProc },
1836 { "AutoraiseProc", AutoraiseProc },
1837 { "AutosaveProc", AutosaveProc },
1838 { "BlindfoldProc", BlindfoldProc },
1839 { "FlashMovesProc", FlashMovesProc },
1840 { "FlipViewProc", FlipViewProc },
1841 { "GetMoveListProc", GetMoveListProc },
1843 { "HighlightDraggingProc", HighlightDraggingProc },
1845 { "HighlightLastMoveProc", HighlightLastMoveProc },
1846 { "IcsAlarmProc", IcsAlarmProc },
1847 { "MoveSoundProc", MoveSoundProc },
1848 { "OldSaveStyleProc", OldSaveStyleProc },
1849 { "PeriodicUpdatesProc", PeriodicUpdatesProc },
1850 { "PonderNextMoveProc", PonderNextMoveProc },
1851 { "PopupExitMessageProc", PopupExitMessageProc },
1852 { "PopupMoveErrorsProc", PopupMoveErrorsProc },
1853 { "PremoveProc", PremoveProc },
1854 { "QuietPlayProc", QuietPlayProc },
1855 { "ShowCoordsProc", ShowCoordsProc },
1856 { "ShowThinkingProc", ShowThinkingProc },
1857 { "HideThinkingProc", HideThinkingProc },
1858 { "TestLegalityProc", TestLegalityProc },
1859 { "InfoProc", InfoProc },
1860 { "ManProc", ManProc },
1861 { "HintProc", HintProc },
1862 { "BookProc", BookProc },
1863 { "AboutGameProc", AboutGameProc },
1864 { "AboutProc", AboutProc },
1865 { "DebugProc", DebugProc },
1866 { "NothingProc", NothingProc },
1867 { "CommentPopDown", (XtActionProc) CommentPopDown },
1868 { "EditCommentPopDown", (XtActionProc) EditCommentPopDown },
1869 { "TagsPopDown", (XtActionProc) TagsPopDown },
1870 { "ErrorPopDown", (XtActionProc) ErrorPopDown },
1871 { "ICSInputBoxPopDown", (XtActionProc) ICSInputBoxPopDown },
1872 { "AnalysisPopDown", (XtActionProc) AnalysisPopDown },
1873 { "FileNamePopDown", (XtActionProc) FileNamePopDown },
1874 { "AskQuestionPopDown", (XtActionProc) AskQuestionPopDown },
1875 { "GameListPopDown", (XtActionProc) GameListPopDown },
1876 { "PromotionPopDown", (XtActionProc) PromotionPopDown },
1877 { "HistoryPopDown", (XtActionProc) HistoryPopDown },
1878 { "EngineOutputPopDown", (XtActionProc) EngineOutputPopDown },
1879 { "ShufflePopDown", (XtActionProc) ShufflePopDown },
1880 { "EnginePopDown", (XtActionProc) EnginePopDown },
1881 { "UciPopDown", (XtActionProc) UciPopDown },
1882 { "TimeControlPopDown", (XtActionProc) TimeControlPopDown },
1883 { "NewVariantPopDown", (XtActionProc) NewVariantPopDown },
1884 { "SettingsPopDown", (XtActionProc) SettingsPopDown },
1887 char globalTranslations[] =
1888 ":<Key>R: ResignProc() \n \
1889 :<Key>r: ResetProc() \n \
1890 :<Key>g: LoadGameProc() \n \
1891 :<Key>N: LoadNextGameProc() \n \
1892 :<Key>P: LoadPrevGameProc() \n \
1893 :<Key>Q: QuitProc() \n \
1894 :<Key>F: ToEndProc() \n \
1895 :<Key>f: ForwardProc() \n \
1896 :<Key>B: ToStartProc() \n \
1897 :<Key>b: BackwardProc() \n \
1898 :<Key>p: PauseProc() \n \
1899 :<Key>d: DrawProc() \n \
1900 :<Key>t: CallFlagProc() \n \
1901 :<Key>i: Iconify() \n \
1902 :<Key>c: Iconify() \n \
1903 :<Key>v: FlipViewProc() \n \
1904 <KeyDown>Control_L: BackwardProc() \n \
1905 <KeyUp>Control_L: ForwardProc() \n \
1906 <KeyDown>Control_R: BackwardProc() \n \
1907 <KeyUp>Control_R: ForwardProc() \n \
1908 Shift<Key>1: AskQuestionProc(\"Direct command\",\
1909 \"Send to chess program:\",,1) \n \
1910 Shift<Key>2: AskQuestionProc(\"Direct command\",\
1911 \"Send to second chess program:\",,2) \n";
1913 char boardTranslations[] =
1914 "<Btn1Down>: HandleUserMove() \n \
1915 <Btn1Up>: HandleUserMove() \n \
1916 <Btn1Motion>: AnimateUserMove() \n \
1917 Shift<Btn2Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD)\
1918 PieceMenuPopup(menuB) \n \
1919 Any<Btn2Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD) \
1920 PieceMenuPopup(menuW) \n \
1921 Shift<Btn3Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD)\
1922 PieceMenuPopup(menuW) \n \
1923 Any<Btn3Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD) \
1924 PieceMenuPopup(menuB) \n";
1926 char whiteTranslations[] = "<BtnDown>: WhiteClock()\n";
1927 char blackTranslations[] = "<BtnDown>: BlackClock()\n";
1929 char ICSInputTranslations[] =
1930 "<Key>Return: EnterKeyProc() \n";
1932 String xboardResources[] = {
1933 "*fileName*value.translations: #override\\n <Key>Return: FileNameAction()",
1934 "*question*value.translations: #override\\n <Key>Return: AskQuestionReplyAction()",
1935 "*errorpopup*translations: #override\\n <Key>Return: ErrorPopDown()",
1940 /* Max possible square size */
1941 #define MAXSQSIZE 256
1943 static int xpm_avail[MAXSQSIZE];
1945 #ifdef HAVE_DIR_STRUCT
1947 /* Extract piece size from filename */
1949 xpm_getsize(name, len, ext)
1960 if ((p=strchr(name, '.')) == NULL ||
1961 StrCaseCmp(p+1, ext) != 0)
1967 while (*p && isdigit(*p))
1974 /* Setup xpm_avail */
1976 xpm_getavail(dirname, ext)
1984 for (i=0; i<MAXSQSIZE; ++i)
1987 if (appData.debugMode)
1988 fprintf(stderr, "XPM dir:%s:ext:%s:\n", dirname, ext);
1990 dir = opendir(dirname);
1993 fprintf(stderr, _("%s: Can't access XPM directory %s\n"),
1994 programName, dirname);
1998 while ((ent=readdir(dir)) != NULL) {
1999 i = xpm_getsize(ent->d_name, NAMLEN(ent), ext);
2000 if (i > 0 && i < MAXSQSIZE)
2010 xpm_print_avail(fp, ext)
2016 fprintf(fp, _("Available `%s' sizes:\n"), ext);
2017 for (i=1; i<MAXSQSIZE; ++i) {
2023 /* Return XPM piecesize closest to size */
2025 xpm_closest_to(dirname, size, ext)
2031 int sm_diff = MAXSQSIZE;
2035 xpm_getavail(dirname, ext);
2037 if (appData.debugMode)
2038 xpm_print_avail(stderr, ext);
2040 for (i=1; i<MAXSQSIZE; ++i) {
2043 diff = (diff<0) ? -diff : diff;
2044 if (diff < sm_diff) {
2052 fprintf(stderr, _("Error: No `%s' files!\n"), ext);
2058 #else /* !HAVE_DIR_STRUCT */
2059 /* If we are on a system without a DIR struct, we can't
2060 read the directory, so we can't collect a list of
2061 filenames, etc., so we can't do any size-fitting. */
2063 xpm_closest_to(dirname, size, ext)
2068 fprintf(stderr, _("\
2069 Warning: No DIR structure found on this system --\n\
2070 Unable to autosize for XPM/XIM pieces.\n\
2071 Please report this error to frankm@hiwaay.net.\n\
2072 Include system type & operating system in message.\n"));
2075 #endif /* HAVE_DIR_STRUCT */
2077 static char *cnames[9] = { "black", "red", "green", "yellow", "blue",
2078 "magenta", "cyan", "white" };
2082 TextColors textColors[(int)NColorClasses];
2084 /* String is: "fg, bg, attr". Which is 0, 1, 2 */
2086 parse_color(str, which)
2090 char *p, buf[100], *d;
2093 if (strlen(str) > 99) /* watch bounds on buf */
2098 for (i=0; i<which; ++i) {
2105 /* Could be looking at something like:
2107 .. in which case we want to stop on a comma also */
2108 while (*p && *p != ',' && !isalpha(*p) && !isdigit(*p))
2112 return -1; /* Use default for empty field */
2115 if (which == 2 || isdigit(*p))
2118 while (*p && isalpha(*p))
2123 for (i=0; i<8; ++i) {
2124 if (!StrCaseCmp(buf, cnames[i]))
2125 return which? (i+40) : (i+30);
2127 if (!StrCaseCmp(buf, "default")) return -1;
2129 fprintf(stderr, _("%s: unrecognized color %s\n"), programName, buf);
2134 parse_cpair(cc, str)
2138 if ((textColors[(int)cc].fg=parse_color(str, 0)) == -2) {
2139 fprintf(stderr, _("%s: can't parse foreground color in `%s'\n"),
2144 /* bg and attr are optional */
2145 textColors[(int)cc].bg = parse_color(str, 1);
2146 if ((textColors[(int)cc].attr = parse_color(str, 2)) < 0) {
2147 textColors[(int)cc].attr = 0;
2153 /* Arrange to catch delete-window events */
2154 Atom wm_delete_window;
2156 CatchDeleteWindow(Widget w, String procname)
2159 XSetWMProtocols(xDisplay, XtWindow(w), &wm_delete_window, 1);
2160 snprintf(buf, sizeof(buf), "<Message>WM_PROTOCOLS: %s() \n", procname);
2161 XtAugmentTranslations(w, XtParseTranslationTable(buf));
2168 XtSetArg(args[0], XtNiconic, False);
2169 XtSetValues(shellWidget, args, 1);
2171 XtPopup(shellWidget, XtGrabNone); /* Raise if lowered */
2175 // eventually, all layout determining code should go into a subroutine, but until then IDSIZE remains undefined
2177 #define BoardSize int
2178 void InitDrawingSizes(BoardSize boardSize, int flags)
2179 { // [HGM] resize is functional now, but for board format changes only (nr of ranks, files)
2180 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
2182 XtGeometryResult gres;
2185 if(!formWidget) return;
2188 * Enable shell resizing.
2190 shellArgs[0].value = (XtArgVal) &w;
2191 shellArgs[1].value = (XtArgVal) &h;
2192 XtGetValues(shellWidget, shellArgs, 2);
2194 shellArgs[4].value = 2*w; shellArgs[2].value = 10;
2195 shellArgs[5].value = 2*h; shellArgs[3].value = 10;
2196 XtSetValues(shellWidget, &shellArgs[2], 4);
2198 XtSetArg(args[0], XtNdefaultDistance, &sep);
2199 XtGetValues(formWidget, args, 1);
2201 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2202 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2205 XtSetArg(args[0], XtNwidth, boardWidth);
2206 XtSetArg(args[1], XtNheight, boardHeight);
2207 XtSetValues(boardWidget, args, 2);
2209 timerWidth = (boardWidth - sep) / 2;
2210 XtSetArg(args[0], XtNwidth, timerWidth);
2211 XtSetValues(whiteTimerWidget, args, 1);
2212 XtSetValues(blackTimerWidget, args, 1);
2214 XawFormDoLayout(formWidget, False);
2216 if (appData.titleInWindow) {
2218 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2219 XtSetArg(args[i], XtNheight, &h); i++;
2220 XtGetValues(titleWidget, args, i);
2222 w = boardWidth - 2*bor;
2224 XtSetArg(args[0], XtNwidth, &w);
2225 XtGetValues(menuBarWidget, args, 1);
2226 w = boardWidth - w - sep - 2*bor - 2; // WIDTH_FUDGE
2229 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
2230 if (gres != XtGeometryYes && appData.debugMode) {
2232 _("%s: titleWidget geometry error %d %d %d %d %d\n"),
2233 programName, gres, w, h, wr, hr);
2237 XawFormDoLayout(formWidget, True);
2240 * Inhibit shell resizing.
2242 shellArgs[0].value = w = (XtArgVal) boardWidth + marginW;
2243 shellArgs[1].value = h = (XtArgVal) boardHeight + marginH;
2244 shellArgs[4].value = shellArgs[2].value = w;
2245 shellArgs[5].value = shellArgs[3].value = h;
2246 XtSetValues(shellWidget, &shellArgs[0], 6);
2255 int i, j, clockFontPxlSize, coordFontPxlSize, fontPxlSize;
2256 XSetWindowAttributes window_attributes;
2258 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
2259 XrmValue vFrom, vTo;
2260 XtGeometryResult gres;
2263 int forceMono = False;
2266 // [HGM] before anything else, expand any indirection files amongst options
2267 char *argvCopy[1000]; // 1000 seems enough
2268 char newArgs[10000]; // holds actual characters
2271 srandom(time(0)); // [HGM] book: make random truly random
2274 for(i=0; i<argc; i++) {
2275 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2276 //fprintf(stderr, "arg %s\n", argv[i]);
2277 if(argv[i][0] != '@') argvCopy[j++] = argv[i]; else {
2279 FILE *f = fopen(argv[i]+1, "rb");
2280 if(f == NULL) { fprintf(stderr, _("ignore %s\n"), argv[i]); continue; } // do not expand non-existing
2281 argvCopy[j++] = newArgs + k; // get ready for first argument from file
2282 while((c = fgetc(f)) != EOF) { // each line of file inserts 1 argument in the list
2284 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2285 newArgs[k++] = 0; // terminate current arg
2286 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2287 argvCopy[j++] = newArgs + k; // get ready for next
2289 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2302 if(appData.debugMode,1) { // OK, appData is not initialized here yet...
2303 for(i=0; i<argc; i++) fprintf(stderr, "argv[%2d] = '%s'\n", i, argv[i]);
2309 setbuf(stdout, NULL);
2310 setbuf(stderr, NULL);
2313 programName = strrchr(argv[0], '/');
2314 if (programName == NULL)
2315 programName = argv[0];
2320 XtSetLanguageProc(NULL, NULL, NULL);
2321 bindtextdomain(PRODUCT, LOCALEDIR);
2322 textdomain(PRODUCT);
2326 XtAppInitialize(&appContext, "XBoard", shellOptions,
2327 XtNumber(shellOptions),
2328 &argc, argv, xboardResources, NULL, 0);
2330 fprintf(stderr, _("%s: unrecognized argument %s\n"),
2331 programName, argv[1]);
2332 fprintf(stderr, "Recognized options:\n");
2333 for(i = 0; i < XtNumber(shellOptions); i++) {
2334 j = fprintf(stderr, " %s%s", shellOptions[i].option,
2335 (shellOptions[i].argKind == XrmoptionSepArg
2337 if (i++ < XtNumber(shellOptions)) {
2338 fprintf(stderr, "%*c%s%s\n", 40 - j, ' ',
2339 shellOptions[i].option,
2340 (shellOptions[i].argKind == XrmoptionSepArg
2343 fprintf(stderr, "\n");
2349 if ((chessDir = (char *) getenv("CHESSDIR")) == NULL) {
2352 if (chdir(chessDir) != 0) {
2353 fprintf(stderr, _("%s: can't cd to CHESSDIR: "), programName);
2360 if (p == NULL) p = "/tmp";
2361 i = strlen(p) + strlen("/.xboardXXXXXx.pgn") + 1;
2362 gameCopyFilename = (char*) malloc(i);
2363 gamePasteFilename = (char*) malloc(i);
2364 snprintf(gameCopyFilename,i, "%s/.xboard%05uc.pgn", p, getpid());
2365 snprintf(gamePasteFilename,i, "%s/.xboard%05up.pgn", p, getpid());
2367 XtGetApplicationResources(shellWidget, (XtPointer) &appData,
2368 clientResources, XtNumber(clientResources),
2371 if (appData.debugMode && appData.nameOfDebugFile && strcmp(appData.nameOfDebugFile, "stderr")) {
2372 /* [DM] debug info to file [HGM] make the filename a command-line option, and allow it to remain stderr */
2373 if ((debugFP = fopen(appData.nameOfDebugFile, "w")) == NULL) {
2374 printf(_("Failed to open file '%s'\n"), appData.nameOfDebugFile);
2377 setbuf(debugFP, NULL);
2380 /* [HGM,HR] make sure board size is acceptable */
2381 if(appData.NrFiles > BOARD_SIZE ||
2382 appData.NrRanks > BOARD_SIZE )
2383 DisplayFatalError(_("Recompile with BOARD_SIZE > 12, to support this size"), 0, 2);
2386 /* This feature does not work; animation needs a rewrite */
2387 appData.highlightDragging = FALSE;
2391 xDisplay = XtDisplay(shellWidget);
2392 xScreen = DefaultScreen(xDisplay);
2393 wm_delete_window = XInternAtom(xDisplay, "WM_DELETE_WINDOW", True);
2395 gameInfo.variant = StringToVariant(appData.variant);
2396 InitPosition(FALSE);
2399 * Determine boardSize
2401 gameInfo.boardWidth = gameInfo.boardHeight = 8; // [HGM] boardsize: make sure we start as 8x8
2404 // [HGM] as long as we have not created the possibility to change size while running, start with requested size
2405 gameInfo.boardWidth = appData.NrFiles > 0 ? appData.NrFiles : 8;
2406 gameInfo.boardHeight = appData.NrRanks > 0 ? appData.NrRanks : 8;
2407 gameInfo.holdingsWidth = appData.holdingsSize > 0 ? 2 : 0;
2412 InitDrawingSizes(-1, 0); // [HGM] initsize: make this into a subroutine
2414 if (isdigit(appData.boardSize[0])) {
2415 i = sscanf(appData.boardSize, "%d,%d,%d,%d,%d,%d,%d", &squareSize,
2416 &lineGap, &clockFontPxlSize, &coordFontPxlSize,
2417 &fontPxlSize, &smallLayout, &tinyLayout);
2419 fprintf(stderr, _("%s: bad boardSize syntax %s\n"),
2420 programName, appData.boardSize);
2424 /* Find some defaults; use the nearest known size */
2425 SizeDefaults *szd, *nearest;
2426 int distance = 99999;
2427 nearest = szd = sizeDefaults;
2428 while (szd->name != NULL) {
2429 if (abs(szd->squareSize - squareSize) < distance) {
2431 distance = abs(szd->squareSize - squareSize);
2432 if (distance == 0) break;
2436 if (i < 2) lineGap = nearest->lineGap;
2437 if (i < 3) clockFontPxlSize = nearest->clockFontPxlSize;
2438 if (i < 4) coordFontPxlSize = nearest->coordFontPxlSize;
2439 if (i < 5) fontPxlSize = nearest->fontPxlSize;
2440 if (i < 6) smallLayout = nearest->smallLayout;
2441 if (i < 7) tinyLayout = nearest->tinyLayout;
2444 SizeDefaults *szd = sizeDefaults;
2445 if (*appData.boardSize == NULLCHAR) {
2446 while (DisplayWidth(xDisplay, xScreen) < szd->minScreenSize ||
2447 DisplayHeight(xDisplay, xScreen) < szd->minScreenSize) {
2450 if (szd->name == NULL) szd--;
2452 while (szd->name != NULL &&
2453 StrCaseCmp(szd->name, appData.boardSize) != 0) szd++;
2454 if (szd->name == NULL) {
2455 fprintf(stderr, _("%s: unrecognized boardSize name %s\n"),
2456 programName, appData.boardSize);
2460 squareSize = szd->squareSize;
2461 lineGap = szd->lineGap;
2462 clockFontPxlSize = szd->clockFontPxlSize;
2463 coordFontPxlSize = szd->coordFontPxlSize;
2464 fontPxlSize = szd->fontPxlSize;
2465 smallLayout = szd->smallLayout;
2466 tinyLayout = szd->tinyLayout;
2469 /* Now, using squareSize as a hint, find a good XPM/XIM set size */
2470 if (strlen(appData.pixmapDirectory) > 0) {
2471 p = ExpandPathName(appData.pixmapDirectory);
2473 fprintf(stderr, _("Error expanding path name \"%s\"\n"),
2474 appData.pixmapDirectory);
2477 if (appData.debugMode) {
2478 fprintf(stderr, _("\
2479 XBoard square size (hint): %d\n\
2480 %s fulldir:%s:\n"), squareSize, IMAGE_EXT, p);
2482 squareSize = xpm_closest_to(p, squareSize, IMAGE_EXT);
2483 if (appData.debugMode) {
2484 fprintf(stderr, _("Closest %s size: %d\n"), IMAGE_EXT, squareSize);
2488 /* [HR] height treated separately (hacked) */
2489 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2490 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2491 if (appData.showJail == 1) {
2492 /* Jail on top and bottom */
2493 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2494 XtSetArg(boardArgs[2], XtNheight,
2495 boardHeight + 2*(lineGap + squareSize));
2496 } else if (appData.showJail == 2) {
2498 XtSetArg(boardArgs[1], XtNwidth,
2499 boardWidth + 2*(lineGap + squareSize));
2500 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2503 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2504 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2508 * Determine what fonts to use.
2510 appData.clockFont = FindFont(appData.clockFont, clockFontPxlSize);
2511 clockFontID = XLoadFont(xDisplay, appData.clockFont);
2512 clockFontStruct = XQueryFont(xDisplay, clockFontID);
2513 appData.coordFont = FindFont(appData.coordFont, coordFontPxlSize);
2514 coordFontID = XLoadFont(xDisplay, appData.coordFont);
2515 coordFontStruct = XQueryFont(xDisplay, coordFontID);
2516 appData.font = FindFont(appData.font, fontPxlSize);
2517 countFontID = XLoadFont(xDisplay, appData.coordFont); // [HGM] holdings
2518 countFontStruct = XQueryFont(xDisplay, countFontID);
2519 // appData.font = FindFont(appData.font, fontPxlSize);
2521 xdb = XtDatabase(xDisplay);
2522 XrmPutStringResource(&xdb, "*font", appData.font);
2525 * Detect if there are not enough colors available and adapt.
2527 if (DefaultDepth(xDisplay, xScreen) <= 2) {
2528 appData.monoMode = True;
2531 if (!appData.monoMode) {
2532 vFrom.addr = (caddr_t) appData.lightSquareColor;
2533 vFrom.size = strlen(appData.lightSquareColor);
2534 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2535 if (vTo.addr == NULL) {
2536 appData.monoMode = True;
2539 lightSquareColor = *(Pixel *) vTo.addr;
2542 if (!appData.monoMode) {
2543 vFrom.addr = (caddr_t) appData.darkSquareColor;
2544 vFrom.size = strlen(appData.darkSquareColor);
2545 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2546 if (vTo.addr == NULL) {
2547 appData.monoMode = True;
2550 darkSquareColor = *(Pixel *) vTo.addr;
2553 if (!appData.monoMode) {
2554 vFrom.addr = (caddr_t) appData.whitePieceColor;
2555 vFrom.size = strlen(appData.whitePieceColor);
2556 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2557 if (vTo.addr == NULL) {
2558 appData.monoMode = True;
2561 whitePieceColor = *(Pixel *) vTo.addr;
2564 if (!appData.monoMode) {
2565 vFrom.addr = (caddr_t) appData.blackPieceColor;
2566 vFrom.size = strlen(appData.blackPieceColor);
2567 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2568 if (vTo.addr == NULL) {
2569 appData.monoMode = True;
2572 blackPieceColor = *(Pixel *) vTo.addr;
2576 if (!appData.monoMode) {
2577 vFrom.addr = (caddr_t) appData.highlightSquareColor;
2578 vFrom.size = strlen(appData.highlightSquareColor);
2579 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2580 if (vTo.addr == NULL) {
2581 appData.monoMode = True;
2584 highlightSquareColor = *(Pixel *) vTo.addr;
2588 if (!appData.monoMode) {
2589 vFrom.addr = (caddr_t) appData.premoveHighlightColor;
2590 vFrom.size = strlen(appData.premoveHighlightColor);
2591 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2592 if (vTo.addr == NULL) {
2593 appData.monoMode = True;
2596 premoveHighlightColor = *(Pixel *) vTo.addr;
2601 fprintf(stderr, _("%s: too few colors available; trying monochrome mode\n"),
2604 if (appData.bitmapDirectory == NULL ||
2605 appData.bitmapDirectory[0] == NULLCHAR)
2606 appData.bitmapDirectory = DEF_BITMAP_DIR;
2609 if (appData.lowTimeWarning && !appData.monoMode) {
2610 vFrom.addr = (caddr_t) appData.lowTimeWarningColor;
2611 vFrom.size = strlen(appData.lowTimeWarningColor);
2612 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2613 if (vTo.addr == NULL)
2614 appData.monoMode = True;
2616 lowTimeWarningColor = *(Pixel *) vTo.addr;
2619 if (appData.monoMode && appData.debugMode) {
2620 fprintf(stderr, _("white pixel = 0x%lx, black pixel = 0x%lx\n"),
2621 (unsigned long) XWhitePixel(xDisplay, xScreen),
2622 (unsigned long) XBlackPixel(xDisplay, xScreen));
2625 if (parse_cpair(ColorShout, appData.colorShout) < 0 ||
2626 parse_cpair(ColorSShout, appData.colorSShout) < 0 ||
2627 parse_cpair(ColorChannel1, appData.colorChannel1) < 0 ||
2628 parse_cpair(ColorChannel, appData.colorChannel) < 0 ||
2629 parse_cpair(ColorKibitz, appData.colorKibitz) < 0 ||
2630 parse_cpair(ColorTell, appData.colorTell) < 0 ||
2631 parse_cpair(ColorChallenge, appData.colorChallenge) < 0 ||
2632 parse_cpair(ColorRequest, appData.colorRequest) < 0 ||
2633 parse_cpair(ColorSeek, appData.colorSeek) < 0 ||
2634 parse_cpair(ColorNormal, appData.colorNormal) < 0)
2636 if (appData.colorize) {
2638 _("%s: can't parse color names; disabling colorization\n"),
2641 appData.colorize = FALSE;
2643 textColors[ColorNone].fg = textColors[ColorNone].bg = -1;
2644 textColors[ColorNone].attr = 0;
2646 XtAppAddActions(appContext, boardActions, XtNumber(boardActions));
2652 layoutName = "tinyLayout";
2653 } else if (smallLayout) {
2654 layoutName = "smallLayout";
2656 layoutName = "normalLayout";
2658 /* Outer layoutWidget is there only to provide a name for use in
2659 resources that depend on the layout style */
2661 XtCreateManagedWidget(layoutName, formWidgetClass, shellWidget,
2662 layoutArgs, XtNumber(layoutArgs));
2664 XtCreateManagedWidget("form", formWidgetClass, layoutWidget,
2665 formArgs, XtNumber(formArgs));
2666 XtSetArg(args[0], XtNdefaultDistance, &sep);
2667 XtGetValues(formWidget, args, 1);
2670 widgetList[j++] = menuBarWidget = CreateMenuBar(menuBar);
2671 XtSetArg(args[0], XtNtop, XtChainTop);
2672 XtSetArg(args[1], XtNbottom, XtChainTop);
2673 XtSetValues(menuBarWidget, args, 2);
2675 widgetList[j++] = whiteTimerWidget =
2676 XtCreateWidget("whiteTime", labelWidgetClass,
2677 formWidget, timerArgs, XtNumber(timerArgs));
2678 XtSetArg(args[0], XtNfont, clockFontStruct);
2679 XtSetArg(args[1], XtNtop, XtChainTop);
2680 XtSetArg(args[2], XtNbottom, XtChainTop);
2681 XtSetValues(whiteTimerWidget, args, 3);
2683 widgetList[j++] = blackTimerWidget =
2684 XtCreateWidget("blackTime", labelWidgetClass,
2685 formWidget, timerArgs, XtNumber(timerArgs));
2686 XtSetArg(args[0], XtNfont, clockFontStruct);
2687 XtSetArg(args[1], XtNtop, XtChainTop);
2688 XtSetArg(args[2], XtNbottom, XtChainTop);
2689 XtSetValues(blackTimerWidget, args, 3);
2691 if (appData.titleInWindow) {
2692 widgetList[j++] = titleWidget =
2693 XtCreateWidget("title", labelWidgetClass, formWidget,
2694 titleArgs, XtNumber(titleArgs));
2695 XtSetArg(args[0], XtNtop, XtChainTop);
2696 XtSetArg(args[1], XtNbottom, XtChainTop);
2697 XtSetValues(titleWidget, args, 2);
2700 if (appData.showButtonBar) {
2701 widgetList[j++] = buttonBarWidget = CreateButtonBar(buttonBar);
2702 XtSetArg(args[0], XtNleft, XtChainRight); // [HGM] glue to right window edge
2703 XtSetArg(args[1], XtNright, XtChainRight); // for good run-time sizing
2704 XtSetArg(args[2], XtNtop, XtChainTop);
2705 XtSetArg(args[3], XtNbottom, XtChainTop);
2706 XtSetValues(buttonBarWidget, args, 4);
2709 widgetList[j++] = messageWidget =
2710 XtCreateWidget("message", labelWidgetClass, formWidget,
2711 messageArgs, XtNumber(messageArgs));
2712 XtSetArg(args[0], XtNtop, XtChainTop);
2713 XtSetArg(args[1], XtNbottom, XtChainTop);
2714 XtSetValues(messageWidget, args, 2);
2716 widgetList[j++] = boardWidget =
2717 XtCreateWidget("board", widgetClass, formWidget, boardArgs,
2718 XtNumber(boardArgs));
2720 XtManageChildren(widgetList, j);
2722 timerWidth = (boardWidth - sep) / 2;
2723 XtSetArg(args[0], XtNwidth, timerWidth);
2724 XtSetValues(whiteTimerWidget, args, 1);
2725 XtSetValues(blackTimerWidget, args, 1);
2727 XtSetArg(args[0], XtNbackground, &timerBackgroundPixel);
2728 XtSetArg(args[1], XtNforeground, &timerForegroundPixel);
2729 XtGetValues(whiteTimerWidget, args, 2);
2731 if (appData.showButtonBar) {
2732 XtSetArg(args[0], XtNbackground, &buttonBackgroundPixel);
2733 XtSetArg(args[1], XtNforeground, &buttonForegroundPixel);
2734 XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
2738 * formWidget uses these constraints but they are stored
2742 XtSetArg(args[i], XtNfromHoriz, 0); i++;
2743 XtSetValues(menuBarWidget, args, i);
2744 if (appData.titleInWindow) {
2747 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2748 XtSetValues(whiteTimerWidget, args, i);
2750 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2751 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2752 XtSetValues(blackTimerWidget, args, i);
2754 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2755 XtSetArg(args[i], XtNjustify, XtJustifyLeft); i++;
2756 XtSetValues(titleWidget, args, i);
2758 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2759 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2760 XtSetValues(messageWidget, args, i);
2761 if (appData.showButtonBar) {
2763 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2764 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2765 XtSetValues(buttonBarWidget, args, i);
2769 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2770 XtSetValues(whiteTimerWidget, args, i);
2772 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2773 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2774 XtSetValues(blackTimerWidget, args, i);
2776 XtSetArg(args[i], XtNfromHoriz, menuBarWidget); i++;
2777 XtSetValues(titleWidget, args, i);
2779 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2780 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2781 XtSetValues(messageWidget, args, i);
2782 if (appData.showButtonBar) {
2784 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2785 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2786 XtSetValues(buttonBarWidget, args, i);
2791 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2792 XtSetValues(whiteTimerWidget, args, i);
2794 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2795 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2796 XtSetValues(blackTimerWidget, args, i);
2798 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2799 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2800 XtSetValues(messageWidget, args, i);
2801 if (appData.showButtonBar) {
2803 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2804 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2805 XtSetValues(buttonBarWidget, args, i);
2809 XtSetArg(args[0], XtNfromVert, messageWidget);
2810 XtSetArg(args[1], XtNtop, XtChainTop);
2811 XtSetArg(args[2], XtNbottom, XtChainBottom);
2812 XtSetArg(args[3], XtNleft, XtChainLeft);
2813 XtSetArg(args[4], XtNright, XtChainRight);
2814 XtSetValues(boardWidget, args, 5);
2816 XtRealizeWidget(shellWidget);
2819 * Correct the width of the message and title widgets.
2820 * It is not known why some systems need the extra fudge term.
2821 * The value "2" is probably larger than needed.
2823 XawFormDoLayout(formWidget, False);
2825 #define WIDTH_FUDGE 2
2827 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2828 XtSetArg(args[i], XtNheight, &h); i++;
2829 XtGetValues(messageWidget, args, i);
2830 if (appData.showButtonBar) {
2832 XtSetArg(args[i], XtNwidth, &w); i++;
2833 XtGetValues(buttonBarWidget, args, i);
2834 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2836 w = boardWidth - 2*bor + 1; /*!! +1 compensates for kludge below */
2839 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2840 if (gres != XtGeometryYes && appData.debugMode) {
2841 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2842 programName, gres, w, h, wr, hr);
2845 /* !! Horrible hack to work around bug in XFree86 4.0.1 (X11R6.4.3) */
2846 /* The size used for the child widget in layout lags one resize behind
2847 its true size, so we resize a second time, 1 pixel smaller. Yeech! */
2849 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2850 if (gres != XtGeometryYes && appData.debugMode) {
2851 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2852 programName, gres, w, h, wr, hr);
2855 XtSetArg(args[0], XtNleft, XtChainLeft); // [HGM] glue ends for good run-time sizing
2856 XtSetArg(args[1], XtNright, XtChainRight);
2857 XtSetValues(messageWidget, args, 2);
2859 if (appData.titleInWindow) {
2861 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2862 XtSetArg(args[i], XtNheight, &h); i++;
2863 XtGetValues(titleWidget, args, i);
2865 w = boardWidth - 2*bor;
2867 XtSetArg(args[0], XtNwidth, &w);
2868 XtGetValues(menuBarWidget, args, 1);
2869 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2872 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
2873 if (gres != XtGeometryYes && appData.debugMode) {
2875 _("%s: titleWidget geometry error %d %d %d %d %d\n"),
2876 programName, gres, w, h, wr, hr);
2879 XawFormDoLayout(formWidget, True);
2881 xBoardWindow = XtWindow(boardWidget);
2883 // [HGM] it seems the layout code ends here, but perhaps the color stuff is size independent and would
2884 // not need to go into InitDrawingSizes().
2888 * Create X checkmark bitmap and initialize option menu checks.
2890 ReadBitmap(&xMarkPixmap, "checkmark.bm",
2891 checkmark_bits, checkmark_width, checkmark_height);
2892 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
2893 if (appData.alwaysPromoteToQueen) {
2894 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
2897 if (appData.animateDragging) {
2898 XtSetValues(XtNameToWidget(menuBarWidget,
2899 "menuOptions.Animate Dragging"),
2902 if (appData.animate) {
2903 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
2906 if (appData.autoComment) {
2907 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
2910 if (appData.autoCallFlag) {
2911 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
2914 if (appData.autoFlipView) {
2915 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Auto Flip View"),
2918 if (appData.autoObserve) {
2919 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
2922 if (appData.autoRaiseBoard) {
2923 XtSetValues(XtNameToWidget(menuBarWidget,
2924 "menuOptions.Auto Raise Board"), args, 1);
2926 if (appData.autoSaveGames) {
2927 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
2930 if (appData.saveGameFile[0] != NULLCHAR) {
2931 /* Can't turn this off from menu */
2932 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
2934 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
2938 if (appData.blindfold) {
2939 XtSetValues(XtNameToWidget(menuBarWidget,
2940 "menuOptions.Blindfold"), args, 1);
2942 if (appData.flashCount > 0) {
2943 XtSetValues(XtNameToWidget(menuBarWidget,
2944 "menuOptions.Flash Moves"),
2947 if (appData.getMoveList) {
2948 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
2952 if (appData.highlightDragging) {
2953 XtSetValues(XtNameToWidget(menuBarWidget,
2954 "menuOptions.Highlight Dragging"),
2958 if (appData.highlightLastMove) {
2959 XtSetValues(XtNameToWidget(menuBarWidget,
2960 "menuOptions.Highlight Last Move"),
2963 if (appData.icsAlarm) {
2964 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.ICS Alarm"),
2967 if (appData.ringBellAfterMoves) {
2968 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
2971 if (appData.oldSaveStyle) {
2972 XtSetValues(XtNameToWidget(menuBarWidget,
2973 "menuOptions.Old Save Style"), args, 1);
2975 if (appData.periodicUpdates) {
2976 XtSetValues(XtNameToWidget(menuBarWidget,
2977 "menuOptions.Periodic Updates"), args, 1);
2979 if (appData.ponderNextMove) {
2980 XtSetValues(XtNameToWidget(menuBarWidget,
2981 "menuOptions.Ponder Next Move"), args, 1);
2983 if (appData.popupExitMessage) {
2984 XtSetValues(XtNameToWidget(menuBarWidget,
2985 "menuOptions.Popup Exit Message"), args, 1);
2987 if (appData.popupMoveErrors) {
2988 XtSetValues(XtNameToWidget(menuBarWidget,
2989 "menuOptions.Popup Move Errors"), args, 1);
2991 if (appData.premove) {
2992 XtSetValues(XtNameToWidget(menuBarWidget,
2993 "menuOptions.Premove"), args, 1);
2995 if (appData.quietPlay) {
2996 XtSetValues(XtNameToWidget(menuBarWidget,
2997 "menuOptions.Quiet Play"), args, 1);
2999 if (appData.showCoords) {
3000 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
3003 if (appData.hideThinkingFromHuman) {
3004 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
3007 if (appData.testLegality) {
3008 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Test Legality"),
3015 ReadBitmap(&wIconPixmap, "icon_white.bm",
3016 icon_white_bits, icon_white_width, icon_white_height);
3017 ReadBitmap(&bIconPixmap, "icon_black.bm",
3018 icon_black_bits, icon_black_width, icon_black_height);
3019 iconPixmap = wIconPixmap;
3021 XtSetArg(args[i], XtNiconPixmap, iconPixmap); i++;
3022 XtSetValues(shellWidget, args, i);
3025 * Create a cursor for the board widget.
3027 window_attributes.cursor = XCreateFontCursor(xDisplay, XC_hand2);
3028 XChangeWindowAttributes(xDisplay, xBoardWindow,
3029 CWCursor, &window_attributes);
3032 * Inhibit shell resizing.
3034 shellArgs[0].value = (XtArgVal) &w;
3035 shellArgs[1].value = (XtArgVal) &h;
3036 XtGetValues(shellWidget, shellArgs, 2);
3037 shellArgs[4].value = shellArgs[2].value = w;
3038 shellArgs[5].value = shellArgs[3].value = h;
3039 XtSetValues(shellWidget, &shellArgs[2], 4);
3040 marginW = w - boardWidth; // [HGM] needed to set new shellWidget size when we resize board
3041 marginH = h - boardHeight;
3043 CatchDeleteWindow(shellWidget, "QuitProc");
3048 if (appData.bitmapDirectory[0] != NULLCHAR) {
3055 /* Create regular pieces */
3056 if (!useImages) CreatePieces();
3061 if (appData.animate || appData.animateDragging)
3064 XtAugmentTranslations(formWidget,
3065 XtParseTranslationTable(globalTranslations));
3066 XtAugmentTranslations(boardWidget,
3067 XtParseTranslationTable(boardTranslations));
3068 XtAugmentTranslations(whiteTimerWidget,
3069 XtParseTranslationTable(whiteTranslations));
3070 XtAugmentTranslations(blackTimerWidget,
3071 XtParseTranslationTable(blackTranslations));
3073 /* Why is the following needed on some versions of X instead
3074 * of a translation? */
3075 XtAddEventHandler(boardWidget, ExposureMask, False,
3076 (XtEventHandler) EventProc, NULL);
3081 if (errorExitStatus == -1) {
3082 if (appData.icsActive) {
3083 /* We now wait until we see "login:" from the ICS before
3084 sending the logon script (problems with timestamp otherwise) */
3085 /*ICSInitScript();*/
3086 if (appData.icsInputBox) ICSInputBoxPopUp();
3089 signal(SIGINT, IntSigHandler);
3090 signal(SIGTERM, IntSigHandler);
3091 if (*appData.cmailGameName != NULLCHAR) {
3092 signal(SIGUSR1, CmailSigHandler);
3097 XtAppMainLoop(appContext);
3098 if (appData.debugMode) fclose(debugFP); // [DM] debug
3105 if (appData.icsActive && oldICSInteractionTitle != NULL) {
3106 DisplayIcsInteractionTitle(oldICSInteractionTitle);
3108 unlink(gameCopyFilename);
3109 unlink(gamePasteFilename);
3120 CmailSigHandler(sig)
3126 signal(SIGUSR1, SIG_IGN); /* suspend handler */
3128 /* Activate call-back function CmailSigHandlerCallBack() */
3129 OutputToProcess(cmailPR, (char *)(&dummy), sizeof(int), &error);
3131 signal(SIGUSR1, CmailSigHandler); /* re-activate handler */
3135 CmailSigHandlerCallBack(isr, closure, message, count, error)
3143 ReloadCmailMsgEvent(TRUE); /* Reload cmail msg */
3145 /**** end signal code ****/
3155 f = fopen(appData.icsLogon, "r");
3161 strcat(buf, appData.icsLogon);
3162 f = fopen(buf, "r");
3166 ProcessICSInitScript(f);
3173 EditCommentPopDown();
3184 SetMenuEnables(enab)
3188 if (!menuBarWidget) return;
3189 while (enab->name != NULL) {
3190 w = XtNameToWidget(menuBarWidget, enab->name);
3192 DisplayError(enab->name, 0);
3194 XtSetSensitive(w, enab->value);
3200 Enables icsEnables[] = {
3201 { "menuFile.Mail Move", False },
3202 { "menuFile.Reload CMail Message", False },
3203 { "menuMode.Machine Black", False },
3204 { "menuMode.Machine White", False },
3205 { "menuMode.Analysis Mode", False },
3206 { "menuMode.Analyze File", False },
3207 { "menuMode.Two Machines", False },
3209 { "menuHelp.Hint", False },
3210 { "menuHelp.Book", False },
3211 { "menuStep.Move Now", False },
3212 { "menuOptions.Periodic Updates", False },
3213 { "menuOptions.Hide Thinking", False },
3214 { "menuOptions.Ponder Next Move", False },
3219 Enables ncpEnables[] = {
3220 { "menuFile.Mail Move", False },
3221 { "menuFile.Reload CMail Message", False },
3222 { "menuMode.Machine White", False },
3223 { "menuMode.Machine Black", False },
3224 { "menuMode.Analysis Mode", False },
3225 { "menuMode.Analyze File", False },
3226 { "menuMode.Two Machines", False },
3227 { "menuMode.ICS Client", False },
3228 { "menuMode.ICS Input Box", False },
3229 { "Action", False },
3230 { "menuStep.Revert", False },
3231 { "menuStep.Move Now", False },
3232 { "menuStep.Retract Move", False },
3233 { "menuOptions.Auto Comment", False },
3234 { "menuOptions.Auto Flag", False },
3235 { "menuOptions.Auto Flip View", False },
3236 { "menuOptions.Auto Observe", False },
3237 { "menuOptions.Auto Raise Board", False },
3238 { "menuOptions.Get Move List", False },
3239 { "menuOptions.ICS Alarm", False },
3240 { "menuOptions.Move Sound", False },
3241 { "menuOptions.Quiet Play", False },
3242 { "menuOptions.Hide Thinking", False },
3243 { "menuOptions.Periodic Updates", False },
3244 { "menuOptions.Ponder Next Move", False },
3245 { "menuHelp.Hint", False },
3246 { "menuHelp.Book", False },
3250 Enables gnuEnables[] = {
3251 { "menuMode.ICS Client", False },
3252 { "menuMode.ICS Input Box", False },
3253 { "menuAction.Accept", False },
3254 { "menuAction.Decline", False },
3255 { "menuAction.Rematch", False },
3256 { "menuAction.Adjourn", False },
3257 { "menuAction.Stop Examining", False },
3258 { "menuAction.Stop Observing", False },
3259 { "menuStep.Revert", False },
3260 { "menuOptions.Auto Comment", False },
3261 { "menuOptions.Auto Observe", False },
3262 { "menuOptions.Auto Raise Board", False },
3263 { "menuOptions.Get Move List", False },
3264 { "menuOptions.Premove", False },
3265 { "menuOptions.Quiet Play", False },
3267 /* The next two options rely on SetCmailMode being called *after* */
3268 /* SetGNUMode so that when GNU is being used to give hints these */
3269 /* menu options are still available */
3271 { "menuFile.Mail Move", False },
3272 { "menuFile.Reload CMail Message", False },
3276 Enables cmailEnables[] = {
3278 { "menuAction.Call Flag", False },
3279 { "menuAction.Draw", True },
3280 { "menuAction.Adjourn", False },
3281 { "menuAction.Abort", False },
3282 { "menuAction.Stop Observing", False },
3283 { "menuAction.Stop Examining", False },
3284 { "menuFile.Mail Move", True },
3285 { "menuFile.Reload CMail Message", True },
3289 Enables trainingOnEnables[] = {
3290 { "menuMode.Edit Comment", False },
3291 { "menuMode.Pause", False },
3292 { "menuStep.Forward", False },
3293 { "menuStep.Backward", False },
3294 { "menuStep.Forward to End", False },
3295 { "menuStep.Back to Start", False },
3296 { "menuStep.Move Now", False },
3297 { "menuStep.Truncate Game", False },
3301 Enables trainingOffEnables[] = {
3302 { "menuMode.Edit Comment", True },
3303 { "menuMode.Pause", True },
3304 { "menuStep.Forward", True },
3305 { "menuStep.Backward", True },
3306 { "menuStep.Forward to End", True },
3307 { "menuStep.Back to Start", True },
3308 { "menuStep.Move Now", True },
3309 { "menuStep.Truncate Game", True },
3313 Enables machineThinkingEnables[] = {
3314 { "menuFile.Load Game", False },
3315 { "menuFile.Load Next Game", False },
3316 { "menuFile.Load Previous Game", False },
3317 { "menuFile.Reload Same Game", False },
3318 { "menuFile.Paste Game", False },
3319 { "menuFile.Load Position", False },
3320 { "menuFile.Load Next Position", False },
3321 { "menuFile.Load Previous Position", False },
3322 { "menuFile.Reload Same Position", False },
3323 { "menuFile.Paste Position", False },
3324 { "menuMode.Machine White", False },
3325 { "menuMode.Machine Black", False },
3326 { "menuMode.Two Machines", False },
3327 { "menuStep.Retract Move", False },
3331 Enables userThinkingEnables[] = {
3332 { "menuFile.Load Game", True },
3333 { "menuFile.Load Next Game", True },
3334 { "menuFile.Load Previous Game", True },
3335 { "menuFile.Reload Same Game", True },
3336 { "menuFile.Paste Game", True },
3337 { "menuFile.Load Position", True },
3338 { "menuFile.Load Next Position", True },
3339 { "menuFile.Load Previous Position", True },
3340 { "menuFile.Reload Same Position", True },
3341 { "menuFile.Paste Position", True },
3342 { "menuMode.Machine White", True },
3343 { "menuMode.Machine Black", True },
3344 { "menuMode.Two Machines", True },
3345 { "menuStep.Retract Move", True },
3351 SetMenuEnables(icsEnables);
3354 if (appData.zippyPlay && !appData.noChessProgram) /* [DM] icsEngineAnalyze */
3355 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Analysis Mode"), True);
3362 SetMenuEnables(ncpEnables);
3368 SetMenuEnables(gnuEnables);
3374 SetMenuEnables(cmailEnables);
3380 SetMenuEnables(trainingOnEnables);
3381 if (appData.showButtonBar) {
3382 XtSetSensitive(buttonBarWidget, False);
3388 SetTrainingModeOff()
3390 SetMenuEnables(trainingOffEnables);
3391 if (appData.showButtonBar) {
3392 XtSetSensitive(buttonBarWidget, True);
3397 SetUserThinkingEnables()
3399 if (appData.noChessProgram) return;
3400 SetMenuEnables(userThinkingEnables);
3404 SetMachineThinkingEnables()
3406 if (appData.noChessProgram) return;
3407 SetMenuEnables(machineThinkingEnables);
3409 case MachinePlaysBlack:
3410 case MachinePlaysWhite:
3411 case TwoMachinesPlay:
3412 XtSetSensitive(XtNameToWidget(menuBarWidget,
3413 ModeToWidgetName(gameMode)), True);
3420 #define Abs(n) ((n)<0 ? -(n) : (n))
3423 * Find a font that matches "pattern" that is as close as
3424 * possible to the targetPxlSize. Prefer fonts that are k
3425 * pixels smaller to fonts that are k pixels larger. The
3426 * pattern must be in the X Consortium standard format,
3427 * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".
3428 * The return value should be freed with XtFree when no
3431 char *FindFont(pattern, targetPxlSize)
3435 char **fonts, *p, *best, *scalable, *scalableTail;
3436 int i, j, nfonts, minerr, err, pxlSize;
3439 char **missing_list;
3441 char *def_string, *base_fnt_lst, strInt[3];
3443 XFontStruct **fnt_list;
3445 base_fnt_lst = calloc(1, strlen(pattern) + 3);
3446 sprintf(strInt, "%d", targetPxlSize);
3447 p = strstr(pattern, "--");
3448 strncpy(base_fnt_lst, pattern, p - pattern + 2);
3449 strcat(base_fnt_lst, strInt);
3450 strcat(base_fnt_lst, strchr(p + 2, '-'));
3452 if ((fntSet = XCreateFontSet(xDisplay,
3456 &def_string)) == NULL) {
3458 fprintf(stderr, _("Unable to create font set.\n"));
3462 nfonts = XFontsOfFontSet(fntSet, &fnt_list, &fonts);
3464 fonts = XListFonts(xDisplay, pattern, 999999, &nfonts);
3466 fprintf(stderr, _("%s: no fonts match pattern %s\n"),
3467 programName, pattern);
3475 for (i=0; i<nfonts; i++) {
3478 if (*p != '-') continue;
3480 if (*p == NULLCHAR) break;
3481 if (*p++ == '-') j++;
3483 if (j < 7) continue;
3486 scalable = fonts[i];
3489 err = pxlSize - targetPxlSize;
3490 if (Abs(err) < Abs(minerr) ||
3491 (minerr > 0 && err < 0 && -err == minerr)) {
3497 if (scalable && Abs(minerr) > appData.fontSizeTolerance) {
3498 /* If the error is too big and there is a scalable font,
3499 use the scalable font. */
3500 int headlen = scalableTail - scalable;
3501 p = (char *) XtMalloc(strlen(scalable) + 10);
3502 while (isdigit(*scalableTail)) scalableTail++;
3503 sprintf(p, "%.*s%d%s", headlen, scalable, targetPxlSize, scalableTail);
3505 p = (char *) XtMalloc(strlen(best) + 1);
3508 if (appData.debugMode) {
3509 fprintf(debugFP, _("resolved %s at pixel size %d\n to %s\n"),
3510 pattern, targetPxlSize, p);
3513 if (missing_count > 0)
3514 XFreeStringList(missing_list);
3515 XFreeFontSet(xDisplay, fntSet);
3517 XFreeFontNames(fonts);
3524 XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
3525 | GCBackground | GCFunction | GCPlaneMask;
3526 XGCValues gc_values;
3529 gc_values.plane_mask = AllPlanes;
3530 gc_values.line_width = lineGap;
3531 gc_values.line_style = LineSolid;
3532 gc_values.function = GXcopy;
3534 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3535 gc_values.background = XBlackPixel(xDisplay, xScreen);
3536 lineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3538 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3539 gc_values.background = XWhitePixel(xDisplay, xScreen);
3540 coordGC = XtGetGC(shellWidget, value_mask, &gc_values);
3541 XSetFont(xDisplay, coordGC, coordFontID);
3543 // [HGM] make font for holdings counts (white on black0
3544 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3545 gc_values.background = XBlackPixel(xDisplay, xScreen);
3546 countGC = XtGetGC(shellWidget, value_mask, &gc_values);
3547 XSetFont(xDisplay, countGC, countFontID);
3549 if (appData.monoMode) {
3550 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3551 gc_values.background = XWhitePixel(xDisplay, xScreen);
3552 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3554 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3555 gc_values.background = XBlackPixel(xDisplay, xScreen);
3556 lightSquareGC = wbPieceGC
3557 = XtGetGC(shellWidget, value_mask, &gc_values);
3559 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3560 gc_values.background = XWhitePixel(xDisplay, xScreen);
3561 darkSquareGC = bwPieceGC
3562 = XtGetGC(shellWidget, value_mask, &gc_values);
3564 if (DefaultDepth(xDisplay, xScreen) == 1) {
3565 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
3566 gc_values.function = GXcopyInverted;
3567 copyInvertedGC = XtGetGC(shellWidget, value_mask, &gc_values);
3568 gc_values.function = GXcopy;
3569 if (XBlackPixel(xDisplay, xScreen) == 1) {
3570 bwPieceGC = darkSquareGC;
3571 wbPieceGC = copyInvertedGC;
3573 bwPieceGC = copyInvertedGC;
3574 wbPieceGC = lightSquareGC;
3578 gc_values.foreground = highlightSquareColor;
3579 gc_values.background = highlightSquareColor;
3580 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3582 gc_values.foreground = premoveHighlightColor;
3583 gc_values.background = premoveHighlightColor;
3584 prelineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3586 gc_values.foreground = lightSquareColor;
3587 gc_values.background = darkSquareColor;
3588 lightSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3590 gc_values.foreground = darkSquareColor;
3591 gc_values.background = lightSquareColor;
3592 darkSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3594 gc_values.foreground = jailSquareColor;
3595 gc_values.background = jailSquareColor;
3596 jailSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3598 gc_values.foreground = whitePieceColor;
3599 gc_values.background = darkSquareColor;
3600 wdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3602 gc_values.foreground = whitePieceColor;
3603 gc_values.background = lightSquareColor;
3604 wlPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3606 gc_values.foreground = whitePieceColor;
3607 gc_values.background = jailSquareColor;
3608 wjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3610 gc_values.foreground = blackPieceColor;
3611 gc_values.background = darkSquareColor;
3612 bdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3614 gc_values.foreground = blackPieceColor;
3615 gc_values.background = lightSquareColor;
3616 blPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3618 gc_values.foreground = blackPieceColor;
3619 gc_values.background = jailSquareColor;
3620 bjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3624 void loadXIM(xim, xmask, filename, dest, mask)
3637 fp = fopen(filename, "rb");
3639 fprintf(stderr, _("%s: error loading XIM!\n"), programName);
3646 for (y=0; y<h; ++y) {
3647 for (x=0; x<h; ++x) {
3652 XPutPixel(xim, x, y, blackPieceColor);
3654 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3657 XPutPixel(xim, x, y, darkSquareColor);
3659 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3662 XPutPixel(xim, x, y, whitePieceColor);
3664 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3667 XPutPixel(xim, x, y, lightSquareColor);
3669 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3675 /* create Pixmap of piece */
3676 *dest = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3678 XPutImage(xDisplay, *dest, lightSquareGC, xim,
3681 /* create Pixmap of clipmask
3682 Note: We assume the white/black pieces have the same
3683 outline, so we make only 6 masks. This is okay
3684 since the XPM clipmask routines do the same. */
3686 temp = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3688 XPutImage(xDisplay, temp, lightSquareGC, xmask,
3691 /* now create the 1-bit version */
3692 *mask = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3695 values.foreground = 1;
3696 values.background = 0;
3698 /* Don't use XtGetGC, not read only */
3699 maskGC = XCreateGC(xDisplay, *mask,
3700 GCForeground | GCBackground, &values);
3701 XCopyPlane(xDisplay, temp, *mask, maskGC,
3702 0, 0, squareSize, squareSize, 0, 0, 1);
3703 XFreePixmap(xDisplay, temp);
3707 void CreateXIMPieces()
3712 static char *ximkind[] = { "ll", "ld", "dl", "dd" };
3717 /* The XSynchronize calls were copied from CreatePieces.
3718 Not sure if needed, but can't hurt */
3719 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3722 /* temp needed by loadXIM() */
3723 ximtemp = XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3724 0, 0, ss, ss, AllPlanes, XYPixmap);
3726 if (strlen(appData.pixmapDirectory) == 0) {
3730 if (appData.monoMode) {
3731 DisplayFatalError(_("XIM pieces cannot be used in monochrome mode"),
3735 fprintf(stderr, _("\nLoading XIMs...\n"));
3737 for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
3738 fprintf(stderr, "%d", piece+1);
3739 for (kind=0; kind<4; kind++) {
3740 fprintf(stderr, ".");
3741 snprintf(buf, sizeof(buf), "%s/%c%s%u.xim",
3742 ExpandPathName(appData.pixmapDirectory),
3743 ToLower(PieceToChar((ChessSquare)piece)),
3745 ximPieceBitmap[kind][piece] =
3746 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3747 0, 0, ss, ss, AllPlanes, XYPixmap);
3748 if (appData.debugMode)
3749 fprintf(stderr, _("(File:%s:) "), buf);
3750 loadXIM(ximPieceBitmap[kind][piece],
3752 &(xpmPieceBitmap[kind][piece]),
3753 &(ximMaskPm[piece%(int)BlackPawn]));
3755 fprintf(stderr," ");
3757 /* Load light and dark squares */
3758 /* If the LSQ and DSQ pieces don't exist, we will
3759 draw them with solid squares. */
3760 snprintf(buf,sizeof(buf), "%s/lsq%u.xim", ExpandPathName(appData.pixmapDirectory), ss);
3761 if (access(buf, 0) != 0) {
3765 fprintf(stderr, _("light square "));
3767 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3768 0, 0, ss, ss, AllPlanes, XYPixmap);
3769 if (appData.debugMode)
3770 fprintf(stderr, _("(File:%s:) "), buf);
3772 loadXIM(ximLightSquare, NULL, buf, &xpmLightSquare, NULL);
3773 fprintf(stderr, _("dark square "));
3774 snprintf(buf,sizeof(buf), "%s/dsq%u.xim",
3775 ExpandPathName(appData.pixmapDirectory), ss);
3776 if (appData.debugMode)
3777 fprintf(stderr, _("(File:%s:) "), buf);
3779 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3780 0, 0, ss, ss, AllPlanes, XYPixmap);
3781 loadXIM(ximDarkSquare, NULL, buf, &xpmDarkSquare, NULL);
3782 xpmJailSquare = xpmLightSquare;
3784 fprintf(stderr, _("Done.\n"));
3786 XSynchronize(xDisplay, False); /* Work-around for xlib/xt buffering bug */
3789 char pieceBitmapNames[] = "pnbrqfeacwmohijgdvlsuk";
3792 void CreateXPMPieces()
3796 u_int ss = squareSize;
3798 static char *xpmkind[] = { "ll", "ld", "dl", "dd" };
3799 XpmColorSymbol symbols[4];
3802 /* Apparently some versions of Xpm don't define XpmFormat at all --tpm */
3803 if (appData.debugMode) {
3804 fprintf(stderr, "XPM Library Version: %d.%d%c\n",
3805 XpmFormat, XpmVersion, (char)('a' + XpmRevision - 1));
3809 /* The XSynchronize calls were copied from CreatePieces.
3810 Not sure if needed, but can't hurt */
3811 XSynchronize(xDisplay, True); /* Work-around for xlib/xt buffering bug */
3813 /* Setup translations so piece colors match square colors */
3814 symbols[0].name = "light_piece";
3815 symbols[0].value = appData.whitePieceColor;
3816 symbols[1].name = "dark_piece";
3817 symbols[1].value = appData.blackPieceColor;
3818 symbols[2].name = "light_square";
3819 symbols[2].value = appData.lightSquareColor;
3820 symbols[3].name = "dark_square";
3821 symbols[3].value = appData.darkSquareColor;
3823 attr.valuemask = XpmColorSymbols;
3824 attr.colorsymbols = symbols;
3825 attr.numsymbols = 4;
3827 if (appData.monoMode) {
3828 DisplayFatalError(_("XPM pieces cannot be used in monochrome mode"),
3832 if (strlen(appData.pixmapDirectory) == 0) {
3833 XpmPieces* pieces = builtInXpms;
3836 while (pieces->size != squareSize && pieces->size) pieces++;
3837 if (!pieces->size) {
3838 fprintf(stderr, _("No builtin XPM pieces of size %d\n"), squareSize);
3841 for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
3842 for (kind=0; kind<4; kind++) {
3844 if ((r=XpmCreatePixmapFromData(xDisplay, xBoardWindow,
3845 pieces->xpm[piece][kind],
3846 &(xpmPieceBitmap[kind][piece]),
3847 NULL, &attr)) != 0) {
3848 fprintf(stderr, _("Error %d loading XPM image \"%s\"\n"),
3855 xpmJailSquare = xpmLightSquare;
3859 fprintf(stderr, _("\nLoading XPMs...\n"));
3862 for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
3863 fprintf(stderr, "%d ", piece+1);
3864 for (kind=0; kind<4; kind++) {
3865 snprintf(buf, sizeof(buf), "%s/%c%s%u.xpm",
3866 ExpandPathName(appData.pixmapDirectory),
3867 pieceBitmapNames[piece],
3869 if (appData.debugMode) {
3870 fprintf(stderr, _("(File:%s:) "), buf);
3872 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3873 &(xpmPieceBitmap[kind][piece]),
3874 NULL, &attr)) != 0) {
3875 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"),
3881 /* Load light and dark squares */
3882 /* If the LSQ and DSQ pieces don't exist, we will
3883 draw them with solid squares. */
3884 fprintf(stderr, _("light square "));
3885 snprintf(buf, sizeof(buf), "%s/lsq%u.xpm", ExpandPathName(appData.pixmapDirectory), ss);
3886 if (access(buf, 0) != 0) {
3890 if (appData.debugMode)
3891 fprintf(stderr, _("(File:%s:) "), buf);
3893 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3894 &xpmLightSquare, NULL, &attr)) != 0) {
3895 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
3898 fprintf(stderr, _("dark square "));
3899 snprintf(buf, sizeof(buf), "%s/dsq%u.xpm",
3900 ExpandPathName(appData.pixmapDirectory), ss);
3901 if (appData.debugMode) {
3902 fprintf(stderr, _("(File:%s:) "), buf);
3904 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3905 &xpmDarkSquare, NULL, &attr)) != 0) {
3906 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
3910 xpmJailSquare = xpmLightSquare;
3911 fprintf(stderr, _("Done.\n"));
3913 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3916 #endif /* HAVE_LIBXPM */
3919 /* No built-in bitmaps */
3924 u_int ss = squareSize;
3926 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3929 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
3930 for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
3931 sprintf(buf, "%c%u%c.bm", pieceBitmapNames[piece],
3932 ss, kind == SOLID ? 's' : 'o');
3933 ReadBitmap(&pieceBitmap[kind][piece], buf, NULL, ss, ss);
3937 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3941 /* With built-in bitmaps */
3944 BuiltInBits* bib = builtInBits;
3947 u_int ss = squareSize;
3949 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3952 while (bib->squareSize != ss && bib->squareSize != 0) bib++;
3954 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
3955 for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
3956 sprintf(buf, "%c%u%c.bm", pieceBitmapNames[piece],
3957 ss, kind == SOLID ? 's' : 'o');
3958 ReadBitmap(&pieceBitmap[kind][piece], buf,
3959 bib->bits[kind][piece], ss, ss);
3963 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3968 void ReadBitmap(pm, name, bits, wreq, hreq)
3971 unsigned char bits[];
3977 char msg[MSG_SIZ], fullname[MSG_SIZ];
3979 if (*appData.bitmapDirectory != NULLCHAR) {
3980 strcpy(fullname, appData.bitmapDirectory);
3981 strcat(fullname, "/");
3982 strcat(fullname, name);
3983 errcode = XReadBitmapFile(xDisplay, xBoardWindow, fullname,
3984 &w, &h, pm, &x_hot, &y_hot);
3985 fprintf(stderr, "load %s\n", name);
3986 if (errcode != BitmapSuccess) {
3988 case BitmapOpenFailed:
3989 snprintf(msg, sizeof(msg), _("Can't open bitmap file %s"), fullname);
3991 case BitmapFileInvalid:
3992 snprintf(msg, sizeof(msg), _("Invalid bitmap in file %s"), fullname);
3994 case BitmapNoMemory:
3995 snprintf(msg, sizeof(msg), _("Ran out of memory reading bitmap file %s"),
3999 snprintf(msg, sizeof(msg), _("Unknown XReadBitmapFile error %d on file %s"),
4003 fprintf(stderr, _("%s: %s...using built-in\n"),
4005 } else if (w != wreq || h != hreq) {
4007 _("%s: Bitmap %s is %dx%d, not %dx%d...using built-in\n"),
4008 programName, fullname, w, h, wreq, hreq);
4015 fprintf(stderr, _("%s: No built-in bitmap for %s; giving up\n"),
4019 ; // [HGM] bitmaps: make it non-fatal if we have no bitmap;
4021 *pm = XCreateBitmapFromData(xDisplay, xBoardWindow, (char *) bits,
4030 if (lineGap == 0) return;
4032 /* [HR] Split this into 2 loops for non-square boards. */
4034 for (i = 0; i < BOARD_HEIGHT + 1; i++) {
4035 gridSegments[i].x1 = 0;
4036 gridSegments[i].x2 =
4037 lineGap + BOARD_WIDTH * (squareSize + lineGap);
4038 gridSegments[i].y1 = gridSegments[i].y2
4039 = lineGap / 2 + (i * (squareSize + lineGap));
4042 for (j = 0; j < BOARD_WIDTH + 1; j++) {
4043 gridSegments[j + i].y1 = 0;
4044 gridSegments[j + i].y2 =
4045 lineGap + BOARD_HEIGHT * (squareSize + lineGap);
4046 gridSegments[j + i].x1 = gridSegments[j + i].x2
4047 = lineGap / 2 + (j * (squareSize + lineGap));
4051 static void MenuBarSelect(w, addr, index)
4056 XtActionProc proc = (XtActionProc) addr;
4058 (proc)(NULL, NULL, NULL, NULL);
4061 void CreateMenuBarPopup(parent, name, mb)
4071 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
4074 XtSetArg(args[j], XtNleftMargin, 20); j++;
4075 XtSetArg(args[j], XtNrightMargin, 20); j++;
4077 while (mi->string != NULL) {
4078 if (strcmp(mi->string, "----") == 0) {
4079 entry = XtCreateManagedWidget(mi->string, smeLineObjectClass,
4082 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string)));
4083 entry = XtCreateManagedWidget(mi->string, smeBSBObjectClass,
4085 XtAddCallback(entry, XtNcallback,
4086 (XtCallbackProc) MenuBarSelect,
4087 (caddr_t) mi->proc);
4093 Widget CreateMenuBar(mb)
4097 Widget anchor, menuBar;
4099 char menuName[MSG_SIZ];
4102 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
4103 XtSetArg(args[j], XtNvSpace, 0); j++;
4104 XtSetArg(args[j], XtNborderWidth, 0); j++;
4105 menuBar = XtCreateWidget("menuBar", boxWidgetClass,
4106 formWidget, args, j);
4108 while (mb->name != NULL) {
4109 strcpy(menuName, "menu");
4110 strcat(menuName, mb->name);
4112 XtSetArg(args[j], XtNmenuName, XtNewString(menuName)); j++;
4115 shortName[0] = _(mb->name)[0];
4116 shortName[1] = NULLCHAR;
4117 XtSetArg(args[j], XtNlabel, XtNewString(shortName)); j++;
4120 XtSetArg(args[j], XtNlabel, XtNewString(_(mb->name))); j++;
4123 XtSetArg(args[j], XtNborderWidth, 0); j++;
4124 anchor = XtCreateManagedWidget(mb->name, menuButtonWidgetClass,
4126 CreateMenuBarPopup(menuBar, menuName, mb);
4132 Widget CreateButtonBar(mi)
4136 Widget button, buttonBar;
4140 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
4142 XtSetArg(args[j], XtNhSpace, 0); j++;
4144 XtSetArg(args[j], XtNborderWidth, 0); j++;
4145 XtSetArg(args[j], XtNvSpace, 0); j++;
4146 buttonBar = XtCreateWidget("buttonBar", boxWidgetClass,
4147 formWidget, args, j);
4149 while (mi->string != NULL) {
4152 XtSetArg(args[j], XtNinternalWidth, 2); j++;
4153 XtSetArg(args[j], XtNborderWidth, 0); j++;
4155 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string))); j++;
4156 button = XtCreateManagedWidget(mi->string, commandWidgetClass,
4157 buttonBar, args, j);
4158 XtAddCallback(button, XtNcallback,
4159 (XtCallbackProc) MenuBarSelect,
4160 (caddr_t) mi->proc);
4167 CreatePieceMenu(name, color)
4174 ChessSquare selection;
4176 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
4177 boardWidget, args, 0);
4179 for (i = 0; i < PIECE_MENU_SIZE; i++) {
4180 String item = pieceMenuStrings[color][i];
4182 if (strcmp(item, "----") == 0) {
4183 entry = XtCreateManagedWidget(item, smeLineObjectClass,
4186 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
4187 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
4189 selection = pieceMenuTranslation[color][i];
4190 XtAddCallback(entry, XtNcallback,
4191 (XtCallbackProc) PieceMenuSelect,
4192 (caddr_t) selection);
4193 if (selection == WhitePawn || selection == BlackPawn) {
4194 XtSetArg(args[0], XtNpopupOnEntry, entry);
4195 XtSetValues(menu, args, 1);
4208 ChessSquare selection;
4210 whitePieceMenu = CreatePieceMenu("menuW", 0);
4211 blackPieceMenu = CreatePieceMenu("menuB", 1);
4213 XtRegisterGrabAction(PieceMenuPopup, True,
4214 (unsigned)(ButtonPressMask|ButtonReleaseMask),
4215 GrabModeAsync, GrabModeAsync);
4217 XtSetArg(args[0], XtNlabel, _("Drop"));
4218 dropMenu = XtCreatePopupShell("menuD", simpleMenuWidgetClass,
4219 boardWidget, args, 1);
4220 for (i = 0; i < DROP_MENU_SIZE; i++) {
4221 String item = dropMenuStrings[i];
4223 if (strcmp(item, "----") == 0) {
4224 entry = XtCreateManagedWidget(item, smeLineObjectClass,
4227 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
4228 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
4230 selection = dropMenuTranslation[i];
4231 XtAddCallback(entry, XtNcallback,
4232 (XtCallbackProc) DropMenuSelect,
4233 (caddr_t) selection);
4238 void SetupDropMenu()
4246 for (i=0; i<sizeof(dmEnables)/sizeof(DropMenuEnables); i++) {
4247 entry = XtNameToWidget(dropMenu, dmEnables[i].widget);
4248 p = strchr(gameMode == IcsPlayingWhite ? white_holding : black_holding,
4249 dmEnables[i].piece);
4250 XtSetSensitive(entry, p != NULL || !appData.testLegality
4251 /*!!temp:*/ || (gameInfo.variant == VariantCrazyhouse
4252 && !appData.icsActive));
4254 while (p && *p++ == dmEnables[i].piece) count++;
4255 snprintf(label, sizeof(label), "%s %d", dmEnables[i].widget, count);
4257 XtSetArg(args[j], XtNlabel, label); j++;
4258 XtSetValues(entry, args, j);
4262 void PieceMenuPopup(w, event, params, num_params)
4266 Cardinal *num_params;
4269 if (event->type != ButtonPress) return;
4270 if (errorUp) ErrorPopDown();
4274 whichMenu = params[0];
4276 case IcsPlayingWhite:
4277 case IcsPlayingBlack:
4279 case MachinePlaysWhite:
4280 case MachinePlaysBlack:
4281 if (appData.testLegality &&
4282 gameInfo.variant != VariantBughouse &&
4283 gameInfo.variant != VariantCrazyhouse) return;
4285 whichMenu = "menuD";
4291 if (((pmFromX = EventToSquare(event->xbutton.x, BOARD_WIDTH)) < 0) ||
4292 ((pmFromY = EventToSquare(event->xbutton.y, BOARD_HEIGHT)) < 0)) {
4293 pmFromX = pmFromY = -1;
4297 pmFromX = BOARD_WIDTH - 1 - pmFromX;
4299 pmFromY = BOARD_HEIGHT - 1 - pmFromY;
4301 XtPopupSpringLoaded(XtNameToWidget(boardWidget, whichMenu));
4304 static void PieceMenuSelect(w, piece, junk)
4309 if (pmFromX < 0 || pmFromY < 0) return;
4310 EditPositionMenuEvent(piece, pmFromX, pmFromY);
4313 static void DropMenuSelect(w, piece, junk)
4318 if (pmFromX < 0 || pmFromY < 0) return;
4319 DropMenuEvent(piece, pmFromX, pmFromY);
4322 void WhiteClock(w, event, prms, nprms)
4328 if (gameMode == EditPosition || gameMode == IcsExamining) {
4329 SetWhiteToPlayEvent();
4330 } else if (gameMode == IcsPlayingBlack || gameMode == MachinePlaysWhite) {
4335 void BlackClock(w, event, prms, nprms)
4341 if (gameMode == EditPosition || gameMode == IcsExamining) {
4342 SetBlackToPlayEvent();
4343 } else if (gameMode == IcsPlayingWhite || gameMode == MachinePlaysBlack) {
4350 * If the user selects on a border boundary, return -1; if off the board,
4351 * return -2. Otherwise map the event coordinate to the square.
4353 int EventToSquare(x, limit)
4361 if ((x % (squareSize + lineGap)) >= squareSize)
4363 x /= (squareSize + lineGap);
4369 static void do_flash_delay(msec)
4375 static void drawHighlight(file, rank, gc)
4381 if (lineGap == 0 || appData.blindfold) return;
4384 x = lineGap/2 + ((BOARD_WIDTH-1)-file) *
4385 (squareSize + lineGap);
4386 y = lineGap/2 + rank * (squareSize + lineGap);
4388 x = lineGap/2 + file * (squareSize + lineGap);
4389 y = lineGap/2 + ((BOARD_HEIGHT-1)-rank) *
4390 (squareSize + lineGap);
4393 XDrawRectangle(xDisplay, xBoardWindow, gc, x, y,
4394 squareSize+lineGap, squareSize+lineGap);
4397 int hi1X = -1, hi1Y = -1, hi2X = -1, hi2Y = -1;
4398 int pm1X = -1, pm1Y = -1, pm2X = -1, pm2Y = -1;
4401 SetHighlights(fromX, fromY, toX, toY)
4402 int fromX, fromY, toX, toY;
4404 if (hi1X != fromX || hi1Y != fromY) {
4405 if (hi1X >= 0 && hi1Y >= 0) {
4406 drawHighlight(hi1X, hi1Y, lineGC);
4408 if (fromX >= 0 && fromY >= 0) {
4409 drawHighlight(fromX, fromY, highlineGC);
4412 if (hi2X != toX || hi2Y != toY) {
4413 if (hi2X >= 0 && hi2Y >= 0) {
4414 drawHighlight(hi2X, hi2Y, lineGC);
4416 if (toX >= 0 && toY >= 0) {
4417 drawHighlight(toX, toY, highlineGC);
4429 SetHighlights(-1, -1, -1, -1);
4434 SetPremoveHighlights(fromX, fromY, toX, toY)
4435 int fromX, fromY, toX, toY;
4437 if (pm1X != fromX || pm1Y != fromY) {
4438 if (pm1X >= 0 && pm1Y >= 0) {
4439 drawHighlight(pm1X, pm1Y, lineGC);
4441 if (fromX >= 0 && fromY >= 0) {
4442 drawHighlight(fromX, fromY, prelineGC);
4445 if (pm2X != toX || pm2Y != toY) {
4446 if (pm2X >= 0 && pm2Y >= 0) {
4447 drawHighlight(pm2X, pm2Y, lineGC);
4449 if (toX >= 0 && toY >= 0) {
4450 drawHighlight(toX, toY, prelineGC);
4460 ClearPremoveHighlights()
4462 SetPremoveHighlights(-1, -1, -1, -1);
4465 static void BlankSquare(x, y, color, piece, dest)
4470 if (useImages && useImageSqs) {
4474 pm = xpmLightSquare;
4479 case 2: /* neutral */
4484 XCopyArea(xDisplay, pm, dest, wlPieceGC, 0, 0,
4485 squareSize, squareSize, x, y);
4495 case 2: /* neutral */
4500 XFillRectangle(xDisplay, dest, gc, x, y, squareSize, squareSize);
4505 I split out the routines to draw a piece so that I could
4506 make a generic flash routine.
4508 static void monoDrawPiece_1bit(piece, square_color, x, y, dest)
4510 int square_color, x, y;
4513 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
4514 switch (square_color) {
4516 case 2: /* neutral */
4518 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
4519 ? *pieceToOutline(piece)
4520 : *pieceToSolid(piece),
4521 dest, bwPieceGC, 0, 0,
4522 squareSize, squareSize, x, y);
4525 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
4526 ? *pieceToSolid(piece)
4527 : *pieceToOutline(piece),
4528 dest, wbPieceGC, 0, 0,
4529 squareSize, squareSize, x, y);
4534 static void monoDrawPiece(piece, square_color, x, y, dest)
4536 int square_color, x, y;
4539 switch (square_color) {
4541 case 2: /* neutral */
4543 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
4544 ? *pieceToOutline(piece)
4545 : *pieceToSolid(piece),
4546 dest, bwPieceGC, 0, 0,
4547 squareSize, squareSize, x, y, 1);
4550 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
4551 ? *pieceToSolid(piece)
4552 : *pieceToOutline(piece),
4553 dest, wbPieceGC, 0, 0,
4554 squareSize, squareSize, x, y, 1);
4559 static void colorDrawPiece(piece, square_color, x, y, dest)
4561 int square_color, x, y;
4564 if(pieceToSolid(piece) == NULL) return; // [HGM] bitmaps: make it non-fatal if we have no bitmap;
4565 switch (square_color) {
4567 XCopyPlane(xDisplay, *pieceToSolid(piece),
4568 dest, (int) piece < (int) BlackPawn
4569 ? wlPieceGC : blPieceGC, 0, 0,
4570 squareSize, squareSize, x, y, 1);
4573 XCopyPlane(xDisplay, *pieceToSolid(piece),
4574 dest, (int) piece < (int) BlackPawn
4575 ? wdPieceGC : bdPieceGC, 0, 0,
4576 squareSize, squareSize, x, y, 1);
4578 case 2: /* neutral */
4580 XCopyPlane(xDisplay, *pieceToSolid(piece),
4581 dest, (int) piece < (int) BlackPawn
4582 ? wjPieceGC : bjPieceGC, 0, 0,
4583 squareSize, squareSize, x, y, 1);
4588 static void colorDrawPieceImage(piece, square_color, x, y, dest)
4590 int square_color, x, y;
4595 switch (square_color) {
4597 case 2: /* neutral */
4599 if ((int)piece < (int) BlackPawn) {
4607 if ((int)piece < (int) BlackPawn) {
4615 XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
4616 dest, wlPieceGC, 0, 0,
4617 squareSize, squareSize, x, y);
4620 typedef void (*DrawFunc)();
4622 DrawFunc ChooseDrawFunc()
4624 if (appData.monoMode) {
4625 if (DefaultDepth(xDisplay, xScreen) == 1) {
4626 return monoDrawPiece_1bit;
4628 return monoDrawPiece;
4632 return colorDrawPieceImage;
4634 return colorDrawPiece;
4638 /* [HR] determine square color depending on chess variant. */
4639 static int SquareColor(row, column)
4644 if (gameInfo.variant == VariantXiangqi) {
4645 if (column >= 3 && column <= 5 && row >= 0 && row <= 2) {
4647 } else if (column >= 3 && column <= 5 && row >= 7 && row <= 9) {
4649 } else if (row <= 4) {
4655 square_color = ((column + row) % 2) == 1;
4658 /* [hgm] holdings: next line makes all holdings squares light */
4659 if(column < BOARD_LEFT || column >= BOARD_RGHT) square_color = 1;
4661 return square_color;
4664 void DrawSquare(row, column, piece, do_flash)
4665 int row, column, do_flash;
4668 int square_color, x, y, direction, font_ascent, font_descent;
4671 XCharStruct overall;
4675 if(gameInfo.variant == VariantShogi) { // [HGM] shogi: in shogi Q is used for Lance
4676 if(piece == WhiteQueen) piece = WhiteLance; else
4677 if(piece == BlackQueen) piece = BlackLance;
4680 else if(gameInfo.variant == VariantGothic) { // [HGM] shogi: in Gothic Chancelor has alternative look
4681 if(piece == WhiteMarshall) piece = WhiteSilver; else
4682 if(piece == BlackMarshall) piece = BlackSilver;
4686 /* Calculate delay in milliseconds (2-delays per complete flash) */
4687 flash_delay = 500 / appData.flashRate;
4690 x = lineGap + ((BOARD_WIDTH-1)-column) *
4691 (squareSize + lineGap);
4692 y = lineGap + row * (squareSize + lineGap);
4694 x = lineGap + column * (squareSize + lineGap);
4695 y = lineGap + ((BOARD_HEIGHT-1)-row) *
4696 (squareSize + lineGap);
4699 square_color = SquareColor(row, column);
4701 if ( // [HGM] holdings: blank out area between board and holdings
4702 column == BOARD_LEFT-1 || column == BOARD_RGHT
4703 || (column == BOARD_LEFT-2 && row < BOARD_HEIGHT-gameInfo.holdingsSize)
4704 || (column == BOARD_RGHT+1 && row >= gameInfo.holdingsSize) ) {
4705 BlankSquare(x, y, 2, EmptySquare, xBoardWindow);
4707 // [HGM] print piece counts next to holdings
4708 string[1] = NULLCHAR;
4709 if (column == (flipView ? BOARD_LEFT-1 : BOARD_RGHT) && piece > 1 ) {
4710 string[0] = '0' + piece;
4711 XTextExtents(countFontStruct, string, 1, &direction,
4712 &font_ascent, &font_descent, &overall);
4713 if (appData.monoMode) {
4714 XDrawImageString(xDisplay, xBoardWindow, countGC,
4715 x + squareSize - overall.width - 2,
4716 y + font_ascent + 1, string, 1);
4718 XDrawString(xDisplay, xBoardWindow, countGC,
4719 x + squareSize - overall.width - 2,
4720 y + font_ascent + 1, string, 1);
4723 if (column == (flipView ? BOARD_RGHT : BOARD_LEFT-1) && piece > 1) {
4724 string[0] = '0' + piece;
4725 XTextExtents(countFontStruct, string, 1, &direction,
4726 &font_ascent, &font_descent, &overall);
4727 if (appData.monoMode) {
4728 XDrawImageString(xDisplay, xBoardWindow, countGC,
4729 x + 2, y + font_ascent + 1, string, 1);
4731 XDrawString(xDisplay, xBoardWindow, countGC,
4732 x + 2, y + font_ascent + 1, string, 1);
4736 if (piece == EmptySquare || appData.blindfold) {
4737 BlankSquare(x, y, square_color, piece, xBoardWindow);
4739 drawfunc = ChooseDrawFunc();
4740 if (do_flash && appData.flashCount > 0) {
4741 for (i=0; i<appData.flashCount; ++i) {
4743 drawfunc(piece, square_color, x, y, xBoardWindow);
4744 XSync(xDisplay, False);
4745 do_flash_delay(flash_delay);
4747 BlankSquare(x, y, square_color, piece, xBoardWindow);
4748 XSync(xDisplay, False);
4749 do_flash_delay(flash_delay);
4752 drawfunc(piece, square_color, x, y, xBoardWindow);
4756 string[1] = NULLCHAR;
4757 if (appData.showCoords && row == (flipView ? BOARD_HEIGHT-1 : 0)
4758 && column >= BOARD_LEFT && column < BOARD_RGHT) {
4759 string[0] = 'a' + column - BOARD_LEFT;
4760 XTextExtents(coordFontStruct, string, 1, &direction,
4761 &font_ascent, &font_descent, &overall);
4762 if (appData.monoMode) {
4763 XDrawImageString(xDisplay, xBoardWindow, coordGC,
4764 x + squareSize - overall.width - 2,
4765 y + squareSize - font_descent - 1, string, 1);
4767 XDrawString(xDisplay, xBoardWindow, coordGC,
4768 x + squareSize - overall.width - 2,
4769 y + squareSize - font_descent - 1, string, 1);
4772 if (appData.showCoords && column == (flipView ? BOARD_RGHT-1 : BOARD_LEFT)) {
4773 string[0] = ONE + row;
4774 XTextExtents(coordFontStruct, string, 1, &direction,
4775 &font_ascent, &font_descent, &overall);
4776 if (appData.monoMode) {
4777 XDrawImageString(xDisplay, xBoardWindow, coordGC,
4778 x + 2, y + font_ascent + 1, string, 1);
4780 XDrawString(xDisplay, xBoardWindow, coordGC,
4781 x + 2, y + font_ascent + 1, string, 1);
4787 /* Why is this needed on some versions of X? */
4788 void EventProc(widget, unused, event)
4793 if (!XtIsRealized(widget))
4796 switch (event->type) {
4798 if (event->xexpose.count > 0) return; /* no clipping is done */
4799 XDrawPosition(widget, True, NULL);
4807 void DrawPosition(fullRedraw, board)
4808 /*Boolean*/int fullRedraw;
4811 XDrawPosition(boardWidget, fullRedraw, board);
4814 /* Returns 1 if there are "too many" differences between b1 and b2
4815 (i.e. more than 1 move was made) */
4816 static int too_many_diffs(b1, b2)
4822 for (i=0; i<BOARD_HEIGHT; ++i) {
4823 for (j=0; j<BOARD_WIDTH; ++j) {
4824 if (b1[i][j] != b2[i][j]) {
4825 if (++c > 4) /* Castling causes 4 diffs */
4834 /* Matrix describing castling maneuvers */
4835 /* Row, ColRookFrom, ColKingFrom, ColRookTo, ColKingTo */
4836 static int castling_matrix[4][5] = {
4837 { 0, 0, 4, 3, 2 }, /* 0-0-0, white */
4838 { 0, 7, 4, 5, 6 }, /* 0-0, white */
4839 { 7, 0, 4, 3, 2 }, /* 0-0-0, black */
4840 { 7, 7, 4, 5, 6 } /* 0-0, black */
4843 /* Checks whether castling occurred. If it did, *rrow and *rcol
4844 are set to the destination (row,col) of the rook that moved.
4846 Returns 1 if castling occurred, 0 if not.
4848 Note: Only handles a max of 1 castling move, so be sure
4849 to call too_many_diffs() first.
4851 static int check_castle_draw(newb, oldb, rrow, rcol)
4858 /* For each type of castling... */
4859 for (i=0; i<4; ++i) {
4860 r = castling_matrix[i];
4862 /* Check the 4 squares involved in the castling move */
4864 for (j=1; j<=4; ++j) {
4865 if (newb[r[0]][r[j]] == oldb[r[0]][r[j]]) {
4872 /* All 4 changed, so it must be a castling move */
4881 static int damage[BOARD_SIZE][BOARD_SIZE];
4884 * event handler for redrawing the board
4886 void XDrawPosition(w, repaint, board)
4888 /*Boolean*/int repaint;
4892 static int lastFlipView = 0;
4893 static int lastBoardValid = 0;
4894 static Board lastBoard;
4898 if (board == NULL) {
4899 if (!lastBoardValid) return;
4902 if (!lastBoardValid || lastFlipView != flipView) {
4903 XtSetArg(args[0], XtNleftBitmap, (flipView ? xMarkPixmap : None));
4904 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flip View"),
4909 * It would be simpler to clear the window with XClearWindow()
4910 * but this causes a very distracting flicker.
4913 if (!repaint && lastBoardValid && lastFlipView == flipView) {
4915 /* If too much changes (begin observing new game, etc.), don't
4917 do_flash = too_many_diffs(board, lastBoard) ? 0 : 1;
4919 /* Special check for castling so we don't flash both the king
4920 and the rook (just flash the king). */
4922 if (check_castle_draw(board, lastBoard, &rrow, &rcol)) {
4923 /* Draw rook with NO flashing. King will be drawn flashing later */
4924 DrawSquare(rrow, rcol, board[rrow][rcol], 0);
4925 lastBoard[rrow][rcol] = board[rrow][rcol];
4929 /* First pass -- Draw (newly) empty squares and repair damage.
4930 This prevents you from having a piece show up twice while it
4931 is flashing on its new square */
4932 for (i = 0; i < BOARD_HEIGHT; i++)
4933 for (j = 0; j < BOARD_WIDTH; j++)
4934 if ((board[i][j] != lastBoard[i][j] && board[i][j] == EmptySquare)
4936 DrawSquare(i, j, board[i][j], 0);
4937 damage[i][j] = False;
4940 /* Second pass -- Draw piece(s) in new position and flash them */
4941 for (i = 0; i < BOARD_HEIGHT; i++)
4942 for (j = 0; j < BOARD_WIDTH; j++)
4943 if (board[i][j] != lastBoard[i][j]) {
4944 DrawSquare(i, j, board[i][j], do_flash);
4948 XDrawSegments(xDisplay, xBoardWindow, lineGC,
4949 gridSegments, BOARD_HEIGHT + BOARD_WIDTH + 2);
4951 for (i = 0; i < BOARD_HEIGHT; i++)
4952 for (j = 0; j < BOARD_WIDTH; j++) {
4953 DrawSquare(i, j, board[i][j], 0);
4954 damage[i][j] = False;
4958 CopyBoard(lastBoard, board);
4960 lastFlipView = flipView;
4962 /* Draw highlights */
4963 if (pm1X >= 0 && pm1Y >= 0) {
4964 drawHighlight(pm1X, pm1Y, prelineGC);
4966 if (pm2X >= 0 && pm2Y >= 0) {
4967 drawHighlight(pm2X, pm2Y, prelineGC);
4969 if (hi1X >= 0 && hi1Y >= 0) {
4970 drawHighlight(hi1X, hi1Y, highlineGC);
4972 if (hi2X >= 0 && hi2Y >= 0) {
4973 drawHighlight(hi2X, hi2Y, highlineGC);
4976 /* If piece being dragged around board, must redraw that too */
4979 XSync(xDisplay, False);
4984 * event handler for redrawing the board
4986 void DrawPositionProc(w, event, prms, nprms)
4992 XDrawPosition(w, True, NULL);
4997 * event handler for parsing user moves
4999 // [HGM] This routine will need quite some reworking. Although the backend still supports the old
5000 // way of doing things, by calling UserMoveEvent() to test the legality of the move and then perform
5001 // it at the end, and doing all kind of preliminary tests here (e.g. to weed out self-captures), it
5002 // should be made to use the new way, of calling UserMoveTest early to determine the legality of the
5003 // move, (which will weed out the illegal selfcaptures and moves into the holdings, and flag promotions),
5004 // and at the end FinishMove() to perform the move after optional promotion popups.
5005 // For now I patched it to allow self-capture with King, and suppress clicks between board and holdings.
5006 void HandleUserMove(w, event, prms, nprms)
5013 Boolean saveAnimate;
5014 static int second = 0;
5016 if (w != boardWidget || errorExitStatus != -1) return;
5018 if (event->type == ButtonPress) ErrorPopDown();
5021 if (event->type == ButtonPress) {
5022 XtPopdown(promotionShell);
5023 XtDestroyWidget(promotionShell);
5024 promotionUp = False;
5032 x = EventToSquare(event->xbutton.x, BOARD_WIDTH);
5033 y = EventToSquare(event->xbutton.y, BOARD_HEIGHT);
5034 if (!flipView && y >= 0) {
5035 y = BOARD_HEIGHT - 1 - y;
5037 if (flipView && x >= 0) {
5038 x = BOARD_WIDTH - 1 - x;
5041 /* [HGM] holdings: next 5 lines: ignore all clicks between board and holdings */
5042 if(event->type == ButtonPress
5043 && ( x == BOARD_LEFT-1 || x == BOARD_RGHT
5044 || x == BOARD_LEFT-2 && y < BOARD_HEIGHT-gameInfo.holdingsSize
5045 || x == BOARD_RGHT+1 && y >= gameInfo.holdingsSize) )
5049 if (event->type == ButtonPress) {
5051 if (OKToStartUserMove(x, y)) {
5055 DragPieceBegin(event->xbutton.x, event->xbutton.y);
5056 if (appData.highlightDragging) {
5057 SetHighlights(x, y, -1, -1);
5065 if (event->type == ButtonPress && gameMode != EditPosition &&
5070 /* Check if clicking again on the same color piece */
5071 fromP = boards[currentMove][fromY][fromX];
5072 toP = boards[currentMove][y][x];
5073 if ((WhitePawn <= fromP && fromP < WhiteKing && // [HGM] this test should go, as UserMoveTest now does it.
5074 WhitePawn <= toP && toP <= WhiteKing) || // For now I made it less critical by exempting King
5075 (BlackPawn <= fromP && fromP < BlackKing && // moves, to not interfere with FRC castlings.
5076 BlackPawn <= toP && toP <= BlackKing)) {
5077 /* Clicked again on same color piece -- changed his mind */
5078 second = (x == fromX && y == fromY);
5079 if (appData.highlightDragging) {
5080 SetHighlights(x, y, -1, -1);
5084 if (OKToStartUserMove(x, y)) {
5087 DragPieceBegin(event->xbutton.x, event->xbutton.y);
5093 if (event->type == ButtonRelease && x == fromX && y == fromY) {
5094 DragPieceEnd(event->xbutton.x, event->xbutton.y);
5095 if (appData.animateDragging) {
5096 /* Undo animation damage if any */
5097 DrawPosition(FALSE, NULL);
5100 /* Second up/down in same square; just abort move */
5105 ClearPremoveHighlights();
5107 /* First upclick in same square; start click-click mode */
5108 SetHighlights(x, y, -1, -1);
5113 /* Completed move */
5116 saveAnimate = appData.animate;
5117 if (event->type == ButtonPress) {
5118 /* Finish clickclick move */
5119 if (appData.animate || appData.highlightLastMove) {
5120 SetHighlights(fromX, fromY, toX, toY);
5125 /* Finish drag move */
5126 if (appData.highlightLastMove) {
5127 SetHighlights(fromX, fromY, toX, toY);
5131 DragPieceEnd(event->xbutton.x, event->xbutton.y);
5132 /* Don't animate move and drag both */
5133 appData.animate = FALSE;
5135 if (IsPromotion(fromX, fromY, toX, toY)) {
5136 if (appData.alwaysPromoteToQueen) {
5137 UserMoveEvent(fromX, fromY, toX, toY, 'q');
5138 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
5139 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
5142 SetHighlights(fromX, fromY, toX, toY);
5146 UserMoveEvent(fromX, fromY, toX, toY, NULLCHAR);
5147 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
5148 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
5151 appData.animate = saveAnimate;
5152 if (appData.animate || appData.animateDragging) {
5153 /* Undo animation damage if needed */
5154 DrawPosition(FALSE, NULL);
5158 void AnimateUserMove (Widget w, XEvent * event,
5159 String * params, Cardinal * nParams)
5161 DragPieceMove(event->xmotion.x, event->xmotion.y);
5164 Widget CommentCreate(name, text, mutable, callback, lines)
5166 int /*Boolean*/ mutable;
5167 XtCallbackProc callback;
5171 Widget shell, layout, form, edit, b_ok, b_cancel, b_clear, b_close, b_edit;
5176 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5177 XtGetValues(boardWidget, args, j);
5180 XtSetArg(args[j], XtNresizable, True); j++;
5183 XtCreatePopupShell(name, topLevelShellWidgetClass,
5184 shellWidget, args, j);
5187 XtCreatePopupShell(name, transientShellWidgetClass,
5188 shellWidget, args, j);
5191 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
5192 layoutArgs, XtNumber(layoutArgs));
5194 XtCreateManagedWidget("form", formWidgetClass, layout,
5195 formArgs, XtNumber(formArgs));
5199 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
5200 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
5202 XtSetArg(args[j], XtNstring, text); j++;
5203 XtSetArg(args[j], XtNtop, XtChainTop); j++;
5204 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5205 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5206 XtSetArg(args[j], XtNright, XtChainRight); j++;
5207 XtSetArg(args[j], XtNresizable, True); j++;
5208 XtSetArg(args[j], XtNwidth, bw_width); j++; /*force wider than buttons*/
5210 XtSetArg(args[j], XtNscrollVertical, XawtextScrollWhenNeeded); j++;
5212 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
5213 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
5215 XtSetArg(args[j], XtNautoFill, True); j++;
5216 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
5218 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
5222 XtSetArg(args[j], XtNfromVert, edit); j++;
5223 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5224 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5225 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5226 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5228 XtCreateManagedWidget(_("ok"), commandWidgetClass, form, args, j);
5229 XtAddCallback(b_ok, XtNcallback, callback, (XtPointer) 0);
5232 XtSetArg(args[j], XtNfromVert, edit); j++;
5233 XtSetArg(args[j], XtNfromHoriz, b_ok); j++;
5234 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5235 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5236 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5237 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5239 XtCreateManagedWidget(_("cancel"), commandWidgetClass, form, args, j);
5240 XtAddCallback(b_cancel, XtNcallback, callback, (XtPointer) 0);
5243 XtSetArg(args[j], XtNfromVert, edit); j++;
5244 XtSetArg(args[j], XtNfromHoriz, b_cancel); j++;
5245 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5246 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5247 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5248 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5250 XtCreateManagedWidget(_("clear"), commandWidgetClass, form, args, j);
5251 XtAddCallback(b_clear, XtNcallback, callback, (XtPointer) 0);
5254 XtSetArg(args[j], XtNfromVert, edit); j++;
5255 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5256 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5257 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5258 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5260 XtCreateManagedWidget(_("close"), commandWidgetClass, form, args, j);
5261 XtAddCallback(b_close, XtNcallback, callback, (XtPointer) 0);
5264 XtSetArg(args[j], XtNfromVert, edit); j++;
5265 XtSetArg(args[j], XtNfromHoriz, b_close); j++;
5266 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5267 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5268 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5269 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5271 XtCreateManagedWidget(_("edit"), commandWidgetClass, form, args, j);
5272 XtAddCallback(b_edit, XtNcallback, callback, (XtPointer) 0);
5275 XtRealizeWidget(shell);
5277 if (commentX == -1) {
5280 Dimension pw_height;
5281 Dimension ew_height;
5284 XtSetArg(args[j], XtNheight, &ew_height); j++;
5285 XtGetValues(edit, args, j);
5288 XtSetArg(args[j], XtNheight, &pw_height); j++;
5289 XtGetValues(shell, args, j);
5290 commentH = pw_height + (lines - 1) * ew_height;
5291 commentW = bw_width - 16;
5293 XSync(xDisplay, False);
5295 /* This code seems to tickle an X bug if it is executed too soon
5296 after xboard starts up. The coordinates get transformed as if
5297 the main window was positioned at (0, 0).
5299 XtTranslateCoords(shellWidget,
5300 (bw_width - commentW) / 2, 0 - commentH / 2,
5301 &commentX, &commentY);
5303 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
5304 RootWindowOfScreen(XtScreen(shellWidget)),
5305 (bw_width - commentW) / 2, 0 - commentH / 2,
5310 if (commentY < 0) commentY = 0; /*avoid positioning top offscreen*/
5313 XtSetArg(args[j], XtNheight, commentH); j++;
5314 XtSetArg(args[j], XtNwidth, commentW); j++;
5315 XtSetArg(args[j], XtNx, commentX); j++;
5316 XtSetArg(args[j], XtNy, commentY); j++;
5317 XtSetValues(shell, args, j);
5318 XtSetKeyboardFocus(shell, edit);
5323 /* Used for analysis window and ICS input window */
5324 Widget MiscCreate(name, text, mutable, callback, lines)
5326 int /*Boolean*/ mutable;
5327 XtCallbackProc callback;
5331 Widget shell, layout, form, edit;
5333 Dimension bw_width, pw_height, ew_height, w, h;
5339 XtSetArg(args[j], XtNresizable, True); j++;
5342 XtCreatePopupShell(name, topLevelShellWidgetClass,
5343 shellWidget, args, j);
5346 XtCreatePopupShell(name, transientShellWidgetClass,
5347 shellWidget, args, j);
5350 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
5351 layoutArgs, XtNumber(layoutArgs));
5353 XtCreateManagedWidget("form", formWidgetClass, layout,
5354 formArgs, XtNumber(formArgs));
5358 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
5359 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
5361 XtSetArg(args[j], XtNstring, text); j++;
5362 XtSetArg(args[j], XtNtop, XtChainTop); j++;
5363 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5364 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5365 XtSetArg(args[j], XtNright, XtChainRight); j++;
5366 XtSetArg(args[j], XtNresizable, True); j++;
5368 XtSetArg(args[j], XtNscrollVertical, XawtextScrollWhenNeeded); j++;
5370 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
5371 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
5373 XtSetArg(args[j], XtNautoFill, True); j++;
5374 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
5376 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
5378 XtRealizeWidget(shell);
5381 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5382 XtGetValues(boardWidget, args, j);
5385 XtSetArg(args[j], XtNheight, &ew_height); j++;
5386 XtGetValues(edit, args, j);
5389 XtSetArg(args[j], XtNheight, &pw_height); j++;
5390 XtGetValues(shell, args, j);
5391 h = pw_height + (lines - 1) * ew_height;
5394 XSync(xDisplay, False);
5396 /* This code seems to tickle an X bug if it is executed too soon
5397 after xboard starts up. The coordinates get transformed as if
5398 the main window was positioned at (0, 0).
5400 XtTranslateCoords(shellWidget, (bw_width - w) / 2, 0 - h / 2, &x, &y);
5402 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
5403 RootWindowOfScreen(XtScreen(shellWidget)),
5404 (bw_width - w) / 2, 0 - h / 2, &xx, &yy, &junk);
5408 if (y < 0) y = 0; /*avoid positioning top offscreen*/
5411 XtSetArg(args[j], XtNheight, h); j++;
5412 XtSetArg(args[j], XtNwidth, w); j++;
5413 XtSetArg(args[j], XtNx, x); j++;
5414 XtSetArg(args[j], XtNy, y); j++;
5415 XtSetValues(shell, args, j);
5421 static int savedIndex; /* gross that this is global */
5423 void EditCommentPopUp(index, title, text)
5432 if (text == NULL) text = "";
5434 if (editShell == NULL) {
5436 CommentCreate(title, text, True, EditCommentCallback, 4);
5437 XtRealizeWidget(editShell);
5438 CatchDeleteWindow(editShell, "EditCommentPopDown");
5440 edit = XtNameToWidget(editShell, "*form.text");
5442 XtSetArg(args[j], XtNstring, text); j++;
5443 XtSetValues(edit, args, j);
5445 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5446 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5447 XtSetValues(editShell, args, j);
5450 XtPopup(editShell, XtGrabNone);
5454 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
5455 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
5459 void EditCommentCallback(w, client_data, call_data)
5461 XtPointer client_data, call_data;
5469 XtSetArg(args[j], XtNlabel, &name); j++;
5470 XtGetValues(w, args, j);
5472 if (strcmp(name, _("ok")) == 0) {
5473 edit = XtNameToWidget(editShell, "*form.text");
5475 XtSetArg(args[j], XtNstring, &val); j++;
5476 XtGetValues(edit, args, j);
5477 ReplaceComment(savedIndex, val);
5478 EditCommentPopDown();
5479 } else if (strcmp(name, _("cancel")) == 0) {
5480 EditCommentPopDown();
5481 } else if (strcmp(name, _("clear")) == 0) {
5482 edit = XtNameToWidget(editShell, "*form.text");
5483 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
5484 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
5488 void EditCommentPopDown()
5493 if (!editUp) return;
5495 XtSetArg(args[j], XtNx, &commentX); j++;
5496 XtSetArg(args[j], XtNy, &commentY); j++;
5497 XtSetArg(args[j], XtNheight, &commentH); j++;
5498 XtSetArg(args[j], XtNwidth, &commentW); j++;
5499 XtGetValues(editShell, args, j);
5500 XtPopdown(editShell);
5503 XtSetArg(args[j], XtNleftBitmap, None); j++;
5504 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
5508 void ICSInputBoxPopUp()
5513 char *title = _("ICS Input");
5516 if (ICSInputShell == NULL) {
5517 ICSInputShell = MiscCreate(title, "", True, NULL, 1);
5518 tr = XtParseTranslationTable(ICSInputTranslations);
5519 edit = XtNameToWidget(ICSInputShell, "*form.text");
5520 XtOverrideTranslations(edit, tr);
5521 XtRealizeWidget(ICSInputShell);
5522 CatchDeleteWindow(ICSInputShell, "ICSInputBoxPopDown");
5525 edit = XtNameToWidget(ICSInputShell, "*form.text");
5527 XtSetArg(args[j], XtNstring, ""); j++;
5528 XtSetValues(edit, args, j);
5530 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5531 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5532 XtSetValues(ICSInputShell, args, j);
5535 XtPopup(ICSInputShell, XtGrabNone);
5536 XtSetKeyboardFocus(ICSInputShell, edit);
5538 ICSInputBoxUp = True;
5540 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
5541 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
5545 void ICSInputSendText()
5552 edit = XtNameToWidget(ICSInputShell, "*form.text");
5554 XtSetArg(args[j], XtNstring, &val); j++;
5555 XtGetValues(edit, args, j);
5556 SendMultiLineToICS(val);
5557 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
5558 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
5561 void ICSInputBoxPopDown()
5566 if (!ICSInputBoxUp) return;
5568 XtPopdown(ICSInputShell);
5569 ICSInputBoxUp = False;
5571 XtSetArg(args[j], XtNleftBitmap, None); j++;
5572 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
5576 void CommentPopUp(title, text)
5583 if (commentShell == NULL) {
5585 CommentCreate(title, text, False, CommentCallback, 4);
5586 XtRealizeWidget(commentShell);
5587 CatchDeleteWindow(commentShell, "CommentPopDown");
5589 edit = XtNameToWidget(commentShell, "*form.text");
5591 XtSetArg(args[j], XtNstring, text); j++;
5592 XtSetValues(edit, args, j);
5594 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5595 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5596 XtSetValues(commentShell, args, j);
5599 XtPopup(commentShell, XtGrabNone);
5600 XSync(xDisplay, False);
5605 void AnalysisPopUp(title, text)
5612 if (analysisShell == NULL) {
5613 analysisShell = MiscCreate(title, text, False, NULL, 4);
5614 XtRealizeWidget(analysisShell);
5615 CatchDeleteWindow(analysisShell, "AnalysisPopDown");
5618 edit = XtNameToWidget(analysisShell, "*form.text");
5620 XtSetArg(args[j], XtNstring, text); j++;
5621 XtSetValues(edit, args, j);
5623 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5624 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5625 XtSetValues(analysisShell, args, j);
5629 XtPopup(analysisShell, XtGrabNone);
5631 XSync(xDisplay, False);
5636 void CommentCallback(w, client_data, call_data)
5638 XtPointer client_data, call_data;
5645 XtSetArg(args[j], XtNlabel, &name); j++;
5646 XtGetValues(w, args, j);
5648 if (strcmp(name, _("close")) == 0) {
5650 } else if (strcmp(name, _("edit")) == 0) {
5657 void CommentPopDown()
5662 if (!commentUp) return;
5664 XtSetArg(args[j], XtNx, &commentX); j++;
5665 XtSetArg(args[j], XtNy, &commentY); j++;
5666 XtSetArg(args[j], XtNwidth, &commentW); j++;
5667 XtSetArg(args[j], XtNheight, &commentH); j++;
5668 XtGetValues(commentShell, args, j);
5669 XtPopdown(commentShell);
5670 XSync(xDisplay, False);
5674 void AnalysisPopDown()
5676 if (!analysisUp) return;
5677 XtPopdown(analysisShell);
5678 XSync(xDisplay, False);
5680 if (appData.icsEngineAnalyze) ExitAnalyzeMode(); /* [DM] icsEngineAnalyze */
5684 void FileNamePopUp(label, def, proc, openMode)
5691 Widget popup, layout, dialog, edit;
5697 fileProc = proc; /* I can't see a way not */
5698 fileOpenMode = openMode; /* to use globals here */
5701 XtSetArg(args[i], XtNresizable, True); i++;
5702 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
5703 XtSetArg(args[i], XtNtitle, XtNewString(_("File name prompt"))); i++;
5704 fileNameShell = popup =
5705 XtCreatePopupShell("File name prompt", transientShellWidgetClass,
5706 shellWidget, args, i);
5709 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
5710 layoutArgs, XtNumber(layoutArgs));
5713 XtSetArg(args[i], XtNlabel, label); i++;
5714 XtSetArg(args[i], XtNvalue, def); i++;
5715 XtSetArg(args[i], XtNborderWidth, 0); i++;
5716 dialog = XtCreateManagedWidget("fileName", dialogWidgetClass,
5719 XawDialogAddButton(dialog, _("ok"), FileNameCallback, (XtPointer) dialog);
5720 XawDialogAddButton(dialog, _("cancel"), FileNameCallback,
5721 (XtPointer) dialog);
5723 XtRealizeWidget(popup);
5724 CatchDeleteWindow(popup, "FileNamePopDown");
5726 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
5727 &x, &y, &win_x, &win_y, &mask);
5729 XtSetArg(args[0], XtNx, x - 10);
5730 XtSetArg(args[1], XtNy, y - 30);
5731 XtSetValues(popup, args, 2);
5733 XtPopup(popup, XtGrabExclusive);
5736 edit = XtNameToWidget(dialog, "*value");
5737 XtSetKeyboardFocus(popup, edit);
5740 void FileNamePopDown()
5742 if (!filenameUp) return;
5743 XtPopdown(fileNameShell);
5744 XtDestroyWidget(fileNameShell);
5749 void FileNameCallback(w, client_data, call_data)
5751 XtPointer client_data, call_data;
5756 XtSetArg(args[0], XtNlabel, &name);
5757 XtGetValues(w, args, 1);
5759 if (strcmp(name, _("cancel")) == 0) {
5764 FileNameAction(w, NULL, NULL, NULL);
5767 void FileNameAction(w, event, prms, nprms)
5779 name = XawDialogGetValueString(w = XtParent(w));
5781 if ((name != NULL) && (*name != NULLCHAR)) {
5783 XtPopdown(w = XtParent(XtParent(w)));
5787 p = strrchr(buf, ' ');
5794 fullname = ExpandPathName(buf);
5796 ErrorPopUp(_("Error"), _("Can't open file"), FALSE);
5799 f = fopen(fullname, fileOpenMode);
5801 DisplayError(_("Failed to open file"), errno);
5803 (void) (*fileProc)(f, index, buf);
5810 XtPopdown(w = XtParent(XtParent(w)));
5816 void PromotionPopUp()
5819 Widget dialog, layout;
5821 Dimension bw_width, pw_width;
5825 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5826 XtGetValues(boardWidget, args, j);
5829 XtSetArg(args[j], XtNresizable, True); j++;
5830 XtSetArg(args[j], XtNtitle, XtNewString(_("Promotion"))); j++;
5832 XtCreatePopupShell("Promotion", transientShellWidgetClass,
5833 shellWidget, args, j);
5835 XtCreateManagedWidget(layoutName, formWidgetClass, promotionShell,
5836 layoutArgs, XtNumber(layoutArgs));
5839 XtSetArg(args[j], XtNlabel, _("Promote pawn to what?")); j++;
5840 XtSetArg(args[j], XtNborderWidth, 0); j++;
5841 dialog = XtCreateManagedWidget("promotion", dialogWidgetClass,
5844 XawDialogAddButton(dialog, _("Queen"), PromotionCallback,
5845 (XtPointer) dialog);
5846 XawDialogAddButton(dialog, _("Rook"), PromotionCallback,
5847 (XtPointer) dialog);
5848 XawDialogAddButton(dialog, _("Bishop"), PromotionCallback,
5849 (XtPointer) dialog);
5850 XawDialogAddButton(dialog, _("Knight"), PromotionCallback,
5851 (XtPointer) dialog);
5852 if (!appData.testLegality || gameInfo.variant == VariantSuicide ||
5853 gameInfo.variant == VariantGiveaway) {
5854 XawDialogAddButton(dialog, _("King"), PromotionCallback,
5855 (XtPointer) dialog);
5857 XawDialogAddButton(dialog, _("cancel"), PromotionCallback,
5858 (XtPointer) dialog);
5860 XtRealizeWidget(promotionShell);
5861 CatchDeleteWindow(promotionShell, "PromotionPopDown");
5864 XtSetArg(args[j], XtNwidth, &pw_width); j++;
5865 XtGetValues(promotionShell, args, j);
5867 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
5868 lineGap + squareSize/3 +
5869 ((toY == BOARD_HEIGHT-1) ^ (flipView) ?
5870 0 : 6*(squareSize + lineGap)), &x, &y);
5873 XtSetArg(args[j], XtNx, x); j++;
5874 XtSetArg(args[j], XtNy, y); j++;
5875 XtSetValues(promotionShell, args, j);
5877 XtPopup(promotionShell, XtGrabNone);
5882 void PromotionPopDown()
5884 if (!promotionUp) return;
5885 XtPopdown(promotionShell);
5886 XtDestroyWidget(promotionShell);
5887 promotionUp = False;
5890 void PromotionCallback(w, client_data, call_data)
5892 XtPointer client_data, call_data;
5898 XtSetArg(args[0], XtNlabel, &name);
5899 XtGetValues(w, args, 1);
5903 if (fromX == -1) return;
5905 if (strcmp(name, _("cancel")) == 0) {
5909 } else if (strcmp(name, _("Knight")) == 0) {
5912 promoChar = ToLower(name[0]);
5915 UserMoveEvent(fromX, fromY, toX, toY, promoChar);
5917 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
5918 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
5923 void ErrorCallback(w, client_data, call_data)
5925 XtPointer client_data, call_data;
5928 XtPopdown(w = XtParent(XtParent(XtParent(w))));
5930 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
5936 if (!errorUp) return;
5938 XtPopdown(errorShell);
5939 XtDestroyWidget(errorShell);
5940 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
5943 void ErrorPopUp(title, label, modal)
5944 char *title, *label;
5948 Widget dialog, layout;
5952 Dimension bw_width, pw_width;
5953 Dimension pw_height;
5957 XtSetArg(args[i], XtNresizable, True); i++;
5958 XtSetArg(args[i], XtNtitle, title); i++;
5960 XtCreatePopupShell("errorpopup", transientShellWidgetClass,
5961 shellWidget, args, i);
5963 XtCreateManagedWidget(layoutName, formWidgetClass, errorShell,
5964 layoutArgs, XtNumber(layoutArgs));
5967 XtSetArg(args[i], XtNlabel, label); i++;
5968 XtSetArg(args[i], XtNborderWidth, 0); i++;
5969 dialog = XtCreateManagedWidget("dialog", dialogWidgetClass,
5972 XawDialogAddButton(dialog, _("ok"), ErrorCallback, (XtPointer) dialog);
5974 XtRealizeWidget(errorShell);
5975 CatchDeleteWindow(errorShell, "ErrorPopDown");
5978 XtSetArg(args[i], XtNwidth, &bw_width); i++;
5979 XtGetValues(boardWidget, args, i);
5981 XtSetArg(args[i], XtNwidth, &pw_width); i++;
5982 XtSetArg(args[i], XtNheight, &pw_height); i++;
5983 XtGetValues(errorShell, args, i);
5986 /* This code seems to tickle an X bug if it is executed too soon
5987 after xboard starts up. The coordinates get transformed as if
5988 the main window was positioned at (0, 0).
5990 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
5991 0 - pw_height + squareSize / 3, &x, &y);
5993 XTranslateCoordinates(xDisplay, XtWindow(boardWidget),
5994 RootWindowOfScreen(XtScreen(boardWidget)),
5995 (bw_width - pw_width) / 2,
5996 0 - pw_height + squareSize / 3, &xx, &yy, &junk);
6000 if (y < 0) y = 0; /*avoid positioning top offscreen*/
6003 XtSetArg(args[i], XtNx, x); i++;
6004 XtSetArg(args[i], XtNy, y); i++;
6005 XtSetValues(errorShell, args, i);
6008 XtPopup(errorShell, modal ? XtGrabExclusive : XtGrabNone);
6011 /* Disable all user input other than deleting the window */
6012 static int frozen = 0;
6016 /* Grab by a widget that doesn't accept input */
6017 XtAddGrab(messageWidget, TRUE, FALSE);
6021 /* Undo a FreezeUI */
6024 if (!frozen) return;
6025 XtRemoveGrab(messageWidget);
6029 char *ModeToWidgetName(mode)
6033 case BeginningOfGame:
6034 if (appData.icsActive)
6035 return "menuMode.ICS Client";
6036 else if (appData.noChessProgram ||
6037 *appData.cmailGameName != NULLCHAR)
6038 return "menuMode.Edit Game";
6040 return "menuMode.Machine Black";
6041 case MachinePlaysBlack:
6042 return "menuMode.Machine Black";
6043 case MachinePlaysWhite:
6044 return "menuMode.Machine White";
6046 return "menuMode.Analysis Mode";
6048 return "menuMode.Analyze File";
6049 case TwoMachinesPlay:
6050 return "menuMode.Two Machines";
6052 return "menuMode.Edit Game";
6053 case PlayFromGameFile:
6054 return "menuFile.Load Game";
6056 return "menuMode.Edit Position";
6058 return "menuMode.Training";
6059 case IcsPlayingWhite:
6060 case IcsPlayingBlack:
6064 return "menuMode.ICS Client";
6071 void ModeHighlight()
6074 static int oldPausing = FALSE;
6075 static GameMode oldmode = (GameMode) -1;
6078 if (!boardWidget || !XtIsRealized(boardWidget)) return;
6080 if (pausing != oldPausing) {
6081 oldPausing = pausing;
6083 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6085 XtSetArg(args[0], XtNleftBitmap, None);
6087 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Pause"),
6090 if (appData.showButtonBar) {
6093 XtSetArg(args[0], XtNbackground, buttonForegroundPixel);
6094 XtSetArg(args[1], XtNforeground, buttonBackgroundPixel);
6096 XtSetArg(args[0], XtNbackground, buttonBackgroundPixel);
6097 XtSetArg(args[1], XtNforeground, buttonForegroundPixel);
6100 /* Always toggle, don't set. Previous code messes up when
6101 invoked while the button is pressed, as releasing it
6102 toggles the state again. */
6105 XtSetArg(args[0], XtNbackground, &oldbg);
6106 XtSetArg(args[1], XtNforeground, &oldfg);
6107 XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON),
6109 XtSetArg(args[0], XtNbackground, oldfg);
6110 XtSetArg(args[1], XtNforeground, oldbg);
6113 XtSetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
6117 wname = ModeToWidgetName(oldmode);
6118 if (wname != NULL) {
6119 XtSetArg(args[0], XtNleftBitmap, None);
6120 XtSetValues(XtNameToWidget(menuBarWidget, wname), args, 1);
6122 wname = ModeToWidgetName(gameMode);
6123 if (wname != NULL) {
6124 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6125 XtSetValues(XtNameToWidget(menuBarWidget, wname), args, 1);
6129 /* Maybe all the enables should be handled here, not just this one */
6130 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Training"),
6131 gameMode == Training || gameMode == PlayFromGameFile);
6136 * Button/menu procedures
6138 void ResetProc(w, event, prms, nprms)
6148 int LoadGamePopUp(f, gameNumber, title)
6153 cmailMsgLoaded = FALSE;
6154 if (gameNumber == 0) {
6155 int error = GameListBuild(f);
6157 DisplayError(_("Cannot build game list"), error);
6158 } else if (!ListEmpty(&gameList) &&
6159 ((ListGame *) gameList.tailPred)->number > 1) {
6160 GameListPopUp(f, title);
6166 return LoadGame(f, gameNumber, title, FALSE);
6169 void LoadGameProc(w, event, prms, nprms)
6175 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
6178 FileNamePopUp(_("Load game file name?"), "", LoadGamePopUp, "rb");
6181 void LoadNextGameProc(w, event, prms, nprms)
6190 void LoadPrevGameProc(w, event, prms, nprms)
6199 void ReloadGameProc(w, event, prms, nprms)
6208 void LoadNextPositionProc(w, event, prms, nprms)
6217 void LoadPrevPositionProc(w, event, prms, nprms)
6226 void ReloadPositionProc(w, event, prms, nprms)
6235 void LoadPositionProc(w, event, prms, nprms)
6241 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
6244 FileNamePopUp(_("Load position file name?"), "", LoadPosition, "rb");
6247 void SaveGameProc(w, event, prms, nprms)
6253 FileNamePopUp(_("Save game file name?"),
6254 DefaultFileName(appData.oldSaveStyle ? "game" : "pgn"),
6258 void SavePositionProc(w, event, prms, nprms)
6264 FileNamePopUp(_("Save position file name?"),
6265 DefaultFileName(appData.oldSaveStyle ? "pos" : "fen"),
6269 void ReloadCmailMsgProc(w, event, prms, nprms)
6275 ReloadCmailMsgEvent(FALSE);
6278 void MailMoveProc(w, event, prms, nprms)
6287 /* this variable is shared between CopyPositionProc and SendPositionSelection */
6288 static char *selected_fen_position=NULL;
6291 SendPositionSelection(Widget w, Atom *selection, Atom *target,
6292 Atom *type_return, XtPointer *value_return,
6293 unsigned long *length_return, int *format_return)
6295 char *selection_tmp;
6297 if (!selected_fen_position) return False; /* should never happen */
6298 if (*target == XA_STRING){
6299 /* note: since no XtSelectionDoneProc was registered, Xt will
6300 * automatically call XtFree on the value returned. So have to
6301 * make a copy of it allocated with XtMalloc */
6302 selection_tmp= XtMalloc(strlen(selected_fen_position)+16);
6303 strcpy(selection_tmp, selected_fen_position);
6305 *value_return=selection_tmp;
6306 *length_return=strlen(selection_tmp);
6307 *type_return=XA_STRING;
6308 *format_return = 8; /* bits per byte */
6315 /* note: when called from menu all parameters are NULL, so no clue what the
6316 * Widget which was clicked on was, or what the click event was
6318 void CopyPositionProc(w, event, prms, nprms)
6326 if (selected_fen_position) free(selected_fen_position);
6327 selected_fen_position = (char *)PositionToFEN(currentMove, NULL);
6328 if (!selected_fen_position) return;
6329 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
6331 SendPositionSelection,
6332 NULL/* lose_ownership_proc */ ,
6333 NULL/* transfer_done_proc */);
6335 free(selected_fen_position);
6336 selected_fen_position=NULL;
6340 /* function called when the data to Paste is ready */
6342 PastePositionCB(Widget w, XtPointer client_data, Atom *selection,
6343 Atom *type, XtPointer value, unsigned long *len, int *format)
6346 if (value==NULL || *len==0) return; /* nothing had been selected to copy */
6347 fenstr[*len]='\0'; /* normally this string is terminated, but be safe */
6348 EditPositionPasteFEN(fenstr);
6352 /* called when Paste Position button is pressed,
6353 * all parameters will be NULL */
6354 void PastePositionProc(w, event, prms, nprms)
6360 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
6361 /* (XtSelectionCallbackProc) */ PastePositionCB,
6362 NULL, /* client_data passed to PastePositionCB */
6364 /* better to use the time field from the event that triggered the
6365 * call to this function, but that isn't trivial to get
6373 SendGameSelection(Widget w, Atom *selection, Atom *target,
6374 Atom *type_return, XtPointer *value_return,
6375 unsigned long *length_return, int *format_return)
6377 char *selection_tmp;
6379 if (*target == XA_STRING){
6380 FILE* f = fopen(gameCopyFilename, "r");
6383 if (f == NULL) return False;
6387 selection_tmp = XtMalloc(len + 1);
6388 count = fread(selection_tmp, 1, len, f);
6390 XtFree(selection_tmp);
6393 selection_tmp[len] = NULLCHAR;
6394 *value_return = selection_tmp;
6395 *length_return = len;
6396 *type_return = XA_STRING;
6397 *format_return = 8; /* bits per byte */
6404 /* note: when called from menu all parameters are NULL, so no clue what the
6405 * Widget which was clicked on was, or what the click event was
6407 void CopyGameProc(w, event, prms, nprms)
6415 ret = SaveGameToFile(gameCopyFilename, FALSE);
6418 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
6421 NULL/* lose_ownership_proc */ ,
6422 NULL/* transfer_done_proc */);
6425 /* function called when the data to Paste is ready */
6427 PasteGameCB(Widget w, XtPointer client_data, Atom *selection,
6428 Atom *type, XtPointer value, unsigned long *len, int *format)
6431 if (value == NULL || *len == 0) {
6432 return; /* nothing had been selected to copy */
6434 f = fopen(gamePasteFilename, "w");
6436 DisplayError(_("Can't open temp file"), errno);
6439 fwrite(value, 1, *len, f);
6442 LoadGameFromFile(gamePasteFilename, 0, gamePasteFilename, TRUE);
6445 /* called when Paste Game button is pressed,
6446 * all parameters will be NULL */
6447 void PasteGameProc(w, event, prms, nprms)
6453 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
6454 /* (XtSelectionCallbackProc) */ PasteGameCB,
6455 NULL, /* client_data passed to PasteGameCB */
6457 /* better to use the time field from the event that triggered the
6458 * call to this function, but that isn't trivial to get
6468 SaveGameProc(NULL, NULL, NULL, NULL);
6472 void QuitProc(w, event, prms, nprms)
6481 void PauseProc(w, event, prms, nprms)
6491 void MachineBlackProc(w, event, prms, nprms)
6497 MachineBlackEvent();
6500 void MachineWhiteProc(w, event, prms, nprms)
6506 MachineWhiteEvent();
6509 void AnalyzeModeProc(w, event, prms, nprms)
6517 if (!first.analysisSupport) {
6518 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
6519 DisplayError(buf, 0);
6522 /* [DM] icsEngineAnalyze [HGM] This is horrible code; reverse the gameMode and isEngineAnalyze tests! */
6523 if (appData.icsActive) {
6524 if (gameMode != IcsObserving) {
6525 sprintf(buf,_("You are not observing a game"));
6526 DisplayError(buf, 0);
6528 if (appData.icsEngineAnalyze) {
6529 if (appData.debugMode)
6530 fprintf(debugFP, _("Found unexpected active ICS engine analyze \n"));
6536 /* if enable, use want disable icsEngineAnalyze */
6537 if (appData.icsEngineAnalyze) {
6542 appData.icsEngineAnalyze = TRUE;
6543 if (appData.debugMode)
6544 fprintf(debugFP, _("ICS engine analyze starting... \n"));
6546 if (!appData.showThinking)
6547 ShowThinkingProc(w,event,prms,nprms);
6552 void AnalyzeFileProc(w, event, prms, nprms)
6558 if (!first.analysisSupport) {
6560 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
6561 DisplayError(buf, 0);
6566 if (!appData.showThinking)
6567 ShowThinkingProc(w,event,prms,nprms);
6570 FileNamePopUp(_("File to analyze"), "", LoadGamePopUp, "rb");
6571 AnalysisPeriodicEvent(1);
6574 void TwoMachinesProc(w, event, prms, nprms)
6583 void IcsClientProc(w, event, prms, nprms)
6592 void EditGameProc(w, event, prms, nprms)
6601 void EditPositionProc(w, event, prms, nprms)
6607 EditPositionEvent();
6610 void TrainingProc(w, event, prms, nprms)
6619 void EditCommentProc(w, event, prms, nprms)
6626 EditCommentPopDown();
6632 void IcsInputBoxProc(w, event, prms, nprms)
6638 if (ICSInputBoxUp) {
6639 ICSInputBoxPopDown();
6645 void AcceptProc(w, event, prms, nprms)
6654 void DeclineProc(w, event, prms, nprms)
6663 void RematchProc(w, event, prms, nprms)
6672 void CallFlagProc(w, event, prms, nprms)
6681 void DrawProc(w, event, prms, nprms)
6690 void AbortProc(w, event, prms, nprms)
6699 void AdjournProc(w, event, prms, nprms)
6708 void ResignProc(w, event, prms, nprms)
6717 void AdjuWhiteProc(w, event, prms, nprms)
6723 UserAdjudicationEvent(+1);
6726 void AdjuBlackProc(w, event, prms, nprms)
6732 UserAdjudicationEvent(-1);
6735 void AdjuDrawProc(w, event, prms, nprms)
6741 UserAdjudicationEvent(0);
6744 void EnterKeyProc(w, event, prms, nprms)
6750 if (ICSInputBoxUp == True)
6754 void StopObservingProc(w, event, prms, nprms)
6760 StopObservingEvent();
6763 void StopExaminingProc(w, event, prms, nprms)
6769 StopExaminingEvent();
6773 void ForwardProc(w, event, prms, nprms)
6783 void BackwardProc(w, event, prms, nprms)
6792 void ToStartProc(w, event, prms, nprms)
6801 void ToEndProc(w, event, prms, nprms)
6810 void RevertProc(w, event, prms, nprms)
6819 void TruncateGameProc(w, event, prms, nprms)
6825 TruncateGameEvent();
6827 void RetractMoveProc(w, event, prms, nprms)
6836 void MoveNowProc(w, event, prms, nprms)
6846 void AlwaysQueenProc(w, event, prms, nprms)
6854 appData.alwaysPromoteToQueen = !appData.alwaysPromoteToQueen;
6856 if (appData.alwaysPromoteToQueen) {
6857 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6859 XtSetArg(args[0], XtNleftBitmap, None);
6861 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
6865 void AnimateDraggingProc(w, event, prms, nprms)
6873 appData.animateDragging = !appData.animateDragging;
6875 if (appData.animateDragging) {
6876 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6879 XtSetArg(args[0], XtNleftBitmap, None);
6881 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Dragging"),
6885 void AnimateMovingProc(w, event, prms, nprms)
6893 appData.animate = !appData.animate;
6895 if (appData.animate) {
6896 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6899 XtSetArg(args[0], XtNleftBitmap, None);
6901 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
6905 void AutocommProc(w, event, prms, nprms)
6913 appData.autoComment = !appData.autoComment;
6915 if (appData.autoComment) {
6916 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6918 XtSetArg(args[0], XtNleftBitmap, None);
6920 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
6925 void AutoflagProc(w, event, prms, nprms)
6933 appData.autoCallFlag = !appData.autoCallFlag;
6935 if (appData.autoCallFlag) {
6936 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6938 XtSetArg(args[0], XtNleftBitmap, None);
6940 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
6944 void AutoflipProc(w, event, prms, nprms)
6952 appData.autoFlipView = !appData.autoFlipView;
6954 if (appData.autoFlipView) {
6955 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6957 XtSetArg(args[0], XtNleftBitmap, None);
6959 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flip View"),
6963 void AutobsProc(w, event, prms, nprms)
6971 appData.autoObserve = !appData.autoObserve;
6973 if (appData.autoObserve) {
6974 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6976 XtSetArg(args[0], XtNleftBitmap, None);
6978 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
6982 void AutoraiseProc(w, event, prms, nprms)
6990 appData.autoRaiseBoard = !appData.autoRaiseBoard;
6992 if (appData.autoRaiseBoard) {
6993 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6995 XtSetArg(args[0], XtNleftBitmap, None);
6997 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Raise Board"),
7001 void AutosaveProc(w, event, prms, nprms)
7009 appData.autoSaveGames = !appData.autoSaveGames;
7011 if (appData.autoSaveGames) {
7012 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7014 XtSetArg(args[0], XtNleftBitmap, None);
7016 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
7020 void BlindfoldProc(w, event, prms, nprms)
7028 appData.blindfold = !appData.blindfold;
7030 if (appData.blindfold) {
7031 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7033 XtSetArg(args[0], XtNleftBitmap, None);
7035 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Blindfold"),
7038 DrawPosition(True, NULL);
7041 void TestLegalityProc(w, event, prms, nprms)
7049 appData.testLegality = !appData.testLegality;
7051 if (appData.testLegality) {
7052 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7054 XtSetArg(args[0], XtNleftBitmap, None);
7056 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Test Legality"),
7061 void FlashMovesProc(w, event, prms, nprms)
7069 if (appData.flashCount == 0) {
7070 appData.flashCount = 3;
7072 appData.flashCount = -appData.flashCount;
7075 if (appData.flashCount > 0) {
7076 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7078 XtSetArg(args[0], XtNleftBitmap, None);
7080 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flash Moves"),
7084 void FlipViewProc(w, event, prms, nprms)
7090 flipView = !flipView;
7091 DrawPosition(True, NULL);
7094 void GetMoveListProc(w, event, prms, nprms)
7102 appData.getMoveList = !appData.getMoveList;
7104 if (appData.getMoveList) {
7105 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7108 XtSetArg(args[0], XtNleftBitmap, None);
7110 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
7115 void HighlightDraggingProc(w, event, prms, nprms)
7123 appData.highlightDragging = !appData.highlightDragging;
7125 if (appData.highlightDragging) {
7126 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7128 XtSetArg(args[0], XtNleftBitmap, None);
7130 XtSetValues(XtNameToWidget(menuBarWidget,
7131 "menuOptions.Highlight Dragging"), args, 1);
7135 void HighlightLastMoveProc(w, event, prms, nprms)
7143 appData.highlightLastMove = !appData.highlightLastMove;
7145 if (appData.highlightLastMove) {
7146 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7148 XtSetArg(args[0], XtNleftBitmap, None);
7150 XtSetValues(XtNameToWidget(menuBarWidget,
7151 "menuOptions.Highlight Last Move"), args, 1);
7154 void IcsAlarmProc(w, event, prms, nprms)
7162 appData.icsAlarm = !appData.icsAlarm;
7164 if (appData.icsAlarm) {
7165 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7167 XtSetArg(args[0], XtNleftBitmap, None);
7169 XtSetValues(XtNameToWidget(menuBarWidget,
7170 "menuOptions.ICS Alarm"), args, 1);
7173 void MoveSoundProc(w, event, prms, nprms)
7181 appData.ringBellAfterMoves = !appData.ringBellAfterMoves;
7183 if (appData.ringBellAfterMoves) {
7184 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7186 XtSetArg(args[0], XtNleftBitmap, None);
7188 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
7193 void OldSaveStyleProc(w, event, prms, nprms)
7201 appData.oldSaveStyle = !appData.oldSaveStyle;
7203 if (appData.oldSaveStyle) {
7204 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7206 XtSetArg(args[0], XtNleftBitmap, None);
7208 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Old Save Style"),
7212 void PeriodicUpdatesProc(w, event, prms, nprms)
7220 PeriodicUpdatesEvent(!appData.periodicUpdates);
7222 if (appData.periodicUpdates) {
7223 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7225 XtSetArg(args[0], XtNleftBitmap, None);
7227 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Periodic Updates"),
7231 void PonderNextMoveProc(w, event, prms, nprms)
7239 PonderNextMoveEvent(!appData.ponderNextMove);
7241 if (appData.ponderNextMove) {
7242 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7244 XtSetArg(args[0], XtNleftBitmap, None);
7246 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Ponder Next Move"),
7250 void PopupExitMessageProc(w, event, prms, nprms)
7258 appData.popupExitMessage = !appData.popupExitMessage;
7260 if (appData.popupExitMessage) {
7261 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7263 XtSetArg(args[0], XtNleftBitmap, None);
7265 XtSetValues(XtNameToWidget(menuBarWidget,
7266 "menuOptions.Popup Exit Message"), args, 1);
7269 void PopupMoveErrorsProc(w, event, prms, nprms)
7277 appData.popupMoveErrors = !appData.popupMoveErrors;
7279 if (appData.popupMoveErrors) {
7280 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7282 XtSetArg(args[0], XtNleftBitmap, None);
7284 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Popup Move Errors"),
7288 void PremoveProc(w, event, prms, nprms)
7296 appData.premove = !appData.premove;
7298 if (appData.premove) {
7299 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7301 XtSetArg(args[0], XtNleftBitmap, None);
7303 XtSetValues(XtNameToWidget(menuBarWidget,
7304 "menuOptions.Premove"), args, 1);
7307 void QuietPlayProc(w, event, prms, nprms)
7315 appData.quietPlay = !appData.quietPlay;
7317 if (appData.quietPlay) {
7318 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7320 XtSetArg(args[0], XtNleftBitmap, None);
7322 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Quiet Play"),
7326 void ShowCoordsProc(w, event, prms, nprms)
7334 appData.showCoords = !appData.showCoords;
7336 if (appData.showCoords) {
7337 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7339 XtSetArg(args[0], XtNleftBitmap, None);
7341 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
7344 DrawPosition(True, NULL);
7347 void ShowThinkingProc(w, event, prms, nprms)
7355 appData.showThinking = !appData.showThinking; // [HGM] thinking: tken out of ShowThinkingEvent
7356 ShowThinkingEvent();
7358 // [HGM] thinking: currently no suc menu item; replaced by Hide Thinking (From Human)
7359 if (appData.showThinking) {
7360 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7362 XtSetArg(args[0], XtNleftBitmap, None);
7364 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Thinking"),
7369 void HideThinkingProc(w, event, prms, nprms)
7377 appData.hideThinkingFromHuman = !appData.hideThinkingFromHuman; // [HGM] thinking: tken out of ShowThinkingEvent
7378 ShowThinkingEvent();
7380 if (appData.hideThinkingFromHuman) {
7381 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7383 XtSetArg(args[0], XtNleftBitmap, None);
7385 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
7389 void InfoProc(w, event, prms, nprms)
7396 snprintf(buf, sizeof(buf), "xterm -e info --directory %s --directory . -f %s &",
7401 void ManProc(w, event, prms, nprms)
7409 if (nprms && *nprms > 0)
7413 snprintf(buf, sizeof(buf), "xterm -e man %s &", name);
7417 void HintProc(w, event, prms, nprms)
7426 void BookProc(w, event, prms, nprms)
7435 void AboutProc(w, event, prms, nprms)
7443 char *zippy = " (with Zippy code)";
7447 snprintf(buf, sizeof(buf), "%s%s\n\n%s\n%s\n%s\n\n%s%s\n%s",
7448 programVersion, zippy,
7449 "Copyright 1991 Digital Equipment Corporation",
7450 "Enhancements Copyright 1992-2009 Free Software Foundation",
7451 "Enhancements Copyright 2005 Alessandro Scotti",
7452 PRODUCT, " is free software and carries NO WARRANTY;",
7453 "see the file COPYING for more information.");
7454 ErrorPopUp(_("About XBoard"), buf, FALSE);
7457 void DebugProc(w, event, prms, nprms)
7463 appData.debugMode = !appData.debugMode;
7466 void AboutGameProc(w, event, prms, nprms)
7475 void NothingProc(w, event, prms, nprms)
7484 void Iconify(w, event, prms, nprms)
7493 XtSetArg(args[0], XtNiconic, True);
7494 XtSetValues(shellWidget, args, 1);
7497 void DisplayMessage(message, extMessage)
7498 char *message, *extMessage;
7505 snprintf(buf, sizeof(buf), "%s %s", message, extMessage);
7508 message = extMessage;
7511 XtSetArg(arg, XtNlabel, message);
7512 XtSetValues(messageWidget, &arg, 1);
7515 void DisplayTitle(text)
7520 char title[MSG_SIZ];
7523 if (text == NULL) text = "";
7525 if (appData.titleInWindow) {
7527 XtSetArg(args[i], XtNlabel, text); i++;
7528 XtSetValues(titleWidget, args, i);
7531 if (*text != NULLCHAR) {
7533 strcpy(title, text);
7534 } else if (appData.icsActive) {
7535 snprintf(icon, sizeof(icon), "%s", appData.icsHost);
7536 snprintf(title, sizeof(title),"%s: %s", programName, appData.icsHost);
7537 } else if (appData.cmailGameName[0] != NULLCHAR) {
7538 snprintf(icon, sizeof(icon), "%s", "CMail");
7539 snprintf(title,sizeof(title), "%s: %s", programName, "CMail");
7541 // [HGM] license: This stuff should really be done in back-end, but WinBoard already had a pop-up for it
7542 } else if (gameInfo.variant == VariantGothic) {
7543 strcpy(icon, programName);
7544 strcpy(title, GOTHIC);
7547 } else if (gameInfo.variant == VariantFalcon) {
7548 strcpy(icon, programName);
7549 strcpy(title, FALCON);
7551 } else if (appData.noChessProgram) {
7552 strcpy(icon, programName);
7553 strcpy(title, programName);
7555 strcpy(icon, first.tidy);
7556 snprintf(title,sizeof(title), "%s: %s", programName, first.tidy);
7559 XtSetArg(args[i], XtNiconName, (XtArgVal) icon); i++;
7560 XtSetArg(args[i], XtNtitle, (XtArgVal) title); i++;
7561 XtSetValues(shellWidget, args, i);
7565 void DisplayError(message, error)
7572 if (appData.debugMode || appData.matchMode) {
7573 fprintf(stderr, "%s: %s\n", programName, message);
7576 if (appData.debugMode || appData.matchMode) {
7577 fprintf(stderr, "%s: %s: %s\n",
7578 programName, message, strerror(error));
7580 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
7583 ErrorPopUp(_("Error"), message, FALSE);
7587 void DisplayMoveError(message)
7592 DrawPosition(FALSE, NULL);
7593 if (appData.debugMode || appData.matchMode) {
7594 fprintf(stderr, "%s: %s\n", programName, message);
7596 if (appData.popupMoveErrors) {
7597 ErrorPopUp(_("Error"), message, FALSE);
7599 DisplayMessage(message, "");
7604 void DisplayFatalError(message, error, status)
7610 errorExitStatus = status;
7612 fprintf(stderr, "%s: %s\n", programName, message);
7614 fprintf(stderr, "%s: %s: %s\n",
7615 programName, message, strerror(error));
7616 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
7619 if (appData.popupExitMessage && boardWidget && XtIsRealized(boardWidget)) {
7620 ErrorPopUp(status ? _("Fatal Error") : _("Exiting"), message, TRUE);
7626 void DisplayInformation(message)
7630 ErrorPopUp(_("Information"), message, TRUE);
7633 void DisplayNote(message)
7637 ErrorPopUp(_("Note"), message, FALSE);
7641 NullXErrorCheck(dpy, error_event)
7643 XErrorEvent *error_event;
7648 void DisplayIcsInteractionTitle(message)
7651 if (oldICSInteractionTitle == NULL) {
7652 /* Magic to find the old window title, adapted from vim */
7653 char *wina = getenv("WINDOWID");
7655 Window win = (Window) atoi(wina);
7656 Window root, parent, *children;
7657 unsigned int nchildren;
7658 int (*oldHandler)() = XSetErrorHandler(NullXErrorCheck);
7660 if (XFetchName(xDisplay, win, &oldICSInteractionTitle)) break;
7661 if (!XQueryTree(xDisplay, win, &root, &parent,
7662 &children, &nchildren)) break;
7663 if (children) XFree((void *)children);
7664 if (parent == root || parent == 0) break;
7667 XSetErrorHandler(oldHandler);
7669 if (oldICSInteractionTitle == NULL) {
7670 oldICSInteractionTitle = "xterm";
7673 printf("\033]0;%s\007", message);
7677 char pendingReplyPrefix[MSG_SIZ];
7678 ProcRef pendingReplyPR;
7680 void AskQuestionProc(w, event, prms, nprms)
7687 fprintf(stderr, _("AskQuestionProc needed 4 parameters, got %d\n"),
7691 AskQuestionEvent(prms[0], prms[1], prms[2], prms[3]);
7694 void AskQuestionPopDown()
7696 if (!askQuestionUp) return;
7697 XtPopdown(askQuestionShell);
7698 XtDestroyWidget(askQuestionShell);
7699 askQuestionUp = False;
7702 void AskQuestionReplyAction(w, event, prms, nprms)
7712 reply = XawDialogGetValueString(w = XtParent(w));
7713 strcpy(buf, pendingReplyPrefix);
7714 if (*buf) strcat(buf, " ");
7717 OutputToProcess(pendingReplyPR, buf, strlen(buf), &err);
7718 AskQuestionPopDown();
7720 if (err) DisplayFatalError(_("Error writing to chess program"), err, 0);
7723 void AskQuestionCallback(w, client_data, call_data)
7725 XtPointer client_data, call_data;
7730 XtSetArg(args[0], XtNlabel, &name);
7731 XtGetValues(w, args, 1);
7733 if (strcmp(name, _("cancel")) == 0) {
7734 AskQuestionPopDown();
7736 AskQuestionReplyAction(w, NULL, NULL, NULL);
7740 void AskQuestion(title, question, replyPrefix, pr)
7741 char *title, *question, *replyPrefix;
7745 Widget popup, layout, dialog, edit;
7751 strcpy(pendingReplyPrefix, replyPrefix);
7752 pendingReplyPR = pr;
7755 XtSetArg(args[i], XtNresizable, True); i++;
7756 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
7757 askQuestionShell = popup =
7758 XtCreatePopupShell(title, transientShellWidgetClass,
7759 shellWidget, args, i);
7762 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
7763 layoutArgs, XtNumber(layoutArgs));
7766 XtSetArg(args[i], XtNlabel, question); i++;
7767 XtSetArg(args[i], XtNvalue, ""); i++;
7768 XtSetArg(args[i], XtNborderWidth, 0); i++;
7769 dialog = XtCreateManagedWidget("question", dialogWidgetClass,
7772 XawDialogAddButton(dialog, _("enter"), AskQuestionCallback,
7773 (XtPointer) dialog);
7774 XawDialogAddButton(dialog, _("cancel"), AskQuestionCallback,
7775 (XtPointer) dialog);
7777 XtRealizeWidget(popup);
7778 CatchDeleteWindow(popup, "AskQuestionPopDown");
7780 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
7781 &x, &y, &win_x, &win_y, &mask);
7783 XtSetArg(args[0], XtNx, x - 10);
7784 XtSetArg(args[1], XtNy, y - 30);
7785 XtSetValues(popup, args, 2);
7787 XtPopup(popup, XtGrabExclusive);
7788 askQuestionUp = True;
7790 edit = XtNameToWidget(dialog, "*value");
7791 XtSetKeyboardFocus(popup, edit);
7799 if (*name == NULLCHAR) {
7801 } else if (strcmp(name, "$") == 0) {
7802 putc(BELLCHAR, stderr);
7805 snprintf(buf, sizeof(buf), "%s '%s' &", appData.soundProgram, name);
7813 PlaySound(appData.soundMove);
7819 PlaySound(appData.soundIcsWin);
7825 PlaySound(appData.soundIcsLoss);
7831 PlaySound(appData.soundIcsDraw);
7835 PlayIcsUnfinishedSound()
7837 PlaySound(appData.soundIcsUnfinished);
7843 PlaySound(appData.soundIcsAlarm);
7849 system("stty echo");
7855 system("stty -echo");
7859 Colorize(cc, continuation)
7864 int count, outCount, error;
7866 if (textColors[(int)cc].bg > 0) {
7867 if (textColors[(int)cc].fg > 0) {
7868 sprintf(buf, "\033[0;%d;%d;%dm", textColors[(int)cc].attr,
7869 textColors[(int)cc].fg, textColors[(int)cc].bg);
7871 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
7872 textColors[(int)cc].bg);
7875 if (textColors[(int)cc].fg > 0) {
7876 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
7877 textColors[(int)cc].fg);
7879 sprintf(buf, "\033[0;%dm", textColors[(int)cc].attr);
7882 count = strlen(buf);
7883 outCount = OutputToProcess(NoProc, buf, count, &error);
7884 if (outCount < count) {
7885 DisplayFatalError(_("Error writing to display"), error, 1);
7888 if (continuation) return;
7891 PlaySound(appData.soundShout);
7894 PlaySound(appData.soundSShout);
7897 PlaySound(appData.soundChannel1);
7900 PlaySound(appData.soundChannel);
7903 PlaySound(appData.soundKibitz);
7906 PlaySound(appData.soundTell);
7908 case ColorChallenge:
7909 PlaySound(appData.soundChallenge);
7912 PlaySound(appData.soundRequest);
7915 PlaySound(appData.soundSeek);
7926 return getpwuid(getuid())->pw_name;
7929 static char *ExpandPathName(path)
7932 static char static_buf[2000];
7933 char *d, *s, buf[2000];
7939 while (*s && isspace(*s))
7948 if (*(s+1) == '/') {
7949 strcpy(d, getpwuid(getuid())->pw_dir);
7954 *strchr(buf, '/') = 0;
7955 pwd = getpwnam(buf);
7958 fprintf(stderr, _("ERROR: Unknown user %s (in path %s)\n"),
7962 strcpy(d, pwd->pw_dir);
7963 strcat(d, strchr(s+1, '/'));
7974 static char host_name[MSG_SIZ];
7976 #if HAVE_GETHOSTNAME
7977 gethostname(host_name, MSG_SIZ);
7979 #else /* not HAVE_GETHOSTNAME */
7980 # if HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H
7981 sysinfo(SI_HOSTNAME, host_name, MSG_SIZ);
7983 # else /* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
7985 # endif/* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
7986 #endif /* not HAVE_GETHOSTNAME */
7989 XtIntervalId delayedEventTimerXID = 0;
7990 DelayedEventCallback delayedEventCallback = 0;
7995 delayedEventTimerXID = 0;
7996 delayedEventCallback();
8000 ScheduleDelayedEvent(cb, millisec)
8001 DelayedEventCallback cb; long millisec;
8003 delayedEventCallback = cb;
8004 delayedEventTimerXID =
8005 XtAppAddTimeOut(appContext, millisec,
8006 (XtTimerCallbackProc) FireDelayedEvent, (XtPointer) 0);
8009 DelayedEventCallback
8012 if (delayedEventTimerXID) {
8013 return delayedEventCallback;
8020 CancelDelayedEvent()
8022 if (delayedEventTimerXID) {
8023 XtRemoveTimeOut(delayedEventTimerXID);
8024 delayedEventTimerXID = 0;
8028 XtIntervalId loadGameTimerXID = 0;
8030 int LoadGameTimerRunning()
8032 return loadGameTimerXID != 0;
8035 int StopLoadGameTimer()
8037 if (loadGameTimerXID != 0) {
8038 XtRemoveTimeOut(loadGameTimerXID);
8039 loadGameTimerXID = 0;
8047 LoadGameTimerCallback(arg, id)
8051 loadGameTimerXID = 0;
8056 StartLoadGameTimer(millisec)
8060 XtAppAddTimeOut(appContext, millisec,
8061 (XtTimerCallbackProc) LoadGameTimerCallback,
8065 XtIntervalId analysisClockXID = 0;
8068 AnalysisClockCallback(arg, id)
8072 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile
8073 || appData.icsEngineAnalyze) { // [DM]
8074 AnalysisPeriodicEvent(0);
8075 StartAnalysisClock();
8080 StartAnalysisClock()
8083 XtAppAddTimeOut(appContext, 2000,
8084 (XtTimerCallbackProc) AnalysisClockCallback,
8088 XtIntervalId clockTimerXID = 0;
8090 int ClockTimerRunning()
8092 return clockTimerXID != 0;
8095 int StopClockTimer()
8097 if (clockTimerXID != 0) {
8098 XtRemoveTimeOut(clockTimerXID);
8107 ClockTimerCallback(arg, id)
8116 StartClockTimer(millisec)
8120 XtAppAddTimeOut(appContext, millisec,
8121 (XtTimerCallbackProc) ClockTimerCallback,
8126 DisplayTimerLabel(w, color, timer, highlight)
8135 Pixel foregroundOrWarningColor = timerForegroundPixel;
8138 && appData.lowTimeWarning
8139 && (timer / 1000) < appData.icsAlarmTime)
8141 foregroundOrWarningColor = lowTimeWarningColor;
8143 if (appData.clockMode) {
8144 sprintf(buf, "%s: %s", color, TimeString(timer));
8145 XtSetArg(args[0], XtNlabel, buf);
8147 sprintf(buf, "%s ", color);
8148 XtSetArg(args[0], XtNlabel, buf);
8153 XtSetArg(args[1], XtNbackground, foregroundOrWarningColor);
8154 XtSetArg(args[2], XtNforeground, timerBackgroundPixel);
8156 XtSetArg(args[1], XtNbackground, timerBackgroundPixel);
8157 XtSetArg(args[2], XtNforeground, foregroundOrWarningColor);
8160 XtSetValues(w, args, 3);
8164 DisplayWhiteClock(timeRemaining, highlight)
8170 if(appData.noGUI) return;
8171 DisplayTimerLabel(whiteTimerWidget, _("White"), timeRemaining, highlight);
8172 if (highlight && iconPixmap == bIconPixmap) {
8173 iconPixmap = wIconPixmap;
8174 XtSetArg(args[0], XtNiconPixmap, iconPixmap);
8175 XtSetValues(shellWidget, args, 1);
8180 DisplayBlackClock(timeRemaining, highlight)
8186 if(appData.noGUI) return;
8187 DisplayTimerLabel(blackTimerWidget, _("Black"), timeRemaining, highlight);
8188 if (highlight && iconPixmap == wIconPixmap) {
8189 iconPixmap = bIconPixmap;
8190 XtSetArg(args[0], XtNiconPixmap, iconPixmap);
8191 XtSetValues(shellWidget, args, 1);
8209 int StartChildProcess(cmdLine, dir, pr)
8216 int to_prog[2], from_prog[2];
8220 if (appData.debugMode) {
8221 fprintf(stderr, "StartChildProcess (dir=\"%s\") %s\n",dir, cmdLine);
8224 /* We do NOT feed the cmdLine to the shell; we just
8225 parse it into blank-separated arguments in the
8226 most simple-minded way possible.
8229 strcpy(buf, cmdLine);
8234 if (p == NULL) break;
8239 SetUpChildIO(to_prog, from_prog);
8241 if ((pid = fork()) == 0) {
8243 // [HGM] PSWBTM: made order resistant against case where fd of created pipe was 0 or 1
8244 close(to_prog[1]); // first close the unused pipe ends
8245 close(from_prog[0]);
8246 dup2(to_prog[0], 0); // to_prog was created first, nd is the only one to use 0 or 1
8247 dup2(from_prog[1], 1);
8248 if(to_prog[0] >= 2) close(to_prog[0]); // if 0 or 1, the dup2 already cosed the original
8249 close(from_prog[1]); // and closing again loses one of the pipes!
8250 if(fileno(stderr) >= 2) // better safe than sorry...
8251 dup2(1, fileno(stderr)); /* force stderr to the pipe */
8253 if (dir[0] != NULLCHAR && chdir(dir) != 0) {
8258 nice(appData.niceEngines); // [HGM] nice: adjust priority of engine proc
8260 execvp(argv[0], argv);
8262 /* If we get here, exec failed */
8267 /* Parent process */
8269 close(from_prog[1]);
8271 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8274 cp->fdFrom = from_prog[0];
8275 cp->fdTo = to_prog[1];
8280 // [HGM] kill: implement the 'hard killing' of AS's Winboard_x
8281 static RETSIGTYPE AlarmCallBack(int n)
8287 DestroyChildProcess(pr, signalType)
8291 ChildProc *cp = (ChildProc *) pr;
8293 if (cp->kind != CPReal) return;
8295 if (signalType == 10) { // [HGM] kill: if it does not terminate in 3 sec, kill
8296 signal(SIGALRM, AlarmCallBack);
8298 if(wait((int *) 0) == -1) { // process does not terminate on its own accord
8299 kill(cp->pid, SIGKILL); // kill it forcefully
8300 wait((int *) 0); // and wait again
8304 kill(cp->pid, signalType == 9 ? SIGKILL : SIGTERM); // [HGM] kill: use hard kill if so requested
8306 /* Process is exiting either because of the kill or because of
8307 a quit command sent by the backend; either way, wait for it to die.
8316 InterruptChildProcess(pr)
8319 ChildProc *cp = (ChildProc *) pr;
8321 if (cp->kind != CPReal) return;
8322 (void) kill(cp->pid, SIGINT); /* stop it thinking */
8325 int OpenTelnet(host, port, pr)
8330 char cmdLine[MSG_SIZ];
8332 if (port[0] == NULLCHAR) {
8333 snprintf(cmdLine, sizeof(cmdLine), "%s %s", appData.telnetProgram, host);
8335 snprintf(cmdLine,sizeof(cmdLine), "%s %s %s", appData.telnetProgram, host, port);
8337 return StartChildProcess(cmdLine, "", pr);
8340 int OpenTCP(host, port, pr)
8346 DisplayFatalError(_("Socket support is not configured in"), 0, 2);
8347 #else /* !OMIT_SOCKETS */
8349 struct sockaddr_in sa;
8351 unsigned short uport;
8354 if ((s = socket(AF_INET, SOCK_STREAM, 6)) < 0) {
8358 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
8359 sa.sin_family = AF_INET;
8360 sa.sin_addr.s_addr = INADDR_ANY;
8361 uport = (unsigned short) 0;
8362 sa.sin_port = htons(uport);
8363 if (bind(s, (struct sockaddr *) &sa, sizeof(struct sockaddr_in)) < 0) {
8367 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
8368 if (!(hp = gethostbyname(host))) {
8370 if (sscanf(host, "%d.%d.%d.%d", &b0, &b1, &b2, &b3) == 4) {
8371 hp = (struct hostent *) calloc(1, sizeof(struct hostent));
8372 hp->h_addrtype = AF_INET;
8374 hp->h_addr_list = (char **) calloc(2, sizeof(char *));
8375 hp->h_addr_list[0] = (char *) malloc(4);
8376 hp->h_addr_list[0][0] = b0;
8377 hp->h_addr_list[0][1] = b1;
8378 hp->h_addr_list[0][2] = b2;
8379 hp->h_addr_list[0][3] = b3;
8384 sa.sin_family = hp->h_addrtype;
8385 uport = (unsigned short) atoi(port);
8386 sa.sin_port = htons(uport);
8387 memcpy((char *) &sa.sin_addr, hp->h_addr, hp->h_length);
8389 if (connect(s, (struct sockaddr *) &sa,
8390 sizeof(struct sockaddr_in)) < 0) {
8394 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8401 #endif /* !OMIT_SOCKETS */
8406 int OpenCommPort(name, pr)
8413 fd = open(name, 2, 0);
8414 if (fd < 0) return errno;
8416 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8426 int OpenLoopback(pr)
8432 SetUpChildIO(to, from);
8434 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8437 cp->fdFrom = to[0]; /* note not from[0]; we are doing a loopback */
8444 int OpenRcmd(host, user, cmd, pr)
8445 char *host, *user, *cmd;
8448 DisplayFatalError(_("internal rcmd not implemented for Unix"), 0, 1);
8452 #define INPUT_SOURCE_BUF_SIZE 8192
8461 char buf[INPUT_SOURCE_BUF_SIZE];
8466 DoInputCallback(closure, source, xid)
8471 InputSource *is = (InputSource *) closure;
8476 if (is->lineByLine) {
8477 count = read(is->fd, is->unused,
8478 INPUT_SOURCE_BUF_SIZE - (is->unused - is->buf));
8480 (is->func)(is, is->closure, is->buf, count, count ? errno : 0);
8483 is->unused += count;
8485 while (p < is->unused) {
8486 q = memchr(p, '\n', is->unused - p);
8487 if (q == NULL) break;
8489 (is->func)(is, is->closure, p, q - p, 0);
8493 while (p < is->unused) {
8498 count = read(is->fd, is->buf, INPUT_SOURCE_BUF_SIZE);
8503 (is->func)(is, is->closure, is->buf, count, error);
8507 InputSourceRef AddInputSource(pr, lineByLine, func, closure)
8514 ChildProc *cp = (ChildProc *) pr;
8516 is = (InputSource *) calloc(1, sizeof(InputSource));
8517 is->lineByLine = lineByLine;
8521 is->fd = fileno(stdin);
8523 is->kind = cp->kind;
8524 is->fd = cp->fdFrom;
8527 is->unused = is->buf;
8530 is->xid = XtAppAddInput(appContext, is->fd,
8531 (XtPointer) (XtInputReadMask),
8532 (XtInputCallbackProc) DoInputCallback,
8534 is->closure = closure;
8535 return (InputSourceRef) is;
8539 RemoveInputSource(isr)
8542 InputSource *is = (InputSource *) isr;
8544 if (is->xid == 0) return;
8545 XtRemoveInput(is->xid);
8549 int OutputToProcess(pr, message, count, outError)
8555 ChildProc *cp = (ChildProc *) pr;
8559 outCount = fwrite(message, 1, count, stdout);
8561 outCount = write(cp->fdTo, message, count);
8571 /* Output message to process, with "ms" milliseconds of delay
8572 between each character. This is needed when sending the logon
8573 script to ICC, which for some reason doesn't like the
8574 instantaneous send. */
8575 int OutputToProcessDelayed(pr, message, count, outError, msdelay)
8582 ChildProc *cp = (ChildProc *) pr;
8587 r = write(cp->fdTo, message++, 1);
8600 /**** Animation code by Hugh Fisher, DCS, ANU.
8602 Known problem: if a window overlapping the board is
8603 moved away while a piece is being animated underneath,
8604 the newly exposed area won't be updated properly.
8605 I can live with this.
8607 Known problem: if you look carefully at the animation
8608 of pieces in mono mode, they are being drawn as solid
8609 shapes without interior detail while moving. Fixing
8610 this would be a major complication for minimal return.
8613 /* Masks for XPM pieces. Black and white pieces can have
8614 different shapes, but in the interest of retaining my
8615 sanity pieces must have the same outline on both light
8616 and dark squares, and all pieces must use the same
8617 background square colors/images. */
8620 CreateAnimMasks (pieceDepth)
8627 unsigned long plane;
8630 /* Need a bitmap just to get a GC with right depth */
8631 buf = XCreatePixmap(xDisplay, xBoardWindow,
8633 values.foreground = 1;
8634 values.background = 0;
8635 /* Don't use XtGetGC, not read only */
8636 maskGC = XCreateGC(xDisplay, buf,
8637 GCForeground | GCBackground, &values);
8638 XFreePixmap(xDisplay, buf);
8640 buf = XCreatePixmap(xDisplay, xBoardWindow,
8641 squareSize, squareSize, pieceDepth);
8642 values.foreground = XBlackPixel(xDisplay, xScreen);
8643 values.background = XWhitePixel(xDisplay, xScreen);
8644 bufGC = XCreateGC(xDisplay, buf,
8645 GCForeground | GCBackground, &values);
8647 for (piece = WhitePawn; piece <= BlackKing; piece++) {
8648 /* Begin with empty mask */
8649 xpmMask[piece] = XCreatePixmap(xDisplay, xBoardWindow,
8650 squareSize, squareSize, 1);
8651 XSetFunction(xDisplay, maskGC, GXclear);
8652 XFillRectangle(xDisplay, xpmMask[piece], maskGC,
8653 0, 0, squareSize, squareSize);
8655 /* Take a copy of the piece */
8660 XSetFunction(xDisplay, bufGC, GXcopy);
8661 XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % (int)BlackPawn],
8663 0, 0, squareSize, squareSize, 0, 0);
8665 /* XOR the background (light) over the piece */
8666 XSetFunction(xDisplay, bufGC, GXxor);
8668 XCopyArea(xDisplay, xpmLightSquare, buf, bufGC,
8669 0, 0, squareSize, squareSize, 0, 0);
8671 XSetForeground(xDisplay, bufGC, lightSquareColor);
8672 XFillRectangle(xDisplay, buf, bufGC, 0, 0, squareSize, squareSize);
8675 /* We now have an inverted piece image with the background
8676 erased. Construct mask by just selecting all the non-zero
8677 pixels - no need to reconstruct the original image. */
8678 XSetFunction(xDisplay, maskGC, GXor);
8680 /* Might be quicker to download an XImage and create bitmap
8681 data from it rather than this N copies per piece, but it
8682 only takes a fraction of a second and there is a much
8683 longer delay for loading the pieces. */
8684 for (n = 0; n < pieceDepth; n ++) {
8685 XCopyPlane(xDisplay, buf, xpmMask[piece], maskGC,
8686 0, 0, squareSize, squareSize,
8692 XFreePixmap(xDisplay, buf);
8693 XFreeGC(xDisplay, bufGC);
8694 XFreeGC(xDisplay, maskGC);
8698 InitAnimState (anim, info)
8700 XWindowAttributes * info;
8705 /* Each buffer is square size, same depth as window */
8706 anim->saveBuf = XCreatePixmap(xDisplay, xBoardWindow,
8707 squareSize, squareSize, info->depth);
8708 anim->newBuf = XCreatePixmap(xDisplay, xBoardWindow,
8709 squareSize, squareSize, info->depth);
8711 /* Create a plain GC for blitting */
8712 mask = GCForeground | GCBackground | GCFunction |
8713 GCPlaneMask | GCGraphicsExposures;
8714 values.foreground = XBlackPixel(xDisplay, xScreen);
8715 values.background = XWhitePixel(xDisplay, xScreen);
8716 values.function = GXcopy;
8717 values.plane_mask = AllPlanes;
8718 values.graphics_exposures = False;
8719 anim->blitGC = XCreateGC(xDisplay, xBoardWindow, mask, &values);
8721 /* Piece will be copied from an existing context at
8722 the start of each new animation/drag. */
8723 anim->pieceGC = XCreateGC(xDisplay, xBoardWindow, 0, &values);
8725 /* Outline will be a read-only copy of an existing */
8726 anim->outlineGC = None;
8732 static int done = 0;
8733 XWindowAttributes info;
8737 XGetWindowAttributes(xDisplay, xBoardWindow, &info);
8739 InitAnimState(&game, &info);
8740 InitAnimState(&player, &info);
8742 /* For XPM pieces, we need bitmaps to use as masks. */
8744 CreateAnimMasks(info.depth);
8749 static Boolean frameWaiting;
8751 static RETSIGTYPE FrameAlarm (sig)
8754 frameWaiting = False;
8755 /* In case System-V style signals. Needed?? */
8756 signal(SIGALRM, FrameAlarm);
8763 struct itimerval delay;
8765 XSync(xDisplay, False);
8768 frameWaiting = True;
8769 signal(SIGALRM, FrameAlarm);
8770 delay.it_interval.tv_sec =
8771 delay.it_value.tv_sec = time / 1000;
8772 delay.it_interval.tv_usec =
8773 delay.it_value.tv_usec = (time % 1000) * 1000;
8774 setitimer(ITIMER_REAL, &delay, NULL);
8776 /* Ugh -- busy-wait! --tpm */
8777 while (frameWaiting);
8779 while (frameWaiting) pause();
8781 delay.it_interval.tv_sec = delay.it_value.tv_sec = 0;
8782 delay.it_interval.tv_usec = delay.it_value.tv_usec = 0;
8783 setitimer(ITIMER_REAL, &delay, NULL);
8793 XSync(xDisplay, False);
8795 usleep(time * 1000);
8800 /* Convert board position to corner of screen rect and color */
8803 ScreenSquare(column, row, pt, color)
8804 int column; int row; XPoint * pt; int * color;
8807 pt->x = lineGap + ((BOARD_WIDTH-1)-column) * (squareSize + lineGap);
8808 pt->y = lineGap + row * (squareSize + lineGap);
8810 pt->x = lineGap + column * (squareSize + lineGap);
8811 pt->y = lineGap + ((BOARD_HEIGHT-1)-row) * (squareSize + lineGap);
8813 *color = SquareColor(row, column);
8816 /* Convert window coords to square */
8819 BoardSquare(x, y, column, row)
8820 int x; int y; int * column; int * row;
8822 *column = EventToSquare(x, BOARD_WIDTH);
8823 if (flipView && *column >= 0)
8824 *column = BOARD_WIDTH - 1 - *column;
8825 *row = EventToSquare(y, BOARD_HEIGHT);
8826 if (!flipView && *row >= 0)
8827 *row = BOARD_HEIGHT - 1 - *row;
8832 #undef Max /* just in case */
8834 #define Max(a, b) ((a) > (b) ? (a) : (b))
8835 #define Min(a, b) ((a) < (b) ? (a) : (b))
8838 SetRect(rect, x, y, width, height)
8839 XRectangle * rect; int x; int y; int width; int height;
8843 rect->width = width;
8844 rect->height = height;
8847 /* Test if two frames overlap. If they do, return
8848 intersection rect within old and location of
8849 that rect within new. */
8852 Intersect(old, new, size, area, pt)
8853 XPoint * old; XPoint * new;
8854 int size; XRectangle * area; XPoint * pt;
8856 if (old->x > new->x + size || new->x > old->x + size ||
8857 old->y > new->y + size || new->y > old->y + size) {
8860 SetRect(area, Max(new->x - old->x, 0), Max(new->y - old->y, 0),
8861 size - abs(old->x - new->x), size - abs(old->y - new->y));
8862 pt->x = Max(old->x - new->x, 0);
8863 pt->y = Max(old->y - new->y, 0);
8868 /* For two overlapping frames, return the rect(s)
8869 in the old that do not intersect with the new. */
8872 CalcUpdateRects(old, new, size, update, nUpdates)
8873 XPoint * old; XPoint * new; int size;
8874 XRectangle update[]; int * nUpdates;
8878 /* If old = new (shouldn't happen) then nothing to draw */
8879 if (old->x == new->x && old->y == new->y) {
8883 /* Work out what bits overlap. Since we know the rects
8884 are the same size we don't need a full intersect calc. */
8886 /* Top or bottom edge? */
8887 if (new->y > old->y) {
8888 SetRect(&(update[count]), old->x, old->y, size, new->y - old->y);
8890 } else if (old->y > new->y) {
8891 SetRect(&(update[count]), old->x, old->y + size - (old->y - new->y),
8892 size, old->y - new->y);
8895 /* Left or right edge - don't overlap any update calculated above. */
8896 if (new->x > old->x) {
8897 SetRect(&(update[count]), old->x, Max(new->y, old->y),
8898 new->x - old->x, size - abs(new->y - old->y));
8900 } else if (old->x > new->x) {
8901 SetRect(&(update[count]), new->x + size, Max(new->y, old->y),
8902 old->x - new->x, size - abs(new->y - old->y));
8909 /* Generate a series of frame coords from start->mid->finish.
8910 The movement rate doubles until the half way point is
8911 reached, then halves back down to the final destination,
8912 which gives a nice slow in/out effect. The algorithmn
8913 may seem to generate too many intermediates for short
8914 moves, but remember that the purpose is to attract the
8915 viewers attention to the piece about to be moved and
8916 then to where it ends up. Too few frames would be less
8920 Tween(start, mid, finish, factor, frames, nFrames)
8921 XPoint * start; XPoint * mid;
8922 XPoint * finish; int factor;
8923 XPoint frames[]; int * nFrames;
8925 int fraction, n, count;
8929 /* Slow in, stepping 1/16th, then 1/8th, ... */
8931 for (n = 0; n < factor; n++)
8933 for (n = 0; n < factor; n++) {
8934 frames[count].x = start->x + (mid->x - start->x) / fraction;
8935 frames[count].y = start->y + (mid->y - start->y) / fraction;
8937 fraction = fraction / 2;
8941 frames[count] = *mid;
8944 /* Slow out, stepping 1/2, then 1/4, ... */
8946 for (n = 0; n < factor; n++) {
8947 frames[count].x = finish->x - (finish->x - mid->x) / fraction;
8948 frames[count].y = finish->y - (finish->y - mid->y) / fraction;
8950 fraction = fraction * 2;
8955 /* Draw a piece on the screen without disturbing what's there */
8958 SelectGCMask(piece, clip, outline, mask)
8959 ChessSquare piece; GC * clip; GC * outline; Pixmap * mask;
8963 /* Bitmap for piece being moved. */
8964 if (appData.monoMode) {
8965 *mask = *pieceToSolid(piece);
8966 } else if (useImages) {
8968 *mask = xpmMask[piece];
8970 *mask = ximMaskPm[piece%(int)BlackPawn];
8973 *mask = *pieceToSolid(piece);
8976 /* GC for piece being moved. Square color doesn't matter, but
8977 since it gets modified we make a copy of the original. */
8979 if (appData.monoMode)
8984 if (appData.monoMode)
8989 XCopyGC(xDisplay, source, 0xFFFFFFFF, *clip);
8991 /* Outline only used in mono mode and is not modified */
8993 *outline = bwPieceGC;
8995 *outline = wbPieceGC;
8999 OverlayPiece(piece, clip, outline, dest)
9000 ChessSquare piece; GC clip; GC outline; Drawable dest;
9005 /* Draw solid rectangle which will be clipped to shape of piece */
9006 XFillRectangle(xDisplay, dest, clip,
9007 0, 0, squareSize, squareSize);
9008 if (appData.monoMode)
9009 /* Also draw outline in contrasting color for black
9010 on black / white on white cases */
9011 XCopyPlane(xDisplay, *pieceToOutline(piece), dest, outline,
9012 0, 0, squareSize, squareSize, 0, 0, 1);
9014 /* Copy the piece */
9019 XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % (int)BlackPawn],
9021 0, 0, squareSize, squareSize,
9026 /* Animate the movement of a single piece */
9029 BeginAnimation(anim, piece, startColor, start)
9037 /* The old buffer is initialised with the start square (empty) */
9038 BlankSquare(0, 0, startColor, EmptySquare, anim->saveBuf);
9039 anim->prevFrame = *start;
9041 /* The piece will be drawn using its own bitmap as a matte */
9042 SelectGCMask(piece, &anim->pieceGC, &anim->outlineGC, &mask);
9043 XSetClipMask(xDisplay, anim->pieceGC, mask);
9047 AnimationFrame(anim, frame, piece)
9052 XRectangle updates[4];
9057 /* Save what we are about to draw into the new buffer */
9058 XCopyArea(xDisplay, xBoardWindow, anim->newBuf, anim->blitGC,
9059 frame->x, frame->y, squareSize, squareSize,
9062 /* Erase bits of the previous frame */
9063 if (Intersect(&anim->prevFrame, frame, squareSize, &overlap, &pt)) {
9064 /* Where the new frame overlapped the previous,
9065 the contents in newBuf are wrong. */
9066 XCopyArea(xDisplay, anim->saveBuf, anim->newBuf, anim->blitGC,
9067 overlap.x, overlap.y,
9068 overlap.width, overlap.height,
9070 /* Repaint the areas in the old that don't overlap new */
9071 CalcUpdateRects(&anim->prevFrame, frame, squareSize, updates, &count);
9072 for (i = 0; i < count; i++)
9073 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9074 updates[i].x - anim->prevFrame.x,
9075 updates[i].y - anim->prevFrame.y,
9076 updates[i].width, updates[i].height,
9077 updates[i].x, updates[i].y);
9079 /* Easy when no overlap */
9080 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9081 0, 0, squareSize, squareSize,
9082 anim->prevFrame.x, anim->prevFrame.y);
9085 /* Save this frame for next time round */
9086 XCopyArea(xDisplay, anim->newBuf, anim->saveBuf, anim->blitGC,
9087 0, 0, squareSize, squareSize,
9089 anim->prevFrame = *frame;
9091 /* Draw piece over original screen contents, not current,
9092 and copy entire rect. Wipes out overlapping piece images. */
9093 OverlayPiece(piece, anim->pieceGC, anim->outlineGC, anim->newBuf);
9094 XCopyArea(xDisplay, anim->newBuf, xBoardWindow, anim->blitGC,
9095 0, 0, squareSize, squareSize,
9096 frame->x, frame->y);
9100 EndAnimation (anim, finish)
9104 XRectangle updates[4];
9109 /* The main code will redraw the final square, so we
9110 only need to erase the bits that don't overlap. */
9111 if (Intersect(&anim->prevFrame, finish, squareSize, &overlap, &pt)) {
9112 CalcUpdateRects(&anim->prevFrame, finish, squareSize, updates, &count);
9113 for (i = 0; i < count; i++)
9114 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9115 updates[i].x - anim->prevFrame.x,
9116 updates[i].y - anim->prevFrame.y,
9117 updates[i].width, updates[i].height,
9118 updates[i].x, updates[i].y);
9120 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9121 0, 0, squareSize, squareSize,
9122 anim->prevFrame.x, anim->prevFrame.y);
9127 FrameSequence(anim, piece, startColor, start, finish, frames, nFrames)
9129 ChessSquare piece; int startColor;
9130 XPoint * start; XPoint * finish;
9131 XPoint frames[]; int nFrames;
9135 BeginAnimation(anim, piece, startColor, start);
9136 for (n = 0; n < nFrames; n++) {
9137 AnimationFrame(anim, &(frames[n]), piece);
9138 FrameDelay(appData.animSpeed);
9140 EndAnimation(anim, finish);
9143 /* Main control logic for deciding what to animate and how */
9146 AnimateMove(board, fromX, fromY, toX, toY)
9155 XPoint start, finish, mid;
9156 XPoint frames[kFactor * 2 + 1];
9157 int nFrames, startColor, endColor;
9159 /* Are we animating? */
9160 if (!appData.animate || appData.blindfold)
9163 if (fromY < 0 || fromX < 0 || toX < 0 || toY < 0) return;
9164 piece = board[fromY][fromX];
9165 if (piece >= EmptySquare) return;
9170 hop = (piece == WhiteKnight || piece == BlackKnight);
9173 if (appData.debugMode) {
9174 fprintf(debugFP, hop ? _("AnimateMove: piece %d hops from %d,%d to %d,%d \n") :
9175 _("AnimateMove: piece %d slides from %d,%d to %d,%d \n"),
9176 piece, fromX, fromY, toX, toY); }
9178 ScreenSquare(fromX, fromY, &start, &startColor);
9179 ScreenSquare(toX, toY, &finish, &endColor);
9182 /* Knight: make diagonal movement then straight */
9183 if (abs(toY - fromY) < abs(toX - fromX)) {
9184 mid.x = start.x + (finish.x - start.x) / 2;
9188 mid.y = start.y + (finish.y - start.y) / 2;
9191 mid.x = start.x + (finish.x - start.x) / 2;
9192 mid.y = start.y + (finish.y - start.y) / 2;
9195 /* Don't use as many frames for very short moves */
9196 if (abs(toY - fromY) + abs(toX - fromX) <= 2)
9197 Tween(&start, &mid, &finish, kFactor - 1, frames, &nFrames);
9199 Tween(&start, &mid, &finish, kFactor, frames, &nFrames);
9200 FrameSequence(&game, piece, startColor, &start, &finish, frames, nFrames);
9202 /* Be sure end square is redrawn */
9203 damage[toY][toX] = True;
9207 DragPieceBegin(x, y)
9210 int boardX, boardY, color;
9213 /* Are we animating? */
9214 if (!appData.animateDragging || appData.blindfold)
9217 /* Figure out which square we start in and the
9218 mouse position relative to top left corner. */
9219 BoardSquare(x, y, &boardX, &boardY);
9220 player.startBoardX = boardX;
9221 player.startBoardY = boardY;
9222 ScreenSquare(boardX, boardY, &corner, &color);
9223 player.startSquare = corner;
9224 player.startColor = color;
9226 /* Start from exactly where the piece is. This can be confusing
9227 if you start dragging far from the center of the square; most
9228 or all of the piece can be over a different square from the one
9229 the mouse pointer is in. */
9230 player.mouseDelta.x = x - corner.x;
9231 player.mouseDelta.y = y - corner.y;
9233 /* As soon as we start dragging, the piece will jump slightly to
9234 be centered over the mouse pointer. */
9235 player.mouseDelta.x = squareSize/2;
9236 player.mouseDelta.y = squareSize/2;
9238 /* Initialise animation */
9239 player.dragPiece = PieceForSquare(boardX, boardY);
9241 if (player.dragPiece >= 0 && player.dragPiece < EmptySquare) {
9242 player.dragActive = True;
9243 BeginAnimation(&player, player.dragPiece, color, &corner);
9244 /* Mark this square as needing to be redrawn. Note that
9245 we don't remove the piece though, since logically (ie
9246 as seen by opponent) the move hasn't been made yet. */
9247 if(boardX == BOARD_RGHT+1 && PieceForSquare(boardX-1, boardY) > 1 ||
9248 boardX == BOARD_LEFT-2 && PieceForSquare(boardX+1, boardY) > 1)
9249 XCopyArea(xDisplay, xBoardWindow, player.saveBuf, player.blitGC,
9250 corner.x, corner.y, squareSize, squareSize,
9251 0, 0); // [HGM] zh: unstack in stead of grab
9252 damage[boardY][boardX] = True;
9254 player.dragActive = False;
9264 /* Are we animating? */
9265 if (!appData.animateDragging || appData.blindfold)
9269 if (! player.dragActive)
9271 /* Move piece, maintaining same relative position
9272 of mouse within square */
9273 corner.x = x - player.mouseDelta.x;
9274 corner.y = y - player.mouseDelta.y;
9275 AnimationFrame(&player, &corner, player.dragPiece);
9277 if (appData.highlightDragging) {
9279 BoardSquare(x, y, &boardX, &boardY);
9280 SetHighlights(fromX, fromY, boardX, boardY);
9289 int boardX, boardY, color;
9292 /* Are we animating? */
9293 if (!appData.animateDragging || appData.blindfold)
9297 if (! player.dragActive)
9299 /* Last frame in sequence is square piece is
9300 placed on, which may not match mouse exactly. */
9301 BoardSquare(x, y, &boardX, &boardY);
9302 ScreenSquare(boardX, boardY, &corner, &color);
9303 EndAnimation(&player, &corner);
9305 /* Be sure end square is redrawn */
9306 damage[boardY][boardX] = True;
9308 /* This prevents weird things happening with fast successive
9309 clicks which on my Sun at least can cause motion events
9310 without corresponding press/release. */
9311 player.dragActive = False;
9314 /* Handle expose event while piece being dragged */
9319 if (!player.dragActive || appData.blindfold)
9322 /* What we're doing: logically, the move hasn't been made yet,
9323 so the piece is still in it's original square. But visually
9324 it's being dragged around the board. So we erase the square
9325 that the piece is on and draw it at the last known drag point. */
9326 BlankSquare(player.startSquare.x, player.startSquare.y,
9327 player.startColor, EmptySquare, xBoardWindow);
9328 AnimationFrame(&player, &player.prevFrame, player.dragPiece);
9329 damage[player.startBoardY][player.startBoardX] = TRUE;
9333 SetProgramStats( FrontEndProgramStats * stats )
9336 // [HGM] done, but perhaps backend should call this directly?
9337 EngineOutputUpdate( stats );