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 */
3790 void CreateXPMPieces()
3794 u_int ss = squareSize;
3796 static char *xpmkind[] = { "ll", "ld", "dl", "dd" };
3797 XpmColorSymbol symbols[4];
3800 /* Apparently some versions of Xpm don't define XpmFormat at all --tpm */
3801 if (appData.debugMode) {
3802 fprintf(stderr, "XPM Library Version: %d.%d%c\n",
3803 XpmFormat, XpmVersion, (char)('a' + XpmRevision - 1));
3807 /* The XSynchronize calls were copied from CreatePieces.
3808 Not sure if needed, but can't hurt */
3809 XSynchronize(xDisplay, True); /* Work-around for xlib/xt buffering bug */
3811 /* Setup translations so piece colors match square colors */
3812 symbols[0].name = "light_piece";
3813 symbols[0].value = appData.whitePieceColor;
3814 symbols[1].name = "dark_piece";
3815 symbols[1].value = appData.blackPieceColor;
3816 symbols[2].name = "light_square";
3817 symbols[2].value = appData.lightSquareColor;
3818 symbols[3].name = "dark_square";
3819 symbols[3].value = appData.darkSquareColor;
3821 attr.valuemask = XpmColorSymbols;
3822 attr.colorsymbols = symbols;
3823 attr.numsymbols = 4;
3825 if (appData.monoMode) {
3826 DisplayFatalError(_("XPM pieces cannot be used in monochrome mode"),
3830 if (strlen(appData.pixmapDirectory) == 0) {
3831 XpmPieces* pieces = builtInXpms;
3834 while (pieces->size != squareSize && pieces->size) pieces++;
3835 if (!pieces->size) {
3836 fprintf(stderr, _("No builtin XPM pieces of size %d\n"), squareSize);
3839 for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
3840 for (kind=0; kind<4; kind++) {
3842 if ((r=XpmCreatePixmapFromData(xDisplay, xBoardWindow,
3843 pieces->xpm[piece][kind],
3844 &(xpmPieceBitmap[kind][piece]),
3845 NULL, &attr)) != 0) {
3846 fprintf(stderr, _("Error %d loading XPM image \"%s\"\n"),
3853 xpmJailSquare = xpmLightSquare;
3857 fprintf(stderr, _("\nLoading XPMs...\n"));
3860 for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
3861 fprintf(stderr, "%d ", piece+1);
3862 for (kind=0; kind<4; kind++) {
3863 snprintf(buf, sizeof(buf), "%s/%c%s%u.xpm",
3864 ExpandPathName(appData.pixmapDirectory),
3865 ToLower(PieceToChar((ChessSquare)piece)),
3867 if (appData.debugMode) {
3868 fprintf(stderr, _("(File:%s:) "), buf);
3870 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3871 &(xpmPieceBitmap[kind][piece]),
3872 NULL, &attr)) != 0) {
3873 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"),
3879 /* Load light and dark squares */
3880 /* If the LSQ and DSQ pieces don't exist, we will
3881 draw them with solid squares. */
3882 fprintf(stderr, _("light square "));
3883 snprintf(buf, sizeof(buf), "%s/lsq%u.xpm", ExpandPathName(appData.pixmapDirectory), ss);
3884 if (access(buf, 0) != 0) {
3888 if (appData.debugMode)
3889 fprintf(stderr, _("(File:%s:) "), buf);
3891 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3892 &xpmLightSquare, NULL, &attr)) != 0) {
3893 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
3896 fprintf(stderr, _("dark square "));
3897 snprintf(buf, sizeof(buf), "%s/dsq%u.xpm",
3898 ExpandPathName(appData.pixmapDirectory), ss);
3899 if (appData.debugMode) {
3900 fprintf(stderr, _("(File:%s:) "), buf);
3902 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3903 &xpmDarkSquare, NULL, &attr)) != 0) {
3904 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
3908 xpmJailSquare = xpmLightSquare;
3909 fprintf(stderr, _("Done.\n"));
3911 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3914 #endif /* HAVE_LIBXPM */
3917 /* No built-in bitmaps */
3922 u_int ss = squareSize;
3924 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3927 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
3928 for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
3929 sprintf(buf, "%c%u%c.bm", ToLower(PieceToChar((ChessSquare)piece)),
3930 ss, kind == SOLID ? 's' : 'o');
3931 ReadBitmap(&pieceBitmap[kind][piece], buf, NULL, ss, ss);
3935 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3939 /* With built-in bitmaps */
3942 BuiltInBits* bib = builtInBits;
3945 u_int ss = squareSize;
3947 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3950 while (bib->squareSize != ss && bib->squareSize != 0) bib++;
3952 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
3953 for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
3954 sprintf(buf, "%c%u%c.bm", ToLower(PieceToChar((ChessSquare)piece)),
3955 ss, kind == SOLID ? 's' : 'o');
3956 ReadBitmap(&pieceBitmap[kind][piece], buf,
3957 bib->bits[kind][piece], ss, ss);
3961 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3966 void ReadBitmap(pm, name, bits, wreq, hreq)
3969 unsigned char bits[];
3975 char msg[MSG_SIZ], fullname[MSG_SIZ];
3977 if (*appData.bitmapDirectory != NULLCHAR) {
3978 strcpy(fullname, appData.bitmapDirectory);
3979 strcat(fullname, "/");
3980 strcat(fullname, name);
3981 errcode = XReadBitmapFile(xDisplay, xBoardWindow, fullname,
3982 &w, &h, pm, &x_hot, &y_hot);
3983 if (errcode != BitmapSuccess) {
3985 case BitmapOpenFailed:
3986 snprintf(msg, sizeof(msg), _("Can't open bitmap file %s"), fullname);
3988 case BitmapFileInvalid:
3989 snprintf(msg, sizeof(msg), _("Invalid bitmap in file %s"), fullname);
3991 case BitmapNoMemory:
3992 snprintf(msg, sizeof(msg), _("Ran out of memory reading bitmap file %s"),
3996 snprintf(msg, sizeof(msg), _("Unknown XReadBitmapFile error %d on file %s"),
4000 fprintf(stderr, _("%s: %s...using built-in\n"),
4002 } else if (w != wreq || h != hreq) {
4004 _("%s: Bitmap %s is %dx%d, not %dx%d...using built-in\n"),
4005 programName, fullname, w, h, wreq, hreq);
4012 fprintf(stderr, _("%s: No built-in bitmap for %s; giving up\n"),
4016 ; // [HGM] bitmaps: make it non-fatal if we have no bitmap;
4018 *pm = XCreateBitmapFromData(xDisplay, xBoardWindow, (char *) bits,
4027 if (lineGap == 0) return;
4029 /* [HR] Split this into 2 loops for non-square boards. */
4031 for (i = 0; i < BOARD_HEIGHT + 1; i++) {
4032 gridSegments[i].x1 = 0;
4033 gridSegments[i].x2 =
4034 lineGap + BOARD_WIDTH * (squareSize + lineGap);
4035 gridSegments[i].y1 = gridSegments[i].y2
4036 = lineGap / 2 + (i * (squareSize + lineGap));
4039 for (j = 0; j < BOARD_WIDTH + 1; j++) {
4040 gridSegments[j + i].y1 = 0;
4041 gridSegments[j + i].y2 =
4042 lineGap + BOARD_HEIGHT * (squareSize + lineGap);
4043 gridSegments[j + i].x1 = gridSegments[j + i].x2
4044 = lineGap / 2 + (j * (squareSize + lineGap));
4048 static void MenuBarSelect(w, addr, index)
4053 XtActionProc proc = (XtActionProc) addr;
4055 (proc)(NULL, NULL, NULL, NULL);
4058 void CreateMenuBarPopup(parent, name, mb)
4068 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
4071 XtSetArg(args[j], XtNleftMargin, 20); j++;
4072 XtSetArg(args[j], XtNrightMargin, 20); j++;
4074 while (mi->string != NULL) {
4075 if (strcmp(mi->string, "----") == 0) {
4076 entry = XtCreateManagedWidget(mi->string, smeLineObjectClass,
4079 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string)));
4080 entry = XtCreateManagedWidget(mi->string, smeBSBObjectClass,
4082 XtAddCallback(entry, XtNcallback,
4083 (XtCallbackProc) MenuBarSelect,
4084 (caddr_t) mi->proc);
4090 Widget CreateMenuBar(mb)
4094 Widget anchor, menuBar;
4096 char menuName[MSG_SIZ];
4099 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
4100 XtSetArg(args[j], XtNvSpace, 0); j++;
4101 XtSetArg(args[j], XtNborderWidth, 0); j++;
4102 menuBar = XtCreateWidget("menuBar", boxWidgetClass,
4103 formWidget, args, j);
4105 while (mb->name != NULL) {
4106 strcpy(menuName, "menu");
4107 strcat(menuName, mb->name);
4109 XtSetArg(args[j], XtNmenuName, XtNewString(menuName)); j++;
4112 shortName[0] = _(mb->name)[0];
4113 shortName[1] = NULLCHAR;
4114 XtSetArg(args[j], XtNlabel, XtNewString(shortName)); j++;
4117 XtSetArg(args[j], XtNlabel, XtNewString(_(mb->name))); j++;
4120 XtSetArg(args[j], XtNborderWidth, 0); j++;
4121 anchor = XtCreateManagedWidget(mb->name, menuButtonWidgetClass,
4123 CreateMenuBarPopup(menuBar, menuName, mb);
4129 Widget CreateButtonBar(mi)
4133 Widget button, buttonBar;
4137 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
4139 XtSetArg(args[j], XtNhSpace, 0); j++;
4141 XtSetArg(args[j], XtNborderWidth, 0); j++;
4142 XtSetArg(args[j], XtNvSpace, 0); j++;
4143 buttonBar = XtCreateWidget("buttonBar", boxWidgetClass,
4144 formWidget, args, j);
4146 while (mi->string != NULL) {
4149 XtSetArg(args[j], XtNinternalWidth, 2); j++;
4150 XtSetArg(args[j], XtNborderWidth, 0); j++;
4152 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string))); j++;
4153 button = XtCreateManagedWidget(mi->string, commandWidgetClass,
4154 buttonBar, args, j);
4155 XtAddCallback(button, XtNcallback,
4156 (XtCallbackProc) MenuBarSelect,
4157 (caddr_t) mi->proc);
4164 CreatePieceMenu(name, color)
4171 ChessSquare selection;
4173 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
4174 boardWidget, args, 0);
4176 for (i = 0; i < PIECE_MENU_SIZE; i++) {
4177 String item = pieceMenuStrings[color][i];
4179 if (strcmp(item, "----") == 0) {
4180 entry = XtCreateManagedWidget(item, smeLineObjectClass,
4183 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
4184 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
4186 selection = pieceMenuTranslation[color][i];
4187 XtAddCallback(entry, XtNcallback,
4188 (XtCallbackProc) PieceMenuSelect,
4189 (caddr_t) selection);
4190 if (selection == WhitePawn || selection == BlackPawn) {
4191 XtSetArg(args[0], XtNpopupOnEntry, entry);
4192 XtSetValues(menu, args, 1);
4205 ChessSquare selection;
4207 whitePieceMenu = CreatePieceMenu("menuW", 0);
4208 blackPieceMenu = CreatePieceMenu("menuB", 1);
4210 XtRegisterGrabAction(PieceMenuPopup, True,
4211 (unsigned)(ButtonPressMask|ButtonReleaseMask),
4212 GrabModeAsync, GrabModeAsync);
4214 XtSetArg(args[0], XtNlabel, _("Drop"));
4215 dropMenu = XtCreatePopupShell("menuD", simpleMenuWidgetClass,
4216 boardWidget, args, 1);
4217 for (i = 0; i < DROP_MENU_SIZE; i++) {
4218 String item = dropMenuStrings[i];
4220 if (strcmp(item, "----") == 0) {
4221 entry = XtCreateManagedWidget(item, smeLineObjectClass,
4224 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
4225 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
4227 selection = dropMenuTranslation[i];
4228 XtAddCallback(entry, XtNcallback,
4229 (XtCallbackProc) DropMenuSelect,
4230 (caddr_t) selection);
4235 void SetupDropMenu()
4243 for (i=0; i<sizeof(dmEnables)/sizeof(DropMenuEnables); i++) {
4244 entry = XtNameToWidget(dropMenu, dmEnables[i].widget);
4245 p = strchr(gameMode == IcsPlayingWhite ? white_holding : black_holding,
4246 dmEnables[i].piece);
4247 XtSetSensitive(entry, p != NULL || !appData.testLegality
4248 /*!!temp:*/ || (gameInfo.variant == VariantCrazyhouse
4249 && !appData.icsActive));
4251 while (p && *p++ == dmEnables[i].piece) count++;
4252 snprintf(label, sizeof(label), "%s %d", dmEnables[i].widget, count);
4254 XtSetArg(args[j], XtNlabel, label); j++;
4255 XtSetValues(entry, args, j);
4259 void PieceMenuPopup(w, event, params, num_params)
4263 Cardinal *num_params;
4266 if (event->type != ButtonPress) return;
4267 if (errorUp) ErrorPopDown();
4271 whichMenu = params[0];
4273 case IcsPlayingWhite:
4274 case IcsPlayingBlack:
4276 case MachinePlaysWhite:
4277 case MachinePlaysBlack:
4278 if (appData.testLegality &&
4279 gameInfo.variant != VariantBughouse &&
4280 gameInfo.variant != VariantCrazyhouse) return;
4282 whichMenu = "menuD";
4288 if (((pmFromX = EventToSquare(event->xbutton.x, BOARD_WIDTH)) < 0) ||
4289 ((pmFromY = EventToSquare(event->xbutton.y, BOARD_HEIGHT)) < 0)) {
4290 pmFromX = pmFromY = -1;
4294 pmFromX = BOARD_WIDTH - 1 - pmFromX;
4296 pmFromY = BOARD_HEIGHT - 1 - pmFromY;
4298 XtPopupSpringLoaded(XtNameToWidget(boardWidget, whichMenu));
4301 static void PieceMenuSelect(w, piece, junk)
4306 if (pmFromX < 0 || pmFromY < 0) return;
4307 EditPositionMenuEvent(piece, pmFromX, pmFromY);
4310 static void DropMenuSelect(w, piece, junk)
4315 if (pmFromX < 0 || pmFromY < 0) return;
4316 DropMenuEvent(piece, pmFromX, pmFromY);
4319 void WhiteClock(w, event, prms, nprms)
4325 if (gameMode == EditPosition || gameMode == IcsExamining) {
4326 SetWhiteToPlayEvent();
4327 } else if (gameMode == IcsPlayingBlack || gameMode == MachinePlaysWhite) {
4332 void BlackClock(w, event, prms, nprms)
4338 if (gameMode == EditPosition || gameMode == IcsExamining) {
4339 SetBlackToPlayEvent();
4340 } else if (gameMode == IcsPlayingWhite || gameMode == MachinePlaysBlack) {
4347 * If the user selects on a border boundary, return -1; if off the board,
4348 * return -2. Otherwise map the event coordinate to the square.
4350 int EventToSquare(x, limit)
4358 if ((x % (squareSize + lineGap)) >= squareSize)
4360 x /= (squareSize + lineGap);
4366 static void do_flash_delay(msec)
4372 static void drawHighlight(file, rank, gc)
4378 if (lineGap == 0 || appData.blindfold) return;
4381 x = lineGap/2 + ((BOARD_WIDTH-1)-file) *
4382 (squareSize + lineGap);
4383 y = lineGap/2 + rank * (squareSize + lineGap);
4385 x = lineGap/2 + file * (squareSize + lineGap);
4386 y = lineGap/2 + ((BOARD_HEIGHT-1)-rank) *
4387 (squareSize + lineGap);
4390 XDrawRectangle(xDisplay, xBoardWindow, gc, x, y,
4391 squareSize+lineGap, squareSize+lineGap);
4394 int hi1X = -1, hi1Y = -1, hi2X = -1, hi2Y = -1;
4395 int pm1X = -1, pm1Y = -1, pm2X = -1, pm2Y = -1;
4398 SetHighlights(fromX, fromY, toX, toY)
4399 int fromX, fromY, toX, toY;
4401 if (hi1X != fromX || hi1Y != fromY) {
4402 if (hi1X >= 0 && hi1Y >= 0) {
4403 drawHighlight(hi1X, hi1Y, lineGC);
4405 if (fromX >= 0 && fromY >= 0) {
4406 drawHighlight(fromX, fromY, highlineGC);
4409 if (hi2X != toX || hi2Y != toY) {
4410 if (hi2X >= 0 && hi2Y >= 0) {
4411 drawHighlight(hi2X, hi2Y, lineGC);
4413 if (toX >= 0 && toY >= 0) {
4414 drawHighlight(toX, toY, highlineGC);
4426 SetHighlights(-1, -1, -1, -1);
4431 SetPremoveHighlights(fromX, fromY, toX, toY)
4432 int fromX, fromY, toX, toY;
4434 if (pm1X != fromX || pm1Y != fromY) {
4435 if (pm1X >= 0 && pm1Y >= 0) {
4436 drawHighlight(pm1X, pm1Y, lineGC);
4438 if (fromX >= 0 && fromY >= 0) {
4439 drawHighlight(fromX, fromY, prelineGC);
4442 if (pm2X != toX || pm2Y != toY) {
4443 if (pm2X >= 0 && pm2Y >= 0) {
4444 drawHighlight(pm2X, pm2Y, lineGC);
4446 if (toX >= 0 && toY >= 0) {
4447 drawHighlight(toX, toY, prelineGC);
4457 ClearPremoveHighlights()
4459 SetPremoveHighlights(-1, -1, -1, -1);
4462 static void BlankSquare(x, y, color, piece, dest)
4467 if (useImages && useImageSqs) {
4471 pm = xpmLightSquare;
4476 case 2: /* neutral */
4481 XCopyArea(xDisplay, pm, dest, wlPieceGC, 0, 0,
4482 squareSize, squareSize, x, y);
4492 case 2: /* neutral */
4497 XFillRectangle(xDisplay, dest, gc, x, y, squareSize, squareSize);
4502 I split out the routines to draw a piece so that I could
4503 make a generic flash routine.
4505 static void monoDrawPiece_1bit(piece, square_color, x, y, dest)
4507 int square_color, x, y;
4510 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
4511 switch (square_color) {
4513 case 2: /* neutral */
4515 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
4516 ? *pieceToOutline(piece)
4517 : *pieceToSolid(piece),
4518 dest, bwPieceGC, 0, 0,
4519 squareSize, squareSize, x, y);
4522 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
4523 ? *pieceToSolid(piece)
4524 : *pieceToOutline(piece),
4525 dest, wbPieceGC, 0, 0,
4526 squareSize, squareSize, x, y);
4531 static void monoDrawPiece(piece, square_color, x, y, dest)
4533 int square_color, x, y;
4536 switch (square_color) {
4538 case 2: /* neutral */
4540 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
4541 ? *pieceToOutline(piece)
4542 : *pieceToSolid(piece),
4543 dest, bwPieceGC, 0, 0,
4544 squareSize, squareSize, x, y, 1);
4547 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
4548 ? *pieceToSolid(piece)
4549 : *pieceToOutline(piece),
4550 dest, wbPieceGC, 0, 0,
4551 squareSize, squareSize, x, y, 1);
4556 static void colorDrawPiece(piece, square_color, x, y, dest)
4558 int square_color, x, y;
4561 if(pieceToSolid(piece) == NULL) return; // [HGM] bitmaps: make it non-fatal if we have no bitmap;
4562 switch (square_color) {
4564 XCopyPlane(xDisplay, *pieceToSolid(piece),
4565 dest, (int) piece < (int) BlackPawn
4566 ? wlPieceGC : blPieceGC, 0, 0,
4567 squareSize, squareSize, x, y, 1);
4570 XCopyPlane(xDisplay, *pieceToSolid(piece),
4571 dest, (int) piece < (int) BlackPawn
4572 ? wdPieceGC : bdPieceGC, 0, 0,
4573 squareSize, squareSize, x, y, 1);
4575 case 2: /* neutral */
4577 XCopyPlane(xDisplay, *pieceToSolid(piece),
4578 dest, (int) piece < (int) BlackPawn
4579 ? wjPieceGC : bjPieceGC, 0, 0,
4580 squareSize, squareSize, x, y, 1);
4585 static void colorDrawPieceImage(piece, square_color, x, y, dest)
4587 int square_color, x, y;
4592 switch (square_color) {
4594 case 2: /* neutral */
4596 if ((int)piece < (int) BlackPawn) {
4604 if ((int)piece < (int) BlackPawn) {
4612 XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
4613 dest, wlPieceGC, 0, 0,
4614 squareSize, squareSize, x, y);
4617 typedef void (*DrawFunc)();
4619 DrawFunc ChooseDrawFunc()
4621 if (appData.monoMode) {
4622 if (DefaultDepth(xDisplay, xScreen) == 1) {
4623 return monoDrawPiece_1bit;
4625 return monoDrawPiece;
4629 return colorDrawPieceImage;
4631 return colorDrawPiece;
4635 /* [HR] determine square color depending on chess variant. */
4636 static int SquareColor(row, column)
4641 if (gameInfo.variant == VariantXiangqi) {
4642 if (column >= 3 && column <= 5 && row >= 0 && row <= 2) {
4644 } else if (column >= 3 && column <= 5 && row >= 7 && row <= 9) {
4646 } else if (row <= 4) {
4652 square_color = ((column + row) % 2) == 1;
4655 /* [hgm] holdings: next line makes all holdings squares light */
4656 if(column < BOARD_LEFT || column >= BOARD_RGHT) square_color = 1;
4658 return square_color;
4661 void DrawSquare(row, column, piece, do_flash)
4662 int row, column, do_flash;
4665 int square_color, x, y, direction, font_ascent, font_descent;
4668 XCharStruct overall;
4672 if(gameInfo.variant == VariantShogi) { // [HGM] shogi: in shogi Q is used for Lance
4673 if(piece == WhiteQueen) piece = WhiteLance; else
4674 if(piece == BlackQueen) piece = BlackLance;
4677 else if(gameInfo.variant == VariantGothic) { // [HGM] shogi: in Gothic Chancelor has alternative look
4678 if(piece == WhiteMarshall) piece = WhiteSilver; else
4679 if(piece == BlackMarshall) piece = BlackSilver;
4683 /* Calculate delay in milliseconds (2-delays per complete flash) */
4684 flash_delay = 500 / appData.flashRate;
4687 x = lineGap + ((BOARD_WIDTH-1)-column) *
4688 (squareSize + lineGap);
4689 y = lineGap + row * (squareSize + lineGap);
4691 x = lineGap + column * (squareSize + lineGap);
4692 y = lineGap + ((BOARD_HEIGHT-1)-row) *
4693 (squareSize + lineGap);
4696 square_color = SquareColor(row, column);
4698 if ( // [HGM] holdings: blank out area between board and holdings
4699 column == BOARD_LEFT-1 || column == BOARD_RGHT
4700 || (column == BOARD_LEFT-2 && row < BOARD_HEIGHT-gameInfo.holdingsSize)
4701 || (column == BOARD_RGHT+1 && row >= gameInfo.holdingsSize) ) {
4702 BlankSquare(x, y, 2, EmptySquare, xBoardWindow);
4704 // [HGM] print piece counts next to holdings
4705 string[1] = NULLCHAR;
4706 if (column == (flipView ? BOARD_LEFT-1 : BOARD_RGHT) && piece > 1 ) {
4707 string[0] = '0' + piece;
4708 XTextExtents(countFontStruct, string, 1, &direction,
4709 &font_ascent, &font_descent, &overall);
4710 if (appData.monoMode) {
4711 XDrawImageString(xDisplay, xBoardWindow, countGC,
4712 x + squareSize - overall.width - 2,
4713 y + font_ascent + 1, string, 1);
4715 XDrawString(xDisplay, xBoardWindow, countGC,
4716 x + squareSize - overall.width - 2,
4717 y + font_ascent + 1, string, 1);
4720 if (column == (flipView ? BOARD_RGHT : BOARD_LEFT-1) && piece > 1) {
4721 string[0] = '0' + piece;
4722 XTextExtents(countFontStruct, string, 1, &direction,
4723 &font_ascent, &font_descent, &overall);
4724 if (appData.monoMode) {
4725 XDrawImageString(xDisplay, xBoardWindow, countGC,
4726 x + 2, y + font_ascent + 1, string, 1);
4728 XDrawString(xDisplay, xBoardWindow, countGC,
4729 x + 2, y + font_ascent + 1, string, 1);
4733 if (piece == EmptySquare || appData.blindfold) {
4734 BlankSquare(x, y, square_color, piece, xBoardWindow);
4736 drawfunc = ChooseDrawFunc();
4737 if (do_flash && appData.flashCount > 0) {
4738 for (i=0; i<appData.flashCount; ++i) {
4740 drawfunc(piece, square_color, x, y, xBoardWindow);
4741 XSync(xDisplay, False);
4742 do_flash_delay(flash_delay);
4744 BlankSquare(x, y, square_color, piece, xBoardWindow);
4745 XSync(xDisplay, False);
4746 do_flash_delay(flash_delay);
4749 drawfunc(piece, square_color, x, y, xBoardWindow);
4753 string[1] = NULLCHAR;
4754 if (appData.showCoords && row == (flipView ? BOARD_HEIGHT-1 : 0)
4755 && column >= BOARD_LEFT && column < BOARD_RGHT) {
4756 string[0] = 'a' + column - BOARD_LEFT;
4757 XTextExtents(coordFontStruct, string, 1, &direction,
4758 &font_ascent, &font_descent, &overall);
4759 if (appData.monoMode) {
4760 XDrawImageString(xDisplay, xBoardWindow, coordGC,
4761 x + squareSize - overall.width - 2,
4762 y + squareSize - font_descent - 1, string, 1);
4764 XDrawString(xDisplay, xBoardWindow, coordGC,
4765 x + squareSize - overall.width - 2,
4766 y + squareSize - font_descent - 1, string, 1);
4769 if (appData.showCoords && column == (flipView ? BOARD_RGHT-1 : BOARD_LEFT)) {
4770 string[0] = ONE + row;
4771 XTextExtents(coordFontStruct, string, 1, &direction,
4772 &font_ascent, &font_descent, &overall);
4773 if (appData.monoMode) {
4774 XDrawImageString(xDisplay, xBoardWindow, coordGC,
4775 x + 2, y + font_ascent + 1, string, 1);
4777 XDrawString(xDisplay, xBoardWindow, coordGC,
4778 x + 2, y + font_ascent + 1, string, 1);
4784 /* Why is this needed on some versions of X? */
4785 void EventProc(widget, unused, event)
4790 if (!XtIsRealized(widget))
4793 switch (event->type) {
4795 if (event->xexpose.count > 0) return; /* no clipping is done */
4796 XDrawPosition(widget, True, NULL);
4804 void DrawPosition(fullRedraw, board)
4805 /*Boolean*/int fullRedraw;
4808 XDrawPosition(boardWidget, fullRedraw, board);
4811 /* Returns 1 if there are "too many" differences between b1 and b2
4812 (i.e. more than 1 move was made) */
4813 static int too_many_diffs(b1, b2)
4819 for (i=0; i<BOARD_HEIGHT; ++i) {
4820 for (j=0; j<BOARD_WIDTH; ++j) {
4821 if (b1[i][j] != b2[i][j]) {
4822 if (++c > 4) /* Castling causes 4 diffs */
4831 /* Matrix describing castling maneuvers */
4832 /* Row, ColRookFrom, ColKingFrom, ColRookTo, ColKingTo */
4833 static int castling_matrix[4][5] = {
4834 { 0, 0, 4, 3, 2 }, /* 0-0-0, white */
4835 { 0, 7, 4, 5, 6 }, /* 0-0, white */
4836 { 7, 0, 4, 3, 2 }, /* 0-0-0, black */
4837 { 7, 7, 4, 5, 6 } /* 0-0, black */
4840 /* Checks whether castling occurred. If it did, *rrow and *rcol
4841 are set to the destination (row,col) of the rook that moved.
4843 Returns 1 if castling occurred, 0 if not.
4845 Note: Only handles a max of 1 castling move, so be sure
4846 to call too_many_diffs() first.
4848 static int check_castle_draw(newb, oldb, rrow, rcol)
4855 /* For each type of castling... */
4856 for (i=0; i<4; ++i) {
4857 r = castling_matrix[i];
4859 /* Check the 4 squares involved in the castling move */
4861 for (j=1; j<=4; ++j) {
4862 if (newb[r[0]][r[j]] == oldb[r[0]][r[j]]) {
4869 /* All 4 changed, so it must be a castling move */
4878 static int damage[BOARD_SIZE][BOARD_SIZE];
4881 * event handler for redrawing the board
4883 void XDrawPosition(w, repaint, board)
4885 /*Boolean*/int repaint;
4889 static int lastFlipView = 0;
4890 static int lastBoardValid = 0;
4891 static Board lastBoard;
4895 if (board == NULL) {
4896 if (!lastBoardValid) return;
4899 if (!lastBoardValid || lastFlipView != flipView) {
4900 XtSetArg(args[0], XtNleftBitmap, (flipView ? xMarkPixmap : None));
4901 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flip View"),
4906 * It would be simpler to clear the window with XClearWindow()
4907 * but this causes a very distracting flicker.
4910 if (!repaint && lastBoardValid && lastFlipView == flipView) {
4912 /* If too much changes (begin observing new game, etc.), don't
4914 do_flash = too_many_diffs(board, lastBoard) ? 0 : 1;
4916 /* Special check for castling so we don't flash both the king
4917 and the rook (just flash the king). */
4919 if (check_castle_draw(board, lastBoard, &rrow, &rcol)) {
4920 /* Draw rook with NO flashing. King will be drawn flashing later */
4921 DrawSquare(rrow, rcol, board[rrow][rcol], 0);
4922 lastBoard[rrow][rcol] = board[rrow][rcol];
4926 /* First pass -- Draw (newly) empty squares and repair damage.
4927 This prevents you from having a piece show up twice while it
4928 is flashing on its new square */
4929 for (i = 0; i < BOARD_HEIGHT; i++)
4930 for (j = 0; j < BOARD_WIDTH; j++)
4931 if ((board[i][j] != lastBoard[i][j] && board[i][j] == EmptySquare)
4933 DrawSquare(i, j, board[i][j], 0);
4934 damage[i][j] = False;
4937 /* Second pass -- Draw piece(s) in new position and flash them */
4938 for (i = 0; i < BOARD_HEIGHT; i++)
4939 for (j = 0; j < BOARD_WIDTH; j++)
4940 if (board[i][j] != lastBoard[i][j]) {
4941 DrawSquare(i, j, board[i][j], do_flash);
4945 XDrawSegments(xDisplay, xBoardWindow, lineGC,
4946 gridSegments, BOARD_HEIGHT + BOARD_WIDTH + 2);
4948 for (i = 0; i < BOARD_HEIGHT; i++)
4949 for (j = 0; j < BOARD_WIDTH; j++) {
4950 DrawSquare(i, j, board[i][j], 0);
4951 damage[i][j] = False;
4955 CopyBoard(lastBoard, board);
4957 lastFlipView = flipView;
4959 /* Draw highlights */
4960 if (pm1X >= 0 && pm1Y >= 0) {
4961 drawHighlight(pm1X, pm1Y, prelineGC);
4963 if (pm2X >= 0 && pm2Y >= 0) {
4964 drawHighlight(pm2X, pm2Y, prelineGC);
4966 if (hi1X >= 0 && hi1Y >= 0) {
4967 drawHighlight(hi1X, hi1Y, highlineGC);
4969 if (hi2X >= 0 && hi2Y >= 0) {
4970 drawHighlight(hi2X, hi2Y, highlineGC);
4973 /* If piece being dragged around board, must redraw that too */
4976 XSync(xDisplay, False);
4981 * event handler for redrawing the board
4983 void DrawPositionProc(w, event, prms, nprms)
4989 XDrawPosition(w, True, NULL);
4994 * event handler for parsing user moves
4996 // [HGM] This routine will need quite some reworking. Although the backend still supports the old
4997 // way of doing things, by calling UserMoveEvent() to test the legality of the move and then perform
4998 // it at the end, and doing all kind of preliminary tests here (e.g. to weed out self-captures), it
4999 // should be made to use the new way, of calling UserMoveTest early to determine the legality of the
5000 // move, (which will weed out the illegal selfcaptures and moves into the holdings, and flag promotions),
5001 // and at the end FinishMove() to perform the move after optional promotion popups.
5002 // For now I patched it to allow self-capture with King, and suppress clicks between board and holdings.
5003 void HandleUserMove(w, event, prms, nprms)
5010 Boolean saveAnimate;
5011 static int second = 0;
5013 if (w != boardWidget || errorExitStatus != -1) return;
5015 if (event->type == ButtonPress) ErrorPopDown();
5018 if (event->type == ButtonPress) {
5019 XtPopdown(promotionShell);
5020 XtDestroyWidget(promotionShell);
5021 promotionUp = False;
5029 x = EventToSquare(event->xbutton.x, BOARD_WIDTH);
5030 y = EventToSquare(event->xbutton.y, BOARD_HEIGHT);
5031 if (!flipView && y >= 0) {
5032 y = BOARD_HEIGHT - 1 - y;
5034 if (flipView && x >= 0) {
5035 x = BOARD_WIDTH - 1 - x;
5038 /* [HGM] holdings: next 5 lines: ignore all clicks between board and holdings */
5039 if(event->type == ButtonPress
5040 && ( x == BOARD_LEFT-1 || x == BOARD_RGHT
5041 || x == BOARD_LEFT-2 && y < BOARD_HEIGHT-gameInfo.holdingsSize
5042 || x == BOARD_RGHT+1 && y >= gameInfo.holdingsSize) )
5046 if (event->type == ButtonPress) {
5048 if (OKToStartUserMove(x, y)) {
5052 DragPieceBegin(event->xbutton.x, event->xbutton.y);
5053 if (appData.highlightDragging) {
5054 SetHighlights(x, y, -1, -1);
5062 if (event->type == ButtonPress && gameMode != EditPosition &&
5067 /* Check if clicking again on the same color piece */
5068 fromP = boards[currentMove][fromY][fromX];
5069 toP = boards[currentMove][y][x];
5070 if ((WhitePawn <= fromP && fromP < WhiteKing && // [HGM] this test should go, as UserMoveTest now does it.
5071 WhitePawn <= toP && toP <= WhiteKing) || // For now I made it less critical by exempting King
5072 (BlackPawn <= fromP && fromP < BlackKing && // moves, to not interfere with FRC castlings.
5073 BlackPawn <= toP && toP <= BlackKing)) {
5074 /* Clicked again on same color piece -- changed his mind */
5075 second = (x == fromX && y == fromY);
5076 if (appData.highlightDragging) {
5077 SetHighlights(x, y, -1, -1);
5081 if (OKToStartUserMove(x, y)) {
5084 DragPieceBegin(event->xbutton.x, event->xbutton.y);
5090 if (event->type == ButtonRelease && x == fromX && y == fromY) {
5091 DragPieceEnd(event->xbutton.x, event->xbutton.y);
5092 if (appData.animateDragging) {
5093 /* Undo animation damage if any */
5094 DrawPosition(FALSE, NULL);
5097 /* Second up/down in same square; just abort move */
5102 ClearPremoveHighlights();
5104 /* First upclick in same square; start click-click mode */
5105 SetHighlights(x, y, -1, -1);
5110 /* Completed move */
5113 saveAnimate = appData.animate;
5114 if (event->type == ButtonPress) {
5115 /* Finish clickclick move */
5116 if (appData.animate || appData.highlightLastMove) {
5117 SetHighlights(fromX, fromY, toX, toY);
5122 /* Finish drag move */
5123 if (appData.highlightLastMove) {
5124 SetHighlights(fromX, fromY, toX, toY);
5128 DragPieceEnd(event->xbutton.x, event->xbutton.y);
5129 /* Don't animate move and drag both */
5130 appData.animate = FALSE;
5132 if (IsPromotion(fromX, fromY, toX, toY)) {
5133 if (appData.alwaysPromoteToQueen) {
5134 UserMoveEvent(fromX, fromY, toX, toY, 'q');
5135 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
5136 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
5139 SetHighlights(fromX, fromY, toX, toY);
5143 UserMoveEvent(fromX, fromY, toX, toY, NULLCHAR);
5144 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
5145 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
5148 appData.animate = saveAnimate;
5149 if (appData.animate || appData.animateDragging) {
5150 /* Undo animation damage if needed */
5151 DrawPosition(FALSE, NULL);
5155 void AnimateUserMove (Widget w, XEvent * event,
5156 String * params, Cardinal * nParams)
5158 DragPieceMove(event->xmotion.x, event->xmotion.y);
5161 Widget CommentCreate(name, text, mutable, callback, lines)
5163 int /*Boolean*/ mutable;
5164 XtCallbackProc callback;
5168 Widget shell, layout, form, edit, b_ok, b_cancel, b_clear, b_close, b_edit;
5173 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5174 XtGetValues(boardWidget, args, j);
5177 XtSetArg(args[j], XtNresizable, True); j++;
5180 XtCreatePopupShell(name, topLevelShellWidgetClass,
5181 shellWidget, args, j);
5184 XtCreatePopupShell(name, transientShellWidgetClass,
5185 shellWidget, args, j);
5188 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
5189 layoutArgs, XtNumber(layoutArgs));
5191 XtCreateManagedWidget("form", formWidgetClass, layout,
5192 formArgs, XtNumber(formArgs));
5196 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
5197 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
5199 XtSetArg(args[j], XtNstring, text); j++;
5200 XtSetArg(args[j], XtNtop, XtChainTop); j++;
5201 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5202 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5203 XtSetArg(args[j], XtNright, XtChainRight); j++;
5204 XtSetArg(args[j], XtNresizable, True); j++;
5205 XtSetArg(args[j], XtNwidth, bw_width); j++; /*force wider than buttons*/
5207 XtSetArg(args[j], XtNscrollVertical, XawtextScrollWhenNeeded); j++;
5209 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
5210 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
5212 XtSetArg(args[j], XtNautoFill, True); j++;
5213 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
5215 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
5219 XtSetArg(args[j], XtNfromVert, edit); j++;
5220 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5221 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5222 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5223 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5225 XtCreateManagedWidget(_("ok"), commandWidgetClass, form, args, j);
5226 XtAddCallback(b_ok, XtNcallback, callback, (XtPointer) 0);
5229 XtSetArg(args[j], XtNfromVert, edit); j++;
5230 XtSetArg(args[j], XtNfromHoriz, b_ok); j++;
5231 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5232 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5233 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5234 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5236 XtCreateManagedWidget(_("cancel"), commandWidgetClass, form, args, j);
5237 XtAddCallback(b_cancel, XtNcallback, callback, (XtPointer) 0);
5240 XtSetArg(args[j], XtNfromVert, edit); j++;
5241 XtSetArg(args[j], XtNfromHoriz, b_cancel); j++;
5242 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5243 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5244 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5245 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5247 XtCreateManagedWidget(_("clear"), commandWidgetClass, form, args, j);
5248 XtAddCallback(b_clear, XtNcallback, callback, (XtPointer) 0);
5251 XtSetArg(args[j], XtNfromVert, edit); j++;
5252 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5253 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5254 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5255 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5257 XtCreateManagedWidget(_("close"), commandWidgetClass, form, args, j);
5258 XtAddCallback(b_close, XtNcallback, callback, (XtPointer) 0);
5261 XtSetArg(args[j], XtNfromVert, edit); j++;
5262 XtSetArg(args[j], XtNfromHoriz, b_close); j++;
5263 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5264 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5265 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5266 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5268 XtCreateManagedWidget(_("edit"), commandWidgetClass, form, args, j);
5269 XtAddCallback(b_edit, XtNcallback, callback, (XtPointer) 0);
5272 XtRealizeWidget(shell);
5274 if (commentX == -1) {
5277 Dimension pw_height;
5278 Dimension ew_height;
5281 XtSetArg(args[j], XtNheight, &ew_height); j++;
5282 XtGetValues(edit, args, j);
5285 XtSetArg(args[j], XtNheight, &pw_height); j++;
5286 XtGetValues(shell, args, j);
5287 commentH = pw_height + (lines - 1) * ew_height;
5288 commentW = bw_width - 16;
5290 XSync(xDisplay, False);
5292 /* This code seems to tickle an X bug if it is executed too soon
5293 after xboard starts up. The coordinates get transformed as if
5294 the main window was positioned at (0, 0).
5296 XtTranslateCoords(shellWidget,
5297 (bw_width - commentW) / 2, 0 - commentH / 2,
5298 &commentX, &commentY);
5300 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
5301 RootWindowOfScreen(XtScreen(shellWidget)),
5302 (bw_width - commentW) / 2, 0 - commentH / 2,
5307 if (commentY < 0) commentY = 0; /*avoid positioning top offscreen*/
5310 XtSetArg(args[j], XtNheight, commentH); j++;
5311 XtSetArg(args[j], XtNwidth, commentW); j++;
5312 XtSetArg(args[j], XtNx, commentX); j++;
5313 XtSetArg(args[j], XtNy, commentY); j++;
5314 XtSetValues(shell, args, j);
5315 XtSetKeyboardFocus(shell, edit);
5320 /* Used for analysis window and ICS input window */
5321 Widget MiscCreate(name, text, mutable, callback, lines)
5323 int /*Boolean*/ mutable;
5324 XtCallbackProc callback;
5328 Widget shell, layout, form, edit;
5330 Dimension bw_width, pw_height, ew_height, w, h;
5336 XtSetArg(args[j], XtNresizable, True); j++;
5339 XtCreatePopupShell(name, topLevelShellWidgetClass,
5340 shellWidget, args, j);
5343 XtCreatePopupShell(name, transientShellWidgetClass,
5344 shellWidget, args, j);
5347 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
5348 layoutArgs, XtNumber(layoutArgs));
5350 XtCreateManagedWidget("form", formWidgetClass, layout,
5351 formArgs, XtNumber(formArgs));
5355 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
5356 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
5358 XtSetArg(args[j], XtNstring, text); j++;
5359 XtSetArg(args[j], XtNtop, XtChainTop); j++;
5360 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5361 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5362 XtSetArg(args[j], XtNright, XtChainRight); j++;
5363 XtSetArg(args[j], XtNresizable, True); j++;
5365 XtSetArg(args[j], XtNscrollVertical, XawtextScrollWhenNeeded); j++;
5367 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
5368 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
5370 XtSetArg(args[j], XtNautoFill, True); j++;
5371 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
5373 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
5375 XtRealizeWidget(shell);
5378 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5379 XtGetValues(boardWidget, args, j);
5382 XtSetArg(args[j], XtNheight, &ew_height); j++;
5383 XtGetValues(edit, args, j);
5386 XtSetArg(args[j], XtNheight, &pw_height); j++;
5387 XtGetValues(shell, args, j);
5388 h = pw_height + (lines - 1) * ew_height;
5391 XSync(xDisplay, False);
5393 /* This code seems to tickle an X bug if it is executed too soon
5394 after xboard starts up. The coordinates get transformed as if
5395 the main window was positioned at (0, 0).
5397 XtTranslateCoords(shellWidget, (bw_width - w) / 2, 0 - h / 2, &x, &y);
5399 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
5400 RootWindowOfScreen(XtScreen(shellWidget)),
5401 (bw_width - w) / 2, 0 - h / 2, &xx, &yy, &junk);
5405 if (y < 0) y = 0; /*avoid positioning top offscreen*/
5408 XtSetArg(args[j], XtNheight, h); j++;
5409 XtSetArg(args[j], XtNwidth, w); j++;
5410 XtSetArg(args[j], XtNx, x); j++;
5411 XtSetArg(args[j], XtNy, y); j++;
5412 XtSetValues(shell, args, j);
5418 static int savedIndex; /* gross that this is global */
5420 void EditCommentPopUp(index, title, text)
5429 if (text == NULL) text = "";
5431 if (editShell == NULL) {
5433 CommentCreate(title, text, True, EditCommentCallback, 4);
5434 XtRealizeWidget(editShell);
5435 CatchDeleteWindow(editShell, "EditCommentPopDown");
5437 edit = XtNameToWidget(editShell, "*form.text");
5439 XtSetArg(args[j], XtNstring, text); j++;
5440 XtSetValues(edit, args, j);
5442 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5443 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5444 XtSetValues(editShell, args, j);
5447 XtPopup(editShell, XtGrabNone);
5451 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
5452 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
5456 void EditCommentCallback(w, client_data, call_data)
5458 XtPointer client_data, call_data;
5466 XtSetArg(args[j], XtNlabel, &name); j++;
5467 XtGetValues(w, args, j);
5469 if (strcmp(name, _("ok")) == 0) {
5470 edit = XtNameToWidget(editShell, "*form.text");
5472 XtSetArg(args[j], XtNstring, &val); j++;
5473 XtGetValues(edit, args, j);
5474 ReplaceComment(savedIndex, val);
5475 EditCommentPopDown();
5476 } else if (strcmp(name, _("cancel")) == 0) {
5477 EditCommentPopDown();
5478 } else if (strcmp(name, _("clear")) == 0) {
5479 edit = XtNameToWidget(editShell, "*form.text");
5480 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
5481 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
5485 void EditCommentPopDown()
5490 if (!editUp) return;
5492 XtSetArg(args[j], XtNx, &commentX); j++;
5493 XtSetArg(args[j], XtNy, &commentY); j++;
5494 XtSetArg(args[j], XtNheight, &commentH); j++;
5495 XtSetArg(args[j], XtNwidth, &commentW); j++;
5496 XtGetValues(editShell, args, j);
5497 XtPopdown(editShell);
5500 XtSetArg(args[j], XtNleftBitmap, None); j++;
5501 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
5505 void ICSInputBoxPopUp()
5510 char *title = _("ICS Input");
5513 if (ICSInputShell == NULL) {
5514 ICSInputShell = MiscCreate(title, "", True, NULL, 1);
5515 tr = XtParseTranslationTable(ICSInputTranslations);
5516 edit = XtNameToWidget(ICSInputShell, "*form.text");
5517 XtOverrideTranslations(edit, tr);
5518 XtRealizeWidget(ICSInputShell);
5519 CatchDeleteWindow(ICSInputShell, "ICSInputBoxPopDown");
5522 edit = XtNameToWidget(ICSInputShell, "*form.text");
5524 XtSetArg(args[j], XtNstring, ""); j++;
5525 XtSetValues(edit, args, j);
5527 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5528 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5529 XtSetValues(ICSInputShell, args, j);
5532 XtPopup(ICSInputShell, XtGrabNone);
5533 XtSetKeyboardFocus(ICSInputShell, edit);
5535 ICSInputBoxUp = True;
5537 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
5538 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
5542 void ICSInputSendText()
5549 edit = XtNameToWidget(ICSInputShell, "*form.text");
5551 XtSetArg(args[j], XtNstring, &val); j++;
5552 XtGetValues(edit, args, j);
5553 SendMultiLineToICS(val);
5554 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
5555 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
5558 void ICSInputBoxPopDown()
5563 if (!ICSInputBoxUp) return;
5565 XtPopdown(ICSInputShell);
5566 ICSInputBoxUp = False;
5568 XtSetArg(args[j], XtNleftBitmap, None); j++;
5569 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
5573 void CommentPopUp(title, text)
5580 if (commentShell == NULL) {
5582 CommentCreate(title, text, False, CommentCallback, 4);
5583 XtRealizeWidget(commentShell);
5584 CatchDeleteWindow(commentShell, "CommentPopDown");
5586 edit = XtNameToWidget(commentShell, "*form.text");
5588 XtSetArg(args[j], XtNstring, text); j++;
5589 XtSetValues(edit, args, j);
5591 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5592 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5593 XtSetValues(commentShell, args, j);
5596 XtPopup(commentShell, XtGrabNone);
5597 XSync(xDisplay, False);
5602 void AnalysisPopUp(title, text)
5609 if (analysisShell == NULL) {
5610 analysisShell = MiscCreate(title, text, False, NULL, 4);
5611 XtRealizeWidget(analysisShell);
5612 CatchDeleteWindow(analysisShell, "AnalysisPopDown");
5615 edit = XtNameToWidget(analysisShell, "*form.text");
5617 XtSetArg(args[j], XtNstring, text); j++;
5618 XtSetValues(edit, args, j);
5620 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5621 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5622 XtSetValues(analysisShell, args, j);
5626 XtPopup(analysisShell, XtGrabNone);
5628 XSync(xDisplay, False);
5633 void CommentCallback(w, client_data, call_data)
5635 XtPointer client_data, call_data;
5642 XtSetArg(args[j], XtNlabel, &name); j++;
5643 XtGetValues(w, args, j);
5645 if (strcmp(name, _("close")) == 0) {
5647 } else if (strcmp(name, _("edit")) == 0) {
5654 void CommentPopDown()
5659 if (!commentUp) return;
5661 XtSetArg(args[j], XtNx, &commentX); j++;
5662 XtSetArg(args[j], XtNy, &commentY); j++;
5663 XtSetArg(args[j], XtNwidth, &commentW); j++;
5664 XtSetArg(args[j], XtNheight, &commentH); j++;
5665 XtGetValues(commentShell, args, j);
5666 XtPopdown(commentShell);
5667 XSync(xDisplay, False);
5671 void AnalysisPopDown()
5673 if (!analysisUp) return;
5674 XtPopdown(analysisShell);
5675 XSync(xDisplay, False);
5677 if (appData.icsEngineAnalyze) ExitAnalyzeMode(); /* [DM] icsEngineAnalyze */
5681 void FileNamePopUp(label, def, proc, openMode)
5688 Widget popup, layout, dialog, edit;
5694 fileProc = proc; /* I can't see a way not */
5695 fileOpenMode = openMode; /* to use globals here */
5698 XtSetArg(args[i], XtNresizable, True); i++;
5699 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
5700 XtSetArg(args[i], XtNtitle, XtNewString(_("File name prompt"))); i++;
5701 fileNameShell = popup =
5702 XtCreatePopupShell("File name prompt", transientShellWidgetClass,
5703 shellWidget, args, i);
5706 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
5707 layoutArgs, XtNumber(layoutArgs));
5710 XtSetArg(args[i], XtNlabel, label); i++;
5711 XtSetArg(args[i], XtNvalue, def); i++;
5712 XtSetArg(args[i], XtNborderWidth, 0); i++;
5713 dialog = XtCreateManagedWidget("fileName", dialogWidgetClass,
5716 XawDialogAddButton(dialog, _("ok"), FileNameCallback, (XtPointer) dialog);
5717 XawDialogAddButton(dialog, _("cancel"), FileNameCallback,
5718 (XtPointer) dialog);
5720 XtRealizeWidget(popup);
5721 CatchDeleteWindow(popup, "FileNamePopDown");
5723 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
5724 &x, &y, &win_x, &win_y, &mask);
5726 XtSetArg(args[0], XtNx, x - 10);
5727 XtSetArg(args[1], XtNy, y - 30);
5728 XtSetValues(popup, args, 2);
5730 XtPopup(popup, XtGrabExclusive);
5733 edit = XtNameToWidget(dialog, "*value");
5734 XtSetKeyboardFocus(popup, edit);
5737 void FileNamePopDown()
5739 if (!filenameUp) return;
5740 XtPopdown(fileNameShell);
5741 XtDestroyWidget(fileNameShell);
5746 void FileNameCallback(w, client_data, call_data)
5748 XtPointer client_data, call_data;
5753 XtSetArg(args[0], XtNlabel, &name);
5754 XtGetValues(w, args, 1);
5756 if (strcmp(name, _("cancel")) == 0) {
5761 FileNameAction(w, NULL, NULL, NULL);
5764 void FileNameAction(w, event, prms, nprms)
5776 name = XawDialogGetValueString(w = XtParent(w));
5778 if ((name != NULL) && (*name != NULLCHAR)) {
5780 XtPopdown(w = XtParent(XtParent(w)));
5784 p = strrchr(buf, ' ');
5791 fullname = ExpandPathName(buf);
5793 ErrorPopUp(_("Error"), _("Can't open file"), FALSE);
5796 f = fopen(fullname, fileOpenMode);
5798 DisplayError(_("Failed to open file"), errno);
5800 (void) (*fileProc)(f, index, buf);
5807 XtPopdown(w = XtParent(XtParent(w)));
5813 void PromotionPopUp()
5816 Widget dialog, layout;
5818 Dimension bw_width, pw_width;
5822 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5823 XtGetValues(boardWidget, args, j);
5826 XtSetArg(args[j], XtNresizable, True); j++;
5827 XtSetArg(args[j], XtNtitle, XtNewString(_("Promotion"))); j++;
5829 XtCreatePopupShell("Promotion", transientShellWidgetClass,
5830 shellWidget, args, j);
5832 XtCreateManagedWidget(layoutName, formWidgetClass, promotionShell,
5833 layoutArgs, XtNumber(layoutArgs));
5836 XtSetArg(args[j], XtNlabel, _("Promote pawn to what?")); j++;
5837 XtSetArg(args[j], XtNborderWidth, 0); j++;
5838 dialog = XtCreateManagedWidget("promotion", dialogWidgetClass,
5841 XawDialogAddButton(dialog, _("Queen"), PromotionCallback,
5842 (XtPointer) dialog);
5843 XawDialogAddButton(dialog, _("Rook"), PromotionCallback,
5844 (XtPointer) dialog);
5845 XawDialogAddButton(dialog, _("Bishop"), PromotionCallback,
5846 (XtPointer) dialog);
5847 XawDialogAddButton(dialog, _("Knight"), PromotionCallback,
5848 (XtPointer) dialog);
5849 if (!appData.testLegality || gameInfo.variant == VariantSuicide ||
5850 gameInfo.variant == VariantGiveaway) {
5851 XawDialogAddButton(dialog, _("King"), PromotionCallback,
5852 (XtPointer) dialog);
5854 XawDialogAddButton(dialog, _("cancel"), PromotionCallback,
5855 (XtPointer) dialog);
5857 XtRealizeWidget(promotionShell);
5858 CatchDeleteWindow(promotionShell, "PromotionPopDown");
5861 XtSetArg(args[j], XtNwidth, &pw_width); j++;
5862 XtGetValues(promotionShell, args, j);
5864 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
5865 lineGap + squareSize/3 +
5866 ((toY == BOARD_HEIGHT-1) ^ (flipView) ?
5867 0 : 6*(squareSize + lineGap)), &x, &y);
5870 XtSetArg(args[j], XtNx, x); j++;
5871 XtSetArg(args[j], XtNy, y); j++;
5872 XtSetValues(promotionShell, args, j);
5874 XtPopup(promotionShell, XtGrabNone);
5879 void PromotionPopDown()
5881 if (!promotionUp) return;
5882 XtPopdown(promotionShell);
5883 XtDestroyWidget(promotionShell);
5884 promotionUp = False;
5887 void PromotionCallback(w, client_data, call_data)
5889 XtPointer client_data, call_data;
5895 XtSetArg(args[0], XtNlabel, &name);
5896 XtGetValues(w, args, 1);
5900 if (fromX == -1) return;
5902 if (strcmp(name, _("cancel")) == 0) {
5906 } else if (strcmp(name, _("Knight")) == 0) {
5909 promoChar = ToLower(name[0]);
5912 UserMoveEvent(fromX, fromY, toX, toY, promoChar);
5914 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
5915 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
5920 void ErrorCallback(w, client_data, call_data)
5922 XtPointer client_data, call_data;
5925 XtPopdown(w = XtParent(XtParent(XtParent(w))));
5927 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
5933 if (!errorUp) return;
5935 XtPopdown(errorShell);
5936 XtDestroyWidget(errorShell);
5937 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
5940 void ErrorPopUp(title, label, modal)
5941 char *title, *label;
5945 Widget dialog, layout;
5949 Dimension bw_width, pw_width;
5950 Dimension pw_height;
5954 XtSetArg(args[i], XtNresizable, True); i++;
5955 XtSetArg(args[i], XtNtitle, title); i++;
5957 XtCreatePopupShell("errorpopup", transientShellWidgetClass,
5958 shellWidget, args, i);
5960 XtCreateManagedWidget(layoutName, formWidgetClass, errorShell,
5961 layoutArgs, XtNumber(layoutArgs));
5964 XtSetArg(args[i], XtNlabel, label); i++;
5965 XtSetArg(args[i], XtNborderWidth, 0); i++;
5966 dialog = XtCreateManagedWidget("dialog", dialogWidgetClass,
5969 XawDialogAddButton(dialog, _("ok"), ErrorCallback, (XtPointer) dialog);
5971 XtRealizeWidget(errorShell);
5972 CatchDeleteWindow(errorShell, "ErrorPopDown");
5975 XtSetArg(args[i], XtNwidth, &bw_width); i++;
5976 XtGetValues(boardWidget, args, i);
5978 XtSetArg(args[i], XtNwidth, &pw_width); i++;
5979 XtSetArg(args[i], XtNheight, &pw_height); i++;
5980 XtGetValues(errorShell, args, i);
5983 /* This code seems to tickle an X bug if it is executed too soon
5984 after xboard starts up. The coordinates get transformed as if
5985 the main window was positioned at (0, 0).
5987 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
5988 0 - pw_height + squareSize / 3, &x, &y);
5990 XTranslateCoordinates(xDisplay, XtWindow(boardWidget),
5991 RootWindowOfScreen(XtScreen(boardWidget)),
5992 (bw_width - pw_width) / 2,
5993 0 - pw_height + squareSize / 3, &xx, &yy, &junk);
5997 if (y < 0) y = 0; /*avoid positioning top offscreen*/
6000 XtSetArg(args[i], XtNx, x); i++;
6001 XtSetArg(args[i], XtNy, y); i++;
6002 XtSetValues(errorShell, args, i);
6005 XtPopup(errorShell, modal ? XtGrabExclusive : XtGrabNone);
6008 /* Disable all user input other than deleting the window */
6009 static int frozen = 0;
6013 /* Grab by a widget that doesn't accept input */
6014 XtAddGrab(messageWidget, TRUE, FALSE);
6018 /* Undo a FreezeUI */
6021 if (!frozen) return;
6022 XtRemoveGrab(messageWidget);
6026 char *ModeToWidgetName(mode)
6030 case BeginningOfGame:
6031 if (appData.icsActive)
6032 return "menuMode.ICS Client";
6033 else if (appData.noChessProgram ||
6034 *appData.cmailGameName != NULLCHAR)
6035 return "menuMode.Edit Game";
6037 return "menuMode.Machine Black";
6038 case MachinePlaysBlack:
6039 return "menuMode.Machine Black";
6040 case MachinePlaysWhite:
6041 return "menuMode.Machine White";
6043 return "menuMode.Analysis Mode";
6045 return "menuMode.Analyze File";
6046 case TwoMachinesPlay:
6047 return "menuMode.Two Machines";
6049 return "menuMode.Edit Game";
6050 case PlayFromGameFile:
6051 return "menuFile.Load Game";
6053 return "menuMode.Edit Position";
6055 return "menuMode.Training";
6056 case IcsPlayingWhite:
6057 case IcsPlayingBlack:
6061 return "menuMode.ICS Client";
6068 void ModeHighlight()
6071 static int oldPausing = FALSE;
6072 static GameMode oldmode = (GameMode) -1;
6075 if (!boardWidget || !XtIsRealized(boardWidget)) return;
6077 if (pausing != oldPausing) {
6078 oldPausing = pausing;
6080 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6082 XtSetArg(args[0], XtNleftBitmap, None);
6084 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Pause"),
6087 if (appData.showButtonBar) {
6090 XtSetArg(args[0], XtNbackground, buttonForegroundPixel);
6091 XtSetArg(args[1], XtNforeground, buttonBackgroundPixel);
6093 XtSetArg(args[0], XtNbackground, buttonBackgroundPixel);
6094 XtSetArg(args[1], XtNforeground, buttonForegroundPixel);
6097 /* Always toggle, don't set. Previous code messes up when
6098 invoked while the button is pressed, as releasing it
6099 toggles the state again. */
6102 XtSetArg(args[0], XtNbackground, &oldbg);
6103 XtSetArg(args[1], XtNforeground, &oldfg);
6104 XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON),
6106 XtSetArg(args[0], XtNbackground, oldfg);
6107 XtSetArg(args[1], XtNforeground, oldbg);
6110 XtSetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
6114 wname = ModeToWidgetName(oldmode);
6115 if (wname != NULL) {
6116 XtSetArg(args[0], XtNleftBitmap, None);
6117 XtSetValues(XtNameToWidget(menuBarWidget, wname), args, 1);
6119 wname = ModeToWidgetName(gameMode);
6120 if (wname != NULL) {
6121 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6122 XtSetValues(XtNameToWidget(menuBarWidget, wname), args, 1);
6126 /* Maybe all the enables should be handled here, not just this one */
6127 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Training"),
6128 gameMode == Training || gameMode == PlayFromGameFile);
6133 * Button/menu procedures
6135 void ResetProc(w, event, prms, nprms)
6145 int LoadGamePopUp(f, gameNumber, title)
6150 cmailMsgLoaded = FALSE;
6151 if (gameNumber == 0) {
6152 int error = GameListBuild(f);
6154 DisplayError(_("Cannot build game list"), error);
6155 } else if (!ListEmpty(&gameList) &&
6156 ((ListGame *) gameList.tailPred)->number > 1) {
6157 GameListPopUp(f, title);
6163 return LoadGame(f, gameNumber, title, FALSE);
6166 void LoadGameProc(w, event, prms, nprms)
6172 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
6175 FileNamePopUp(_("Load game file name?"), "", LoadGamePopUp, "rb");
6178 void LoadNextGameProc(w, event, prms, nprms)
6187 void LoadPrevGameProc(w, event, prms, nprms)
6196 void ReloadGameProc(w, event, prms, nprms)
6205 void LoadNextPositionProc(w, event, prms, nprms)
6214 void LoadPrevPositionProc(w, event, prms, nprms)
6223 void ReloadPositionProc(w, event, prms, nprms)
6232 void LoadPositionProc(w, event, prms, nprms)
6238 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
6241 FileNamePopUp(_("Load position file name?"), "", LoadPosition, "rb");
6244 void SaveGameProc(w, event, prms, nprms)
6250 FileNamePopUp(_("Save game file name?"),
6251 DefaultFileName(appData.oldSaveStyle ? "game" : "pgn"),
6255 void SavePositionProc(w, event, prms, nprms)
6261 FileNamePopUp(_("Save position file name?"),
6262 DefaultFileName(appData.oldSaveStyle ? "pos" : "fen"),
6266 void ReloadCmailMsgProc(w, event, prms, nprms)
6272 ReloadCmailMsgEvent(FALSE);
6275 void MailMoveProc(w, event, prms, nprms)
6284 /* this variable is shared between CopyPositionProc and SendPositionSelection */
6285 static char *selected_fen_position=NULL;
6288 SendPositionSelection(Widget w, Atom *selection, Atom *target,
6289 Atom *type_return, XtPointer *value_return,
6290 unsigned long *length_return, int *format_return)
6292 char *selection_tmp;
6294 if (!selected_fen_position) return False; /* should never happen */
6295 if (*target == XA_STRING){
6296 /* note: since no XtSelectionDoneProc was registered, Xt will
6297 * automatically call XtFree on the value returned. So have to
6298 * make a copy of it allocated with XtMalloc */
6299 selection_tmp= XtMalloc(strlen(selected_fen_position)+16);
6300 strcpy(selection_tmp, selected_fen_position);
6302 *value_return=selection_tmp;
6303 *length_return=strlen(selection_tmp);
6304 *type_return=XA_STRING;
6305 *format_return = 8; /* bits per byte */
6312 /* note: when called from menu all parameters are NULL, so no clue what the
6313 * Widget which was clicked on was, or what the click event was
6315 void CopyPositionProc(w, event, prms, nprms)
6323 if (selected_fen_position) free(selected_fen_position);
6324 selected_fen_position = (char *)PositionToFEN(currentMove, NULL);
6325 if (!selected_fen_position) return;
6326 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
6328 SendPositionSelection,
6329 NULL/* lose_ownership_proc */ ,
6330 NULL/* transfer_done_proc */);
6332 free(selected_fen_position);
6333 selected_fen_position=NULL;
6337 /* function called when the data to Paste is ready */
6339 PastePositionCB(Widget w, XtPointer client_data, Atom *selection,
6340 Atom *type, XtPointer value, unsigned long *len, int *format)
6343 if (value==NULL || *len==0) return; /* nothing had been selected to copy */
6344 fenstr[*len]='\0'; /* normally this string is terminated, but be safe */
6345 EditPositionPasteFEN(fenstr);
6349 /* called when Paste Position button is pressed,
6350 * all parameters will be NULL */
6351 void PastePositionProc(w, event, prms, nprms)
6357 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
6358 /* (XtSelectionCallbackProc) */ PastePositionCB,
6359 NULL, /* client_data passed to PastePositionCB */
6361 /* better to use the time field from the event that triggered the
6362 * call to this function, but that isn't trivial to get
6370 SendGameSelection(Widget w, Atom *selection, Atom *target,
6371 Atom *type_return, XtPointer *value_return,
6372 unsigned long *length_return, int *format_return)
6374 char *selection_tmp;
6376 if (*target == XA_STRING){
6377 FILE* f = fopen(gameCopyFilename, "r");
6380 if (f == NULL) return False;
6384 selection_tmp = XtMalloc(len + 1);
6385 count = fread(selection_tmp, 1, len, f);
6387 XtFree(selection_tmp);
6390 selection_tmp[len] = NULLCHAR;
6391 *value_return = selection_tmp;
6392 *length_return = len;
6393 *type_return = XA_STRING;
6394 *format_return = 8; /* bits per byte */
6401 /* note: when called from menu all parameters are NULL, so no clue what the
6402 * Widget which was clicked on was, or what the click event was
6404 void CopyGameProc(w, event, prms, nprms)
6412 ret = SaveGameToFile(gameCopyFilename, FALSE);
6415 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
6418 NULL/* lose_ownership_proc */ ,
6419 NULL/* transfer_done_proc */);
6422 /* function called when the data to Paste is ready */
6424 PasteGameCB(Widget w, XtPointer client_data, Atom *selection,
6425 Atom *type, XtPointer value, unsigned long *len, int *format)
6428 if (value == NULL || *len == 0) {
6429 return; /* nothing had been selected to copy */
6431 f = fopen(gamePasteFilename, "w");
6433 DisplayError(_("Can't open temp file"), errno);
6436 fwrite(value, 1, *len, f);
6439 LoadGameFromFile(gamePasteFilename, 0, gamePasteFilename, TRUE);
6442 /* called when Paste Game button is pressed,
6443 * all parameters will be NULL */
6444 void PasteGameProc(w, event, prms, nprms)
6450 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
6451 /* (XtSelectionCallbackProc) */ PasteGameCB,
6452 NULL, /* client_data passed to PasteGameCB */
6454 /* better to use the time field from the event that triggered the
6455 * call to this function, but that isn't trivial to get
6465 SaveGameProc(NULL, NULL, NULL, NULL);
6469 void QuitProc(w, event, prms, nprms)
6478 void PauseProc(w, event, prms, nprms)
6488 void MachineBlackProc(w, event, prms, nprms)
6494 MachineBlackEvent();
6497 void MachineWhiteProc(w, event, prms, nprms)
6503 MachineWhiteEvent();
6506 void AnalyzeModeProc(w, event, prms, nprms)
6514 if (!first.analysisSupport) {
6515 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
6516 DisplayError(buf, 0);
6519 /* [DM] icsEngineAnalyze [HGM] This is horrible code; reverse the gameMode and isEngineAnalyze tests! */
6520 if (appData.icsActive) {
6521 if (gameMode != IcsObserving) {
6522 sprintf(buf,_("You are not observing a game"));
6523 DisplayError(buf, 0);
6525 if (appData.icsEngineAnalyze) {
6526 if (appData.debugMode)
6527 fprintf(debugFP, _("Found unexpected active ICS engine analyze \n"));
6533 /* if enable, use want disable icsEngineAnalyze */
6534 if (appData.icsEngineAnalyze) {
6539 appData.icsEngineAnalyze = TRUE;
6540 if (appData.debugMode)
6541 fprintf(debugFP, _("ICS engine analyze starting... \n"));
6543 if (!appData.showThinking)
6544 ShowThinkingProc(w,event,prms,nprms);
6549 void AnalyzeFileProc(w, event, prms, nprms)
6555 if (!first.analysisSupport) {
6557 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
6558 DisplayError(buf, 0);
6563 if (!appData.showThinking)
6564 ShowThinkingProc(w,event,prms,nprms);
6567 FileNamePopUp(_("File to analyze"), "", LoadGamePopUp, "rb");
6568 AnalysisPeriodicEvent(1);
6571 void TwoMachinesProc(w, event, prms, nprms)
6580 void IcsClientProc(w, event, prms, nprms)
6589 void EditGameProc(w, event, prms, nprms)
6598 void EditPositionProc(w, event, prms, nprms)
6604 EditPositionEvent();
6607 void TrainingProc(w, event, prms, nprms)
6616 void EditCommentProc(w, event, prms, nprms)
6623 EditCommentPopDown();
6629 void IcsInputBoxProc(w, event, prms, nprms)
6635 if (ICSInputBoxUp) {
6636 ICSInputBoxPopDown();
6642 void AcceptProc(w, event, prms, nprms)
6651 void DeclineProc(w, event, prms, nprms)
6660 void RematchProc(w, event, prms, nprms)
6669 void CallFlagProc(w, event, prms, nprms)
6678 void DrawProc(w, event, prms, nprms)
6687 void AbortProc(w, event, prms, nprms)
6696 void AdjournProc(w, event, prms, nprms)
6705 void ResignProc(w, event, prms, nprms)
6714 void AdjuWhiteProc(w, event, prms, nprms)
6720 UserAdjudicationEvent(+1);
6723 void AdjuBlackProc(w, event, prms, nprms)
6729 UserAdjudicationEvent(-1);
6732 void AdjuDrawProc(w, event, prms, nprms)
6738 UserAdjudicationEvent(0);
6741 void EnterKeyProc(w, event, prms, nprms)
6747 if (ICSInputBoxUp == True)
6751 void StopObservingProc(w, event, prms, nprms)
6757 StopObservingEvent();
6760 void StopExaminingProc(w, event, prms, nprms)
6766 StopExaminingEvent();
6770 void ForwardProc(w, event, prms, nprms)
6780 void BackwardProc(w, event, prms, nprms)
6789 void ToStartProc(w, event, prms, nprms)
6798 void ToEndProc(w, event, prms, nprms)
6807 void RevertProc(w, event, prms, nprms)
6816 void TruncateGameProc(w, event, prms, nprms)
6822 TruncateGameEvent();
6824 void RetractMoveProc(w, event, prms, nprms)
6833 void MoveNowProc(w, event, prms, nprms)
6843 void AlwaysQueenProc(w, event, prms, nprms)
6851 appData.alwaysPromoteToQueen = !appData.alwaysPromoteToQueen;
6853 if (appData.alwaysPromoteToQueen) {
6854 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6856 XtSetArg(args[0], XtNleftBitmap, None);
6858 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
6862 void AnimateDraggingProc(w, event, prms, nprms)
6870 appData.animateDragging = !appData.animateDragging;
6872 if (appData.animateDragging) {
6873 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6876 XtSetArg(args[0], XtNleftBitmap, None);
6878 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Dragging"),
6882 void AnimateMovingProc(w, event, prms, nprms)
6890 appData.animate = !appData.animate;
6892 if (appData.animate) {
6893 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6896 XtSetArg(args[0], XtNleftBitmap, None);
6898 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
6902 void AutocommProc(w, event, prms, nprms)
6910 appData.autoComment = !appData.autoComment;
6912 if (appData.autoComment) {
6913 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6915 XtSetArg(args[0], XtNleftBitmap, None);
6917 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
6922 void AutoflagProc(w, event, prms, nprms)
6930 appData.autoCallFlag = !appData.autoCallFlag;
6932 if (appData.autoCallFlag) {
6933 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6935 XtSetArg(args[0], XtNleftBitmap, None);
6937 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
6941 void AutoflipProc(w, event, prms, nprms)
6949 appData.autoFlipView = !appData.autoFlipView;
6951 if (appData.autoFlipView) {
6952 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6954 XtSetArg(args[0], XtNleftBitmap, None);
6956 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flip View"),
6960 void AutobsProc(w, event, prms, nprms)
6968 appData.autoObserve = !appData.autoObserve;
6970 if (appData.autoObserve) {
6971 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6973 XtSetArg(args[0], XtNleftBitmap, None);
6975 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
6979 void AutoraiseProc(w, event, prms, nprms)
6987 appData.autoRaiseBoard = !appData.autoRaiseBoard;
6989 if (appData.autoRaiseBoard) {
6990 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6992 XtSetArg(args[0], XtNleftBitmap, None);
6994 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Raise Board"),
6998 void AutosaveProc(w, event, prms, nprms)
7006 appData.autoSaveGames = !appData.autoSaveGames;
7008 if (appData.autoSaveGames) {
7009 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7011 XtSetArg(args[0], XtNleftBitmap, None);
7013 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
7017 void BlindfoldProc(w, event, prms, nprms)
7025 appData.blindfold = !appData.blindfold;
7027 if (appData.blindfold) {
7028 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7030 XtSetArg(args[0], XtNleftBitmap, None);
7032 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Blindfold"),
7035 DrawPosition(True, NULL);
7038 void TestLegalityProc(w, event, prms, nprms)
7046 appData.testLegality = !appData.testLegality;
7048 if (appData.testLegality) {
7049 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7051 XtSetArg(args[0], XtNleftBitmap, None);
7053 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Test Legality"),
7058 void FlashMovesProc(w, event, prms, nprms)
7066 if (appData.flashCount == 0) {
7067 appData.flashCount = 3;
7069 appData.flashCount = -appData.flashCount;
7072 if (appData.flashCount > 0) {
7073 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7075 XtSetArg(args[0], XtNleftBitmap, None);
7077 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flash Moves"),
7081 void FlipViewProc(w, event, prms, nprms)
7087 flipView = !flipView;
7088 DrawPosition(True, NULL);
7091 void GetMoveListProc(w, event, prms, nprms)
7099 appData.getMoveList = !appData.getMoveList;
7101 if (appData.getMoveList) {
7102 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7105 XtSetArg(args[0], XtNleftBitmap, None);
7107 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
7112 void HighlightDraggingProc(w, event, prms, nprms)
7120 appData.highlightDragging = !appData.highlightDragging;
7122 if (appData.highlightDragging) {
7123 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7125 XtSetArg(args[0], XtNleftBitmap, None);
7127 XtSetValues(XtNameToWidget(menuBarWidget,
7128 "menuOptions.Highlight Dragging"), args, 1);
7132 void HighlightLastMoveProc(w, event, prms, nprms)
7140 appData.highlightLastMove = !appData.highlightLastMove;
7142 if (appData.highlightLastMove) {
7143 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7145 XtSetArg(args[0], XtNleftBitmap, None);
7147 XtSetValues(XtNameToWidget(menuBarWidget,
7148 "menuOptions.Highlight Last Move"), args, 1);
7151 void IcsAlarmProc(w, event, prms, nprms)
7159 appData.icsAlarm = !appData.icsAlarm;
7161 if (appData.icsAlarm) {
7162 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7164 XtSetArg(args[0], XtNleftBitmap, None);
7166 XtSetValues(XtNameToWidget(menuBarWidget,
7167 "menuOptions.ICS Alarm"), args, 1);
7170 void MoveSoundProc(w, event, prms, nprms)
7178 appData.ringBellAfterMoves = !appData.ringBellAfterMoves;
7180 if (appData.ringBellAfterMoves) {
7181 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7183 XtSetArg(args[0], XtNleftBitmap, None);
7185 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
7190 void OldSaveStyleProc(w, event, prms, nprms)
7198 appData.oldSaveStyle = !appData.oldSaveStyle;
7200 if (appData.oldSaveStyle) {
7201 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7203 XtSetArg(args[0], XtNleftBitmap, None);
7205 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Old Save Style"),
7209 void PeriodicUpdatesProc(w, event, prms, nprms)
7217 PeriodicUpdatesEvent(!appData.periodicUpdates);
7219 if (appData.periodicUpdates) {
7220 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7222 XtSetArg(args[0], XtNleftBitmap, None);
7224 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Periodic Updates"),
7228 void PonderNextMoveProc(w, event, prms, nprms)
7236 PonderNextMoveEvent(!appData.ponderNextMove);
7238 if (appData.ponderNextMove) {
7239 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7241 XtSetArg(args[0], XtNleftBitmap, None);
7243 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Ponder Next Move"),
7247 void PopupExitMessageProc(w, event, prms, nprms)
7255 appData.popupExitMessage = !appData.popupExitMessage;
7257 if (appData.popupExitMessage) {
7258 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7260 XtSetArg(args[0], XtNleftBitmap, None);
7262 XtSetValues(XtNameToWidget(menuBarWidget,
7263 "menuOptions.Popup Exit Message"), args, 1);
7266 void PopupMoveErrorsProc(w, event, prms, nprms)
7274 appData.popupMoveErrors = !appData.popupMoveErrors;
7276 if (appData.popupMoveErrors) {
7277 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7279 XtSetArg(args[0], XtNleftBitmap, None);
7281 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Popup Move Errors"),
7285 void PremoveProc(w, event, prms, nprms)
7293 appData.premove = !appData.premove;
7295 if (appData.premove) {
7296 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7298 XtSetArg(args[0], XtNleftBitmap, None);
7300 XtSetValues(XtNameToWidget(menuBarWidget,
7301 "menuOptions.Premove"), args, 1);
7304 void QuietPlayProc(w, event, prms, nprms)
7312 appData.quietPlay = !appData.quietPlay;
7314 if (appData.quietPlay) {
7315 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7317 XtSetArg(args[0], XtNleftBitmap, None);
7319 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Quiet Play"),
7323 void ShowCoordsProc(w, event, prms, nprms)
7331 appData.showCoords = !appData.showCoords;
7333 if (appData.showCoords) {
7334 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7336 XtSetArg(args[0], XtNleftBitmap, None);
7338 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
7341 DrawPosition(True, NULL);
7344 void ShowThinkingProc(w, event, prms, nprms)
7352 appData.showThinking = !appData.showThinking; // [HGM] thinking: tken out of ShowThinkingEvent
7353 ShowThinkingEvent();
7355 // [HGM] thinking: currently no suc menu item; replaced by Hide Thinking (From Human)
7356 if (appData.showThinking) {
7357 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7359 XtSetArg(args[0], XtNleftBitmap, None);
7361 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Thinking"),
7366 void HideThinkingProc(w, event, prms, nprms)
7374 appData.hideThinkingFromHuman = !appData.hideThinkingFromHuman; // [HGM] thinking: tken out of ShowThinkingEvent
7375 ShowThinkingEvent();
7377 if (appData.hideThinkingFromHuman) {
7378 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7380 XtSetArg(args[0], XtNleftBitmap, None);
7382 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
7386 void InfoProc(w, event, prms, nprms)
7393 snprintf(buf, sizeof(buf), "xterm -e info --directory %s --directory . -f %s &",
7398 void ManProc(w, event, prms, nprms)
7406 if (nprms && *nprms > 0)
7410 snprintf(buf, sizeof(buf), "xterm -e man %s &", name);
7414 void HintProc(w, event, prms, nprms)
7423 void BookProc(w, event, prms, nprms)
7432 void AboutProc(w, event, prms, nprms)
7440 char *zippy = " (with Zippy code)";
7444 snprintf(buf, sizeof(buf), "%s%s\n\n%s\n%s\n%s\n\n%s%s\n%s",
7445 programVersion, zippy,
7446 "Copyright 1991 Digital Equipment Corporation",
7447 "Enhancements Copyright 1992-2009 Free Software Foundation",
7448 "Enhancements Copyright 2005 Alessandro Scotti",
7449 PRODUCT, " is free software and carries NO WARRANTY;",
7450 "see the file COPYING for more information.");
7451 ErrorPopUp(_("About XBoard"), buf, FALSE);
7454 void DebugProc(w, event, prms, nprms)
7460 appData.debugMode = !appData.debugMode;
7463 void AboutGameProc(w, event, prms, nprms)
7472 void NothingProc(w, event, prms, nprms)
7481 void Iconify(w, event, prms, nprms)
7490 XtSetArg(args[0], XtNiconic, True);
7491 XtSetValues(shellWidget, args, 1);
7494 void DisplayMessage(message, extMessage)
7495 char *message, *extMessage;
7502 snprintf(buf, sizeof(buf), "%s %s", message, extMessage);
7505 message = extMessage;
7508 XtSetArg(arg, XtNlabel, message);
7509 XtSetValues(messageWidget, &arg, 1);
7512 void DisplayTitle(text)
7517 char title[MSG_SIZ];
7520 if (text == NULL) text = "";
7522 if (appData.titleInWindow) {
7524 XtSetArg(args[i], XtNlabel, text); i++;
7525 XtSetValues(titleWidget, args, i);
7528 if (*text != NULLCHAR) {
7530 strcpy(title, text);
7531 } else if (appData.icsActive) {
7532 snprintf(icon, sizeof(icon), "%s", appData.icsHost);
7533 snprintf(title, sizeof(title),"%s: %s", programName, appData.icsHost);
7534 } else if (appData.cmailGameName[0] != NULLCHAR) {
7535 snprintf(icon, sizeof(icon), "%s", "CMail");
7536 snprintf(title,sizeof(title), "%s: %s", programName, "CMail");
7538 // [HGM] license: This stuff should really be done in back-end, but WinBoard already had a pop-up for it
7539 } else if (gameInfo.variant == VariantGothic) {
7540 strcpy(icon, programName);
7541 strcpy(title, GOTHIC);
7544 } else if (gameInfo.variant == VariantFalcon) {
7545 strcpy(icon, programName);
7546 strcpy(title, FALCON);
7548 } else if (appData.noChessProgram) {
7549 strcpy(icon, programName);
7550 strcpy(title, programName);
7552 strcpy(icon, first.tidy);
7553 snprintf(title,sizeof(title), "%s: %s", programName, first.tidy);
7556 XtSetArg(args[i], XtNiconName, (XtArgVal) icon); i++;
7557 XtSetArg(args[i], XtNtitle, (XtArgVal) title); i++;
7558 XtSetValues(shellWidget, args, i);
7562 void DisplayError(message, error)
7569 if (appData.debugMode || appData.matchMode) {
7570 fprintf(stderr, "%s: %s\n", programName, message);
7573 if (appData.debugMode || appData.matchMode) {
7574 fprintf(stderr, "%s: %s: %s\n",
7575 programName, message, strerror(error));
7577 snprintf(buf,sizeof(buf), "%s: %s", message, strerror(error));
7580 ErrorPopUp(_("Error"), message, FALSE);
7584 void DisplayMoveError(message)
7589 DrawPosition(FALSE, NULL);
7590 if (appData.debugMode || appData.matchMode) {
7591 fprintf(stderr, "%s: %s\n", programName, message);
7593 if (appData.popupMoveErrors) {
7594 ErrorPopUp(_("Error"), message, FALSE);
7596 DisplayMessage(message, "");
7601 void DisplayFatalError(message, error, status)
7607 errorExitStatus = status;
7609 fprintf(stderr, "%s: %s\n", programName, message);
7611 fprintf(stderr, "%s: %s: %s\n",
7612 programName, message, strerror(error));
7613 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
7616 if (appData.popupExitMessage && boardWidget && XtIsRealized(boardWidget)) {
7617 ErrorPopUp(status ? _("Fatal Error") : _("Exiting"), message, TRUE);
7623 void DisplayInformation(message)
7627 ErrorPopUp(_("Information"), message, TRUE);
7630 void DisplayNote(message)
7634 ErrorPopUp(_("Note"), message, FALSE);
7638 NullXErrorCheck(dpy, error_event)
7640 XErrorEvent *error_event;
7645 void DisplayIcsInteractionTitle(message)
7648 if (oldICSInteractionTitle == NULL) {
7649 /* Magic to find the old window title, adapted from vim */
7650 char *wina = getenv("WINDOWID");
7652 Window win = (Window) atoi(wina);
7653 Window root, parent, *children;
7654 unsigned int nchildren;
7655 int (*oldHandler)() = XSetErrorHandler(NullXErrorCheck);
7657 if (XFetchName(xDisplay, win, &oldICSInteractionTitle)) break;
7658 if (!XQueryTree(xDisplay, win, &root, &parent,
7659 &children, &nchildren)) break;
7660 if (children) XFree((void *)children);
7661 if (parent == root || parent == 0) break;
7664 XSetErrorHandler(oldHandler);
7666 if (oldICSInteractionTitle == NULL) {
7667 oldICSInteractionTitle = "xterm";
7670 printf("\033]0;%s\007", message);
7674 char pendingReplyPrefix[MSG_SIZ];
7675 ProcRef pendingReplyPR;
7677 void AskQuestionProc(w, event, prms, nprms)
7684 fprintf(stderr, _("AskQuestionProc needed 4 parameters, got %d\n"),
7688 AskQuestionEvent(prms[0], prms[1], prms[2], prms[3]);
7691 void AskQuestionPopDown()
7693 if (!askQuestionUp) return;
7694 XtPopdown(askQuestionShell);
7695 XtDestroyWidget(askQuestionShell);
7696 askQuestionUp = False;
7699 void AskQuestionReplyAction(w, event, prms, nprms)
7709 reply = XawDialogGetValueString(w = XtParent(w));
7710 strcpy(buf, pendingReplyPrefix);
7711 if (*buf) strcat(buf, " ");
7714 OutputToProcess(pendingReplyPR, buf, strlen(buf), &err);
7715 AskQuestionPopDown();
7717 if (err) DisplayFatalError(_("Error writing to chess program"), err, 0);
7720 void AskQuestionCallback(w, client_data, call_data)
7722 XtPointer client_data, call_data;
7727 XtSetArg(args[0], XtNlabel, &name);
7728 XtGetValues(w, args, 1);
7730 if (strcmp(name, _("cancel")) == 0) {
7731 AskQuestionPopDown();
7733 AskQuestionReplyAction(w, NULL, NULL, NULL);
7737 void AskQuestion(title, question, replyPrefix, pr)
7738 char *title, *question, *replyPrefix;
7742 Widget popup, layout, dialog, edit;
7748 strcpy(pendingReplyPrefix, replyPrefix);
7749 pendingReplyPR = pr;
7752 XtSetArg(args[i], XtNresizable, True); i++;
7753 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
7754 askQuestionShell = popup =
7755 XtCreatePopupShell(title, transientShellWidgetClass,
7756 shellWidget, args, i);
7759 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
7760 layoutArgs, XtNumber(layoutArgs));
7763 XtSetArg(args[i], XtNlabel, question); i++;
7764 XtSetArg(args[i], XtNvalue, ""); i++;
7765 XtSetArg(args[i], XtNborderWidth, 0); i++;
7766 dialog = XtCreateManagedWidget("question", dialogWidgetClass,
7769 XawDialogAddButton(dialog, _("enter"), AskQuestionCallback,
7770 (XtPointer) dialog);
7771 XawDialogAddButton(dialog, _("cancel"), AskQuestionCallback,
7772 (XtPointer) dialog);
7774 XtRealizeWidget(popup);
7775 CatchDeleteWindow(popup, "AskQuestionPopDown");
7777 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
7778 &x, &y, &win_x, &win_y, &mask);
7780 XtSetArg(args[0], XtNx, x - 10);
7781 XtSetArg(args[1], XtNy, y - 30);
7782 XtSetValues(popup, args, 2);
7784 XtPopup(popup, XtGrabExclusive);
7785 askQuestionUp = True;
7787 edit = XtNameToWidget(dialog, "*value");
7788 XtSetKeyboardFocus(popup, edit);
7796 if (*name == NULLCHAR) {
7798 } else if (strcmp(name, "$") == 0) {
7799 putc(BELLCHAR, stderr);
7802 snprintf(buf, sizeof(buf), "%s '%s' &", appData.soundProgram, name);
7810 PlaySound(appData.soundMove);
7816 PlaySound(appData.soundIcsWin);
7822 PlaySound(appData.soundIcsLoss);
7828 PlaySound(appData.soundIcsDraw);
7832 PlayIcsUnfinishedSound()
7834 PlaySound(appData.soundIcsUnfinished);
7840 PlaySound(appData.soundIcsAlarm);
7846 system("stty echo");
7852 system("stty -echo");
7856 Colorize(cc, continuation)
7861 int count, outCount, error;
7863 if (textColors[(int)cc].bg > 0) {
7864 if (textColors[(int)cc].fg > 0) {
7865 sprintf(buf, "\033[0;%d;%d;%dm", textColors[(int)cc].attr,
7866 textColors[(int)cc].fg, textColors[(int)cc].bg);
7868 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
7869 textColors[(int)cc].bg);
7872 if (textColors[(int)cc].fg > 0) {
7873 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
7874 textColors[(int)cc].fg);
7876 sprintf(buf, "\033[0;%dm", textColors[(int)cc].attr);
7879 count = strlen(buf);
7880 outCount = OutputToProcess(NoProc, buf, count, &error);
7881 if (outCount < count) {
7882 DisplayFatalError(_("Error writing to display"), error, 1);
7885 if (continuation) return;
7888 PlaySound(appData.soundShout);
7891 PlaySound(appData.soundSShout);
7894 PlaySound(appData.soundChannel1);
7897 PlaySound(appData.soundChannel);
7900 PlaySound(appData.soundKibitz);
7903 PlaySound(appData.soundTell);
7905 case ColorChallenge:
7906 PlaySound(appData.soundChallenge);
7909 PlaySound(appData.soundRequest);
7912 PlaySound(appData.soundSeek);
7923 return getpwuid(getuid())->pw_name;
7926 static char *ExpandPathName(path)
7929 static char static_buf[2000];
7930 char *d, *s, buf[2000];
7936 while (*s && isspace(*s))
7945 if (*(s+1) == '/') {
7946 strcpy(d, getpwuid(getuid())->pw_dir);
7951 *strchr(buf, '/') = 0;
7952 pwd = getpwnam(buf);
7955 fprintf(stderr, _("ERROR: Unknown user %s (in path %s)\n"),
7959 strcpy(d, pwd->pw_dir);
7960 strcat(d, strchr(s+1, '/'));
7971 static char host_name[MSG_SIZ];
7973 #if HAVE_GETHOSTNAME
7974 gethostname(host_name, MSG_SIZ);
7976 #else /* not HAVE_GETHOSTNAME */
7977 # if HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H
7978 sysinfo(SI_HOSTNAME, host_name, MSG_SIZ);
7980 # else /* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
7982 # endif/* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
7983 #endif /* not HAVE_GETHOSTNAME */
7986 XtIntervalId delayedEventTimerXID = 0;
7987 DelayedEventCallback delayedEventCallback = 0;
7992 delayedEventTimerXID = 0;
7993 delayedEventCallback();
7997 ScheduleDelayedEvent(cb, millisec)
7998 DelayedEventCallback cb; long millisec;
8000 delayedEventCallback = cb;
8001 delayedEventTimerXID =
8002 XtAppAddTimeOut(appContext, millisec,
8003 (XtTimerCallbackProc) FireDelayedEvent, (XtPointer) 0);
8006 DelayedEventCallback
8009 if (delayedEventTimerXID) {
8010 return delayedEventCallback;
8017 CancelDelayedEvent()
8019 if (delayedEventTimerXID) {
8020 XtRemoveTimeOut(delayedEventTimerXID);
8021 delayedEventTimerXID = 0;
8025 XtIntervalId loadGameTimerXID = 0;
8027 int LoadGameTimerRunning()
8029 return loadGameTimerXID != 0;
8032 int StopLoadGameTimer()
8034 if (loadGameTimerXID != 0) {
8035 XtRemoveTimeOut(loadGameTimerXID);
8036 loadGameTimerXID = 0;
8044 LoadGameTimerCallback(arg, id)
8048 loadGameTimerXID = 0;
8053 StartLoadGameTimer(millisec)
8057 XtAppAddTimeOut(appContext, millisec,
8058 (XtTimerCallbackProc) LoadGameTimerCallback,
8062 XtIntervalId analysisClockXID = 0;
8065 AnalysisClockCallback(arg, id)
8069 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile
8070 || appData.icsEngineAnalyze) { // [DM]
8071 AnalysisPeriodicEvent(0);
8072 StartAnalysisClock();
8077 StartAnalysisClock()
8080 XtAppAddTimeOut(appContext, 2000,
8081 (XtTimerCallbackProc) AnalysisClockCallback,
8085 XtIntervalId clockTimerXID = 0;
8087 int ClockTimerRunning()
8089 return clockTimerXID != 0;
8092 int StopClockTimer()
8094 if (clockTimerXID != 0) {
8095 XtRemoveTimeOut(clockTimerXID);
8104 ClockTimerCallback(arg, id)
8113 StartClockTimer(millisec)
8117 XtAppAddTimeOut(appContext, millisec,
8118 (XtTimerCallbackProc) ClockTimerCallback,
8123 DisplayTimerLabel(w, color, timer, highlight)
8132 Pixel foregroundOrWarningColor = timerForegroundPixel;
8135 && appData.lowTimeWarning
8136 && (timer / 1000) < appData.icsAlarmTime)
8138 foregroundOrWarningColor = lowTimeWarningColor;
8140 if (appData.clockMode) {
8141 sprintf(buf, "%s: %s", color, TimeString(timer));
8142 XtSetArg(args[0], XtNlabel, buf);
8144 sprintf(buf, "%s ", color);
8145 XtSetArg(args[0], XtNlabel, buf);
8150 XtSetArg(args[1], XtNbackground, foregroundOrWarningColor);
8151 XtSetArg(args[2], XtNforeground, timerBackgroundPixel);
8153 XtSetArg(args[1], XtNbackground, timerBackgroundPixel);
8154 XtSetArg(args[2], XtNforeground, foregroundOrWarningColor);
8157 XtSetValues(w, args, 3);
8161 DisplayWhiteClock(timeRemaining, highlight)
8167 if(appData.noGUI) return;
8168 DisplayTimerLabel(whiteTimerWidget, _("White"), timeRemaining, highlight);
8169 if (highlight && iconPixmap == bIconPixmap) {
8170 iconPixmap = wIconPixmap;
8171 XtSetArg(args[0], XtNiconPixmap, iconPixmap);
8172 XtSetValues(shellWidget, args, 1);
8177 DisplayBlackClock(timeRemaining, highlight)
8183 if(appData.noGUI) return;
8184 DisplayTimerLabel(blackTimerWidget, _("Black"), timeRemaining, highlight);
8185 if (highlight && iconPixmap == wIconPixmap) {
8186 iconPixmap = bIconPixmap;
8187 XtSetArg(args[0], XtNiconPixmap, iconPixmap);
8188 XtSetValues(shellWidget, args, 1);
8206 int StartChildProcess(cmdLine, dir, pr)
8213 int to_prog[2], from_prog[2];
8217 if (appData.debugMode) {
8218 fprintf(stderr, "StartChildProcess (dir=\"%s\") %s\n",dir, cmdLine);
8221 /* We do NOT feed the cmdLine to the shell; we just
8222 parse it into blank-separated arguments in the
8223 most simple-minded way possible.
8226 strcpy(buf, cmdLine);
8231 if (p == NULL) break;
8236 SetUpChildIO(to_prog, from_prog);
8238 if ((pid = fork()) == 0) {
8240 // [HGM] PSWBTM: made order resistant against case where fd of created pipe was 0 or 1
8241 close(to_prog[1]); // first close the unused pipe ends
8242 close(from_prog[0]);
8243 dup2(to_prog[0], 0); // to_prog was created first, nd is the only one to use 0 or 1
8244 dup2(from_prog[1], 1);
8245 if(to_prog[0] >= 2) close(to_prog[0]); // if 0 or 1, the dup2 already cosed the original
8246 close(from_prog[1]); // and closing again loses one of the pipes!
8247 if(fileno(stderr) >= 2) // better safe than sorry...
8248 dup2(1, fileno(stderr)); /* force stderr to the pipe */
8250 if (dir[0] != NULLCHAR && chdir(dir) != 0) {
8255 nice(appData.niceEngines); // [HGM] nice: adjust priority of engine proc
8257 execvp(argv[0], argv);
8259 /* If we get here, exec failed */
8264 /* Parent process */
8266 close(from_prog[1]);
8268 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8271 cp->fdFrom = from_prog[0];
8272 cp->fdTo = to_prog[1];
8277 // [HGM] kill: implement the 'hard killing' of AS's Winboard_x
8278 static RETSIGTYPE AlarmCallBack(int n)
8284 DestroyChildProcess(pr, signalType)
8288 ChildProc *cp = (ChildProc *) pr;
8290 if (cp->kind != CPReal) return;
8292 if (signalType == 10) { // [HGM] kill: if it does not terminate in 3 sec, kill
8293 signal(SIGALRM, AlarmCallBack);
8295 if(wait((int *) 0) == -1) { // process does not terminate on its own accord
8296 kill(cp->pid, SIGKILL); // kill it forcefully
8297 wait((int *) 0); // and wait again
8301 kill(cp->pid, signalType == 9 ? SIGKILL : SIGTERM); // [HGM] kill: use hard kill if so requested
8303 /* Process is exiting either because of the kill or because of
8304 a quit command sent by the backend; either way, wait for it to die.
8313 InterruptChildProcess(pr)
8316 ChildProc *cp = (ChildProc *) pr;
8318 if (cp->kind != CPReal) return;
8319 (void) kill(cp->pid, SIGINT); /* stop it thinking */
8322 int OpenTelnet(host, port, pr)
8327 char cmdLine[MSG_SIZ];
8329 if (port[0] == NULLCHAR) {
8330 snprintf(cmdLine, sizeof(cmdLine), "%s %s", appData.telnetProgram, host);
8332 snprintf(cmdLine,sizeof(cmdLine), "%s %s %s", appData.telnetProgram, host, port);
8334 return StartChildProcess(cmdLine, "", pr);
8337 int OpenTCP(host, port, pr)
8343 DisplayFatalError(_("Socket support is not configured in"), 0, 2);
8344 #else /* !OMIT_SOCKETS */
8346 struct sockaddr_in sa;
8348 unsigned short uport;
8351 if ((s = socket(AF_INET, SOCK_STREAM, 6)) < 0) {
8355 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
8356 sa.sin_family = AF_INET;
8357 sa.sin_addr.s_addr = INADDR_ANY;
8358 uport = (unsigned short) 0;
8359 sa.sin_port = htons(uport);
8360 if (bind(s, (struct sockaddr *) &sa, sizeof(struct sockaddr_in)) < 0) {
8364 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
8365 if (!(hp = gethostbyname(host))) {
8367 if (sscanf(host, "%d.%d.%d.%d", &b0, &b1, &b2, &b3) == 4) {
8368 hp = (struct hostent *) calloc(1, sizeof(struct hostent));
8369 hp->h_addrtype = AF_INET;
8371 hp->h_addr_list = (char **) calloc(2, sizeof(char *));
8372 hp->h_addr_list[0] = (char *) malloc(4);
8373 hp->h_addr_list[0][0] = b0;
8374 hp->h_addr_list[0][1] = b1;
8375 hp->h_addr_list[0][2] = b2;
8376 hp->h_addr_list[0][3] = b3;
8381 sa.sin_family = hp->h_addrtype;
8382 uport = (unsigned short) atoi(port);
8383 sa.sin_port = htons(uport);
8384 memcpy((char *) &sa.sin_addr, hp->h_addr, hp->h_length);
8386 if (connect(s, (struct sockaddr *) &sa,
8387 sizeof(struct sockaddr_in)) < 0) {
8391 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8398 #endif /* !OMIT_SOCKETS */
8403 int OpenCommPort(name, pr)
8410 fd = open(name, 2, 0);
8411 if (fd < 0) return errno;
8413 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8423 int OpenLoopback(pr)
8429 SetUpChildIO(to, from);
8431 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8434 cp->fdFrom = to[0]; /* note not from[0]; we are doing a loopback */
8441 int OpenRcmd(host, user, cmd, pr)
8442 char *host, *user, *cmd;
8445 DisplayFatalError(_("internal rcmd not implemented for Unix"), 0, 1);
8449 #define INPUT_SOURCE_BUF_SIZE 8192
8458 char buf[INPUT_SOURCE_BUF_SIZE];
8463 DoInputCallback(closure, source, xid)
8468 InputSource *is = (InputSource *) closure;
8473 if (is->lineByLine) {
8474 count = read(is->fd, is->unused,
8475 INPUT_SOURCE_BUF_SIZE - (is->unused - is->buf));
8477 (is->func)(is, is->closure, is->buf, count, count ? errno : 0);
8480 is->unused += count;
8482 while (p < is->unused) {
8483 q = memchr(p, '\n', is->unused - p);
8484 if (q == NULL) break;
8486 (is->func)(is, is->closure, p, q - p, 0);
8490 while (p < is->unused) {
8495 count = read(is->fd, is->buf, INPUT_SOURCE_BUF_SIZE);
8500 (is->func)(is, is->closure, is->buf, count, error);
8504 InputSourceRef AddInputSource(pr, lineByLine, func, closure)
8511 ChildProc *cp = (ChildProc *) pr;
8513 is = (InputSource *) calloc(1, sizeof(InputSource));
8514 is->lineByLine = lineByLine;
8518 is->fd = fileno(stdin);
8520 is->kind = cp->kind;
8521 is->fd = cp->fdFrom;
8524 is->unused = is->buf;
8527 is->xid = XtAppAddInput(appContext, is->fd,
8528 (XtPointer) (XtInputReadMask),
8529 (XtInputCallbackProc) DoInputCallback,
8531 is->closure = closure;
8532 return (InputSourceRef) is;
8536 RemoveInputSource(isr)
8539 InputSource *is = (InputSource *) isr;
8541 if (is->xid == 0) return;
8542 XtRemoveInput(is->xid);
8546 int OutputToProcess(pr, message, count, outError)
8552 ChildProc *cp = (ChildProc *) pr;
8556 outCount = fwrite(message, 1, count, stdout);
8558 outCount = write(cp->fdTo, message, count);
8568 /* Output message to process, with "ms" milliseconds of delay
8569 between each character. This is needed when sending the logon
8570 script to ICC, which for some reason doesn't like the
8571 instantaneous send. */
8572 int OutputToProcessDelayed(pr, message, count, outError, msdelay)
8579 ChildProc *cp = (ChildProc *) pr;
8584 r = write(cp->fdTo, message++, 1);
8597 /**** Animation code by Hugh Fisher, DCS, ANU.
8599 Known problem: if a window overlapping the board is
8600 moved away while a piece is being animated underneath,
8601 the newly exposed area won't be updated properly.
8602 I can live with this.
8604 Known problem: if you look carefully at the animation
8605 of pieces in mono mode, they are being drawn as solid
8606 shapes without interior detail while moving. Fixing
8607 this would be a major complication for minimal return.
8610 /* Masks for XPM pieces. Black and white pieces can have
8611 different shapes, but in the interest of retaining my
8612 sanity pieces must have the same outline on both light
8613 and dark squares, and all pieces must use the same
8614 background square colors/images. */
8617 CreateAnimMasks (pieceDepth)
8624 unsigned long plane;
8627 /* Need a bitmap just to get a GC with right depth */
8628 buf = XCreatePixmap(xDisplay, xBoardWindow,
8630 values.foreground = 1;
8631 values.background = 0;
8632 /* Don't use XtGetGC, not read only */
8633 maskGC = XCreateGC(xDisplay, buf,
8634 GCForeground | GCBackground, &values);
8635 XFreePixmap(xDisplay, buf);
8637 buf = XCreatePixmap(xDisplay, xBoardWindow,
8638 squareSize, squareSize, pieceDepth);
8639 values.foreground = XBlackPixel(xDisplay, xScreen);
8640 values.background = XWhitePixel(xDisplay, xScreen);
8641 bufGC = XCreateGC(xDisplay, buf,
8642 GCForeground | GCBackground, &values);
8644 for (piece = WhitePawn; piece <= BlackKing; piece++) {
8645 /* Begin with empty mask */
8646 xpmMask[piece] = XCreatePixmap(xDisplay, xBoardWindow,
8647 squareSize, squareSize, 1);
8648 XSetFunction(xDisplay, maskGC, GXclear);
8649 XFillRectangle(xDisplay, xpmMask[piece], maskGC,
8650 0, 0, squareSize, squareSize);
8652 /* Take a copy of the piece */
8657 XSetFunction(xDisplay, bufGC, GXcopy);
8658 XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % (int)BlackPawn],
8660 0, 0, squareSize, squareSize, 0, 0);
8662 /* XOR the background (light) over the piece */
8663 XSetFunction(xDisplay, bufGC, GXxor);
8665 XCopyArea(xDisplay, xpmLightSquare, buf, bufGC,
8666 0, 0, squareSize, squareSize, 0, 0);
8668 XSetForeground(xDisplay, bufGC, lightSquareColor);
8669 XFillRectangle(xDisplay, buf, bufGC, 0, 0, squareSize, squareSize);
8672 /* We now have an inverted piece image with the background
8673 erased. Construct mask by just selecting all the non-zero
8674 pixels - no need to reconstruct the original image. */
8675 XSetFunction(xDisplay, maskGC, GXor);
8677 /* Might be quicker to download an XImage and create bitmap
8678 data from it rather than this N copies per piece, but it
8679 only takes a fraction of a second and there is a much
8680 longer delay for loading the pieces. */
8681 for (n = 0; n < pieceDepth; n ++) {
8682 XCopyPlane(xDisplay, buf, xpmMask[piece], maskGC,
8683 0, 0, squareSize, squareSize,
8689 XFreePixmap(xDisplay, buf);
8690 XFreeGC(xDisplay, bufGC);
8691 XFreeGC(xDisplay, maskGC);
8695 InitAnimState (anim, info)
8697 XWindowAttributes * info;
8702 /* Each buffer is square size, same depth as window */
8703 anim->saveBuf = XCreatePixmap(xDisplay, xBoardWindow,
8704 squareSize, squareSize, info->depth);
8705 anim->newBuf = XCreatePixmap(xDisplay, xBoardWindow,
8706 squareSize, squareSize, info->depth);
8708 /* Create a plain GC for blitting */
8709 mask = GCForeground | GCBackground | GCFunction |
8710 GCPlaneMask | GCGraphicsExposures;
8711 values.foreground = XBlackPixel(xDisplay, xScreen);
8712 values.background = XWhitePixel(xDisplay, xScreen);
8713 values.function = GXcopy;
8714 values.plane_mask = AllPlanes;
8715 values.graphics_exposures = False;
8716 anim->blitGC = XCreateGC(xDisplay, xBoardWindow, mask, &values);
8718 /* Piece will be copied from an existing context at
8719 the start of each new animation/drag. */
8720 anim->pieceGC = XCreateGC(xDisplay, xBoardWindow, 0, &values);
8722 /* Outline will be a read-only copy of an existing */
8723 anim->outlineGC = None;
8729 static int done = 0;
8730 XWindowAttributes info;
8734 XGetWindowAttributes(xDisplay, xBoardWindow, &info);
8736 InitAnimState(&game, &info);
8737 InitAnimState(&player, &info);
8739 /* For XPM pieces, we need bitmaps to use as masks. */
8741 CreateAnimMasks(info.depth);
8746 static Boolean frameWaiting;
8748 static RETSIGTYPE FrameAlarm (sig)
8751 frameWaiting = False;
8752 /* In case System-V style signals. Needed?? */
8753 signal(SIGALRM, FrameAlarm);
8760 struct itimerval delay;
8762 XSync(xDisplay, False);
8765 frameWaiting = True;
8766 signal(SIGALRM, FrameAlarm);
8767 delay.it_interval.tv_sec =
8768 delay.it_value.tv_sec = time / 1000;
8769 delay.it_interval.tv_usec =
8770 delay.it_value.tv_usec = (time % 1000) * 1000;
8771 setitimer(ITIMER_REAL, &delay, NULL);
8773 /* Ugh -- busy-wait! --tpm */
8774 while (frameWaiting);
8776 while (frameWaiting) pause();
8778 delay.it_interval.tv_sec = delay.it_value.tv_sec = 0;
8779 delay.it_interval.tv_usec = delay.it_value.tv_usec = 0;
8780 setitimer(ITIMER_REAL, &delay, NULL);
8790 XSync(xDisplay, False);
8792 usleep(time * 1000);
8797 /* Convert board position to corner of screen rect and color */
8800 ScreenSquare(column, row, pt, color)
8801 int column; int row; XPoint * pt; int * color;
8804 pt->x = lineGap + ((BOARD_WIDTH-1)-column) * (squareSize + lineGap);
8805 pt->y = lineGap + row * (squareSize + lineGap);
8807 pt->x = lineGap + column * (squareSize + lineGap);
8808 pt->y = lineGap + ((BOARD_HEIGHT-1)-row) * (squareSize + lineGap);
8810 *color = SquareColor(row, column);
8813 /* Convert window coords to square */
8816 BoardSquare(x, y, column, row)
8817 int x; int y; int * column; int * row;
8819 *column = EventToSquare(x, BOARD_WIDTH);
8820 if (flipView && *column >= 0)
8821 *column = BOARD_WIDTH - 1 - *column;
8822 *row = EventToSquare(y, BOARD_HEIGHT);
8823 if (!flipView && *row >= 0)
8824 *row = BOARD_HEIGHT - 1 - *row;
8829 #undef Max /* just in case */
8831 #define Max(a, b) ((a) > (b) ? (a) : (b))
8832 #define Min(a, b) ((a) < (b) ? (a) : (b))
8835 SetRect(rect, x, y, width, height)
8836 XRectangle * rect; int x; int y; int width; int height;
8840 rect->width = width;
8841 rect->height = height;
8844 /* Test if two frames overlap. If they do, return
8845 intersection rect within old and location of
8846 that rect within new. */
8849 Intersect(old, new, size, area, pt)
8850 XPoint * old; XPoint * new;
8851 int size; XRectangle * area; XPoint * pt;
8853 if (old->x > new->x + size || new->x > old->x + size ||
8854 old->y > new->y + size || new->y > old->y + size) {
8857 SetRect(area, Max(new->x - old->x, 0), Max(new->y - old->y, 0),
8858 size - abs(old->x - new->x), size - abs(old->y - new->y));
8859 pt->x = Max(old->x - new->x, 0);
8860 pt->y = Max(old->y - new->y, 0);
8865 /* For two overlapping frames, return the rect(s)
8866 in the old that do not intersect with the new. */
8869 CalcUpdateRects(old, new, size, update, nUpdates)
8870 XPoint * old; XPoint * new; int size;
8871 XRectangle update[]; int * nUpdates;
8875 /* If old = new (shouldn't happen) then nothing to draw */
8876 if (old->x == new->x && old->y == new->y) {
8880 /* Work out what bits overlap. Since we know the rects
8881 are the same size we don't need a full intersect calc. */
8883 /* Top or bottom edge? */
8884 if (new->y > old->y) {
8885 SetRect(&(update[count]), old->x, old->y, size, new->y - old->y);
8887 } else if (old->y > new->y) {
8888 SetRect(&(update[count]), old->x, old->y + size - (old->y - new->y),
8889 size, old->y - new->y);
8892 /* Left or right edge - don't overlap any update calculated above. */
8893 if (new->x > old->x) {
8894 SetRect(&(update[count]), old->x, Max(new->y, old->y),
8895 new->x - old->x, size - abs(new->y - old->y));
8897 } else if (old->x > new->x) {
8898 SetRect(&(update[count]), new->x + size, Max(new->y, old->y),
8899 old->x - new->x, size - abs(new->y - old->y));
8906 /* Generate a series of frame coords from start->mid->finish.
8907 The movement rate doubles until the half way point is
8908 reached, then halves back down to the final destination,
8909 which gives a nice slow in/out effect. The algorithmn
8910 may seem to generate too many intermediates for short
8911 moves, but remember that the purpose is to attract the
8912 viewers attention to the piece about to be moved and
8913 then to where it ends up. Too few frames would be less
8917 Tween(start, mid, finish, factor, frames, nFrames)
8918 XPoint * start; XPoint * mid;
8919 XPoint * finish; int factor;
8920 XPoint frames[]; int * nFrames;
8922 int fraction, n, count;
8926 /* Slow in, stepping 1/16th, then 1/8th, ... */
8928 for (n = 0; n < factor; n++)
8930 for (n = 0; n < factor; n++) {
8931 frames[count].x = start->x + (mid->x - start->x) / fraction;
8932 frames[count].y = start->y + (mid->y - start->y) / fraction;
8934 fraction = fraction / 2;
8938 frames[count] = *mid;
8941 /* Slow out, stepping 1/2, then 1/4, ... */
8943 for (n = 0; n < factor; n++) {
8944 frames[count].x = finish->x - (finish->x - mid->x) / fraction;
8945 frames[count].y = finish->y - (finish->y - mid->y) / fraction;
8947 fraction = fraction * 2;
8952 /* Draw a piece on the screen without disturbing what's there */
8955 SelectGCMask(piece, clip, outline, mask)
8956 ChessSquare piece; GC * clip; GC * outline; Pixmap * mask;
8960 /* Bitmap for piece being moved. */
8961 if (appData.monoMode) {
8962 *mask = *pieceToSolid(piece);
8963 } else if (useImages) {
8965 *mask = xpmMask[piece];
8967 *mask = ximMaskPm[piece%(int)BlackPawn];
8970 *mask = *pieceToSolid(piece);
8973 /* GC for piece being moved. Square color doesn't matter, but
8974 since it gets modified we make a copy of the original. */
8976 if (appData.monoMode)
8981 if (appData.monoMode)
8986 XCopyGC(xDisplay, source, 0xFFFFFFFF, *clip);
8988 /* Outline only used in mono mode and is not modified */
8990 *outline = bwPieceGC;
8992 *outline = wbPieceGC;
8996 OverlayPiece(piece, clip, outline, dest)
8997 ChessSquare piece; GC clip; GC outline; Drawable dest;
9002 /* Draw solid rectangle which will be clipped to shape of piece */
9003 XFillRectangle(xDisplay, dest, clip,
9004 0, 0, squareSize, squareSize);
9005 if (appData.monoMode)
9006 /* Also draw outline in contrasting color for black
9007 on black / white on white cases */
9008 XCopyPlane(xDisplay, *pieceToOutline(piece), dest, outline,
9009 0, 0, squareSize, squareSize, 0, 0, 1);
9011 /* Copy the piece */
9016 XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % (int)BlackPawn],
9018 0, 0, squareSize, squareSize,
9023 /* Animate the movement of a single piece */
9026 BeginAnimation(anim, piece, startColor, start)
9034 /* The old buffer is initialised with the start square (empty) */
9035 BlankSquare(0, 0, startColor, EmptySquare, anim->saveBuf);
9036 anim->prevFrame = *start;
9038 /* The piece will be drawn using its own bitmap as a matte */
9039 SelectGCMask(piece, &anim->pieceGC, &anim->outlineGC, &mask);
9040 XSetClipMask(xDisplay, anim->pieceGC, mask);
9044 AnimationFrame(anim, frame, piece)
9049 XRectangle updates[4];
9054 /* Save what we are about to draw into the new buffer */
9055 XCopyArea(xDisplay, xBoardWindow, anim->newBuf, anim->blitGC,
9056 frame->x, frame->y, squareSize, squareSize,
9059 /* Erase bits of the previous frame */
9060 if (Intersect(&anim->prevFrame, frame, squareSize, &overlap, &pt)) {
9061 /* Where the new frame overlapped the previous,
9062 the contents in newBuf are wrong. */
9063 XCopyArea(xDisplay, anim->saveBuf, anim->newBuf, anim->blitGC,
9064 overlap.x, overlap.y,
9065 overlap.width, overlap.height,
9067 /* Repaint the areas in the old that don't overlap new */
9068 CalcUpdateRects(&anim->prevFrame, frame, squareSize, updates, &count);
9069 for (i = 0; i < count; i++)
9070 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9071 updates[i].x - anim->prevFrame.x,
9072 updates[i].y - anim->prevFrame.y,
9073 updates[i].width, updates[i].height,
9074 updates[i].x, updates[i].y);
9076 /* Easy when no overlap */
9077 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9078 0, 0, squareSize, squareSize,
9079 anim->prevFrame.x, anim->prevFrame.y);
9082 /* Save this frame for next time round */
9083 XCopyArea(xDisplay, anim->newBuf, anim->saveBuf, anim->blitGC,
9084 0, 0, squareSize, squareSize,
9086 anim->prevFrame = *frame;
9088 /* Draw piece over original screen contents, not current,
9089 and copy entire rect. Wipes out overlapping piece images. */
9090 OverlayPiece(piece, anim->pieceGC, anim->outlineGC, anim->newBuf);
9091 XCopyArea(xDisplay, anim->newBuf, xBoardWindow, anim->blitGC,
9092 0, 0, squareSize, squareSize,
9093 frame->x, frame->y);
9097 EndAnimation (anim, finish)
9101 XRectangle updates[4];
9106 /* The main code will redraw the final square, so we
9107 only need to erase the bits that don't overlap. */
9108 if (Intersect(&anim->prevFrame, finish, squareSize, &overlap, &pt)) {
9109 CalcUpdateRects(&anim->prevFrame, finish, squareSize, updates, &count);
9110 for (i = 0; i < count; i++)
9111 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9112 updates[i].x - anim->prevFrame.x,
9113 updates[i].y - anim->prevFrame.y,
9114 updates[i].width, updates[i].height,
9115 updates[i].x, updates[i].y);
9117 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9118 0, 0, squareSize, squareSize,
9119 anim->prevFrame.x, anim->prevFrame.y);
9124 FrameSequence(anim, piece, startColor, start, finish, frames, nFrames)
9126 ChessSquare piece; int startColor;
9127 XPoint * start; XPoint * finish;
9128 XPoint frames[]; int nFrames;
9132 BeginAnimation(anim, piece, startColor, start);
9133 for (n = 0; n < nFrames; n++) {
9134 AnimationFrame(anim, &(frames[n]), piece);
9135 FrameDelay(appData.animSpeed);
9137 EndAnimation(anim, finish);
9140 /* Main control logic for deciding what to animate and how */
9143 AnimateMove(board, fromX, fromY, toX, toY)
9152 XPoint start, finish, mid;
9153 XPoint frames[kFactor * 2 + 1];
9154 int nFrames, startColor, endColor;
9156 /* Are we animating? */
9157 if (!appData.animate || appData.blindfold)
9160 if (fromY < 0 || fromX < 0 || toX < 0 || toY < 0) return;
9161 piece = board[fromY][fromX];
9162 if (piece >= EmptySquare) return;
9167 hop = (piece == WhiteKnight || piece == BlackKnight);
9170 if (appData.debugMode) {
9171 fprintf(debugFP, hop ? _("AnimateMove: piece %d hops from %d,%d to %d,%d \n") :
9172 _("AnimateMove: piece %d slides from %d,%d to %d,%d \n"),
9173 piece, fromX, fromY, toX, toY); }
9175 ScreenSquare(fromX, fromY, &start, &startColor);
9176 ScreenSquare(toX, toY, &finish, &endColor);
9179 /* Knight: make diagonal movement then straight */
9180 if (abs(toY - fromY) < abs(toX - fromX)) {
9181 mid.x = start.x + (finish.x - start.x) / 2;
9185 mid.y = start.y + (finish.y - start.y) / 2;
9188 mid.x = start.x + (finish.x - start.x) / 2;
9189 mid.y = start.y + (finish.y - start.y) / 2;
9192 /* Don't use as many frames for very short moves */
9193 if (abs(toY - fromY) + abs(toX - fromX) <= 2)
9194 Tween(&start, &mid, &finish, kFactor - 1, frames, &nFrames);
9196 Tween(&start, &mid, &finish, kFactor, frames, &nFrames);
9197 FrameSequence(&game, piece, startColor, &start, &finish, frames, nFrames);
9199 /* Be sure end square is redrawn */
9200 damage[toY][toX] = True;
9204 DragPieceBegin(x, y)
9207 int boardX, boardY, color;
9210 /* Are we animating? */
9211 if (!appData.animateDragging || appData.blindfold)
9214 /* Figure out which square we start in and the
9215 mouse position relative to top left corner. */
9216 BoardSquare(x, y, &boardX, &boardY);
9217 player.startBoardX = boardX;
9218 player.startBoardY = boardY;
9219 ScreenSquare(boardX, boardY, &corner, &color);
9220 player.startSquare = corner;
9221 player.startColor = color;
9223 /* Start from exactly where the piece is. This can be confusing
9224 if you start dragging far from the center of the square; most
9225 or all of the piece can be over a different square from the one
9226 the mouse pointer is in. */
9227 player.mouseDelta.x = x - corner.x;
9228 player.mouseDelta.y = y - corner.y;
9230 /* As soon as we start dragging, the piece will jump slightly to
9231 be centered over the mouse pointer. */
9232 player.mouseDelta.x = squareSize/2;
9233 player.mouseDelta.y = squareSize/2;
9235 /* Initialise animation */
9236 player.dragPiece = PieceForSquare(boardX, boardY);
9238 if (player.dragPiece >= 0 && player.dragPiece < EmptySquare) {
9239 player.dragActive = True;
9240 BeginAnimation(&player, player.dragPiece, color, &corner);
9241 /* Mark this square as needing to be redrawn. Note that
9242 we don't remove the piece though, since logically (ie
9243 as seen by opponent) the move hasn't been made yet. */
9244 if(boardX == BOARD_RGHT+1 && PieceForSquare(boardX-1, boardY) > 1 ||
9245 boardX == BOARD_LEFT-2 && PieceForSquare(boardX+1, boardY) > 1)
9246 XCopyArea(xDisplay, xBoardWindow, player.saveBuf, player.blitGC,
9247 corner.x, corner.y, squareSize, squareSize,
9248 0, 0); // [HGM] zh: unstack in stead of grab
9249 damage[boardY][boardX] = True;
9251 player.dragActive = False;
9261 /* Are we animating? */
9262 if (!appData.animateDragging || appData.blindfold)
9266 if (! player.dragActive)
9268 /* Move piece, maintaining same relative position
9269 of mouse within square */
9270 corner.x = x - player.mouseDelta.x;
9271 corner.y = y - player.mouseDelta.y;
9272 AnimationFrame(&player, &corner, player.dragPiece);
9274 if (appData.highlightDragging) {
9276 BoardSquare(x, y, &boardX, &boardY);
9277 SetHighlights(fromX, fromY, boardX, boardY);
9286 int boardX, boardY, color;
9289 /* Are we animating? */
9290 if (!appData.animateDragging || appData.blindfold)
9294 if (! player.dragActive)
9296 /* Last frame in sequence is square piece is
9297 placed on, which may not match mouse exactly. */
9298 BoardSquare(x, y, &boardX, &boardY);
9299 ScreenSquare(boardX, boardY, &corner, &color);
9300 EndAnimation(&player, &corner);
9302 /* Be sure end square is redrawn */
9303 damage[boardY][boardX] = True;
9305 /* This prevents weird things happening with fast successive
9306 clicks which on my Sun at least can cause motion events
9307 without corresponding press/release. */
9308 player.dragActive = False;
9311 /* Handle expose event while piece being dragged */
9316 if (!player.dragActive || appData.blindfold)
9319 /* What we're doing: logically, the move hasn't been made yet,
9320 so the piece is still in it's original square. But visually
9321 it's being dragged around the board. So we erase the square
9322 that the piece is on and draw it at the last known drag point. */
9323 BlankSquare(player.startSquare.x, player.startSquare.y,
9324 player.startColor, EmptySquare, xBoardWindow);
9325 AnimationFrame(&player, &player.prevFrame, player.dragPiece);
9326 damage[player.startBoardY][player.startBoardX] = TRUE;
9330 SetProgramStats( FrontEndProgramStats * stats )
9333 // [HGM] done, but perhaps backend should call this directly?
9334 EngineOutputUpdate( stats );