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]);
2335 if ((chessDir = (char *) getenv("CHESSDIR")) == NULL) {
2338 if (chdir(chessDir) != 0) {
2339 fprintf(stderr, _("%s: can't cd to CHESSDIR: "), programName);
2346 if (p == NULL) p = "/tmp";
2347 i = strlen(p) + strlen("/.xboardXXXXXx.pgn") + 1;
2348 gameCopyFilename = (char*) malloc(i);
2349 gamePasteFilename = (char*) malloc(i);
2350 snprintf(gameCopyFilename,i, "%s/.xboard%05uc.pgn", p, getpid());
2351 snprintf(gamePasteFilename,i, "%s/.xboard%05up.pgn", p, getpid());
2353 XtGetApplicationResources(shellWidget, (XtPointer) &appData,
2354 clientResources, XtNumber(clientResources),
2357 if (appData.debugMode && appData.nameOfDebugFile && strcmp(appData.nameOfDebugFile, "stderr")) {
2358 /* [DM] debug info to file [HGM] make the filename a command-line option, and allow it to remain stderr */
2359 if ((debugFP = fopen(appData.nameOfDebugFile, "w")) == NULL) {
2360 printf(_("Failed to open file '%s'\n"), appData.nameOfDebugFile);
2363 setbuf(debugFP, NULL);
2366 /* [HGM,HR] make sure board size is acceptable */
2367 if(appData.NrFiles > BOARD_SIZE ||
2368 appData.NrRanks > BOARD_SIZE )
2369 DisplayFatalError(_("Recompile with BOARD_SIZE > 12, to support this size"), 0, 2);
2372 /* This feature does not work; animation needs a rewrite */
2373 appData.highlightDragging = FALSE;
2377 xDisplay = XtDisplay(shellWidget);
2378 xScreen = DefaultScreen(xDisplay);
2379 wm_delete_window = XInternAtom(xDisplay, "WM_DELETE_WINDOW", True);
2381 gameInfo.variant = StringToVariant(appData.variant);
2382 InitPosition(FALSE);
2385 * Determine boardSize
2387 gameInfo.boardWidth = gameInfo.boardHeight = 8; // [HGM] boardsize: make sure we start as 8x8
2390 // [HGM] as long as we have not created the possibility to change size while running, start with requested size
2391 gameInfo.boardWidth = appData.NrFiles > 0 ? appData.NrFiles : 8;
2392 gameInfo.boardHeight = appData.NrRanks > 0 ? appData.NrRanks : 8;
2393 gameInfo.holdingsWidth = appData.holdingsSize > 0 ? 2 : 0;
2398 InitDrawingSizes(-1, 0); // [HGM] initsize: make this into a subroutine
2400 if (isdigit(appData.boardSize[0])) {
2401 i = sscanf(appData.boardSize, "%d,%d,%d,%d,%d,%d,%d", &squareSize,
2402 &lineGap, &clockFontPxlSize, &coordFontPxlSize,
2403 &fontPxlSize, &smallLayout, &tinyLayout);
2405 fprintf(stderr, _("%s: bad boardSize syntax %s\n"),
2406 programName, appData.boardSize);
2410 /* Find some defaults; use the nearest known size */
2411 SizeDefaults *szd, *nearest;
2412 int distance = 99999;
2413 nearest = szd = sizeDefaults;
2414 while (szd->name != NULL) {
2415 if (abs(szd->squareSize - squareSize) < distance) {
2417 distance = abs(szd->squareSize - squareSize);
2418 if (distance == 0) break;
2422 if (i < 2) lineGap = nearest->lineGap;
2423 if (i < 3) clockFontPxlSize = nearest->clockFontPxlSize;
2424 if (i < 4) coordFontPxlSize = nearest->coordFontPxlSize;
2425 if (i < 5) fontPxlSize = nearest->fontPxlSize;
2426 if (i < 6) smallLayout = nearest->smallLayout;
2427 if (i < 7) tinyLayout = nearest->tinyLayout;
2430 SizeDefaults *szd = sizeDefaults;
2431 if (*appData.boardSize == NULLCHAR) {
2432 while (DisplayWidth(xDisplay, xScreen) < szd->minScreenSize ||
2433 DisplayHeight(xDisplay, xScreen) < szd->minScreenSize) {
2436 if (szd->name == NULL) szd--;
2438 while (szd->name != NULL &&
2439 StrCaseCmp(szd->name, appData.boardSize) != 0) szd++;
2440 if (szd->name == NULL) {
2441 fprintf(stderr, _("%s: unrecognized boardSize name %s\n"),
2442 programName, appData.boardSize);
2446 squareSize = szd->squareSize;
2447 lineGap = szd->lineGap;
2448 clockFontPxlSize = szd->clockFontPxlSize;
2449 coordFontPxlSize = szd->coordFontPxlSize;
2450 fontPxlSize = szd->fontPxlSize;
2451 smallLayout = szd->smallLayout;
2452 tinyLayout = szd->tinyLayout;
2455 /* Now, using squareSize as a hint, find a good XPM/XIM set size */
2456 if (strlen(appData.pixmapDirectory) > 0) {
2457 p = ExpandPathName(appData.pixmapDirectory);
2459 fprintf(stderr, _("Error expanding path name \"%s\"\n"),
2460 appData.pixmapDirectory);
2463 if (appData.debugMode) {
2464 fprintf(stderr, _("\
2465 XBoard square size (hint): %d\n\
2466 %s fulldir:%s:\n"), squareSize, IMAGE_EXT, p);
2468 squareSize = xpm_closest_to(p, squareSize, IMAGE_EXT);
2469 if (appData.debugMode) {
2470 fprintf(stderr, _("Closest %s size: %d\n"), IMAGE_EXT, squareSize);
2474 /* [HR] height treated separately (hacked) */
2475 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2476 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2477 if (appData.showJail == 1) {
2478 /* Jail on top and bottom */
2479 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2480 XtSetArg(boardArgs[2], XtNheight,
2481 boardHeight + 2*(lineGap + squareSize));
2482 } else if (appData.showJail == 2) {
2484 XtSetArg(boardArgs[1], XtNwidth,
2485 boardWidth + 2*(lineGap + squareSize));
2486 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2489 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2490 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2494 * Determine what fonts to use.
2496 appData.clockFont = FindFont(appData.clockFont, clockFontPxlSize);
2497 clockFontID = XLoadFont(xDisplay, appData.clockFont);
2498 clockFontStruct = XQueryFont(xDisplay, clockFontID);
2499 appData.coordFont = FindFont(appData.coordFont, coordFontPxlSize);
2500 coordFontID = XLoadFont(xDisplay, appData.coordFont);
2501 coordFontStruct = XQueryFont(xDisplay, coordFontID);
2502 appData.font = FindFont(appData.font, fontPxlSize);
2503 countFontID = XLoadFont(xDisplay, appData.coordFont); // [HGM] holdings
2504 countFontStruct = XQueryFont(xDisplay, countFontID);
2505 // appData.font = FindFont(appData.font, fontPxlSize);
2507 xdb = XtDatabase(xDisplay);
2508 XrmPutStringResource(&xdb, "*font", appData.font);
2511 * Detect if there are not enough colors available and adapt.
2513 if (DefaultDepth(xDisplay, xScreen) <= 2) {
2514 appData.monoMode = True;
2517 if (!appData.monoMode) {
2518 vFrom.addr = (caddr_t) appData.lightSquareColor;
2519 vFrom.size = strlen(appData.lightSquareColor);
2520 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2521 if (vTo.addr == NULL) {
2522 appData.monoMode = True;
2525 lightSquareColor = *(Pixel *) vTo.addr;
2528 if (!appData.monoMode) {
2529 vFrom.addr = (caddr_t) appData.darkSquareColor;
2530 vFrom.size = strlen(appData.darkSquareColor);
2531 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2532 if (vTo.addr == NULL) {
2533 appData.monoMode = True;
2536 darkSquareColor = *(Pixel *) vTo.addr;
2539 if (!appData.monoMode) {
2540 vFrom.addr = (caddr_t) appData.whitePieceColor;
2541 vFrom.size = strlen(appData.whitePieceColor);
2542 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2543 if (vTo.addr == NULL) {
2544 appData.monoMode = True;
2547 whitePieceColor = *(Pixel *) vTo.addr;
2550 if (!appData.monoMode) {
2551 vFrom.addr = (caddr_t) appData.blackPieceColor;
2552 vFrom.size = strlen(appData.blackPieceColor);
2553 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2554 if (vTo.addr == NULL) {
2555 appData.monoMode = True;
2558 blackPieceColor = *(Pixel *) vTo.addr;
2562 if (!appData.monoMode) {
2563 vFrom.addr = (caddr_t) appData.highlightSquareColor;
2564 vFrom.size = strlen(appData.highlightSquareColor);
2565 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2566 if (vTo.addr == NULL) {
2567 appData.monoMode = True;
2570 highlightSquareColor = *(Pixel *) vTo.addr;
2574 if (!appData.monoMode) {
2575 vFrom.addr = (caddr_t) appData.premoveHighlightColor;
2576 vFrom.size = strlen(appData.premoveHighlightColor);
2577 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2578 if (vTo.addr == NULL) {
2579 appData.monoMode = True;
2582 premoveHighlightColor = *(Pixel *) vTo.addr;
2587 fprintf(stderr, _("%s: too few colors available; trying monochrome mode\n"),
2591 if (appData.lowTimeWarning && !appData.monoMode) {
2592 vFrom.addr = (caddr_t) appData.lowTimeWarningColor;
2593 vFrom.size = strlen(appData.lowTimeWarningColor);
2594 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2595 if (vTo.addr == NULL)
2596 appData.monoMode = True;
2598 lowTimeWarningColor = *(Pixel *) vTo.addr;
2601 if (appData.monoMode && appData.debugMode) {
2602 fprintf(stderr, _("white pixel = 0x%lx, black pixel = 0x%lx\n"),
2603 (unsigned long) XWhitePixel(xDisplay, xScreen),
2604 (unsigned long) XBlackPixel(xDisplay, xScreen));
2607 if (parse_cpair(ColorShout, appData.colorShout) < 0 ||
2608 parse_cpair(ColorSShout, appData.colorSShout) < 0 ||
2609 parse_cpair(ColorChannel1, appData.colorChannel1) < 0 ||
2610 parse_cpair(ColorChannel, appData.colorChannel) < 0 ||
2611 parse_cpair(ColorKibitz, appData.colorKibitz) < 0 ||
2612 parse_cpair(ColorTell, appData.colorTell) < 0 ||
2613 parse_cpair(ColorChallenge, appData.colorChallenge) < 0 ||
2614 parse_cpair(ColorRequest, appData.colorRequest) < 0 ||
2615 parse_cpair(ColorSeek, appData.colorSeek) < 0 ||
2616 parse_cpair(ColorNormal, appData.colorNormal) < 0)
2618 if (appData.colorize) {
2620 _("%s: can't parse color names; disabling colorization\n"),
2623 appData.colorize = FALSE;
2625 textColors[ColorNone].fg = textColors[ColorNone].bg = -1;
2626 textColors[ColorNone].attr = 0;
2628 XtAppAddActions(appContext, boardActions, XtNumber(boardActions));
2634 layoutName = "tinyLayout";
2635 } else if (smallLayout) {
2636 layoutName = "smallLayout";
2638 layoutName = "normalLayout";
2640 /* Outer layoutWidget is there only to provide a name for use in
2641 resources that depend on the layout style */
2643 XtCreateManagedWidget(layoutName, formWidgetClass, shellWidget,
2644 layoutArgs, XtNumber(layoutArgs));
2646 XtCreateManagedWidget("form", formWidgetClass, layoutWidget,
2647 formArgs, XtNumber(formArgs));
2648 XtSetArg(args[0], XtNdefaultDistance, &sep);
2649 XtGetValues(formWidget, args, 1);
2652 widgetList[j++] = menuBarWidget = CreateMenuBar(menuBar);
2653 XtSetArg(args[0], XtNtop, XtChainTop);
2654 XtSetArg(args[1], XtNbottom, XtChainTop);
2655 XtSetValues(menuBarWidget, args, 2);
2657 widgetList[j++] = whiteTimerWidget =
2658 XtCreateWidget("whiteTime", labelWidgetClass,
2659 formWidget, timerArgs, XtNumber(timerArgs));
2660 XtSetArg(args[0], XtNfont, clockFontStruct);
2661 XtSetArg(args[1], XtNtop, XtChainTop);
2662 XtSetArg(args[2], XtNbottom, XtChainTop);
2663 XtSetValues(whiteTimerWidget, args, 3);
2665 widgetList[j++] = blackTimerWidget =
2666 XtCreateWidget("blackTime", labelWidgetClass,
2667 formWidget, timerArgs, XtNumber(timerArgs));
2668 XtSetArg(args[0], XtNfont, clockFontStruct);
2669 XtSetArg(args[1], XtNtop, XtChainTop);
2670 XtSetArg(args[2], XtNbottom, XtChainTop);
2671 XtSetValues(blackTimerWidget, args, 3);
2673 if (appData.titleInWindow) {
2674 widgetList[j++] = titleWidget =
2675 XtCreateWidget("title", labelWidgetClass, formWidget,
2676 titleArgs, XtNumber(titleArgs));
2677 XtSetArg(args[0], XtNtop, XtChainTop);
2678 XtSetArg(args[1], XtNbottom, XtChainTop);
2679 XtSetValues(titleWidget, args, 2);
2682 if (appData.showButtonBar) {
2683 widgetList[j++] = buttonBarWidget = CreateButtonBar(buttonBar);
2684 XtSetArg(args[0], XtNleft, XtChainRight); // [HGM] glue to right window edge
2685 XtSetArg(args[1], XtNright, XtChainRight); // for good run-time sizing
2686 XtSetArg(args[2], XtNtop, XtChainTop);
2687 XtSetArg(args[3], XtNbottom, XtChainTop);
2688 XtSetValues(buttonBarWidget, args, 4);
2691 widgetList[j++] = messageWidget =
2692 XtCreateWidget("message", labelWidgetClass, formWidget,
2693 messageArgs, XtNumber(messageArgs));
2694 XtSetArg(args[0], XtNtop, XtChainTop);
2695 XtSetArg(args[1], XtNbottom, XtChainTop);
2696 XtSetValues(messageWidget, args, 2);
2698 widgetList[j++] = boardWidget =
2699 XtCreateWidget("board", widgetClass, formWidget, boardArgs,
2700 XtNumber(boardArgs));
2702 XtManageChildren(widgetList, j);
2704 timerWidth = (boardWidth - sep) / 2;
2705 XtSetArg(args[0], XtNwidth, timerWidth);
2706 XtSetValues(whiteTimerWidget, args, 1);
2707 XtSetValues(blackTimerWidget, args, 1);
2709 XtSetArg(args[0], XtNbackground, &timerBackgroundPixel);
2710 XtSetArg(args[1], XtNforeground, &timerForegroundPixel);
2711 XtGetValues(whiteTimerWidget, args, 2);
2713 if (appData.showButtonBar) {
2714 XtSetArg(args[0], XtNbackground, &buttonBackgroundPixel);
2715 XtSetArg(args[1], XtNforeground, &buttonForegroundPixel);
2716 XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
2720 * formWidget uses these constraints but they are stored
2724 XtSetArg(args[i], XtNfromHoriz, 0); i++;
2725 XtSetValues(menuBarWidget, args, i);
2726 if (appData.titleInWindow) {
2729 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2730 XtSetValues(whiteTimerWidget, args, i);
2732 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2733 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2734 XtSetValues(blackTimerWidget, args, i);
2736 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2737 XtSetArg(args[i], XtNjustify, XtJustifyLeft); i++;
2738 XtSetValues(titleWidget, args, i);
2740 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2741 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2742 XtSetValues(messageWidget, args, i);
2743 if (appData.showButtonBar) {
2745 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2746 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2747 XtSetValues(buttonBarWidget, args, i);
2751 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2752 XtSetValues(whiteTimerWidget, args, i);
2754 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2755 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2756 XtSetValues(blackTimerWidget, args, i);
2758 XtSetArg(args[i], XtNfromHoriz, menuBarWidget); i++;
2759 XtSetValues(titleWidget, args, i);
2761 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2762 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2763 XtSetValues(messageWidget, args, i);
2764 if (appData.showButtonBar) {
2766 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2767 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2768 XtSetValues(buttonBarWidget, args, i);
2773 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2774 XtSetValues(whiteTimerWidget, args, i);
2776 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2777 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2778 XtSetValues(blackTimerWidget, args, i);
2780 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2781 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2782 XtSetValues(messageWidget, args, i);
2783 if (appData.showButtonBar) {
2785 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2786 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2787 XtSetValues(buttonBarWidget, args, i);
2791 XtSetArg(args[0], XtNfromVert, messageWidget);
2792 XtSetArg(args[1], XtNtop, XtChainTop);
2793 XtSetArg(args[2], XtNbottom, XtChainBottom);
2794 XtSetArg(args[3], XtNleft, XtChainLeft);
2795 XtSetArg(args[4], XtNright, XtChainRight);
2796 XtSetValues(boardWidget, args, 5);
2798 XtRealizeWidget(shellWidget);
2801 * Correct the width of the message and title widgets.
2802 * It is not known why some systems need the extra fudge term.
2803 * The value "2" is probably larger than needed.
2805 XawFormDoLayout(formWidget, False);
2807 #define WIDTH_FUDGE 2
2809 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2810 XtSetArg(args[i], XtNheight, &h); i++;
2811 XtGetValues(messageWidget, args, i);
2812 if (appData.showButtonBar) {
2814 XtSetArg(args[i], XtNwidth, &w); i++;
2815 XtGetValues(buttonBarWidget, args, i);
2816 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2818 w = boardWidth - 2*bor + 1; /*!! +1 compensates for kludge below */
2821 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2822 if (gres != XtGeometryYes && appData.debugMode) {
2823 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2824 programName, gres, w, h, wr, hr);
2827 /* !! Horrible hack to work around bug in XFree86 4.0.1 (X11R6.4.3) */
2828 /* The size used for the child widget in layout lags one resize behind
2829 its true size, so we resize a second time, 1 pixel smaller. Yeech! */
2831 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2832 if (gres != XtGeometryYes && appData.debugMode) {
2833 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2834 programName, gres, w, h, wr, hr);
2837 XtSetArg(args[0], XtNleft, XtChainLeft); // [HGM] glue ends for good run-time sizing
2838 XtSetArg(args[1], XtNright, XtChainRight);
2839 XtSetValues(messageWidget, args, 2);
2841 if (appData.titleInWindow) {
2843 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2844 XtSetArg(args[i], XtNheight, &h); i++;
2845 XtGetValues(titleWidget, args, i);
2847 w = boardWidth - 2*bor;
2849 XtSetArg(args[0], XtNwidth, &w);
2850 XtGetValues(menuBarWidget, args, 1);
2851 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2854 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
2855 if (gres != XtGeometryYes && appData.debugMode) {
2857 _("%s: titleWidget geometry error %d %d %d %d %d\n"),
2858 programName, gres, w, h, wr, hr);
2861 XawFormDoLayout(formWidget, True);
2863 xBoardWindow = XtWindow(boardWidget);
2865 // [HGM] it seems the layout code ends here, but perhaps the color stuff is size independent and would
2866 // not need to go into InitDrawingSizes().
2870 * Create X checkmark bitmap and initialize option menu checks.
2872 ReadBitmap(&xMarkPixmap, "checkmark.bm",
2873 checkmark_bits, checkmark_width, checkmark_height);
2874 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
2875 if (appData.alwaysPromoteToQueen) {
2876 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
2879 if (appData.animateDragging) {
2880 XtSetValues(XtNameToWidget(menuBarWidget,
2881 "menuOptions.Animate Dragging"),
2884 if (appData.animate) {
2885 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
2888 if (appData.autoComment) {
2889 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
2892 if (appData.autoCallFlag) {
2893 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
2896 if (appData.autoFlipView) {
2897 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Auto Flip View"),
2900 if (appData.autoObserve) {
2901 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
2904 if (appData.autoRaiseBoard) {
2905 XtSetValues(XtNameToWidget(menuBarWidget,
2906 "menuOptions.Auto Raise Board"), args, 1);
2908 if (appData.autoSaveGames) {
2909 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
2912 if (appData.saveGameFile[0] != NULLCHAR) {
2913 /* Can't turn this off from menu */
2914 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
2916 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
2920 if (appData.blindfold) {
2921 XtSetValues(XtNameToWidget(menuBarWidget,
2922 "menuOptions.Blindfold"), args, 1);
2924 if (appData.flashCount > 0) {
2925 XtSetValues(XtNameToWidget(menuBarWidget,
2926 "menuOptions.Flash Moves"),
2929 if (appData.getMoveList) {
2930 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
2934 if (appData.highlightDragging) {
2935 XtSetValues(XtNameToWidget(menuBarWidget,
2936 "menuOptions.Highlight Dragging"),
2940 if (appData.highlightLastMove) {
2941 XtSetValues(XtNameToWidget(menuBarWidget,
2942 "menuOptions.Highlight Last Move"),
2945 if (appData.icsAlarm) {
2946 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.ICS Alarm"),
2949 if (appData.ringBellAfterMoves) {
2950 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
2953 if (appData.oldSaveStyle) {
2954 XtSetValues(XtNameToWidget(menuBarWidget,
2955 "menuOptions.Old Save Style"), args, 1);
2957 if (appData.periodicUpdates) {
2958 XtSetValues(XtNameToWidget(menuBarWidget,
2959 "menuOptions.Periodic Updates"), args, 1);
2961 if (appData.ponderNextMove) {
2962 XtSetValues(XtNameToWidget(menuBarWidget,
2963 "menuOptions.Ponder Next Move"), args, 1);
2965 if (appData.popupExitMessage) {
2966 XtSetValues(XtNameToWidget(menuBarWidget,
2967 "menuOptions.Popup Exit Message"), args, 1);
2969 if (appData.popupMoveErrors) {
2970 XtSetValues(XtNameToWidget(menuBarWidget,
2971 "menuOptions.Popup Move Errors"), args, 1);
2973 if (appData.premove) {
2974 XtSetValues(XtNameToWidget(menuBarWidget,
2975 "menuOptions.Premove"), args, 1);
2977 if (appData.quietPlay) {
2978 XtSetValues(XtNameToWidget(menuBarWidget,
2979 "menuOptions.Quiet Play"), args, 1);
2981 if (appData.showCoords) {
2982 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
2985 if (appData.hideThinkingFromHuman) {
2986 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
2989 if (appData.testLegality) {
2990 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Test Legality"),
2997 ReadBitmap(&wIconPixmap, "icon_white.bm",
2998 icon_white_bits, icon_white_width, icon_white_height);
2999 ReadBitmap(&bIconPixmap, "icon_black.bm",
3000 icon_black_bits, icon_black_width, icon_black_height);
3001 iconPixmap = wIconPixmap;
3003 XtSetArg(args[i], XtNiconPixmap, iconPixmap); i++;
3004 XtSetValues(shellWidget, args, i);
3007 * Create a cursor for the board widget.
3009 window_attributes.cursor = XCreateFontCursor(xDisplay, XC_hand2);
3010 XChangeWindowAttributes(xDisplay, xBoardWindow,
3011 CWCursor, &window_attributes);
3014 * Inhibit shell resizing.
3016 shellArgs[0].value = (XtArgVal) &w;
3017 shellArgs[1].value = (XtArgVal) &h;
3018 XtGetValues(shellWidget, shellArgs, 2);
3019 shellArgs[4].value = shellArgs[2].value = w;
3020 shellArgs[5].value = shellArgs[3].value = h;
3021 XtSetValues(shellWidget, &shellArgs[2], 4);
3022 marginW = w - boardWidth; // [HGM] needed to set new shellWidget size when we resize board
3023 marginH = h - boardHeight;
3025 CatchDeleteWindow(shellWidget, "QuitProc");
3030 if (appData.bitmapDirectory[0] != NULLCHAR) {
3037 /* Create regular pieces */
3038 if (!useImages) CreatePieces();
3043 if (appData.animate || appData.animateDragging)
3046 XtAugmentTranslations(formWidget,
3047 XtParseTranslationTable(globalTranslations));
3048 XtAugmentTranslations(boardWidget,
3049 XtParseTranslationTable(boardTranslations));
3050 XtAugmentTranslations(whiteTimerWidget,
3051 XtParseTranslationTable(whiteTranslations));
3052 XtAugmentTranslations(blackTimerWidget,
3053 XtParseTranslationTable(blackTranslations));
3055 /* Why is the following needed on some versions of X instead
3056 * of a translation? */
3057 XtAddEventHandler(boardWidget, ExposureMask, False,
3058 (XtEventHandler) EventProc, NULL);
3063 if (errorExitStatus == -1) {
3064 if (appData.icsActive) {
3065 /* We now wait until we see "login:" from the ICS before
3066 sending the logon script (problems with timestamp otherwise) */
3067 /*ICSInitScript();*/
3068 if (appData.icsInputBox) ICSInputBoxPopUp();
3071 signal(SIGINT, IntSigHandler);
3072 signal(SIGTERM, IntSigHandler);
3073 if (*appData.cmailGameName != NULLCHAR) {
3074 signal(SIGUSR1, CmailSigHandler);
3079 XtAppMainLoop(appContext);
3080 if (appData.debugMode) fclose(debugFP); // [DM] debug
3087 if (appData.icsActive && oldICSInteractionTitle != NULL) {
3088 DisplayIcsInteractionTitle(oldICSInteractionTitle);
3090 unlink(gameCopyFilename);
3091 unlink(gamePasteFilename);
3102 CmailSigHandler(sig)
3108 signal(SIGUSR1, SIG_IGN); /* suspend handler */
3110 /* Activate call-back function CmailSigHandlerCallBack() */
3111 OutputToProcess(cmailPR, (char *)(&dummy), sizeof(int), &error);
3113 signal(SIGUSR1, CmailSigHandler); /* re-activate handler */
3117 CmailSigHandlerCallBack(isr, closure, message, count, error)
3125 ReloadCmailMsgEvent(TRUE); /* Reload cmail msg */
3127 /**** end signal code ****/
3137 f = fopen(appData.icsLogon, "r");
3143 strcat(buf, appData.icsLogon);
3144 f = fopen(buf, "r");
3148 ProcessICSInitScript(f);
3155 EditCommentPopDown();
3166 SetMenuEnables(enab)
3170 if (!menuBarWidget) return;
3171 while (enab->name != NULL) {
3172 w = XtNameToWidget(menuBarWidget, enab->name);
3174 DisplayError(enab->name, 0);
3176 XtSetSensitive(w, enab->value);
3182 Enables icsEnables[] = {
3183 { "menuFile.Mail Move", False },
3184 { "menuFile.Reload CMail Message", False },
3185 { "menuMode.Machine Black", False },
3186 { "menuMode.Machine White", False },
3187 { "menuMode.Analysis Mode", False },
3188 { "menuMode.Analyze File", False },
3189 { "menuMode.Two Machines", False },
3191 { "menuHelp.Hint", False },
3192 { "menuHelp.Book", False },
3193 { "menuStep.Move Now", False },
3194 { "menuOptions.Periodic Updates", False },
3195 { "menuOptions.Hide Thinking", False },
3196 { "menuOptions.Ponder Next Move", False },
3201 Enables ncpEnables[] = {
3202 { "menuFile.Mail Move", False },
3203 { "menuFile.Reload CMail Message", False },
3204 { "menuMode.Machine White", False },
3205 { "menuMode.Machine Black", False },
3206 { "menuMode.Analysis Mode", False },
3207 { "menuMode.Analyze File", False },
3208 { "menuMode.Two Machines", False },
3209 { "menuMode.ICS Client", False },
3210 { "menuMode.ICS Input Box", False },
3211 { "Action", False },
3212 { "menuStep.Revert", False },
3213 { "menuStep.Move Now", False },
3214 { "menuStep.Retract Move", False },
3215 { "menuOptions.Auto Comment", False },
3216 { "menuOptions.Auto Flag", False },
3217 { "menuOptions.Auto Flip View", False },
3218 { "menuOptions.Auto Observe", False },
3219 { "menuOptions.Auto Raise Board", False },
3220 { "menuOptions.Get Move List", False },
3221 { "menuOptions.ICS Alarm", False },
3222 { "menuOptions.Move Sound", False },
3223 { "menuOptions.Quiet Play", False },
3224 { "menuOptions.Hide Thinking", False },
3225 { "menuOptions.Periodic Updates", False },
3226 { "menuOptions.Ponder Next Move", False },
3227 { "menuHelp.Hint", False },
3228 { "menuHelp.Book", False },
3232 Enables gnuEnables[] = {
3233 { "menuMode.ICS Client", False },
3234 { "menuMode.ICS Input Box", False },
3235 { "menuAction.Accept", False },
3236 { "menuAction.Decline", False },
3237 { "menuAction.Rematch", False },
3238 { "menuAction.Adjourn", False },
3239 { "menuAction.Stop Examining", False },
3240 { "menuAction.Stop Observing", False },
3241 { "menuStep.Revert", False },
3242 { "menuOptions.Auto Comment", False },
3243 { "menuOptions.Auto Observe", False },
3244 { "menuOptions.Auto Raise Board", False },
3245 { "menuOptions.Get Move List", False },
3246 { "menuOptions.Premove", False },
3247 { "menuOptions.Quiet Play", False },
3249 /* The next two options rely on SetCmailMode being called *after* */
3250 /* SetGNUMode so that when GNU is being used to give hints these */
3251 /* menu options are still available */
3253 { "menuFile.Mail Move", False },
3254 { "menuFile.Reload CMail Message", False },
3258 Enables cmailEnables[] = {
3260 { "menuAction.Call Flag", False },
3261 { "menuAction.Draw", True },
3262 { "menuAction.Adjourn", False },
3263 { "menuAction.Abort", False },
3264 { "menuAction.Stop Observing", False },
3265 { "menuAction.Stop Examining", False },
3266 { "menuFile.Mail Move", True },
3267 { "menuFile.Reload CMail Message", True },
3271 Enables trainingOnEnables[] = {
3272 { "menuMode.Edit Comment", False },
3273 { "menuMode.Pause", False },
3274 { "menuStep.Forward", False },
3275 { "menuStep.Backward", False },
3276 { "menuStep.Forward to End", False },
3277 { "menuStep.Back to Start", False },
3278 { "menuStep.Move Now", False },
3279 { "menuStep.Truncate Game", False },
3283 Enables trainingOffEnables[] = {
3284 { "menuMode.Edit Comment", True },
3285 { "menuMode.Pause", True },
3286 { "menuStep.Forward", True },
3287 { "menuStep.Backward", True },
3288 { "menuStep.Forward to End", True },
3289 { "menuStep.Back to Start", True },
3290 { "menuStep.Move Now", True },
3291 { "menuStep.Truncate Game", True },
3295 Enables machineThinkingEnables[] = {
3296 { "menuFile.Load Game", False },
3297 { "menuFile.Load Next Game", False },
3298 { "menuFile.Load Previous Game", False },
3299 { "menuFile.Reload Same Game", False },
3300 { "menuFile.Paste Game", False },
3301 { "menuFile.Load Position", False },
3302 { "menuFile.Load Next Position", False },
3303 { "menuFile.Load Previous Position", False },
3304 { "menuFile.Reload Same Position", False },
3305 { "menuFile.Paste Position", False },
3306 { "menuMode.Machine White", False },
3307 { "menuMode.Machine Black", False },
3308 { "menuMode.Two Machines", False },
3309 { "menuStep.Retract Move", False },
3313 Enables userThinkingEnables[] = {
3314 { "menuFile.Load Game", True },
3315 { "menuFile.Load Next Game", True },
3316 { "menuFile.Load Previous Game", True },
3317 { "menuFile.Reload Same Game", True },
3318 { "menuFile.Paste Game", True },
3319 { "menuFile.Load Position", True },
3320 { "menuFile.Load Next Position", True },
3321 { "menuFile.Load Previous Position", True },
3322 { "menuFile.Reload Same Position", True },
3323 { "menuFile.Paste Position", True },
3324 { "menuMode.Machine White", True },
3325 { "menuMode.Machine Black", True },
3326 { "menuMode.Two Machines", True },
3327 { "menuStep.Retract Move", True },
3333 SetMenuEnables(icsEnables);
3336 if (appData.zippyPlay && !appData.noChessProgram) /* [DM] icsEngineAnalyze */
3337 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Analysis Mode"), True);
3344 SetMenuEnables(ncpEnables);
3350 SetMenuEnables(gnuEnables);
3356 SetMenuEnables(cmailEnables);
3362 SetMenuEnables(trainingOnEnables);
3363 if (appData.showButtonBar) {
3364 XtSetSensitive(buttonBarWidget, False);
3370 SetTrainingModeOff()
3372 SetMenuEnables(trainingOffEnables);
3373 if (appData.showButtonBar) {
3374 XtSetSensitive(buttonBarWidget, True);
3379 SetUserThinkingEnables()
3381 if (appData.noChessProgram) return;
3382 SetMenuEnables(userThinkingEnables);
3386 SetMachineThinkingEnables()
3388 if (appData.noChessProgram) return;
3389 SetMenuEnables(machineThinkingEnables);
3391 case MachinePlaysBlack:
3392 case MachinePlaysWhite:
3393 case TwoMachinesPlay:
3394 XtSetSensitive(XtNameToWidget(menuBarWidget,
3395 ModeToWidgetName(gameMode)), True);
3402 #define Abs(n) ((n)<0 ? -(n) : (n))
3405 * Find a font that matches "pattern" that is as close as
3406 * possible to the targetPxlSize. Prefer fonts that are k
3407 * pixels smaller to fonts that are k pixels larger. The
3408 * pattern must be in the X Consortium standard format,
3409 * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".
3410 * The return value should be freed with XtFree when no
3413 char *FindFont(pattern, targetPxlSize)
3417 char **fonts, *p, *best, *scalable, *scalableTail;
3418 int i, j, nfonts, minerr, err, pxlSize;
3421 char **missing_list;
3423 char *def_string, *base_fnt_lst, strInt[3];
3425 XFontStruct **fnt_list;
3427 base_fnt_lst = calloc(1, strlen(pattern) + 3);
3428 sprintf(strInt, "%d", targetPxlSize);
3429 p = strstr(pattern, "--");
3430 strncpy(base_fnt_lst, pattern, p - pattern + 2);
3431 strcat(base_fnt_lst, strInt);
3432 strcat(base_fnt_lst, strchr(p + 2, '-'));
3434 if ((fntSet = XCreateFontSet(xDisplay,
3438 &def_string)) == NULL) {
3440 fprintf(stderr, _("Unable to create font set.\n"));
3444 nfonts = XFontsOfFontSet(fntSet, &fnt_list, &fonts);
3446 fonts = XListFonts(xDisplay, pattern, 999999, &nfonts);
3448 fprintf(stderr, _("%s: no fonts match pattern %s\n"),
3449 programName, pattern);
3457 for (i=0; i<nfonts; i++) {
3460 if (*p != '-') continue;
3462 if (*p == NULLCHAR) break;
3463 if (*p++ == '-') j++;
3465 if (j < 7) continue;
3468 scalable = fonts[i];
3471 err = pxlSize - targetPxlSize;
3472 if (Abs(err) < Abs(minerr) ||
3473 (minerr > 0 && err < 0 && -err == minerr)) {
3479 if (scalable && Abs(minerr) > appData.fontSizeTolerance) {
3480 /* If the error is too big and there is a scalable font,
3481 use the scalable font. */
3482 int headlen = scalableTail - scalable;
3483 p = (char *) XtMalloc(strlen(scalable) + 10);
3484 while (isdigit(*scalableTail)) scalableTail++;
3485 sprintf(p, "%.*s%d%s", headlen, scalable, targetPxlSize, scalableTail);
3487 p = (char *) XtMalloc(strlen(best) + 1);
3490 if (appData.debugMode) {
3491 fprintf(debugFP, _("resolved %s at pixel size %d\n to %s\n"),
3492 pattern, targetPxlSize, p);
3495 if (missing_count > 0)
3496 XFreeStringList(missing_list);
3497 XFreeFontSet(xDisplay, fntSet);
3499 XFreeFontNames(fonts);
3506 XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
3507 | GCBackground | GCFunction | GCPlaneMask;
3508 XGCValues gc_values;
3511 gc_values.plane_mask = AllPlanes;
3512 gc_values.line_width = lineGap;
3513 gc_values.line_style = LineSolid;
3514 gc_values.function = GXcopy;
3516 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3517 gc_values.background = XBlackPixel(xDisplay, xScreen);
3518 lineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3520 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3521 gc_values.background = XWhitePixel(xDisplay, xScreen);
3522 coordGC = XtGetGC(shellWidget, value_mask, &gc_values);
3523 XSetFont(xDisplay, coordGC, coordFontID);
3525 // [HGM] make font for holdings counts (white on black0
3526 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3527 gc_values.background = XBlackPixel(xDisplay, xScreen);
3528 countGC = XtGetGC(shellWidget, value_mask, &gc_values);
3529 XSetFont(xDisplay, countGC, countFontID);
3531 if (appData.monoMode) {
3532 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3533 gc_values.background = XWhitePixel(xDisplay, xScreen);
3534 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3536 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3537 gc_values.background = XBlackPixel(xDisplay, xScreen);
3538 lightSquareGC = wbPieceGC
3539 = XtGetGC(shellWidget, value_mask, &gc_values);
3541 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3542 gc_values.background = XWhitePixel(xDisplay, xScreen);
3543 darkSquareGC = bwPieceGC
3544 = XtGetGC(shellWidget, value_mask, &gc_values);
3546 if (DefaultDepth(xDisplay, xScreen) == 1) {
3547 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
3548 gc_values.function = GXcopyInverted;
3549 copyInvertedGC = XtGetGC(shellWidget, value_mask, &gc_values);
3550 gc_values.function = GXcopy;
3551 if (XBlackPixel(xDisplay, xScreen) == 1) {
3552 bwPieceGC = darkSquareGC;
3553 wbPieceGC = copyInvertedGC;
3555 bwPieceGC = copyInvertedGC;
3556 wbPieceGC = lightSquareGC;
3560 gc_values.foreground = highlightSquareColor;
3561 gc_values.background = highlightSquareColor;
3562 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3564 gc_values.foreground = premoveHighlightColor;
3565 gc_values.background = premoveHighlightColor;
3566 prelineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3568 gc_values.foreground = lightSquareColor;
3569 gc_values.background = darkSquareColor;
3570 lightSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3572 gc_values.foreground = darkSquareColor;
3573 gc_values.background = lightSquareColor;
3574 darkSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3576 gc_values.foreground = jailSquareColor;
3577 gc_values.background = jailSquareColor;
3578 jailSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3580 gc_values.foreground = whitePieceColor;
3581 gc_values.background = darkSquareColor;
3582 wdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3584 gc_values.foreground = whitePieceColor;
3585 gc_values.background = lightSquareColor;
3586 wlPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3588 gc_values.foreground = whitePieceColor;
3589 gc_values.background = jailSquareColor;
3590 wjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3592 gc_values.foreground = blackPieceColor;
3593 gc_values.background = darkSquareColor;
3594 bdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3596 gc_values.foreground = blackPieceColor;
3597 gc_values.background = lightSquareColor;
3598 blPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3600 gc_values.foreground = blackPieceColor;
3601 gc_values.background = jailSquareColor;
3602 bjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3606 void loadXIM(xim, xmask, filename, dest, mask)
3619 fp = fopen(filename, "rb");
3621 fprintf(stderr, _("%s: error loading XIM!\n"), programName);
3628 for (y=0; y<h; ++y) {
3629 for (x=0; x<h; ++x) {
3634 XPutPixel(xim, x, y, blackPieceColor);
3636 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3639 XPutPixel(xim, x, y, darkSquareColor);
3641 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3644 XPutPixel(xim, x, y, whitePieceColor);
3646 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3649 XPutPixel(xim, x, y, lightSquareColor);
3651 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3657 /* create Pixmap of piece */
3658 *dest = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3660 XPutImage(xDisplay, *dest, lightSquareGC, xim,
3663 /* create Pixmap of clipmask
3664 Note: We assume the white/black pieces have the same
3665 outline, so we make only 6 masks. This is okay
3666 since the XPM clipmask routines do the same. */
3668 temp = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3670 XPutImage(xDisplay, temp, lightSquareGC, xmask,
3673 /* now create the 1-bit version */
3674 *mask = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3677 values.foreground = 1;
3678 values.background = 0;
3680 /* Don't use XtGetGC, not read only */
3681 maskGC = XCreateGC(xDisplay, *mask,
3682 GCForeground | GCBackground, &values);
3683 XCopyPlane(xDisplay, temp, *mask, maskGC,
3684 0, 0, squareSize, squareSize, 0, 0, 1);
3685 XFreePixmap(xDisplay, temp);
3689 void CreateXIMPieces()
3694 static char *ximkind[] = { "ll", "ld", "dl", "dd" };
3699 /* The XSynchronize calls were copied from CreatePieces.
3700 Not sure if needed, but can't hurt */
3701 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3704 /* temp needed by loadXIM() */
3705 ximtemp = XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3706 0, 0, ss, ss, AllPlanes, XYPixmap);
3708 if (strlen(appData.pixmapDirectory) == 0) {
3712 if (appData.monoMode) {
3713 DisplayFatalError(_("XIM pieces cannot be used in monochrome mode"),
3717 fprintf(stderr, _("\nLoading XIMs...\n"));
3719 for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
3720 fprintf(stderr, "%d", piece+1);
3721 for (kind=0; kind<4; kind++) {
3722 fprintf(stderr, ".");
3723 snprintf(buf, sizeof(buf), "%s/%c%s%u.xim",
3724 ExpandPathName(appData.pixmapDirectory),
3725 ToLower(PieceToChar((ChessSquare)piece)),
3727 ximPieceBitmap[kind][piece] =
3728 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3729 0, 0, ss, ss, AllPlanes, XYPixmap);
3730 if (appData.debugMode)
3731 fprintf(stderr, _("(File:%s:) "), buf);
3732 loadXIM(ximPieceBitmap[kind][piece],
3734 &(xpmPieceBitmap[kind][piece]),
3735 &(ximMaskPm[piece%(int)BlackPawn]));
3737 fprintf(stderr," ");
3739 /* Load light and dark squares */
3740 /* If the LSQ and DSQ pieces don't exist, we will
3741 draw them with solid squares. */
3742 snprintf(buf,sizeof(buf), "%s/lsq%u.xim", ExpandPathName(appData.pixmapDirectory), ss);
3743 if (access(buf, 0) != 0) {
3747 fprintf(stderr, _("light square "));
3749 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3750 0, 0, ss, ss, AllPlanes, XYPixmap);
3751 if (appData.debugMode)
3752 fprintf(stderr, _("(File:%s:) "), buf);
3754 loadXIM(ximLightSquare, NULL, buf, &xpmLightSquare, NULL);
3755 fprintf(stderr, _("dark square "));
3756 snprintf(buf,sizeof(buf), "%s/dsq%u.xim",
3757 ExpandPathName(appData.pixmapDirectory), ss);
3758 if (appData.debugMode)
3759 fprintf(stderr, _("(File:%s:) "), buf);
3761 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3762 0, 0, ss, ss, AllPlanes, XYPixmap);
3763 loadXIM(ximDarkSquare, NULL, buf, &xpmDarkSquare, NULL);
3764 xpmJailSquare = xpmLightSquare;
3766 fprintf(stderr, _("Done.\n"));
3768 XSynchronize(xDisplay, False); /* Work-around for xlib/xt buffering bug */
3772 void CreateXPMPieces()
3776 u_int ss = squareSize;
3778 static char *xpmkind[] = { "ll", "ld", "dl", "dd" };
3779 XpmColorSymbol symbols[4];
3782 /* Apparently some versions of Xpm don't define XpmFormat at all --tpm */
3783 if (appData.debugMode) {
3784 fprintf(stderr, "XPM Library Version: %d.%d%c\n",
3785 XpmFormat, XpmVersion, (char)('a' + XpmRevision - 1));
3789 /* The XSynchronize calls were copied from CreatePieces.
3790 Not sure if needed, but can't hurt */
3791 XSynchronize(xDisplay, True); /* Work-around for xlib/xt buffering bug */
3793 /* Setup translations so piece colors match square colors */
3794 symbols[0].name = "light_piece";
3795 symbols[0].value = appData.whitePieceColor;
3796 symbols[1].name = "dark_piece";
3797 symbols[1].value = appData.blackPieceColor;
3798 symbols[2].name = "light_square";
3799 symbols[2].value = appData.lightSquareColor;
3800 symbols[3].name = "dark_square";
3801 symbols[3].value = appData.darkSquareColor;
3803 attr.valuemask = XpmColorSymbols;
3804 attr.colorsymbols = symbols;
3805 attr.numsymbols = 4;
3807 if (appData.monoMode) {
3808 DisplayFatalError(_("XPM pieces cannot be used in monochrome mode"),
3812 if (strlen(appData.pixmapDirectory) == 0) {
3813 XpmPieces* pieces = builtInXpms;
3816 while (pieces->size != squareSize && pieces->size) pieces++;
3817 if (!pieces->size) {
3818 fprintf(stderr, _("No builtin XPM pieces of size %d\n"), squareSize);
3821 for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
3822 for (kind=0; kind<4; kind++) {
3824 if ((r=XpmCreatePixmapFromData(xDisplay, xBoardWindow,
3825 pieces->xpm[piece][kind],
3826 &(xpmPieceBitmap[kind][piece]),
3827 NULL, &attr)) != 0) {
3828 fprintf(stderr, _("Error %d loading XPM image \"%s\"\n"),
3835 xpmJailSquare = xpmLightSquare;
3839 fprintf(stderr, _("\nLoading XPMs...\n"));
3842 for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
3843 fprintf(stderr, "%d ", piece+1);
3844 for (kind=0; kind<4; kind++) {
3845 snprintf(buf, sizeof(buf), "%s/%c%s%u.xpm",
3846 ExpandPathName(appData.pixmapDirectory),
3847 ToLower(PieceToChar((ChessSquare)piece)),
3849 if (appData.debugMode) {
3850 fprintf(stderr, _("(File:%s:) "), buf);
3852 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3853 &(xpmPieceBitmap[kind][piece]),
3854 NULL, &attr)) != 0) {
3855 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"),
3861 /* Load light and dark squares */
3862 /* If the LSQ and DSQ pieces don't exist, we will
3863 draw them with solid squares. */
3864 fprintf(stderr, _("light square "));
3865 snprintf(buf, sizeof(buf), "%s/lsq%u.xpm", ExpandPathName(appData.pixmapDirectory), ss);
3866 if (access(buf, 0) != 0) {
3870 if (appData.debugMode)
3871 fprintf(stderr, _("(File:%s:) "), buf);
3873 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3874 &xpmLightSquare, NULL, &attr)) != 0) {
3875 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
3878 fprintf(stderr, _("dark square "));
3879 snprintf(buf, sizeof(buf), "%s/dsq%u.xpm",
3880 ExpandPathName(appData.pixmapDirectory), ss);
3881 if (appData.debugMode) {
3882 fprintf(stderr, _("(File:%s:) "), buf);
3884 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3885 &xpmDarkSquare, NULL, &attr)) != 0) {
3886 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
3890 xpmJailSquare = xpmLightSquare;
3891 fprintf(stderr, _("Done.\n"));
3893 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3896 #endif /* HAVE_LIBXPM */
3899 /* No built-in bitmaps */
3904 u_int ss = squareSize;
3906 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3909 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
3910 for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
3911 sprintf(buf, "%c%u%c.bm", ToLower(PieceToChar((ChessSquare)piece)),
3912 ss, kind == SOLID ? 's' : 'o');
3913 ReadBitmap(&pieceBitmap[kind][piece], buf, NULL, ss, ss);
3917 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3921 /* With built-in bitmaps */
3924 BuiltInBits* bib = builtInBits;
3927 u_int ss = squareSize;
3929 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3932 while (bib->squareSize != ss && bib->squareSize != 0) bib++;
3934 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
3935 for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
3936 sprintf(buf, "%c%u%c.bm", ToLower(PieceToChar((ChessSquare)piece)),
3937 ss, kind == SOLID ? 's' : 'o');
3938 ReadBitmap(&pieceBitmap[kind][piece], buf,
3939 bib->bits[kind][piece], ss, ss);
3943 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3948 void ReadBitmap(pm, name, bits, wreq, hreq)
3951 unsigned char bits[];
3957 char msg[MSG_SIZ], fullname[MSG_SIZ];
3959 if (*appData.bitmapDirectory != NULLCHAR) {
3960 strcpy(fullname, appData.bitmapDirectory);
3961 strcat(fullname, "/");
3962 strcat(fullname, name);
3963 errcode = XReadBitmapFile(xDisplay, xBoardWindow, fullname,
3964 &w, &h, pm, &x_hot, &y_hot);
3965 if (errcode != BitmapSuccess) {
3967 case BitmapOpenFailed:
3968 snprintf(msg, sizeof(msg), _("Can't open bitmap file %s"), fullname);
3970 case BitmapFileInvalid:
3971 snprintf(msg, sizeof(msg), _("Invalid bitmap in file %s"), fullname);
3973 case BitmapNoMemory:
3974 snprintf(msg, sizeof(msg), _("Ran out of memory reading bitmap file %s"),
3978 snprintf(msg, sizeof(msg), _("Unknown XReadBitmapFile error %d on file %s"),
3982 fprintf(stderr, _("%s: %s...using built-in\n"),
3984 } else if (w != wreq || h != hreq) {
3986 _("%s: Bitmap %s is %dx%d, not %dx%d...using built-in\n"),
3987 programName, fullname, w, h, wreq, hreq);
3994 fprintf(stderr, _("%s: No built-in bitmap for %s; giving up\n"),
3998 ; // [HGM] bitmaps: make it non-fatal if we have no bitmap;
4000 *pm = XCreateBitmapFromData(xDisplay, xBoardWindow, (char *) bits,
4009 if (lineGap == 0) return;
4011 /* [HR] Split this into 2 loops for non-square boards. */
4013 for (i = 0; i < BOARD_HEIGHT + 1; i++) {
4014 gridSegments[i].x1 = 0;
4015 gridSegments[i].x2 =
4016 lineGap + BOARD_WIDTH * (squareSize + lineGap);
4017 gridSegments[i].y1 = gridSegments[i].y2
4018 = lineGap / 2 + (i * (squareSize + lineGap));
4021 for (j = 0; j < BOARD_WIDTH + 1; j++) {
4022 gridSegments[j + i].y1 = 0;
4023 gridSegments[j + i].y2 =
4024 lineGap + BOARD_HEIGHT * (squareSize + lineGap);
4025 gridSegments[j + i].x1 = gridSegments[j + i].x2
4026 = lineGap / 2 + (j * (squareSize + lineGap));
4030 static void MenuBarSelect(w, addr, index)
4035 XtActionProc proc = (XtActionProc) addr;
4037 (proc)(NULL, NULL, NULL, NULL);
4040 void CreateMenuBarPopup(parent, name, mb)
4050 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
4053 XtSetArg(args[j], XtNleftMargin, 20); j++;
4054 XtSetArg(args[j], XtNrightMargin, 20); j++;
4056 while (mi->string != NULL) {
4057 if (strcmp(mi->string, "----") == 0) {
4058 entry = XtCreateManagedWidget(mi->string, smeLineObjectClass,
4061 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string)));
4062 entry = XtCreateManagedWidget(mi->string, smeBSBObjectClass,
4064 XtAddCallback(entry, XtNcallback,
4065 (XtCallbackProc) MenuBarSelect,
4066 (caddr_t) mi->proc);
4072 Widget CreateMenuBar(mb)
4076 Widget anchor, menuBar;
4078 char menuName[MSG_SIZ];
4081 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
4082 XtSetArg(args[j], XtNvSpace, 0); j++;
4083 XtSetArg(args[j], XtNborderWidth, 0); j++;
4084 menuBar = XtCreateWidget("menuBar", boxWidgetClass,
4085 formWidget, args, j);
4087 while (mb->name != NULL) {
4088 strcpy(menuName, "menu");
4089 strcat(menuName, mb->name);
4091 XtSetArg(args[j], XtNmenuName, XtNewString(menuName)); j++;
4094 shortName[0] = _(mb->name)[0];
4095 shortName[1] = NULLCHAR;
4096 XtSetArg(args[j], XtNlabel, XtNewString(shortName)); j++;
4099 XtSetArg(args[j], XtNlabel, XtNewString(_(mb->name))); j++;
4102 XtSetArg(args[j], XtNborderWidth, 0); j++;
4103 anchor = XtCreateManagedWidget(mb->name, menuButtonWidgetClass,
4105 CreateMenuBarPopup(menuBar, menuName, mb);
4111 Widget CreateButtonBar(mi)
4115 Widget button, buttonBar;
4119 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
4121 XtSetArg(args[j], XtNhSpace, 0); j++;
4123 XtSetArg(args[j], XtNborderWidth, 0); j++;
4124 XtSetArg(args[j], XtNvSpace, 0); j++;
4125 buttonBar = XtCreateWidget("buttonBar", boxWidgetClass,
4126 formWidget, args, j);
4128 while (mi->string != NULL) {
4131 XtSetArg(args[j], XtNinternalWidth, 2); j++;
4132 XtSetArg(args[j], XtNborderWidth, 0); j++;
4134 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string))); j++;
4135 button = XtCreateManagedWidget(mi->string, commandWidgetClass,
4136 buttonBar, args, j);
4137 XtAddCallback(button, XtNcallback,
4138 (XtCallbackProc) MenuBarSelect,
4139 (caddr_t) mi->proc);
4146 CreatePieceMenu(name, color)
4153 ChessSquare selection;
4155 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
4156 boardWidget, args, 0);
4158 for (i = 0; i < PIECE_MENU_SIZE; i++) {
4159 String item = pieceMenuStrings[color][i];
4161 if (strcmp(item, "----") == 0) {
4162 entry = XtCreateManagedWidget(item, smeLineObjectClass,
4165 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
4166 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
4168 selection = pieceMenuTranslation[color][i];
4169 XtAddCallback(entry, XtNcallback,
4170 (XtCallbackProc) PieceMenuSelect,
4171 (caddr_t) selection);
4172 if (selection == WhitePawn || selection == BlackPawn) {
4173 XtSetArg(args[0], XtNpopupOnEntry, entry);
4174 XtSetValues(menu, args, 1);
4187 ChessSquare selection;
4189 whitePieceMenu = CreatePieceMenu("menuW", 0);
4190 blackPieceMenu = CreatePieceMenu("menuB", 1);
4192 XtRegisterGrabAction(PieceMenuPopup, True,
4193 (unsigned)(ButtonPressMask|ButtonReleaseMask),
4194 GrabModeAsync, GrabModeAsync);
4196 XtSetArg(args[0], XtNlabel, _("Drop"));
4197 dropMenu = XtCreatePopupShell("menuD", simpleMenuWidgetClass,
4198 boardWidget, args, 1);
4199 for (i = 0; i < DROP_MENU_SIZE; i++) {
4200 String item = dropMenuStrings[i];
4202 if (strcmp(item, "----") == 0) {
4203 entry = XtCreateManagedWidget(item, smeLineObjectClass,
4206 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
4207 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
4209 selection = dropMenuTranslation[i];
4210 XtAddCallback(entry, XtNcallback,
4211 (XtCallbackProc) DropMenuSelect,
4212 (caddr_t) selection);
4217 void SetupDropMenu()
4225 for (i=0; i<sizeof(dmEnables)/sizeof(DropMenuEnables); i++) {
4226 entry = XtNameToWidget(dropMenu, dmEnables[i].widget);
4227 p = strchr(gameMode == IcsPlayingWhite ? white_holding : black_holding,
4228 dmEnables[i].piece);
4229 XtSetSensitive(entry, p != NULL || !appData.testLegality
4230 /*!!temp:*/ || (gameInfo.variant == VariantCrazyhouse
4231 && !appData.icsActive));
4233 while (p && *p++ == dmEnables[i].piece) count++;
4234 snprintf(label, sizeof(label), "%s %d", dmEnables[i].widget, count);
4236 XtSetArg(args[j], XtNlabel, label); j++;
4237 XtSetValues(entry, args, j);
4241 void PieceMenuPopup(w, event, params, num_params)
4245 Cardinal *num_params;
4248 if (event->type != ButtonPress) return;
4249 if (errorUp) ErrorPopDown();
4253 whichMenu = params[0];
4255 case IcsPlayingWhite:
4256 case IcsPlayingBlack:
4258 case MachinePlaysWhite:
4259 case MachinePlaysBlack:
4260 if (appData.testLegality &&
4261 gameInfo.variant != VariantBughouse &&
4262 gameInfo.variant != VariantCrazyhouse) return;
4264 whichMenu = "menuD";
4270 if (((pmFromX = EventToSquare(event->xbutton.x, BOARD_WIDTH)) < 0) ||
4271 ((pmFromY = EventToSquare(event->xbutton.y, BOARD_HEIGHT)) < 0)) {
4272 pmFromX = pmFromY = -1;
4276 pmFromX = BOARD_WIDTH - 1 - pmFromX;
4278 pmFromY = BOARD_HEIGHT - 1 - pmFromY;
4280 XtPopupSpringLoaded(XtNameToWidget(boardWidget, whichMenu));
4283 static void PieceMenuSelect(w, piece, junk)
4288 if (pmFromX < 0 || pmFromY < 0) return;
4289 EditPositionMenuEvent(piece, pmFromX, pmFromY);
4292 static void DropMenuSelect(w, piece, junk)
4297 if (pmFromX < 0 || pmFromY < 0) return;
4298 DropMenuEvent(piece, pmFromX, pmFromY);
4301 void WhiteClock(w, event, prms, nprms)
4307 if (gameMode == EditPosition || gameMode == IcsExamining) {
4308 SetWhiteToPlayEvent();
4309 } else if (gameMode == IcsPlayingBlack || gameMode == MachinePlaysWhite) {
4314 void BlackClock(w, event, prms, nprms)
4320 if (gameMode == EditPosition || gameMode == IcsExamining) {
4321 SetBlackToPlayEvent();
4322 } else if (gameMode == IcsPlayingWhite || gameMode == MachinePlaysBlack) {
4329 * If the user selects on a border boundary, return -1; if off the board,
4330 * return -2. Otherwise map the event coordinate to the square.
4332 int EventToSquare(x, limit)
4340 if ((x % (squareSize + lineGap)) >= squareSize)
4342 x /= (squareSize + lineGap);
4348 static void do_flash_delay(msec)
4354 static void drawHighlight(file, rank, gc)
4360 if (lineGap == 0 || appData.blindfold) return;
4363 x = lineGap/2 + ((BOARD_WIDTH-1)-file) *
4364 (squareSize + lineGap);
4365 y = lineGap/2 + rank * (squareSize + lineGap);
4367 x = lineGap/2 + file * (squareSize + lineGap);
4368 y = lineGap/2 + ((BOARD_HEIGHT-1)-rank) *
4369 (squareSize + lineGap);
4372 XDrawRectangle(xDisplay, xBoardWindow, gc, x, y,
4373 squareSize+lineGap, squareSize+lineGap);
4376 int hi1X = -1, hi1Y = -1, hi2X = -1, hi2Y = -1;
4377 int pm1X = -1, pm1Y = -1, pm2X = -1, pm2Y = -1;
4380 SetHighlights(fromX, fromY, toX, toY)
4381 int fromX, fromY, toX, toY;
4383 if (hi1X != fromX || hi1Y != fromY) {
4384 if (hi1X >= 0 && hi1Y >= 0) {
4385 drawHighlight(hi1X, hi1Y, lineGC);
4387 if (fromX >= 0 && fromY >= 0) {
4388 drawHighlight(fromX, fromY, highlineGC);
4391 if (hi2X != toX || hi2Y != toY) {
4392 if (hi2X >= 0 && hi2Y >= 0) {
4393 drawHighlight(hi2X, hi2Y, lineGC);
4395 if (toX >= 0 && toY >= 0) {
4396 drawHighlight(toX, toY, highlineGC);
4408 SetHighlights(-1, -1, -1, -1);
4413 SetPremoveHighlights(fromX, fromY, toX, toY)
4414 int fromX, fromY, toX, toY;
4416 if (pm1X != fromX || pm1Y != fromY) {
4417 if (pm1X >= 0 && pm1Y >= 0) {
4418 drawHighlight(pm1X, pm1Y, lineGC);
4420 if (fromX >= 0 && fromY >= 0) {
4421 drawHighlight(fromX, fromY, prelineGC);
4424 if (pm2X != toX || pm2Y != toY) {
4425 if (pm2X >= 0 && pm2Y >= 0) {
4426 drawHighlight(pm2X, pm2Y, lineGC);
4428 if (toX >= 0 && toY >= 0) {
4429 drawHighlight(toX, toY, prelineGC);
4439 ClearPremoveHighlights()
4441 SetPremoveHighlights(-1, -1, -1, -1);
4444 static void BlankSquare(x, y, color, piece, dest)
4449 if (useImages && useImageSqs) {
4453 pm = xpmLightSquare;
4458 case 2: /* neutral */
4463 XCopyArea(xDisplay, pm, dest, wlPieceGC, 0, 0,
4464 squareSize, squareSize, x, y);
4474 case 2: /* neutral */
4479 XFillRectangle(xDisplay, dest, gc, x, y, squareSize, squareSize);
4484 I split out the routines to draw a piece so that I could
4485 make a generic flash routine.
4487 static void monoDrawPiece_1bit(piece, square_color, x, y, dest)
4489 int square_color, x, y;
4492 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
4493 switch (square_color) {
4495 case 2: /* neutral */
4497 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
4498 ? *pieceToOutline(piece)
4499 : *pieceToSolid(piece),
4500 dest, bwPieceGC, 0, 0,
4501 squareSize, squareSize, x, y);
4504 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
4505 ? *pieceToSolid(piece)
4506 : *pieceToOutline(piece),
4507 dest, wbPieceGC, 0, 0,
4508 squareSize, squareSize, x, y);
4513 static void monoDrawPiece(piece, square_color, x, y, dest)
4515 int square_color, x, y;
4518 switch (square_color) {
4520 case 2: /* neutral */
4522 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
4523 ? *pieceToOutline(piece)
4524 : *pieceToSolid(piece),
4525 dest, bwPieceGC, 0, 0,
4526 squareSize, squareSize, x, y, 1);
4529 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
4530 ? *pieceToSolid(piece)
4531 : *pieceToOutline(piece),
4532 dest, wbPieceGC, 0, 0,
4533 squareSize, squareSize, x, y, 1);
4538 static void colorDrawPiece(piece, square_color, x, y, dest)
4540 int square_color, x, y;
4543 if(pieceToSolid(piece) == NULL) return; // [HGM] bitmaps: make it non-fatal if we have no bitmap;
4544 switch (square_color) {
4546 XCopyPlane(xDisplay, *pieceToSolid(piece),
4547 dest, (int) piece < (int) BlackPawn
4548 ? wlPieceGC : blPieceGC, 0, 0,
4549 squareSize, squareSize, x, y, 1);
4552 XCopyPlane(xDisplay, *pieceToSolid(piece),
4553 dest, (int) piece < (int) BlackPawn
4554 ? wdPieceGC : bdPieceGC, 0, 0,
4555 squareSize, squareSize, x, y, 1);
4557 case 2: /* neutral */
4559 XCopyPlane(xDisplay, *pieceToSolid(piece),
4560 dest, (int) piece < (int) BlackPawn
4561 ? wjPieceGC : bjPieceGC, 0, 0,
4562 squareSize, squareSize, x, y, 1);
4567 static void colorDrawPieceImage(piece, square_color, x, y, dest)
4569 int square_color, x, y;
4574 switch (square_color) {
4576 case 2: /* neutral */
4578 if ((int)piece < (int) BlackPawn) {
4586 if ((int)piece < (int) BlackPawn) {
4594 XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
4595 dest, wlPieceGC, 0, 0,
4596 squareSize, squareSize, x, y);
4599 typedef void (*DrawFunc)();
4601 DrawFunc ChooseDrawFunc()
4603 if (appData.monoMode) {
4604 if (DefaultDepth(xDisplay, xScreen) == 1) {
4605 return monoDrawPiece_1bit;
4607 return monoDrawPiece;
4611 return colorDrawPieceImage;
4613 return colorDrawPiece;
4617 /* [HR] determine square color depending on chess variant. */
4618 static int SquareColor(row, column)
4623 if (gameInfo.variant == VariantXiangqi) {
4624 if (column >= 3 && column <= 5 && row >= 0 && row <= 2) {
4626 } else if (column >= 3 && column <= 5 && row >= 7 && row <= 9) {
4628 } else if (row <= 4) {
4634 square_color = ((column + row) % 2) == 1;
4637 /* [hgm] holdings: next line makes all holdings squares light */
4638 if(column < BOARD_LEFT || column >= BOARD_RGHT) square_color = 1;
4640 return square_color;
4643 void DrawSquare(row, column, piece, do_flash)
4644 int row, column, do_flash;
4647 int square_color, x, y, direction, font_ascent, font_descent;
4650 XCharStruct overall;
4654 if(gameInfo.variant == VariantShogi) { // [HGM] shogi: in shogi Q is used for Lance
4655 if(piece == WhiteQueen) piece = WhiteLance; else
4656 if(piece == BlackQueen) piece = BlackLance;
4659 else if(gameInfo.variant == VariantGothic) { // [HGM] shogi: in Gothic Chancelor has alternative look
4660 if(piece == WhiteMarshall) piece = WhiteSilver; else
4661 if(piece == BlackMarshall) piece = BlackSilver;
4665 /* Calculate delay in milliseconds (2-delays per complete flash) */
4666 flash_delay = 500 / appData.flashRate;
4669 x = lineGap + ((BOARD_WIDTH-1)-column) *
4670 (squareSize + lineGap);
4671 y = lineGap + row * (squareSize + lineGap);
4673 x = lineGap + column * (squareSize + lineGap);
4674 y = lineGap + ((BOARD_HEIGHT-1)-row) *
4675 (squareSize + lineGap);
4678 square_color = SquareColor(row, column);
4680 if ( // [HGM] holdings: blank out area between board and holdings
4681 column == BOARD_LEFT-1 || column == BOARD_RGHT
4682 || (column == BOARD_LEFT-2 && row < BOARD_HEIGHT-gameInfo.holdingsSize)
4683 || (column == BOARD_RGHT+1 && row >= gameInfo.holdingsSize) ) {
4684 BlankSquare(x, y, 2, EmptySquare, xBoardWindow);
4686 // [HGM] print piece counts next to holdings
4687 string[1] = NULLCHAR;
4688 if (column == (flipView ? BOARD_LEFT-1 : BOARD_RGHT) && piece > 1 ) {
4689 string[0] = '0' + piece;
4690 XTextExtents(countFontStruct, string, 1, &direction,
4691 &font_ascent, &font_descent, &overall);
4692 if (appData.monoMode) {
4693 XDrawImageString(xDisplay, xBoardWindow, countGC,
4694 x + squareSize - overall.width - 2,
4695 y + font_ascent + 1, string, 1);
4697 XDrawString(xDisplay, xBoardWindow, countGC,
4698 x + squareSize - overall.width - 2,
4699 y + font_ascent + 1, string, 1);
4702 if (column == (flipView ? BOARD_RGHT : BOARD_LEFT-1) && piece > 1) {
4703 string[0] = '0' + piece;
4704 XTextExtents(countFontStruct, string, 1, &direction,
4705 &font_ascent, &font_descent, &overall);
4706 if (appData.monoMode) {
4707 XDrawImageString(xDisplay, xBoardWindow, countGC,
4708 x + 2, y + font_ascent + 1, string, 1);
4710 XDrawString(xDisplay, xBoardWindow, countGC,
4711 x + 2, y + font_ascent + 1, string, 1);
4715 if (piece == EmptySquare || appData.blindfold) {
4716 BlankSquare(x, y, square_color, piece, xBoardWindow);
4718 drawfunc = ChooseDrawFunc();
4719 if (do_flash && appData.flashCount > 0) {
4720 for (i=0; i<appData.flashCount; ++i) {
4722 drawfunc(piece, square_color, x, y, xBoardWindow);
4723 XSync(xDisplay, False);
4724 do_flash_delay(flash_delay);
4726 BlankSquare(x, y, square_color, piece, xBoardWindow);
4727 XSync(xDisplay, False);
4728 do_flash_delay(flash_delay);
4731 drawfunc(piece, square_color, x, y, xBoardWindow);
4735 string[1] = NULLCHAR;
4736 if (appData.showCoords && row == (flipView ? BOARD_HEIGHT-1 : 0)
4737 && column >= BOARD_LEFT && column < BOARD_RGHT) {
4738 string[0] = 'a' + column - BOARD_LEFT;
4739 XTextExtents(coordFontStruct, string, 1, &direction,
4740 &font_ascent, &font_descent, &overall);
4741 if (appData.monoMode) {
4742 XDrawImageString(xDisplay, xBoardWindow, coordGC,
4743 x + squareSize - overall.width - 2,
4744 y + squareSize - font_descent - 1, string, 1);
4746 XDrawString(xDisplay, xBoardWindow, coordGC,
4747 x + squareSize - overall.width - 2,
4748 y + squareSize - font_descent - 1, string, 1);
4751 if (appData.showCoords && column == (flipView ? BOARD_RGHT-1 : BOARD_LEFT)) {
4752 string[0] = ONE + row;
4753 XTextExtents(coordFontStruct, string, 1, &direction,
4754 &font_ascent, &font_descent, &overall);
4755 if (appData.monoMode) {
4756 XDrawImageString(xDisplay, xBoardWindow, coordGC,
4757 x + 2, y + font_ascent + 1, string, 1);
4759 XDrawString(xDisplay, xBoardWindow, coordGC,
4760 x + 2, y + font_ascent + 1, string, 1);
4766 /* Why is this needed on some versions of X? */
4767 void EventProc(widget, unused, event)
4772 if (!XtIsRealized(widget))
4775 switch (event->type) {
4777 if (event->xexpose.count > 0) return; /* no clipping is done */
4778 XDrawPosition(widget, True, NULL);
4786 void DrawPosition(fullRedraw, board)
4787 /*Boolean*/int fullRedraw;
4790 XDrawPosition(boardWidget, fullRedraw, board);
4793 /* Returns 1 if there are "too many" differences between b1 and b2
4794 (i.e. more than 1 move was made) */
4795 static int too_many_diffs(b1, b2)
4801 for (i=0; i<BOARD_HEIGHT; ++i) {
4802 for (j=0; j<BOARD_WIDTH; ++j) {
4803 if (b1[i][j] != b2[i][j]) {
4804 if (++c > 4) /* Castling causes 4 diffs */
4813 /* Matrix describing castling maneuvers */
4814 /* Row, ColRookFrom, ColKingFrom, ColRookTo, ColKingTo */
4815 static int castling_matrix[4][5] = {
4816 { 0, 0, 4, 3, 2 }, /* 0-0-0, white */
4817 { 0, 7, 4, 5, 6 }, /* 0-0, white */
4818 { 7, 0, 4, 3, 2 }, /* 0-0-0, black */
4819 { 7, 7, 4, 5, 6 } /* 0-0, black */
4822 /* Checks whether castling occurred. If it did, *rrow and *rcol
4823 are set to the destination (row,col) of the rook that moved.
4825 Returns 1 if castling occurred, 0 if not.
4827 Note: Only handles a max of 1 castling move, so be sure
4828 to call too_many_diffs() first.
4830 static int check_castle_draw(newb, oldb, rrow, rcol)
4837 /* For each type of castling... */
4838 for (i=0; i<4; ++i) {
4839 r = castling_matrix[i];
4841 /* Check the 4 squares involved in the castling move */
4843 for (j=1; j<=4; ++j) {
4844 if (newb[r[0]][r[j]] == oldb[r[0]][r[j]]) {
4851 /* All 4 changed, so it must be a castling move */
4860 static int damage[BOARD_SIZE][BOARD_SIZE];
4863 * event handler for redrawing the board
4865 void XDrawPosition(w, repaint, board)
4867 /*Boolean*/int repaint;
4871 static int lastFlipView = 0;
4872 static int lastBoardValid = 0;
4873 static Board lastBoard;
4877 if (board == NULL) {
4878 if (!lastBoardValid) return;
4881 if (!lastBoardValid || lastFlipView != flipView) {
4882 XtSetArg(args[0], XtNleftBitmap, (flipView ? xMarkPixmap : None));
4883 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flip View"),
4888 * It would be simpler to clear the window with XClearWindow()
4889 * but this causes a very distracting flicker.
4892 if (!repaint && lastBoardValid && lastFlipView == flipView) {
4894 /* If too much changes (begin observing new game, etc.), don't
4896 do_flash = too_many_diffs(board, lastBoard) ? 0 : 1;
4898 /* Special check for castling so we don't flash both the king
4899 and the rook (just flash the king). */
4901 if (check_castle_draw(board, lastBoard, &rrow, &rcol)) {
4902 /* Draw rook with NO flashing. King will be drawn flashing later */
4903 DrawSquare(rrow, rcol, board[rrow][rcol], 0);
4904 lastBoard[rrow][rcol] = board[rrow][rcol];
4908 /* First pass -- Draw (newly) empty squares and repair damage.
4909 This prevents you from having a piece show up twice while it
4910 is flashing on its new square */
4911 for (i = 0; i < BOARD_HEIGHT; i++)
4912 for (j = 0; j < BOARD_WIDTH; j++)
4913 if ((board[i][j] != lastBoard[i][j] && board[i][j] == EmptySquare)
4915 DrawSquare(i, j, board[i][j], 0);
4916 damage[i][j] = False;
4919 /* Second pass -- Draw piece(s) in new position and flash them */
4920 for (i = 0; i < BOARD_HEIGHT; i++)
4921 for (j = 0; j < BOARD_WIDTH; j++)
4922 if (board[i][j] != lastBoard[i][j]) {
4923 DrawSquare(i, j, board[i][j], do_flash);
4927 XDrawSegments(xDisplay, xBoardWindow, lineGC,
4928 gridSegments, BOARD_HEIGHT + BOARD_WIDTH + 2);
4930 for (i = 0; i < BOARD_HEIGHT; i++)
4931 for (j = 0; j < BOARD_WIDTH; j++) {
4932 DrawSquare(i, j, board[i][j], 0);
4933 damage[i][j] = False;
4937 CopyBoard(lastBoard, board);
4939 lastFlipView = flipView;
4941 /* Draw highlights */
4942 if (pm1X >= 0 && pm1Y >= 0) {
4943 drawHighlight(pm1X, pm1Y, prelineGC);
4945 if (pm2X >= 0 && pm2Y >= 0) {
4946 drawHighlight(pm2X, pm2Y, prelineGC);
4948 if (hi1X >= 0 && hi1Y >= 0) {
4949 drawHighlight(hi1X, hi1Y, highlineGC);
4951 if (hi2X >= 0 && hi2Y >= 0) {
4952 drawHighlight(hi2X, hi2Y, highlineGC);
4955 /* If piece being dragged around board, must redraw that too */
4958 XSync(xDisplay, False);
4963 * event handler for redrawing the board
4965 void DrawPositionProc(w, event, prms, nprms)
4971 XDrawPosition(w, True, NULL);
4976 * event handler for parsing user moves
4978 // [HGM] This routine will need quite some reworking. Although the backend still supports the old
4979 // way of doing things, by calling UserMoveEvent() to test the legality of the move and then perform
4980 // it at the end, and doing all kind of preliminary tests here (e.g. to weed out self-captures), it
4981 // should be made to use the new way, of calling UserMoveTest early to determine the legality of the
4982 // move, (which will weed out the illegal selfcaptures and moves into the holdings, and flag promotions),
4983 // and at the end FinishMove() to perform the move after optional promotion popups.
4984 // For now I patched it to allow self-capture with King, and suppress clicks between board and holdings.
4985 void HandleUserMove(w, event, prms, nprms)
4992 Boolean saveAnimate;
4993 static int second = 0;
4995 if (w != boardWidget || errorExitStatus != -1) return;
4997 if (event->type == ButtonPress) ErrorPopDown();
5000 if (event->type == ButtonPress) {
5001 XtPopdown(promotionShell);
5002 XtDestroyWidget(promotionShell);
5003 promotionUp = False;
5011 x = EventToSquare(event->xbutton.x, BOARD_WIDTH);
5012 y = EventToSquare(event->xbutton.y, BOARD_HEIGHT);
5013 if (!flipView && y >= 0) {
5014 y = BOARD_HEIGHT - 1 - y;
5016 if (flipView && x >= 0) {
5017 x = BOARD_WIDTH - 1 - x;
5020 /* [HGM] holdings: next 5 lines: ignore all clicks between board and holdings */
5021 if(event->type == ButtonPress
5022 && ( x == BOARD_LEFT-1 || x == BOARD_RGHT
5023 || x == BOARD_LEFT-2 && y < BOARD_HEIGHT-gameInfo.holdingsSize
5024 || x == BOARD_RGHT+1 && y >= gameInfo.holdingsSize) )
5028 if (event->type == ButtonPress) {
5030 if (OKToStartUserMove(x, y)) {
5034 DragPieceBegin(event->xbutton.x, event->xbutton.y);
5035 if (appData.highlightDragging) {
5036 SetHighlights(x, y, -1, -1);
5044 if (event->type == ButtonPress && gameMode != EditPosition &&
5049 /* Check if clicking again on the same color piece */
5050 fromP = boards[currentMove][fromY][fromX];
5051 toP = boards[currentMove][y][x];
5052 if ((WhitePawn <= fromP && fromP < WhiteKing && // [HGM] this test should go, as UserMoveTest now does it.
5053 WhitePawn <= toP && toP <= WhiteKing) || // For now I made it less critical by exempting King
5054 (BlackPawn <= fromP && fromP < BlackKing && // moves, to not interfere with FRC castlings.
5055 BlackPawn <= toP && toP <= BlackKing)) {
5056 /* Clicked again on same color piece -- changed his mind */
5057 second = (x == fromX && y == fromY);
5058 if (appData.highlightDragging) {
5059 SetHighlights(x, y, -1, -1);
5063 if (OKToStartUserMove(x, y)) {
5066 DragPieceBegin(event->xbutton.x, event->xbutton.y);
5072 if (event->type == ButtonRelease && x == fromX && y == fromY) {
5073 DragPieceEnd(event->xbutton.x, event->xbutton.y);
5074 if (appData.animateDragging) {
5075 /* Undo animation damage if any */
5076 DrawPosition(FALSE, NULL);
5079 /* Second up/down in same square; just abort move */
5084 ClearPremoveHighlights();
5086 /* First upclick in same square; start click-click mode */
5087 SetHighlights(x, y, -1, -1);
5092 /* Completed move */
5095 saveAnimate = appData.animate;
5096 if (event->type == ButtonPress) {
5097 /* Finish clickclick move */
5098 if (appData.animate || appData.highlightLastMove) {
5099 SetHighlights(fromX, fromY, toX, toY);
5104 /* Finish drag move */
5105 if (appData.highlightLastMove) {
5106 SetHighlights(fromX, fromY, toX, toY);
5110 DragPieceEnd(event->xbutton.x, event->xbutton.y);
5111 /* Don't animate move and drag both */
5112 appData.animate = FALSE;
5114 if (IsPromotion(fromX, fromY, toX, toY)) {
5115 if (appData.alwaysPromoteToQueen) {
5116 UserMoveEvent(fromX, fromY, toX, toY, 'q');
5117 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
5118 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
5121 SetHighlights(fromX, fromY, toX, toY);
5125 UserMoveEvent(fromX, fromY, toX, toY, NULLCHAR);
5126 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
5127 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
5130 appData.animate = saveAnimate;
5131 if (appData.animate || appData.animateDragging) {
5132 /* Undo animation damage if needed */
5133 DrawPosition(FALSE, NULL);
5137 void AnimateUserMove (Widget w, XEvent * event,
5138 String * params, Cardinal * nParams)
5140 DragPieceMove(event->xmotion.x, event->xmotion.y);
5143 Widget CommentCreate(name, text, mutable, callback, lines)
5145 int /*Boolean*/ mutable;
5146 XtCallbackProc callback;
5150 Widget shell, layout, form, edit, b_ok, b_cancel, b_clear, b_close, b_edit;
5155 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5156 XtGetValues(boardWidget, args, j);
5159 XtSetArg(args[j], XtNresizable, True); j++;
5162 XtCreatePopupShell(name, topLevelShellWidgetClass,
5163 shellWidget, args, j);
5166 XtCreatePopupShell(name, transientShellWidgetClass,
5167 shellWidget, args, j);
5170 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
5171 layoutArgs, XtNumber(layoutArgs));
5173 XtCreateManagedWidget("form", formWidgetClass, layout,
5174 formArgs, XtNumber(formArgs));
5178 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
5179 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
5181 XtSetArg(args[j], XtNstring, text); j++;
5182 XtSetArg(args[j], XtNtop, XtChainTop); j++;
5183 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5184 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5185 XtSetArg(args[j], XtNright, XtChainRight); j++;
5186 XtSetArg(args[j], XtNresizable, True); j++;
5187 XtSetArg(args[j], XtNwidth, bw_width); j++; /*force wider than buttons*/
5189 XtSetArg(args[j], XtNscrollVertical, XawtextScrollWhenNeeded); j++;
5191 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
5192 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
5194 XtSetArg(args[j], XtNautoFill, True); j++;
5195 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
5197 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
5201 XtSetArg(args[j], XtNfromVert, edit); j++;
5202 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5203 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5204 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5205 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5207 XtCreateManagedWidget(_("ok"), commandWidgetClass, form, args, j);
5208 XtAddCallback(b_ok, XtNcallback, callback, (XtPointer) 0);
5211 XtSetArg(args[j], XtNfromVert, edit); j++;
5212 XtSetArg(args[j], XtNfromHoriz, b_ok); j++;
5213 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5214 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5215 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5216 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5218 XtCreateManagedWidget(_("cancel"), commandWidgetClass, form, args, j);
5219 XtAddCallback(b_cancel, XtNcallback, callback, (XtPointer) 0);
5222 XtSetArg(args[j], XtNfromVert, edit); j++;
5223 XtSetArg(args[j], XtNfromHoriz, b_cancel); j++;
5224 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5225 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5226 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5227 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5229 XtCreateManagedWidget(_("clear"), commandWidgetClass, form, args, j);
5230 XtAddCallback(b_clear, XtNcallback, callback, (XtPointer) 0);
5233 XtSetArg(args[j], XtNfromVert, edit); j++;
5234 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5235 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5236 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5237 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5239 XtCreateManagedWidget(_("close"), commandWidgetClass, form, args, j);
5240 XtAddCallback(b_close, XtNcallback, callback, (XtPointer) 0);
5243 XtSetArg(args[j], XtNfromVert, edit); j++;
5244 XtSetArg(args[j], XtNfromHoriz, b_close); j++;
5245 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5246 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5247 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5248 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5250 XtCreateManagedWidget(_("edit"), commandWidgetClass, form, args, j);
5251 XtAddCallback(b_edit, XtNcallback, callback, (XtPointer) 0);
5254 XtRealizeWidget(shell);
5256 if (commentX == -1) {
5259 Dimension pw_height;
5260 Dimension ew_height;
5263 XtSetArg(args[j], XtNheight, &ew_height); j++;
5264 XtGetValues(edit, args, j);
5267 XtSetArg(args[j], XtNheight, &pw_height); j++;
5268 XtGetValues(shell, args, j);
5269 commentH = pw_height + (lines - 1) * ew_height;
5270 commentW = bw_width - 16;
5272 XSync(xDisplay, False);
5274 /* This code seems to tickle an X bug if it is executed too soon
5275 after xboard starts up. The coordinates get transformed as if
5276 the main window was positioned at (0, 0).
5278 XtTranslateCoords(shellWidget,
5279 (bw_width - commentW) / 2, 0 - commentH / 2,
5280 &commentX, &commentY);
5282 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
5283 RootWindowOfScreen(XtScreen(shellWidget)),
5284 (bw_width - commentW) / 2, 0 - commentH / 2,
5289 if (commentY < 0) commentY = 0; /*avoid positioning top offscreen*/
5292 XtSetArg(args[j], XtNheight, commentH); j++;
5293 XtSetArg(args[j], XtNwidth, commentW); j++;
5294 XtSetArg(args[j], XtNx, commentX); j++;
5295 XtSetArg(args[j], XtNy, commentY); j++;
5296 XtSetValues(shell, args, j);
5297 XtSetKeyboardFocus(shell, edit);
5302 /* Used for analysis window and ICS input window */
5303 Widget MiscCreate(name, text, mutable, callback, lines)
5305 int /*Boolean*/ mutable;
5306 XtCallbackProc callback;
5310 Widget shell, layout, form, edit;
5312 Dimension bw_width, pw_height, ew_height, w, h;
5318 XtSetArg(args[j], XtNresizable, True); j++;
5321 XtCreatePopupShell(name, topLevelShellWidgetClass,
5322 shellWidget, args, j);
5325 XtCreatePopupShell(name, transientShellWidgetClass,
5326 shellWidget, args, j);
5329 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
5330 layoutArgs, XtNumber(layoutArgs));
5332 XtCreateManagedWidget("form", formWidgetClass, layout,
5333 formArgs, XtNumber(formArgs));
5337 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
5338 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
5340 XtSetArg(args[j], XtNstring, text); j++;
5341 XtSetArg(args[j], XtNtop, XtChainTop); j++;
5342 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5343 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5344 XtSetArg(args[j], XtNright, XtChainRight); j++;
5345 XtSetArg(args[j], XtNresizable, True); j++;
5347 XtSetArg(args[j], XtNscrollVertical, XawtextScrollWhenNeeded); j++;
5349 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
5350 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
5352 XtSetArg(args[j], XtNautoFill, True); j++;
5353 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
5355 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
5357 XtRealizeWidget(shell);
5360 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5361 XtGetValues(boardWidget, args, j);
5364 XtSetArg(args[j], XtNheight, &ew_height); j++;
5365 XtGetValues(edit, args, j);
5368 XtSetArg(args[j], XtNheight, &pw_height); j++;
5369 XtGetValues(shell, args, j);
5370 h = pw_height + (lines - 1) * ew_height;
5373 XSync(xDisplay, False);
5375 /* This code seems to tickle an X bug if it is executed too soon
5376 after xboard starts up. The coordinates get transformed as if
5377 the main window was positioned at (0, 0).
5379 XtTranslateCoords(shellWidget, (bw_width - w) / 2, 0 - h / 2, &x, &y);
5381 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
5382 RootWindowOfScreen(XtScreen(shellWidget)),
5383 (bw_width - w) / 2, 0 - h / 2, &xx, &yy, &junk);
5387 if (y < 0) y = 0; /*avoid positioning top offscreen*/
5390 XtSetArg(args[j], XtNheight, h); j++;
5391 XtSetArg(args[j], XtNwidth, w); j++;
5392 XtSetArg(args[j], XtNx, x); j++;
5393 XtSetArg(args[j], XtNy, y); j++;
5394 XtSetValues(shell, args, j);
5400 static int savedIndex; /* gross that this is global */
5402 void EditCommentPopUp(index, title, text)
5411 if (text == NULL) text = "";
5413 if (editShell == NULL) {
5415 CommentCreate(title, text, True, EditCommentCallback, 4);
5416 XtRealizeWidget(editShell);
5417 CatchDeleteWindow(editShell, "EditCommentPopDown");
5419 edit = XtNameToWidget(editShell, "*form.text");
5421 XtSetArg(args[j], XtNstring, text); j++;
5422 XtSetValues(edit, args, j);
5424 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5425 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5426 XtSetValues(editShell, args, j);
5429 XtPopup(editShell, XtGrabNone);
5433 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
5434 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
5438 void EditCommentCallback(w, client_data, call_data)
5440 XtPointer client_data, call_data;
5448 XtSetArg(args[j], XtNlabel, &name); j++;
5449 XtGetValues(w, args, j);
5451 if (strcmp(name, _("ok")) == 0) {
5452 edit = XtNameToWidget(editShell, "*form.text");
5454 XtSetArg(args[j], XtNstring, &val); j++;
5455 XtGetValues(edit, args, j);
5456 ReplaceComment(savedIndex, val);
5457 EditCommentPopDown();
5458 } else if (strcmp(name, _("cancel")) == 0) {
5459 EditCommentPopDown();
5460 } else if (strcmp(name, _("clear")) == 0) {
5461 edit = XtNameToWidget(editShell, "*form.text");
5462 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
5463 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
5467 void EditCommentPopDown()
5472 if (!editUp) return;
5474 XtSetArg(args[j], XtNx, &commentX); j++;
5475 XtSetArg(args[j], XtNy, &commentY); j++;
5476 XtSetArg(args[j], XtNheight, &commentH); j++;
5477 XtSetArg(args[j], XtNwidth, &commentW); j++;
5478 XtGetValues(editShell, args, j);
5479 XtPopdown(editShell);
5482 XtSetArg(args[j], XtNleftBitmap, None); j++;
5483 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
5487 void ICSInputBoxPopUp()
5492 char *title = _("ICS Input");
5495 if (ICSInputShell == NULL) {
5496 ICSInputShell = MiscCreate(title, "", True, NULL, 1);
5497 tr = XtParseTranslationTable(ICSInputTranslations);
5498 edit = XtNameToWidget(ICSInputShell, "*form.text");
5499 XtOverrideTranslations(edit, tr);
5500 XtRealizeWidget(ICSInputShell);
5501 CatchDeleteWindow(ICSInputShell, "ICSInputBoxPopDown");
5504 edit = XtNameToWidget(ICSInputShell, "*form.text");
5506 XtSetArg(args[j], XtNstring, ""); j++;
5507 XtSetValues(edit, args, j);
5509 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5510 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5511 XtSetValues(ICSInputShell, args, j);
5514 XtPopup(ICSInputShell, XtGrabNone);
5515 XtSetKeyboardFocus(ICSInputShell, edit);
5517 ICSInputBoxUp = True;
5519 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
5520 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
5524 void ICSInputSendText()
5531 edit = XtNameToWidget(ICSInputShell, "*form.text");
5533 XtSetArg(args[j], XtNstring, &val); j++;
5534 XtGetValues(edit, args, j);
5535 SendMultiLineToICS(val);
5536 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
5537 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
5540 void ICSInputBoxPopDown()
5545 if (!ICSInputBoxUp) return;
5547 XtPopdown(ICSInputShell);
5548 ICSInputBoxUp = False;
5550 XtSetArg(args[j], XtNleftBitmap, None); j++;
5551 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
5555 void CommentPopUp(title, text)
5562 if (commentShell == NULL) {
5564 CommentCreate(title, text, False, CommentCallback, 4);
5565 XtRealizeWidget(commentShell);
5566 CatchDeleteWindow(commentShell, "CommentPopDown");
5568 edit = XtNameToWidget(commentShell, "*form.text");
5570 XtSetArg(args[j], XtNstring, text); j++;
5571 XtSetValues(edit, args, j);
5573 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5574 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5575 XtSetValues(commentShell, args, j);
5578 XtPopup(commentShell, XtGrabNone);
5579 XSync(xDisplay, False);
5584 void AnalysisPopUp(title, text)
5591 if (analysisShell == NULL) {
5592 analysisShell = MiscCreate(title, text, False, NULL, 4);
5593 XtRealizeWidget(analysisShell);
5594 CatchDeleteWindow(analysisShell, "AnalysisPopDown");
5597 edit = XtNameToWidget(analysisShell, "*form.text");
5599 XtSetArg(args[j], XtNstring, text); j++;
5600 XtSetValues(edit, args, j);
5602 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5603 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5604 XtSetValues(analysisShell, args, j);
5608 XtPopup(analysisShell, XtGrabNone);
5610 XSync(xDisplay, False);
5615 void CommentCallback(w, client_data, call_data)
5617 XtPointer client_data, call_data;
5624 XtSetArg(args[j], XtNlabel, &name); j++;
5625 XtGetValues(w, args, j);
5627 if (strcmp(name, _("close")) == 0) {
5629 } else if (strcmp(name, _("edit")) == 0) {
5636 void CommentPopDown()
5641 if (!commentUp) return;
5643 XtSetArg(args[j], XtNx, &commentX); j++;
5644 XtSetArg(args[j], XtNy, &commentY); j++;
5645 XtSetArg(args[j], XtNwidth, &commentW); j++;
5646 XtSetArg(args[j], XtNheight, &commentH); j++;
5647 XtGetValues(commentShell, args, j);
5648 XtPopdown(commentShell);
5649 XSync(xDisplay, False);
5653 void AnalysisPopDown()
5655 if (!analysisUp) return;
5656 XtPopdown(analysisShell);
5657 XSync(xDisplay, False);
5659 if (appData.icsEngineAnalyze) ExitAnalyzeMode(); /* [DM] icsEngineAnalyze */
5663 void FileNamePopUp(label, def, proc, openMode)
5670 Widget popup, layout, dialog, edit;
5676 fileProc = proc; /* I can't see a way not */
5677 fileOpenMode = openMode; /* to use globals here */
5680 XtSetArg(args[i], XtNresizable, True); i++;
5681 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
5682 XtSetArg(args[i], XtNtitle, XtNewString(_("File name prompt"))); i++;
5683 fileNameShell = popup =
5684 XtCreatePopupShell("File name prompt", transientShellWidgetClass,
5685 shellWidget, args, i);
5688 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
5689 layoutArgs, XtNumber(layoutArgs));
5692 XtSetArg(args[i], XtNlabel, label); i++;
5693 XtSetArg(args[i], XtNvalue, def); i++;
5694 XtSetArg(args[i], XtNborderWidth, 0); i++;
5695 dialog = XtCreateManagedWidget("fileName", dialogWidgetClass,
5698 XawDialogAddButton(dialog, _("ok"), FileNameCallback, (XtPointer) dialog);
5699 XawDialogAddButton(dialog, _("cancel"), FileNameCallback,
5700 (XtPointer) dialog);
5702 XtRealizeWidget(popup);
5703 CatchDeleteWindow(popup, "FileNamePopDown");
5705 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
5706 &x, &y, &win_x, &win_y, &mask);
5708 XtSetArg(args[0], XtNx, x - 10);
5709 XtSetArg(args[1], XtNy, y - 30);
5710 XtSetValues(popup, args, 2);
5712 XtPopup(popup, XtGrabExclusive);
5715 edit = XtNameToWidget(dialog, "*value");
5716 XtSetKeyboardFocus(popup, edit);
5719 void FileNamePopDown()
5721 if (!filenameUp) return;
5722 XtPopdown(fileNameShell);
5723 XtDestroyWidget(fileNameShell);
5728 void FileNameCallback(w, client_data, call_data)
5730 XtPointer client_data, call_data;
5735 XtSetArg(args[0], XtNlabel, &name);
5736 XtGetValues(w, args, 1);
5738 if (strcmp(name, _("cancel")) == 0) {
5743 FileNameAction(w, NULL, NULL, NULL);
5746 void FileNameAction(w, event, prms, nprms)
5758 name = XawDialogGetValueString(w = XtParent(w));
5760 if ((name != NULL) && (*name != NULLCHAR)) {
5762 XtPopdown(w = XtParent(XtParent(w)));
5766 p = strrchr(buf, ' ');
5773 fullname = ExpandPathName(buf);
5775 ErrorPopUp(_("Error"), _("Can't open file"), FALSE);
5778 f = fopen(fullname, fileOpenMode);
5780 DisplayError(_("Failed to open file"), errno);
5782 (void) (*fileProc)(f, index, buf);
5789 XtPopdown(w = XtParent(XtParent(w)));
5795 void PromotionPopUp()
5798 Widget dialog, layout;
5800 Dimension bw_width, pw_width;
5804 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5805 XtGetValues(boardWidget, args, j);
5808 XtSetArg(args[j], XtNresizable, True); j++;
5809 XtSetArg(args[j], XtNtitle, XtNewString(_("Promotion"))); j++;
5811 XtCreatePopupShell("Promotion", transientShellWidgetClass,
5812 shellWidget, args, j);
5814 XtCreateManagedWidget(layoutName, formWidgetClass, promotionShell,
5815 layoutArgs, XtNumber(layoutArgs));
5818 XtSetArg(args[j], XtNlabel, _("Promote pawn to what?")); j++;
5819 XtSetArg(args[j], XtNborderWidth, 0); j++;
5820 dialog = XtCreateManagedWidget("promotion", dialogWidgetClass,
5823 XawDialogAddButton(dialog, _("Queen"), PromotionCallback,
5824 (XtPointer) dialog);
5825 XawDialogAddButton(dialog, _("Rook"), PromotionCallback,
5826 (XtPointer) dialog);
5827 XawDialogAddButton(dialog, _("Bishop"), PromotionCallback,
5828 (XtPointer) dialog);
5829 XawDialogAddButton(dialog, _("Knight"), PromotionCallback,
5830 (XtPointer) dialog);
5831 if (!appData.testLegality || gameInfo.variant == VariantSuicide ||
5832 gameInfo.variant == VariantGiveaway) {
5833 XawDialogAddButton(dialog, _("King"), PromotionCallback,
5834 (XtPointer) dialog);
5836 XawDialogAddButton(dialog, _("cancel"), PromotionCallback,
5837 (XtPointer) dialog);
5839 XtRealizeWidget(promotionShell);
5840 CatchDeleteWindow(promotionShell, "PromotionPopDown");
5843 XtSetArg(args[j], XtNwidth, &pw_width); j++;
5844 XtGetValues(promotionShell, args, j);
5846 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
5847 lineGap + squareSize/3 +
5848 ((toY == BOARD_HEIGHT-1) ^ (flipView) ?
5849 0 : 6*(squareSize + lineGap)), &x, &y);
5852 XtSetArg(args[j], XtNx, x); j++;
5853 XtSetArg(args[j], XtNy, y); j++;
5854 XtSetValues(promotionShell, args, j);
5856 XtPopup(promotionShell, XtGrabNone);
5861 void PromotionPopDown()
5863 if (!promotionUp) return;
5864 XtPopdown(promotionShell);
5865 XtDestroyWidget(promotionShell);
5866 promotionUp = False;
5869 void PromotionCallback(w, client_data, call_data)
5871 XtPointer client_data, call_data;
5877 XtSetArg(args[0], XtNlabel, &name);
5878 XtGetValues(w, args, 1);
5882 if (fromX == -1) return;
5884 if (strcmp(name, _("cancel")) == 0) {
5888 } else if (strcmp(name, _("Knight")) == 0) {
5891 promoChar = ToLower(name[0]);
5894 UserMoveEvent(fromX, fromY, toX, toY, promoChar);
5896 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
5897 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
5902 void ErrorCallback(w, client_data, call_data)
5904 XtPointer client_data, call_data;
5907 XtPopdown(w = XtParent(XtParent(XtParent(w))));
5909 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
5915 if (!errorUp) return;
5917 XtPopdown(errorShell);
5918 XtDestroyWidget(errorShell);
5919 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
5922 void ErrorPopUp(title, label, modal)
5923 char *title, *label;
5927 Widget dialog, layout;
5931 Dimension bw_width, pw_width;
5932 Dimension pw_height;
5936 XtSetArg(args[i], XtNresizable, True); i++;
5937 XtSetArg(args[i], XtNtitle, title); i++;
5939 XtCreatePopupShell("errorpopup", transientShellWidgetClass,
5940 shellWidget, args, i);
5942 XtCreateManagedWidget(layoutName, formWidgetClass, errorShell,
5943 layoutArgs, XtNumber(layoutArgs));
5946 XtSetArg(args[i], XtNlabel, label); i++;
5947 XtSetArg(args[i], XtNborderWidth, 0); i++;
5948 dialog = XtCreateManagedWidget("dialog", dialogWidgetClass,
5951 XawDialogAddButton(dialog, _("ok"), ErrorCallback, (XtPointer) dialog);
5953 XtRealizeWidget(errorShell);
5954 CatchDeleteWindow(errorShell, "ErrorPopDown");
5957 XtSetArg(args[i], XtNwidth, &bw_width); i++;
5958 XtGetValues(boardWidget, args, i);
5960 XtSetArg(args[i], XtNwidth, &pw_width); i++;
5961 XtSetArg(args[i], XtNheight, &pw_height); i++;
5962 XtGetValues(errorShell, args, i);
5965 /* This code seems to tickle an X bug if it is executed too soon
5966 after xboard starts up. The coordinates get transformed as if
5967 the main window was positioned at (0, 0).
5969 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
5970 0 - pw_height + squareSize / 3, &x, &y);
5972 XTranslateCoordinates(xDisplay, XtWindow(boardWidget),
5973 RootWindowOfScreen(XtScreen(boardWidget)),
5974 (bw_width - pw_width) / 2,
5975 0 - pw_height + squareSize / 3, &xx, &yy, &junk);
5979 if (y < 0) y = 0; /*avoid positioning top offscreen*/
5982 XtSetArg(args[i], XtNx, x); i++;
5983 XtSetArg(args[i], XtNy, y); i++;
5984 XtSetValues(errorShell, args, i);
5987 XtPopup(errorShell, modal ? XtGrabExclusive : XtGrabNone);
5990 /* Disable all user input other than deleting the window */
5991 static int frozen = 0;
5995 /* Grab by a widget that doesn't accept input */
5996 XtAddGrab(messageWidget, TRUE, FALSE);
6000 /* Undo a FreezeUI */
6003 if (!frozen) return;
6004 XtRemoveGrab(messageWidget);
6008 char *ModeToWidgetName(mode)
6012 case BeginningOfGame:
6013 if (appData.icsActive)
6014 return "menuMode.ICS Client";
6015 else if (appData.noChessProgram ||
6016 *appData.cmailGameName != NULLCHAR)
6017 return "menuMode.Edit Game";
6019 return "menuMode.Machine Black";
6020 case MachinePlaysBlack:
6021 return "menuMode.Machine Black";
6022 case MachinePlaysWhite:
6023 return "menuMode.Machine White";
6025 return "menuMode.Analysis Mode";
6027 return "menuMode.Analyze File";
6028 case TwoMachinesPlay:
6029 return "menuMode.Two Machines";
6031 return "menuMode.Edit Game";
6032 case PlayFromGameFile:
6033 return "menuFile.Load Game";
6035 return "menuMode.Edit Position";
6037 return "menuMode.Training";
6038 case IcsPlayingWhite:
6039 case IcsPlayingBlack:
6043 return "menuMode.ICS Client";
6050 void ModeHighlight()
6053 static int oldPausing = FALSE;
6054 static GameMode oldmode = (GameMode) -1;
6057 if (!boardWidget || !XtIsRealized(boardWidget)) return;
6059 if (pausing != oldPausing) {
6060 oldPausing = pausing;
6062 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6064 XtSetArg(args[0], XtNleftBitmap, None);
6066 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Pause"),
6069 if (appData.showButtonBar) {
6072 XtSetArg(args[0], XtNbackground, buttonForegroundPixel);
6073 XtSetArg(args[1], XtNforeground, buttonBackgroundPixel);
6075 XtSetArg(args[0], XtNbackground, buttonBackgroundPixel);
6076 XtSetArg(args[1], XtNforeground, buttonForegroundPixel);
6079 /* Always toggle, don't set. Previous code messes up when
6080 invoked while the button is pressed, as releasing it
6081 toggles the state again. */
6084 XtSetArg(args[0], XtNbackground, &oldbg);
6085 XtSetArg(args[1], XtNforeground, &oldfg);
6086 XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON),
6088 XtSetArg(args[0], XtNbackground, oldfg);
6089 XtSetArg(args[1], XtNforeground, oldbg);
6092 XtSetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
6096 wname = ModeToWidgetName(oldmode);
6097 if (wname != NULL) {
6098 XtSetArg(args[0], XtNleftBitmap, None);
6099 XtSetValues(XtNameToWidget(menuBarWidget, wname), args, 1);
6101 wname = ModeToWidgetName(gameMode);
6102 if (wname != NULL) {
6103 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6104 XtSetValues(XtNameToWidget(menuBarWidget, wname), args, 1);
6108 /* Maybe all the enables should be handled here, not just this one */
6109 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Training"),
6110 gameMode == Training || gameMode == PlayFromGameFile);
6115 * Button/menu procedures
6117 void ResetProc(w, event, prms, nprms)
6127 int LoadGamePopUp(f, gameNumber, title)
6132 cmailMsgLoaded = FALSE;
6133 if (gameNumber == 0) {
6134 int error = GameListBuild(f);
6136 DisplayError(_("Cannot build game list"), error);
6137 } else if (!ListEmpty(&gameList) &&
6138 ((ListGame *) gameList.tailPred)->number > 1) {
6139 GameListPopUp(f, title);
6145 return LoadGame(f, gameNumber, title, FALSE);
6148 void LoadGameProc(w, event, prms, nprms)
6154 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
6157 FileNamePopUp(_("Load game file name?"), "", LoadGamePopUp, "rb");
6160 void LoadNextGameProc(w, event, prms, nprms)
6169 void LoadPrevGameProc(w, event, prms, nprms)
6178 void ReloadGameProc(w, event, prms, nprms)
6187 void LoadNextPositionProc(w, event, prms, nprms)
6196 void LoadPrevPositionProc(w, event, prms, nprms)
6205 void ReloadPositionProc(w, event, prms, nprms)
6214 void LoadPositionProc(w, event, prms, nprms)
6220 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
6223 FileNamePopUp(_("Load position file name?"), "", LoadPosition, "rb");
6226 void SaveGameProc(w, event, prms, nprms)
6232 FileNamePopUp(_("Save game file name?"),
6233 DefaultFileName(appData.oldSaveStyle ? "game" : "pgn"),
6237 void SavePositionProc(w, event, prms, nprms)
6243 FileNamePopUp(_("Save position file name?"),
6244 DefaultFileName(appData.oldSaveStyle ? "pos" : "fen"),
6248 void ReloadCmailMsgProc(w, event, prms, nprms)
6254 ReloadCmailMsgEvent(FALSE);
6257 void MailMoveProc(w, event, prms, nprms)
6266 /* this variable is shared between CopyPositionProc and SendPositionSelection */
6267 static char *selected_fen_position=NULL;
6270 SendPositionSelection(Widget w, Atom *selection, Atom *target,
6271 Atom *type_return, XtPointer *value_return,
6272 unsigned long *length_return, int *format_return)
6274 char *selection_tmp;
6276 if (!selected_fen_position) return False; /* should never happen */
6277 if (*target == XA_STRING){
6278 /* note: since no XtSelectionDoneProc was registered, Xt will
6279 * automatically call XtFree on the value returned. So have to
6280 * make a copy of it allocated with XtMalloc */
6281 selection_tmp= XtMalloc(strlen(selected_fen_position)+16);
6282 strcpy(selection_tmp, selected_fen_position);
6284 *value_return=selection_tmp;
6285 *length_return=strlen(selection_tmp);
6286 *type_return=XA_STRING;
6287 *format_return = 8; /* bits per byte */
6294 /* note: when called from menu all parameters are NULL, so no clue what the
6295 * Widget which was clicked on was, or what the click event was
6297 void CopyPositionProc(w, event, prms, nprms)
6305 if (selected_fen_position) free(selected_fen_position);
6306 selected_fen_position = (char *)PositionToFEN(currentMove, NULL);
6307 if (!selected_fen_position) return;
6308 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
6310 SendPositionSelection,
6311 NULL/* lose_ownership_proc */ ,
6312 NULL/* transfer_done_proc */);
6314 free(selected_fen_position);
6315 selected_fen_position=NULL;
6319 /* function called when the data to Paste is ready */
6321 PastePositionCB(Widget w, XtPointer client_data, Atom *selection,
6322 Atom *type, XtPointer value, unsigned long *len, int *format)
6325 if (value==NULL || *len==0) return; /* nothing had been selected to copy */
6326 fenstr[*len]='\0'; /* normally this string is terminated, but be safe */
6327 EditPositionPasteFEN(fenstr);
6331 /* called when Paste Position button is pressed,
6332 * all parameters will be NULL */
6333 void PastePositionProc(w, event, prms, nprms)
6339 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
6340 /* (XtSelectionCallbackProc) */ PastePositionCB,
6341 NULL, /* client_data passed to PastePositionCB */
6343 /* better to use the time field from the event that triggered the
6344 * call to this function, but that isn't trivial to get
6352 SendGameSelection(Widget w, Atom *selection, Atom *target,
6353 Atom *type_return, XtPointer *value_return,
6354 unsigned long *length_return, int *format_return)
6356 char *selection_tmp;
6358 if (*target == XA_STRING){
6359 FILE* f = fopen(gameCopyFilename, "r");
6362 if (f == NULL) return False;
6366 selection_tmp = XtMalloc(len + 1);
6367 count = fread(selection_tmp, 1, len, f);
6369 XtFree(selection_tmp);
6372 selection_tmp[len] = NULLCHAR;
6373 *value_return = selection_tmp;
6374 *length_return = len;
6375 *type_return = XA_STRING;
6376 *format_return = 8; /* bits per byte */
6383 /* note: when called from menu all parameters are NULL, so no clue what the
6384 * Widget which was clicked on was, or what the click event was
6386 void CopyGameProc(w, event, prms, nprms)
6394 ret = SaveGameToFile(gameCopyFilename, FALSE);
6397 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
6400 NULL/* lose_ownership_proc */ ,
6401 NULL/* transfer_done_proc */);
6404 /* function called when the data to Paste is ready */
6406 PasteGameCB(Widget w, XtPointer client_data, Atom *selection,
6407 Atom *type, XtPointer value, unsigned long *len, int *format)
6410 if (value == NULL || *len == 0) {
6411 return; /* nothing had been selected to copy */
6413 f = fopen(gamePasteFilename, "w");
6415 DisplayError(_("Can't open temp file"), errno);
6418 fwrite(value, 1, *len, f);
6421 LoadGameFromFile(gamePasteFilename, 0, gamePasteFilename, TRUE);
6424 /* called when Paste Game button is pressed,
6425 * all parameters will be NULL */
6426 void PasteGameProc(w, event, prms, nprms)
6432 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
6433 /* (XtSelectionCallbackProc) */ PasteGameCB,
6434 NULL, /* client_data passed to PasteGameCB */
6436 /* better to use the time field from the event that triggered the
6437 * call to this function, but that isn't trivial to get
6447 SaveGameProc(NULL, NULL, NULL, NULL);
6451 void QuitProc(w, event, prms, nprms)
6460 void PauseProc(w, event, prms, nprms)
6470 void MachineBlackProc(w, event, prms, nprms)
6476 MachineBlackEvent();
6479 void MachineWhiteProc(w, event, prms, nprms)
6485 MachineWhiteEvent();
6488 void AnalyzeModeProc(w, event, prms, nprms)
6496 if (!first.analysisSupport) {
6497 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
6498 DisplayError(buf, 0);
6501 /* [DM] icsEngineAnalyze [HGM] This is horrible code; reverse the gameMode and isEngineAnalyze tests! */
6502 if (appData.icsActive) {
6503 if (gameMode != IcsObserving) {
6504 sprintf(buf,_("You are not observing a game"));
6505 DisplayError(buf, 0);
6507 if (appData.icsEngineAnalyze) {
6508 if (appData.debugMode)
6509 fprintf(debugFP, _("Found unexpected active ICS engine analyze \n"));
6515 /* if enable, use want disable icsEngineAnalyze */
6516 if (appData.icsEngineAnalyze) {
6521 appData.icsEngineAnalyze = TRUE;
6522 if (appData.debugMode)
6523 fprintf(debugFP, _("ICS engine analyze starting... \n"));
6525 if (!appData.showThinking)
6526 ShowThinkingProc(w,event,prms,nprms);
6531 void AnalyzeFileProc(w, event, prms, nprms)
6537 if (!first.analysisSupport) {
6539 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
6540 DisplayError(buf, 0);
6545 if (!appData.showThinking)
6546 ShowThinkingProc(w,event,prms,nprms);
6549 FileNamePopUp(_("File to analyze"), "", LoadGamePopUp, "rb");
6550 AnalysisPeriodicEvent(1);
6553 void TwoMachinesProc(w, event, prms, nprms)
6562 void IcsClientProc(w, event, prms, nprms)
6571 void EditGameProc(w, event, prms, nprms)
6580 void EditPositionProc(w, event, prms, nprms)
6586 EditPositionEvent();
6589 void TrainingProc(w, event, prms, nprms)
6598 void EditCommentProc(w, event, prms, nprms)
6605 EditCommentPopDown();
6611 void IcsInputBoxProc(w, event, prms, nprms)
6617 if (ICSInputBoxUp) {
6618 ICSInputBoxPopDown();
6624 void AcceptProc(w, event, prms, nprms)
6633 void DeclineProc(w, event, prms, nprms)
6642 void RematchProc(w, event, prms, nprms)
6651 void CallFlagProc(w, event, prms, nprms)
6660 void DrawProc(w, event, prms, nprms)
6669 void AbortProc(w, event, prms, nprms)
6678 void AdjournProc(w, event, prms, nprms)
6687 void ResignProc(w, event, prms, nprms)
6696 void AdjuWhiteProc(w, event, prms, nprms)
6702 UserAdjudicationEvent(+1);
6705 void AdjuBlackProc(w, event, prms, nprms)
6711 UserAdjudicationEvent(-1);
6714 void AdjuDrawProc(w, event, prms, nprms)
6720 UserAdjudicationEvent(0);
6723 void EnterKeyProc(w, event, prms, nprms)
6729 if (ICSInputBoxUp == True)
6733 void StopObservingProc(w, event, prms, nprms)
6739 StopObservingEvent();
6742 void StopExaminingProc(w, event, prms, nprms)
6748 StopExaminingEvent();
6752 void ForwardProc(w, event, prms, nprms)
6762 void BackwardProc(w, event, prms, nprms)
6771 void ToStartProc(w, event, prms, nprms)
6780 void ToEndProc(w, event, prms, nprms)
6789 void RevertProc(w, event, prms, nprms)
6798 void TruncateGameProc(w, event, prms, nprms)
6804 TruncateGameEvent();
6806 void RetractMoveProc(w, event, prms, nprms)
6815 void MoveNowProc(w, event, prms, nprms)
6825 void AlwaysQueenProc(w, event, prms, nprms)
6833 appData.alwaysPromoteToQueen = !appData.alwaysPromoteToQueen;
6835 if (appData.alwaysPromoteToQueen) {
6836 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6838 XtSetArg(args[0], XtNleftBitmap, None);
6840 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
6844 void AnimateDraggingProc(w, event, prms, nprms)
6852 appData.animateDragging = !appData.animateDragging;
6854 if (appData.animateDragging) {
6855 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6858 XtSetArg(args[0], XtNleftBitmap, None);
6860 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Dragging"),
6864 void AnimateMovingProc(w, event, prms, nprms)
6872 appData.animate = !appData.animate;
6874 if (appData.animate) {
6875 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6878 XtSetArg(args[0], XtNleftBitmap, None);
6880 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
6884 void AutocommProc(w, event, prms, nprms)
6892 appData.autoComment = !appData.autoComment;
6894 if (appData.autoComment) {
6895 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6897 XtSetArg(args[0], XtNleftBitmap, None);
6899 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
6904 void AutoflagProc(w, event, prms, nprms)
6912 appData.autoCallFlag = !appData.autoCallFlag;
6914 if (appData.autoCallFlag) {
6915 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6917 XtSetArg(args[0], XtNleftBitmap, None);
6919 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
6923 void AutoflipProc(w, event, prms, nprms)
6931 appData.autoFlipView = !appData.autoFlipView;
6933 if (appData.autoFlipView) {
6934 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6936 XtSetArg(args[0], XtNleftBitmap, None);
6938 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flip View"),
6942 void AutobsProc(w, event, prms, nprms)
6950 appData.autoObserve = !appData.autoObserve;
6952 if (appData.autoObserve) {
6953 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6955 XtSetArg(args[0], XtNleftBitmap, None);
6957 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
6961 void AutoraiseProc(w, event, prms, nprms)
6969 appData.autoRaiseBoard = !appData.autoRaiseBoard;
6971 if (appData.autoRaiseBoard) {
6972 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6974 XtSetArg(args[0], XtNleftBitmap, None);
6976 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Raise Board"),
6980 void AutosaveProc(w, event, prms, nprms)
6988 appData.autoSaveGames = !appData.autoSaveGames;
6990 if (appData.autoSaveGames) {
6991 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6993 XtSetArg(args[0], XtNleftBitmap, None);
6995 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
6999 void BlindfoldProc(w, event, prms, nprms)
7007 appData.blindfold = !appData.blindfold;
7009 if (appData.blindfold) {
7010 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7012 XtSetArg(args[0], XtNleftBitmap, None);
7014 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Blindfold"),
7017 DrawPosition(True, NULL);
7020 void TestLegalityProc(w, event, prms, nprms)
7028 appData.testLegality = !appData.testLegality;
7030 if (appData.testLegality) {
7031 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7033 XtSetArg(args[0], XtNleftBitmap, None);
7035 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Test Legality"),
7040 void FlashMovesProc(w, event, prms, nprms)
7048 if (appData.flashCount == 0) {
7049 appData.flashCount = 3;
7051 appData.flashCount = -appData.flashCount;
7054 if (appData.flashCount > 0) {
7055 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7057 XtSetArg(args[0], XtNleftBitmap, None);
7059 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flash Moves"),
7063 void FlipViewProc(w, event, prms, nprms)
7069 flipView = !flipView;
7070 DrawPosition(True, NULL);
7073 void GetMoveListProc(w, event, prms, nprms)
7081 appData.getMoveList = !appData.getMoveList;
7083 if (appData.getMoveList) {
7084 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7087 XtSetArg(args[0], XtNleftBitmap, None);
7089 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
7094 void HighlightDraggingProc(w, event, prms, nprms)
7102 appData.highlightDragging = !appData.highlightDragging;
7104 if (appData.highlightDragging) {
7105 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7107 XtSetArg(args[0], XtNleftBitmap, None);
7109 XtSetValues(XtNameToWidget(menuBarWidget,
7110 "menuOptions.Highlight Dragging"), args, 1);
7114 void HighlightLastMoveProc(w, event, prms, nprms)
7122 appData.highlightLastMove = !appData.highlightLastMove;
7124 if (appData.highlightLastMove) {
7125 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7127 XtSetArg(args[0], XtNleftBitmap, None);
7129 XtSetValues(XtNameToWidget(menuBarWidget,
7130 "menuOptions.Highlight Last Move"), args, 1);
7133 void IcsAlarmProc(w, event, prms, nprms)
7141 appData.icsAlarm = !appData.icsAlarm;
7143 if (appData.icsAlarm) {
7144 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7146 XtSetArg(args[0], XtNleftBitmap, None);
7148 XtSetValues(XtNameToWidget(menuBarWidget,
7149 "menuOptions.ICS Alarm"), args, 1);
7152 void MoveSoundProc(w, event, prms, nprms)
7160 appData.ringBellAfterMoves = !appData.ringBellAfterMoves;
7162 if (appData.ringBellAfterMoves) {
7163 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7165 XtSetArg(args[0], XtNleftBitmap, None);
7167 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
7172 void OldSaveStyleProc(w, event, prms, nprms)
7180 appData.oldSaveStyle = !appData.oldSaveStyle;
7182 if (appData.oldSaveStyle) {
7183 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7185 XtSetArg(args[0], XtNleftBitmap, None);
7187 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Old Save Style"),
7191 void PeriodicUpdatesProc(w, event, prms, nprms)
7199 PeriodicUpdatesEvent(!appData.periodicUpdates);
7201 if (appData.periodicUpdates) {
7202 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7204 XtSetArg(args[0], XtNleftBitmap, None);
7206 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Periodic Updates"),
7210 void PonderNextMoveProc(w, event, prms, nprms)
7218 PonderNextMoveEvent(!appData.ponderNextMove);
7220 if (appData.ponderNextMove) {
7221 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7223 XtSetArg(args[0], XtNleftBitmap, None);
7225 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Ponder Next Move"),
7229 void PopupExitMessageProc(w, event, prms, nprms)
7237 appData.popupExitMessage = !appData.popupExitMessage;
7239 if (appData.popupExitMessage) {
7240 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7242 XtSetArg(args[0], XtNleftBitmap, None);
7244 XtSetValues(XtNameToWidget(menuBarWidget,
7245 "menuOptions.Popup Exit Message"), args, 1);
7248 void PopupMoveErrorsProc(w, event, prms, nprms)
7256 appData.popupMoveErrors = !appData.popupMoveErrors;
7258 if (appData.popupMoveErrors) {
7259 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7261 XtSetArg(args[0], XtNleftBitmap, None);
7263 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Popup Move Errors"),
7267 void PremoveProc(w, event, prms, nprms)
7275 appData.premove = !appData.premove;
7277 if (appData.premove) {
7278 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7280 XtSetArg(args[0], XtNleftBitmap, None);
7282 XtSetValues(XtNameToWidget(menuBarWidget,
7283 "menuOptions.Premove"), args, 1);
7286 void QuietPlayProc(w, event, prms, nprms)
7294 appData.quietPlay = !appData.quietPlay;
7296 if (appData.quietPlay) {
7297 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7299 XtSetArg(args[0], XtNleftBitmap, None);
7301 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Quiet Play"),
7305 void ShowCoordsProc(w, event, prms, nprms)
7313 appData.showCoords = !appData.showCoords;
7315 if (appData.showCoords) {
7316 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7318 XtSetArg(args[0], XtNleftBitmap, None);
7320 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
7323 DrawPosition(True, NULL);
7326 void ShowThinkingProc(w, event, prms, nprms)
7334 appData.showThinking = !appData.showThinking; // [HGM] thinking: tken out of ShowThinkingEvent
7335 ShowThinkingEvent();
7337 // [HGM] thinking: currently no suc menu item; replaced by Hide Thinking (From Human)
7338 if (appData.showThinking) {
7339 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7341 XtSetArg(args[0], XtNleftBitmap, None);
7343 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Thinking"),
7348 void HideThinkingProc(w, event, prms, nprms)
7356 appData.hideThinkingFromHuman = !appData.hideThinkingFromHuman; // [HGM] thinking: tken out of ShowThinkingEvent
7357 ShowThinkingEvent();
7359 if (appData.hideThinkingFromHuman) {
7360 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7362 XtSetArg(args[0], XtNleftBitmap, None);
7364 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
7368 void InfoProc(w, event, prms, nprms)
7375 snprintf(buf, sizeof(buf), "xterm -e info --directory %s --directory . -f %s &",
7380 void ManProc(w, event, prms, nprms)
7388 if (nprms && *nprms > 0)
7392 snprintf(buf, sizeof(buf), "xterm -e man %s &", name);
7396 void HintProc(w, event, prms, nprms)
7405 void BookProc(w, event, prms, nprms)
7414 void AboutProc(w, event, prms, nprms)
7422 char *zippy = " (with Zippy code)";
7426 snprintf(buf, sizeof(buf), "%s%s\n\n%s\n%s\n%s\n\n%s%s\n%s",
7427 programVersion, zippy,
7428 "Copyright 1991 Digital Equipment Corporation",
7429 "Enhancements Copyright 1992-2009 Free Software Foundation",
7430 "Enhancements Copyright 2005 Alessandro Scotti",
7431 PRODUCT, " is free software and carries NO WARRANTY;",
7432 "see the file COPYING for more information.");
7433 ErrorPopUp(_("About XBoard"), buf, FALSE);
7436 void DebugProc(w, event, prms, nprms)
7442 appData.debugMode = !appData.debugMode;
7445 void AboutGameProc(w, event, prms, nprms)
7454 void NothingProc(w, event, prms, nprms)
7463 void Iconify(w, event, prms, nprms)
7472 XtSetArg(args[0], XtNiconic, True);
7473 XtSetValues(shellWidget, args, 1);
7476 void DisplayMessage(message, extMessage)
7477 char *message, *extMessage;
7484 snprintf(buf, sizeof(buf), "%s %s", message, extMessage);
7487 message = extMessage;
7490 XtSetArg(arg, XtNlabel, message);
7491 XtSetValues(messageWidget, &arg, 1);
7494 void DisplayTitle(text)
7499 char title[MSG_SIZ];
7502 if (text == NULL) text = "";
7504 if (appData.titleInWindow) {
7506 XtSetArg(args[i], XtNlabel, text); i++;
7507 XtSetValues(titleWidget, args, i);
7510 if (*text != NULLCHAR) {
7512 strcpy(title, text);
7513 } else if (appData.icsActive) {
7514 snprintf(icon, sizeof(icon), "%s", appData.icsHost);
7515 snprintf(title, sizeof(title),"%s: %s", programName, appData.icsHost);
7516 } else if (appData.cmailGameName[0] != NULLCHAR) {
7517 snprintf(icon, sizeof(icon), "%s", "CMail");
7518 snprintf(title,sizeof(title), "%s: %s", programName, "CMail");
7520 // [HGM] license: This stuff should really be done in back-end, but WinBoard already had a pop-up for it
7521 } else if (gameInfo.variant == VariantGothic) {
7522 strcpy(icon, programName);
7523 strcpy(title, GOTHIC);
7526 } else if (gameInfo.variant == VariantFalcon) {
7527 strcpy(icon, programName);
7528 strcpy(title, FALCON);
7530 } else if (appData.noChessProgram) {
7531 strcpy(icon, programName);
7532 strcpy(title, programName);
7534 strcpy(icon, first.tidy);
7535 snprintf(title,sizeof(title), "%s: %s", programName, first.tidy);
7538 XtSetArg(args[i], XtNiconName, (XtArgVal) icon); i++;
7539 XtSetArg(args[i], XtNtitle, (XtArgVal) title); i++;
7540 XtSetValues(shellWidget, args, i);
7544 void DisplayError(message, error)
7551 if (appData.debugMode || appData.matchMode) {
7552 fprintf(stderr, "%s: %s\n", programName, message);
7555 if (appData.debugMode || appData.matchMode) {
7556 fprintf(stderr, "%s: %s: %s\n",
7557 programName, message, strerror(error));
7559 snprintf(buf,sizeof(buf), "%s: %s", message, strerror(error));
7562 ErrorPopUp(_("Error"), message, FALSE);
7566 void DisplayMoveError(message)
7571 DrawPosition(FALSE, NULL);
7572 if (appData.debugMode || appData.matchMode) {
7573 fprintf(stderr, "%s: %s\n", programName, message);
7575 if (appData.popupMoveErrors) {
7576 ErrorPopUp(_("Error"), message, FALSE);
7578 DisplayMessage(message, "");
7583 void DisplayFatalError(message, error, status)
7589 errorExitStatus = status;
7591 fprintf(stderr, "%s: %s\n", programName, message);
7593 fprintf(stderr, "%s: %s: %s\n",
7594 programName, message, strerror(error));
7595 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
7598 if (appData.popupExitMessage && boardWidget && XtIsRealized(boardWidget)) {
7599 ErrorPopUp(status ? _("Fatal Error") : _("Exiting"), message, TRUE);
7605 void DisplayInformation(message)
7609 ErrorPopUp(_("Information"), message, TRUE);
7612 void DisplayNote(message)
7616 ErrorPopUp(_("Note"), message, FALSE);
7620 NullXErrorCheck(dpy, error_event)
7622 XErrorEvent *error_event;
7627 void DisplayIcsInteractionTitle(message)
7630 if (oldICSInteractionTitle == NULL) {
7631 /* Magic to find the old window title, adapted from vim */
7632 char *wina = getenv("WINDOWID");
7634 Window win = (Window) atoi(wina);
7635 Window root, parent, *children;
7636 unsigned int nchildren;
7637 int (*oldHandler)() = XSetErrorHandler(NullXErrorCheck);
7639 if (XFetchName(xDisplay, win, &oldICSInteractionTitle)) break;
7640 if (!XQueryTree(xDisplay, win, &root, &parent,
7641 &children, &nchildren)) break;
7642 if (children) XFree((void *)children);
7643 if (parent == root || parent == 0) break;
7646 XSetErrorHandler(oldHandler);
7648 if (oldICSInteractionTitle == NULL) {
7649 oldICSInteractionTitle = "xterm";
7652 printf("\033]0;%s\007", message);
7656 char pendingReplyPrefix[MSG_SIZ];
7657 ProcRef pendingReplyPR;
7659 void AskQuestionProc(w, event, prms, nprms)
7666 fprintf(stderr, _("AskQuestionProc needed 4 parameters, got %d\n"),
7670 AskQuestionEvent(prms[0], prms[1], prms[2], prms[3]);
7673 void AskQuestionPopDown()
7675 if (!askQuestionUp) return;
7676 XtPopdown(askQuestionShell);
7677 XtDestroyWidget(askQuestionShell);
7678 askQuestionUp = False;
7681 void AskQuestionReplyAction(w, event, prms, nprms)
7691 reply = XawDialogGetValueString(w = XtParent(w));
7692 strcpy(buf, pendingReplyPrefix);
7693 if (*buf) strcat(buf, " ");
7696 OutputToProcess(pendingReplyPR, buf, strlen(buf), &err);
7697 AskQuestionPopDown();
7699 if (err) DisplayFatalError(_("Error writing to chess program"), err, 0);
7702 void AskQuestionCallback(w, client_data, call_data)
7704 XtPointer client_data, call_data;
7709 XtSetArg(args[0], XtNlabel, &name);
7710 XtGetValues(w, args, 1);
7712 if (strcmp(name, _("cancel")) == 0) {
7713 AskQuestionPopDown();
7715 AskQuestionReplyAction(w, NULL, NULL, NULL);
7719 void AskQuestion(title, question, replyPrefix, pr)
7720 char *title, *question, *replyPrefix;
7724 Widget popup, layout, dialog, edit;
7730 strcpy(pendingReplyPrefix, replyPrefix);
7731 pendingReplyPR = pr;
7734 XtSetArg(args[i], XtNresizable, True); i++;
7735 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
7736 askQuestionShell = popup =
7737 XtCreatePopupShell(title, transientShellWidgetClass,
7738 shellWidget, args, i);
7741 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
7742 layoutArgs, XtNumber(layoutArgs));
7745 XtSetArg(args[i], XtNlabel, question); i++;
7746 XtSetArg(args[i], XtNvalue, ""); i++;
7747 XtSetArg(args[i], XtNborderWidth, 0); i++;
7748 dialog = XtCreateManagedWidget("question", dialogWidgetClass,
7751 XawDialogAddButton(dialog, _("enter"), AskQuestionCallback,
7752 (XtPointer) dialog);
7753 XawDialogAddButton(dialog, _("cancel"), AskQuestionCallback,
7754 (XtPointer) dialog);
7756 XtRealizeWidget(popup);
7757 CatchDeleteWindow(popup, "AskQuestionPopDown");
7759 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
7760 &x, &y, &win_x, &win_y, &mask);
7762 XtSetArg(args[0], XtNx, x - 10);
7763 XtSetArg(args[1], XtNy, y - 30);
7764 XtSetValues(popup, args, 2);
7766 XtPopup(popup, XtGrabExclusive);
7767 askQuestionUp = True;
7769 edit = XtNameToWidget(dialog, "*value");
7770 XtSetKeyboardFocus(popup, edit);
7778 if (*name == NULLCHAR) {
7780 } else if (strcmp(name, "$") == 0) {
7781 putc(BELLCHAR, stderr);
7784 snprintf(buf, sizeof(buf), "%s '%s' &", appData.soundProgram, name);
7792 PlaySound(appData.soundMove);
7798 PlaySound(appData.soundIcsWin);
7804 PlaySound(appData.soundIcsLoss);
7810 PlaySound(appData.soundIcsDraw);
7814 PlayIcsUnfinishedSound()
7816 PlaySound(appData.soundIcsUnfinished);
7822 PlaySound(appData.soundIcsAlarm);
7828 system("stty echo");
7834 system("stty -echo");
7838 Colorize(cc, continuation)
7843 int count, outCount, error;
7845 if (textColors[(int)cc].bg > 0) {
7846 if (textColors[(int)cc].fg > 0) {
7847 sprintf(buf, "\033[0;%d;%d;%dm", textColors[(int)cc].attr,
7848 textColors[(int)cc].fg, textColors[(int)cc].bg);
7850 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
7851 textColors[(int)cc].bg);
7854 if (textColors[(int)cc].fg > 0) {
7855 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
7856 textColors[(int)cc].fg);
7858 sprintf(buf, "\033[0;%dm", textColors[(int)cc].attr);
7861 count = strlen(buf);
7862 outCount = OutputToProcess(NoProc, buf, count, &error);
7863 if (outCount < count) {
7864 DisplayFatalError(_("Error writing to display"), error, 1);
7867 if (continuation) return;
7870 PlaySound(appData.soundShout);
7873 PlaySound(appData.soundSShout);
7876 PlaySound(appData.soundChannel1);
7879 PlaySound(appData.soundChannel);
7882 PlaySound(appData.soundKibitz);
7885 PlaySound(appData.soundTell);
7887 case ColorChallenge:
7888 PlaySound(appData.soundChallenge);
7891 PlaySound(appData.soundRequest);
7894 PlaySound(appData.soundSeek);
7905 return getpwuid(getuid())->pw_name;
7908 static char *ExpandPathName(path)
7911 static char static_buf[2000];
7912 char *d, *s, buf[2000];
7918 while (*s && isspace(*s))
7927 if (*(s+1) == '/') {
7928 strcpy(d, getpwuid(getuid())->pw_dir);
7933 *strchr(buf, '/') = 0;
7934 pwd = getpwnam(buf);
7937 fprintf(stderr, _("ERROR: Unknown user %s (in path %s)\n"),
7941 strcpy(d, pwd->pw_dir);
7942 strcat(d, strchr(s+1, '/'));
7953 static char host_name[MSG_SIZ];
7955 #if HAVE_GETHOSTNAME
7956 gethostname(host_name, MSG_SIZ);
7958 #else /* not HAVE_GETHOSTNAME */
7959 # if HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H
7960 sysinfo(SI_HOSTNAME, host_name, MSG_SIZ);
7962 # else /* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
7964 # endif/* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
7965 #endif /* not HAVE_GETHOSTNAME */
7968 XtIntervalId delayedEventTimerXID = 0;
7969 DelayedEventCallback delayedEventCallback = 0;
7974 delayedEventTimerXID = 0;
7975 delayedEventCallback();
7979 ScheduleDelayedEvent(cb, millisec)
7980 DelayedEventCallback cb; long millisec;
7982 delayedEventCallback = cb;
7983 delayedEventTimerXID =
7984 XtAppAddTimeOut(appContext, millisec,
7985 (XtTimerCallbackProc) FireDelayedEvent, (XtPointer) 0);
7988 DelayedEventCallback
7991 if (delayedEventTimerXID) {
7992 return delayedEventCallback;
7999 CancelDelayedEvent()
8001 if (delayedEventTimerXID) {
8002 XtRemoveTimeOut(delayedEventTimerXID);
8003 delayedEventTimerXID = 0;
8007 XtIntervalId loadGameTimerXID = 0;
8009 int LoadGameTimerRunning()
8011 return loadGameTimerXID != 0;
8014 int StopLoadGameTimer()
8016 if (loadGameTimerXID != 0) {
8017 XtRemoveTimeOut(loadGameTimerXID);
8018 loadGameTimerXID = 0;
8026 LoadGameTimerCallback(arg, id)
8030 loadGameTimerXID = 0;
8035 StartLoadGameTimer(millisec)
8039 XtAppAddTimeOut(appContext, millisec,
8040 (XtTimerCallbackProc) LoadGameTimerCallback,
8044 XtIntervalId analysisClockXID = 0;
8047 AnalysisClockCallback(arg, id)
8051 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile
8052 || appData.icsEngineAnalyze) { // [DM]
8053 AnalysisPeriodicEvent(0);
8054 StartAnalysisClock();
8059 StartAnalysisClock()
8062 XtAppAddTimeOut(appContext, 2000,
8063 (XtTimerCallbackProc) AnalysisClockCallback,
8067 XtIntervalId clockTimerXID = 0;
8069 int ClockTimerRunning()
8071 return clockTimerXID != 0;
8074 int StopClockTimer()
8076 if (clockTimerXID != 0) {
8077 XtRemoveTimeOut(clockTimerXID);
8086 ClockTimerCallback(arg, id)
8095 StartClockTimer(millisec)
8099 XtAppAddTimeOut(appContext, millisec,
8100 (XtTimerCallbackProc) ClockTimerCallback,
8105 DisplayTimerLabel(w, color, timer, highlight)
8114 Pixel foregroundOrWarningColor = timerForegroundPixel;
8117 && appData.lowTimeWarning
8118 && (timer / 1000) < appData.icsAlarmTime)
8120 foregroundOrWarningColor = lowTimeWarningColor;
8122 if (appData.clockMode) {
8123 sprintf(buf, "%s: %s", color, TimeString(timer));
8124 XtSetArg(args[0], XtNlabel, buf);
8126 sprintf(buf, "%s ", color);
8127 XtSetArg(args[0], XtNlabel, buf);
8132 XtSetArg(args[1], XtNbackground, foregroundOrWarningColor);
8133 XtSetArg(args[2], XtNforeground, timerBackgroundPixel);
8135 XtSetArg(args[1], XtNbackground, timerBackgroundPixel);
8136 XtSetArg(args[2], XtNforeground, foregroundOrWarningColor);
8139 XtSetValues(w, args, 3);
8143 DisplayWhiteClock(timeRemaining, highlight)
8149 if(appData.noGUI) return;
8150 DisplayTimerLabel(whiteTimerWidget, _("White"), timeRemaining, highlight);
8151 if (highlight && iconPixmap == bIconPixmap) {
8152 iconPixmap = wIconPixmap;
8153 XtSetArg(args[0], XtNiconPixmap, iconPixmap);
8154 XtSetValues(shellWidget, args, 1);
8159 DisplayBlackClock(timeRemaining, highlight)
8165 if(appData.noGUI) return;
8166 DisplayTimerLabel(blackTimerWidget, _("Black"), timeRemaining, highlight);
8167 if (highlight && iconPixmap == wIconPixmap) {
8168 iconPixmap = bIconPixmap;
8169 XtSetArg(args[0], XtNiconPixmap, iconPixmap);
8170 XtSetValues(shellWidget, args, 1);
8188 int StartChildProcess(cmdLine, dir, pr)
8195 int to_prog[2], from_prog[2];
8199 if (appData.debugMode) {
8200 fprintf(stderr, "StartChildProcess (dir=\"%s\") %s\n",dir, cmdLine);
8203 /* We do NOT feed the cmdLine to the shell; we just
8204 parse it into blank-separated arguments in the
8205 most simple-minded way possible.
8208 strcpy(buf, cmdLine);
8213 if (p == NULL) break;
8218 SetUpChildIO(to_prog, from_prog);
8220 if ((pid = fork()) == 0) {
8222 // [HGM] PSWBTM: made order resistant against case where fd of created pipe was 0 or 1
8223 close(to_prog[1]); // first close the unused pipe ends
8224 close(from_prog[0]);
8225 dup2(to_prog[0], 0); // to_prog was created first, nd is the only one to use 0 or 1
8226 dup2(from_prog[1], 1);
8227 if(to_prog[0] >= 2) close(to_prog[0]); // if 0 or 1, the dup2 already cosed the original
8228 close(from_prog[1]); // and closing again loses one of the pipes!
8229 if(fileno(stderr) >= 2) // better safe than sorry...
8230 dup2(1, fileno(stderr)); /* force stderr to the pipe */
8232 if (dir[0] != NULLCHAR && chdir(dir) != 0) {
8237 nice(appData.niceEngines); // [HGM] nice: adjust priority of engine proc
8239 execvp(argv[0], argv);
8241 /* If we get here, exec failed */
8246 /* Parent process */
8248 close(from_prog[1]);
8250 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8253 cp->fdFrom = from_prog[0];
8254 cp->fdTo = to_prog[1];
8259 // [HGM] kill: implement the 'hard killing' of AS's Winboard_x
8260 static RETSIGTYPE AlarmCallBack(int n)
8266 DestroyChildProcess(pr, signalType)
8270 ChildProc *cp = (ChildProc *) pr;
8272 if (cp->kind != CPReal) return;
8274 if (signalType == 10) { // [HGM] kill: if it does not terminate in 3 sec, kill
8275 signal(SIGALRM, AlarmCallBack);
8277 if(wait((int *) 0) == -1) { // process does not terminate on its own accord
8278 kill(cp->pid, SIGKILL); // kill it forcefully
8279 wait((int *) 0); // and wait again
8283 kill(cp->pid, signalType == 9 ? SIGKILL : SIGTERM); // [HGM] kill: use hard kill if so requested
8285 /* Process is exiting either because of the kill or because of
8286 a quit command sent by the backend; either way, wait for it to die.
8295 InterruptChildProcess(pr)
8298 ChildProc *cp = (ChildProc *) pr;
8300 if (cp->kind != CPReal) return;
8301 (void) kill(cp->pid, SIGINT); /* stop it thinking */
8304 int OpenTelnet(host, port, pr)
8309 char cmdLine[MSG_SIZ];
8311 if (port[0] == NULLCHAR) {
8312 snprintf(cmdLine, sizeof(cmdLine), "%s %s", appData.telnetProgram, host);
8314 snprintf(cmdLine,sizeof(cmdLine), "%s %s %s", appData.telnetProgram, host, port);
8316 return StartChildProcess(cmdLine, "", pr);
8319 int OpenTCP(host, port, pr)
8325 DisplayFatalError(_("Socket support is not configured in"), 0, 2);
8326 #else /* !OMIT_SOCKETS */
8328 struct sockaddr_in sa;
8330 unsigned short uport;
8333 if ((s = socket(AF_INET, SOCK_STREAM, 6)) < 0) {
8337 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
8338 sa.sin_family = AF_INET;
8339 sa.sin_addr.s_addr = INADDR_ANY;
8340 uport = (unsigned short) 0;
8341 sa.sin_port = htons(uport);
8342 if (bind(s, (struct sockaddr *) &sa, sizeof(struct sockaddr_in)) < 0) {
8346 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
8347 if (!(hp = gethostbyname(host))) {
8349 if (sscanf(host, "%d.%d.%d.%d", &b0, &b1, &b2, &b3) == 4) {
8350 hp = (struct hostent *) calloc(1, sizeof(struct hostent));
8351 hp->h_addrtype = AF_INET;
8353 hp->h_addr_list = (char **) calloc(2, sizeof(char *));
8354 hp->h_addr_list[0] = (char *) malloc(4);
8355 hp->h_addr_list[0][0] = b0;
8356 hp->h_addr_list[0][1] = b1;
8357 hp->h_addr_list[0][2] = b2;
8358 hp->h_addr_list[0][3] = b3;
8363 sa.sin_family = hp->h_addrtype;
8364 uport = (unsigned short) atoi(port);
8365 sa.sin_port = htons(uport);
8366 memcpy((char *) &sa.sin_addr, hp->h_addr, hp->h_length);
8368 if (connect(s, (struct sockaddr *) &sa,
8369 sizeof(struct sockaddr_in)) < 0) {
8373 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8380 #endif /* !OMIT_SOCKETS */
8385 int OpenCommPort(name, pr)
8392 fd = open(name, 2, 0);
8393 if (fd < 0) return errno;
8395 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8405 int OpenLoopback(pr)
8411 SetUpChildIO(to, from);
8413 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8416 cp->fdFrom = to[0]; /* note not from[0]; we are doing a loopback */
8423 int OpenRcmd(host, user, cmd, pr)
8424 char *host, *user, *cmd;
8427 DisplayFatalError(_("internal rcmd not implemented for Unix"), 0, 1);
8431 #define INPUT_SOURCE_BUF_SIZE 8192
8440 char buf[INPUT_SOURCE_BUF_SIZE];
8445 DoInputCallback(closure, source, xid)
8450 InputSource *is = (InputSource *) closure;
8455 if (is->lineByLine) {
8456 count = read(is->fd, is->unused,
8457 INPUT_SOURCE_BUF_SIZE - (is->unused - is->buf));
8459 (is->func)(is, is->closure, is->buf, count, count ? errno : 0);
8462 is->unused += count;
8464 while (p < is->unused) {
8465 q = memchr(p, '\n', is->unused - p);
8466 if (q == NULL) break;
8468 (is->func)(is, is->closure, p, q - p, 0);
8472 while (p < is->unused) {
8477 count = read(is->fd, is->buf, INPUT_SOURCE_BUF_SIZE);
8482 (is->func)(is, is->closure, is->buf, count, error);
8486 InputSourceRef AddInputSource(pr, lineByLine, func, closure)
8493 ChildProc *cp = (ChildProc *) pr;
8495 is = (InputSource *) calloc(1, sizeof(InputSource));
8496 is->lineByLine = lineByLine;
8500 is->fd = fileno(stdin);
8502 is->kind = cp->kind;
8503 is->fd = cp->fdFrom;
8506 is->unused = is->buf;
8509 is->xid = XtAppAddInput(appContext, is->fd,
8510 (XtPointer) (XtInputReadMask),
8511 (XtInputCallbackProc) DoInputCallback,
8513 is->closure = closure;
8514 return (InputSourceRef) is;
8518 RemoveInputSource(isr)
8521 InputSource *is = (InputSource *) isr;
8523 if (is->xid == 0) return;
8524 XtRemoveInput(is->xid);
8528 int OutputToProcess(pr, message, count, outError)
8534 ChildProc *cp = (ChildProc *) pr;
8538 outCount = fwrite(message, 1, count, stdout);
8540 outCount = write(cp->fdTo, message, count);
8550 /* Output message to process, with "ms" milliseconds of delay
8551 between each character. This is needed when sending the logon
8552 script to ICC, which for some reason doesn't like the
8553 instantaneous send. */
8554 int OutputToProcessDelayed(pr, message, count, outError, msdelay)
8561 ChildProc *cp = (ChildProc *) pr;
8566 r = write(cp->fdTo, message++, 1);
8579 /**** Animation code by Hugh Fisher, DCS, ANU.
8581 Known problem: if a window overlapping the board is
8582 moved away while a piece is being animated underneath,
8583 the newly exposed area won't be updated properly.
8584 I can live with this.
8586 Known problem: if you look carefully at the animation
8587 of pieces in mono mode, they are being drawn as solid
8588 shapes without interior detail while moving. Fixing
8589 this would be a major complication for minimal return.
8592 /* Masks for XPM pieces. Black and white pieces can have
8593 different shapes, but in the interest of retaining my
8594 sanity pieces must have the same outline on both light
8595 and dark squares, and all pieces must use the same
8596 background square colors/images. */
8599 CreateAnimMasks (pieceDepth)
8606 unsigned long plane;
8609 /* Need a bitmap just to get a GC with right depth */
8610 buf = XCreatePixmap(xDisplay, xBoardWindow,
8612 values.foreground = 1;
8613 values.background = 0;
8614 /* Don't use XtGetGC, not read only */
8615 maskGC = XCreateGC(xDisplay, buf,
8616 GCForeground | GCBackground, &values);
8617 XFreePixmap(xDisplay, buf);
8619 buf = XCreatePixmap(xDisplay, xBoardWindow,
8620 squareSize, squareSize, pieceDepth);
8621 values.foreground = XBlackPixel(xDisplay, xScreen);
8622 values.background = XWhitePixel(xDisplay, xScreen);
8623 bufGC = XCreateGC(xDisplay, buf,
8624 GCForeground | GCBackground, &values);
8626 for (piece = WhitePawn; piece <= BlackKing; piece++) {
8627 /* Begin with empty mask */
8628 xpmMask[piece] = XCreatePixmap(xDisplay, xBoardWindow,
8629 squareSize, squareSize, 1);
8630 XSetFunction(xDisplay, maskGC, GXclear);
8631 XFillRectangle(xDisplay, xpmMask[piece], maskGC,
8632 0, 0, squareSize, squareSize);
8634 /* Take a copy of the piece */
8639 XSetFunction(xDisplay, bufGC, GXcopy);
8640 XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % (int)BlackPawn],
8642 0, 0, squareSize, squareSize, 0, 0);
8644 /* XOR the background (light) over the piece */
8645 XSetFunction(xDisplay, bufGC, GXxor);
8647 XCopyArea(xDisplay, xpmLightSquare, buf, bufGC,
8648 0, 0, squareSize, squareSize, 0, 0);
8650 XSetForeground(xDisplay, bufGC, lightSquareColor);
8651 XFillRectangle(xDisplay, buf, bufGC, 0, 0, squareSize, squareSize);
8654 /* We now have an inverted piece image with the background
8655 erased. Construct mask by just selecting all the non-zero
8656 pixels - no need to reconstruct the original image. */
8657 XSetFunction(xDisplay, maskGC, GXor);
8659 /* Might be quicker to download an XImage and create bitmap
8660 data from it rather than this N copies per piece, but it
8661 only takes a fraction of a second and there is a much
8662 longer delay for loading the pieces. */
8663 for (n = 0; n < pieceDepth; n ++) {
8664 XCopyPlane(xDisplay, buf, xpmMask[piece], maskGC,
8665 0, 0, squareSize, squareSize,
8671 XFreePixmap(xDisplay, buf);
8672 XFreeGC(xDisplay, bufGC);
8673 XFreeGC(xDisplay, maskGC);
8677 InitAnimState (anim, info)
8679 XWindowAttributes * info;
8684 /* Each buffer is square size, same depth as window */
8685 anim->saveBuf = XCreatePixmap(xDisplay, xBoardWindow,
8686 squareSize, squareSize, info->depth);
8687 anim->newBuf = XCreatePixmap(xDisplay, xBoardWindow,
8688 squareSize, squareSize, info->depth);
8690 /* Create a plain GC for blitting */
8691 mask = GCForeground | GCBackground | GCFunction |
8692 GCPlaneMask | GCGraphicsExposures;
8693 values.foreground = XBlackPixel(xDisplay, xScreen);
8694 values.background = XWhitePixel(xDisplay, xScreen);
8695 values.function = GXcopy;
8696 values.plane_mask = AllPlanes;
8697 values.graphics_exposures = False;
8698 anim->blitGC = XCreateGC(xDisplay, xBoardWindow, mask, &values);
8700 /* Piece will be copied from an existing context at
8701 the start of each new animation/drag. */
8702 anim->pieceGC = XCreateGC(xDisplay, xBoardWindow, 0, &values);
8704 /* Outline will be a read-only copy of an existing */
8705 anim->outlineGC = None;
8711 static int done = 0;
8712 XWindowAttributes info;
8716 XGetWindowAttributes(xDisplay, xBoardWindow, &info);
8718 InitAnimState(&game, &info);
8719 InitAnimState(&player, &info);
8721 /* For XPM pieces, we need bitmaps to use as masks. */
8723 CreateAnimMasks(info.depth);
8728 static Boolean frameWaiting;
8730 static RETSIGTYPE FrameAlarm (sig)
8733 frameWaiting = False;
8734 /* In case System-V style signals. Needed?? */
8735 signal(SIGALRM, FrameAlarm);
8742 struct itimerval delay;
8744 XSync(xDisplay, False);
8747 frameWaiting = True;
8748 signal(SIGALRM, FrameAlarm);
8749 delay.it_interval.tv_sec =
8750 delay.it_value.tv_sec = time / 1000;
8751 delay.it_interval.tv_usec =
8752 delay.it_value.tv_usec = (time % 1000) * 1000;
8753 setitimer(ITIMER_REAL, &delay, NULL);
8755 /* Ugh -- busy-wait! --tpm */
8756 while (frameWaiting);
8758 while (frameWaiting) pause();
8760 delay.it_interval.tv_sec = delay.it_value.tv_sec = 0;
8761 delay.it_interval.tv_usec = delay.it_value.tv_usec = 0;
8762 setitimer(ITIMER_REAL, &delay, NULL);
8772 XSync(xDisplay, False);
8774 usleep(time * 1000);
8779 /* Convert board position to corner of screen rect and color */
8782 ScreenSquare(column, row, pt, color)
8783 int column; int row; XPoint * pt; int * color;
8786 pt->x = lineGap + ((BOARD_WIDTH-1)-column) * (squareSize + lineGap);
8787 pt->y = lineGap + row * (squareSize + lineGap);
8789 pt->x = lineGap + column * (squareSize + lineGap);
8790 pt->y = lineGap + ((BOARD_HEIGHT-1)-row) * (squareSize + lineGap);
8792 *color = SquareColor(row, column);
8795 /* Convert window coords to square */
8798 BoardSquare(x, y, column, row)
8799 int x; int y; int * column; int * row;
8801 *column = EventToSquare(x, BOARD_WIDTH);
8802 if (flipView && *column >= 0)
8803 *column = BOARD_WIDTH - 1 - *column;
8804 *row = EventToSquare(y, BOARD_HEIGHT);
8805 if (!flipView && *row >= 0)
8806 *row = BOARD_HEIGHT - 1 - *row;
8811 #undef Max /* just in case */
8813 #define Max(a, b) ((a) > (b) ? (a) : (b))
8814 #define Min(a, b) ((a) < (b) ? (a) : (b))
8817 SetRect(rect, x, y, width, height)
8818 XRectangle * rect; int x; int y; int width; int height;
8822 rect->width = width;
8823 rect->height = height;
8826 /* Test if two frames overlap. If they do, return
8827 intersection rect within old and location of
8828 that rect within new. */
8831 Intersect(old, new, size, area, pt)
8832 XPoint * old; XPoint * new;
8833 int size; XRectangle * area; XPoint * pt;
8835 if (old->x > new->x + size || new->x > old->x + size ||
8836 old->y > new->y + size || new->y > old->y + size) {
8839 SetRect(area, Max(new->x - old->x, 0), Max(new->y - old->y, 0),
8840 size - abs(old->x - new->x), size - abs(old->y - new->y));
8841 pt->x = Max(old->x - new->x, 0);
8842 pt->y = Max(old->y - new->y, 0);
8847 /* For two overlapping frames, return the rect(s)
8848 in the old that do not intersect with the new. */
8851 CalcUpdateRects(old, new, size, update, nUpdates)
8852 XPoint * old; XPoint * new; int size;
8853 XRectangle update[]; int * nUpdates;
8857 /* If old = new (shouldn't happen) then nothing to draw */
8858 if (old->x == new->x && old->y == new->y) {
8862 /* Work out what bits overlap. Since we know the rects
8863 are the same size we don't need a full intersect calc. */
8865 /* Top or bottom edge? */
8866 if (new->y > old->y) {
8867 SetRect(&(update[count]), old->x, old->y, size, new->y - old->y);
8869 } else if (old->y > new->y) {
8870 SetRect(&(update[count]), old->x, old->y + size - (old->y - new->y),
8871 size, old->y - new->y);
8874 /* Left or right edge - don't overlap any update calculated above. */
8875 if (new->x > old->x) {
8876 SetRect(&(update[count]), old->x, Max(new->y, old->y),
8877 new->x - old->x, size - abs(new->y - old->y));
8879 } else if (old->x > new->x) {
8880 SetRect(&(update[count]), new->x + size, Max(new->y, old->y),
8881 old->x - new->x, size - abs(new->y - old->y));
8888 /* Generate a series of frame coords from start->mid->finish.
8889 The movement rate doubles until the half way point is
8890 reached, then halves back down to the final destination,
8891 which gives a nice slow in/out effect. The algorithmn
8892 may seem to generate too many intermediates for short
8893 moves, but remember that the purpose is to attract the
8894 viewers attention to the piece about to be moved and
8895 then to where it ends up. Too few frames would be less
8899 Tween(start, mid, finish, factor, frames, nFrames)
8900 XPoint * start; XPoint * mid;
8901 XPoint * finish; int factor;
8902 XPoint frames[]; int * nFrames;
8904 int fraction, n, count;
8908 /* Slow in, stepping 1/16th, then 1/8th, ... */
8910 for (n = 0; n < factor; n++)
8912 for (n = 0; n < factor; n++) {
8913 frames[count].x = start->x + (mid->x - start->x) / fraction;
8914 frames[count].y = start->y + (mid->y - start->y) / fraction;
8916 fraction = fraction / 2;
8920 frames[count] = *mid;
8923 /* Slow out, stepping 1/2, then 1/4, ... */
8925 for (n = 0; n < factor; n++) {
8926 frames[count].x = finish->x - (finish->x - mid->x) / fraction;
8927 frames[count].y = finish->y - (finish->y - mid->y) / fraction;
8929 fraction = fraction * 2;
8934 /* Draw a piece on the screen without disturbing what's there */
8937 SelectGCMask(piece, clip, outline, mask)
8938 ChessSquare piece; GC * clip; GC * outline; Pixmap * mask;
8942 /* Bitmap for piece being moved. */
8943 if (appData.monoMode) {
8944 *mask = *pieceToSolid(piece);
8945 } else if (useImages) {
8947 *mask = xpmMask[piece];
8949 *mask = ximMaskPm[piece%(int)BlackPawn];
8952 *mask = *pieceToSolid(piece);
8955 /* GC for piece being moved. Square color doesn't matter, but
8956 since it gets modified we make a copy of the original. */
8958 if (appData.monoMode)
8963 if (appData.monoMode)
8968 XCopyGC(xDisplay, source, 0xFFFFFFFF, *clip);
8970 /* Outline only used in mono mode and is not modified */
8972 *outline = bwPieceGC;
8974 *outline = wbPieceGC;
8978 OverlayPiece(piece, clip, outline, dest)
8979 ChessSquare piece; GC clip; GC outline; Drawable dest;
8984 /* Draw solid rectangle which will be clipped to shape of piece */
8985 XFillRectangle(xDisplay, dest, clip,
8986 0, 0, squareSize, squareSize);
8987 if (appData.monoMode)
8988 /* Also draw outline in contrasting color for black
8989 on black / white on white cases */
8990 XCopyPlane(xDisplay, *pieceToOutline(piece), dest, outline,
8991 0, 0, squareSize, squareSize, 0, 0, 1);
8993 /* Copy the piece */
8998 XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % (int)BlackPawn],
9000 0, 0, squareSize, squareSize,
9005 /* Animate the movement of a single piece */
9008 BeginAnimation(anim, piece, startColor, start)
9016 /* The old buffer is initialised with the start square (empty) */
9017 BlankSquare(0, 0, startColor, EmptySquare, anim->saveBuf);
9018 anim->prevFrame = *start;
9020 /* The piece will be drawn using its own bitmap as a matte */
9021 SelectGCMask(piece, &anim->pieceGC, &anim->outlineGC, &mask);
9022 XSetClipMask(xDisplay, anim->pieceGC, mask);
9026 AnimationFrame(anim, frame, piece)
9031 XRectangle updates[4];
9036 /* Save what we are about to draw into the new buffer */
9037 XCopyArea(xDisplay, xBoardWindow, anim->newBuf, anim->blitGC,
9038 frame->x, frame->y, squareSize, squareSize,
9041 /* Erase bits of the previous frame */
9042 if (Intersect(&anim->prevFrame, frame, squareSize, &overlap, &pt)) {
9043 /* Where the new frame overlapped the previous,
9044 the contents in newBuf are wrong. */
9045 XCopyArea(xDisplay, anim->saveBuf, anim->newBuf, anim->blitGC,
9046 overlap.x, overlap.y,
9047 overlap.width, overlap.height,
9049 /* Repaint the areas in the old that don't overlap new */
9050 CalcUpdateRects(&anim->prevFrame, frame, squareSize, updates, &count);
9051 for (i = 0; i < count; i++)
9052 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9053 updates[i].x - anim->prevFrame.x,
9054 updates[i].y - anim->prevFrame.y,
9055 updates[i].width, updates[i].height,
9056 updates[i].x, updates[i].y);
9058 /* Easy when no overlap */
9059 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9060 0, 0, squareSize, squareSize,
9061 anim->prevFrame.x, anim->prevFrame.y);
9064 /* Save this frame for next time round */
9065 XCopyArea(xDisplay, anim->newBuf, anim->saveBuf, anim->blitGC,
9066 0, 0, squareSize, squareSize,
9068 anim->prevFrame = *frame;
9070 /* Draw piece over original screen contents, not current,
9071 and copy entire rect. Wipes out overlapping piece images. */
9072 OverlayPiece(piece, anim->pieceGC, anim->outlineGC, anim->newBuf);
9073 XCopyArea(xDisplay, anim->newBuf, xBoardWindow, anim->blitGC,
9074 0, 0, squareSize, squareSize,
9075 frame->x, frame->y);
9079 EndAnimation (anim, finish)
9083 XRectangle updates[4];
9088 /* The main code will redraw the final square, so we
9089 only need to erase the bits that don't overlap. */
9090 if (Intersect(&anim->prevFrame, finish, squareSize, &overlap, &pt)) {
9091 CalcUpdateRects(&anim->prevFrame, finish, squareSize, updates, &count);
9092 for (i = 0; i < count; i++)
9093 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9094 updates[i].x - anim->prevFrame.x,
9095 updates[i].y - anim->prevFrame.y,
9096 updates[i].width, updates[i].height,
9097 updates[i].x, updates[i].y);
9099 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9100 0, 0, squareSize, squareSize,
9101 anim->prevFrame.x, anim->prevFrame.y);
9106 FrameSequence(anim, piece, startColor, start, finish, frames, nFrames)
9108 ChessSquare piece; int startColor;
9109 XPoint * start; XPoint * finish;
9110 XPoint frames[]; int nFrames;
9114 BeginAnimation(anim, piece, startColor, start);
9115 for (n = 0; n < nFrames; n++) {
9116 AnimationFrame(anim, &(frames[n]), piece);
9117 FrameDelay(appData.animSpeed);
9119 EndAnimation(anim, finish);
9122 /* Main control logic for deciding what to animate and how */
9125 AnimateMove(board, fromX, fromY, toX, toY)
9134 XPoint start, finish, mid;
9135 XPoint frames[kFactor * 2 + 1];
9136 int nFrames, startColor, endColor;
9138 /* Are we animating? */
9139 if (!appData.animate || appData.blindfold)
9142 if (fromY < 0 || fromX < 0 || toX < 0 || toY < 0) return;
9143 piece = board[fromY][fromX];
9144 if (piece >= EmptySquare) return;
9149 hop = (piece == WhiteKnight || piece == BlackKnight);
9152 if (appData.debugMode) {
9153 fprintf(debugFP, hop ? _("AnimateMove: piece %d hops from %d,%d to %d,%d \n") :
9154 _("AnimateMove: piece %d slides from %d,%d to %d,%d \n"),
9155 piece, fromX, fromY, toX, toY); }
9157 ScreenSquare(fromX, fromY, &start, &startColor);
9158 ScreenSquare(toX, toY, &finish, &endColor);
9161 /* Knight: make diagonal movement then straight */
9162 if (abs(toY - fromY) < abs(toX - fromX)) {
9163 mid.x = start.x + (finish.x - start.x) / 2;
9167 mid.y = start.y + (finish.y - start.y) / 2;
9170 mid.x = start.x + (finish.x - start.x) / 2;
9171 mid.y = start.y + (finish.y - start.y) / 2;
9174 /* Don't use as many frames for very short moves */
9175 if (abs(toY - fromY) + abs(toX - fromX) <= 2)
9176 Tween(&start, &mid, &finish, kFactor - 1, frames, &nFrames);
9178 Tween(&start, &mid, &finish, kFactor, frames, &nFrames);
9179 FrameSequence(&game, piece, startColor, &start, &finish, frames, nFrames);
9181 /* Be sure end square is redrawn */
9182 damage[toY][toX] = True;
9186 DragPieceBegin(x, y)
9189 int boardX, boardY, color;
9192 /* Are we animating? */
9193 if (!appData.animateDragging || appData.blindfold)
9196 /* Figure out which square we start in and the
9197 mouse position relative to top left corner. */
9198 BoardSquare(x, y, &boardX, &boardY);
9199 player.startBoardX = boardX;
9200 player.startBoardY = boardY;
9201 ScreenSquare(boardX, boardY, &corner, &color);
9202 player.startSquare = corner;
9203 player.startColor = color;
9205 /* Start from exactly where the piece is. This can be confusing
9206 if you start dragging far from the center of the square; most
9207 or all of the piece can be over a different square from the one
9208 the mouse pointer is in. */
9209 player.mouseDelta.x = x - corner.x;
9210 player.mouseDelta.y = y - corner.y;
9212 /* As soon as we start dragging, the piece will jump slightly to
9213 be centered over the mouse pointer. */
9214 player.mouseDelta.x = squareSize/2;
9215 player.mouseDelta.y = squareSize/2;
9217 /* Initialise animation */
9218 player.dragPiece = PieceForSquare(boardX, boardY);
9220 if (player.dragPiece >= 0 && player.dragPiece < EmptySquare) {
9221 player.dragActive = True;
9222 BeginAnimation(&player, player.dragPiece, color, &corner);
9223 /* Mark this square as needing to be redrawn. Note that
9224 we don't remove the piece though, since logically (ie
9225 as seen by opponent) the move hasn't been made yet. */
9226 if(boardX == BOARD_RGHT+1 && PieceForSquare(boardX-1, boardY) > 1 ||
9227 boardX == BOARD_LEFT-2 && PieceForSquare(boardX+1, boardY) > 1)
9228 XCopyArea(xDisplay, xBoardWindow, player.saveBuf, player.blitGC,
9229 corner.x, corner.y, squareSize, squareSize,
9230 0, 0); // [HGM] zh: unstack in stead of grab
9231 damage[boardY][boardX] = True;
9233 player.dragActive = False;
9243 /* Are we animating? */
9244 if (!appData.animateDragging || appData.blindfold)
9248 if (! player.dragActive)
9250 /* Move piece, maintaining same relative position
9251 of mouse within square */
9252 corner.x = x - player.mouseDelta.x;
9253 corner.y = y - player.mouseDelta.y;
9254 AnimationFrame(&player, &corner, player.dragPiece);
9256 if (appData.highlightDragging) {
9258 BoardSquare(x, y, &boardX, &boardY);
9259 SetHighlights(fromX, fromY, boardX, boardY);
9268 int boardX, boardY, color;
9271 /* Are we animating? */
9272 if (!appData.animateDragging || appData.blindfold)
9276 if (! player.dragActive)
9278 /* Last frame in sequence is square piece is
9279 placed on, which may not match mouse exactly. */
9280 BoardSquare(x, y, &boardX, &boardY);
9281 ScreenSquare(boardX, boardY, &corner, &color);
9282 EndAnimation(&player, &corner);
9284 /* Be sure end square is redrawn */
9285 damage[boardY][boardX] = True;
9287 /* This prevents weird things happening with fast successive
9288 clicks which on my Sun at least can cause motion events
9289 without corresponding press/release. */
9290 player.dragActive = False;
9293 /* Handle expose event while piece being dragged */
9298 if (!player.dragActive || appData.blindfold)
9301 /* What we're doing: logically, the move hasn't been made yet,
9302 so the piece is still in it's original square. But visually
9303 it's being dragged around the board. So we erase the square
9304 that the piece is on and draw it at the last known drag point. */
9305 BlankSquare(player.startSquare.x, player.startSquare.y,
9306 player.startColor, EmptySquare, xBoardWindow);
9307 AnimationFrame(&player, &player.prevFrame, player.dragPiece);
9308 damage[player.startBoardY][player.startBoardX] = TRUE;
9312 SetProgramStats( FrontEndProgramStats * stats )
9315 // [HGM] done, but perhaps backend should call this directly?
9316 EngineOutputUpdate( stats );