2 * xboard.c -- X front end for XBoard
3 * $Id: xboard.c,v 2.2 2003/11/06 07:22:14 mann Exp $
5 * Copyright 1991 by Digital Equipment Corporation, Maynard,
6 * Massachusetts. Enhancements Copyright
7 * 1992-2001,2002,2003,2004,2005,2006,2007,2008,2009 Free Software
10 * The following terms apply to Digital Equipment Corporation's copyright
12 * ------------------------------------------------------------------------
15 * Permission to use, copy, modify, and distribute this software and its
16 * documentation for any purpose and without fee is hereby granted,
17 * provided that the above copyright notice appear in all copies and that
18 * both that copyright notice and this permission notice appear in
19 * supporting documentation, and that the name of Digital not be
20 * used in advertising or publicity pertaining to distribution of the
21 * software without specific, written prior permission.
23 * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
24 * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
25 * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
26 * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
27 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
28 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
30 * ------------------------------------------------------------------------
32 * The following terms apply to the enhanced version of XBoard
33 * distributed by the Free Software Foundation:
34 * ------------------------------------------------------------------------
36 * GNU XBoard is free software: you can redistribute it and/or modify
37 * it under the terms of the GNU General Public License as published by
38 * the Free Software Foundation, either version 3 of the License, or (at
39 * your option) any later version.
41 * GNU XBoard is distributed in the hope that it will be useful, but
42 * WITHOUT ANY WARRANTY; without even the implied warranty of
43 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
44 * General Public License for more details.
46 * You should have received a copy of the GNU General Public License
47 * along with this program. If not, see http://www.gnu.org/licenses/. *
49 *------------------------------------------------------------------------
50 ** See the file ChangeLog for a revision history. */
58 #include <sys/types.h>
63 # if HAVE_SYS_SOCKET_H
64 # include <sys/socket.h>
65 # include <netinet/in.h>
67 # else /* not HAVE_SYS_SOCKET_H */
68 # if HAVE_LAN_SOCKET_H
69 # include <lan/socket.h>
71 # include <lan/netdb.h>
72 # else /* not HAVE_LAN_SOCKET_H */
73 # define OMIT_SOCKETS 1
74 # endif /* not HAVE_LAN_SOCKET_H */
75 # endif /* not HAVE_SYS_SOCKET_H */
76 #endif /* !OMIT_SOCKETS */
81 #else /* not STDC_HEADERS */
82 extern char *getenv();
85 # else /* not HAVE_STRING_H */
87 # endif /* not HAVE_STRING_H */
88 #endif /* not STDC_HEADERS */
91 # include <sys/fcntl.h>
92 #else /* not HAVE_SYS_FCNTL_H */
95 # endif /* HAVE_FCNTL_H */
96 #endif /* not HAVE_SYS_FCNTL_H */
98 #if HAVE_SYS_SYSTEMINFO_H
99 # include <sys/systeminfo.h>
100 #endif /* HAVE_SYS_SYSTEMINFO_H */
102 #if TIME_WITH_SYS_TIME
103 # include <sys/time.h>
107 # include <sys/time.h>
118 # include <sys/wait.h>
123 # define NAMLEN(dirent) strlen((dirent)->d_name)
124 # define HAVE_DIR_STRUCT
126 # define dirent direct
127 # define NAMLEN(dirent) (dirent)->d_namlen
129 # include <sys/ndir.h>
130 # define HAVE_DIR_STRUCT
133 # include <sys/dir.h>
134 # define HAVE_DIR_STRUCT
138 # define HAVE_DIR_STRUCT
142 #include <X11/Intrinsic.h>
143 #include <X11/StringDefs.h>
144 #include <X11/Shell.h>
145 #include <X11/cursorfont.h>
146 #include <X11/Xatom.h>
148 #include <X11/Xaw3d/Dialog.h>
149 #include <X11/Xaw3d/Form.h>
150 #include <X11/Xaw3d/List.h>
151 #include <X11/Xaw3d/Label.h>
152 #include <X11/Xaw3d/SimpleMenu.h>
153 #include <X11/Xaw3d/SmeBSB.h>
154 #include <X11/Xaw3d/SmeLine.h>
155 #include <X11/Xaw3d/Box.h>
156 #include <X11/Xaw3d/MenuButton.h>
157 #include <X11/Xaw3d/Text.h>
158 #include <X11/Xaw3d/AsciiText.h>
160 #include <X11/Xaw/Dialog.h>
161 #include <X11/Xaw/Form.h>
162 #include <X11/Xaw/List.h>
163 #include <X11/Xaw/Label.h>
164 #include <X11/Xaw/SimpleMenu.h>
165 #include <X11/Xaw/SmeBSB.h>
166 #include <X11/Xaw/SmeLine.h>
167 #include <X11/Xaw/Box.h>
168 #include <X11/Xaw/MenuButton.h>
169 #include <X11/Xaw/Text.h>
170 #include <X11/Xaw/AsciiText.h>
173 // [HGM] bitmaps: put before incuding the bitmaps / pixmaps, to know how many piece types there are.
178 #include "pixmaps/pixmaps.h"
179 #define IMAGE_EXT "xpm"
181 #define IMAGE_EXT "xim"
182 #include "bitmaps/bitmaps.h"
185 #include "bitmaps/icon_white.bm"
186 #include "bitmaps/icon_black.bm"
187 #include "bitmaps/checkmark.bm"
189 #include "frontend.h"
194 #include "xgamelist.h"
195 #include "xhistory.h"
196 #include "xedittags.h"
199 // must be moved to xengineoutput.h
201 void EngineOutputProc P((Widget w, XEvent *event,
202 String *prms, Cardinal *nprms));
204 void EngineOutputPopDown();
211 #define usleep(t) _sleep2(((t)+500)/1000)
215 # define _(s) gettext (s)
216 # define N_(s) gettext_noop (s)
232 int main P((int argc, char **argv));
233 RETSIGTYPE CmailSigHandler P((int sig));
234 RETSIGTYPE IntSigHandler P((int sig));
235 void CreateGCs P((void));
236 void CreateXIMPieces P((void));
237 void CreateXPMPieces P((void));
238 void CreatePieces P((void));
239 void CreatePieceMenus P((void));
240 Widget CreateMenuBar P((Menu *mb));
241 Widget CreateButtonBar P ((MenuItem *mi));
242 char *FindFont P((char *pattern, int targetPxlSize));
243 void PieceMenuPopup P((Widget w, XEvent *event,
244 String *params, Cardinal *num_params));
245 static void PieceMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
246 static void DropMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
247 void ReadBitmap P((Pixmap *pm, String name, unsigned char bits[],
248 u_int wreq, u_int hreq));
249 void CreateGrid P((void));
250 int EventToSquare P((int x, int limit));
251 void DrawSquare P((int row, int column, ChessSquare piece, int do_flash));
252 void EventProc P((Widget widget, caddr_t unused, XEvent *event));
253 void HandleUserMove P((Widget w, XEvent *event,
254 String *prms, Cardinal *nprms));
255 void AnimateUserMove P((Widget w, XEvent * event,
256 String * params, Cardinal * nParams));
257 void WhiteClock P((Widget w, XEvent *event,
258 String *prms, Cardinal *nprms));
259 void BlackClock P((Widget w, XEvent *event,
260 String *prms, Cardinal *nprms));
261 void DrawPositionProc P((Widget w, XEvent *event,
262 String *prms, Cardinal *nprms));
263 void XDrawPosition P((Widget w, /*Boolean*/int repaint,
265 void CommentPopUp P((char *title, char *label));
266 void CommentPopDown P((void));
267 void CommentCallback P((Widget w, XtPointer client_data,
268 XtPointer call_data));
269 void ICSInputBoxPopUp P((void));
270 void ICSInputBoxPopDown P((void));
271 void FileNamePopUp P((char *label, char *def,
272 FileProc proc, char *openMode));
273 void FileNamePopDown P((void));
274 void FileNameCallback P((Widget w, XtPointer client_data,
275 XtPointer call_data));
276 void FileNameAction P((Widget w, XEvent *event,
277 String *prms, Cardinal *nprms));
278 void AskQuestionReplyAction P((Widget w, XEvent *event,
279 String *prms, Cardinal *nprms));
280 void AskQuestionProc P((Widget w, XEvent *event,
281 String *prms, Cardinal *nprms));
282 void AskQuestionPopDown P((void));
283 void PromotionPopUp P((void));
284 void PromotionPopDown P((void));
285 void PromotionCallback P((Widget w, XtPointer client_data,
286 XtPointer call_data));
287 void EditCommentPopDown P((void));
288 void EditCommentCallback P((Widget w, XtPointer client_data,
289 XtPointer call_data));
290 void SelectCommand P((Widget w, XtPointer client_data, XtPointer call_data));
291 void ResetProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
292 void LoadGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
293 void LoadNextGameProc P((Widget w, XEvent *event, String *prms,
295 void LoadPrevGameProc P((Widget w, XEvent *event, String *prms,
297 void ReloadGameProc P((Widget w, XEvent *event, String *prms,
299 void LoadPositionProc P((Widget w, XEvent *event,
300 String *prms, Cardinal *nprms));
301 void LoadNextPositionProc P((Widget w, XEvent *event, String *prms,
303 void LoadPrevPositionProc P((Widget w, XEvent *event, String *prms,
305 void ReloadPositionProc P((Widget w, XEvent *event, String *prms,
307 void CopyPositionProc P((Widget w, XEvent *event, String *prms,
309 void PastePositionProc P((Widget w, XEvent *event, String *prms,
311 void CopyGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
312 void PasteGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
313 void SaveGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
314 void SavePositionProc P((Widget w, XEvent *event,
315 String *prms, Cardinal *nprms));
316 void MailMoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
317 void ReloadCmailMsgProc P((Widget w, XEvent *event, String *prms,
319 void QuitProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
320 void PauseProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
321 void MachineBlackProc P((Widget w, XEvent *event, String *prms,
323 void MachineWhiteProc P((Widget w, XEvent *event,
324 String *prms, Cardinal *nprms));
325 void AnalyzeModeProc P((Widget w, XEvent *event,
326 String *prms, Cardinal *nprms));
327 void AnalyzeFileProc P((Widget w, XEvent *event,
328 String *prms, Cardinal *nprms));
329 void TwoMachinesProc P((Widget w, XEvent *event, String *prms,
331 void IcsClientProc P((Widget w, XEvent *event, String *prms,
333 void EditGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
334 void EditPositionProc P((Widget w, XEvent *event,
335 String *prms, Cardinal *nprms));
336 void TrainingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
337 void EditCommentProc P((Widget w, XEvent *event,
338 String *prms, Cardinal *nprms));
339 void IcsInputBoxProc P((Widget w, XEvent *event,
340 String *prms, Cardinal *nprms));
341 void AcceptProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
342 void DeclineProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
343 void RematchProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
344 void CallFlagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
345 void DrawProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
346 void AbortProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
347 void AdjournProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
348 void ResignProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
349 void AdjuWhiteProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
350 void AdjuBlackProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
351 void AdjuDrawProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
352 void EnterKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
353 void StopObservingProc P((Widget w, XEvent *event, String *prms,
355 void StopExaminingProc P((Widget w, XEvent *event, String *prms,
357 void BackwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
358 void ForwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
359 void ToStartProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
360 void ToEndProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
361 void RevertProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
362 void TruncateGameProc P((Widget w, XEvent *event, String *prms,
364 void RetractMoveProc P((Widget w, XEvent *event, String *prms,
366 void MoveNowProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
367 void AlwaysQueenProc P((Widget w, XEvent *event, String *prms,
369 void AnimateDraggingProc P((Widget w, XEvent *event, String *prms,
371 void AnimateMovingProc P((Widget w, XEvent *event, String *prms,
373 void AutocommProc P((Widget w, XEvent *event, String *prms,
375 void AutoflagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
376 void AutoflipProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
377 void AutobsProc P((Widget w, XEvent *event, String *prms,
379 void AutoraiseProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
380 void AutosaveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
381 void BlindfoldProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
382 void FlashMovesProc P((Widget w, XEvent *event, String *prms,
384 void FlipViewProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
385 void GetMoveListProc P((Widget w, XEvent *event, String *prms,
387 void HighlightDraggingProc P((Widget w, XEvent *event, String *prms,
389 void HighlightLastMoveProc P((Widget w, XEvent *event, String *prms,
391 void MoveSoundProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
392 void IcsAlarmProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
393 void OldSaveStyleProc P((Widget w, XEvent *event, String *prms,
395 void PeriodicUpdatesProc P((Widget w, XEvent *event, String *prms,
397 void PonderNextMoveProc P((Widget w, XEvent *event, String *prms,
399 void PopupMoveErrorsProc P((Widget w, XEvent *event, String *prms,
401 void PopupExitMessageProc P((Widget w, XEvent *event, String *prms,
403 void PremoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
404 void QuietPlayProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
405 void ShowCoordsProc P((Widget w, XEvent *event, String *prms,
407 void ShowThinkingProc P((Widget w, XEvent *event, String *prms,
409 void HideThinkingProc P((Widget w, XEvent *event, String *prms,
411 void TestLegalityProc P((Widget w, XEvent *event, String *prms,
413 void InfoProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
414 void ManProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
415 void HintProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
416 void BookProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
417 void AboutGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
418 void AboutProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
419 void DebugProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
420 void NothingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
421 void Iconify P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
422 void DisplayMove P((int moveNumber));
423 void DisplayTitle P((char *title));
424 void ICSInitScript P((void));
425 int LoadGamePopUp P((FILE *f, int gameNumber, char *title));
426 void ErrorPopUp P((char *title, char *text, int modal));
427 void ErrorPopDown P((void));
428 static char *ExpandPathName P((char *path));
429 static void CreateAnimVars P((void));
430 static void DragPieceBegin P((int x, int y));
431 static void DragPieceMove P((int x, int y));
432 static void DragPieceEnd P((int x, int y));
433 static void DrawDragPiece P((void));
434 char *ModeToWidgetName P((GameMode mode));
435 void EngineOutputUpdate( FrontEndProgramStats * stats );
436 void ShuffleMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
437 void EngineMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
438 void UciMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
439 void TimeControlProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
440 void NewVariantProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
441 void FirstSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
442 void SecondSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
443 void ShufflePopDown P(());
444 void EnginePopDown P(());
445 void UciPopDown P(());
446 void TimeControlPopDown P(());
447 void NewVariantPopDown P(());
448 void SettingsPopDown P(());
450 * XBoard depends on Xt R4 or higher
452 int xtVersion = XtSpecificationRelease;
457 Pixel lightSquareColor, darkSquareColor, whitePieceColor, blackPieceColor,
458 jailSquareColor, highlightSquareColor, premoveHighlightColor;
459 Pixel lowTimeWarningColor;
460 GC lightSquareGC, darkSquareGC, jailSquareGC, lineGC, wdPieceGC, wlPieceGC,
461 bdPieceGC, blPieceGC, wbPieceGC, bwPieceGC, coordGC, highlineGC,
462 wjPieceGC, bjPieceGC, prelineGC, countGC;
463 Pixmap iconPixmap, wIconPixmap, bIconPixmap, xMarkPixmap;
464 Widget shellWidget, layoutWidget, formWidget, boardWidget, messageWidget,
465 whiteTimerWidget, blackTimerWidget, titleWidget, widgetList[16],
466 commentShell, promotionShell, whitePieceMenu, blackPieceMenu, dropMenu,
467 menuBarWidget, buttonBarWidget, editShell, errorShell, analysisShell,
468 ICSInputShell, fileNameShell, askQuestionShell;
469 XSegment gridSegments[(BOARD_SIZE + 1) * 2];
470 XSegment jailGridSegments[(BOARD_SIZE + 3) * 2];
471 Font clockFontID, coordFontID, countFontID;
472 XFontStruct *clockFontStruct, *coordFontStruct, *countFontStruct;
473 XtAppContext appContext;
475 char *oldICSInteractionTitle;
479 char installDir[] = "."; // [HGM] UCI: needed for UCI; probably needs run-time initializtion
481 Position commentX = -1, commentY = -1;
482 Dimension commentW, commentH;
484 int squareSize, smallLayout = 0, tinyLayout = 0,
485 marginW, marginH, // [HGM] for run-time resizing
486 fromX = -1, fromY = -1, toX, toY, commentUp = False, analysisUp = False,
487 ICSInputBoxUp = False, askQuestionUp = False,
488 filenameUp = False, promotionUp = False, pmFromX = -1, pmFromY = -1,
489 editUp = False, errorUp = False, errorExitStatus = -1, lineGap;
490 Pixel timerForegroundPixel, timerBackgroundPixel;
491 Pixel buttonForegroundPixel, buttonBackgroundPixel;
492 char *chessDir, *programName, *programVersion,
493 *gameCopyFilename, *gamePasteFilename;
497 Pixmap pieceBitmap[2][(int)BlackPawn];
498 Pixmap xpmPieceBitmap[4][(int)BlackPawn]; /* LL, LD, DL, DD */
499 Pixmap xpmLightSquare, xpmDarkSquare, xpmJailSquare;
500 int useImages, useImageSqs;
501 XImage *ximPieceBitmap[4][(int)BlackPawn]; /* LL, LD, DL, DD */
502 Pixmap ximMaskPm[(int)BlackPawn]; /* clipmasks, used for XIM pieces */
503 XImage *ximLightSquare, *ximDarkSquare;
506 #define pieceToSolid(piece) &pieceBitmap[SOLID][((int)(piece)) % (int)BlackPawn]
507 #define pieceToOutline(piece) &pieceBitmap[OUTLINE][((int)(piece)) % (int)BlackPawn]
509 #define White(piece) ((int)(piece) < (int)BlackPawn)
511 /* Variables for doing smooth animation. This whole thing
512 would be much easier if the board was double-buffered,
513 but that would require a fairly major rewrite. */
518 GC blitGC, pieceGC, outlineGC;
519 XPoint startSquare, prevFrame, mouseDelta;
523 int startBoardX, startBoardY;
526 /* There can be two pieces being animated at once: a player
527 can begin dragging a piece before the remote opponent has moved. */
529 static AnimState game, player;
531 /* Bitmaps for use as masks when drawing XPM pieces.
532 Need one for each black and white piece. */
533 static Pixmap xpmMask[BlackKing + 1];
535 /* This magic number is the number of intermediate frames used
536 in each half of the animation. For short moves it's reduced
537 by 1. The total number of frames will be factor * 2 + 1. */
540 SizeDefaults sizeDefaults[] = SIZE_DEFAULTS;
542 MenuItem fileMenu[] = {
543 {N_("New Game"), ResetProc},
544 {N_("New Shuffle Game ..."), ShuffleMenuProc},
545 {N_("New Variant ..."), NewVariantProc}, // [HGM] variant: not functional yet
546 {"----", NothingProc},
547 {N_("Load Game"), LoadGameProc},
548 {N_("Load Next Game"), LoadNextGameProc},
549 {N_("Load Previous Game"), LoadPrevGameProc},
550 {N_("Reload Same Game"), ReloadGameProc},
551 {N_("Save Game"), SaveGameProc},
552 {"----", NothingProc},
553 {N_("Copy Game"), CopyGameProc},
554 {N_("Paste Game"), PasteGameProc},
555 {"----", NothingProc},
556 {N_("Load Position"), LoadPositionProc},
557 {N_("Load Next Position"), LoadNextPositionProc},
558 {N_("Load Previous Position"), LoadPrevPositionProc},
559 {N_("Reload Same Position"), ReloadPositionProc},
560 {N_("Save Position"), SavePositionProc},
561 {"----", NothingProc},
562 {N_("Copy Position"), CopyPositionProc},
563 {N_("Paste Position"), PastePositionProc},
564 {"----", NothingProc},
565 {N_("Mail Move"), MailMoveProc},
566 {N_("Reload CMail Message"), ReloadCmailMsgProc},
567 {"----", NothingProc},
568 {N_("Exit"), QuitProc},
572 MenuItem modeMenu[] = {
573 {N_("Machine White"), MachineWhiteProc},
574 {N_("Machine Black"), MachineBlackProc},
575 {N_("Two Machines"), TwoMachinesProc},
576 {N_("Analysis Mode"), AnalyzeModeProc},
577 {N_("Analyze File"), AnalyzeFileProc },
578 {N_("ICS Client"), IcsClientProc},
579 {N_("Edit Game"), EditGameProc},
580 {N_("Edit Position"), EditPositionProc},
581 {N_("Training"), TrainingProc},
582 {"----", NothingProc},
583 {N_("Show Engine Output"), EngineOutputProc},
584 {N_("Show Evaluation Graph"), NothingProc}, // [HGM] evalgr: not functional yet
585 {N_("Show Game List"), ShowGameListProc},
586 {"Show Move History", HistoryShowProc}, // [HGM] hist: activate 4.2.7 code
587 {"----", NothingProc},
588 {N_("Edit Tags"), EditTagsProc},
589 {N_("Edit Comment"), EditCommentProc},
590 {N_("ICS Input Box"), IcsInputBoxProc},
591 {N_("Pause"), PauseProc},
595 MenuItem actionMenu[] = {
596 {N_("Accept"), AcceptProc},
597 {N_("Decline"), DeclineProc},
598 {N_("Rematch"), RematchProc},
599 {"----", NothingProc},
600 {N_("Call Flag"), CallFlagProc},
601 {N_("Draw"), DrawProc},
602 {N_("Adjourn"), AdjournProc},
603 {N_("Abort"), AbortProc},
604 {N_("Resign"), ResignProc},
605 {"----", NothingProc},
606 {N_("Stop Observing"), StopObservingProc},
607 {N_("Stop Examining"), StopExaminingProc},
608 {"----", NothingProc},
609 {N_("Adjudicate to White"), AdjuWhiteProc},
610 {N_("Adjudicate to Black"), AdjuBlackProc},
611 {N_("Adjudicate Draw"), AdjuDrawProc},
615 MenuItem stepMenu[] = {
616 {N_("Backward"), BackwardProc},
617 {N_("Forward"), ForwardProc},
618 {N_("Back to Start"), ToStartProc},
619 {N_("Forward to End"), ToEndProc},
620 {N_("Revert"), RevertProc},
621 {N_("Truncate Game"), TruncateGameProc},
622 {"----", NothingProc},
623 {N_("Move Now"), MoveNowProc},
624 {N_("Retract Move"), RetractMoveProc},
628 MenuItem optionsMenu[] = {
629 {N_("Flip View"), FlipViewProc},
630 {"----", NothingProc},
631 {N_("Adjudications ..."), EngineMenuProc},
632 {N_("General Settings ..."), UciMenuProc},
633 {N_("Engine #1 Settings ..."), FirstSettingsProc},
634 {N_("Engine #2 Settings ..."), SecondSettingsProc},
635 {N_("Time Control ..."), TimeControlProc},
636 {"----", NothingProc},
637 {N_("Always Queen"), AlwaysQueenProc},
638 {N_("Animate Dragging"), AnimateDraggingProc},
639 {N_("Animate Moving"), AnimateMovingProc},
640 {N_("Auto Comment"), AutocommProc},
641 {N_("Auto Flag"), AutoflagProc},
642 {N_("Auto Flip View"), AutoflipProc},
643 {N_("Auto Observe"), AutobsProc},
644 {N_("Auto Raise Board"), AutoraiseProc},
645 {N_("Auto Save"), AutosaveProc},
646 {N_("Blindfold"), BlindfoldProc},
647 {N_("Flash Moves"), FlashMovesProc},
648 {N_("Get Move List"), GetMoveListProc},
650 {N_("Highlight Dragging"), HighlightDraggingProc},
652 {N_("Highlight Last Move"), HighlightLastMoveProc},
653 {N_("Move Sound"), MoveSoundProc},
654 {N_("ICS Alarm"), IcsAlarmProc},
655 {N_("Old Save Style"), OldSaveStyleProc},
656 {N_("Periodic Updates"), PeriodicUpdatesProc},
657 {N_("Ponder Next Move"), PonderNextMoveProc},
658 {N_("Popup Exit Message"), PopupExitMessageProc},
659 {N_("Popup Move Errors"), PopupMoveErrorsProc},
660 {N_("Premove"), PremoveProc},
661 {N_("Quiet Play"), QuietPlayProc},
662 {N_("Show Coords"), ShowCoordsProc},
663 {N_("Hide Thinking"), HideThinkingProc},
664 {N_("Test Legality"), TestLegalityProc},
668 MenuItem helpMenu[] = {
669 {N_("Info XBoard"), InfoProc},
670 {N_("Man XBoard"), ManProc},
671 {"----", NothingProc},
672 {N_("Hint"), HintProc},
673 {N_("Book"), BookProc},
674 {"----", NothingProc},
675 {N_("About XBoard"), AboutProc},
680 {N_("File"), fileMenu},
681 {N_("Mode"), modeMenu},
682 {N_("Action"), actionMenu},
683 {N_("Step"), stepMenu},
684 {N_("Options"), optionsMenu},
685 {N_("Help"), helpMenu},
689 #define PAUSE_BUTTON N_("P")
690 MenuItem buttonBar[] = {
693 {PAUSE_BUTTON, PauseProc},
699 #define PIECE_MENU_SIZE 11
700 String pieceMenuStrings[2][PIECE_MENU_SIZE] = {
701 { N_("White"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
702 N_("Queen"), N_("King"), "----", N_("Empty square"), N_("Clear board") },
703 { N_("Black"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
704 N_("Queen"), N_("King"), "----", N_("Empty square"), N_("Clear board") },
706 /* must be in same order as PieceMenuStrings! */
707 ChessSquare pieceMenuTranslation[2][PIECE_MENU_SIZE] = {
708 { WhitePlay, (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
709 WhiteRook, WhiteQueen, WhiteKing,
710 (ChessSquare) 0, EmptySquare, ClearBoard },
711 { BlackPlay, (ChessSquare) 0, BlackPawn, BlackKnight, BlackBishop,
712 BlackRook, BlackQueen, BlackKing,
713 (ChessSquare) 0, EmptySquare, ClearBoard },
716 #define DROP_MENU_SIZE 6
717 String dropMenuStrings[DROP_MENU_SIZE] = {
718 "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"), N_("Queen")
720 /* must be in same order as PieceMenuStrings! */
721 ChessSquare dropMenuTranslation[DROP_MENU_SIZE] = {
722 (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
723 WhiteRook, WhiteQueen
731 DropMenuEnables dmEnables[] = {
749 { XtNborderWidth, 0 },
750 { XtNdefaultDistance, 0 },
754 { XtNborderWidth, 0 },
755 { XtNresizable, (XtArgVal) True },
759 { XtNborderWidth, 0 },
765 { XtNjustify, (XtArgVal) XtJustifyRight },
766 { XtNlabel, (XtArgVal) "..." },
767 { XtNresizable, (XtArgVal) True },
768 { XtNresize, (XtArgVal) False }
771 Arg messageArgs[] = {
772 { XtNjustify, (XtArgVal) XtJustifyLeft },
773 { XtNlabel, (XtArgVal) "..." },
774 { XtNresizable, (XtArgVal) True },
775 { XtNresize, (XtArgVal) False }
779 { XtNborderWidth, 0 },
780 { XtNjustify, (XtArgVal) XtJustifyLeft }
783 XtResource clientResources[] = {
784 { "whitePieceColor", "whitePieceColor", XtRString, sizeof(String),
785 XtOffset(AppDataPtr, whitePieceColor), XtRString,
787 { "blackPieceColor", "blackPieceColor", XtRString, sizeof(String),
788 XtOffset(AppDataPtr, blackPieceColor), XtRString,
790 { "lightSquareColor", "lightSquareColor", XtRString,
791 sizeof(String), XtOffset(AppDataPtr, lightSquareColor),
792 XtRString, LIGHT_SQUARE_COLOR },
793 { "darkSquareColor", "darkSquareColor", XtRString, sizeof(String),
794 XtOffset(AppDataPtr, darkSquareColor), XtRString,
796 { "highlightSquareColor", "highlightSquareColor", XtRString,
797 sizeof(String), XtOffset(AppDataPtr, highlightSquareColor),
798 XtRString, HIGHLIGHT_SQUARE_COLOR },
799 { "premoveHighlightColor", "premoveHighlightColor", XtRString,
800 sizeof(String), XtOffset(AppDataPtr, premoveHighlightColor),
801 XtRString, PREMOVE_HIGHLIGHT_COLOR },
802 { "movesPerSession", "movesPerSession", XtRInt, sizeof(int),
803 XtOffset(AppDataPtr, movesPerSession), XtRImmediate,
804 (XtPointer) MOVES_PER_SESSION },
805 { "timeIncrement", "timeIncrement", XtRInt, sizeof(int),
806 XtOffset(AppDataPtr, timeIncrement), XtRImmediate,
807 (XtPointer) TIME_INCREMENT },
808 { "initString", "initString", XtRString, sizeof(String),
809 XtOffset(AppDataPtr, initString), XtRString, INIT_STRING },
810 { "secondInitString", "secondInitString", XtRString, sizeof(String),
811 XtOffset(AppDataPtr, secondInitString), XtRString, INIT_STRING },
812 { "firstComputerString", "firstComputerString", XtRString,
813 sizeof(String), XtOffset(AppDataPtr, firstComputerString), XtRString,
815 { "secondComputerString", "secondComputerString", XtRString,
816 sizeof(String), XtOffset(AppDataPtr, secondComputerString), XtRString,
818 { "firstChessProgram", "firstChessProgram", XtRString,
819 sizeof(String), XtOffset(AppDataPtr, firstChessProgram),
820 XtRString, FIRST_CHESS_PROGRAM },
821 { "secondChessProgram", "secondChessProgram", XtRString,
822 sizeof(String), XtOffset(AppDataPtr, secondChessProgram),
823 XtRString, SECOND_CHESS_PROGRAM },
824 { "firstPlaysBlack", "firstPlaysBlack", XtRBoolean,
825 sizeof(Boolean), XtOffset(AppDataPtr, firstPlaysBlack),
826 XtRImmediate, (XtPointer) False },
827 { "noChessProgram", "noChessProgram", XtRBoolean,
828 sizeof(Boolean), XtOffset(AppDataPtr, noChessProgram),
829 XtRImmediate, (XtPointer) False },
830 { "firstHost", "firstHost", XtRString, sizeof(String),
831 XtOffset(AppDataPtr, firstHost), XtRString, FIRST_HOST },
832 { "secondHost", "secondHost", XtRString, sizeof(String),
833 XtOffset(AppDataPtr, secondHost), XtRString, SECOND_HOST },
834 { "firstDirectory", "firstDirectory", XtRString, sizeof(String),
835 XtOffset(AppDataPtr, firstDirectory), XtRString, "." },
836 { "secondDirectory", "secondDirectory", XtRString, sizeof(String),
837 XtOffset(AppDataPtr, secondDirectory), XtRString, "." },
838 { "bitmapDirectory", "bitmapDirectory", XtRString,
839 sizeof(String), XtOffset(AppDataPtr, bitmapDirectory),
841 { "remoteShell", "remoteShell", XtRString, sizeof(String),
842 XtOffset(AppDataPtr, remoteShell), XtRString, REMOTE_SHELL },
843 { "remoteUser", "remoteUser", XtRString, sizeof(String),
844 XtOffset(AppDataPtr, remoteUser), XtRString, "" },
845 { "timeDelay", "timeDelay", XtRFloat, sizeof(float),
846 XtOffset(AppDataPtr, timeDelay), XtRString,
847 (XtPointer) TIME_DELAY_QUOTE },
848 { "timeControl", "timeControl", XtRString, sizeof(String),
849 XtOffset(AppDataPtr, timeControl), XtRString,
850 (XtPointer) TIME_CONTROL },
851 { "internetChessServerMode", "internetChessServerMode",
852 XtRBoolean, sizeof(Boolean),
853 XtOffset(AppDataPtr, icsActive), XtRImmediate,
855 { "internetChessServerHost", "internetChessServerHost",
856 XtRString, sizeof(String),
857 XtOffset(AppDataPtr, icsHost),
858 XtRString, (XtPointer) ICS_HOST },
859 { "internetChessServerPort", "internetChessServerPort",
860 XtRString, sizeof(String),
861 XtOffset(AppDataPtr, icsPort), XtRString,
862 (XtPointer) ICS_PORT },
863 { "internetChessServerCommPort", "internetChessServerCommPort",
864 XtRString, sizeof(String),
865 XtOffset(AppDataPtr, icsCommPort), XtRString,
867 { "internetChessServerLogonScript", "internetChessServerLogonScript",
868 XtRString, sizeof(String),
869 XtOffset(AppDataPtr, icsLogon), XtRString,
871 { "internetChessServerHelper", "internetChessServerHelper",
872 XtRString, sizeof(String),
873 XtOffset(AppDataPtr, icsHelper), XtRString, "" },
874 { "internetChessServerInputBox", "internetChessServerInputBox",
875 XtRBoolean, sizeof(Boolean),
876 XtOffset(AppDataPtr, icsInputBox), XtRImmediate,
878 { "icsAlarm", "icsAlarm",
879 XtRBoolean, sizeof(Boolean),
880 XtOffset(AppDataPtr, icsAlarm), XtRImmediate,
882 { "icsAlarmTime", "icsAlarmTime",
884 XtOffset(AppDataPtr, icsAlarmTime), XtRImmediate,
886 { "useTelnet", "useTelnet", XtRBoolean, sizeof(Boolean),
887 XtOffset(AppDataPtr, useTelnet), XtRImmediate,
889 { "telnetProgram", "telnetProgram", XtRString, sizeof(String),
890 XtOffset(AppDataPtr, telnetProgram), XtRString, TELNET_PROGRAM },
891 { "gateway", "gateway", XtRString, sizeof(String),
892 XtOffset(AppDataPtr, gateway), XtRString, "" },
893 { "loadGameFile", "loadGameFile", XtRString, sizeof(String),
894 XtOffset(AppDataPtr, loadGameFile), XtRString, "" },
895 { "loadGameIndex", "loadGameIndex",
897 XtOffset(AppDataPtr, loadGameIndex), XtRImmediate,
899 { "saveGameFile", "saveGameFile", XtRString, sizeof(String),
900 XtOffset(AppDataPtr, saveGameFile), XtRString, "" },
901 { "autoRaiseBoard", "autoRaiseBoard", XtRBoolean,
902 sizeof(Boolean), XtOffset(AppDataPtr, autoRaiseBoard),
903 XtRImmediate, (XtPointer) True },
904 { "autoSaveGames", "autoSaveGames", XtRBoolean,
905 sizeof(Boolean), XtOffset(AppDataPtr, autoSaveGames),
906 XtRImmediate, (XtPointer) False },
907 { "blindfold", "blindfold", XtRBoolean,
908 sizeof(Boolean), XtOffset(AppDataPtr, blindfold),
909 XtRImmediate, (XtPointer) False },
910 { "loadPositionFile", "loadPositionFile", XtRString,
911 sizeof(String), XtOffset(AppDataPtr, loadPositionFile),
913 { "loadPositionIndex", "loadPositionIndex",
915 XtOffset(AppDataPtr, loadPositionIndex), XtRImmediate,
917 { "savePositionFile", "savePositionFile", XtRString,
918 sizeof(String), XtOffset(AppDataPtr, savePositionFile),
920 { "matchMode", "matchMode", XtRBoolean, sizeof(Boolean),
921 XtOffset(AppDataPtr, matchMode), XtRImmediate, (XtPointer) False },
922 { "matchGames", "matchGames", XtRInt, sizeof(int),
923 XtOffset(AppDataPtr, matchGames), XtRImmediate,
925 { "monoMode", "monoMode", XtRBoolean, sizeof(Boolean),
926 XtOffset(AppDataPtr, monoMode), XtRImmediate,
928 { "debugMode", "debugMode", XtRBoolean, sizeof(Boolean),
929 XtOffset(AppDataPtr, debugMode), XtRImmediate,
931 { "clockMode", "clockMode", XtRBoolean, sizeof(Boolean),
932 XtOffset(AppDataPtr, clockMode), XtRImmediate,
934 { "boardSize", "boardSize", XtRString, sizeof(String),
935 XtOffset(AppDataPtr, boardSize), XtRString, "" },
936 { "searchTime", "searchTime", XtRString, sizeof(String),
937 XtOffset(AppDataPtr, searchTime), XtRString,
939 { "searchDepth", "searchDepth", XtRInt, sizeof(int),
940 XtOffset(AppDataPtr, searchDepth), XtRImmediate,
942 { "showCoords", "showCoords", XtRBoolean, sizeof(Boolean),
943 XtOffset(AppDataPtr, showCoords), XtRImmediate,
945 { "showJail", "showJail", XtRInt, sizeof(int),
946 XtOffset(AppDataPtr, showJail), XtRImmediate,
948 { "showThinking", "showThinking", XtRBoolean, sizeof(Boolean),
949 XtOffset(AppDataPtr, showThinking), XtRImmediate,
951 { "ponderNextMove", "ponderNextMove", XtRBoolean, sizeof(Boolean),
952 XtOffset(AppDataPtr, ponderNextMove), XtRImmediate,
954 { "periodicUpdates", "periodicUpdates", XtRBoolean, sizeof(Boolean),
955 XtOffset(AppDataPtr, periodicUpdates), XtRImmediate,
957 { "clockFont", "clockFont", XtRString, sizeof(String),
958 XtOffset(AppDataPtr, clockFont), XtRString, CLOCK_FONT },
959 { "coordFont", "coordFont", XtRString, sizeof(String),
960 XtOffset(AppDataPtr, coordFont), XtRString, COORD_FONT },
961 { "font", "font", XtRString, sizeof(String),
962 XtOffset(AppDataPtr, font), XtRString, DEFAULT_FONT },
963 { "ringBellAfterMoves", "ringBellAfterMoves",
964 XtRBoolean, sizeof(Boolean),
965 XtOffset(AppDataPtr, ringBellAfterMoves),
966 XtRImmediate, (XtPointer) False },
967 { "autoCallFlag", "autoCallFlag", XtRBoolean,
968 sizeof(Boolean), XtOffset(AppDataPtr, autoCallFlag),
969 XtRImmediate, (XtPointer) False },
970 { "autoFlipView", "autoFlipView", XtRBoolean,
971 sizeof(Boolean), XtOffset(AppDataPtr, autoFlipView),
972 XtRImmediate, (XtPointer) True },
973 { "autoObserve", "autoObserve", XtRBoolean,
974 sizeof(Boolean), XtOffset(AppDataPtr, autoObserve),
975 XtRImmediate, (XtPointer) False },
976 { "autoComment", "autoComment", XtRBoolean,
977 sizeof(Boolean), XtOffset(AppDataPtr, autoComment),
978 XtRImmediate, (XtPointer) False },
979 { "getMoveList", "getMoveList", XtRBoolean,
980 sizeof(Boolean), XtOffset(AppDataPtr, getMoveList),
981 XtRImmediate, (XtPointer) True },
983 { "highlightDragging", "highlightDragging", XtRBoolean,
984 sizeof(Boolean), XtOffset(AppDataPtr, highlightDragging),
985 XtRImmediate, (XtPointer) False },
987 { "highlightLastMove", "highlightLastMove", XtRBoolean,
988 sizeof(Boolean), XtOffset(AppDataPtr, highlightLastMove),
989 XtRImmediate, (XtPointer) False },
990 { "premove", "premove", XtRBoolean,
991 sizeof(Boolean), XtOffset(AppDataPtr, premove),
992 XtRImmediate, (XtPointer) True },
993 { "testLegality", "testLegality", XtRBoolean,
994 sizeof(Boolean), XtOffset(AppDataPtr, testLegality),
995 XtRImmediate, (XtPointer) True },
996 { "flipView", "flipView", XtRBoolean,
997 sizeof(Boolean), XtOffset(AppDataPtr, flipView),
998 XtRImmediate, (XtPointer) False },
999 { "cmail", "cmailGameName", XtRString, sizeof(String),
1000 XtOffset(AppDataPtr, cmailGameName), XtRString, "" },
1001 { "alwaysPromoteToQueen", "alwaysPromoteToQueen", XtRBoolean,
1002 sizeof(Boolean), XtOffset(AppDataPtr, alwaysPromoteToQueen),
1003 XtRImmediate, (XtPointer) False },
1004 { "oldSaveStyle", "oldSaveStyle", XtRBoolean,
1005 sizeof(Boolean), XtOffset(AppDataPtr, oldSaveStyle),
1006 XtRImmediate, (XtPointer) False },
1007 { "quietPlay", "quietPlay", XtRBoolean,
1008 sizeof(Boolean), XtOffset(AppDataPtr, quietPlay),
1009 XtRImmediate, (XtPointer) False },
1010 { "titleInWindow", "titleInWindow", XtRBoolean,
1011 sizeof(Boolean), XtOffset(AppDataPtr, titleInWindow),
1012 XtRImmediate, (XtPointer) False },
1013 { "localLineEditing", "localLineEditing", XtRBoolean,
1014 sizeof(Boolean), XtOffset(AppDataPtr, localLineEditing),
1015 XtRImmediate, (XtPointer) True }, /* not implemented, must be True */
1017 { "zippyTalk", "zippyTalk", XtRBoolean,
1018 sizeof(Boolean), XtOffset(AppDataPtr, zippyTalk),
1019 XtRImmediate, (XtPointer) ZIPPY_TALK },
1020 { "zippyPlay", "zippyPlay", XtRBoolean,
1021 sizeof(Boolean), XtOffset(AppDataPtr, zippyPlay),
1022 XtRImmediate, (XtPointer) ZIPPY_PLAY },
1023 { "zippyLines", "zippyLines", XtRString, sizeof(String),
1024 XtOffset(AppDataPtr, zippyLines), XtRString, ZIPPY_LINES },
1025 { "zippyPinhead", "zippyPinhead", XtRString, sizeof(String),
1026 XtOffset(AppDataPtr, zippyPinhead), XtRString, ZIPPY_PINHEAD },
1027 { "zippyPassword", "zippyPassword", XtRString, sizeof(String),
1028 XtOffset(AppDataPtr, zippyPassword), XtRString, ZIPPY_PASSWORD },
1029 { "zippyPassword2", "zippyPassword2", XtRString, sizeof(String),
1030 XtOffset(AppDataPtr, zippyPassword2), XtRString, ZIPPY_PASSWORD2 },
1031 { "zippyWrongPassword", "zippyWrongPassword", XtRString, sizeof(String),
1032 XtOffset(AppDataPtr, zippyWrongPassword), XtRString,
1033 ZIPPY_WRONG_PASSWORD },
1034 { "zippyAcceptOnly", "zippyAcceptOnly", XtRString, sizeof(String),
1035 XtOffset(AppDataPtr, zippyAcceptOnly), XtRString, ZIPPY_ACCEPT_ONLY },
1036 { "zippyUseI", "zippyUseI", XtRBoolean,
1037 sizeof(Boolean), XtOffset(AppDataPtr, zippyUseI),
1038 XtRImmediate, (XtPointer) ZIPPY_USE_I },
1039 { "zippyBughouse", "zippyBughouse", XtRInt,
1040 sizeof(int), XtOffset(AppDataPtr, zippyBughouse),
1041 XtRImmediate, (XtPointer) ZIPPY_BUGHOUSE },
1042 { "zippyNoplayCrafty", "zippyNoplayCrafty", XtRBoolean,
1043 sizeof(Boolean), XtOffset(AppDataPtr, zippyNoplayCrafty),
1044 XtRImmediate, (XtPointer) ZIPPY_NOPLAY_CRAFTY },
1045 { "zippyGameEnd", "zippyGameEnd", XtRString, sizeof(String),
1046 XtOffset(AppDataPtr, zippyGameEnd), XtRString, ZIPPY_GAME_END },
1047 { "zippyGameStart", "zippyGameStart", XtRString, sizeof(String),
1048 XtOffset(AppDataPtr, zippyGameStart), XtRString, ZIPPY_GAME_START },
1049 { "zippyAdjourn", "zippyAdjourn", XtRBoolean,
1050 sizeof(Boolean), XtOffset(AppDataPtr, zippyAdjourn),
1051 XtRImmediate, (XtPointer) ZIPPY_ADJOURN },
1052 { "zippyAbort", "zippyAbort", XtRBoolean,
1053 sizeof(Boolean), XtOffset(AppDataPtr, zippyAbort),
1054 XtRImmediate, (XtPointer) ZIPPY_ABORT },
1055 { "zippyVariants", "zippyVariants", XtRString, sizeof(String),
1056 XtOffset(AppDataPtr, zippyVariants), XtRString, ZIPPY_VARIANTS },
1057 { "zippyMaxGames", "zippyMaxGames", XtRInt, sizeof(int),
1058 XtOffset(AppDataPtr, zippyMaxGames), XtRImmediate,
1059 (XtPointer) ZIPPY_MAX_GAMES },
1060 { "zippyReplayTimeout", "zippyReplayTimeout", XtRInt, sizeof(int),
1061 XtOffset(AppDataPtr, zippyReplayTimeout), XtRImmediate,
1062 (XtPointer) ZIPPY_REPLAY_TIMEOUT },
1063 { "zippyShortGame", "zippyShortGame", XtRInt, sizeof(int),
1064 XtOffset(AppDataPtr, zippyShortGame), XtRImmediate,
1067 { "flashCount", "flashCount", XtRInt, sizeof(int),
1068 XtOffset(AppDataPtr, flashCount), XtRImmediate,
1069 (XtPointer) FLASH_COUNT },
1070 { "flashRate", "flashRate", XtRInt, sizeof(int),
1071 XtOffset(AppDataPtr, flashRate), XtRImmediate,
1072 (XtPointer) FLASH_RATE },
1073 { "pixmapDirectory", "pixmapDirectory", XtRString,
1074 sizeof(String), XtOffset(AppDataPtr, pixmapDirectory),
1076 { "msLoginDelay", "msLoginDelay", XtRInt, sizeof(int),
1077 XtOffset(AppDataPtr, msLoginDelay), XtRImmediate,
1078 (XtPointer) MS_LOGIN_DELAY },
1079 { "colorizeMessages", "colorizeMessages", XtRBoolean,
1080 sizeof(Boolean), XtOffset(AppDataPtr, colorize),
1081 XtRImmediate, (XtPointer) False },
1082 { "colorShout", "colorShout", XtRString,
1083 sizeof(String), XtOffset(AppDataPtr, colorShout),
1084 XtRString, COLOR_SHOUT },
1085 { "colorSShout", "colorSShout", XtRString,
1086 sizeof(String), XtOffset(AppDataPtr, colorSShout),
1087 XtRString, COLOR_SSHOUT },
1088 { "colorChannel1", "colorChannel1", XtRString,
1089 sizeof(String), XtOffset(AppDataPtr, colorChannel1),
1090 XtRString, COLOR_CHANNEL1 },
1091 { "colorChannel", "colorChannel", XtRString,
1092 sizeof(String), XtOffset(AppDataPtr, colorChannel),
1093 XtRString, COLOR_CHANNEL },
1094 { "colorKibitz", "colorKibitz", XtRString,
1095 sizeof(String), XtOffset(AppDataPtr, colorKibitz),
1096 XtRString, COLOR_KIBITZ },
1097 { "colorTell", "colorTell", XtRString,
1098 sizeof(String), XtOffset(AppDataPtr, colorTell),
1099 XtRString, COLOR_TELL },
1100 { "colorChallenge", "colorChallenge", XtRString,
1101 sizeof(String), XtOffset(AppDataPtr, colorChallenge),
1102 XtRString, COLOR_CHALLENGE },
1103 { "colorRequest", "colorRequest", XtRString,
1104 sizeof(String), XtOffset(AppDataPtr, colorRequest),
1105 XtRString, COLOR_REQUEST },
1106 { "colorSeek", "colorSeek", XtRString,
1107 sizeof(String), XtOffset(AppDataPtr, colorSeek),
1108 XtRString, COLOR_SEEK },
1109 { "colorNormal", "colorNormal", XtRString,
1110 sizeof(String), XtOffset(AppDataPtr, colorNormal),
1111 XtRString, COLOR_NORMAL },
1112 { "soundProgram", "soundProgram", XtRString,
1113 sizeof(String), XtOffset(AppDataPtr, soundProgram),
1114 XtRString, "play" },
1115 { "soundShout", "soundShout", XtRString,
1116 sizeof(String), XtOffset(AppDataPtr, soundShout),
1118 { "soundSShout", "soundSShout", XtRString,
1119 sizeof(String), XtOffset(AppDataPtr, soundSShout),
1121 { "soundChannel1", "soundChannel1", XtRString,
1122 sizeof(String), XtOffset(AppDataPtr, soundChannel1),
1124 { "soundChannel", "soundChannel", XtRString,
1125 sizeof(String), XtOffset(AppDataPtr, soundChannel),
1127 { "soundKibitz", "soundKibitz", XtRString,
1128 sizeof(String), XtOffset(AppDataPtr, soundKibitz),
1130 { "soundTell", "soundTell", XtRString,
1131 sizeof(String), XtOffset(AppDataPtr, soundTell),
1133 { "soundChallenge", "soundChallenge", XtRString,
1134 sizeof(String), XtOffset(AppDataPtr, soundChallenge),
1136 { "soundRequest", "soundRequest", XtRString,
1137 sizeof(String), XtOffset(AppDataPtr, soundRequest),
1139 { "soundSeek", "soundSeek", XtRString,
1140 sizeof(String), XtOffset(AppDataPtr, soundSeek),
1142 { "soundMove", "soundMove", XtRString,
1143 sizeof(String), XtOffset(AppDataPtr, soundMove),
1145 { "soundIcsWin", "soundIcsWin", XtRString,
1146 sizeof(String), XtOffset(AppDataPtr, soundIcsWin),
1148 { "soundIcsLoss", "soundIcsLoss", XtRString,
1149 sizeof(String), XtOffset(AppDataPtr, soundIcsLoss),
1151 { "soundIcsDraw", "soundIcsDraw", XtRString,
1152 sizeof(String), XtOffset(AppDataPtr, soundIcsDraw),
1154 { "soundIcsUnfinished", "soundIcsUnfinished", XtRString,
1155 sizeof(String), XtOffset(AppDataPtr, soundIcsUnfinished),
1157 { "soundIcsAlarm", "soundIcsAlarm", XtRString,
1158 sizeof(String), XtOffset(AppDataPtr, soundIcsAlarm),
1160 { "reuseFirst", "reuseFirst", XtRBoolean,
1161 sizeof(Boolean), XtOffset(AppDataPtr, reuseFirst),
1162 XtRImmediate, (XtPointer) True },
1163 { "reuseSecond", "reuseSecond", XtRBoolean,
1164 sizeof(Boolean), XtOffset(AppDataPtr, reuseSecond),
1165 XtRImmediate, (XtPointer) True },
1166 { "animateDragging", "animateDragging", XtRBoolean,
1167 sizeof(Boolean), XtOffset(AppDataPtr, animateDragging),
1168 XtRImmediate, (XtPointer) True },
1169 { "animateMoving", "animateMoving", XtRBoolean,
1170 sizeof(Boolean), XtOffset(AppDataPtr, animate),
1171 XtRImmediate, (XtPointer) True },
1172 { "animateSpeed", "animateSpeed", XtRInt,
1173 sizeof(int), XtOffset(AppDataPtr, animSpeed),
1174 XtRImmediate, (XtPointer)10 },
1175 { "popupExitMessage", "popupExitMessage", XtRBoolean,
1176 sizeof(Boolean), XtOffset(AppDataPtr, popupExitMessage),
1177 XtRImmediate, (XtPointer) True },
1178 { "popupMoveErrors", "popupMoveErrors", XtRBoolean,
1179 sizeof(Boolean), XtOffset(AppDataPtr, popupMoveErrors),
1180 XtRImmediate, (XtPointer) False },
1181 { "fontSizeTolerance", "fontSizeTolerance", XtRInt,
1182 sizeof(int), XtOffset(AppDataPtr, fontSizeTolerance),
1183 XtRImmediate, (XtPointer)4 },
1184 { "initialMode", "initialMode", XtRString,
1185 sizeof(String), XtOffset(AppDataPtr, initialMode),
1186 XtRImmediate, (XtPointer) "" },
1187 { "variant", "variant", XtRString,
1188 sizeof(String), XtOffset(AppDataPtr, variant),
1189 XtRImmediate, (XtPointer) "normal" },
1190 { "firstProtocolVersion", "firstProtocolVersion", XtRInt,
1191 sizeof(int), XtOffset(AppDataPtr, firstProtocolVersion),
1192 XtRImmediate, (XtPointer)PROTOVER },
1193 { "secondProtocolVersion", "secondProtocolVersion", XtRInt,
1194 sizeof(int), XtOffset(AppDataPtr, secondProtocolVersion),
1195 XtRImmediate, (XtPointer)PROTOVER },
1196 { "showButtonBar", "showButtonBar", XtRBoolean,
1197 sizeof(Boolean), XtOffset(AppDataPtr, showButtonBar),
1198 XtRImmediate, (XtPointer) True },
1199 { "lowTimeWarningColor", "lowTimeWarningColor", XtRString,
1200 sizeof(String), XtOffset(AppDataPtr, lowTimeWarningColor),
1201 XtRString, COLOR_LOWTIMEWARNING },
1202 { "lowTimeWarning", "lowTimeWarning", XtRBoolean,
1203 sizeof(Boolean), XtOffset(AppDataPtr, lowTimeWarning),
1204 XtRImmediate, (XtPointer) False },
1205 {"icsEngineAnalyze", "icsEngineAnalyze", XtRBoolean, /* [DM] icsEngineAnalyze */
1206 sizeof(Boolean), XtOffset(AppDataPtr, icsEngineAnalyze),
1207 XtRImmediate, (XtPointer) False },
1208 { "firstScoreAbs", "firstScoreAbs", XtRBoolean,
1209 sizeof(Boolean), XtOffset(AppDataPtr, firstScoreIsAbsolute),
1210 XtRImmediate, (XtPointer) False },
1211 { "secondScoreAbs", "secondScoreAbs", XtRBoolean,
1212 sizeof(Boolean), XtOffset(AppDataPtr, secondScoreIsAbsolute),
1213 XtRImmediate, (XtPointer) False },
1214 { "pgnExtendedInfo", "pgnExtendedInfo", XtRBoolean,
1215 sizeof(Boolean), XtOffset(AppDataPtr, saveExtendedInfoInPGN),
1216 XtRImmediate, (XtPointer) False },
1217 { "hideThinkingFromHuman", "hideThinkingFromHuman", XtRBoolean,
1218 sizeof(Boolean), XtOffset(AppDataPtr, hideThinkingFromHuman),
1219 XtRImmediate, (XtPointer) True },
1220 { "adjudicateLossThreshold", "adjudicateLossThreshold", XtRInt,
1221 sizeof(int), XtOffset(AppDataPtr, adjudicateLossThreshold),
1222 XtRImmediate, (XtPointer) 0},
1223 { "pgnEventHeader", "pgnEventHeader", XtRString,
1224 sizeof(String), XtOffset(AppDataPtr, pgnEventHeader),
1225 XtRImmediate, (XtPointer) "Computer Chess Game" },
1226 { "defaultFrcPosition", "defaultFrcPositon", XtRInt,
1227 sizeof(int), XtOffset(AppDataPtr, defaultFrcPosition),
1228 XtRImmediate, (XtPointer) -1},
1229 { "gameListTags", "gameListTags", XtRString,
1230 sizeof(String), XtOffset(AppDataPtr, gameListTags),
1231 XtRImmediate, (XtPointer) GLT_DEFAULT_TAGS },
1233 // [HGM] 4.3.xx options
1234 { "boardWidth", "boardWidth", XtRInt,
1235 sizeof(int), XtOffset(AppDataPtr, NrFiles),
1236 XtRImmediate, (XtPointer) -1},
1237 { "boardHeight", "boardHeight", XtRInt,
1238 sizeof(int), XtOffset(AppDataPtr, NrRanks),
1239 XtRImmediate, (XtPointer) -1},
1240 { "matchPause", "matchPause", XtRInt,
1241 sizeof(int), XtOffset(AppDataPtr, matchPause),
1242 XtRImmediate, (XtPointer) 10000},
1243 { "holdingsSize", "holdingsSize", XtRInt,
1244 sizeof(int), XtOffset(AppDataPtr, holdingsSize),
1245 XtRImmediate, (XtPointer) -1},
1246 { "flipBlack", "flipBlack", XtRBoolean,
1247 sizeof(Boolean), XtOffset(AppDataPtr, upsideDown),
1248 XtRImmediate, (XtPointer) False},
1249 { "allWhite", "allWhite", XtRBoolean,
1250 sizeof(Boolean), XtOffset(AppDataPtr, allWhite),
1251 XtRImmediate, (XtPointer) False},
1252 { "pieceToCharTable", "pieceToCharTable", XtRString,
1253 sizeof(String), XtOffset(AppDataPtr, pieceToCharTable),
1254 XtRImmediate, (XtPointer) 0},
1255 { "alphaRank", "alphaRank", XtRBoolean,
1256 sizeof(Boolean), XtOffset(AppDataPtr, alphaRank),
1257 XtRImmediate, (XtPointer) False},
1258 { "testClaims", "testClaims", XtRBoolean,
1259 sizeof(Boolean), XtOffset(AppDataPtr, testClaims),
1260 XtRImmediate, (XtPointer) True},
1261 { "checkMates", "checkMates", XtRBoolean,
1262 sizeof(Boolean), XtOffset(AppDataPtr, checkMates),
1263 XtRImmediate, (XtPointer) True},
1264 { "materialDraws", "materialDraws", XtRBoolean,
1265 sizeof(Boolean), XtOffset(AppDataPtr, materialDraws),
1266 XtRImmediate, (XtPointer) True},
1267 { "trivialDraws", "trivialDraws", XtRBoolean,
1268 sizeof(Boolean), XtOffset(AppDataPtr, trivialDraws),
1269 XtRImmediate, (XtPointer) False},
1270 { "ruleMoves", "ruleMoves", XtRInt,
1271 sizeof(int), XtOffset(AppDataPtr, ruleMoves),
1272 XtRImmediate, (XtPointer) 51},
1273 { "repeatsToDraw", "repeatsToDraw", XtRInt,
1274 sizeof(int), XtOffset(AppDataPtr, drawRepeats),
1275 XtRImmediate, (XtPointer) 6},
1276 { "engineDebugOutput", "engineDebugOutput", XtRInt,
1277 sizeof(int), XtOffset(AppDataPtr, engineComments),
1278 XtRImmediate, (XtPointer) 1},
1279 { "userName", "userName", XtRString,
1280 sizeof(int), XtOffset(AppDataPtr, userName),
1281 XtRImmediate, (XtPointer) 0},
1282 { "autoKibitz", "autoKibitz", XtRBoolean,
1283 sizeof(Boolean), XtOffset(AppDataPtr, autoKibitz),
1284 XtRImmediate, (XtPointer) False},
1285 { "firstTimeOdds", "firstTimeOdds", XtRInt,
1286 sizeof(int), XtOffset(AppDataPtr, firstTimeOdds),
1287 XtRImmediate, (XtPointer) 1},
1288 { "secondTimeOdds", "secondTimeOdds", XtRInt,
1289 sizeof(int), XtOffset(AppDataPtr, secondTimeOdds),
1290 XtRImmediate, (XtPointer) 1},
1291 { "timeOddsMode", "timeOddsMode", XtRInt,
1292 sizeof(int), XtOffset(AppDataPtr, timeOddsMode),
1293 XtRImmediate, (XtPointer) 0},
1294 { "firstAccumulateTC", "firstAccumulateTC", XtRInt,
1295 sizeof(int), XtOffset(AppDataPtr, firstAccumulateTC),
1296 XtRImmediate, (XtPointer) 1},
1297 { "secondAccumulateTC", "secondAccumulateTC", XtRInt,
1298 sizeof(int), XtOffset(AppDataPtr, secondAccumulateTC),
1299 XtRImmediate, (XtPointer) 1},
1300 { "firstNPS", "firstNPS", XtRInt,
1301 sizeof(int), XtOffset(AppDataPtr, firstNPS),
1302 XtRImmediate, (XtPointer) -1},
1303 { "secondNPS", "secondNPS", XtRInt,
1304 sizeof(int), XtOffset(AppDataPtr, secondNPS),
1305 XtRImmediate, (XtPointer) -1},
1306 { "serverMoves", "serverMoves", XtRString,
1307 sizeof(String), XtOffset(AppDataPtr, serverMovesName),
1308 XtRImmediate, (XtPointer) 0},
1309 { "serverPause", "serverPause", XtRInt,
1310 sizeof(int), XtOffset(AppDataPtr, serverPause),
1311 XtRImmediate, (XtPointer) 0},
1312 { "suppressLoadMoves", "suppressLoadMoves", XtRBoolean,
1313 sizeof(Boolean), XtOffset(AppDataPtr, suppressLoadMoves),
1314 XtRImmediate, (XtPointer) False},
1315 { "userName", "userName", XtRString,
1316 sizeof(String), XtOffset(AppDataPtr, userName),
1317 XtRImmediate, (XtPointer) 0},
1318 { "egtFormats", "egtFormats", XtRString,
1319 sizeof(String), XtOffset(AppDataPtr, egtFormats),
1320 XtRImmediate, (XtPointer) 0},
1321 { "rewindIndex", "rewindIndex", XtRInt,
1322 sizeof(int), XtOffset(AppDataPtr, rewindIndex),
1323 XtRImmediate, (XtPointer) 0},
1324 { "sameColorGames", "sameColorGames", XtRInt,
1325 sizeof(int), XtOffset(AppDataPtr, sameColorGames),
1326 XtRImmediate, (XtPointer) 0},
1327 { "smpCores", "smpCores", XtRInt,
1328 sizeof(int), XtOffset(AppDataPtr, smpCores),
1329 XtRImmediate, (XtPointer) 1},
1330 { "niceEngines", "niceEngines", XtRInt,
1331 sizeof(int), XtOffset(AppDataPtr, niceEngines),
1332 XtRImmediate, (XtPointer) 0},
1333 { "nameOfDebugFile", "nameOfDebugFile", XtRString,
1334 sizeof(String), XtOffset(AppDataPtr, nameOfDebugFile),
1335 XtRImmediate, (XtPointer) "xboard.debug"},
1336 { "engineDebugOutput", "engineDebugOutput", XtRInt,
1337 sizeof(int), XtOffset(AppDataPtr, engineComments),
1338 XtRImmediate, (XtPointer) 0},
1339 { "noGUI", "noGUI", XtRBoolean,
1340 sizeof(Boolean), XtOffset(AppDataPtr, noGUI),
1341 XtRImmediate, (XtPointer) 0},
1342 { "firstOptions", "firstOptions", XtRString,
1343 sizeof(String), XtOffset(AppDataPtr, firstOptions),
1344 XtRImmediate, (XtPointer) "" },
1345 { "secondOptions", "secondOptions", XtRString,
1346 sizeof(String), XtOffset(AppDataPtr, secondOptions),
1347 XtRImmediate, (XtPointer) "" },
1348 { "firstNeedsNoncompliantFEN", "firstNeedsNoncompliantFEN", XtRString,
1349 sizeof(String), XtOffset(AppDataPtr, fenOverride1),
1350 XtRImmediate, (XtPointer) 0 },
1351 { "secondNeedsNoncompliantFEN", "secondNeedsNoncompliantFEN", XtRString,
1352 sizeof(String), XtOffset(AppDataPtr, fenOverride2),
1353 XtRImmediate, (XtPointer) 0 },
1355 // [HGM] Winboard_x UCI options
1356 { "firstIsUCI", "firstIsUCI", XtRBoolean,
1357 sizeof(Boolean), XtOffset(AppDataPtr, firstIsUCI),
1358 XtRImmediate, (XtPointer) False},
1359 { "secondIsUCI", "secondIsUCI", XtRBoolean,
1360 sizeof(Boolean), XtOffset(AppDataPtr, secondIsUCI),
1361 XtRImmediate, (XtPointer) False},
1362 { "firstHasOwnBookUCI", "firstHasOwnBookUCI", XtRBoolean,
1363 sizeof(Boolean), XtOffset(AppDataPtr, firstHasOwnBookUCI),
1364 XtRImmediate, (XtPointer) True},
1365 { "secondHasOwnBookUCI", "secondHasOwnBookUCI", XtRBoolean,
1366 sizeof(Boolean), XtOffset(AppDataPtr, secondHasOwnBookUCI),
1367 XtRImmediate, (XtPointer) True},
1368 { "usePolyglotBook", "usePolyglotBook", XtRBoolean,
1369 sizeof(Boolean), XtOffset(AppDataPtr, usePolyglotBook),
1370 XtRImmediate, (XtPointer) False},
1371 { "defaultHashSize", "defaultHashSize", XtRInt,
1372 sizeof(int), XtOffset(AppDataPtr, defaultHashSize),
1373 XtRImmediate, (XtPointer) 64},
1374 { "defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XtRInt,
1375 sizeof(int), XtOffset(AppDataPtr, defaultCacheSizeEGTB),
1376 XtRImmediate, (XtPointer) 4},
1377 { "polyglotDir", "polyglotDir", XtRString,
1378 sizeof(String), XtOffset(AppDataPtr, polyglotDir),
1379 XtRImmediate, (XtPointer) "." },
1380 { "polyglotBook", "polyglotBook", XtRString,
1381 sizeof(String), XtOffset(AppDataPtr, polyglotBook),
1382 XtRImmediate, (XtPointer) "" },
1383 { "defaultPathEGTB", "defaultPathEGTB", XtRString,
1384 sizeof(String), XtOffset(AppDataPtr, defaultPathEGTB),
1385 XtRImmediate, (XtPointer) "/usr/local/share/egtb"},
1386 { "delayBeforeQuit", "delayBeforeQuit", XtRInt,
1387 sizeof(int), XtOffset(AppDataPtr, delayBeforeQuit),
1388 XtRImmediate, (XtPointer) 0},
1389 { "delayAfterQuit", "delayAfterQuit", XtRInt,
1390 sizeof(int), XtOffset(AppDataPtr, delayAfterQuit),
1391 XtRImmediate, (XtPointer) 0},
1394 XrmOptionDescRec shellOptions[] = {
1395 { "-whitePieceColor", "whitePieceColor", XrmoptionSepArg, NULL },
1396 { "-blackPieceColor", "blackPieceColor", XrmoptionSepArg, NULL },
1397 { "-lightSquareColor", "lightSquareColor", XrmoptionSepArg, NULL },
1398 { "-darkSquareColor", "darkSquareColor", XrmoptionSepArg, NULL },
1399 { "-highlightSquareColor", "highlightSquareColor", XrmoptionSepArg, NULL },
1400 { "-premoveHighlightColor", "premoveHighlightColor", XrmoptionSepArg,NULL},
1401 { "-movesPerSession", "movesPerSession", XrmoptionSepArg, NULL },
1402 { "-mps", "movesPerSession", XrmoptionSepArg, NULL },
1403 { "-timeIncrement", "timeIncrement", XrmoptionSepArg, NULL },
1404 { "-inc", "timeIncrement", XrmoptionSepArg, NULL },
1405 { "-initString", "initString", XrmoptionSepArg, NULL },
1406 { "-firstInitString", "initString", XrmoptionSepArg, NULL },
1407 { "-secondInitString", "secondInitString", XrmoptionSepArg, NULL },
1408 { "-firstComputerString", "firstComputerString", XrmoptionSepArg, NULL },
1409 { "-secondComputerString", "secondComputerString", XrmoptionSepArg, NULL },
1410 { "-firstChessProgram", "firstChessProgram", XrmoptionSepArg, NULL },
1411 { "-fcp", "firstChessProgram", XrmoptionSepArg, NULL },
1412 { "-secondChessProgram", "secondChessProgram", XrmoptionSepArg, NULL },
1413 { "-scp", "secondChessProgram", XrmoptionSepArg, NULL },
1414 { "-firstPlaysBlack", "firstPlaysBlack", XrmoptionSepArg, NULL },
1415 { "-fb", "firstPlaysBlack", XrmoptionNoArg, "True" },
1416 { "-xfb", "firstPlaysBlack", XrmoptionNoArg, "False" },
1417 { "-noChessProgram", "noChessProgram", XrmoptionSepArg, NULL },
1418 { "-ncp", "noChessProgram", XrmoptionNoArg, "True" },
1419 { "-xncp", "noChessProgram", XrmoptionNoArg, "False" },
1420 { "-firstHost", "firstHost", XrmoptionSepArg, NULL },
1421 { "-fh", "firstHost", XrmoptionSepArg, NULL },
1422 { "-secondHost", "secondHost", XrmoptionSepArg, NULL },
1423 { "-sh", "secondHost", XrmoptionSepArg, NULL },
1424 { "-firstDirectory", "firstDirectory", XrmoptionSepArg, NULL },
1425 { "-fd", "firstDirectory", XrmoptionSepArg, NULL },
1426 { "-secondDirectory", "secondDirectory", XrmoptionSepArg, NULL },
1427 { "-sd", "secondDirectory", XrmoptionSepArg, NULL },
1428 { "-bitmapDirectory", "bitmapDirectory", XrmoptionSepArg, NULL },
1429 { "-bm", "bitmapDirectory", XrmoptionSepArg, NULL },
1430 { "-remoteShell", "remoteShell", XrmoptionSepArg, NULL },
1431 { "-rsh", "remoteShell", XrmoptionSepArg, NULL },
1432 { "-remoteUser", "remoteUser", XrmoptionSepArg, NULL },
1433 { "-ruser", "remoteUser", XrmoptionSepArg, NULL },
1434 { "-timeDelay", "timeDelay", XrmoptionSepArg, NULL },
1435 { "-td", "timeDelay", XrmoptionSepArg, NULL },
1436 { "-timeControl", "timeControl", XrmoptionSepArg, NULL },
1437 { "-tc", "timeControl", XrmoptionSepArg, NULL },
1438 { "-internetChessServerMode", "internetChessServerMode",
1439 XrmoptionSepArg, NULL },
1440 { "-ics", "internetChessServerMode", XrmoptionNoArg, "True" },
1441 { "-xics", "internetChessServerMode", XrmoptionNoArg, "False" },
1442 { "-internetChessServerHost", "internetChessServerHost",
1443 XrmoptionSepArg, NULL },
1444 { "-icshost", "internetChessServerHost", XrmoptionSepArg, NULL },
1445 { "-internetChessServerPort", "internetChessServerPort",
1446 XrmoptionSepArg, NULL },
1447 { "-icsport", "internetChessServerPort", XrmoptionSepArg, NULL },
1448 { "-internetChessServerCommPort", "internetChessServerCommPort",
1449 XrmoptionSepArg, NULL },
1450 { "-icscomm", "internetChessServerCommPort", XrmoptionSepArg, NULL },
1451 { "-internetChessServerLogonScript", "internetChessServerLogonScript",
1452 XrmoptionSepArg, NULL },
1453 { "-icslogon", "internetChessServerLogonScript", XrmoptionSepArg, NULL },
1454 { "-internetChessServerHelper", "internetChessServerHelper",
1455 XrmoptionSepArg, NULL },
1456 { "-icshelper", "internetChessServerHelper", XrmoptionSepArg, NULL },
1457 { "-internetChessServerInputBox", "internetChessServerInputBox",
1458 XrmoptionSepArg, NULL },
1459 { "-icsinput", "internetChessServerInputBox", XrmoptionNoArg, "True" },
1460 { "-xicsinput", "internetChessServerInputBox", XrmoptionNoArg, "False" },
1461 { "-icsAlarm", "icsAlarm", XrmoptionSepArg, NULL },
1462 { "-alarm", "icsAlarm", XrmoptionNoArg, "True" },
1463 { "-xalarm", "icsAlarm", XrmoptionNoArg, "False" },
1464 { "-icsAlarmTime", "icsAlarmTime", XrmoptionSepArg, NULL },
1465 { "-useTelnet", "useTelnet", XrmoptionSepArg, NULL },
1466 { "-telnet", "useTelnet", XrmoptionNoArg, "True" },
1467 { "-xtelnet", "useTelnet", XrmoptionNoArg, "False" },
1468 { "-telnetProgram", "telnetProgram", XrmoptionSepArg, NULL },
1469 { "-gateway", "gateway", XrmoptionSepArg, NULL },
1470 { "-loadGameFile", "loadGameFile", XrmoptionSepArg, NULL },
1471 { "-lgf", "loadGameFile", XrmoptionSepArg, NULL },
1472 { "-loadGameIndex", "loadGameIndex", XrmoptionSepArg, NULL },
1473 { "-lgi", "loadGameIndex", XrmoptionSepArg, NULL },
1474 { "-saveGameFile", "saveGameFile", XrmoptionSepArg, NULL },
1475 { "-sgf", "saveGameFile", XrmoptionSepArg, NULL },
1476 { "-autoSaveGames", "autoSaveGames", XrmoptionSepArg, NULL },
1477 { "-autosave", "autoSaveGames", XrmoptionNoArg, "True" },
1478 { "-xautosave", "autoSaveGames", XrmoptionNoArg, "False" },
1479 { "-autoRaiseBoard", "autoRaiseBoard", XrmoptionSepArg, NULL },
1480 { "-autoraise", "autoRaiseBoard", XrmoptionNoArg, "True" },
1481 { "-xautoraise", "autoRaiseBoard", XrmoptionNoArg, "False" },
1482 { "-blindfold", "blindfold", XrmoptionSepArg, NULL },
1483 { "-blind", "blindfold", XrmoptionNoArg, "True" },
1484 { "-xblind", "blindfold", XrmoptionNoArg, "False" },
1485 { "-loadPositionFile", "loadPositionFile", XrmoptionSepArg, NULL },
1486 { "-lpf", "loadPositionFile", XrmoptionSepArg, NULL },
1487 { "-loadPositionIndex", "loadPositionIndex", XrmoptionSepArg, NULL },
1488 { "-lpi", "loadPositionIndex", XrmoptionSepArg, NULL },
1489 { "-savePositionFile", "savePositionFile", XrmoptionSepArg, NULL },
1490 { "-spf", "savePositionFile", XrmoptionSepArg, NULL },
1491 { "-matchMode", "matchMode", XrmoptionSepArg, NULL },
1492 { "-mm", "matchMode", XrmoptionNoArg, "True" },
1493 { "-xmm", "matchMode", XrmoptionNoArg, "False" },
1494 { "-matchGames", "matchGames", XrmoptionSepArg, NULL },
1495 { "-mg", "matchGames", XrmoptionSepArg, NULL },
1496 { "-monoMode", "monoMode", XrmoptionSepArg, NULL },
1497 { "-mono", "monoMode", XrmoptionNoArg, "True" },
1498 { "-xmono", "monoMode", XrmoptionNoArg, "False" },
1499 { "-debugMode", "debugMode", XrmoptionSepArg, NULL },
1500 { "-debug", "debugMode", XrmoptionNoArg, "True" },
1501 { "-xdebug", "debugMode", XrmoptionNoArg, "False" },
1502 { "-clockMode", "clockMode", XrmoptionSepArg, NULL },
1503 { "-clock", "clockMode", XrmoptionNoArg, "True" },
1504 { "-xclock", "clockMode", XrmoptionNoArg, "False" },
1505 { "-boardSize", "boardSize", XrmoptionSepArg, NULL },
1506 { "-size", "boardSize", XrmoptionSepArg, NULL },
1507 { "-searchTime", "searchTime", XrmoptionSepArg, NULL },
1508 { "-st", "searchTime", XrmoptionSepArg, NULL },
1509 { "-searchDepth", "searchDepth", XrmoptionSepArg, NULL },
1510 { "-depth", "searchDepth", XrmoptionSepArg, NULL },
1511 { "-showCoords", "showCoords", XrmoptionSepArg, NULL },
1512 { "-coords", "showCoords", XrmoptionNoArg, "True" },
1513 { "-xcoords", "showCoords", XrmoptionNoArg, "False" },
1515 { "-showJail", "showJail", XrmoptionSepArg, NULL },
1516 { "-jail", "showJail", XrmoptionNoArg, "1" },
1517 { "-sidejail", "showJail", XrmoptionNoArg, "2" },
1518 { "-xjail", "showJail", XrmoptionNoArg, "0" },
1520 { "-showThinking", "showThinking", XrmoptionSepArg, NULL },
1521 { "-thinking", "showThinking", XrmoptionNoArg, "True" },
1522 { "-xthinking", "showThinking", XrmoptionNoArg, "False" },
1523 { "-ponderNextMove", "ponderNextMove", XrmoptionSepArg, NULL },
1524 { "-ponder", "ponderNextMove", XrmoptionNoArg, "True" },
1525 { "-xponder", "ponderNextMove", XrmoptionNoArg, "False" },
1526 { "-periodicUpdates", "periodicUpdates", XrmoptionSepArg, NULL },
1527 { "-periodic", "periodicUpdates", XrmoptionNoArg, "True" },
1528 { "-xperiodic", "periodicUpdates", XrmoptionNoArg, "False" },
1529 { "-clockFont", "clockFont", XrmoptionSepArg, NULL },
1530 { "-coordFont", "coordFont", XrmoptionSepArg, NULL },
1531 { "-font", "font", XrmoptionSepArg, NULL },
1532 { "-ringBellAfterMoves", "ringBellAfterMoves", XrmoptionSepArg, NULL },
1533 { "-bell", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1534 { "-xbell", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1535 { "-movesound", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1536 { "-xmovesound", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1537 { "-autoCallFlag", "autoCallFlag", XrmoptionSepArg, NULL },
1538 { "-autoflag", "autoCallFlag", XrmoptionNoArg, "True" },
1539 { "-xautoflag", "autoCallFlag", XrmoptionNoArg, "False" },
1540 { "-autoFlipView", "autoFlipView", XrmoptionSepArg, NULL },
1541 { "-autoflip", "autoFlipView", XrmoptionNoArg, "True" },
1542 { "-xautoflip", "autoFlipView", XrmoptionNoArg, "False" },
1543 { "-autoObserve", "autoObserve", XrmoptionSepArg, NULL },
1544 { "-autobs", "autoObserve", XrmoptionNoArg, "True" },
1545 { "-xautobs", "autoObserve", XrmoptionNoArg, "False" },
1546 { "-autoComment", "autoComment", XrmoptionSepArg, NULL },
1547 { "-autocomm", "autoComment", XrmoptionNoArg, "True" },
1548 { "-xautocomm", "autoComment", XrmoptionNoArg, "False" },
1549 { "-getMoveList", "getMoveList", XrmoptionSepArg, NULL },
1550 { "-moves", "getMoveList", XrmoptionNoArg, "True" },
1551 { "-xmoves", "getMoveList", XrmoptionNoArg, "False" },
1553 { "-highlightDragging", "highlightDragging", XrmoptionSepArg, NULL },
1554 { "-highdrag", "highlightDragging", XrmoptionNoArg, "True" },
1555 { "-xhighdrag", "highlightDragging", XrmoptionNoArg, "False" },
1557 { "-highlightLastMove", "highlightLastMove", XrmoptionSepArg, NULL },
1558 { "-highlight", "highlightLastMove", XrmoptionNoArg, "True" },
1559 { "-xhighlight", "highlightLastMove", XrmoptionNoArg, "False" },
1560 { "-premove", "premove", XrmoptionSepArg, NULL },
1561 { "-pre", "premove", XrmoptionNoArg, "True" },
1562 { "-xpre", "premove", XrmoptionNoArg, "False" },
1563 { "-testLegality", "testLegality", XrmoptionSepArg, NULL },
1564 { "-legal", "testLegality", XrmoptionNoArg, "True" },
1565 { "-xlegal", "testLegality", XrmoptionNoArg, "False" },
1566 { "-flipView", "flipView", XrmoptionSepArg, NULL },
1567 { "-flip", "flipView", XrmoptionNoArg, "True" },
1568 { "-xflip", "flipView", XrmoptionNoArg, "False" },
1569 { "-cmail", "cmailGameName", XrmoptionSepArg, NULL },
1570 { "-alwaysPromoteToQueen", "alwaysPromoteToQueen",
1571 XrmoptionSepArg, NULL },
1572 { "-queen", "alwaysPromoteToQueen", XrmoptionNoArg, "True" },
1573 { "-xqueen", "alwaysPromoteToQueen", XrmoptionNoArg, "False" },
1574 { "-oldSaveStyle", "oldSaveStyle", XrmoptionSepArg, NULL },
1575 { "-oldsave", "oldSaveStyle", XrmoptionNoArg, "True" },
1576 { "-xoldsave", "oldSaveStyle", XrmoptionNoArg, "False" },
1577 { "-quietPlay", "quietPlay", XrmoptionSepArg, NULL },
1578 { "-quiet", "quietPlay", XrmoptionNoArg, "True" },
1579 { "-xquiet", "quietPlay", XrmoptionNoArg, "False" },
1580 { "-titleInWindow", "titleInWindow", XrmoptionSepArg, NULL },
1581 { "-title", "titleInWindow", XrmoptionNoArg, "True" },
1582 { "-xtitle", "titleInWindow", XrmoptionNoArg, "False" },
1584 { "-zippyTalk", "zippyTalk", XrmoptionSepArg, NULL },
1585 { "-zt", "zippyTalk", XrmoptionNoArg, "True" },
1586 { "-xzt", "zippyTalk", XrmoptionNoArg, "False" },
1587 { "-zippyPlay", "zippyPlay", XrmoptionSepArg, NULL },
1588 { "-zp", "zippyPlay", XrmoptionNoArg, "True" },
1589 { "-xzp", "zippyPlay", XrmoptionNoArg, "False" },
1590 { "-zippyLines", "zippyLines", XrmoptionSepArg, NULL },
1591 { "-zippyPinhead", "zippyPinhead", XrmoptionSepArg, NULL },
1592 { "-zippyPassword", "zippyPassword", XrmoptionSepArg, NULL },
1593 { "-zippyPassword2", "zippyPassword2", XrmoptionSepArg, NULL },
1594 { "-zippyWrongPassword", "zippyWrongPassword", XrmoptionSepArg, NULL },
1595 { "-zippyAcceptOnly", "zippyAcceptOnly", XrmoptionSepArg, NULL },
1596 { "-zippyUseI", "zippyUseI", XrmoptionSepArg, NULL },
1597 { "-zui", "zippyUseI", XrmoptionNoArg, "True" },
1598 { "-xzui", "zippyUseI", XrmoptionNoArg, "False" },
1599 { "-zippyBughouse", "zippyBughouse", XrmoptionSepArg, NULL },
1600 { "-zippyNoplayCrafty", "zippyNoplayCrafty", XrmoptionSepArg, NULL },
1601 { "-znc", "zippyNoplayCrafty", XrmoptionNoArg, "True" },
1602 { "-xznc", "zippyNoplayCrafty", XrmoptionNoArg, "False" },
1603 { "-zippyGameEnd", "zippyGameEnd", XrmoptionSepArg, NULL },
1604 { "-zippyGameStart", "zippyGameStart", XrmoptionSepArg, NULL },
1605 { "-zippyAdjourn", "zippyAdjourn", XrmoptionSepArg, NULL },
1606 { "-zadj", "zippyAdjourn", XrmoptionNoArg, "True" },
1607 { "-xzadj", "zippyAdjourn", XrmoptionNoArg, "False" },
1608 { "-zippyAbort", "zippyAbort", XrmoptionSepArg, NULL },
1609 { "-zab", "zippyAbort", XrmoptionNoArg, "True" },
1610 { "-xzab", "zippyAbort", XrmoptionNoArg, "False" },
1611 { "-zippyVariants", "zippyVariants", XrmoptionSepArg, NULL },
1612 { "-zippyMaxGames", "zippyMaxGames", XrmoptionSepArg, NULL },
1613 { "-zippyReplayTimeout", "zippyReplayTimeout", XrmoptionSepArg, NULL },
1614 { "-zippyShortGame", "zippyShortGame", XrmoptionSepArg, NULL },
1616 { "-flashCount", "flashCount", XrmoptionSepArg, NULL },
1617 { "-flash", "flashCount", XrmoptionNoArg, "3" },
1618 { "-xflash", "flashCount", XrmoptionNoArg, "0" },
1619 { "-flashRate", "flashRate", XrmoptionSepArg, NULL },
1620 { "-pixmapDirectory", "pixmapDirectory", XrmoptionSepArg, NULL },
1621 { "-msLoginDelay", "msLoginDelay", XrmoptionSepArg, NULL },
1622 { "-pixmap", "pixmapDirectory", XrmoptionSepArg, NULL },
1623 { "-colorizeMessages", "colorizeMessages", XrmoptionSepArg, NULL },
1624 { "-colorize", "colorizeMessages", XrmoptionNoArg, "True" },
1625 { "-xcolorize", "colorizeMessages", XrmoptionNoArg, "False" },
1626 { "-colorShout", "colorShout", XrmoptionSepArg, NULL },
1627 { "-colorSShout", "colorSShout", XrmoptionSepArg, NULL },
1628 { "-colorCShout", "colorSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1629 { "-colorChannel1", "colorChannel1", XrmoptionSepArg, NULL },
1630 { "-colorChannel", "colorChannel", XrmoptionSepArg, NULL },
1631 { "-colorKibitz", "colorKibitz", XrmoptionSepArg, NULL },
1632 { "-colorTell", "colorTell", XrmoptionSepArg, NULL },
1633 { "-colorChallenge", "colorChallenge", XrmoptionSepArg, NULL },
1634 { "-colorRequest", "colorRequest", XrmoptionSepArg, NULL },
1635 { "-colorSeek", "colorSeek", XrmoptionSepArg, NULL },
1636 { "-colorNormal", "colorNormal", XrmoptionSepArg, NULL },
1637 { "-soundProgram", "soundProgram", XrmoptionSepArg, NULL },
1638 { "-soundShout", "soundShout", XrmoptionSepArg, NULL },
1639 { "-soundSShout", "soundSShout", XrmoptionSepArg, NULL },
1640 { "-soundCShout", "soundSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1641 { "-soundChannel1", "soundChannel1", XrmoptionSepArg, NULL },
1642 { "-soundChannel", "soundChannel", XrmoptionSepArg, NULL },
1643 { "-soundKibitz", "soundKibitz", XrmoptionSepArg, NULL },
1644 { "-soundTell", "soundTell", XrmoptionSepArg, NULL },
1645 { "-soundChallenge", "soundChallenge", XrmoptionSepArg, NULL },
1646 { "-soundRequest", "soundRequest", XrmoptionSepArg, NULL },
1647 { "-soundSeek", "soundSeek", XrmoptionSepArg, NULL },
1648 { "-soundMove", "soundMove", XrmoptionSepArg, NULL },
1649 { "-soundIcsWin", "soundIcsWin", XrmoptionSepArg, NULL },
1650 { "-soundIcsLoss", "soundIcsLoss", XrmoptionSepArg, NULL },
1651 { "-soundIcsDraw", "soundIcsDraw", XrmoptionSepArg, NULL },
1652 { "-soundIcsUnfinished", "soundIcsUnfinished", XrmoptionSepArg, NULL },
1653 { "-soundIcsAlarm", "soundIcsAlarm", XrmoptionSepArg, NULL },
1654 { "-reuseFirst", "reuseFirst", XrmoptionSepArg, NULL },
1655 { "-reuseChessPrograms", "reuseFirst", XrmoptionSepArg, NULL }, /*compat*/
1656 { "-reuse", "reuseFirst", XrmoptionNoArg, "True" },
1657 { "-xreuse", "reuseFirst", XrmoptionNoArg, "False" },
1658 { "-reuseSecond", "reuseSecond", XrmoptionSepArg, NULL },
1659 { "-reuse2", "reuseSecond", XrmoptionNoArg, "True" },
1660 { "-xreuse2", "reuseSecond", XrmoptionNoArg, "False" },
1661 { "-animateMoving", "animateMoving", XrmoptionSepArg, NULL },
1662 { "-animate", "animateMoving", XrmoptionNoArg, "True" },
1663 { "-xanimate", "animateMoving", XrmoptionNoArg, "False" },
1664 { "-animateDragging", "animateDragging", XrmoptionSepArg, NULL },
1665 { "-drag", "animateDragging", XrmoptionNoArg, "True" },
1666 { "-xdrag", "animateDragging", XrmoptionNoArg, "False" },
1667 { "-animateSpeed", "animateSpeed", XrmoptionSepArg, NULL },
1668 { "-popupExitMessage", "popupExitMessage", XrmoptionSepArg, NULL },
1669 { "-exit", "popupExitMessage", XrmoptionNoArg, "True" },
1670 { "-xexit", "popupExitMessage", XrmoptionNoArg, "False" },
1671 { "-popupMoveErrors", "popupMoveErrors", XrmoptionSepArg, NULL },
1672 { "-popup", "popupMoveErrors", XrmoptionNoArg, "True" },
1673 { "-xpopup", "popupMoveErrors", XrmoptionNoArg, "False" },
1674 { "-fontSizeTolerance", "fontSizeTolerance", XrmoptionSepArg, NULL },
1675 { "-initialMode", "initialMode", XrmoptionSepArg, NULL },
1676 { "-mode", "initialMode", XrmoptionSepArg, NULL },
1677 { "-variant", "variant", XrmoptionSepArg, NULL },
1678 { "-firstProtocolVersion", "firstProtocolVersion", XrmoptionSepArg, NULL },
1679 { "-secondProtocolVersion","secondProtocolVersion",XrmoptionSepArg, NULL },
1680 { "-showButtonBar", "showButtonBar", XrmoptionSepArg, NULL },
1681 { "-buttons", "showButtonBar", XrmoptionNoArg, "True" },
1682 { "-xbuttons", "showButtonBar", XrmoptionNoArg, "False" },
1683 { "-lowTimeWarningColor", "lowTimeWarningColor", XrmoptionSepArg, NULL },
1684 { "-lowTimeWarning", "lowTimeWarning", XrmoptionSepArg, NULL },
1685 /* [AS,HR] New features */
1686 { "-firstScoreAbs", "firstScoreAbs", XrmoptionSepArg, NULL },
1687 { "-secondScoreAbs", "secondScoreAbs", XrmoptionSepArg, NULL },
1688 { "-pgnExtendedInfo", "pgnExtendedInfo", XrmoptionSepArg, NULL },
1689 { "-hideThinkingFromHuman", "hideThinkingFromHuman", XrmoptionSepArg, NULL },
1690 { "-adjudicateLossThreshold", "adjudicateLossThreshold", XrmoptionSepArg, NULL },
1691 { "-pgnEventHeader", "pgnEventHeader", XrmoptionSepArg, NULL },
1692 { "-firstIsUCI", "firstIsUCI", XrmoptionSepArg, NULL },
1693 { "-secondIsUCI", "secondIsUCI", XrmoptionSepArg, NULL },
1694 { "-fUCI", "firstIsUCI", XrmoptionNoArg, "True" },
1695 { "-sUCI", "secondIsUCI", XrmoptionNoArg, "True" },
1696 { "-firstHasOwnBookUCI", "firstHasOwnBookUCI", XrmoptionSepArg, NULL },
1697 { "-secondHasOwnBookUCI", "secondHasOwnBookUCI", XrmoptionSepArg, NULL },
1698 { "-fNoOwnBookUCI", "firstHasOwnBookUCI", XrmoptionNoArg, "False" },
1699 { "-sNoOwnBookUCI", "secondHasOwnBookUCI", XrmoptionNoArg, "False" },
1700 { "-firstXBook", "firstHasOwnBookUCI", XrmoptionNoArg, "False" },
1701 { "-secondXBook", "secondHasOwnBookUCI", XrmoptionNoArg, "False" },
1702 { "-polyglotDir", "polyglotDir", XrmoptionSepArg, NULL },
1703 { "-usePolyglotBook", "usePolyglotBook", XrmoptionSepArg, NULL },
1704 { "-polyglotBook", "polyglotBook", XrmoptionSepArg, NULL },
1705 { "-defaultHashSize", "defaultHashSize", XrmoptionSepArg, NULL },
1706 { "-defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XrmoptionSepArg, NULL },
1707 { "-defaultPathEGTB", "defaultPathEGTB", XrmoptionSepArg, NULL },
1708 { "-defaultFrcPosition", "defaultFrcPosition", XrmoptionSepArg, NULL },
1709 { "-gameListTags", "gameListTags", XrmoptionSepArg, NULL },
1710 // [HGM] I am sure AS added many more options, but we have to fish them out, from the list in winboard.c
1712 /* [HGM,HR] User-selectable board size */
1713 { "-boardWidth", "boardWidth", XrmoptionSepArg, NULL },
1714 { "-boardHeight", "boardHeight", XrmoptionSepArg, NULL },
1715 { "-matchPause", "matchPause", XrmoptionSepArg, NULL },
1717 /* [HGM] new arguments of 4.3.xx. All except first three are back-end options, which should work immediately */
1718 { "-holdingsSize", "holdingsSize", XrmoptionSepArg, NULL }, // requires extensive front-end changes to work
1719 { "-flipBlack", "flipBlack", XrmoptionSepArg, NULL }, // requires front-end changes to work
1720 { "-allWhite", "allWhite", XrmoptionSepArg, NULL }, // requires front-end changes to work
1721 { "-pieceToCharTable", "pieceToCharTable", XrmoptionSepArg, NULL },
1722 { "-alphaRank", "alphaRank", XrmoptionSepArg, NULL },
1723 { "-testClaims", "testClaims", XrmoptionSepArg, NULL },
1724 { "-checkMates", "checkMates", XrmoptionSepArg, NULL },
1725 { "-materialDraws", "materialDraws", XrmoptionSepArg, NULL },
1726 { "-trivialDraws", "trivialDraws", XrmoptionSepArg, NULL },
1727 { "-ruleMoves", "ruleMoves", XrmoptionSepArg, NULL },
1728 { "-repeatsToDraw", "repeatsToDraw", XrmoptionSepArg, NULL },
1729 { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL },
1730 { "-userName", "userName", XrmoptionSepArg, NULL },
1731 { "-autoKibitz", "autoKibitz", XrmoptionNoArg, "True" },
1732 { "-firstTimeOdds", "firstTimeOdds", XrmoptionSepArg, NULL },
1733 { "-secondTimeOdds", "secondTimeOdds", XrmoptionSepArg, NULL },
1734 { "-timeOddsMode", "timeOddsMode", XrmoptionSepArg, NULL },
1735 { "-firstAccumulateTC", "firstAccumulateTC", XrmoptionSepArg, NULL },
1736 { "-secondAccumulateTC", "secondAccumulateTC", XrmoptionSepArg, NULL },
1737 { "-firstNPS", "firstNPS", XrmoptionSepArg, NULL },
1738 { "-secondNPS", "secondNPS", XrmoptionSepArg, NULL },
1739 { "-serverMoves", "serverMoves", XrmoptionSepArg, NULL },
1740 { "-serverPause", "serverPause", XrmoptionSepArg, NULL },
1741 { "-suppressLoadMoves", "suppressLoadMoves", XrmoptionSepArg, NULL },
1742 { "-egtFormats", "egtFormats", XrmoptionSepArg, NULL },
1743 { "-userName", "userName", XrmoptionSepArg, NULL },
1744 { "-smpCores", "smpCores", XrmoptionSepArg, NULL },
1745 { "-sameColorGames", "sameColorGames", XrmoptionSepArg, NULL },
1746 { "-rewindIndex", "rewindIndex", XrmoptionSepArg, NULL },
1747 { "-niceEngines", "niceEngines", XrmoptionSepArg, NULL },
1748 { "-delayBeforeQuit", "delayBeforeQuit", XrmoptionSepArg, NULL },
1749 { "-delayAfterQuit", "delayAfterQuit", XrmoptionSepArg, NULL },
1750 { "-nameOfDebugFile", "nameOfDebugFile", XrmoptionSepArg, NULL },
1751 { "-debugFile", "nameOfDebugFile", XrmoptionSepArg, NULL },
1752 { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL },
1753 { "-noGUI", "noGUI", XrmoptionNoArg, "True" },
1754 { "-firstOptions", "firstOptions", XrmoptionSepArg, NULL },
1755 { "-secondOptions", "secondOptions", XrmoptionSepArg, NULL },
1756 { "-firstNeedsNoncompliantFEN", "firstNeedsNoncompliantFEN", XrmoptionSepArg, NULL },
1757 { "-secondNeedsNoncompliantFEN", "secondNeedsNoncompliantFEN", XrmoptionSepArg, NULL },
1761 XtActionsRec boardActions[] = {
1762 { "DrawPosition", DrawPositionProc },
1763 { "HandleUserMove", HandleUserMove },
1764 { "AnimateUserMove", AnimateUserMove },
1765 { "FileNameAction", FileNameAction },
1766 { "AskQuestionProc", AskQuestionProc },
1767 { "AskQuestionReplyAction", AskQuestionReplyAction },
1768 { "PieceMenuPopup", PieceMenuPopup },
1769 { "WhiteClock", WhiteClock },
1770 { "BlackClock", BlackClock },
1771 { "Iconify", Iconify },
1772 { "ResetProc", ResetProc },
1773 { "LoadGameProc", LoadGameProc },
1774 { "LoadNextGameProc", LoadNextGameProc },
1775 { "LoadPrevGameProc", LoadPrevGameProc },
1776 { "LoadSelectedProc", LoadSelectedProc },
1777 { "ReloadGameProc", ReloadGameProc },
1778 { "LoadPositionProc", LoadPositionProc },
1779 { "LoadNextPositionProc", LoadNextPositionProc },
1780 { "LoadPrevPositionProc", LoadPrevPositionProc },
1781 { "ReloadPositionProc", ReloadPositionProc },
1782 { "CopyPositionProc", CopyPositionProc },
1783 { "PastePositionProc", PastePositionProc },
1784 { "CopyGameProc", CopyGameProc },
1785 { "PasteGameProc", PasteGameProc },
1786 { "SaveGameProc", SaveGameProc },
1787 { "SavePositionProc", SavePositionProc },
1788 { "MailMoveProc", MailMoveProc },
1789 { "ReloadCmailMsgProc", ReloadCmailMsgProc },
1790 { "QuitProc", QuitProc },
1791 { "MachineWhiteProc", MachineWhiteProc },
1792 { "MachineBlackProc", MachineBlackProc },
1793 { "AnalysisModeProc", AnalyzeModeProc },
1794 { "AnalyzeFileProc", AnalyzeFileProc },
1795 { "TwoMachinesProc", TwoMachinesProc },
1796 { "IcsClientProc", IcsClientProc },
1797 { "EditGameProc", EditGameProc },
1798 { "EditPositionProc", EditPositionProc },
1799 { "TrainingProc", EditPositionProc },
1800 { "EngineOutputProc", EngineOutputProc}, // [HGM] Winboard_x engine-output window
1801 { "ShowGameListProc", ShowGameListProc },
1802 { "ShowMoveListProc", HistoryShowProc},
1803 { "EditTagsProc", EditCommentProc },
1804 { "EditCommentProc", EditCommentProc },
1805 { "IcsAlarmProc", IcsAlarmProc },
1806 { "IcsInputBoxProc", IcsInputBoxProc },
1807 { "PauseProc", PauseProc },
1808 { "AcceptProc", AcceptProc },
1809 { "DeclineProc", DeclineProc },
1810 { "RematchProc", RematchProc },
1811 { "CallFlagProc", CallFlagProc },
1812 { "DrawProc", DrawProc },
1813 { "AdjournProc", AdjournProc },
1814 { "AbortProc", AbortProc },
1815 { "ResignProc", ResignProc },
1816 { "AdjuWhiteProc", AdjuWhiteProc },
1817 { "AdjuBlackProc", AdjuBlackProc },
1818 { "AdjuDrawProc", AdjuDrawProc },
1819 { "EnterKeyProc", EnterKeyProc },
1820 { "StopObservingProc", StopObservingProc },
1821 { "StopExaminingProc", StopExaminingProc },
1822 { "BackwardProc", BackwardProc },
1823 { "ForwardProc", ForwardProc },
1824 { "ToStartProc", ToStartProc },
1825 { "ToEndProc", ToEndProc },
1826 { "RevertProc", RevertProc },
1827 { "TruncateGameProc", TruncateGameProc },
1828 { "MoveNowProc", MoveNowProc },
1829 { "RetractMoveProc", RetractMoveProc },
1830 { "AlwaysQueenProc", AlwaysQueenProc },
1831 { "AnimateDraggingProc", AnimateDraggingProc },
1832 { "AnimateMovingProc", AnimateMovingProc },
1833 { "AutoflagProc", AutoflagProc },
1834 { "AutoflipProc", AutoflipProc },
1835 { "AutobsProc", AutobsProc },
1836 { "AutoraiseProc", AutoraiseProc },
1837 { "AutosaveProc", AutosaveProc },
1838 { "BlindfoldProc", BlindfoldProc },
1839 { "FlashMovesProc", FlashMovesProc },
1840 { "FlipViewProc", FlipViewProc },
1841 { "GetMoveListProc", GetMoveListProc },
1843 { "HighlightDraggingProc", HighlightDraggingProc },
1845 { "HighlightLastMoveProc", HighlightLastMoveProc },
1846 { "IcsAlarmProc", IcsAlarmProc },
1847 { "MoveSoundProc", MoveSoundProc },
1848 { "OldSaveStyleProc", OldSaveStyleProc },
1849 { "PeriodicUpdatesProc", PeriodicUpdatesProc },
1850 { "PonderNextMoveProc", PonderNextMoveProc },
1851 { "PopupExitMessageProc", PopupExitMessageProc },
1852 { "PopupMoveErrorsProc", PopupMoveErrorsProc },
1853 { "PremoveProc", PremoveProc },
1854 { "QuietPlayProc", QuietPlayProc },
1855 { "ShowCoordsProc", ShowCoordsProc },
1856 { "ShowThinkingProc", ShowThinkingProc },
1857 { "HideThinkingProc", HideThinkingProc },
1858 { "TestLegalityProc", TestLegalityProc },
1859 { "InfoProc", InfoProc },
1860 { "ManProc", ManProc },
1861 { "HintProc", HintProc },
1862 { "BookProc", BookProc },
1863 { "AboutGameProc", AboutGameProc },
1864 { "AboutProc", AboutProc },
1865 { "DebugProc", DebugProc },
1866 { "NothingProc", NothingProc },
1867 { "CommentPopDown", (XtActionProc) CommentPopDown },
1868 { "EditCommentPopDown", (XtActionProc) EditCommentPopDown },
1869 { "TagsPopDown", (XtActionProc) TagsPopDown },
1870 { "ErrorPopDown", (XtActionProc) ErrorPopDown },
1871 { "ICSInputBoxPopDown", (XtActionProc) ICSInputBoxPopDown },
1872 { "AnalysisPopDown", (XtActionProc) AnalysisPopDown },
1873 { "FileNamePopDown", (XtActionProc) FileNamePopDown },
1874 { "AskQuestionPopDown", (XtActionProc) AskQuestionPopDown },
1875 { "GameListPopDown", (XtActionProc) GameListPopDown },
1876 { "PromotionPopDown", (XtActionProc) PromotionPopDown },
1877 { "HistoryPopDown", (XtActionProc) HistoryPopDown },
1878 { "EngineOutputPopDown", (XtActionProc) EngineOutputPopDown },
1879 { "ShufflePopDown", (XtActionProc) ShufflePopDown },
1880 { "EnginePopDown", (XtActionProc) EnginePopDown },
1881 { "UciPopDown", (XtActionProc) UciPopDown },
1882 { "TimeControlPopDown", (XtActionProc) TimeControlPopDown },
1883 { "NewVariantPopDown", (XtActionProc) NewVariantPopDown },
1884 { "SettingsPopDown", (XtActionProc) SettingsPopDown },
1887 char globalTranslations[] =
1888 ":<Key>R: ResignProc() \n \
1889 :<Key>r: ResetProc() \n \
1890 :<Key>g: LoadGameProc() \n \
1891 :<Key>N: LoadNextGameProc() \n \
1892 :<Key>P: LoadPrevGameProc() \n \
1893 :<Key>Q: QuitProc() \n \
1894 :<Key>F: ToEndProc() \n \
1895 :<Key>f: ForwardProc() \n \
1896 :<Key>B: ToStartProc() \n \
1897 :<Key>b: BackwardProc() \n \
1898 :<Key>p: PauseProc() \n \
1899 :<Key>d: DrawProc() \n \
1900 :<Key>t: CallFlagProc() \n \
1901 :<Key>i: Iconify() \n \
1902 :<Key>c: Iconify() \n \
1903 :<Key>v: FlipViewProc() \n \
1904 <KeyDown>Control_L: BackwardProc() \n \
1905 <KeyUp>Control_L: ForwardProc() \n \
1906 <KeyDown>Control_R: BackwardProc() \n \
1907 <KeyUp>Control_R: ForwardProc() \n \
1908 Shift<Key>1: AskQuestionProc(\"Direct command\",\
1909 \"Send to chess program:\",,1) \n \
1910 Shift<Key>2: AskQuestionProc(\"Direct command\",\
1911 \"Send to second chess program:\",,2) \n";
1913 char boardTranslations[] =
1914 "<Btn1Down>: HandleUserMove() \n \
1915 <Btn1Up>: HandleUserMove() \n \
1916 <Btn1Motion>: AnimateUserMove() \n \
1917 Shift<Btn2Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD)\
1918 PieceMenuPopup(menuB) \n \
1919 Any<Btn2Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD) \
1920 PieceMenuPopup(menuW) \n \
1921 Shift<Btn3Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD)\
1922 PieceMenuPopup(menuW) \n \
1923 Any<Btn3Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD) \
1924 PieceMenuPopup(menuB) \n";
1926 char whiteTranslations[] = "<BtnDown>: WhiteClock()\n";
1927 char blackTranslations[] = "<BtnDown>: BlackClock()\n";
1929 char ICSInputTranslations[] =
1930 "<Key>Return: EnterKeyProc() \n";
1932 String xboardResources[] = {
1933 "*fileName*value.translations: #override\\n <Key>Return: FileNameAction()",
1934 "*question*value.translations: #override\\n <Key>Return: AskQuestionReplyAction()",
1935 "*errorpopup*translations: #override\\n <Key>Return: ErrorPopDown()",
1940 /* Max possible square size */
1941 #define MAXSQSIZE 256
1943 static int xpm_avail[MAXSQSIZE];
1945 #ifdef HAVE_DIR_STRUCT
1947 /* Extract piece size from filename */
1949 xpm_getsize(name, len, ext)
1960 if ((p=strchr(name, '.')) == NULL ||
1961 StrCaseCmp(p+1, ext) != 0)
1967 while (*p && isdigit(*p))
1974 /* Setup xpm_avail */
1976 xpm_getavail(dirname, ext)
1984 for (i=0; i<MAXSQSIZE; ++i)
1987 if (appData.debugMode)
1988 fprintf(stderr, "XPM dir:%s:ext:%s:\n", dirname, ext);
1990 dir = opendir(dirname);
1993 fprintf(stderr, _("%s: Can't access XPM directory %s\n"),
1994 programName, dirname);
1998 while ((ent=readdir(dir)) != NULL) {
1999 i = xpm_getsize(ent->d_name, NAMLEN(ent), ext);
2000 if (i > 0 && i < MAXSQSIZE)
2010 xpm_print_avail(fp, ext)
2016 fprintf(fp, _("Available `%s' sizes:\n"), ext);
2017 for (i=1; i<MAXSQSIZE; ++i) {
2023 /* Return XPM piecesize closest to size */
2025 xpm_closest_to(dirname, size, ext)
2031 int sm_diff = MAXSQSIZE;
2035 xpm_getavail(dirname, ext);
2037 if (appData.debugMode)
2038 xpm_print_avail(stderr, ext);
2040 for (i=1; i<MAXSQSIZE; ++i) {
2043 diff = (diff<0) ? -diff : diff;
2044 if (diff < sm_diff) {
2052 fprintf(stderr, _("Error: No `%s' files!\n"), ext);
2058 #else /* !HAVE_DIR_STRUCT */
2059 /* If we are on a system without a DIR struct, we can't
2060 read the directory, so we can't collect a list of
2061 filenames, etc., so we can't do any size-fitting. */
2063 xpm_closest_to(dirname, size, ext)
2068 fprintf(stderr, _("\
2069 Warning: No DIR structure found on this system --\n\
2070 Unable to autosize for XPM/XIM pieces.\n\
2071 Please report this error to frankm@hiwaay.net.\n\
2072 Include system type & operating system in message.\n"));
2075 #endif /* HAVE_DIR_STRUCT */
2077 static char *cnames[9] = { "black", "red", "green", "yellow", "blue",
2078 "magenta", "cyan", "white" };
2082 TextColors textColors[(int)NColorClasses];
2084 /* String is: "fg, bg, attr". Which is 0, 1, 2 */
2086 parse_color(str, which)
2090 char *p, buf[100], *d;
2093 if (strlen(str) > 99) /* watch bounds on buf */
2098 for (i=0; i<which; ++i) {
2105 /* Could be looking at something like:
2107 .. in which case we want to stop on a comma also */
2108 while (*p && *p != ',' && !isalpha(*p) && !isdigit(*p))
2112 return -1; /* Use default for empty field */
2115 if (which == 2 || isdigit(*p))
2118 while (*p && isalpha(*p))
2123 for (i=0; i<8; ++i) {
2124 if (!StrCaseCmp(buf, cnames[i]))
2125 return which? (i+40) : (i+30);
2127 if (!StrCaseCmp(buf, "default")) return -1;
2129 fprintf(stderr, _("%s: unrecognized color %s\n"), programName, buf);
2134 parse_cpair(cc, str)
2138 if ((textColors[(int)cc].fg=parse_color(str, 0)) == -2) {
2139 fprintf(stderr, _("%s: can't parse foreground color in `%s'\n"),
2144 /* bg and attr are optional */
2145 textColors[(int)cc].bg = parse_color(str, 1);
2146 if ((textColors[(int)cc].attr = parse_color(str, 2)) < 0) {
2147 textColors[(int)cc].attr = 0;
2153 /* Arrange to catch delete-window events */
2154 Atom wm_delete_window;
2156 CatchDeleteWindow(Widget w, String procname)
2159 XSetWMProtocols(xDisplay, XtWindow(w), &wm_delete_window, 1);
2160 snprintf(buf, sizeof(buf), "<Message>WM_PROTOCOLS: %s() \n", procname);
2161 XtAugmentTranslations(w, XtParseTranslationTable(buf));
2168 XtSetArg(args[0], XtNiconic, False);
2169 XtSetValues(shellWidget, args, 1);
2171 XtPopup(shellWidget, XtGrabNone); /* Raise if lowered */
2175 // eventually, all layout determining code should go into a subroutine, but until then IDSIZE remains undefined
2177 #define BoardSize int
2178 void InitDrawingSizes(BoardSize boardSize, int flags)
2179 { // [HGM] resize is functional now, but for board format changes only (nr of ranks, files)
2180 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
2182 XtGeometryResult gres;
2185 if(!formWidget) return;
2188 * Enable shell resizing.
2190 shellArgs[0].value = (XtArgVal) &w;
2191 shellArgs[1].value = (XtArgVal) &h;
2192 XtGetValues(shellWidget, shellArgs, 2);
2194 shellArgs[4].value = 2*w; shellArgs[2].value = 10;
2195 shellArgs[5].value = 2*h; shellArgs[3].value = 10;
2196 XtSetValues(shellWidget, &shellArgs[2], 4);
2198 XtSetArg(args[0], XtNdefaultDistance, &sep);
2199 XtGetValues(formWidget, args, 1);
2201 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2202 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2205 XtSetArg(args[0], XtNwidth, boardWidth);
2206 XtSetArg(args[1], XtNheight, boardHeight);
2207 XtSetValues(boardWidget, args, 2);
2209 timerWidth = (boardWidth - sep) / 2;
2210 XtSetArg(args[0], XtNwidth, timerWidth);
2211 XtSetValues(whiteTimerWidget, args, 1);
2212 XtSetValues(blackTimerWidget, args, 1);
2214 XawFormDoLayout(formWidget, False);
2216 if (appData.titleInWindow) {
2218 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2219 XtSetArg(args[i], XtNheight, &h); i++;
2220 XtGetValues(titleWidget, args, i);
2222 w = boardWidth - 2*bor;
2224 XtSetArg(args[0], XtNwidth, &w);
2225 XtGetValues(menuBarWidget, args, 1);
2226 w = boardWidth - w - sep - 2*bor - 2; // WIDTH_FUDGE
2229 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
2230 if (gres != XtGeometryYes && appData.debugMode) {
2232 _("%s: titleWidget geometry error %d %d %d %d %d\n"),
2233 programName, gres, w, h, wr, hr);
2237 XawFormDoLayout(formWidget, True);
2240 * Inhibit shell resizing.
2242 shellArgs[0].value = w = (XtArgVal) boardWidth + marginW;
2243 shellArgs[1].value = h = (XtArgVal) boardHeight + marginH;
2244 shellArgs[4].value = shellArgs[2].value = w;
2245 shellArgs[5].value = shellArgs[3].value = h;
2246 XtSetValues(shellWidget, &shellArgs[0], 6);
2255 int i, j, clockFontPxlSize, coordFontPxlSize, fontPxlSize;
2256 XSetWindowAttributes window_attributes;
2258 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
2259 XrmValue vFrom, vTo;
2260 XtGeometryResult gres;
2263 int forceMono = False;
2266 // [HGM] before anything else, expand any indirection files amongst options
2267 char *argvCopy[1000]; // 1000 seems enough
2268 char newArgs[10000]; // holds actual characters
2271 srandom(time(0)); // [HGM] book: make random truly random
2274 for(i=0; i<argc; i++) {
2275 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2276 //fprintf(stderr, "arg %s\n", argv[i]);
2277 if(argv[i][0] != '@') argvCopy[j++] = argv[i]; else {
2279 FILE *f = fopen(argv[i]+1, "rb");
2280 if(f == NULL) { fprintf(stderr, _("ignore %s\n"), argv[i]); continue; } // do not expand non-existing
2281 argvCopy[j++] = newArgs + k; // get ready for first argument from file
2282 while((c = fgetc(f)) != EOF) { // each line of file inserts 1 argument in the list
2284 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2285 newArgs[k++] = 0; // terminate current arg
2286 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2287 argvCopy[j++] = newArgs + k; // get ready for next
2289 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2302 if(appData.debugMode,1) { // OK, appData is not initialized here yet...
2303 for(i=0; i<argc; i++) fprintf(stderr, "argv[%2d] = '%s'\n", i, argv[i]);
2309 setbuf(stdout, NULL);
2310 setbuf(stderr, NULL);
2313 programName = strrchr(argv[0], '/');
2314 if (programName == NULL)
2315 programName = argv[0];
2320 XtSetLanguageProc(NULL, NULL, NULL);
2321 bindtextdomain(PRODUCT, LOCALEDIR);
2322 textdomain(PRODUCT);
2326 XtAppInitialize(&appContext, "XBoard", shellOptions,
2327 XtNumber(shellOptions),
2328 &argc, argv, xboardResources, NULL, 0);
2330 fprintf(stderr, _("%s: unrecognized argument %s\n"),
2331 programName, argv[1]);
2332 fprintf(stderr, "Recognized options:\n");
2333 for(i = 0; i < XtNumber(shellOptions); i++) {
2334 j = fprintf(stderr, " %s%s", shellOptions[i].option,
2335 (shellOptions[i].argKind == XrmoptionSepArg
2337 if (i++ < XtNumber(shellOptions)) {
2338 fprintf(stderr, "%*c%s%s\n", 40 - j, ' ',
2339 shellOptions[i].option,
2340 (shellOptions[i].argKind == XrmoptionSepArg
2343 fprintf(stderr, "\n");
2349 if ((chessDir = (char *) getenv("CHESSDIR")) == NULL) {
2352 if (chdir(chessDir) != 0) {
2353 fprintf(stderr, _("%s: can't cd to CHESSDIR: "), programName);
2360 if (p == NULL) p = "/tmp";
2361 i = strlen(p) + strlen("/.xboardXXXXXx.pgn") + 1;
2362 gameCopyFilename = (char*) malloc(i);
2363 gamePasteFilename = (char*) malloc(i);
2364 snprintf(gameCopyFilename,i, "%s/.xboard%05uc.pgn", p, getpid());
2365 snprintf(gamePasteFilename,i, "%s/.xboard%05up.pgn", p, getpid());
2367 XtGetApplicationResources(shellWidget, (XtPointer) &appData,
2368 clientResources, XtNumber(clientResources),
2371 if (appData.debugMode && appData.nameOfDebugFile && strcmp(appData.nameOfDebugFile, "stderr")) {
2372 /* [DM] debug info to file [HGM] make the filename a command-line option, and allow it to remain stderr */
2373 if ((debugFP = fopen(appData.nameOfDebugFile, "w")) == NULL) {
2374 printf(_("Failed to open file '%s'\n"), appData.nameOfDebugFile);
2377 setbuf(debugFP, NULL);
2380 /* [HGM,HR] make sure board size is acceptable */
2381 if(appData.NrFiles > BOARD_SIZE ||
2382 appData.NrRanks > BOARD_SIZE )
2383 DisplayFatalError(_("Recompile with BOARD_SIZE > 12, to support this size"), 0, 2);
2386 /* This feature does not work; animation needs a rewrite */
2387 appData.highlightDragging = FALSE;
2391 xDisplay = XtDisplay(shellWidget);
2392 xScreen = DefaultScreen(xDisplay);
2393 wm_delete_window = XInternAtom(xDisplay, "WM_DELETE_WINDOW", True);
2395 gameInfo.variant = StringToVariant(appData.variant);
2396 InitPosition(FALSE);
2399 * Determine boardSize
2401 gameInfo.boardWidth = gameInfo.boardHeight = 8; // [HGM] boardsize: make sure we start as 8x8
2404 // [HGM] as long as we have not created the possibility to change size while running, start with requested size
2405 gameInfo.boardWidth = appData.NrFiles > 0 ? appData.NrFiles : 8;
2406 gameInfo.boardHeight = appData.NrRanks > 0 ? appData.NrRanks : 8;
2407 gameInfo.holdingsWidth = appData.holdingsSize > 0 ? 2 : 0;
2412 InitDrawingSizes(-1, 0); // [HGM] initsize: make this into a subroutine
2414 if (isdigit(appData.boardSize[0])) {
2415 i = sscanf(appData.boardSize, "%d,%d,%d,%d,%d,%d,%d", &squareSize,
2416 &lineGap, &clockFontPxlSize, &coordFontPxlSize,
2417 &fontPxlSize, &smallLayout, &tinyLayout);
2419 fprintf(stderr, _("%s: bad boardSize syntax %s\n"),
2420 programName, appData.boardSize);
2424 /* Find some defaults; use the nearest known size */
2425 SizeDefaults *szd, *nearest;
2426 int distance = 99999;
2427 nearest = szd = sizeDefaults;
2428 while (szd->name != NULL) {
2429 if (abs(szd->squareSize - squareSize) < distance) {
2431 distance = abs(szd->squareSize - squareSize);
2432 if (distance == 0) break;
2436 if (i < 2) lineGap = nearest->lineGap;
2437 if (i < 3) clockFontPxlSize = nearest->clockFontPxlSize;
2438 if (i < 4) coordFontPxlSize = nearest->coordFontPxlSize;
2439 if (i < 5) fontPxlSize = nearest->fontPxlSize;
2440 if (i < 6) smallLayout = nearest->smallLayout;
2441 if (i < 7) tinyLayout = nearest->tinyLayout;
2444 SizeDefaults *szd = sizeDefaults;
2445 if (*appData.boardSize == NULLCHAR) {
2446 while (DisplayWidth(xDisplay, xScreen) < szd->minScreenSize ||
2447 DisplayHeight(xDisplay, xScreen) < szd->minScreenSize) {
2450 if (szd->name == NULL) szd--;
2452 while (szd->name != NULL &&
2453 StrCaseCmp(szd->name, appData.boardSize) != 0) szd++;
2454 if (szd->name == NULL) {
2455 fprintf(stderr, _("%s: unrecognized boardSize name %s\n"),
2456 programName, appData.boardSize);
2460 squareSize = szd->squareSize;
2461 lineGap = szd->lineGap;
2462 clockFontPxlSize = szd->clockFontPxlSize;
2463 coordFontPxlSize = szd->coordFontPxlSize;
2464 fontPxlSize = szd->fontPxlSize;
2465 smallLayout = szd->smallLayout;
2466 tinyLayout = szd->tinyLayout;
2469 /* Now, using squareSize as a hint, find a good XPM/XIM set size */
2470 if (strlen(appData.pixmapDirectory) > 0) {
2471 p = ExpandPathName(appData.pixmapDirectory);
2473 fprintf(stderr, _("Error expanding path name \"%s\"\n"),
2474 appData.pixmapDirectory);
2477 if (appData.debugMode) {
2478 fprintf(stderr, _("\
2479 XBoard square size (hint): %d\n\
2480 %s fulldir:%s:\n"), squareSize, IMAGE_EXT, p);
2482 squareSize = xpm_closest_to(p, squareSize, IMAGE_EXT);
2483 if (appData.debugMode) {
2484 fprintf(stderr, _("Closest %s size: %d\n"), IMAGE_EXT, squareSize);
2488 /* [HR] height treated separately (hacked) */
2489 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2490 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2491 if (appData.showJail == 1) {
2492 /* Jail on top and bottom */
2493 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2494 XtSetArg(boardArgs[2], XtNheight,
2495 boardHeight + 2*(lineGap + squareSize));
2496 } else if (appData.showJail == 2) {
2498 XtSetArg(boardArgs[1], XtNwidth,
2499 boardWidth + 2*(lineGap + squareSize));
2500 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2503 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2504 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2508 * Determine what fonts to use.
2510 appData.clockFont = FindFont(appData.clockFont, clockFontPxlSize);
2511 clockFontID = XLoadFont(xDisplay, appData.clockFont);
2512 clockFontStruct = XQueryFont(xDisplay, clockFontID);
2513 appData.coordFont = FindFont(appData.coordFont, coordFontPxlSize);
2514 coordFontID = XLoadFont(xDisplay, appData.coordFont);
2515 coordFontStruct = XQueryFont(xDisplay, coordFontID);
2516 appData.font = FindFont(appData.font, fontPxlSize);
2517 countFontID = XLoadFont(xDisplay, appData.coordFont); // [HGM] holdings
2518 countFontStruct = XQueryFont(xDisplay, countFontID);
2519 // appData.font = FindFont(appData.font, fontPxlSize);
2521 xdb = XtDatabase(xDisplay);
2522 XrmPutStringResource(&xdb, "*font", appData.font);
2525 * Detect if there are not enough colors available and adapt.
2527 if (DefaultDepth(xDisplay, xScreen) <= 2) {
2528 appData.monoMode = True;
2531 if (!appData.monoMode) {
2532 vFrom.addr = (caddr_t) appData.lightSquareColor;
2533 vFrom.size = strlen(appData.lightSquareColor);
2534 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2535 if (vTo.addr == NULL) {
2536 appData.monoMode = True;
2539 lightSquareColor = *(Pixel *) vTo.addr;
2542 if (!appData.monoMode) {
2543 vFrom.addr = (caddr_t) appData.darkSquareColor;
2544 vFrom.size = strlen(appData.darkSquareColor);
2545 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2546 if (vTo.addr == NULL) {
2547 appData.monoMode = True;
2550 darkSquareColor = *(Pixel *) vTo.addr;
2553 if (!appData.monoMode) {
2554 vFrom.addr = (caddr_t) appData.whitePieceColor;
2555 vFrom.size = strlen(appData.whitePieceColor);
2556 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2557 if (vTo.addr == NULL) {
2558 appData.monoMode = True;
2561 whitePieceColor = *(Pixel *) vTo.addr;
2564 if (!appData.monoMode) {
2565 vFrom.addr = (caddr_t) appData.blackPieceColor;
2566 vFrom.size = strlen(appData.blackPieceColor);
2567 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2568 if (vTo.addr == NULL) {
2569 appData.monoMode = True;
2572 blackPieceColor = *(Pixel *) vTo.addr;
2576 if (!appData.monoMode) {
2577 vFrom.addr = (caddr_t) appData.highlightSquareColor;
2578 vFrom.size = strlen(appData.highlightSquareColor);
2579 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2580 if (vTo.addr == NULL) {
2581 appData.monoMode = True;
2584 highlightSquareColor = *(Pixel *) vTo.addr;
2588 if (!appData.monoMode) {
2589 vFrom.addr = (caddr_t) appData.premoveHighlightColor;
2590 vFrom.size = strlen(appData.premoveHighlightColor);
2591 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2592 if (vTo.addr == NULL) {
2593 appData.monoMode = True;
2596 premoveHighlightColor = *(Pixel *) vTo.addr;
2601 fprintf(stderr, _("%s: too few colors available; trying monochrome mode\n"),
2605 if (appData.lowTimeWarning && !appData.monoMode) {
2606 vFrom.addr = (caddr_t) appData.lowTimeWarningColor;
2607 vFrom.size = strlen(appData.lowTimeWarningColor);
2608 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2609 if (vTo.addr == NULL)
2610 appData.monoMode = True;
2612 lowTimeWarningColor = *(Pixel *) vTo.addr;
2615 if (appData.monoMode && appData.debugMode) {
2616 fprintf(stderr, _("white pixel = 0x%lx, black pixel = 0x%lx\n"),
2617 (unsigned long) XWhitePixel(xDisplay, xScreen),
2618 (unsigned long) XBlackPixel(xDisplay, xScreen));
2621 if (parse_cpair(ColorShout, appData.colorShout) < 0 ||
2622 parse_cpair(ColorSShout, appData.colorSShout) < 0 ||
2623 parse_cpair(ColorChannel1, appData.colorChannel1) < 0 ||
2624 parse_cpair(ColorChannel, appData.colorChannel) < 0 ||
2625 parse_cpair(ColorKibitz, appData.colorKibitz) < 0 ||
2626 parse_cpair(ColorTell, appData.colorTell) < 0 ||
2627 parse_cpair(ColorChallenge, appData.colorChallenge) < 0 ||
2628 parse_cpair(ColorRequest, appData.colorRequest) < 0 ||
2629 parse_cpair(ColorSeek, appData.colorSeek) < 0 ||
2630 parse_cpair(ColorNormal, appData.colorNormal) < 0)
2632 if (appData.colorize) {
2634 _("%s: can't parse color names; disabling colorization\n"),
2637 appData.colorize = FALSE;
2639 textColors[ColorNone].fg = textColors[ColorNone].bg = -1;
2640 textColors[ColorNone].attr = 0;
2642 XtAppAddActions(appContext, boardActions, XtNumber(boardActions));
2648 layoutName = "tinyLayout";
2649 } else if (smallLayout) {
2650 layoutName = "smallLayout";
2652 layoutName = "normalLayout";
2654 /* Outer layoutWidget is there only to provide a name for use in
2655 resources that depend on the layout style */
2657 XtCreateManagedWidget(layoutName, formWidgetClass, shellWidget,
2658 layoutArgs, XtNumber(layoutArgs));
2660 XtCreateManagedWidget("form", formWidgetClass, layoutWidget,
2661 formArgs, XtNumber(formArgs));
2662 XtSetArg(args[0], XtNdefaultDistance, &sep);
2663 XtGetValues(formWidget, args, 1);
2666 widgetList[j++] = menuBarWidget = CreateMenuBar(menuBar);
2667 XtSetArg(args[0], XtNtop, XtChainTop);
2668 XtSetArg(args[1], XtNbottom, XtChainTop);
2669 XtSetValues(menuBarWidget, args, 2);
2671 widgetList[j++] = whiteTimerWidget =
2672 XtCreateWidget("whiteTime", labelWidgetClass,
2673 formWidget, timerArgs, XtNumber(timerArgs));
2674 XtSetArg(args[0], XtNfont, clockFontStruct);
2675 XtSetArg(args[1], XtNtop, XtChainTop);
2676 XtSetArg(args[2], XtNbottom, XtChainTop);
2677 XtSetValues(whiteTimerWidget, args, 3);
2679 widgetList[j++] = blackTimerWidget =
2680 XtCreateWidget("blackTime", labelWidgetClass,
2681 formWidget, timerArgs, XtNumber(timerArgs));
2682 XtSetArg(args[0], XtNfont, clockFontStruct);
2683 XtSetArg(args[1], XtNtop, XtChainTop);
2684 XtSetArg(args[2], XtNbottom, XtChainTop);
2685 XtSetValues(blackTimerWidget, args, 3);
2687 if (appData.titleInWindow) {
2688 widgetList[j++] = titleWidget =
2689 XtCreateWidget("title", labelWidgetClass, formWidget,
2690 titleArgs, XtNumber(titleArgs));
2691 XtSetArg(args[0], XtNtop, XtChainTop);
2692 XtSetArg(args[1], XtNbottom, XtChainTop);
2693 XtSetValues(titleWidget, args, 2);
2696 if (appData.showButtonBar) {
2697 widgetList[j++] = buttonBarWidget = CreateButtonBar(buttonBar);
2698 XtSetArg(args[0], XtNleft, XtChainRight); // [HGM] glue to right window edge
2699 XtSetArg(args[1], XtNright, XtChainRight); // for good run-time sizing
2700 XtSetArg(args[2], XtNtop, XtChainTop);
2701 XtSetArg(args[3], XtNbottom, XtChainTop);
2702 XtSetValues(buttonBarWidget, args, 4);
2705 widgetList[j++] = messageWidget =
2706 XtCreateWidget("message", labelWidgetClass, formWidget,
2707 messageArgs, XtNumber(messageArgs));
2708 XtSetArg(args[0], XtNtop, XtChainTop);
2709 XtSetArg(args[1], XtNbottom, XtChainTop);
2710 XtSetValues(messageWidget, args, 2);
2712 widgetList[j++] = boardWidget =
2713 XtCreateWidget("board", widgetClass, formWidget, boardArgs,
2714 XtNumber(boardArgs));
2716 XtManageChildren(widgetList, j);
2718 timerWidth = (boardWidth - sep) / 2;
2719 XtSetArg(args[0], XtNwidth, timerWidth);
2720 XtSetValues(whiteTimerWidget, args, 1);
2721 XtSetValues(blackTimerWidget, args, 1);
2723 XtSetArg(args[0], XtNbackground, &timerBackgroundPixel);
2724 XtSetArg(args[1], XtNforeground, &timerForegroundPixel);
2725 XtGetValues(whiteTimerWidget, args, 2);
2727 if (appData.showButtonBar) {
2728 XtSetArg(args[0], XtNbackground, &buttonBackgroundPixel);
2729 XtSetArg(args[1], XtNforeground, &buttonForegroundPixel);
2730 XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
2734 * formWidget uses these constraints but they are stored
2738 XtSetArg(args[i], XtNfromHoriz, 0); i++;
2739 XtSetValues(menuBarWidget, args, i);
2740 if (appData.titleInWindow) {
2743 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2744 XtSetValues(whiteTimerWidget, args, i);
2746 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2747 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2748 XtSetValues(blackTimerWidget, args, i);
2750 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2751 XtSetArg(args[i], XtNjustify, XtJustifyLeft); i++;
2752 XtSetValues(titleWidget, args, i);
2754 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2755 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2756 XtSetValues(messageWidget, args, i);
2757 if (appData.showButtonBar) {
2759 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2760 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2761 XtSetValues(buttonBarWidget, args, i);
2765 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2766 XtSetValues(whiteTimerWidget, args, i);
2768 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2769 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2770 XtSetValues(blackTimerWidget, args, i);
2772 XtSetArg(args[i], XtNfromHoriz, menuBarWidget); i++;
2773 XtSetValues(titleWidget, args, i);
2775 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2776 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2777 XtSetValues(messageWidget, args, i);
2778 if (appData.showButtonBar) {
2780 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2781 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2782 XtSetValues(buttonBarWidget, args, i);
2787 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2788 XtSetValues(whiteTimerWidget, args, i);
2790 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2791 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2792 XtSetValues(blackTimerWidget, args, i);
2794 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2795 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2796 XtSetValues(messageWidget, args, i);
2797 if (appData.showButtonBar) {
2799 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2800 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2801 XtSetValues(buttonBarWidget, args, i);
2805 XtSetArg(args[0], XtNfromVert, messageWidget);
2806 XtSetArg(args[1], XtNtop, XtChainTop);
2807 XtSetArg(args[2], XtNbottom, XtChainBottom);
2808 XtSetArg(args[3], XtNleft, XtChainLeft);
2809 XtSetArg(args[4], XtNright, XtChainRight);
2810 XtSetValues(boardWidget, args, 5);
2812 XtRealizeWidget(shellWidget);
2815 * Correct the width of the message and title widgets.
2816 * It is not known why some systems need the extra fudge term.
2817 * The value "2" is probably larger than needed.
2819 XawFormDoLayout(formWidget, False);
2821 #define WIDTH_FUDGE 2
2823 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2824 XtSetArg(args[i], XtNheight, &h); i++;
2825 XtGetValues(messageWidget, args, i);
2826 if (appData.showButtonBar) {
2828 XtSetArg(args[i], XtNwidth, &w); i++;
2829 XtGetValues(buttonBarWidget, args, i);
2830 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2832 w = boardWidth - 2*bor + 1; /*!! +1 compensates for kludge below */
2835 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2836 if (gres != XtGeometryYes && appData.debugMode) {
2837 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2838 programName, gres, w, h, wr, hr);
2841 /* !! Horrible hack to work around bug in XFree86 4.0.1 (X11R6.4.3) */
2842 /* The size used for the child widget in layout lags one resize behind
2843 its true size, so we resize a second time, 1 pixel smaller. Yeech! */
2845 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2846 if (gres != XtGeometryYes && appData.debugMode) {
2847 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2848 programName, gres, w, h, wr, hr);
2851 XtSetArg(args[0], XtNleft, XtChainLeft); // [HGM] glue ends for good run-time sizing
2852 XtSetArg(args[1], XtNright, XtChainRight);
2853 XtSetValues(messageWidget, args, 2);
2855 if (appData.titleInWindow) {
2857 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2858 XtSetArg(args[i], XtNheight, &h); i++;
2859 XtGetValues(titleWidget, args, i);
2861 w = boardWidth - 2*bor;
2863 XtSetArg(args[0], XtNwidth, &w);
2864 XtGetValues(menuBarWidget, args, 1);
2865 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2868 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
2869 if (gres != XtGeometryYes && appData.debugMode) {
2871 _("%s: titleWidget geometry error %d %d %d %d %d\n"),
2872 programName, gres, w, h, wr, hr);
2875 XawFormDoLayout(formWidget, True);
2877 xBoardWindow = XtWindow(boardWidget);
2879 // [HGM] it seems the layout code ends here, but perhaps the color stuff is size independent and would
2880 // not need to go into InitDrawingSizes().
2884 * Create X checkmark bitmap and initialize option menu checks.
2886 ReadBitmap(&xMarkPixmap, "checkmark.bm",
2887 checkmark_bits, checkmark_width, checkmark_height);
2888 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
2889 if (appData.alwaysPromoteToQueen) {
2890 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
2893 if (appData.animateDragging) {
2894 XtSetValues(XtNameToWidget(menuBarWidget,
2895 "menuOptions.Animate Dragging"),
2898 if (appData.animate) {
2899 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
2902 if (appData.autoComment) {
2903 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
2906 if (appData.autoCallFlag) {
2907 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
2910 if (appData.autoFlipView) {
2911 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Auto Flip View"),
2914 if (appData.autoObserve) {
2915 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
2918 if (appData.autoRaiseBoard) {
2919 XtSetValues(XtNameToWidget(menuBarWidget,
2920 "menuOptions.Auto Raise Board"), args, 1);
2922 if (appData.autoSaveGames) {
2923 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
2926 if (appData.saveGameFile[0] != NULLCHAR) {
2927 /* Can't turn this off from menu */
2928 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
2930 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
2934 if (appData.blindfold) {
2935 XtSetValues(XtNameToWidget(menuBarWidget,
2936 "menuOptions.Blindfold"), args, 1);
2938 if (appData.flashCount > 0) {
2939 XtSetValues(XtNameToWidget(menuBarWidget,
2940 "menuOptions.Flash Moves"),
2943 if (appData.getMoveList) {
2944 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
2948 if (appData.highlightDragging) {
2949 XtSetValues(XtNameToWidget(menuBarWidget,
2950 "menuOptions.Highlight Dragging"),
2954 if (appData.highlightLastMove) {
2955 XtSetValues(XtNameToWidget(menuBarWidget,
2956 "menuOptions.Highlight Last Move"),
2959 if (appData.icsAlarm) {
2960 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.ICS Alarm"),
2963 if (appData.ringBellAfterMoves) {
2964 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
2967 if (appData.oldSaveStyle) {
2968 XtSetValues(XtNameToWidget(menuBarWidget,
2969 "menuOptions.Old Save Style"), args, 1);
2971 if (appData.periodicUpdates) {
2972 XtSetValues(XtNameToWidget(menuBarWidget,
2973 "menuOptions.Periodic Updates"), args, 1);
2975 if (appData.ponderNextMove) {
2976 XtSetValues(XtNameToWidget(menuBarWidget,
2977 "menuOptions.Ponder Next Move"), args, 1);
2979 if (appData.popupExitMessage) {
2980 XtSetValues(XtNameToWidget(menuBarWidget,
2981 "menuOptions.Popup Exit Message"), args, 1);
2983 if (appData.popupMoveErrors) {
2984 XtSetValues(XtNameToWidget(menuBarWidget,
2985 "menuOptions.Popup Move Errors"), args, 1);
2987 if (appData.premove) {
2988 XtSetValues(XtNameToWidget(menuBarWidget,
2989 "menuOptions.Premove"), args, 1);
2991 if (appData.quietPlay) {
2992 XtSetValues(XtNameToWidget(menuBarWidget,
2993 "menuOptions.Quiet Play"), args, 1);
2995 if (appData.showCoords) {
2996 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
2999 if (appData.hideThinkingFromHuman) {
3000 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
3003 if (appData.testLegality) {
3004 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Test Legality"),
3011 ReadBitmap(&wIconPixmap, "icon_white.bm",
3012 icon_white_bits, icon_white_width, icon_white_height);
3013 ReadBitmap(&bIconPixmap, "icon_black.bm",
3014 icon_black_bits, icon_black_width, icon_black_height);
3015 iconPixmap = wIconPixmap;
3017 XtSetArg(args[i], XtNiconPixmap, iconPixmap); i++;
3018 XtSetValues(shellWidget, args, i);
3021 * Create a cursor for the board widget.
3023 window_attributes.cursor = XCreateFontCursor(xDisplay, XC_hand2);
3024 XChangeWindowAttributes(xDisplay, xBoardWindow,
3025 CWCursor, &window_attributes);
3028 * Inhibit shell resizing.
3030 shellArgs[0].value = (XtArgVal) &w;
3031 shellArgs[1].value = (XtArgVal) &h;
3032 XtGetValues(shellWidget, shellArgs, 2);
3033 shellArgs[4].value = shellArgs[2].value = w;
3034 shellArgs[5].value = shellArgs[3].value = h;
3035 XtSetValues(shellWidget, &shellArgs[2], 4);
3036 marginW = w - boardWidth; // [HGM] needed to set new shellWidget size when we resize board
3037 marginH = h - boardHeight;
3039 CatchDeleteWindow(shellWidget, "QuitProc");
3044 if (appData.bitmapDirectory[0] != NULLCHAR) {
3051 /* Create regular pieces */
3052 if (!useImages) CreatePieces();
3057 if (appData.animate || appData.animateDragging)
3060 XtAugmentTranslations(formWidget,
3061 XtParseTranslationTable(globalTranslations));
3062 XtAugmentTranslations(boardWidget,
3063 XtParseTranslationTable(boardTranslations));
3064 XtAugmentTranslations(whiteTimerWidget,
3065 XtParseTranslationTable(whiteTranslations));
3066 XtAugmentTranslations(blackTimerWidget,
3067 XtParseTranslationTable(blackTranslations));
3069 /* Why is the following needed on some versions of X instead
3070 * of a translation? */
3071 XtAddEventHandler(boardWidget, ExposureMask, False,
3072 (XtEventHandler) EventProc, NULL);
3077 if (errorExitStatus == -1) {
3078 if (appData.icsActive) {
3079 /* We now wait until we see "login:" from the ICS before
3080 sending the logon script (problems with timestamp otherwise) */
3081 /*ICSInitScript();*/
3082 if (appData.icsInputBox) ICSInputBoxPopUp();
3085 signal(SIGINT, IntSigHandler);
3086 signal(SIGTERM, IntSigHandler);
3087 if (*appData.cmailGameName != NULLCHAR) {
3088 signal(SIGUSR1, CmailSigHandler);
3093 XtAppMainLoop(appContext);
3094 if (appData.debugMode) fclose(debugFP); // [DM] debug
3101 if (appData.icsActive && oldICSInteractionTitle != NULL) {
3102 DisplayIcsInteractionTitle(oldICSInteractionTitle);
3104 unlink(gameCopyFilename);
3105 unlink(gamePasteFilename);
3116 CmailSigHandler(sig)
3122 signal(SIGUSR1, SIG_IGN); /* suspend handler */
3124 /* Activate call-back function CmailSigHandlerCallBack() */
3125 OutputToProcess(cmailPR, (char *)(&dummy), sizeof(int), &error);
3127 signal(SIGUSR1, CmailSigHandler); /* re-activate handler */
3131 CmailSigHandlerCallBack(isr, closure, message, count, error)
3139 ReloadCmailMsgEvent(TRUE); /* Reload cmail msg */
3141 /**** end signal code ****/
3151 f = fopen(appData.icsLogon, "r");
3157 strcat(buf, appData.icsLogon);
3158 f = fopen(buf, "r");
3162 ProcessICSInitScript(f);
3169 EditCommentPopDown();
3180 SetMenuEnables(enab)
3184 if (!menuBarWidget) return;
3185 while (enab->name != NULL) {
3186 w = XtNameToWidget(menuBarWidget, enab->name);
3188 DisplayError(enab->name, 0);
3190 XtSetSensitive(w, enab->value);
3196 Enables icsEnables[] = {
3197 { "menuFile.Mail Move", False },
3198 { "menuFile.Reload CMail Message", False },
3199 { "menuMode.Machine Black", False },
3200 { "menuMode.Machine White", False },
3201 { "menuMode.Analysis Mode", False },
3202 { "menuMode.Analyze File", False },
3203 { "menuMode.Two Machines", False },
3205 { "menuHelp.Hint", False },
3206 { "menuHelp.Book", False },
3207 { "menuStep.Move Now", False },
3208 { "menuOptions.Periodic Updates", False },
3209 { "menuOptions.Hide Thinking", False },
3210 { "menuOptions.Ponder Next Move", False },
3215 Enables ncpEnables[] = {
3216 { "menuFile.Mail Move", False },
3217 { "menuFile.Reload CMail Message", False },
3218 { "menuMode.Machine White", False },
3219 { "menuMode.Machine Black", False },
3220 { "menuMode.Analysis Mode", False },
3221 { "menuMode.Analyze File", False },
3222 { "menuMode.Two Machines", False },
3223 { "menuMode.ICS Client", False },
3224 { "menuMode.ICS Input Box", False },
3225 { "Action", False },
3226 { "menuStep.Revert", False },
3227 { "menuStep.Move Now", False },
3228 { "menuStep.Retract Move", False },
3229 { "menuOptions.Auto Comment", False },
3230 { "menuOptions.Auto Flag", False },
3231 { "menuOptions.Auto Flip View", False },
3232 { "menuOptions.Auto Observe", False },
3233 { "menuOptions.Auto Raise Board", False },
3234 { "menuOptions.Get Move List", False },
3235 { "menuOptions.ICS Alarm", False },
3236 { "menuOptions.Move Sound", False },
3237 { "menuOptions.Quiet Play", False },
3238 { "menuOptions.Hide Thinking", False },
3239 { "menuOptions.Periodic Updates", False },
3240 { "menuOptions.Ponder Next Move", False },
3241 { "menuHelp.Hint", False },
3242 { "menuHelp.Book", False },
3246 Enables gnuEnables[] = {
3247 { "menuMode.ICS Client", False },
3248 { "menuMode.ICS Input Box", False },
3249 { "menuAction.Accept", False },
3250 { "menuAction.Decline", False },
3251 { "menuAction.Rematch", False },
3252 { "menuAction.Adjourn", False },
3253 { "menuAction.Stop Examining", False },
3254 { "menuAction.Stop Observing", False },
3255 { "menuStep.Revert", False },
3256 { "menuOptions.Auto Comment", False },
3257 { "menuOptions.Auto Observe", False },
3258 { "menuOptions.Auto Raise Board", False },
3259 { "menuOptions.Get Move List", False },
3260 { "menuOptions.Premove", False },
3261 { "menuOptions.Quiet Play", False },
3263 /* The next two options rely on SetCmailMode being called *after* */
3264 /* SetGNUMode so that when GNU is being used to give hints these */
3265 /* menu options are still available */
3267 { "menuFile.Mail Move", False },
3268 { "menuFile.Reload CMail Message", False },
3272 Enables cmailEnables[] = {
3274 { "menuAction.Call Flag", False },
3275 { "menuAction.Draw", True },
3276 { "menuAction.Adjourn", False },
3277 { "menuAction.Abort", False },
3278 { "menuAction.Stop Observing", False },
3279 { "menuAction.Stop Examining", False },
3280 { "menuFile.Mail Move", True },
3281 { "menuFile.Reload CMail Message", True },
3285 Enables trainingOnEnables[] = {
3286 { "menuMode.Edit Comment", False },
3287 { "menuMode.Pause", False },
3288 { "menuStep.Forward", False },
3289 { "menuStep.Backward", False },
3290 { "menuStep.Forward to End", False },
3291 { "menuStep.Back to Start", False },
3292 { "menuStep.Move Now", False },
3293 { "menuStep.Truncate Game", False },
3297 Enables trainingOffEnables[] = {
3298 { "menuMode.Edit Comment", True },
3299 { "menuMode.Pause", True },
3300 { "menuStep.Forward", True },
3301 { "menuStep.Backward", True },
3302 { "menuStep.Forward to End", True },
3303 { "menuStep.Back to Start", True },
3304 { "menuStep.Move Now", True },
3305 { "menuStep.Truncate Game", True },
3309 Enables machineThinkingEnables[] = {
3310 { "menuFile.Load Game", False },
3311 { "menuFile.Load Next Game", False },
3312 { "menuFile.Load Previous Game", False },
3313 { "menuFile.Reload Same Game", False },
3314 { "menuFile.Paste Game", False },
3315 { "menuFile.Load Position", False },
3316 { "menuFile.Load Next Position", False },
3317 { "menuFile.Load Previous Position", False },
3318 { "menuFile.Reload Same Position", False },
3319 { "menuFile.Paste Position", False },
3320 { "menuMode.Machine White", False },
3321 { "menuMode.Machine Black", False },
3322 { "menuMode.Two Machines", False },
3323 { "menuStep.Retract Move", False },
3327 Enables userThinkingEnables[] = {
3328 { "menuFile.Load Game", True },
3329 { "menuFile.Load Next Game", True },
3330 { "menuFile.Load Previous Game", True },
3331 { "menuFile.Reload Same Game", True },
3332 { "menuFile.Paste Game", True },
3333 { "menuFile.Load Position", True },
3334 { "menuFile.Load Next Position", True },
3335 { "menuFile.Load Previous Position", True },
3336 { "menuFile.Reload Same Position", True },
3337 { "menuFile.Paste Position", True },
3338 { "menuMode.Machine White", True },
3339 { "menuMode.Machine Black", True },
3340 { "menuMode.Two Machines", True },
3341 { "menuStep.Retract Move", True },
3347 SetMenuEnables(icsEnables);
3350 if (appData.zippyPlay && !appData.noChessProgram) /* [DM] icsEngineAnalyze */
3351 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Analysis Mode"), True);
3358 SetMenuEnables(ncpEnables);
3364 SetMenuEnables(gnuEnables);
3370 SetMenuEnables(cmailEnables);
3376 SetMenuEnables(trainingOnEnables);
3377 if (appData.showButtonBar) {
3378 XtSetSensitive(buttonBarWidget, False);
3384 SetTrainingModeOff()
3386 SetMenuEnables(trainingOffEnables);
3387 if (appData.showButtonBar) {
3388 XtSetSensitive(buttonBarWidget, True);
3393 SetUserThinkingEnables()
3395 if (appData.noChessProgram) return;
3396 SetMenuEnables(userThinkingEnables);
3400 SetMachineThinkingEnables()
3402 if (appData.noChessProgram) return;
3403 SetMenuEnables(machineThinkingEnables);
3405 case MachinePlaysBlack:
3406 case MachinePlaysWhite:
3407 case TwoMachinesPlay:
3408 XtSetSensitive(XtNameToWidget(menuBarWidget,
3409 ModeToWidgetName(gameMode)), True);
3416 #define Abs(n) ((n)<0 ? -(n) : (n))
3419 * Find a font that matches "pattern" that is as close as
3420 * possible to the targetPxlSize. Prefer fonts that are k
3421 * pixels smaller to fonts that are k pixels larger. The
3422 * pattern must be in the X Consortium standard format,
3423 * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".
3424 * The return value should be freed with XtFree when no
3427 char *FindFont(pattern, targetPxlSize)
3431 char **fonts, *p, *best, *scalable, *scalableTail;
3432 int i, j, nfonts, minerr, err, pxlSize;
3435 char **missing_list;
3437 char *def_string, *base_fnt_lst, strInt[3];
3439 XFontStruct **fnt_list;
3441 base_fnt_lst = calloc(1, strlen(pattern) + 3);
3442 sprintf(strInt, "%d", targetPxlSize);
3443 p = strstr(pattern, "--");
3444 strncpy(base_fnt_lst, pattern, p - pattern + 2);
3445 strcat(base_fnt_lst, strInt);
3446 strcat(base_fnt_lst, strchr(p + 2, '-'));
3448 if ((fntSet = XCreateFontSet(xDisplay,
3452 &def_string)) == NULL) {
3454 fprintf(stderr, _("Unable to create font set.\n"));
3458 nfonts = XFontsOfFontSet(fntSet, &fnt_list, &fonts);
3460 fonts = XListFonts(xDisplay, pattern, 999999, &nfonts);
3462 fprintf(stderr, _("%s: no fonts match pattern %s\n"),
3463 programName, pattern);
3471 for (i=0; i<nfonts; i++) {
3474 if (*p != '-') continue;
3476 if (*p == NULLCHAR) break;
3477 if (*p++ == '-') j++;
3479 if (j < 7) continue;
3482 scalable = fonts[i];
3485 err = pxlSize - targetPxlSize;
3486 if (Abs(err) < Abs(minerr) ||
3487 (minerr > 0 && err < 0 && -err == minerr)) {
3493 if (scalable && Abs(minerr) > appData.fontSizeTolerance) {
3494 /* If the error is too big and there is a scalable font,
3495 use the scalable font. */
3496 int headlen = scalableTail - scalable;
3497 p = (char *) XtMalloc(strlen(scalable) + 10);
3498 while (isdigit(*scalableTail)) scalableTail++;
3499 sprintf(p, "%.*s%d%s", headlen, scalable, targetPxlSize, scalableTail);
3501 p = (char *) XtMalloc(strlen(best) + 1);
3504 if (appData.debugMode) {
3505 fprintf(debugFP, _("resolved %s at pixel size %d\n to %s\n"),
3506 pattern, targetPxlSize, p);
3509 if (missing_count > 0)
3510 XFreeStringList(missing_list);
3511 XFreeFontSet(xDisplay, fntSet);
3513 XFreeFontNames(fonts);
3520 XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
3521 | GCBackground | GCFunction | GCPlaneMask;
3522 XGCValues gc_values;
3525 gc_values.plane_mask = AllPlanes;
3526 gc_values.line_width = lineGap;
3527 gc_values.line_style = LineSolid;
3528 gc_values.function = GXcopy;
3530 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3531 gc_values.background = XBlackPixel(xDisplay, xScreen);
3532 lineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3534 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3535 gc_values.background = XWhitePixel(xDisplay, xScreen);
3536 coordGC = XtGetGC(shellWidget, value_mask, &gc_values);
3537 XSetFont(xDisplay, coordGC, coordFontID);
3539 // [HGM] make font for holdings counts (white on black0
3540 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3541 gc_values.background = XBlackPixel(xDisplay, xScreen);
3542 countGC = XtGetGC(shellWidget, value_mask, &gc_values);
3543 XSetFont(xDisplay, countGC, countFontID);
3545 if (appData.monoMode) {
3546 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3547 gc_values.background = XWhitePixel(xDisplay, xScreen);
3548 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3550 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3551 gc_values.background = XBlackPixel(xDisplay, xScreen);
3552 lightSquareGC = wbPieceGC
3553 = XtGetGC(shellWidget, value_mask, &gc_values);
3555 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3556 gc_values.background = XWhitePixel(xDisplay, xScreen);
3557 darkSquareGC = bwPieceGC
3558 = XtGetGC(shellWidget, value_mask, &gc_values);
3560 if (DefaultDepth(xDisplay, xScreen) == 1) {
3561 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
3562 gc_values.function = GXcopyInverted;
3563 copyInvertedGC = XtGetGC(shellWidget, value_mask, &gc_values);
3564 gc_values.function = GXcopy;
3565 if (XBlackPixel(xDisplay, xScreen) == 1) {
3566 bwPieceGC = darkSquareGC;
3567 wbPieceGC = copyInvertedGC;
3569 bwPieceGC = copyInvertedGC;
3570 wbPieceGC = lightSquareGC;
3574 gc_values.foreground = highlightSquareColor;
3575 gc_values.background = highlightSquareColor;
3576 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3578 gc_values.foreground = premoveHighlightColor;
3579 gc_values.background = premoveHighlightColor;
3580 prelineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3582 gc_values.foreground = lightSquareColor;
3583 gc_values.background = darkSquareColor;
3584 lightSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3586 gc_values.foreground = darkSquareColor;
3587 gc_values.background = lightSquareColor;
3588 darkSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3590 gc_values.foreground = jailSquareColor;
3591 gc_values.background = jailSquareColor;
3592 jailSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3594 gc_values.foreground = whitePieceColor;
3595 gc_values.background = darkSquareColor;
3596 wdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3598 gc_values.foreground = whitePieceColor;
3599 gc_values.background = lightSquareColor;
3600 wlPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3602 gc_values.foreground = whitePieceColor;
3603 gc_values.background = jailSquareColor;
3604 wjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3606 gc_values.foreground = blackPieceColor;
3607 gc_values.background = darkSquareColor;
3608 bdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3610 gc_values.foreground = blackPieceColor;
3611 gc_values.background = lightSquareColor;
3612 blPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3614 gc_values.foreground = blackPieceColor;
3615 gc_values.background = jailSquareColor;
3616 bjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3620 void loadXIM(xim, xmask, filename, dest, mask)
3633 fp = fopen(filename, "rb");
3635 fprintf(stderr, _("%s: error loading XIM!\n"), programName);
3642 for (y=0; y<h; ++y) {
3643 for (x=0; x<h; ++x) {
3648 XPutPixel(xim, x, y, blackPieceColor);
3650 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3653 XPutPixel(xim, x, y, darkSquareColor);
3655 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3658 XPutPixel(xim, x, y, whitePieceColor);
3660 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3663 XPutPixel(xim, x, y, lightSquareColor);
3665 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3671 /* create Pixmap of piece */
3672 *dest = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3674 XPutImage(xDisplay, *dest, lightSquareGC, xim,
3677 /* create Pixmap of clipmask
3678 Note: We assume the white/black pieces have the same
3679 outline, so we make only 6 masks. This is okay
3680 since the XPM clipmask routines do the same. */
3682 temp = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3684 XPutImage(xDisplay, temp, lightSquareGC, xmask,
3687 /* now create the 1-bit version */
3688 *mask = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3691 values.foreground = 1;
3692 values.background = 0;
3694 /* Don't use XtGetGC, not read only */
3695 maskGC = XCreateGC(xDisplay, *mask,
3696 GCForeground | GCBackground, &values);
3697 XCopyPlane(xDisplay, temp, *mask, maskGC,
3698 0, 0, squareSize, squareSize, 0, 0, 1);
3699 XFreePixmap(xDisplay, temp);
3703 void CreateXIMPieces()
3708 static char *ximkind[] = { "ll", "ld", "dl", "dd" };
3713 /* The XSynchronize calls were copied from CreatePieces.
3714 Not sure if needed, but can't hurt */
3715 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3718 /* temp needed by loadXIM() */
3719 ximtemp = XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3720 0, 0, ss, ss, AllPlanes, XYPixmap);
3722 if (strlen(appData.pixmapDirectory) == 0) {
3726 if (appData.monoMode) {
3727 DisplayFatalError(_("XIM pieces cannot be used in monochrome mode"),
3731 fprintf(stderr, _("\nLoading XIMs...\n"));
3733 for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
3734 fprintf(stderr, "%d", piece+1);
3735 for (kind=0; kind<4; kind++) {
3736 fprintf(stderr, ".");
3737 snprintf(buf, sizeof(buf), "%s/%c%s%u.xim",
3738 ExpandPathName(appData.pixmapDirectory),
3739 ToLower(PieceToChar((ChessSquare)piece)),
3741 ximPieceBitmap[kind][piece] =
3742 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3743 0, 0, ss, ss, AllPlanes, XYPixmap);
3744 if (appData.debugMode)
3745 fprintf(stderr, _("(File:%s:) "), buf);
3746 loadXIM(ximPieceBitmap[kind][piece],
3748 &(xpmPieceBitmap[kind][piece]),
3749 &(ximMaskPm[piece%(int)BlackPawn]));
3751 fprintf(stderr," ");
3753 /* Load light and dark squares */
3754 /* If the LSQ and DSQ pieces don't exist, we will
3755 draw them with solid squares. */
3756 snprintf(buf,sizeof(buf), "%s/lsq%u.xim", ExpandPathName(appData.pixmapDirectory), ss);
3757 if (access(buf, 0) != 0) {
3761 fprintf(stderr, _("light square "));
3763 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3764 0, 0, ss, ss, AllPlanes, XYPixmap);
3765 if (appData.debugMode)
3766 fprintf(stderr, _("(File:%s:) "), buf);
3768 loadXIM(ximLightSquare, NULL, buf, &xpmLightSquare, NULL);
3769 fprintf(stderr, _("dark square "));
3770 snprintf(buf,sizeof(buf), "%s/dsq%u.xim",
3771 ExpandPathName(appData.pixmapDirectory), ss);
3772 if (appData.debugMode)
3773 fprintf(stderr, _("(File:%s:) "), buf);
3775 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3776 0, 0, ss, ss, AllPlanes, XYPixmap);
3777 loadXIM(ximDarkSquare, NULL, buf, &xpmDarkSquare, NULL);
3778 xpmJailSquare = xpmLightSquare;
3780 fprintf(stderr, _("Done.\n"));
3782 XSynchronize(xDisplay, False); /* Work-around for xlib/xt buffering bug */
3786 void CreateXPMPieces()
3790 u_int ss = squareSize;
3792 static char *xpmkind[] = { "ll", "ld", "dl", "dd" };
3793 XpmColorSymbol symbols[4];
3796 /* Apparently some versions of Xpm don't define XpmFormat at all --tpm */
3797 if (appData.debugMode) {
3798 fprintf(stderr, "XPM Library Version: %d.%d%c\n",
3799 XpmFormat, XpmVersion, (char)('a' + XpmRevision - 1));
3803 /* The XSynchronize calls were copied from CreatePieces.
3804 Not sure if needed, but can't hurt */
3805 XSynchronize(xDisplay, True); /* Work-around for xlib/xt buffering bug */
3807 /* Setup translations so piece colors match square colors */
3808 symbols[0].name = "light_piece";
3809 symbols[0].value = appData.whitePieceColor;
3810 symbols[1].name = "dark_piece";
3811 symbols[1].value = appData.blackPieceColor;
3812 symbols[2].name = "light_square";
3813 symbols[2].value = appData.lightSquareColor;
3814 symbols[3].name = "dark_square";
3815 symbols[3].value = appData.darkSquareColor;
3817 attr.valuemask = XpmColorSymbols;
3818 attr.colorsymbols = symbols;
3819 attr.numsymbols = 4;
3821 if (appData.monoMode) {
3822 DisplayFatalError(_("XPM pieces cannot be used in monochrome mode"),
3826 if (strlen(appData.pixmapDirectory) == 0) {
3827 XpmPieces* pieces = builtInXpms;
3830 while (pieces->size != squareSize && pieces->size) pieces++;
3831 if (!pieces->size) {
3832 fprintf(stderr, _("No builtin XPM pieces of size %d\n"), squareSize);
3835 for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
3836 for (kind=0; kind<4; kind++) {
3838 if ((r=XpmCreatePixmapFromData(xDisplay, xBoardWindow,
3839 pieces->xpm[piece][kind],
3840 &(xpmPieceBitmap[kind][piece]),
3841 NULL, &attr)) != 0) {
3842 fprintf(stderr, _("Error %d loading XPM image \"%s\"\n"),
3849 xpmJailSquare = xpmLightSquare;
3853 fprintf(stderr, _("\nLoading XPMs...\n"));
3856 for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
3857 fprintf(stderr, "%d ", piece+1);
3858 for (kind=0; kind<4; kind++) {
3859 snprintf(buf, sizeof(buf), "%s/%c%s%u.xpm",
3860 ExpandPathName(appData.pixmapDirectory),
3861 ToLower(PieceToChar((ChessSquare)piece)),
3863 if (appData.debugMode) {
3864 fprintf(stderr, _("(File:%s:) "), buf);
3866 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3867 &(xpmPieceBitmap[kind][piece]),
3868 NULL, &attr)) != 0) {
3869 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"),
3875 /* Load light and dark squares */
3876 /* If the LSQ and DSQ pieces don't exist, we will
3877 draw them with solid squares. */
3878 fprintf(stderr, _("light square "));
3879 snprintf(buf, sizeof(buf), "%s/lsq%u.xpm", ExpandPathName(appData.pixmapDirectory), ss);
3880 if (access(buf, 0) != 0) {
3884 if (appData.debugMode)
3885 fprintf(stderr, _("(File:%s:) "), buf);
3887 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3888 &xpmLightSquare, NULL, &attr)) != 0) {
3889 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
3892 fprintf(stderr, _("dark square "));
3893 snprintf(buf, sizeof(buf), "%s/dsq%u.xpm",
3894 ExpandPathName(appData.pixmapDirectory), ss);
3895 if (appData.debugMode) {
3896 fprintf(stderr, _("(File:%s:) "), buf);
3898 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3899 &xpmDarkSquare, NULL, &attr)) != 0) {
3900 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
3904 xpmJailSquare = xpmLightSquare;
3905 fprintf(stderr, _("Done.\n"));
3907 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3910 #endif /* HAVE_LIBXPM */
3913 /* No built-in bitmaps */
3918 u_int ss = squareSize;
3920 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3923 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
3924 for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
3925 sprintf(buf, "%c%u%c.bm", ToLower(PieceToChar((ChessSquare)piece)),
3926 ss, kind == SOLID ? 's' : 'o');
3927 ReadBitmap(&pieceBitmap[kind][piece], buf, NULL, ss, ss);
3931 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3935 /* With built-in bitmaps */
3938 BuiltInBits* bib = builtInBits;
3941 u_int ss = squareSize;
3943 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3946 while (bib->squareSize != ss && bib->squareSize != 0) bib++;
3948 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
3949 for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
3950 sprintf(buf, "%c%u%c.bm", ToLower(PieceToChar((ChessSquare)piece)),
3951 ss, kind == SOLID ? 's' : 'o');
3952 ReadBitmap(&pieceBitmap[kind][piece], buf,
3953 bib->bits[kind][piece], ss, ss);
3957 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3962 void ReadBitmap(pm, name, bits, wreq, hreq)
3965 unsigned char bits[];
3971 char msg[MSG_SIZ], fullname[MSG_SIZ];
3973 if (*appData.bitmapDirectory != NULLCHAR) {
3974 strcpy(fullname, appData.bitmapDirectory);
3975 strcat(fullname, "/");
3976 strcat(fullname, name);
3977 errcode = XReadBitmapFile(xDisplay, xBoardWindow, fullname,
3978 &w, &h, pm, &x_hot, &y_hot);
3979 if (errcode != BitmapSuccess) {
3981 case BitmapOpenFailed:
3982 snprintf(msg, sizeof(msg), _("Can't open bitmap file %s"), fullname);
3984 case BitmapFileInvalid:
3985 snprintf(msg, sizeof(msg), _("Invalid bitmap in file %s"), fullname);
3987 case BitmapNoMemory:
3988 snprintf(msg, sizeof(msg), _("Ran out of memory reading bitmap file %s"),
3992 snprintf(msg, sizeof(msg), _("Unknown XReadBitmapFile error %d on file %s"),
3996 fprintf(stderr, _("%s: %s...using built-in\n"),
3998 } else if (w != wreq || h != hreq) {
4000 _("%s: Bitmap %s is %dx%d, not %dx%d...using built-in\n"),
4001 programName, fullname, w, h, wreq, hreq);
4008 fprintf(stderr, _("%s: No built-in bitmap for %s; giving up\n"),
4012 ; // [HGM] bitmaps: make it non-fatal if we have no bitmap;
4014 *pm = XCreateBitmapFromData(xDisplay, xBoardWindow, (char *) bits,
4023 if (lineGap == 0) return;
4025 /* [HR] Split this into 2 loops for non-square boards. */
4027 for (i = 0; i < BOARD_HEIGHT + 1; i++) {
4028 gridSegments[i].x1 = 0;
4029 gridSegments[i].x2 =
4030 lineGap + BOARD_WIDTH * (squareSize + lineGap);
4031 gridSegments[i].y1 = gridSegments[i].y2
4032 = lineGap / 2 + (i * (squareSize + lineGap));
4035 for (j = 0; j < BOARD_WIDTH + 1; j++) {
4036 gridSegments[j + i].y1 = 0;
4037 gridSegments[j + i].y2 =
4038 lineGap + BOARD_HEIGHT * (squareSize + lineGap);
4039 gridSegments[j + i].x1 = gridSegments[j + i].x2
4040 = lineGap / 2 + (j * (squareSize + lineGap));
4044 static void MenuBarSelect(w, addr, index)
4049 XtActionProc proc = (XtActionProc) addr;
4051 (proc)(NULL, NULL, NULL, NULL);
4054 void CreateMenuBarPopup(parent, name, mb)
4064 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
4067 XtSetArg(args[j], XtNleftMargin, 20); j++;
4068 XtSetArg(args[j], XtNrightMargin, 20); j++;
4070 while (mi->string != NULL) {
4071 if (strcmp(mi->string, "----") == 0) {
4072 entry = XtCreateManagedWidget(mi->string, smeLineObjectClass,
4075 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string)));
4076 entry = XtCreateManagedWidget(mi->string, smeBSBObjectClass,
4078 XtAddCallback(entry, XtNcallback,
4079 (XtCallbackProc) MenuBarSelect,
4080 (caddr_t) mi->proc);
4086 Widget CreateMenuBar(mb)
4090 Widget anchor, menuBar;
4092 char menuName[MSG_SIZ];
4095 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
4096 XtSetArg(args[j], XtNvSpace, 0); j++;
4097 XtSetArg(args[j], XtNborderWidth, 0); j++;
4098 menuBar = XtCreateWidget("menuBar", boxWidgetClass,
4099 formWidget, args, j);
4101 while (mb->name != NULL) {
4102 strcpy(menuName, "menu");
4103 strcat(menuName, mb->name);
4105 XtSetArg(args[j], XtNmenuName, XtNewString(menuName)); j++;
4108 shortName[0] = _(mb->name)[0];
4109 shortName[1] = NULLCHAR;
4110 XtSetArg(args[j], XtNlabel, XtNewString(shortName)); j++;
4113 XtSetArg(args[j], XtNlabel, XtNewString(_(mb->name))); j++;
4116 XtSetArg(args[j], XtNborderWidth, 0); j++;
4117 anchor = XtCreateManagedWidget(mb->name, menuButtonWidgetClass,
4119 CreateMenuBarPopup(menuBar, menuName, mb);
4125 Widget CreateButtonBar(mi)
4129 Widget button, buttonBar;
4133 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
4135 XtSetArg(args[j], XtNhSpace, 0); j++;
4137 XtSetArg(args[j], XtNborderWidth, 0); j++;
4138 XtSetArg(args[j], XtNvSpace, 0); j++;
4139 buttonBar = XtCreateWidget("buttonBar", boxWidgetClass,
4140 formWidget, args, j);
4142 while (mi->string != NULL) {
4145 XtSetArg(args[j], XtNinternalWidth, 2); j++;
4146 XtSetArg(args[j], XtNborderWidth, 0); j++;
4148 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string))); j++;
4149 button = XtCreateManagedWidget(mi->string, commandWidgetClass,
4150 buttonBar, args, j);
4151 XtAddCallback(button, XtNcallback,
4152 (XtCallbackProc) MenuBarSelect,
4153 (caddr_t) mi->proc);
4160 CreatePieceMenu(name, color)
4167 ChessSquare selection;
4169 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
4170 boardWidget, args, 0);
4172 for (i = 0; i < PIECE_MENU_SIZE; i++) {
4173 String item = pieceMenuStrings[color][i];
4175 if (strcmp(item, "----") == 0) {
4176 entry = XtCreateManagedWidget(item, smeLineObjectClass,
4179 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
4180 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
4182 selection = pieceMenuTranslation[color][i];
4183 XtAddCallback(entry, XtNcallback,
4184 (XtCallbackProc) PieceMenuSelect,
4185 (caddr_t) selection);
4186 if (selection == WhitePawn || selection == BlackPawn) {
4187 XtSetArg(args[0], XtNpopupOnEntry, entry);
4188 XtSetValues(menu, args, 1);
4201 ChessSquare selection;
4203 whitePieceMenu = CreatePieceMenu("menuW", 0);
4204 blackPieceMenu = CreatePieceMenu("menuB", 1);
4206 XtRegisterGrabAction(PieceMenuPopup, True,
4207 (unsigned)(ButtonPressMask|ButtonReleaseMask),
4208 GrabModeAsync, GrabModeAsync);
4210 XtSetArg(args[0], XtNlabel, _("Drop"));
4211 dropMenu = XtCreatePopupShell("menuD", simpleMenuWidgetClass,
4212 boardWidget, args, 1);
4213 for (i = 0; i < DROP_MENU_SIZE; i++) {
4214 String item = dropMenuStrings[i];
4216 if (strcmp(item, "----") == 0) {
4217 entry = XtCreateManagedWidget(item, smeLineObjectClass,
4220 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
4221 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
4223 selection = dropMenuTranslation[i];
4224 XtAddCallback(entry, XtNcallback,
4225 (XtCallbackProc) DropMenuSelect,
4226 (caddr_t) selection);
4231 void SetupDropMenu()
4239 for (i=0; i<sizeof(dmEnables)/sizeof(DropMenuEnables); i++) {
4240 entry = XtNameToWidget(dropMenu, dmEnables[i].widget);
4241 p = strchr(gameMode == IcsPlayingWhite ? white_holding : black_holding,
4242 dmEnables[i].piece);
4243 XtSetSensitive(entry, p != NULL || !appData.testLegality
4244 /*!!temp:*/ || (gameInfo.variant == VariantCrazyhouse
4245 && !appData.icsActive));
4247 while (p && *p++ == dmEnables[i].piece) count++;
4248 snprintf(label, sizeof(label), "%s %d", dmEnables[i].widget, count);
4250 XtSetArg(args[j], XtNlabel, label); j++;
4251 XtSetValues(entry, args, j);
4255 void PieceMenuPopup(w, event, params, num_params)
4259 Cardinal *num_params;
4262 if (event->type != ButtonPress) return;
4263 if (errorUp) ErrorPopDown();
4267 whichMenu = params[0];
4269 case IcsPlayingWhite:
4270 case IcsPlayingBlack:
4272 case MachinePlaysWhite:
4273 case MachinePlaysBlack:
4274 if (appData.testLegality &&
4275 gameInfo.variant != VariantBughouse &&
4276 gameInfo.variant != VariantCrazyhouse) return;
4278 whichMenu = "menuD";
4284 if (((pmFromX = EventToSquare(event->xbutton.x, BOARD_WIDTH)) < 0) ||
4285 ((pmFromY = EventToSquare(event->xbutton.y, BOARD_HEIGHT)) < 0)) {
4286 pmFromX = pmFromY = -1;
4290 pmFromX = BOARD_WIDTH - 1 - pmFromX;
4292 pmFromY = BOARD_HEIGHT - 1 - pmFromY;
4294 XtPopupSpringLoaded(XtNameToWidget(boardWidget, whichMenu));
4297 static void PieceMenuSelect(w, piece, junk)
4302 if (pmFromX < 0 || pmFromY < 0) return;
4303 EditPositionMenuEvent(piece, pmFromX, pmFromY);
4306 static void DropMenuSelect(w, piece, junk)
4311 if (pmFromX < 0 || pmFromY < 0) return;
4312 DropMenuEvent(piece, pmFromX, pmFromY);
4315 void WhiteClock(w, event, prms, nprms)
4321 if (gameMode == EditPosition || gameMode == IcsExamining) {
4322 SetWhiteToPlayEvent();
4323 } else if (gameMode == IcsPlayingBlack || gameMode == MachinePlaysWhite) {
4328 void BlackClock(w, event, prms, nprms)
4334 if (gameMode == EditPosition || gameMode == IcsExamining) {
4335 SetBlackToPlayEvent();
4336 } else if (gameMode == IcsPlayingWhite || gameMode == MachinePlaysBlack) {
4343 * If the user selects on a border boundary, return -1; if off the board,
4344 * return -2. Otherwise map the event coordinate to the square.
4346 int EventToSquare(x, limit)
4354 if ((x % (squareSize + lineGap)) >= squareSize)
4356 x /= (squareSize + lineGap);
4362 static void do_flash_delay(msec)
4368 static void drawHighlight(file, rank, gc)
4374 if (lineGap == 0 || appData.blindfold) return;
4377 x = lineGap/2 + ((BOARD_WIDTH-1)-file) *
4378 (squareSize + lineGap);
4379 y = lineGap/2 + rank * (squareSize + lineGap);
4381 x = lineGap/2 + file * (squareSize + lineGap);
4382 y = lineGap/2 + ((BOARD_HEIGHT-1)-rank) *
4383 (squareSize + lineGap);
4386 XDrawRectangle(xDisplay, xBoardWindow, gc, x, y,
4387 squareSize+lineGap, squareSize+lineGap);
4390 int hi1X = -1, hi1Y = -1, hi2X = -1, hi2Y = -1;
4391 int pm1X = -1, pm1Y = -1, pm2X = -1, pm2Y = -1;
4394 SetHighlights(fromX, fromY, toX, toY)
4395 int fromX, fromY, toX, toY;
4397 if (hi1X != fromX || hi1Y != fromY) {
4398 if (hi1X >= 0 && hi1Y >= 0) {
4399 drawHighlight(hi1X, hi1Y, lineGC);
4401 if (fromX >= 0 && fromY >= 0) {
4402 drawHighlight(fromX, fromY, highlineGC);
4405 if (hi2X != toX || hi2Y != toY) {
4406 if (hi2X >= 0 && hi2Y >= 0) {
4407 drawHighlight(hi2X, hi2Y, lineGC);
4409 if (toX >= 0 && toY >= 0) {
4410 drawHighlight(toX, toY, highlineGC);
4422 SetHighlights(-1, -1, -1, -1);
4427 SetPremoveHighlights(fromX, fromY, toX, toY)
4428 int fromX, fromY, toX, toY;
4430 if (pm1X != fromX || pm1Y != fromY) {
4431 if (pm1X >= 0 && pm1Y >= 0) {
4432 drawHighlight(pm1X, pm1Y, lineGC);
4434 if (fromX >= 0 && fromY >= 0) {
4435 drawHighlight(fromX, fromY, prelineGC);
4438 if (pm2X != toX || pm2Y != toY) {
4439 if (pm2X >= 0 && pm2Y >= 0) {
4440 drawHighlight(pm2X, pm2Y, lineGC);
4442 if (toX >= 0 && toY >= 0) {
4443 drawHighlight(toX, toY, prelineGC);
4453 ClearPremoveHighlights()
4455 SetPremoveHighlights(-1, -1, -1, -1);
4458 static void BlankSquare(x, y, color, piece, dest)
4463 if (useImages && useImageSqs) {
4467 pm = xpmLightSquare;
4472 case 2: /* neutral */
4477 XCopyArea(xDisplay, pm, dest, wlPieceGC, 0, 0,
4478 squareSize, squareSize, x, y);
4488 case 2: /* neutral */
4493 XFillRectangle(xDisplay, dest, gc, x, y, squareSize, squareSize);
4498 I split out the routines to draw a piece so that I could
4499 make a generic flash routine.
4501 static void monoDrawPiece_1bit(piece, square_color, x, y, dest)
4503 int square_color, x, y;
4506 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
4507 switch (square_color) {
4509 case 2: /* neutral */
4511 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
4512 ? *pieceToOutline(piece)
4513 : *pieceToSolid(piece),
4514 dest, bwPieceGC, 0, 0,
4515 squareSize, squareSize, x, y);
4518 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
4519 ? *pieceToSolid(piece)
4520 : *pieceToOutline(piece),
4521 dest, wbPieceGC, 0, 0,
4522 squareSize, squareSize, x, y);
4527 static void monoDrawPiece(piece, square_color, x, y, dest)
4529 int square_color, x, y;
4532 switch (square_color) {
4534 case 2: /* neutral */
4536 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
4537 ? *pieceToOutline(piece)
4538 : *pieceToSolid(piece),
4539 dest, bwPieceGC, 0, 0,
4540 squareSize, squareSize, x, y, 1);
4543 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
4544 ? *pieceToSolid(piece)
4545 : *pieceToOutline(piece),
4546 dest, wbPieceGC, 0, 0,
4547 squareSize, squareSize, x, y, 1);
4552 static void colorDrawPiece(piece, square_color, x, y, dest)
4554 int square_color, x, y;
4557 if(pieceToSolid(piece) == NULL) return; // [HGM] bitmaps: make it non-fatal if we have no bitmap;
4558 switch (square_color) {
4560 XCopyPlane(xDisplay, *pieceToSolid(piece),
4561 dest, (int) piece < (int) BlackPawn
4562 ? wlPieceGC : blPieceGC, 0, 0,
4563 squareSize, squareSize, x, y, 1);
4566 XCopyPlane(xDisplay, *pieceToSolid(piece),
4567 dest, (int) piece < (int) BlackPawn
4568 ? wdPieceGC : bdPieceGC, 0, 0,
4569 squareSize, squareSize, x, y, 1);
4571 case 2: /* neutral */
4573 XCopyPlane(xDisplay, *pieceToSolid(piece),
4574 dest, (int) piece < (int) BlackPawn
4575 ? wjPieceGC : bjPieceGC, 0, 0,
4576 squareSize, squareSize, x, y, 1);
4581 static void colorDrawPieceImage(piece, square_color, x, y, dest)
4583 int square_color, x, y;
4588 switch (square_color) {
4590 case 2: /* neutral */
4592 if ((int)piece < (int) BlackPawn) {
4600 if ((int)piece < (int) BlackPawn) {
4608 XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
4609 dest, wlPieceGC, 0, 0,
4610 squareSize, squareSize, x, y);
4613 typedef void (*DrawFunc)();
4615 DrawFunc ChooseDrawFunc()
4617 if (appData.monoMode) {
4618 if (DefaultDepth(xDisplay, xScreen) == 1) {
4619 return monoDrawPiece_1bit;
4621 return monoDrawPiece;
4625 return colorDrawPieceImage;
4627 return colorDrawPiece;
4631 /* [HR] determine square color depending on chess variant. */
4632 static int SquareColor(row, column)
4637 if (gameInfo.variant == VariantXiangqi) {
4638 if (column >= 3 && column <= 5 && row >= 0 && row <= 2) {
4640 } else if (column >= 3 && column <= 5 && row >= 7 && row <= 9) {
4642 } else if (row <= 4) {
4648 square_color = ((column + row) % 2) == 1;
4651 /* [hgm] holdings: next line makes all holdings squares light */
4652 if(column < BOARD_LEFT || column >= BOARD_RGHT) square_color = 1;
4654 return square_color;
4657 void DrawSquare(row, column, piece, do_flash)
4658 int row, column, do_flash;
4661 int square_color, x, y, direction, font_ascent, font_descent;
4664 XCharStruct overall;
4668 if(gameInfo.variant == VariantShogi) { // [HGM] shogi: in shogi Q is used for Lance
4669 if(piece == WhiteQueen) piece = WhiteLance; else
4670 if(piece == BlackQueen) piece = BlackLance;
4673 else if(gameInfo.variant == VariantGothic) { // [HGM] shogi: in Gothic Chancelor has alternative look
4674 if(piece == WhiteMarshall) piece = WhiteSilver; else
4675 if(piece == BlackMarshall) piece = BlackSilver;
4679 /* Calculate delay in milliseconds (2-delays per complete flash) */
4680 flash_delay = 500 / appData.flashRate;
4683 x = lineGap + ((BOARD_WIDTH-1)-column) *
4684 (squareSize + lineGap);
4685 y = lineGap + row * (squareSize + lineGap);
4687 x = lineGap + column * (squareSize + lineGap);
4688 y = lineGap + ((BOARD_HEIGHT-1)-row) *
4689 (squareSize + lineGap);
4692 square_color = SquareColor(row, column);
4694 if ( // [HGM] holdings: blank out area between board and holdings
4695 column == BOARD_LEFT-1 || column == BOARD_RGHT
4696 || (column == BOARD_LEFT-2 && row < BOARD_HEIGHT-gameInfo.holdingsSize)
4697 || (column == BOARD_RGHT+1 && row >= gameInfo.holdingsSize) ) {
4698 BlankSquare(x, y, 2, EmptySquare, xBoardWindow);
4700 // [HGM] print piece counts next to holdings
4701 string[1] = NULLCHAR;
4702 if (column == (flipView ? BOARD_LEFT-1 : BOARD_RGHT) && 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 + squareSize - overall.width - 2,
4709 y + font_ascent + 1, string, 1);
4711 XDrawString(xDisplay, xBoardWindow, countGC,
4712 x + squareSize - overall.width - 2,
4713 y + font_ascent + 1, string, 1);
4716 if (column == (flipView ? BOARD_RGHT : BOARD_LEFT-1) && piece > 1) {
4717 string[0] = '0' + piece;
4718 XTextExtents(countFontStruct, string, 1, &direction,
4719 &font_ascent, &font_descent, &overall);
4720 if (appData.monoMode) {
4721 XDrawImageString(xDisplay, xBoardWindow, countGC,
4722 x + 2, y + font_ascent + 1, string, 1);
4724 XDrawString(xDisplay, xBoardWindow, countGC,
4725 x + 2, y + font_ascent + 1, string, 1);
4729 if (piece == EmptySquare || appData.blindfold) {
4730 BlankSquare(x, y, square_color, piece, xBoardWindow);
4732 drawfunc = ChooseDrawFunc();
4733 if (do_flash && appData.flashCount > 0) {
4734 for (i=0; i<appData.flashCount; ++i) {
4736 drawfunc(piece, square_color, x, y, xBoardWindow);
4737 XSync(xDisplay, False);
4738 do_flash_delay(flash_delay);
4740 BlankSquare(x, y, square_color, piece, xBoardWindow);
4741 XSync(xDisplay, False);
4742 do_flash_delay(flash_delay);
4745 drawfunc(piece, square_color, x, y, xBoardWindow);
4749 string[1] = NULLCHAR;
4750 if (appData.showCoords && row == (flipView ? BOARD_HEIGHT-1 : 0)
4751 && column >= BOARD_LEFT && column < BOARD_RGHT) {
4752 string[0] = 'a' + column - BOARD_LEFT;
4753 XTextExtents(coordFontStruct, string, 1, &direction,
4754 &font_ascent, &font_descent, &overall);
4755 if (appData.monoMode) {
4756 XDrawImageString(xDisplay, xBoardWindow, coordGC,
4757 x + squareSize - overall.width - 2,
4758 y + squareSize - font_descent - 1, string, 1);
4760 XDrawString(xDisplay, xBoardWindow, coordGC,
4761 x + squareSize - overall.width - 2,
4762 y + squareSize - font_descent - 1, string, 1);
4765 if (appData.showCoords && column == (flipView ? BOARD_RGHT-1 : BOARD_LEFT)) {
4766 string[0] = ONE + row;
4767 XTextExtents(coordFontStruct, string, 1, &direction,
4768 &font_ascent, &font_descent, &overall);
4769 if (appData.monoMode) {
4770 XDrawImageString(xDisplay, xBoardWindow, coordGC,
4771 x + 2, y + font_ascent + 1, string, 1);
4773 XDrawString(xDisplay, xBoardWindow, coordGC,
4774 x + 2, y + font_ascent + 1, string, 1);
4780 /* Why is this needed on some versions of X? */
4781 void EventProc(widget, unused, event)
4786 if (!XtIsRealized(widget))
4789 switch (event->type) {
4791 if (event->xexpose.count > 0) return; /* no clipping is done */
4792 XDrawPosition(widget, True, NULL);
4800 void DrawPosition(fullRedraw, board)
4801 /*Boolean*/int fullRedraw;
4804 XDrawPosition(boardWidget, fullRedraw, board);
4807 /* Returns 1 if there are "too many" differences between b1 and b2
4808 (i.e. more than 1 move was made) */
4809 static int too_many_diffs(b1, b2)
4815 for (i=0; i<BOARD_HEIGHT; ++i) {
4816 for (j=0; j<BOARD_WIDTH; ++j) {
4817 if (b1[i][j] != b2[i][j]) {
4818 if (++c > 4) /* Castling causes 4 diffs */
4827 /* Matrix describing castling maneuvers */
4828 /* Row, ColRookFrom, ColKingFrom, ColRookTo, ColKingTo */
4829 static int castling_matrix[4][5] = {
4830 { 0, 0, 4, 3, 2 }, /* 0-0-0, white */
4831 { 0, 7, 4, 5, 6 }, /* 0-0, white */
4832 { 7, 0, 4, 3, 2 }, /* 0-0-0, black */
4833 { 7, 7, 4, 5, 6 } /* 0-0, black */
4836 /* Checks whether castling occurred. If it did, *rrow and *rcol
4837 are set to the destination (row,col) of the rook that moved.
4839 Returns 1 if castling occurred, 0 if not.
4841 Note: Only handles a max of 1 castling move, so be sure
4842 to call too_many_diffs() first.
4844 static int check_castle_draw(newb, oldb, rrow, rcol)
4851 /* For each type of castling... */
4852 for (i=0; i<4; ++i) {
4853 r = castling_matrix[i];
4855 /* Check the 4 squares involved in the castling move */
4857 for (j=1; j<=4; ++j) {
4858 if (newb[r[0]][r[j]] == oldb[r[0]][r[j]]) {
4865 /* All 4 changed, so it must be a castling move */
4874 static int damage[BOARD_SIZE][BOARD_SIZE];
4877 * event handler for redrawing the board
4879 void XDrawPosition(w, repaint, board)
4881 /*Boolean*/int repaint;
4885 static int lastFlipView = 0;
4886 static int lastBoardValid = 0;
4887 static Board lastBoard;
4891 if (board == NULL) {
4892 if (!lastBoardValid) return;
4895 if (!lastBoardValid || lastFlipView != flipView) {
4896 XtSetArg(args[0], XtNleftBitmap, (flipView ? xMarkPixmap : None));
4897 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flip View"),
4902 * It would be simpler to clear the window with XClearWindow()
4903 * but this causes a very distracting flicker.
4906 if (!repaint && lastBoardValid && lastFlipView == flipView) {
4908 /* If too much changes (begin observing new game, etc.), don't
4910 do_flash = too_many_diffs(board, lastBoard) ? 0 : 1;
4912 /* Special check for castling so we don't flash both the king
4913 and the rook (just flash the king). */
4915 if (check_castle_draw(board, lastBoard, &rrow, &rcol)) {
4916 /* Draw rook with NO flashing. King will be drawn flashing later */
4917 DrawSquare(rrow, rcol, board[rrow][rcol], 0);
4918 lastBoard[rrow][rcol] = board[rrow][rcol];
4922 /* First pass -- Draw (newly) empty squares and repair damage.
4923 This prevents you from having a piece show up twice while it
4924 is flashing on its new square */
4925 for (i = 0; i < BOARD_HEIGHT; i++)
4926 for (j = 0; j < BOARD_WIDTH; j++)
4927 if ((board[i][j] != lastBoard[i][j] && board[i][j] == EmptySquare)
4929 DrawSquare(i, j, board[i][j], 0);
4930 damage[i][j] = False;
4933 /* Second pass -- Draw piece(s) in new position and flash them */
4934 for (i = 0; i < BOARD_HEIGHT; i++)
4935 for (j = 0; j < BOARD_WIDTH; j++)
4936 if (board[i][j] != lastBoard[i][j]) {
4937 DrawSquare(i, j, board[i][j], do_flash);
4941 XDrawSegments(xDisplay, xBoardWindow, lineGC,
4942 gridSegments, BOARD_HEIGHT + BOARD_WIDTH + 2);
4944 for (i = 0; i < BOARD_HEIGHT; i++)
4945 for (j = 0; j < BOARD_WIDTH; j++) {
4946 DrawSquare(i, j, board[i][j], 0);
4947 damage[i][j] = False;
4951 CopyBoard(lastBoard, board);
4953 lastFlipView = flipView;
4955 /* Draw highlights */
4956 if (pm1X >= 0 && pm1Y >= 0) {
4957 drawHighlight(pm1X, pm1Y, prelineGC);
4959 if (pm2X >= 0 && pm2Y >= 0) {
4960 drawHighlight(pm2X, pm2Y, prelineGC);
4962 if (hi1X >= 0 && hi1Y >= 0) {
4963 drawHighlight(hi1X, hi1Y, highlineGC);
4965 if (hi2X >= 0 && hi2Y >= 0) {
4966 drawHighlight(hi2X, hi2Y, highlineGC);
4969 /* If piece being dragged around board, must redraw that too */
4972 XSync(xDisplay, False);
4977 * event handler for redrawing the board
4979 void DrawPositionProc(w, event, prms, nprms)
4985 XDrawPosition(w, True, NULL);
4990 * event handler for parsing user moves
4992 // [HGM] This routine will need quite some reworking. Although the backend still supports the old
4993 // way of doing things, by calling UserMoveEvent() to test the legality of the move and then perform
4994 // it at the end, and doing all kind of preliminary tests here (e.g. to weed out self-captures), it
4995 // should be made to use the new way, of calling UserMoveTest early to determine the legality of the
4996 // move, (which will weed out the illegal selfcaptures and moves into the holdings, and flag promotions),
4997 // and at the end FinishMove() to perform the move after optional promotion popups.
4998 // For now I patched it to allow self-capture with King, and suppress clicks between board and holdings.
4999 void HandleUserMove(w, event, prms, nprms)
5006 Boolean saveAnimate;
5007 static int second = 0;
5009 if (w != boardWidget || errorExitStatus != -1) return;
5011 if (event->type == ButtonPress) ErrorPopDown();
5014 if (event->type == ButtonPress) {
5015 XtPopdown(promotionShell);
5016 XtDestroyWidget(promotionShell);
5017 promotionUp = False;
5025 x = EventToSquare(event->xbutton.x, BOARD_WIDTH);
5026 y = EventToSquare(event->xbutton.y, BOARD_HEIGHT);
5027 if (!flipView && y >= 0) {
5028 y = BOARD_HEIGHT - 1 - y;
5030 if (flipView && x >= 0) {
5031 x = BOARD_WIDTH - 1 - x;
5034 /* [HGM] holdings: next 5 lines: ignore all clicks between board and holdings */
5035 if(event->type == ButtonPress
5036 && ( x == BOARD_LEFT-1 || x == BOARD_RGHT
5037 || x == BOARD_LEFT-2 && y < BOARD_HEIGHT-gameInfo.holdingsSize
5038 || x == BOARD_RGHT+1 && y >= gameInfo.holdingsSize) )
5042 if (event->type == ButtonPress) {
5044 if (OKToStartUserMove(x, y)) {
5048 DragPieceBegin(event->xbutton.x, event->xbutton.y);
5049 if (appData.highlightDragging) {
5050 SetHighlights(x, y, -1, -1);
5058 if (event->type == ButtonPress && gameMode != EditPosition &&
5063 /* Check if clicking again on the same color piece */
5064 fromP = boards[currentMove][fromY][fromX];
5065 toP = boards[currentMove][y][x];
5066 if ((WhitePawn <= fromP && fromP < WhiteKing && // [HGM] this test should go, as UserMoveTest now does it.
5067 WhitePawn <= toP && toP <= WhiteKing) || // For now I made it less critical by exempting King
5068 (BlackPawn <= fromP && fromP < BlackKing && // moves, to not interfere with FRC castlings.
5069 BlackPawn <= toP && toP <= BlackKing)) {
5070 /* Clicked again on same color piece -- changed his mind */
5071 second = (x == fromX && y == fromY);
5072 if (appData.highlightDragging) {
5073 SetHighlights(x, y, -1, -1);
5077 if (OKToStartUserMove(x, y)) {
5080 DragPieceBegin(event->xbutton.x, event->xbutton.y);
5086 if (event->type == ButtonRelease && x == fromX && y == fromY) {
5087 DragPieceEnd(event->xbutton.x, event->xbutton.y);
5088 if (appData.animateDragging) {
5089 /* Undo animation damage if any */
5090 DrawPosition(FALSE, NULL);
5093 /* Second up/down in same square; just abort move */
5098 ClearPremoveHighlights();
5100 /* First upclick in same square; start click-click mode */
5101 SetHighlights(x, y, -1, -1);
5106 /* Completed move */
5109 saveAnimate = appData.animate;
5110 if (event->type == ButtonPress) {
5111 /* Finish clickclick move */
5112 if (appData.animate || appData.highlightLastMove) {
5113 SetHighlights(fromX, fromY, toX, toY);
5118 /* Finish drag move */
5119 if (appData.highlightLastMove) {
5120 SetHighlights(fromX, fromY, toX, toY);
5124 DragPieceEnd(event->xbutton.x, event->xbutton.y);
5125 /* Don't animate move and drag both */
5126 appData.animate = FALSE;
5128 if (IsPromotion(fromX, fromY, toX, toY)) {
5129 if (appData.alwaysPromoteToQueen) {
5130 UserMoveEvent(fromX, fromY, toX, toY, 'q');
5131 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
5132 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
5135 SetHighlights(fromX, fromY, toX, toY);
5139 UserMoveEvent(fromX, fromY, toX, toY, NULLCHAR);
5140 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
5141 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
5144 appData.animate = saveAnimate;
5145 if (appData.animate || appData.animateDragging) {
5146 /* Undo animation damage if needed */
5147 DrawPosition(FALSE, NULL);
5151 void AnimateUserMove (Widget w, XEvent * event,
5152 String * params, Cardinal * nParams)
5154 DragPieceMove(event->xmotion.x, event->xmotion.y);
5157 Widget CommentCreate(name, text, mutable, callback, lines)
5159 int /*Boolean*/ mutable;
5160 XtCallbackProc callback;
5164 Widget shell, layout, form, edit, b_ok, b_cancel, b_clear, b_close, b_edit;
5169 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5170 XtGetValues(boardWidget, args, j);
5173 XtSetArg(args[j], XtNresizable, True); j++;
5176 XtCreatePopupShell(name, topLevelShellWidgetClass,
5177 shellWidget, args, j);
5180 XtCreatePopupShell(name, transientShellWidgetClass,
5181 shellWidget, args, j);
5184 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
5185 layoutArgs, XtNumber(layoutArgs));
5187 XtCreateManagedWidget("form", formWidgetClass, layout,
5188 formArgs, XtNumber(formArgs));
5192 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
5193 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
5195 XtSetArg(args[j], XtNstring, text); j++;
5196 XtSetArg(args[j], XtNtop, XtChainTop); j++;
5197 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5198 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5199 XtSetArg(args[j], XtNright, XtChainRight); j++;
5200 XtSetArg(args[j], XtNresizable, True); j++;
5201 XtSetArg(args[j], XtNwidth, bw_width); j++; /*force wider than buttons*/
5203 XtSetArg(args[j], XtNscrollVertical, XawtextScrollWhenNeeded); j++;
5205 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
5206 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
5208 XtSetArg(args[j], XtNautoFill, True); j++;
5209 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
5211 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
5215 XtSetArg(args[j], XtNfromVert, edit); j++;
5216 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5217 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5218 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5219 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5221 XtCreateManagedWidget(_("ok"), commandWidgetClass, form, args, j);
5222 XtAddCallback(b_ok, XtNcallback, callback, (XtPointer) 0);
5225 XtSetArg(args[j], XtNfromVert, edit); j++;
5226 XtSetArg(args[j], XtNfromHoriz, b_ok); j++;
5227 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5228 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5229 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5230 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5232 XtCreateManagedWidget(_("cancel"), commandWidgetClass, form, args, j);
5233 XtAddCallback(b_cancel, XtNcallback, callback, (XtPointer) 0);
5236 XtSetArg(args[j], XtNfromVert, edit); j++;
5237 XtSetArg(args[j], XtNfromHoriz, b_cancel); j++;
5238 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5239 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5240 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5241 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5243 XtCreateManagedWidget(_("clear"), commandWidgetClass, form, args, j);
5244 XtAddCallback(b_clear, XtNcallback, callback, (XtPointer) 0);
5247 XtSetArg(args[j], XtNfromVert, edit); j++;
5248 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5249 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5250 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5251 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5253 XtCreateManagedWidget(_("close"), commandWidgetClass, form, args, j);
5254 XtAddCallback(b_close, XtNcallback, callback, (XtPointer) 0);
5257 XtSetArg(args[j], XtNfromVert, edit); j++;
5258 XtSetArg(args[j], XtNfromHoriz, b_close); j++;
5259 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5260 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5261 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5262 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5264 XtCreateManagedWidget(_("edit"), commandWidgetClass, form, args, j);
5265 XtAddCallback(b_edit, XtNcallback, callback, (XtPointer) 0);
5268 XtRealizeWidget(shell);
5270 if (commentX == -1) {
5273 Dimension pw_height;
5274 Dimension ew_height;
5277 XtSetArg(args[j], XtNheight, &ew_height); j++;
5278 XtGetValues(edit, args, j);
5281 XtSetArg(args[j], XtNheight, &pw_height); j++;
5282 XtGetValues(shell, args, j);
5283 commentH = pw_height + (lines - 1) * ew_height;
5284 commentW = bw_width - 16;
5286 XSync(xDisplay, False);
5288 /* This code seems to tickle an X bug if it is executed too soon
5289 after xboard starts up. The coordinates get transformed as if
5290 the main window was positioned at (0, 0).
5292 XtTranslateCoords(shellWidget,
5293 (bw_width - commentW) / 2, 0 - commentH / 2,
5294 &commentX, &commentY);
5296 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
5297 RootWindowOfScreen(XtScreen(shellWidget)),
5298 (bw_width - commentW) / 2, 0 - commentH / 2,
5303 if (commentY < 0) commentY = 0; /*avoid positioning top offscreen*/
5306 XtSetArg(args[j], XtNheight, commentH); j++;
5307 XtSetArg(args[j], XtNwidth, commentW); j++;
5308 XtSetArg(args[j], XtNx, commentX); j++;
5309 XtSetArg(args[j], XtNy, commentY); j++;
5310 XtSetValues(shell, args, j);
5311 XtSetKeyboardFocus(shell, edit);
5316 /* Used for analysis window and ICS input window */
5317 Widget MiscCreate(name, text, mutable, callback, lines)
5319 int /*Boolean*/ mutable;
5320 XtCallbackProc callback;
5324 Widget shell, layout, form, edit;
5326 Dimension bw_width, pw_height, ew_height, w, h;
5332 XtSetArg(args[j], XtNresizable, True); j++;
5335 XtCreatePopupShell(name, topLevelShellWidgetClass,
5336 shellWidget, args, j);
5339 XtCreatePopupShell(name, transientShellWidgetClass,
5340 shellWidget, args, j);
5343 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
5344 layoutArgs, XtNumber(layoutArgs));
5346 XtCreateManagedWidget("form", formWidgetClass, layout,
5347 formArgs, XtNumber(formArgs));
5351 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
5352 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
5354 XtSetArg(args[j], XtNstring, text); j++;
5355 XtSetArg(args[j], XtNtop, XtChainTop); j++;
5356 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5357 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5358 XtSetArg(args[j], XtNright, XtChainRight); j++;
5359 XtSetArg(args[j], XtNresizable, True); j++;
5361 XtSetArg(args[j], XtNscrollVertical, XawtextScrollWhenNeeded); j++;
5363 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
5364 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
5366 XtSetArg(args[j], XtNautoFill, True); j++;
5367 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
5369 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
5371 XtRealizeWidget(shell);
5374 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5375 XtGetValues(boardWidget, args, j);
5378 XtSetArg(args[j], XtNheight, &ew_height); j++;
5379 XtGetValues(edit, args, j);
5382 XtSetArg(args[j], XtNheight, &pw_height); j++;
5383 XtGetValues(shell, args, j);
5384 h = pw_height + (lines - 1) * ew_height;
5387 XSync(xDisplay, False);
5389 /* This code seems to tickle an X bug if it is executed too soon
5390 after xboard starts up. The coordinates get transformed as if
5391 the main window was positioned at (0, 0).
5393 XtTranslateCoords(shellWidget, (bw_width - w) / 2, 0 - h / 2, &x, &y);
5395 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
5396 RootWindowOfScreen(XtScreen(shellWidget)),
5397 (bw_width - w) / 2, 0 - h / 2, &xx, &yy, &junk);
5401 if (y < 0) y = 0; /*avoid positioning top offscreen*/
5404 XtSetArg(args[j], XtNheight, h); j++;
5405 XtSetArg(args[j], XtNwidth, w); j++;
5406 XtSetArg(args[j], XtNx, x); j++;
5407 XtSetArg(args[j], XtNy, y); j++;
5408 XtSetValues(shell, args, j);
5414 static int savedIndex; /* gross that this is global */
5416 void EditCommentPopUp(index, title, text)
5425 if (text == NULL) text = "";
5427 if (editShell == NULL) {
5429 CommentCreate(title, text, True, EditCommentCallback, 4);
5430 XtRealizeWidget(editShell);
5431 CatchDeleteWindow(editShell, "EditCommentPopDown");
5433 edit = XtNameToWidget(editShell, "*form.text");
5435 XtSetArg(args[j], XtNstring, text); j++;
5436 XtSetValues(edit, args, j);
5438 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5439 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5440 XtSetValues(editShell, args, j);
5443 XtPopup(editShell, XtGrabNone);
5447 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
5448 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
5452 void EditCommentCallback(w, client_data, call_data)
5454 XtPointer client_data, call_data;
5462 XtSetArg(args[j], XtNlabel, &name); j++;
5463 XtGetValues(w, args, j);
5465 if (strcmp(name, _("ok")) == 0) {
5466 edit = XtNameToWidget(editShell, "*form.text");
5468 XtSetArg(args[j], XtNstring, &val); j++;
5469 XtGetValues(edit, args, j);
5470 ReplaceComment(savedIndex, val);
5471 EditCommentPopDown();
5472 } else if (strcmp(name, _("cancel")) == 0) {
5473 EditCommentPopDown();
5474 } else if (strcmp(name, _("clear")) == 0) {
5475 edit = XtNameToWidget(editShell, "*form.text");
5476 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
5477 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
5481 void EditCommentPopDown()
5486 if (!editUp) return;
5488 XtSetArg(args[j], XtNx, &commentX); j++;
5489 XtSetArg(args[j], XtNy, &commentY); j++;
5490 XtSetArg(args[j], XtNheight, &commentH); j++;
5491 XtSetArg(args[j], XtNwidth, &commentW); j++;
5492 XtGetValues(editShell, args, j);
5493 XtPopdown(editShell);
5496 XtSetArg(args[j], XtNleftBitmap, None); j++;
5497 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
5501 void ICSInputBoxPopUp()
5506 char *title = _("ICS Input");
5509 if (ICSInputShell == NULL) {
5510 ICSInputShell = MiscCreate(title, "", True, NULL, 1);
5511 tr = XtParseTranslationTable(ICSInputTranslations);
5512 edit = XtNameToWidget(ICSInputShell, "*form.text");
5513 XtOverrideTranslations(edit, tr);
5514 XtRealizeWidget(ICSInputShell);
5515 CatchDeleteWindow(ICSInputShell, "ICSInputBoxPopDown");
5518 edit = XtNameToWidget(ICSInputShell, "*form.text");
5520 XtSetArg(args[j], XtNstring, ""); j++;
5521 XtSetValues(edit, args, j);
5523 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5524 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5525 XtSetValues(ICSInputShell, args, j);
5528 XtPopup(ICSInputShell, XtGrabNone);
5529 XtSetKeyboardFocus(ICSInputShell, edit);
5531 ICSInputBoxUp = True;
5533 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
5534 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
5538 void ICSInputSendText()
5545 edit = XtNameToWidget(ICSInputShell, "*form.text");
5547 XtSetArg(args[j], XtNstring, &val); j++;
5548 XtGetValues(edit, args, j);
5549 SendMultiLineToICS(val);
5550 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
5551 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
5554 void ICSInputBoxPopDown()
5559 if (!ICSInputBoxUp) return;
5561 XtPopdown(ICSInputShell);
5562 ICSInputBoxUp = False;
5564 XtSetArg(args[j], XtNleftBitmap, None); j++;
5565 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
5569 void CommentPopUp(title, text)
5576 if (commentShell == NULL) {
5578 CommentCreate(title, text, False, CommentCallback, 4);
5579 XtRealizeWidget(commentShell);
5580 CatchDeleteWindow(commentShell, "CommentPopDown");
5582 edit = XtNameToWidget(commentShell, "*form.text");
5584 XtSetArg(args[j], XtNstring, text); j++;
5585 XtSetValues(edit, args, j);
5587 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5588 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5589 XtSetValues(commentShell, args, j);
5592 XtPopup(commentShell, XtGrabNone);
5593 XSync(xDisplay, False);
5598 void AnalysisPopUp(title, text)
5605 if (analysisShell == NULL) {
5606 analysisShell = MiscCreate(title, text, False, NULL, 4);
5607 XtRealizeWidget(analysisShell);
5608 CatchDeleteWindow(analysisShell, "AnalysisPopDown");
5611 edit = XtNameToWidget(analysisShell, "*form.text");
5613 XtSetArg(args[j], XtNstring, text); j++;
5614 XtSetValues(edit, args, j);
5616 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5617 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5618 XtSetValues(analysisShell, args, j);
5622 XtPopup(analysisShell, XtGrabNone);
5624 XSync(xDisplay, False);
5629 void CommentCallback(w, client_data, call_data)
5631 XtPointer client_data, call_data;
5638 XtSetArg(args[j], XtNlabel, &name); j++;
5639 XtGetValues(w, args, j);
5641 if (strcmp(name, _("close")) == 0) {
5643 } else if (strcmp(name, _("edit")) == 0) {
5650 void CommentPopDown()
5655 if (!commentUp) return;
5657 XtSetArg(args[j], XtNx, &commentX); j++;
5658 XtSetArg(args[j], XtNy, &commentY); j++;
5659 XtSetArg(args[j], XtNwidth, &commentW); j++;
5660 XtSetArg(args[j], XtNheight, &commentH); j++;
5661 XtGetValues(commentShell, args, j);
5662 XtPopdown(commentShell);
5663 XSync(xDisplay, False);
5667 void AnalysisPopDown()
5669 if (!analysisUp) return;
5670 XtPopdown(analysisShell);
5671 XSync(xDisplay, False);
5673 if (appData.icsEngineAnalyze) ExitAnalyzeMode(); /* [DM] icsEngineAnalyze */
5677 void FileNamePopUp(label, def, proc, openMode)
5684 Widget popup, layout, dialog, edit;
5690 fileProc = proc; /* I can't see a way not */
5691 fileOpenMode = openMode; /* to use globals here */
5694 XtSetArg(args[i], XtNresizable, True); i++;
5695 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
5696 XtSetArg(args[i], XtNtitle, XtNewString(_("File name prompt"))); i++;
5697 fileNameShell = popup =
5698 XtCreatePopupShell("File name prompt", transientShellWidgetClass,
5699 shellWidget, args, i);
5702 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
5703 layoutArgs, XtNumber(layoutArgs));
5706 XtSetArg(args[i], XtNlabel, label); i++;
5707 XtSetArg(args[i], XtNvalue, def); i++;
5708 XtSetArg(args[i], XtNborderWidth, 0); i++;
5709 dialog = XtCreateManagedWidget("fileName", dialogWidgetClass,
5712 XawDialogAddButton(dialog, _("ok"), FileNameCallback, (XtPointer) dialog);
5713 XawDialogAddButton(dialog, _("cancel"), FileNameCallback,
5714 (XtPointer) dialog);
5716 XtRealizeWidget(popup);
5717 CatchDeleteWindow(popup, "FileNamePopDown");
5719 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
5720 &x, &y, &win_x, &win_y, &mask);
5722 XtSetArg(args[0], XtNx, x - 10);
5723 XtSetArg(args[1], XtNy, y - 30);
5724 XtSetValues(popup, args, 2);
5726 XtPopup(popup, XtGrabExclusive);
5729 edit = XtNameToWidget(dialog, "*value");
5730 XtSetKeyboardFocus(popup, edit);
5733 void FileNamePopDown()
5735 if (!filenameUp) return;
5736 XtPopdown(fileNameShell);
5737 XtDestroyWidget(fileNameShell);
5742 void FileNameCallback(w, client_data, call_data)
5744 XtPointer client_data, call_data;
5749 XtSetArg(args[0], XtNlabel, &name);
5750 XtGetValues(w, args, 1);
5752 if (strcmp(name, _("cancel")) == 0) {
5757 FileNameAction(w, NULL, NULL, NULL);
5760 void FileNameAction(w, event, prms, nprms)
5772 name = XawDialogGetValueString(w = XtParent(w));
5774 if ((name != NULL) && (*name != NULLCHAR)) {
5776 XtPopdown(w = XtParent(XtParent(w)));
5780 p = strrchr(buf, ' ');
5787 fullname = ExpandPathName(buf);
5789 ErrorPopUp(_("Error"), _("Can't open file"), FALSE);
5792 f = fopen(fullname, fileOpenMode);
5794 DisplayError(_("Failed to open file"), errno);
5796 (void) (*fileProc)(f, index, buf);
5803 XtPopdown(w = XtParent(XtParent(w)));
5809 void PromotionPopUp()
5812 Widget dialog, layout;
5814 Dimension bw_width, pw_width;
5818 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5819 XtGetValues(boardWidget, args, j);
5822 XtSetArg(args[j], XtNresizable, True); j++;
5823 XtSetArg(args[j], XtNtitle, XtNewString(_("Promotion"))); j++;
5825 XtCreatePopupShell("Promotion", transientShellWidgetClass,
5826 shellWidget, args, j);
5828 XtCreateManagedWidget(layoutName, formWidgetClass, promotionShell,
5829 layoutArgs, XtNumber(layoutArgs));
5832 XtSetArg(args[j], XtNlabel, _("Promote pawn to what?")); j++;
5833 XtSetArg(args[j], XtNborderWidth, 0); j++;
5834 dialog = XtCreateManagedWidget("promotion", dialogWidgetClass,
5837 XawDialogAddButton(dialog, _("Queen"), PromotionCallback,
5838 (XtPointer) dialog);
5839 XawDialogAddButton(dialog, _("Rook"), PromotionCallback,
5840 (XtPointer) dialog);
5841 XawDialogAddButton(dialog, _("Bishop"), PromotionCallback,
5842 (XtPointer) dialog);
5843 XawDialogAddButton(dialog, _("Knight"), PromotionCallback,
5844 (XtPointer) dialog);
5845 if (!appData.testLegality || gameInfo.variant == VariantSuicide ||
5846 gameInfo.variant == VariantGiveaway) {
5847 XawDialogAddButton(dialog, _("King"), PromotionCallback,
5848 (XtPointer) dialog);
5850 XawDialogAddButton(dialog, _("cancel"), PromotionCallback,
5851 (XtPointer) dialog);
5853 XtRealizeWidget(promotionShell);
5854 CatchDeleteWindow(promotionShell, "PromotionPopDown");
5857 XtSetArg(args[j], XtNwidth, &pw_width); j++;
5858 XtGetValues(promotionShell, args, j);
5860 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
5861 lineGap + squareSize/3 +
5862 ((toY == BOARD_HEIGHT-1) ^ (flipView) ?
5863 0 : 6*(squareSize + lineGap)), &x, &y);
5866 XtSetArg(args[j], XtNx, x); j++;
5867 XtSetArg(args[j], XtNy, y); j++;
5868 XtSetValues(promotionShell, args, j);
5870 XtPopup(promotionShell, XtGrabNone);
5875 void PromotionPopDown()
5877 if (!promotionUp) return;
5878 XtPopdown(promotionShell);
5879 XtDestroyWidget(promotionShell);
5880 promotionUp = False;
5883 void PromotionCallback(w, client_data, call_data)
5885 XtPointer client_data, call_data;
5891 XtSetArg(args[0], XtNlabel, &name);
5892 XtGetValues(w, args, 1);
5896 if (fromX == -1) return;
5898 if (strcmp(name, _("cancel")) == 0) {
5902 } else if (strcmp(name, _("Knight")) == 0) {
5905 promoChar = ToLower(name[0]);
5908 UserMoveEvent(fromX, fromY, toX, toY, promoChar);
5910 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
5911 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
5916 void ErrorCallback(w, client_data, call_data)
5918 XtPointer client_data, call_data;
5921 XtPopdown(w = XtParent(XtParent(XtParent(w))));
5923 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
5929 if (!errorUp) return;
5931 XtPopdown(errorShell);
5932 XtDestroyWidget(errorShell);
5933 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
5936 void ErrorPopUp(title, label, modal)
5937 char *title, *label;
5941 Widget dialog, layout;
5945 Dimension bw_width, pw_width;
5946 Dimension pw_height;
5950 XtSetArg(args[i], XtNresizable, True); i++;
5951 XtSetArg(args[i], XtNtitle, title); i++;
5953 XtCreatePopupShell("errorpopup", transientShellWidgetClass,
5954 shellWidget, args, i);
5956 XtCreateManagedWidget(layoutName, formWidgetClass, errorShell,
5957 layoutArgs, XtNumber(layoutArgs));
5960 XtSetArg(args[i], XtNlabel, label); i++;
5961 XtSetArg(args[i], XtNborderWidth, 0); i++;
5962 dialog = XtCreateManagedWidget("dialog", dialogWidgetClass,
5965 XawDialogAddButton(dialog, _("ok"), ErrorCallback, (XtPointer) dialog);
5967 XtRealizeWidget(errorShell);
5968 CatchDeleteWindow(errorShell, "ErrorPopDown");
5971 XtSetArg(args[i], XtNwidth, &bw_width); i++;
5972 XtGetValues(boardWidget, args, i);
5974 XtSetArg(args[i], XtNwidth, &pw_width); i++;
5975 XtSetArg(args[i], XtNheight, &pw_height); i++;
5976 XtGetValues(errorShell, args, i);
5979 /* This code seems to tickle an X bug if it is executed too soon
5980 after xboard starts up. The coordinates get transformed as if
5981 the main window was positioned at (0, 0).
5983 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
5984 0 - pw_height + squareSize / 3, &x, &y);
5986 XTranslateCoordinates(xDisplay, XtWindow(boardWidget),
5987 RootWindowOfScreen(XtScreen(boardWidget)),
5988 (bw_width - pw_width) / 2,
5989 0 - pw_height + squareSize / 3, &xx, &yy, &junk);
5993 if (y < 0) y = 0; /*avoid positioning top offscreen*/
5996 XtSetArg(args[i], XtNx, x); i++;
5997 XtSetArg(args[i], XtNy, y); i++;
5998 XtSetValues(errorShell, args, i);
6001 XtPopup(errorShell, modal ? XtGrabExclusive : XtGrabNone);
6004 /* Disable all user input other than deleting the window */
6005 static int frozen = 0;
6009 /* Grab by a widget that doesn't accept input */
6010 XtAddGrab(messageWidget, TRUE, FALSE);
6014 /* Undo a FreezeUI */
6017 if (!frozen) return;
6018 XtRemoveGrab(messageWidget);
6022 char *ModeToWidgetName(mode)
6026 case BeginningOfGame:
6027 if (appData.icsActive)
6028 return "menuMode.ICS Client";
6029 else if (appData.noChessProgram ||
6030 *appData.cmailGameName != NULLCHAR)
6031 return "menuMode.Edit Game";
6033 return "menuMode.Machine Black";
6034 case MachinePlaysBlack:
6035 return "menuMode.Machine Black";
6036 case MachinePlaysWhite:
6037 return "menuMode.Machine White";
6039 return "menuMode.Analysis Mode";
6041 return "menuMode.Analyze File";
6042 case TwoMachinesPlay:
6043 return "menuMode.Two Machines";
6045 return "menuMode.Edit Game";
6046 case PlayFromGameFile:
6047 return "menuFile.Load Game";
6049 return "menuMode.Edit Position";
6051 return "menuMode.Training";
6052 case IcsPlayingWhite:
6053 case IcsPlayingBlack:
6057 return "menuMode.ICS Client";
6064 void ModeHighlight()
6067 static int oldPausing = FALSE;
6068 static GameMode oldmode = (GameMode) -1;
6071 if (!boardWidget || !XtIsRealized(boardWidget)) return;
6073 if (pausing != oldPausing) {
6074 oldPausing = pausing;
6076 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6078 XtSetArg(args[0], XtNleftBitmap, None);
6080 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Pause"),
6083 if (appData.showButtonBar) {
6086 XtSetArg(args[0], XtNbackground, buttonForegroundPixel);
6087 XtSetArg(args[1], XtNforeground, buttonBackgroundPixel);
6089 XtSetArg(args[0], XtNbackground, buttonBackgroundPixel);
6090 XtSetArg(args[1], XtNforeground, buttonForegroundPixel);
6093 /* Always toggle, don't set. Previous code messes up when
6094 invoked while the button is pressed, as releasing it
6095 toggles the state again. */
6098 XtSetArg(args[0], XtNbackground, &oldbg);
6099 XtSetArg(args[1], XtNforeground, &oldfg);
6100 XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON),
6102 XtSetArg(args[0], XtNbackground, oldfg);
6103 XtSetArg(args[1], XtNforeground, oldbg);
6106 XtSetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
6110 wname = ModeToWidgetName(oldmode);
6111 if (wname != NULL) {
6112 XtSetArg(args[0], XtNleftBitmap, None);
6113 XtSetValues(XtNameToWidget(menuBarWidget, wname), args, 1);
6115 wname = ModeToWidgetName(gameMode);
6116 if (wname != NULL) {
6117 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6118 XtSetValues(XtNameToWidget(menuBarWidget, wname), args, 1);
6122 /* Maybe all the enables should be handled here, not just this one */
6123 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Training"),
6124 gameMode == Training || gameMode == PlayFromGameFile);
6129 * Button/menu procedures
6131 void ResetProc(w, event, prms, nprms)
6141 int LoadGamePopUp(f, gameNumber, title)
6146 cmailMsgLoaded = FALSE;
6147 if (gameNumber == 0) {
6148 int error = GameListBuild(f);
6150 DisplayError(_("Cannot build game list"), error);
6151 } else if (!ListEmpty(&gameList) &&
6152 ((ListGame *) gameList.tailPred)->number > 1) {
6153 GameListPopUp(f, title);
6159 return LoadGame(f, gameNumber, title, FALSE);
6162 void LoadGameProc(w, event, prms, nprms)
6168 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
6171 FileNamePopUp(_("Load game file name?"), "", LoadGamePopUp, "rb");
6174 void LoadNextGameProc(w, event, prms, nprms)
6183 void LoadPrevGameProc(w, event, prms, nprms)
6192 void ReloadGameProc(w, event, prms, nprms)
6201 void LoadNextPositionProc(w, event, prms, nprms)
6210 void LoadPrevPositionProc(w, event, prms, nprms)
6219 void ReloadPositionProc(w, event, prms, nprms)
6228 void LoadPositionProc(w, event, prms, nprms)
6234 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
6237 FileNamePopUp(_("Load position file name?"), "", LoadPosition, "rb");
6240 void SaveGameProc(w, event, prms, nprms)
6246 FileNamePopUp(_("Save game file name?"),
6247 DefaultFileName(appData.oldSaveStyle ? "game" : "pgn"),
6251 void SavePositionProc(w, event, prms, nprms)
6257 FileNamePopUp(_("Save position file name?"),
6258 DefaultFileName(appData.oldSaveStyle ? "pos" : "fen"),
6262 void ReloadCmailMsgProc(w, event, prms, nprms)
6268 ReloadCmailMsgEvent(FALSE);
6271 void MailMoveProc(w, event, prms, nprms)
6280 /* this variable is shared between CopyPositionProc and SendPositionSelection */
6281 static char *selected_fen_position=NULL;
6284 SendPositionSelection(Widget w, Atom *selection, Atom *target,
6285 Atom *type_return, XtPointer *value_return,
6286 unsigned long *length_return, int *format_return)
6288 char *selection_tmp;
6290 if (!selected_fen_position) return False; /* should never happen */
6291 if (*target == XA_STRING){
6292 /* note: since no XtSelectionDoneProc was registered, Xt will
6293 * automatically call XtFree on the value returned. So have to
6294 * make a copy of it allocated with XtMalloc */
6295 selection_tmp= XtMalloc(strlen(selected_fen_position)+16);
6296 strcpy(selection_tmp, selected_fen_position);
6298 *value_return=selection_tmp;
6299 *length_return=strlen(selection_tmp);
6300 *type_return=XA_STRING;
6301 *format_return = 8; /* bits per byte */
6308 /* note: when called from menu all parameters are NULL, so no clue what the
6309 * Widget which was clicked on was, or what the click event was
6311 void CopyPositionProc(w, event, prms, nprms)
6319 if (selected_fen_position) free(selected_fen_position);
6320 selected_fen_position = (char *)PositionToFEN(currentMove, NULL);
6321 if (!selected_fen_position) return;
6322 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
6324 SendPositionSelection,
6325 NULL/* lose_ownership_proc */ ,
6326 NULL/* transfer_done_proc */);
6328 free(selected_fen_position);
6329 selected_fen_position=NULL;
6333 /* function called when the data to Paste is ready */
6335 PastePositionCB(Widget w, XtPointer client_data, Atom *selection,
6336 Atom *type, XtPointer value, unsigned long *len, int *format)
6339 if (value==NULL || *len==0) return; /* nothing had been selected to copy */
6340 fenstr[*len]='\0'; /* normally this string is terminated, but be safe */
6341 EditPositionPasteFEN(fenstr);
6345 /* called when Paste Position button is pressed,
6346 * all parameters will be NULL */
6347 void PastePositionProc(w, event, prms, nprms)
6353 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
6354 /* (XtSelectionCallbackProc) */ PastePositionCB,
6355 NULL, /* client_data passed to PastePositionCB */
6357 /* better to use the time field from the event that triggered the
6358 * call to this function, but that isn't trivial to get
6366 SendGameSelection(Widget w, Atom *selection, Atom *target,
6367 Atom *type_return, XtPointer *value_return,
6368 unsigned long *length_return, int *format_return)
6370 char *selection_tmp;
6372 if (*target == XA_STRING){
6373 FILE* f = fopen(gameCopyFilename, "r");
6376 if (f == NULL) return False;
6380 selection_tmp = XtMalloc(len + 1);
6381 count = fread(selection_tmp, 1, len, f);
6383 XtFree(selection_tmp);
6386 selection_tmp[len] = NULLCHAR;
6387 *value_return = selection_tmp;
6388 *length_return = len;
6389 *type_return = XA_STRING;
6390 *format_return = 8; /* bits per byte */
6397 /* note: when called from menu all parameters are NULL, so no clue what the
6398 * Widget which was clicked on was, or what the click event was
6400 void CopyGameProc(w, event, prms, nprms)
6408 ret = SaveGameToFile(gameCopyFilename, FALSE);
6411 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
6414 NULL/* lose_ownership_proc */ ,
6415 NULL/* transfer_done_proc */);
6418 /* function called when the data to Paste is ready */
6420 PasteGameCB(Widget w, XtPointer client_data, Atom *selection,
6421 Atom *type, XtPointer value, unsigned long *len, int *format)
6424 if (value == NULL || *len == 0) {
6425 return; /* nothing had been selected to copy */
6427 f = fopen(gamePasteFilename, "w");
6429 DisplayError(_("Can't open temp file"), errno);
6432 fwrite(value, 1, *len, f);
6435 LoadGameFromFile(gamePasteFilename, 0, gamePasteFilename, TRUE);
6438 /* called when Paste Game button is pressed,
6439 * all parameters will be NULL */
6440 void PasteGameProc(w, event, prms, nprms)
6446 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
6447 /* (XtSelectionCallbackProc) */ PasteGameCB,
6448 NULL, /* client_data passed to PasteGameCB */
6450 /* better to use the time field from the event that triggered the
6451 * call to this function, but that isn't trivial to get
6461 SaveGameProc(NULL, NULL, NULL, NULL);
6465 void QuitProc(w, event, prms, nprms)
6474 void PauseProc(w, event, prms, nprms)
6484 void MachineBlackProc(w, event, prms, nprms)
6490 MachineBlackEvent();
6493 void MachineWhiteProc(w, event, prms, nprms)
6499 MachineWhiteEvent();
6502 void AnalyzeModeProc(w, event, prms, nprms)
6510 if (!first.analysisSupport) {
6511 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
6512 DisplayError(buf, 0);
6515 /* [DM] icsEngineAnalyze [HGM] This is horrible code; reverse the gameMode and isEngineAnalyze tests! */
6516 if (appData.icsActive) {
6517 if (gameMode != IcsObserving) {
6518 sprintf(buf,_("You are not observing a game"));
6519 DisplayError(buf, 0);
6521 if (appData.icsEngineAnalyze) {
6522 if (appData.debugMode)
6523 fprintf(debugFP, _("Found unexpected active ICS engine analyze \n"));
6529 /* if enable, use want disable icsEngineAnalyze */
6530 if (appData.icsEngineAnalyze) {
6535 appData.icsEngineAnalyze = TRUE;
6536 if (appData.debugMode)
6537 fprintf(debugFP, _("ICS engine analyze starting... \n"));
6539 if (!appData.showThinking)
6540 ShowThinkingProc(w,event,prms,nprms);
6545 void AnalyzeFileProc(w, event, prms, nprms)
6551 if (!first.analysisSupport) {
6553 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
6554 DisplayError(buf, 0);
6559 if (!appData.showThinking)
6560 ShowThinkingProc(w,event,prms,nprms);
6563 FileNamePopUp(_("File to analyze"), "", LoadGamePopUp, "rb");
6564 AnalysisPeriodicEvent(1);
6567 void TwoMachinesProc(w, event, prms, nprms)
6576 void IcsClientProc(w, event, prms, nprms)
6585 void EditGameProc(w, event, prms, nprms)
6594 void EditPositionProc(w, event, prms, nprms)
6600 EditPositionEvent();
6603 void TrainingProc(w, event, prms, nprms)
6612 void EditCommentProc(w, event, prms, nprms)
6619 EditCommentPopDown();
6625 void IcsInputBoxProc(w, event, prms, nprms)
6631 if (ICSInputBoxUp) {
6632 ICSInputBoxPopDown();
6638 void AcceptProc(w, event, prms, nprms)
6647 void DeclineProc(w, event, prms, nprms)
6656 void RematchProc(w, event, prms, nprms)
6665 void CallFlagProc(w, event, prms, nprms)
6674 void DrawProc(w, event, prms, nprms)
6683 void AbortProc(w, event, prms, nprms)
6692 void AdjournProc(w, event, prms, nprms)
6701 void ResignProc(w, event, prms, nprms)
6710 void AdjuWhiteProc(w, event, prms, nprms)
6716 UserAdjudicationEvent(+1);
6719 void AdjuBlackProc(w, event, prms, nprms)
6725 UserAdjudicationEvent(-1);
6728 void AdjuDrawProc(w, event, prms, nprms)
6734 UserAdjudicationEvent(0);
6737 void EnterKeyProc(w, event, prms, nprms)
6743 if (ICSInputBoxUp == True)
6747 void StopObservingProc(w, event, prms, nprms)
6753 StopObservingEvent();
6756 void StopExaminingProc(w, event, prms, nprms)
6762 StopExaminingEvent();
6766 void ForwardProc(w, event, prms, nprms)
6776 void BackwardProc(w, event, prms, nprms)
6785 void ToStartProc(w, event, prms, nprms)
6794 void ToEndProc(w, event, prms, nprms)
6803 void RevertProc(w, event, prms, nprms)
6812 void TruncateGameProc(w, event, prms, nprms)
6818 TruncateGameEvent();
6820 void RetractMoveProc(w, event, prms, nprms)
6829 void MoveNowProc(w, event, prms, nprms)
6839 void AlwaysQueenProc(w, event, prms, nprms)
6847 appData.alwaysPromoteToQueen = !appData.alwaysPromoteToQueen;
6849 if (appData.alwaysPromoteToQueen) {
6850 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6852 XtSetArg(args[0], XtNleftBitmap, None);
6854 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
6858 void AnimateDraggingProc(w, event, prms, nprms)
6866 appData.animateDragging = !appData.animateDragging;
6868 if (appData.animateDragging) {
6869 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6872 XtSetArg(args[0], XtNleftBitmap, None);
6874 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Dragging"),
6878 void AnimateMovingProc(w, event, prms, nprms)
6886 appData.animate = !appData.animate;
6888 if (appData.animate) {
6889 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6892 XtSetArg(args[0], XtNleftBitmap, None);
6894 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
6898 void AutocommProc(w, event, prms, nprms)
6906 appData.autoComment = !appData.autoComment;
6908 if (appData.autoComment) {
6909 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6911 XtSetArg(args[0], XtNleftBitmap, None);
6913 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
6918 void AutoflagProc(w, event, prms, nprms)
6926 appData.autoCallFlag = !appData.autoCallFlag;
6928 if (appData.autoCallFlag) {
6929 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6931 XtSetArg(args[0], XtNleftBitmap, None);
6933 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
6937 void AutoflipProc(w, event, prms, nprms)
6945 appData.autoFlipView = !appData.autoFlipView;
6947 if (appData.autoFlipView) {
6948 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6950 XtSetArg(args[0], XtNleftBitmap, None);
6952 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flip View"),
6956 void AutobsProc(w, event, prms, nprms)
6964 appData.autoObserve = !appData.autoObserve;
6966 if (appData.autoObserve) {
6967 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6969 XtSetArg(args[0], XtNleftBitmap, None);
6971 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
6975 void AutoraiseProc(w, event, prms, nprms)
6983 appData.autoRaiseBoard = !appData.autoRaiseBoard;
6985 if (appData.autoRaiseBoard) {
6986 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6988 XtSetArg(args[0], XtNleftBitmap, None);
6990 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Raise Board"),
6994 void AutosaveProc(w, event, prms, nprms)
7002 appData.autoSaveGames = !appData.autoSaveGames;
7004 if (appData.autoSaveGames) {
7005 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7007 XtSetArg(args[0], XtNleftBitmap, None);
7009 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
7013 void BlindfoldProc(w, event, prms, nprms)
7021 appData.blindfold = !appData.blindfold;
7023 if (appData.blindfold) {
7024 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7026 XtSetArg(args[0], XtNleftBitmap, None);
7028 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Blindfold"),
7031 DrawPosition(True, NULL);
7034 void TestLegalityProc(w, event, prms, nprms)
7042 appData.testLegality = !appData.testLegality;
7044 if (appData.testLegality) {
7045 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7047 XtSetArg(args[0], XtNleftBitmap, None);
7049 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Test Legality"),
7054 void FlashMovesProc(w, event, prms, nprms)
7062 if (appData.flashCount == 0) {
7063 appData.flashCount = 3;
7065 appData.flashCount = -appData.flashCount;
7068 if (appData.flashCount > 0) {
7069 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7071 XtSetArg(args[0], XtNleftBitmap, None);
7073 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flash Moves"),
7077 void FlipViewProc(w, event, prms, nprms)
7083 flipView = !flipView;
7084 DrawPosition(True, NULL);
7087 void GetMoveListProc(w, event, prms, nprms)
7095 appData.getMoveList = !appData.getMoveList;
7097 if (appData.getMoveList) {
7098 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7101 XtSetArg(args[0], XtNleftBitmap, None);
7103 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
7108 void HighlightDraggingProc(w, event, prms, nprms)
7116 appData.highlightDragging = !appData.highlightDragging;
7118 if (appData.highlightDragging) {
7119 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7121 XtSetArg(args[0], XtNleftBitmap, None);
7123 XtSetValues(XtNameToWidget(menuBarWidget,
7124 "menuOptions.Highlight Dragging"), args, 1);
7128 void HighlightLastMoveProc(w, event, prms, nprms)
7136 appData.highlightLastMove = !appData.highlightLastMove;
7138 if (appData.highlightLastMove) {
7139 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7141 XtSetArg(args[0], XtNleftBitmap, None);
7143 XtSetValues(XtNameToWidget(menuBarWidget,
7144 "menuOptions.Highlight Last Move"), args, 1);
7147 void IcsAlarmProc(w, event, prms, nprms)
7155 appData.icsAlarm = !appData.icsAlarm;
7157 if (appData.icsAlarm) {
7158 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7160 XtSetArg(args[0], XtNleftBitmap, None);
7162 XtSetValues(XtNameToWidget(menuBarWidget,
7163 "menuOptions.ICS Alarm"), args, 1);
7166 void MoveSoundProc(w, event, prms, nprms)
7174 appData.ringBellAfterMoves = !appData.ringBellAfterMoves;
7176 if (appData.ringBellAfterMoves) {
7177 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7179 XtSetArg(args[0], XtNleftBitmap, None);
7181 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
7186 void OldSaveStyleProc(w, event, prms, nprms)
7194 appData.oldSaveStyle = !appData.oldSaveStyle;
7196 if (appData.oldSaveStyle) {
7197 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7199 XtSetArg(args[0], XtNleftBitmap, None);
7201 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Old Save Style"),
7205 void PeriodicUpdatesProc(w, event, prms, nprms)
7213 PeriodicUpdatesEvent(!appData.periodicUpdates);
7215 if (appData.periodicUpdates) {
7216 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7218 XtSetArg(args[0], XtNleftBitmap, None);
7220 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Periodic Updates"),
7224 void PonderNextMoveProc(w, event, prms, nprms)
7232 PonderNextMoveEvent(!appData.ponderNextMove);
7234 if (appData.ponderNextMove) {
7235 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7237 XtSetArg(args[0], XtNleftBitmap, None);
7239 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Ponder Next Move"),
7243 void PopupExitMessageProc(w, event, prms, nprms)
7251 appData.popupExitMessage = !appData.popupExitMessage;
7253 if (appData.popupExitMessage) {
7254 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7256 XtSetArg(args[0], XtNleftBitmap, None);
7258 XtSetValues(XtNameToWidget(menuBarWidget,
7259 "menuOptions.Popup Exit Message"), args, 1);
7262 void PopupMoveErrorsProc(w, event, prms, nprms)
7270 appData.popupMoveErrors = !appData.popupMoveErrors;
7272 if (appData.popupMoveErrors) {
7273 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7275 XtSetArg(args[0], XtNleftBitmap, None);
7277 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Popup Move Errors"),
7281 void PremoveProc(w, event, prms, nprms)
7289 appData.premove = !appData.premove;
7291 if (appData.premove) {
7292 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7294 XtSetArg(args[0], XtNleftBitmap, None);
7296 XtSetValues(XtNameToWidget(menuBarWidget,
7297 "menuOptions.Premove"), args, 1);
7300 void QuietPlayProc(w, event, prms, nprms)
7308 appData.quietPlay = !appData.quietPlay;
7310 if (appData.quietPlay) {
7311 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7313 XtSetArg(args[0], XtNleftBitmap, None);
7315 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Quiet Play"),
7319 void ShowCoordsProc(w, event, prms, nprms)
7327 appData.showCoords = !appData.showCoords;
7329 if (appData.showCoords) {
7330 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7332 XtSetArg(args[0], XtNleftBitmap, None);
7334 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
7337 DrawPosition(True, NULL);
7340 void ShowThinkingProc(w, event, prms, nprms)
7348 appData.showThinking = !appData.showThinking; // [HGM] thinking: tken out of ShowThinkingEvent
7349 ShowThinkingEvent();
7351 // [HGM] thinking: currently no suc menu item; replaced by Hide Thinking (From Human)
7352 if (appData.showThinking) {
7353 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7355 XtSetArg(args[0], XtNleftBitmap, None);
7357 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Thinking"),
7362 void HideThinkingProc(w, event, prms, nprms)
7370 appData.hideThinkingFromHuman = !appData.hideThinkingFromHuman; // [HGM] thinking: tken out of ShowThinkingEvent
7371 ShowThinkingEvent();
7373 if (appData.hideThinkingFromHuman) {
7374 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7376 XtSetArg(args[0], XtNleftBitmap, None);
7378 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
7382 void InfoProc(w, event, prms, nprms)
7389 snprintf(buf, sizeof(buf), "xterm -e info --directory %s --directory . -f %s &",
7394 void ManProc(w, event, prms, nprms)
7402 if (nprms && *nprms > 0)
7406 snprintf(buf, sizeof(buf), "xterm -e man %s &", name);
7410 void HintProc(w, event, prms, nprms)
7419 void BookProc(w, event, prms, nprms)
7428 void AboutProc(w, event, prms, nprms)
7436 char *zippy = " (with Zippy code)";
7440 snprintf(buf, sizeof(buf), "%s%s\n\n%s\n%s\n%s\n\n%s%s\n%s",
7441 programVersion, zippy,
7442 "Copyright 1991 Digital Equipment Corporation",
7443 "Enhancements Copyright 1992-2009 Free Software Foundation",
7444 "Enhancements Copyright 2005 Alessandro Scotti",
7445 PRODUCT, " is free software and carries NO WARRANTY;",
7446 "see the file COPYING for more information.");
7447 ErrorPopUp(_("About XBoard"), buf, FALSE);
7450 void DebugProc(w, event, prms, nprms)
7456 appData.debugMode = !appData.debugMode;
7459 void AboutGameProc(w, event, prms, nprms)
7468 void NothingProc(w, event, prms, nprms)
7477 void Iconify(w, event, prms, nprms)
7486 XtSetArg(args[0], XtNiconic, True);
7487 XtSetValues(shellWidget, args, 1);
7490 void DisplayMessage(message, extMessage)
7491 char *message, *extMessage;
7498 snprintf(buf, sizeof(buf), "%s %s", message, extMessage);
7501 message = extMessage;
7504 XtSetArg(arg, XtNlabel, message);
7505 XtSetValues(messageWidget, &arg, 1);
7508 void DisplayTitle(text)
7513 char title[MSG_SIZ];
7516 if (text == NULL) text = "";
7518 if (appData.titleInWindow) {
7520 XtSetArg(args[i], XtNlabel, text); i++;
7521 XtSetValues(titleWidget, args, i);
7524 if (*text != NULLCHAR) {
7526 strcpy(title, text);
7527 } else if (appData.icsActive) {
7528 snprintf(icon, sizeof(icon), "%s", appData.icsHost);
7529 snprintf(title, sizeof(title),"%s: %s", programName, appData.icsHost);
7530 } else if (appData.cmailGameName[0] != NULLCHAR) {
7531 snprintf(icon, sizeof(icon), "%s", "CMail");
7532 snprintf(title,sizeof(title), "%s: %s", programName, "CMail");
7534 // [HGM] license: This stuff should really be done in back-end, but WinBoard already had a pop-up for it
7535 } else if (gameInfo.variant == VariantGothic) {
7536 strcpy(icon, programName);
7537 strcpy(title, GOTHIC);
7540 } else if (gameInfo.variant == VariantFalcon) {
7541 strcpy(icon, programName);
7542 strcpy(title, FALCON);
7544 } else if (appData.noChessProgram) {
7545 strcpy(icon, programName);
7546 strcpy(title, programName);
7548 strcpy(icon, first.tidy);
7549 snprintf(title,sizeof(title), "%s: %s", programName, first.tidy);
7552 XtSetArg(args[i], XtNiconName, (XtArgVal) icon); i++;
7553 XtSetArg(args[i], XtNtitle, (XtArgVal) title); i++;
7554 XtSetValues(shellWidget, args, i);
7558 void DisplayError(message, error)
7565 if (appData.debugMode || appData.matchMode) {
7566 fprintf(stderr, "%s: %s\n", programName, message);
7569 if (appData.debugMode || appData.matchMode) {
7570 fprintf(stderr, "%s: %s: %s\n",
7571 programName, message, strerror(error));
7573 snprintf(buf,sizeof(buf), "%s: %s", message, strerror(error));
7576 ErrorPopUp(_("Error"), message, FALSE);
7580 void DisplayMoveError(message)
7585 DrawPosition(FALSE, NULL);
7586 if (appData.debugMode || appData.matchMode) {
7587 fprintf(stderr, "%s: %s\n", programName, message);
7589 if (appData.popupMoveErrors) {
7590 ErrorPopUp(_("Error"), message, FALSE);
7592 DisplayMessage(message, "");
7597 void DisplayFatalError(message, error, status)
7603 errorExitStatus = status;
7605 fprintf(stderr, "%s: %s\n", programName, message);
7607 fprintf(stderr, "%s: %s: %s\n",
7608 programName, message, strerror(error));
7609 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
7612 if (appData.popupExitMessage && boardWidget && XtIsRealized(boardWidget)) {
7613 ErrorPopUp(status ? _("Fatal Error") : _("Exiting"), message, TRUE);
7619 void DisplayInformation(message)
7623 ErrorPopUp(_("Information"), message, TRUE);
7626 void DisplayNote(message)
7630 ErrorPopUp(_("Note"), message, FALSE);
7634 NullXErrorCheck(dpy, error_event)
7636 XErrorEvent *error_event;
7641 void DisplayIcsInteractionTitle(message)
7644 if (oldICSInteractionTitle == NULL) {
7645 /* Magic to find the old window title, adapted from vim */
7646 char *wina = getenv("WINDOWID");
7648 Window win = (Window) atoi(wina);
7649 Window root, parent, *children;
7650 unsigned int nchildren;
7651 int (*oldHandler)() = XSetErrorHandler(NullXErrorCheck);
7653 if (XFetchName(xDisplay, win, &oldICSInteractionTitle)) break;
7654 if (!XQueryTree(xDisplay, win, &root, &parent,
7655 &children, &nchildren)) break;
7656 if (children) XFree((void *)children);
7657 if (parent == root || parent == 0) break;
7660 XSetErrorHandler(oldHandler);
7662 if (oldICSInteractionTitle == NULL) {
7663 oldICSInteractionTitle = "xterm";
7666 printf("\033]0;%s\007", message);
7670 char pendingReplyPrefix[MSG_SIZ];
7671 ProcRef pendingReplyPR;
7673 void AskQuestionProc(w, event, prms, nprms)
7680 fprintf(stderr, _("AskQuestionProc needed 4 parameters, got %d\n"),
7684 AskQuestionEvent(prms[0], prms[1], prms[2], prms[3]);
7687 void AskQuestionPopDown()
7689 if (!askQuestionUp) return;
7690 XtPopdown(askQuestionShell);
7691 XtDestroyWidget(askQuestionShell);
7692 askQuestionUp = False;
7695 void AskQuestionReplyAction(w, event, prms, nprms)
7705 reply = XawDialogGetValueString(w = XtParent(w));
7706 strcpy(buf, pendingReplyPrefix);
7707 if (*buf) strcat(buf, " ");
7710 OutputToProcess(pendingReplyPR, buf, strlen(buf), &err);
7711 AskQuestionPopDown();
7713 if (err) DisplayFatalError(_("Error writing to chess program"), err, 0);
7716 void AskQuestionCallback(w, client_data, call_data)
7718 XtPointer client_data, call_data;
7723 XtSetArg(args[0], XtNlabel, &name);
7724 XtGetValues(w, args, 1);
7726 if (strcmp(name, _("cancel")) == 0) {
7727 AskQuestionPopDown();
7729 AskQuestionReplyAction(w, NULL, NULL, NULL);
7733 void AskQuestion(title, question, replyPrefix, pr)
7734 char *title, *question, *replyPrefix;
7738 Widget popup, layout, dialog, edit;
7744 strcpy(pendingReplyPrefix, replyPrefix);
7745 pendingReplyPR = pr;
7748 XtSetArg(args[i], XtNresizable, True); i++;
7749 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
7750 askQuestionShell = popup =
7751 XtCreatePopupShell(title, transientShellWidgetClass,
7752 shellWidget, args, i);
7755 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
7756 layoutArgs, XtNumber(layoutArgs));
7759 XtSetArg(args[i], XtNlabel, question); i++;
7760 XtSetArg(args[i], XtNvalue, ""); i++;
7761 XtSetArg(args[i], XtNborderWidth, 0); i++;
7762 dialog = XtCreateManagedWidget("question", dialogWidgetClass,
7765 XawDialogAddButton(dialog, _("enter"), AskQuestionCallback,
7766 (XtPointer) dialog);
7767 XawDialogAddButton(dialog, _("cancel"), AskQuestionCallback,
7768 (XtPointer) dialog);
7770 XtRealizeWidget(popup);
7771 CatchDeleteWindow(popup, "AskQuestionPopDown");
7773 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
7774 &x, &y, &win_x, &win_y, &mask);
7776 XtSetArg(args[0], XtNx, x - 10);
7777 XtSetArg(args[1], XtNy, y - 30);
7778 XtSetValues(popup, args, 2);
7780 XtPopup(popup, XtGrabExclusive);
7781 askQuestionUp = True;
7783 edit = XtNameToWidget(dialog, "*value");
7784 XtSetKeyboardFocus(popup, edit);
7792 if (*name == NULLCHAR) {
7794 } else if (strcmp(name, "$") == 0) {
7795 putc(BELLCHAR, stderr);
7798 snprintf(buf, sizeof(buf), "%s '%s' &", appData.soundProgram, name);
7806 PlaySound(appData.soundMove);
7812 PlaySound(appData.soundIcsWin);
7818 PlaySound(appData.soundIcsLoss);
7824 PlaySound(appData.soundIcsDraw);
7828 PlayIcsUnfinishedSound()
7830 PlaySound(appData.soundIcsUnfinished);
7836 PlaySound(appData.soundIcsAlarm);
7842 system("stty echo");
7848 system("stty -echo");
7852 Colorize(cc, continuation)
7857 int count, outCount, error;
7859 if (textColors[(int)cc].bg > 0) {
7860 if (textColors[(int)cc].fg > 0) {
7861 sprintf(buf, "\033[0;%d;%d;%dm", textColors[(int)cc].attr,
7862 textColors[(int)cc].fg, textColors[(int)cc].bg);
7864 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
7865 textColors[(int)cc].bg);
7868 if (textColors[(int)cc].fg > 0) {
7869 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
7870 textColors[(int)cc].fg);
7872 sprintf(buf, "\033[0;%dm", textColors[(int)cc].attr);
7875 count = strlen(buf);
7876 outCount = OutputToProcess(NoProc, buf, count, &error);
7877 if (outCount < count) {
7878 DisplayFatalError(_("Error writing to display"), error, 1);
7881 if (continuation) return;
7884 PlaySound(appData.soundShout);
7887 PlaySound(appData.soundSShout);
7890 PlaySound(appData.soundChannel1);
7893 PlaySound(appData.soundChannel);
7896 PlaySound(appData.soundKibitz);
7899 PlaySound(appData.soundTell);
7901 case ColorChallenge:
7902 PlaySound(appData.soundChallenge);
7905 PlaySound(appData.soundRequest);
7908 PlaySound(appData.soundSeek);
7919 return getpwuid(getuid())->pw_name;
7922 static char *ExpandPathName(path)
7925 static char static_buf[2000];
7926 char *d, *s, buf[2000];
7932 while (*s && isspace(*s))
7941 if (*(s+1) == '/') {
7942 strcpy(d, getpwuid(getuid())->pw_dir);
7947 *strchr(buf, '/') = 0;
7948 pwd = getpwnam(buf);
7951 fprintf(stderr, _("ERROR: Unknown user %s (in path %s)\n"),
7955 strcpy(d, pwd->pw_dir);
7956 strcat(d, strchr(s+1, '/'));
7967 static char host_name[MSG_SIZ];
7969 #if HAVE_GETHOSTNAME
7970 gethostname(host_name, MSG_SIZ);
7972 #else /* not HAVE_GETHOSTNAME */
7973 # if HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H
7974 sysinfo(SI_HOSTNAME, host_name, MSG_SIZ);
7976 # else /* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
7978 # endif/* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
7979 #endif /* not HAVE_GETHOSTNAME */
7982 XtIntervalId delayedEventTimerXID = 0;
7983 DelayedEventCallback delayedEventCallback = 0;
7988 delayedEventTimerXID = 0;
7989 delayedEventCallback();
7993 ScheduleDelayedEvent(cb, millisec)
7994 DelayedEventCallback cb; long millisec;
7996 delayedEventCallback = cb;
7997 delayedEventTimerXID =
7998 XtAppAddTimeOut(appContext, millisec,
7999 (XtTimerCallbackProc) FireDelayedEvent, (XtPointer) 0);
8002 DelayedEventCallback
8005 if (delayedEventTimerXID) {
8006 return delayedEventCallback;
8013 CancelDelayedEvent()
8015 if (delayedEventTimerXID) {
8016 XtRemoveTimeOut(delayedEventTimerXID);
8017 delayedEventTimerXID = 0;
8021 XtIntervalId loadGameTimerXID = 0;
8023 int LoadGameTimerRunning()
8025 return loadGameTimerXID != 0;
8028 int StopLoadGameTimer()
8030 if (loadGameTimerXID != 0) {
8031 XtRemoveTimeOut(loadGameTimerXID);
8032 loadGameTimerXID = 0;
8040 LoadGameTimerCallback(arg, id)
8044 loadGameTimerXID = 0;
8049 StartLoadGameTimer(millisec)
8053 XtAppAddTimeOut(appContext, millisec,
8054 (XtTimerCallbackProc) LoadGameTimerCallback,
8058 XtIntervalId analysisClockXID = 0;
8061 AnalysisClockCallback(arg, id)
8065 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile
8066 || appData.icsEngineAnalyze) { // [DM]
8067 AnalysisPeriodicEvent(0);
8068 StartAnalysisClock();
8073 StartAnalysisClock()
8076 XtAppAddTimeOut(appContext, 2000,
8077 (XtTimerCallbackProc) AnalysisClockCallback,
8081 XtIntervalId clockTimerXID = 0;
8083 int ClockTimerRunning()
8085 return clockTimerXID != 0;
8088 int StopClockTimer()
8090 if (clockTimerXID != 0) {
8091 XtRemoveTimeOut(clockTimerXID);
8100 ClockTimerCallback(arg, id)
8109 StartClockTimer(millisec)
8113 XtAppAddTimeOut(appContext, millisec,
8114 (XtTimerCallbackProc) ClockTimerCallback,
8119 DisplayTimerLabel(w, color, timer, highlight)
8128 Pixel foregroundOrWarningColor = timerForegroundPixel;
8131 && appData.lowTimeWarning
8132 && (timer / 1000) < appData.icsAlarmTime)
8134 foregroundOrWarningColor = lowTimeWarningColor;
8136 if (appData.clockMode) {
8137 sprintf(buf, "%s: %s", color, TimeString(timer));
8138 XtSetArg(args[0], XtNlabel, buf);
8140 sprintf(buf, "%s ", color);
8141 XtSetArg(args[0], XtNlabel, buf);
8146 XtSetArg(args[1], XtNbackground, foregroundOrWarningColor);
8147 XtSetArg(args[2], XtNforeground, timerBackgroundPixel);
8149 XtSetArg(args[1], XtNbackground, timerBackgroundPixel);
8150 XtSetArg(args[2], XtNforeground, foregroundOrWarningColor);
8153 XtSetValues(w, args, 3);
8157 DisplayWhiteClock(timeRemaining, highlight)
8163 if(appData.noGUI) return;
8164 DisplayTimerLabel(whiteTimerWidget, _("White"), timeRemaining, highlight);
8165 if (highlight && iconPixmap == bIconPixmap) {
8166 iconPixmap = wIconPixmap;
8167 XtSetArg(args[0], XtNiconPixmap, iconPixmap);
8168 XtSetValues(shellWidget, args, 1);
8173 DisplayBlackClock(timeRemaining, highlight)
8179 if(appData.noGUI) return;
8180 DisplayTimerLabel(blackTimerWidget, _("Black"), timeRemaining, highlight);
8181 if (highlight && iconPixmap == wIconPixmap) {
8182 iconPixmap = bIconPixmap;
8183 XtSetArg(args[0], XtNiconPixmap, iconPixmap);
8184 XtSetValues(shellWidget, args, 1);
8202 int StartChildProcess(cmdLine, dir, pr)
8209 int to_prog[2], from_prog[2];
8213 if (appData.debugMode) {
8214 fprintf(stderr, "StartChildProcess (dir=\"%s\") %s\n",dir, cmdLine);
8217 /* We do NOT feed the cmdLine to the shell; we just
8218 parse it into blank-separated arguments in the
8219 most simple-minded way possible.
8222 strcpy(buf, cmdLine);
8227 if (p == NULL) break;
8232 SetUpChildIO(to_prog, from_prog);
8234 if ((pid = fork()) == 0) {
8236 // [HGM] PSWBTM: made order resistant against case where fd of created pipe was 0 or 1
8237 close(to_prog[1]); // first close the unused pipe ends
8238 close(from_prog[0]);
8239 dup2(to_prog[0], 0); // to_prog was created first, nd is the only one to use 0 or 1
8240 dup2(from_prog[1], 1);
8241 if(to_prog[0] >= 2) close(to_prog[0]); // if 0 or 1, the dup2 already cosed the original
8242 close(from_prog[1]); // and closing again loses one of the pipes!
8243 if(fileno(stderr) >= 2) // better safe than sorry...
8244 dup2(1, fileno(stderr)); /* force stderr to the pipe */
8246 if (dir[0] != NULLCHAR && chdir(dir) != 0) {
8251 nice(appData.niceEngines); // [HGM] nice: adjust priority of engine proc
8253 execvp(argv[0], argv);
8255 /* If we get here, exec failed */
8260 /* Parent process */
8262 close(from_prog[1]);
8264 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8267 cp->fdFrom = from_prog[0];
8268 cp->fdTo = to_prog[1];
8273 // [HGM] kill: implement the 'hard killing' of AS's Winboard_x
8274 static RETSIGTYPE AlarmCallBack(int n)
8280 DestroyChildProcess(pr, signalType)
8284 ChildProc *cp = (ChildProc *) pr;
8286 if (cp->kind != CPReal) return;
8288 if (signalType == 10) { // [HGM] kill: if it does not terminate in 3 sec, kill
8289 signal(SIGALRM, AlarmCallBack);
8291 if(wait((int *) 0) == -1) { // process does not terminate on its own accord
8292 kill(cp->pid, SIGKILL); // kill it forcefully
8293 wait((int *) 0); // and wait again
8297 kill(cp->pid, signalType == 9 ? SIGKILL : SIGTERM); // [HGM] kill: use hard kill if so requested
8299 /* Process is exiting either because of the kill or because of
8300 a quit command sent by the backend; either way, wait for it to die.
8309 InterruptChildProcess(pr)
8312 ChildProc *cp = (ChildProc *) pr;
8314 if (cp->kind != CPReal) return;
8315 (void) kill(cp->pid, SIGINT); /* stop it thinking */
8318 int OpenTelnet(host, port, pr)
8323 char cmdLine[MSG_SIZ];
8325 if (port[0] == NULLCHAR) {
8326 snprintf(cmdLine, sizeof(cmdLine), "%s %s", appData.telnetProgram, host);
8328 snprintf(cmdLine,sizeof(cmdLine), "%s %s %s", appData.telnetProgram, host, port);
8330 return StartChildProcess(cmdLine, "", pr);
8333 int OpenTCP(host, port, pr)
8339 DisplayFatalError(_("Socket support is not configured in"), 0, 2);
8340 #else /* !OMIT_SOCKETS */
8342 struct sockaddr_in sa;
8344 unsigned short uport;
8347 if ((s = socket(AF_INET, SOCK_STREAM, 6)) < 0) {
8351 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
8352 sa.sin_family = AF_INET;
8353 sa.sin_addr.s_addr = INADDR_ANY;
8354 uport = (unsigned short) 0;
8355 sa.sin_port = htons(uport);
8356 if (bind(s, (struct sockaddr *) &sa, sizeof(struct sockaddr_in)) < 0) {
8360 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
8361 if (!(hp = gethostbyname(host))) {
8363 if (sscanf(host, "%d.%d.%d.%d", &b0, &b1, &b2, &b3) == 4) {
8364 hp = (struct hostent *) calloc(1, sizeof(struct hostent));
8365 hp->h_addrtype = AF_INET;
8367 hp->h_addr_list = (char **) calloc(2, sizeof(char *));
8368 hp->h_addr_list[0] = (char *) malloc(4);
8369 hp->h_addr_list[0][0] = b0;
8370 hp->h_addr_list[0][1] = b1;
8371 hp->h_addr_list[0][2] = b2;
8372 hp->h_addr_list[0][3] = b3;
8377 sa.sin_family = hp->h_addrtype;
8378 uport = (unsigned short) atoi(port);
8379 sa.sin_port = htons(uport);
8380 memcpy((char *) &sa.sin_addr, hp->h_addr, hp->h_length);
8382 if (connect(s, (struct sockaddr *) &sa,
8383 sizeof(struct sockaddr_in)) < 0) {
8387 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8394 #endif /* !OMIT_SOCKETS */
8399 int OpenCommPort(name, pr)
8406 fd = open(name, 2, 0);
8407 if (fd < 0) return errno;
8409 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8419 int OpenLoopback(pr)
8425 SetUpChildIO(to, from);
8427 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8430 cp->fdFrom = to[0]; /* note not from[0]; we are doing a loopback */
8437 int OpenRcmd(host, user, cmd, pr)
8438 char *host, *user, *cmd;
8441 DisplayFatalError(_("internal rcmd not implemented for Unix"), 0, 1);
8445 #define INPUT_SOURCE_BUF_SIZE 8192
8454 char buf[INPUT_SOURCE_BUF_SIZE];
8459 DoInputCallback(closure, source, xid)
8464 InputSource *is = (InputSource *) closure;
8469 if (is->lineByLine) {
8470 count = read(is->fd, is->unused,
8471 INPUT_SOURCE_BUF_SIZE - (is->unused - is->buf));
8473 (is->func)(is, is->closure, is->buf, count, count ? errno : 0);
8476 is->unused += count;
8478 while (p < is->unused) {
8479 q = memchr(p, '\n', is->unused - p);
8480 if (q == NULL) break;
8482 (is->func)(is, is->closure, p, q - p, 0);
8486 while (p < is->unused) {
8491 count = read(is->fd, is->buf, INPUT_SOURCE_BUF_SIZE);
8496 (is->func)(is, is->closure, is->buf, count, error);
8500 InputSourceRef AddInputSource(pr, lineByLine, func, closure)
8507 ChildProc *cp = (ChildProc *) pr;
8509 is = (InputSource *) calloc(1, sizeof(InputSource));
8510 is->lineByLine = lineByLine;
8514 is->fd = fileno(stdin);
8516 is->kind = cp->kind;
8517 is->fd = cp->fdFrom;
8520 is->unused = is->buf;
8523 is->xid = XtAppAddInput(appContext, is->fd,
8524 (XtPointer) (XtInputReadMask),
8525 (XtInputCallbackProc) DoInputCallback,
8527 is->closure = closure;
8528 return (InputSourceRef) is;
8532 RemoveInputSource(isr)
8535 InputSource *is = (InputSource *) isr;
8537 if (is->xid == 0) return;
8538 XtRemoveInput(is->xid);
8542 int OutputToProcess(pr, message, count, outError)
8548 ChildProc *cp = (ChildProc *) pr;
8552 outCount = fwrite(message, 1, count, stdout);
8554 outCount = write(cp->fdTo, message, count);
8564 /* Output message to process, with "ms" milliseconds of delay
8565 between each character. This is needed when sending the logon
8566 script to ICC, which for some reason doesn't like the
8567 instantaneous send. */
8568 int OutputToProcessDelayed(pr, message, count, outError, msdelay)
8575 ChildProc *cp = (ChildProc *) pr;
8580 r = write(cp->fdTo, message++, 1);
8593 /**** Animation code by Hugh Fisher, DCS, ANU.
8595 Known problem: if a window overlapping the board is
8596 moved away while a piece is being animated underneath,
8597 the newly exposed area won't be updated properly.
8598 I can live with this.
8600 Known problem: if you look carefully at the animation
8601 of pieces in mono mode, they are being drawn as solid
8602 shapes without interior detail while moving. Fixing
8603 this would be a major complication for minimal return.
8606 /* Masks for XPM pieces. Black and white pieces can have
8607 different shapes, but in the interest of retaining my
8608 sanity pieces must have the same outline on both light
8609 and dark squares, and all pieces must use the same
8610 background square colors/images. */
8613 CreateAnimMasks (pieceDepth)
8620 unsigned long plane;
8623 /* Need a bitmap just to get a GC with right depth */
8624 buf = XCreatePixmap(xDisplay, xBoardWindow,
8626 values.foreground = 1;
8627 values.background = 0;
8628 /* Don't use XtGetGC, not read only */
8629 maskGC = XCreateGC(xDisplay, buf,
8630 GCForeground | GCBackground, &values);
8631 XFreePixmap(xDisplay, buf);
8633 buf = XCreatePixmap(xDisplay, xBoardWindow,
8634 squareSize, squareSize, pieceDepth);
8635 values.foreground = XBlackPixel(xDisplay, xScreen);
8636 values.background = XWhitePixel(xDisplay, xScreen);
8637 bufGC = XCreateGC(xDisplay, buf,
8638 GCForeground | GCBackground, &values);
8640 for (piece = WhitePawn; piece <= BlackKing; piece++) {
8641 /* Begin with empty mask */
8642 xpmMask[piece] = XCreatePixmap(xDisplay, xBoardWindow,
8643 squareSize, squareSize, 1);
8644 XSetFunction(xDisplay, maskGC, GXclear);
8645 XFillRectangle(xDisplay, xpmMask[piece], maskGC,
8646 0, 0, squareSize, squareSize);
8648 /* Take a copy of the piece */
8653 XSetFunction(xDisplay, bufGC, GXcopy);
8654 XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % (int)BlackPawn],
8656 0, 0, squareSize, squareSize, 0, 0);
8658 /* XOR the background (light) over the piece */
8659 XSetFunction(xDisplay, bufGC, GXxor);
8661 XCopyArea(xDisplay, xpmLightSquare, buf, bufGC,
8662 0, 0, squareSize, squareSize, 0, 0);
8664 XSetForeground(xDisplay, bufGC, lightSquareColor);
8665 XFillRectangle(xDisplay, buf, bufGC, 0, 0, squareSize, squareSize);
8668 /* We now have an inverted piece image with the background
8669 erased. Construct mask by just selecting all the non-zero
8670 pixels - no need to reconstruct the original image. */
8671 XSetFunction(xDisplay, maskGC, GXor);
8673 /* Might be quicker to download an XImage and create bitmap
8674 data from it rather than this N copies per piece, but it
8675 only takes a fraction of a second and there is a much
8676 longer delay for loading the pieces. */
8677 for (n = 0; n < pieceDepth; n ++) {
8678 XCopyPlane(xDisplay, buf, xpmMask[piece], maskGC,
8679 0, 0, squareSize, squareSize,
8685 XFreePixmap(xDisplay, buf);
8686 XFreeGC(xDisplay, bufGC);
8687 XFreeGC(xDisplay, maskGC);
8691 InitAnimState (anim, info)
8693 XWindowAttributes * info;
8698 /* Each buffer is square size, same depth as window */
8699 anim->saveBuf = XCreatePixmap(xDisplay, xBoardWindow,
8700 squareSize, squareSize, info->depth);
8701 anim->newBuf = XCreatePixmap(xDisplay, xBoardWindow,
8702 squareSize, squareSize, info->depth);
8704 /* Create a plain GC for blitting */
8705 mask = GCForeground | GCBackground | GCFunction |
8706 GCPlaneMask | GCGraphicsExposures;
8707 values.foreground = XBlackPixel(xDisplay, xScreen);
8708 values.background = XWhitePixel(xDisplay, xScreen);
8709 values.function = GXcopy;
8710 values.plane_mask = AllPlanes;
8711 values.graphics_exposures = False;
8712 anim->blitGC = XCreateGC(xDisplay, xBoardWindow, mask, &values);
8714 /* Piece will be copied from an existing context at
8715 the start of each new animation/drag. */
8716 anim->pieceGC = XCreateGC(xDisplay, xBoardWindow, 0, &values);
8718 /* Outline will be a read-only copy of an existing */
8719 anim->outlineGC = None;
8725 static int done = 0;
8726 XWindowAttributes info;
8730 XGetWindowAttributes(xDisplay, xBoardWindow, &info);
8732 InitAnimState(&game, &info);
8733 InitAnimState(&player, &info);
8735 /* For XPM pieces, we need bitmaps to use as masks. */
8737 CreateAnimMasks(info.depth);
8742 static Boolean frameWaiting;
8744 static RETSIGTYPE FrameAlarm (sig)
8747 frameWaiting = False;
8748 /* In case System-V style signals. Needed?? */
8749 signal(SIGALRM, FrameAlarm);
8756 struct itimerval delay;
8758 XSync(xDisplay, False);
8761 frameWaiting = True;
8762 signal(SIGALRM, FrameAlarm);
8763 delay.it_interval.tv_sec =
8764 delay.it_value.tv_sec = time / 1000;
8765 delay.it_interval.tv_usec =
8766 delay.it_value.tv_usec = (time % 1000) * 1000;
8767 setitimer(ITIMER_REAL, &delay, NULL);
8769 /* Ugh -- busy-wait! --tpm */
8770 while (frameWaiting);
8772 while (frameWaiting) pause();
8774 delay.it_interval.tv_sec = delay.it_value.tv_sec = 0;
8775 delay.it_interval.tv_usec = delay.it_value.tv_usec = 0;
8776 setitimer(ITIMER_REAL, &delay, NULL);
8786 XSync(xDisplay, False);
8788 usleep(time * 1000);
8793 /* Convert board position to corner of screen rect and color */
8796 ScreenSquare(column, row, pt, color)
8797 int column; int row; XPoint * pt; int * color;
8800 pt->x = lineGap + ((BOARD_WIDTH-1)-column) * (squareSize + lineGap);
8801 pt->y = lineGap + row * (squareSize + lineGap);
8803 pt->x = lineGap + column * (squareSize + lineGap);
8804 pt->y = lineGap + ((BOARD_HEIGHT-1)-row) * (squareSize + lineGap);
8806 *color = SquareColor(row, column);
8809 /* Convert window coords to square */
8812 BoardSquare(x, y, column, row)
8813 int x; int y; int * column; int * row;
8815 *column = EventToSquare(x, BOARD_WIDTH);
8816 if (flipView && *column >= 0)
8817 *column = BOARD_WIDTH - 1 - *column;
8818 *row = EventToSquare(y, BOARD_HEIGHT);
8819 if (!flipView && *row >= 0)
8820 *row = BOARD_HEIGHT - 1 - *row;
8825 #undef Max /* just in case */
8827 #define Max(a, b) ((a) > (b) ? (a) : (b))
8828 #define Min(a, b) ((a) < (b) ? (a) : (b))
8831 SetRect(rect, x, y, width, height)
8832 XRectangle * rect; int x; int y; int width; int height;
8836 rect->width = width;
8837 rect->height = height;
8840 /* Test if two frames overlap. If they do, return
8841 intersection rect within old and location of
8842 that rect within new. */
8845 Intersect(old, new, size, area, pt)
8846 XPoint * old; XPoint * new;
8847 int size; XRectangle * area; XPoint * pt;
8849 if (old->x > new->x + size || new->x > old->x + size ||
8850 old->y > new->y + size || new->y > old->y + size) {
8853 SetRect(area, Max(new->x - old->x, 0), Max(new->y - old->y, 0),
8854 size - abs(old->x - new->x), size - abs(old->y - new->y));
8855 pt->x = Max(old->x - new->x, 0);
8856 pt->y = Max(old->y - new->y, 0);
8861 /* For two overlapping frames, return the rect(s)
8862 in the old that do not intersect with the new. */
8865 CalcUpdateRects(old, new, size, update, nUpdates)
8866 XPoint * old; XPoint * new; int size;
8867 XRectangle update[]; int * nUpdates;
8871 /* If old = new (shouldn't happen) then nothing to draw */
8872 if (old->x == new->x && old->y == new->y) {
8876 /* Work out what bits overlap. Since we know the rects
8877 are the same size we don't need a full intersect calc. */
8879 /* Top or bottom edge? */
8880 if (new->y > old->y) {
8881 SetRect(&(update[count]), old->x, old->y, size, new->y - old->y);
8883 } else if (old->y > new->y) {
8884 SetRect(&(update[count]), old->x, old->y + size - (old->y - new->y),
8885 size, old->y - new->y);
8888 /* Left or right edge - don't overlap any update calculated above. */
8889 if (new->x > old->x) {
8890 SetRect(&(update[count]), old->x, Max(new->y, old->y),
8891 new->x - old->x, size - abs(new->y - old->y));
8893 } else if (old->x > new->x) {
8894 SetRect(&(update[count]), new->x + size, Max(new->y, old->y),
8895 old->x - new->x, size - abs(new->y - old->y));
8902 /* Generate a series of frame coords from start->mid->finish.
8903 The movement rate doubles until the half way point is
8904 reached, then halves back down to the final destination,
8905 which gives a nice slow in/out effect. The algorithmn
8906 may seem to generate too many intermediates for short
8907 moves, but remember that the purpose is to attract the
8908 viewers attention to the piece about to be moved and
8909 then to where it ends up. Too few frames would be less
8913 Tween(start, mid, finish, factor, frames, nFrames)
8914 XPoint * start; XPoint * mid;
8915 XPoint * finish; int factor;
8916 XPoint frames[]; int * nFrames;
8918 int fraction, n, count;
8922 /* Slow in, stepping 1/16th, then 1/8th, ... */
8924 for (n = 0; n < factor; n++)
8926 for (n = 0; n < factor; n++) {
8927 frames[count].x = start->x + (mid->x - start->x) / fraction;
8928 frames[count].y = start->y + (mid->y - start->y) / fraction;
8930 fraction = fraction / 2;
8934 frames[count] = *mid;
8937 /* Slow out, stepping 1/2, then 1/4, ... */
8939 for (n = 0; n < factor; n++) {
8940 frames[count].x = finish->x - (finish->x - mid->x) / fraction;
8941 frames[count].y = finish->y - (finish->y - mid->y) / fraction;
8943 fraction = fraction * 2;
8948 /* Draw a piece on the screen without disturbing what's there */
8951 SelectGCMask(piece, clip, outline, mask)
8952 ChessSquare piece; GC * clip; GC * outline; Pixmap * mask;
8956 /* Bitmap for piece being moved. */
8957 if (appData.monoMode) {
8958 *mask = *pieceToSolid(piece);
8959 } else if (useImages) {
8961 *mask = xpmMask[piece];
8963 *mask = ximMaskPm[piece%(int)BlackPawn];
8966 *mask = *pieceToSolid(piece);
8969 /* GC for piece being moved. Square color doesn't matter, but
8970 since it gets modified we make a copy of the original. */
8972 if (appData.monoMode)
8977 if (appData.monoMode)
8982 XCopyGC(xDisplay, source, 0xFFFFFFFF, *clip);
8984 /* Outline only used in mono mode and is not modified */
8986 *outline = bwPieceGC;
8988 *outline = wbPieceGC;
8992 OverlayPiece(piece, clip, outline, dest)
8993 ChessSquare piece; GC clip; GC outline; Drawable dest;
8998 /* Draw solid rectangle which will be clipped to shape of piece */
8999 XFillRectangle(xDisplay, dest, clip,
9000 0, 0, squareSize, squareSize);
9001 if (appData.monoMode)
9002 /* Also draw outline in contrasting color for black
9003 on black / white on white cases */
9004 XCopyPlane(xDisplay, *pieceToOutline(piece), dest, outline,
9005 0, 0, squareSize, squareSize, 0, 0, 1);
9007 /* Copy the piece */
9012 XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % (int)BlackPawn],
9014 0, 0, squareSize, squareSize,
9019 /* Animate the movement of a single piece */
9022 BeginAnimation(anim, piece, startColor, start)
9030 /* The old buffer is initialised with the start square (empty) */
9031 BlankSquare(0, 0, startColor, EmptySquare, anim->saveBuf);
9032 anim->prevFrame = *start;
9034 /* The piece will be drawn using its own bitmap as a matte */
9035 SelectGCMask(piece, &anim->pieceGC, &anim->outlineGC, &mask);
9036 XSetClipMask(xDisplay, anim->pieceGC, mask);
9040 AnimationFrame(anim, frame, piece)
9045 XRectangle updates[4];
9050 /* Save what we are about to draw into the new buffer */
9051 XCopyArea(xDisplay, xBoardWindow, anim->newBuf, anim->blitGC,
9052 frame->x, frame->y, squareSize, squareSize,
9055 /* Erase bits of the previous frame */
9056 if (Intersect(&anim->prevFrame, frame, squareSize, &overlap, &pt)) {
9057 /* Where the new frame overlapped the previous,
9058 the contents in newBuf are wrong. */
9059 XCopyArea(xDisplay, anim->saveBuf, anim->newBuf, anim->blitGC,
9060 overlap.x, overlap.y,
9061 overlap.width, overlap.height,
9063 /* Repaint the areas in the old that don't overlap new */
9064 CalcUpdateRects(&anim->prevFrame, frame, squareSize, updates, &count);
9065 for (i = 0; i < count; i++)
9066 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9067 updates[i].x - anim->prevFrame.x,
9068 updates[i].y - anim->prevFrame.y,
9069 updates[i].width, updates[i].height,
9070 updates[i].x, updates[i].y);
9072 /* Easy when no overlap */
9073 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9074 0, 0, squareSize, squareSize,
9075 anim->prevFrame.x, anim->prevFrame.y);
9078 /* Save this frame for next time round */
9079 XCopyArea(xDisplay, anim->newBuf, anim->saveBuf, anim->blitGC,
9080 0, 0, squareSize, squareSize,
9082 anim->prevFrame = *frame;
9084 /* Draw piece over original screen contents, not current,
9085 and copy entire rect. Wipes out overlapping piece images. */
9086 OverlayPiece(piece, anim->pieceGC, anim->outlineGC, anim->newBuf);
9087 XCopyArea(xDisplay, anim->newBuf, xBoardWindow, anim->blitGC,
9088 0, 0, squareSize, squareSize,
9089 frame->x, frame->y);
9093 EndAnimation (anim, finish)
9097 XRectangle updates[4];
9102 /* The main code will redraw the final square, so we
9103 only need to erase the bits that don't overlap. */
9104 if (Intersect(&anim->prevFrame, finish, squareSize, &overlap, &pt)) {
9105 CalcUpdateRects(&anim->prevFrame, finish, squareSize, updates, &count);
9106 for (i = 0; i < count; i++)
9107 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9108 updates[i].x - anim->prevFrame.x,
9109 updates[i].y - anim->prevFrame.y,
9110 updates[i].width, updates[i].height,
9111 updates[i].x, updates[i].y);
9113 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9114 0, 0, squareSize, squareSize,
9115 anim->prevFrame.x, anim->prevFrame.y);
9120 FrameSequence(anim, piece, startColor, start, finish, frames, nFrames)
9122 ChessSquare piece; int startColor;
9123 XPoint * start; XPoint * finish;
9124 XPoint frames[]; int nFrames;
9128 BeginAnimation(anim, piece, startColor, start);
9129 for (n = 0; n < nFrames; n++) {
9130 AnimationFrame(anim, &(frames[n]), piece);
9131 FrameDelay(appData.animSpeed);
9133 EndAnimation(anim, finish);
9136 /* Main control logic for deciding what to animate and how */
9139 AnimateMove(board, fromX, fromY, toX, toY)
9148 XPoint start, finish, mid;
9149 XPoint frames[kFactor * 2 + 1];
9150 int nFrames, startColor, endColor;
9152 /* Are we animating? */
9153 if (!appData.animate || appData.blindfold)
9156 if (fromY < 0 || fromX < 0 || toX < 0 || toY < 0) return;
9157 piece = board[fromY][fromX];
9158 if (piece >= EmptySquare) return;
9163 hop = (piece == WhiteKnight || piece == BlackKnight);
9166 if (appData.debugMode) {
9167 fprintf(debugFP, hop ? _("AnimateMove: piece %d hops from %d,%d to %d,%d \n") :
9168 _("AnimateMove: piece %d slides from %d,%d to %d,%d \n"),
9169 piece, fromX, fromY, toX, toY); }
9171 ScreenSquare(fromX, fromY, &start, &startColor);
9172 ScreenSquare(toX, toY, &finish, &endColor);
9175 /* Knight: make diagonal movement then straight */
9176 if (abs(toY - fromY) < abs(toX - fromX)) {
9177 mid.x = start.x + (finish.x - start.x) / 2;
9181 mid.y = start.y + (finish.y - start.y) / 2;
9184 mid.x = start.x + (finish.x - start.x) / 2;
9185 mid.y = start.y + (finish.y - start.y) / 2;
9188 /* Don't use as many frames for very short moves */
9189 if (abs(toY - fromY) + abs(toX - fromX) <= 2)
9190 Tween(&start, &mid, &finish, kFactor - 1, frames, &nFrames);
9192 Tween(&start, &mid, &finish, kFactor, frames, &nFrames);
9193 FrameSequence(&game, piece, startColor, &start, &finish, frames, nFrames);
9195 /* Be sure end square is redrawn */
9196 damage[toY][toX] = True;
9200 DragPieceBegin(x, y)
9203 int boardX, boardY, color;
9206 /* Are we animating? */
9207 if (!appData.animateDragging || appData.blindfold)
9210 /* Figure out which square we start in and the
9211 mouse position relative to top left corner. */
9212 BoardSquare(x, y, &boardX, &boardY);
9213 player.startBoardX = boardX;
9214 player.startBoardY = boardY;
9215 ScreenSquare(boardX, boardY, &corner, &color);
9216 player.startSquare = corner;
9217 player.startColor = color;
9219 /* Start from exactly where the piece is. This can be confusing
9220 if you start dragging far from the center of the square; most
9221 or all of the piece can be over a different square from the one
9222 the mouse pointer is in. */
9223 player.mouseDelta.x = x - corner.x;
9224 player.mouseDelta.y = y - corner.y;
9226 /* As soon as we start dragging, the piece will jump slightly to
9227 be centered over the mouse pointer. */
9228 player.mouseDelta.x = squareSize/2;
9229 player.mouseDelta.y = squareSize/2;
9231 /* Initialise animation */
9232 player.dragPiece = PieceForSquare(boardX, boardY);
9234 if (player.dragPiece >= 0 && player.dragPiece < EmptySquare) {
9235 player.dragActive = True;
9236 BeginAnimation(&player, player.dragPiece, color, &corner);
9237 /* Mark this square as needing to be redrawn. Note that
9238 we don't remove the piece though, since logically (ie
9239 as seen by opponent) the move hasn't been made yet. */
9240 if(boardX == BOARD_RGHT+1 && PieceForSquare(boardX-1, boardY) > 1 ||
9241 boardX == BOARD_LEFT-2 && PieceForSquare(boardX+1, boardY) > 1)
9242 XCopyArea(xDisplay, xBoardWindow, player.saveBuf, player.blitGC,
9243 corner.x, corner.y, squareSize, squareSize,
9244 0, 0); // [HGM] zh: unstack in stead of grab
9245 damage[boardY][boardX] = True;
9247 player.dragActive = False;
9257 /* Are we animating? */
9258 if (!appData.animateDragging || appData.blindfold)
9262 if (! player.dragActive)
9264 /* Move piece, maintaining same relative position
9265 of mouse within square */
9266 corner.x = x - player.mouseDelta.x;
9267 corner.y = y - player.mouseDelta.y;
9268 AnimationFrame(&player, &corner, player.dragPiece);
9270 if (appData.highlightDragging) {
9272 BoardSquare(x, y, &boardX, &boardY);
9273 SetHighlights(fromX, fromY, boardX, boardY);
9282 int boardX, boardY, color;
9285 /* Are we animating? */
9286 if (!appData.animateDragging || appData.blindfold)
9290 if (! player.dragActive)
9292 /* Last frame in sequence is square piece is
9293 placed on, which may not match mouse exactly. */
9294 BoardSquare(x, y, &boardX, &boardY);
9295 ScreenSquare(boardX, boardY, &corner, &color);
9296 EndAnimation(&player, &corner);
9298 /* Be sure end square is redrawn */
9299 damage[boardY][boardX] = True;
9301 /* This prevents weird things happening with fast successive
9302 clicks which on my Sun at least can cause motion events
9303 without corresponding press/release. */
9304 player.dragActive = False;
9307 /* Handle expose event while piece being dragged */
9312 if (!player.dragActive || appData.blindfold)
9315 /* What we're doing: logically, the move hasn't been made yet,
9316 so the piece is still in it's original square. But visually
9317 it's being dragged around the board. So we erase the square
9318 that the piece is on and draw it at the last known drag point. */
9319 BlankSquare(player.startSquare.x, player.startSquare.y,
9320 player.startColor, EmptySquare, xBoardWindow);
9321 AnimationFrame(&player, &player.prevFrame, player.dragPiece);
9322 damage[player.startBoardY][player.startBoardX] = TRUE;
9326 SetProgramStats( FrontEndProgramStats * stats )
9329 // [HGM] done, but perhaps backend should call this directly?
9330 EngineOutputUpdate( stats );