2 * xboard.c -- X front end for XBoard
4 * Copyright 1991 by Digital Equipment Corporation, Maynard,
7 * Enhancements Copyright 1992-2001, 2002, 2003, 2004, 2005, 2006,
8 * 2007, 2008, 2009 Free Software Foundation, Inc.
10 * The following terms apply to Digital Equipment Corporation's copyright
12 * ------------------------------------------------------------------------
15 * Permission to use, copy, modify, and distribute this software and its
16 * documentation for any purpose and without fee is hereby granted,
17 * provided that the above copyright notice appear in all copies and that
18 * both that copyright notice and this permission notice appear in
19 * supporting documentation, and that the name of Digital not be
20 * used in advertising or publicity pertaining to distribution of the
21 * software without specific, written prior permission.
23 * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
24 * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
25 * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
26 * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
27 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
28 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
30 * ------------------------------------------------------------------------
32 * The following terms apply to the enhanced version of XBoard
33 * distributed by the Free Software Foundation:
34 * ------------------------------------------------------------------------
36 * GNU XBoard is free software: you can redistribute it and/or modify
37 * it under the terms of the GNU General Public License as published by
38 * the Free Software Foundation, either version 3 of the License, or (at
39 * your option) any later version.
41 * GNU XBoard is distributed in the hope that it will be useful, but
42 * WITHOUT ANY WARRANTY; without even the implied warranty of
43 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
44 * General Public License for more details.
46 * You should have received a copy of the GNU General Public License
47 * along with this program. If not, see http://www.gnu.org/licenses/. *
49 *------------------------------------------------------------------------
50 ** See the file ChangeLog for a revision history. */
58 #include <sys/types.h>
63 # if HAVE_SYS_SOCKET_H
64 # include <sys/socket.h>
65 # include <netinet/in.h>
67 # else /* not HAVE_SYS_SOCKET_H */
68 # if HAVE_LAN_SOCKET_H
69 # include <lan/socket.h>
71 # include <lan/netdb.h>
72 # else /* not HAVE_LAN_SOCKET_H */
73 # define OMIT_SOCKETS 1
74 # endif /* not HAVE_LAN_SOCKET_H */
75 # endif /* not HAVE_SYS_SOCKET_H */
76 #endif /* !OMIT_SOCKETS */
81 #else /* not STDC_HEADERS */
82 extern char *getenv();
85 # else /* not HAVE_STRING_H */
87 # endif /* not HAVE_STRING_H */
88 #endif /* not STDC_HEADERS */
91 # include <sys/fcntl.h>
92 #else /* not HAVE_SYS_FCNTL_H */
95 # endif /* HAVE_FCNTL_H */
96 #endif /* not HAVE_SYS_FCNTL_H */
98 #if HAVE_SYS_SYSTEMINFO_H
99 # include <sys/systeminfo.h>
100 #endif /* HAVE_SYS_SYSTEMINFO_H */
102 #if TIME_WITH_SYS_TIME
103 # include <sys/time.h>
107 # include <sys/time.h>
118 # include <sys/wait.h>
123 # define NAMLEN(dirent) strlen((dirent)->d_name)
124 # define HAVE_DIR_STRUCT
126 # define dirent direct
127 # define NAMLEN(dirent) (dirent)->d_namlen
129 # include <sys/ndir.h>
130 # define HAVE_DIR_STRUCT
133 # include <sys/dir.h>
134 # define HAVE_DIR_STRUCT
138 # define HAVE_DIR_STRUCT
142 #include <X11/Intrinsic.h>
143 #include <X11/StringDefs.h>
144 #include <X11/Shell.h>
145 #include <X11/cursorfont.h>
146 #include <X11/Xatom.h>
148 #include <X11/Xaw3d/Dialog.h>
149 #include <X11/Xaw3d/Form.h>
150 #include <X11/Xaw3d/List.h>
151 #include <X11/Xaw3d/Label.h>
152 #include <X11/Xaw3d/SimpleMenu.h>
153 #include <X11/Xaw3d/SmeBSB.h>
154 #include <X11/Xaw3d/SmeLine.h>
155 #include <X11/Xaw3d/Box.h>
156 #include <X11/Xaw3d/MenuButton.h>
157 #include <X11/Xaw3d/Text.h>
158 #include <X11/Xaw3d/AsciiText.h>
160 #include <X11/Xaw/Dialog.h>
161 #include <X11/Xaw/Form.h>
162 #include <X11/Xaw/List.h>
163 #include <X11/Xaw/Label.h>
164 #include <X11/Xaw/SimpleMenu.h>
165 #include <X11/Xaw/SmeBSB.h>
166 #include <X11/Xaw/SmeLine.h>
167 #include <X11/Xaw/Box.h>
168 #include <X11/Xaw/MenuButton.h>
169 #include <X11/Xaw/Text.h>
170 #include <X11/Xaw/AsciiText.h>
173 // [HGM] bitmaps: put before incuding the bitmaps / pixmaps, to know how many piece types there are.
178 #include "pixmaps/pixmaps.h"
179 #define IMAGE_EXT "xpm"
181 #define IMAGE_EXT "xim"
182 #include "bitmaps/bitmaps.h"
185 #include "bitmaps/icon_white.bm"
186 #include "bitmaps/icon_black.bm"
187 #include "bitmaps/checkmark.bm"
189 #include "frontend.h"
194 #include "xgamelist.h"
195 #include "xhistory.h"
196 #include "xedittags.h"
199 // must be moved to xengineoutput.h
201 void EngineOutputProc P((Widget w, XEvent *event,
202 String *prms, Cardinal *nprms));
204 void EngineOutputPopDown();
211 #define usleep(t) _sleep2(((t)+500)/1000)
215 # define _(s) gettext (s)
216 # define N_(s) gettext_noop (s)
232 int main P((int argc, char **argv));
233 RETSIGTYPE CmailSigHandler P((int sig));
234 RETSIGTYPE IntSigHandler P((int sig));
235 void CreateGCs P((void));
236 void CreateXIMPieces P((void));
237 void CreateXPMPieces P((void));
238 void CreatePieces P((void));
239 void CreatePieceMenus P((void));
240 Widget CreateMenuBar P((Menu *mb));
241 Widget CreateButtonBar P ((MenuItem *mi));
242 char *FindFont P((char *pattern, int targetPxlSize));
243 void PieceMenuPopup P((Widget w, XEvent *event,
244 String *params, Cardinal *num_params));
245 static void PieceMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
246 static void DropMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
247 void ReadBitmap P((Pixmap *pm, String name, unsigned char bits[],
248 u_int wreq, u_int hreq));
249 void CreateGrid P((void));
250 int EventToSquare P((int x, int limit));
251 void DrawSquare P((int row, int column, ChessSquare piece, int do_flash));
252 void EventProc P((Widget widget, caddr_t unused, XEvent *event));
253 void HandleUserMove P((Widget w, XEvent *event,
254 String *prms, Cardinal *nprms));
255 void AnimateUserMove P((Widget w, XEvent * event,
256 String * params, Cardinal * nParams));
257 void WhiteClock P((Widget w, XEvent *event,
258 String *prms, Cardinal *nprms));
259 void BlackClock P((Widget w, XEvent *event,
260 String *prms, Cardinal *nprms));
261 void DrawPositionProc P((Widget w, XEvent *event,
262 String *prms, Cardinal *nprms));
263 void XDrawPosition P((Widget w, /*Boolean*/int repaint,
265 void CommentPopUp P((char *title, char *label));
266 void CommentPopDown P((void));
267 void CommentCallback P((Widget w, XtPointer client_data,
268 XtPointer call_data));
269 void ICSInputBoxPopUp P((void));
270 void ICSInputBoxPopDown P((void));
271 void FileNamePopUp P((char *label, char *def,
272 FileProc proc, char *openMode));
273 void FileNamePopDown P((void));
274 void FileNameCallback P((Widget w, XtPointer client_data,
275 XtPointer call_data));
276 void FileNameAction P((Widget w, XEvent *event,
277 String *prms, Cardinal *nprms));
278 void AskQuestionReplyAction P((Widget w, XEvent *event,
279 String *prms, Cardinal *nprms));
280 void AskQuestionProc P((Widget w, XEvent *event,
281 String *prms, Cardinal *nprms));
282 void AskQuestionPopDown P((void));
283 void PromotionPopUp P((void));
284 void PromotionPopDown P((void));
285 void PromotionCallback P((Widget w, XtPointer client_data,
286 XtPointer call_data));
287 void EditCommentPopDown P((void));
288 void EditCommentCallback P((Widget w, XtPointer client_data,
289 XtPointer call_data));
290 void SelectCommand P((Widget w, XtPointer client_data, XtPointer call_data));
291 void ResetProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
292 void LoadGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
293 void LoadNextGameProc P((Widget w, XEvent *event, String *prms,
295 void LoadPrevGameProc P((Widget w, XEvent *event, String *prms,
297 void ReloadGameProc P((Widget w, XEvent *event, String *prms,
299 void LoadPositionProc P((Widget w, XEvent *event,
300 String *prms, Cardinal *nprms));
301 void LoadNextPositionProc P((Widget w, XEvent *event, String *prms,
303 void LoadPrevPositionProc P((Widget w, XEvent *event, String *prms,
305 void ReloadPositionProc P((Widget w, XEvent *event, String *prms,
307 void CopyPositionProc P((Widget w, XEvent *event, String *prms,
309 void PastePositionProc P((Widget w, XEvent *event, String *prms,
311 void CopyGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
312 void PasteGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
313 void SaveGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
314 void SavePositionProc P((Widget w, XEvent *event,
315 String *prms, Cardinal *nprms));
316 void MailMoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
317 void ReloadCmailMsgProc P((Widget w, XEvent *event, String *prms,
319 void QuitProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
320 void PauseProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
321 void MachineBlackProc P((Widget w, XEvent *event, String *prms,
323 void MachineWhiteProc P((Widget w, XEvent *event,
324 String *prms, Cardinal *nprms));
325 void AnalyzeModeProc P((Widget w, XEvent *event,
326 String *prms, Cardinal *nprms));
327 void AnalyzeFileProc P((Widget w, XEvent *event,
328 String *prms, Cardinal *nprms));
329 void TwoMachinesProc P((Widget w, XEvent *event, String *prms,
331 void IcsClientProc P((Widget w, XEvent *event, String *prms,
333 void EditGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
334 void EditPositionProc P((Widget w, XEvent *event,
335 String *prms, Cardinal *nprms));
336 void TrainingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
337 void EditCommentProc P((Widget w, XEvent *event,
338 String *prms, Cardinal *nprms));
339 void IcsInputBoxProc P((Widget w, XEvent *event,
340 String *prms, Cardinal *nprms));
341 void AcceptProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
342 void DeclineProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
343 void RematchProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
344 void CallFlagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
345 void DrawProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
346 void AbortProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
347 void AdjournProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
348 void ResignProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
349 void AdjuWhiteProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
350 void AdjuBlackProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
351 void AdjuDrawProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
352 void EnterKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
353 void StopObservingProc P((Widget w, XEvent *event, String *prms,
355 void StopExaminingProc P((Widget w, XEvent *event, String *prms,
357 void BackwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
358 void ForwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
359 void ToStartProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
360 void ToEndProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
361 void RevertProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
362 void TruncateGameProc P((Widget w, XEvent *event, String *prms,
364 void RetractMoveProc P((Widget w, XEvent *event, String *prms,
366 void MoveNowProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
367 void AlwaysQueenProc P((Widget w, XEvent *event, String *prms,
369 void AnimateDraggingProc P((Widget w, XEvent *event, String *prms,
371 void AnimateMovingProc P((Widget w, XEvent *event, String *prms,
373 void AutocommProc P((Widget w, XEvent *event, String *prms,
375 void AutoflagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
376 void AutoflipProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
377 void AutobsProc P((Widget w, XEvent *event, String *prms,
379 void AutoraiseProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
380 void AutosaveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
381 void BlindfoldProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
382 void FlashMovesProc P((Widget w, XEvent *event, String *prms,
384 void FlipViewProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
385 void GetMoveListProc P((Widget w, XEvent *event, String *prms,
387 void HighlightDraggingProc P((Widget w, XEvent *event, String *prms,
389 void HighlightLastMoveProc P((Widget w, XEvent *event, String *prms,
391 void MoveSoundProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
392 void IcsAlarmProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
393 void OldSaveStyleProc P((Widget w, XEvent *event, String *prms,
395 void PeriodicUpdatesProc P((Widget w, XEvent *event, String *prms,
397 void PonderNextMoveProc P((Widget w, XEvent *event, String *prms,
399 void PopupMoveErrorsProc P((Widget w, XEvent *event, String *prms,
401 void PopupExitMessageProc P((Widget w, XEvent *event, String *prms,
403 void PremoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
404 void QuietPlayProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
405 void ShowCoordsProc P((Widget w, XEvent *event, String *prms,
407 void ShowThinkingProc P((Widget w, XEvent *event, String *prms,
409 void HideThinkingProc P((Widget w, XEvent *event, String *prms,
411 void TestLegalityProc P((Widget w, XEvent *event, String *prms,
413 void InfoProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
414 void ManProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
415 void HintProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
416 void BookProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
417 void AboutGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
418 void AboutProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
419 void DebugProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
420 void NothingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
421 void Iconify P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
422 void DisplayMove P((int moveNumber));
423 void DisplayTitle P((char *title));
424 void ICSInitScript P((void));
425 int LoadGamePopUp P((FILE *f, int gameNumber, char *title));
426 void ErrorPopUp P((char *title, char *text, int modal));
427 void ErrorPopDown P((void));
428 static char *ExpandPathName P((char *path));
429 static void CreateAnimVars P((void));
430 static void DragPieceBegin P((int x, int y));
431 static void DragPieceMove P((int x, int y));
432 static void DragPieceEnd P((int x, int y));
433 static void DrawDragPiece P((void));
434 char *ModeToWidgetName P((GameMode mode));
435 void EngineOutputUpdate( FrontEndProgramStats * stats );
436 void ShuffleMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
437 void EngineMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
438 void UciMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
439 void TimeControlProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
440 void NewVariantProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
441 void FirstSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
442 void SecondSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
443 void ShufflePopDown P(());
444 void EnginePopDown P(());
445 void UciPopDown P(());
446 void TimeControlPopDown P(());
447 void NewVariantPopDown P(());
448 void SettingsPopDown P(());
450 * XBoard depends on Xt R4 or higher
452 int xtVersion = XtSpecificationRelease;
457 Pixel lightSquareColor, darkSquareColor, whitePieceColor, blackPieceColor,
458 jailSquareColor, highlightSquareColor, premoveHighlightColor;
459 Pixel lowTimeWarningColor;
460 GC lightSquareGC, darkSquareGC, jailSquareGC, lineGC, wdPieceGC, wlPieceGC,
461 bdPieceGC, blPieceGC, wbPieceGC, bwPieceGC, coordGC, highlineGC,
462 wjPieceGC, bjPieceGC, prelineGC, countGC;
463 Pixmap iconPixmap, wIconPixmap, bIconPixmap, xMarkPixmap;
464 Widget shellWidget, layoutWidget, formWidget, boardWidget, messageWidget,
465 whiteTimerWidget, blackTimerWidget, titleWidget, widgetList[16],
466 commentShell, promotionShell, whitePieceMenu, blackPieceMenu, dropMenu,
467 menuBarWidget, buttonBarWidget, editShell, errorShell, analysisShell,
468 ICSInputShell, fileNameShell, askQuestionShell;
469 XSegment gridSegments[(BOARD_SIZE + 1) * 2];
470 XSegment jailGridSegments[(BOARD_SIZE + 3) * 2];
471 Font clockFontID, coordFontID, countFontID;
472 XFontStruct *clockFontStruct, *coordFontStruct, *countFontStruct;
473 XtAppContext appContext;
475 char *oldICSInteractionTitle;
479 char installDir[] = "."; // [HGM] UCI: needed for UCI; probably needs run-time initializtion
481 Position commentX = -1, commentY = -1;
482 Dimension commentW, commentH;
484 int squareSize, smallLayout = 0, tinyLayout = 0,
485 marginW, marginH, // [HGM] for run-time resizing
486 fromX = -1, fromY = -1, toX, toY, commentUp = False, analysisUp = False,
487 ICSInputBoxUp = False, askQuestionUp = False,
488 filenameUp = False, promotionUp = False, pmFromX = -1, pmFromY = -1,
489 editUp = False, errorUp = False, errorExitStatus = -1, lineGap;
490 Pixel timerForegroundPixel, timerBackgroundPixel;
491 Pixel buttonForegroundPixel, buttonBackgroundPixel;
492 char *chessDir, *programName, *programVersion,
493 *gameCopyFilename, *gamePasteFilename;
497 Pixmap pieceBitmap[2][(int)BlackPawn];
498 Pixmap pieceBitmap2[2][(int)BlackPawn+4]; /* [HGM] pieces */
499 Pixmap xpmPieceBitmap[4][(int)BlackPawn]; /* LL, LD, DL, DD actually used*/
500 Pixmap xpmPieceBitmap2[4][(int)BlackPawn+4]; /* LL, LD, DL, DD set to select from */
501 Pixmap xpmLightSquare, xpmDarkSquare, xpmJailSquare;
502 int useImages, useImageSqs;
503 XImage *ximPieceBitmap[4][(int)BlackPawn+4]; /* LL, LD, DL, DD */
504 Pixmap ximMaskPm[(int)BlackPawn]; /* clipmasks, used for XIM pieces */
505 Pixmap ximMaskPm2[(int)BlackPawn+4]; /* clipmasks, used for XIM pieces */
506 XImage *ximLightSquare, *ximDarkSquare;
509 #define pieceToSolid(piece) &pieceBitmap[SOLID][(piece) % (int)BlackPawn]
510 #define pieceToOutline(piece) &pieceBitmap[OUTLINE][(piece) % (int)BlackPawn]
512 #define White(piece) ((int)(piece) < (int)BlackPawn)
514 /* Variables for doing smooth animation. This whole thing
515 would be much easier if the board was double-buffered,
516 but that would require a fairly major rewrite. */
521 GC blitGC, pieceGC, outlineGC;
522 XPoint startSquare, prevFrame, mouseDelta;
526 int startBoardX, startBoardY;
529 /* There can be two pieces being animated at once: a player
530 can begin dragging a piece before the remote opponent has moved. */
532 static AnimState game, player;
534 /* Bitmaps for use as masks when drawing XPM pieces.
535 Need one for each black and white piece. */
536 static Pixmap xpmMask[BlackKing + 1];
538 /* This magic number is the number of intermediate frames used
539 in each half of the animation. For short moves it's reduced
540 by 1. The total number of frames will be factor * 2 + 1. */
543 SizeDefaults sizeDefaults[] = SIZE_DEFAULTS;
545 MenuItem fileMenu[] = {
546 {N_("New Game"), ResetProc},
547 {N_("New Shuffle Game ..."), ShuffleMenuProc},
548 {N_("New Variant ..."), NewVariantProc}, // [HGM] variant: not functional yet
549 {"----", NothingProc},
550 {N_("Load Game"), LoadGameProc},
551 {N_("Load Next Game"), LoadNextGameProc},
552 {N_("Load Previous Game"), LoadPrevGameProc},
553 {N_("Reload Same Game"), ReloadGameProc},
554 {N_("Save Game"), SaveGameProc},
555 {"----", NothingProc},
556 {N_("Copy Game"), CopyGameProc},
557 {N_("Paste Game"), PasteGameProc},
558 {"----", NothingProc},
559 {N_("Load Position"), LoadPositionProc},
560 {N_("Load Next Position"), LoadNextPositionProc},
561 {N_("Load Previous Position"), LoadPrevPositionProc},
562 {N_("Reload Same Position"), ReloadPositionProc},
563 {N_("Save Position"), SavePositionProc},
564 {"----", NothingProc},
565 {N_("Copy Position"), CopyPositionProc},
566 {N_("Paste Position"), PastePositionProc},
567 {"----", NothingProc},
568 {N_("Mail Move"), MailMoveProc},
569 {N_("Reload CMail Message"), ReloadCmailMsgProc},
570 {"----", NothingProc},
571 {N_("Exit"), QuitProc},
575 MenuItem modeMenu[] = {
576 {N_("Machine White"), MachineWhiteProc},
577 {N_("Machine Black"), MachineBlackProc},
578 {N_("Two Machines"), TwoMachinesProc},
579 {N_("Analysis Mode"), AnalyzeModeProc},
580 {N_("Analyze File"), AnalyzeFileProc },
581 {N_("ICS Client"), IcsClientProc},
582 {N_("Edit Game"), EditGameProc},
583 {N_("Edit Position"), EditPositionProc},
584 {N_("Training"), TrainingProc},
585 {"----", NothingProc},
586 {N_("Show Engine Output"), EngineOutputProc},
587 {N_("Show Evaluation Graph"), NothingProc}, // [HGM] evalgr: not functional yet
588 {N_("Show Game List"), ShowGameListProc},
589 {"Show Move History", HistoryShowProc}, // [HGM] hist: activate 4.2.7 code
590 {"----", NothingProc},
591 {N_("Edit Tags"), EditTagsProc},
592 {N_("Edit Comment"), EditCommentProc},
593 {N_("ICS Input Box"), IcsInputBoxProc},
594 {N_("Pause"), PauseProc},
598 MenuItem actionMenu[] = {
599 {N_("Accept"), AcceptProc},
600 {N_("Decline"), DeclineProc},
601 {N_("Rematch"), RematchProc},
602 {"----", NothingProc},
603 {N_("Call Flag"), CallFlagProc},
604 {N_("Draw"), DrawProc},
605 {N_("Adjourn"), AdjournProc},
606 {N_("Abort"), AbortProc},
607 {N_("Resign"), ResignProc},
608 {"----", NothingProc},
609 {N_("Stop Observing"), StopObservingProc},
610 {N_("Stop Examining"), StopExaminingProc},
611 {"----", NothingProc},
612 {N_("Adjudicate to White"), AdjuWhiteProc},
613 {N_("Adjudicate to Black"), AdjuBlackProc},
614 {N_("Adjudicate Draw"), AdjuDrawProc},
618 MenuItem stepMenu[] = {
619 {N_("Backward"), BackwardProc},
620 {N_("Forward"), ForwardProc},
621 {N_("Back to Start"), ToStartProc},
622 {N_("Forward to End"), ToEndProc},
623 {N_("Revert"), RevertProc},
624 {N_("Truncate Game"), TruncateGameProc},
625 {"----", NothingProc},
626 {N_("Move Now"), MoveNowProc},
627 {N_("Retract Move"), RetractMoveProc},
631 MenuItem optionsMenu[] = {
632 {N_("Flip View"), FlipViewProc},
633 {"----", NothingProc},
634 {N_("Adjudications ..."), EngineMenuProc},
635 {N_("General Settings ..."), UciMenuProc},
636 {N_("Engine #1 Settings ..."), FirstSettingsProc},
637 {N_("Engine #2 Settings ..."), SecondSettingsProc},
638 {N_("Time Control ..."), TimeControlProc},
639 {"----", NothingProc},
640 {N_("Always Queen"), AlwaysQueenProc},
641 {N_("Animate Dragging"), AnimateDraggingProc},
642 {N_("Animate Moving"), AnimateMovingProc},
643 {N_("Auto Comment"), AutocommProc},
644 {N_("Auto Flag"), AutoflagProc},
645 {N_("Auto Flip View"), AutoflipProc},
646 {N_("Auto Observe"), AutobsProc},
647 {N_("Auto Raise Board"), AutoraiseProc},
648 {N_("Auto Save"), AutosaveProc},
649 {N_("Blindfold"), BlindfoldProc},
650 {N_("Flash Moves"), FlashMovesProc},
651 {N_("Get Move List"), GetMoveListProc},
653 {N_("Highlight Dragging"), HighlightDraggingProc},
655 {N_("Highlight Last Move"), HighlightLastMoveProc},
656 {N_("Move Sound"), MoveSoundProc},
657 {N_("ICS Alarm"), IcsAlarmProc},
658 {N_("Old Save Style"), OldSaveStyleProc},
659 {N_("Periodic Updates"), PeriodicUpdatesProc},
660 {N_("Ponder Next Move"), PonderNextMoveProc},
661 {N_("Popup Exit Message"), PopupExitMessageProc},
662 {N_("Popup Move Errors"), PopupMoveErrorsProc},
663 {N_("Premove"), PremoveProc},
664 {N_("Quiet Play"), QuietPlayProc},
665 {N_("Show Coords"), ShowCoordsProc},
666 {N_("Hide Thinking"), HideThinkingProc},
667 {N_("Test Legality"), TestLegalityProc},
671 MenuItem helpMenu[] = {
672 {N_("Info XBoard"), InfoProc},
673 {N_("Man XBoard"), ManProc},
674 {"----", NothingProc},
675 {N_("Hint"), HintProc},
676 {N_("Book"), BookProc},
677 {"----", NothingProc},
678 {N_("About XBoard"), AboutProc},
683 {N_("File"), fileMenu},
684 {N_("Mode"), modeMenu},
685 {N_("Action"), actionMenu},
686 {N_("Step"), stepMenu},
687 {N_("Options"), optionsMenu},
688 {N_("Help"), helpMenu},
692 #define PAUSE_BUTTON N_("P")
693 MenuItem buttonBar[] = {
696 {PAUSE_BUTTON, PauseProc},
702 #define PIECE_MENU_SIZE 18
703 String pieceMenuStrings[2][PIECE_MENU_SIZE] = {
704 { N_("White"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
705 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
706 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
707 N_("Empty square"), N_("Clear board") },
708 { N_("Black"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
709 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
710 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
711 N_("Empty square"), N_("Clear board") }
713 /* must be in same order as PieceMenuStrings! */
714 ChessSquare pieceMenuTranslation[2][PIECE_MENU_SIZE] = {
715 { WhitePlay, (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
716 WhiteRook, WhiteQueen, WhiteKing, (ChessSquare) 0, WhiteAlfil,
717 WhiteCannon, WhiteAngel, WhiteMarshall, (ChessSquare) 0,
718 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
719 { BlackPlay, (ChessSquare) 0, BlackPawn, BlackKnight, BlackBishop,
720 BlackRook, BlackQueen, BlackKing, (ChessSquare) 0, BlackAlfil,
721 BlackCannon, BlackAngel, BlackMarshall, (ChessSquare) 0,
722 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
725 #define DROP_MENU_SIZE 6
726 String dropMenuStrings[DROP_MENU_SIZE] = {
727 "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"), N_("Queen")
729 /* must be in same order as PieceMenuStrings! */
730 ChessSquare dropMenuTranslation[DROP_MENU_SIZE] = {
731 (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
732 WhiteRook, WhiteQueen
740 DropMenuEnables dmEnables[] = {
758 { XtNborderWidth, 0 },
759 { XtNdefaultDistance, 0 },
763 { XtNborderWidth, 0 },
764 { XtNresizable, (XtArgVal) True },
768 { XtNborderWidth, 0 },
774 { XtNjustify, (XtArgVal) XtJustifyRight },
775 { XtNlabel, (XtArgVal) "..." },
776 { XtNresizable, (XtArgVal) True },
777 { XtNresize, (XtArgVal) False }
780 Arg messageArgs[] = {
781 { XtNjustify, (XtArgVal) XtJustifyLeft },
782 { XtNlabel, (XtArgVal) "..." },
783 { XtNresizable, (XtArgVal) True },
784 { XtNresize, (XtArgVal) False }
788 { XtNborderWidth, 0 },
789 { XtNjustify, (XtArgVal) XtJustifyLeft }
792 XtResource clientResources[] = {
793 { "whitePieceColor", "whitePieceColor", XtRString, sizeof(String),
794 XtOffset(AppDataPtr, whitePieceColor), XtRString,
796 { "blackPieceColor", "blackPieceColor", XtRString, sizeof(String),
797 XtOffset(AppDataPtr, blackPieceColor), XtRString,
799 { "lightSquareColor", "lightSquareColor", XtRString,
800 sizeof(String), XtOffset(AppDataPtr, lightSquareColor),
801 XtRString, LIGHT_SQUARE_COLOR },
802 { "darkSquareColor", "darkSquareColor", XtRString, sizeof(String),
803 XtOffset(AppDataPtr, darkSquareColor), XtRString,
805 { "highlightSquareColor", "highlightSquareColor", XtRString,
806 sizeof(String), XtOffset(AppDataPtr, highlightSquareColor),
807 XtRString, HIGHLIGHT_SQUARE_COLOR },
808 { "premoveHighlightColor", "premoveHighlightColor", XtRString,
809 sizeof(String), XtOffset(AppDataPtr, premoveHighlightColor),
810 XtRString, PREMOVE_HIGHLIGHT_COLOR },
811 { "movesPerSession", "movesPerSession", XtRInt, sizeof(int),
812 XtOffset(AppDataPtr, movesPerSession), XtRImmediate,
813 (XtPointer) MOVES_PER_SESSION },
814 { "timeIncrement", "timeIncrement", XtRInt, sizeof(int),
815 XtOffset(AppDataPtr, timeIncrement), XtRImmediate,
816 (XtPointer) TIME_INCREMENT },
817 { "initString", "initString", XtRString, sizeof(String),
818 XtOffset(AppDataPtr, initString), XtRString, INIT_STRING },
819 { "secondInitString", "secondInitString", XtRString, sizeof(String),
820 XtOffset(AppDataPtr, secondInitString), XtRString, INIT_STRING },
821 { "firstComputerString", "firstComputerString", XtRString,
822 sizeof(String), XtOffset(AppDataPtr, firstComputerString), XtRString,
824 { "secondComputerString", "secondComputerString", XtRString,
825 sizeof(String), XtOffset(AppDataPtr, secondComputerString), XtRString,
827 { "firstChessProgram", "firstChessProgram", XtRString,
828 sizeof(String), XtOffset(AppDataPtr, firstChessProgram),
829 XtRString, FIRST_CHESS_PROGRAM },
830 { "secondChessProgram", "secondChessProgram", XtRString,
831 sizeof(String), XtOffset(AppDataPtr, secondChessProgram),
832 XtRString, SECOND_CHESS_PROGRAM },
833 { "firstPlaysBlack", "firstPlaysBlack", XtRBoolean,
834 sizeof(Boolean), XtOffset(AppDataPtr, firstPlaysBlack),
835 XtRImmediate, (XtPointer) False },
836 { "noChessProgram", "noChessProgram", XtRBoolean,
837 sizeof(Boolean), XtOffset(AppDataPtr, noChessProgram),
838 XtRImmediate, (XtPointer) False },
839 { "firstHost", "firstHost", XtRString, sizeof(String),
840 XtOffset(AppDataPtr, firstHost), XtRString, FIRST_HOST },
841 { "secondHost", "secondHost", XtRString, sizeof(String),
842 XtOffset(AppDataPtr, secondHost), XtRString, SECOND_HOST },
843 { "firstDirectory", "firstDirectory", XtRString, sizeof(String),
844 XtOffset(AppDataPtr, firstDirectory), XtRString, "." },
845 { "secondDirectory", "secondDirectory", XtRString, sizeof(String),
846 XtOffset(AppDataPtr, secondDirectory), XtRString, "." },
847 { "bitmapDirectory", "bitmapDirectory", XtRString,
848 sizeof(String), XtOffset(AppDataPtr, bitmapDirectory),
850 { "remoteShell", "remoteShell", XtRString, sizeof(String),
851 XtOffset(AppDataPtr, remoteShell), XtRString, REMOTE_SHELL },
852 { "remoteUser", "remoteUser", XtRString, sizeof(String),
853 XtOffset(AppDataPtr, remoteUser), XtRString, "" },
854 { "timeDelay", "timeDelay", XtRFloat, sizeof(float),
855 XtOffset(AppDataPtr, timeDelay), XtRString,
856 (XtPointer) TIME_DELAY_QUOTE },
857 { "timeControl", "timeControl", XtRString, sizeof(String),
858 XtOffset(AppDataPtr, timeControl), XtRString,
859 (XtPointer) TIME_CONTROL },
860 { "internetChessServerMode", "internetChessServerMode",
861 XtRBoolean, sizeof(Boolean),
862 XtOffset(AppDataPtr, icsActive), XtRImmediate,
864 { "internetChessServerHost", "internetChessServerHost",
865 XtRString, sizeof(String),
866 XtOffset(AppDataPtr, icsHost),
867 XtRString, (XtPointer) ICS_HOST },
868 { "internetChessServerPort", "internetChessServerPort",
869 XtRString, sizeof(String),
870 XtOffset(AppDataPtr, icsPort), XtRString,
871 (XtPointer) ICS_PORT },
872 { "internetChessServerCommPort", "internetChessServerCommPort",
873 XtRString, sizeof(String),
874 XtOffset(AppDataPtr, icsCommPort), XtRString,
876 { "internetChessServerLogonScript", "internetChessServerLogonScript",
877 XtRString, sizeof(String),
878 XtOffset(AppDataPtr, icsLogon), XtRString,
880 { "internetChessServerHelper", "internetChessServerHelper",
881 XtRString, sizeof(String),
882 XtOffset(AppDataPtr, icsHelper), XtRString, "" },
883 { "internetChessServerInputBox", "internetChessServerInputBox",
884 XtRBoolean, sizeof(Boolean),
885 XtOffset(AppDataPtr, icsInputBox), XtRImmediate,
887 { "icsAlarm", "icsAlarm",
888 XtRBoolean, sizeof(Boolean),
889 XtOffset(AppDataPtr, icsAlarm), XtRImmediate,
891 { "icsAlarmTime", "icsAlarmTime",
893 XtOffset(AppDataPtr, icsAlarmTime), XtRImmediate,
895 { "useTelnet", "useTelnet", XtRBoolean, sizeof(Boolean),
896 XtOffset(AppDataPtr, useTelnet), XtRImmediate,
898 { "telnetProgram", "telnetProgram", XtRString, sizeof(String),
899 XtOffset(AppDataPtr, telnetProgram), XtRString, TELNET_PROGRAM },
900 { "gateway", "gateway", XtRString, sizeof(String),
901 XtOffset(AppDataPtr, gateway), XtRString, "" },
902 { "loadGameFile", "loadGameFile", XtRString, sizeof(String),
903 XtOffset(AppDataPtr, loadGameFile), XtRString, "" },
904 { "loadGameIndex", "loadGameIndex",
906 XtOffset(AppDataPtr, loadGameIndex), XtRImmediate,
908 { "saveGameFile", "saveGameFile", XtRString, sizeof(String),
909 XtOffset(AppDataPtr, saveGameFile), XtRString, "" },
910 { "autoRaiseBoard", "autoRaiseBoard", XtRBoolean,
911 sizeof(Boolean), XtOffset(AppDataPtr, autoRaiseBoard),
912 XtRImmediate, (XtPointer) True },
913 { "autoSaveGames", "autoSaveGames", XtRBoolean,
914 sizeof(Boolean), XtOffset(AppDataPtr, autoSaveGames),
915 XtRImmediate, (XtPointer) False },
916 { "blindfold", "blindfold", XtRBoolean,
917 sizeof(Boolean), XtOffset(AppDataPtr, blindfold),
918 XtRImmediate, (XtPointer) False },
919 { "loadPositionFile", "loadPositionFile", XtRString,
920 sizeof(String), XtOffset(AppDataPtr, loadPositionFile),
922 { "loadPositionIndex", "loadPositionIndex",
924 XtOffset(AppDataPtr, loadPositionIndex), XtRImmediate,
926 { "savePositionFile", "savePositionFile", XtRString,
927 sizeof(String), XtOffset(AppDataPtr, savePositionFile),
929 { "matchMode", "matchMode", XtRBoolean, sizeof(Boolean),
930 XtOffset(AppDataPtr, matchMode), XtRImmediate, (XtPointer) False },
931 { "matchGames", "matchGames", XtRInt, sizeof(int),
932 XtOffset(AppDataPtr, matchGames), XtRImmediate,
934 { "monoMode", "monoMode", XtRBoolean, sizeof(Boolean),
935 XtOffset(AppDataPtr, monoMode), XtRImmediate,
937 { "debugMode", "debugMode", XtRBoolean, sizeof(Boolean),
938 XtOffset(AppDataPtr, debugMode), XtRImmediate,
940 { "clockMode", "clockMode", XtRBoolean, sizeof(Boolean),
941 XtOffset(AppDataPtr, clockMode), XtRImmediate,
943 { "boardSize", "boardSize", XtRString, sizeof(String),
944 XtOffset(AppDataPtr, boardSize), XtRString, "" },
945 { "searchTime", "searchTime", XtRString, sizeof(String),
946 XtOffset(AppDataPtr, searchTime), XtRString,
948 { "searchDepth", "searchDepth", XtRInt, sizeof(int),
949 XtOffset(AppDataPtr, searchDepth), XtRImmediate,
951 { "showCoords", "showCoords", XtRBoolean, sizeof(Boolean),
952 XtOffset(AppDataPtr, showCoords), XtRImmediate,
954 { "showJail", "showJail", XtRInt, sizeof(int),
955 XtOffset(AppDataPtr, showJail), XtRImmediate,
957 { "showThinking", "showThinking", XtRBoolean, sizeof(Boolean),
958 XtOffset(AppDataPtr, showThinking), XtRImmediate,
960 { "ponderNextMove", "ponderNextMove", XtRBoolean, sizeof(Boolean),
961 XtOffset(AppDataPtr, ponderNextMove), XtRImmediate,
963 { "periodicUpdates", "periodicUpdates", XtRBoolean, sizeof(Boolean),
964 XtOffset(AppDataPtr, periodicUpdates), XtRImmediate,
966 { "clockFont", "clockFont", XtRString, sizeof(String),
967 XtOffset(AppDataPtr, clockFont), XtRString, CLOCK_FONT },
968 { "coordFont", "coordFont", XtRString, sizeof(String),
969 XtOffset(AppDataPtr, coordFont), XtRString, COORD_FONT },
970 { "font", "font", XtRString, sizeof(String),
971 XtOffset(AppDataPtr, font), XtRString, DEFAULT_FONT },
972 { "ringBellAfterMoves", "ringBellAfterMoves",
973 XtRBoolean, sizeof(Boolean),
974 XtOffset(AppDataPtr, ringBellAfterMoves),
975 XtRImmediate, (XtPointer) False },
976 { "autoCallFlag", "autoCallFlag", XtRBoolean,
977 sizeof(Boolean), XtOffset(AppDataPtr, autoCallFlag),
978 XtRImmediate, (XtPointer) False },
979 { "autoFlipView", "autoFlipView", XtRBoolean,
980 sizeof(Boolean), XtOffset(AppDataPtr, autoFlipView),
981 XtRImmediate, (XtPointer) True },
982 { "autoObserve", "autoObserve", XtRBoolean,
983 sizeof(Boolean), XtOffset(AppDataPtr, autoObserve),
984 XtRImmediate, (XtPointer) False },
985 { "autoComment", "autoComment", XtRBoolean,
986 sizeof(Boolean), XtOffset(AppDataPtr, autoComment),
987 XtRImmediate, (XtPointer) False },
988 { "getMoveList", "getMoveList", XtRBoolean,
989 sizeof(Boolean), XtOffset(AppDataPtr, getMoveList),
990 XtRImmediate, (XtPointer) True },
992 { "highlightDragging", "highlightDragging", XtRBoolean,
993 sizeof(Boolean), XtOffset(AppDataPtr, highlightDragging),
994 XtRImmediate, (XtPointer) False },
996 { "highlightLastMove", "highlightLastMove", XtRBoolean,
997 sizeof(Boolean), XtOffset(AppDataPtr, highlightLastMove),
998 XtRImmediate, (XtPointer) False },
999 { "premove", "premove", XtRBoolean,
1000 sizeof(Boolean), XtOffset(AppDataPtr, premove),
1001 XtRImmediate, (XtPointer) True },
1002 { "testLegality", "testLegality", XtRBoolean,
1003 sizeof(Boolean), XtOffset(AppDataPtr, testLegality),
1004 XtRImmediate, (XtPointer) True },
1005 { "flipView", "flipView", XtRBoolean,
1006 sizeof(Boolean), XtOffset(AppDataPtr, flipView),
1007 XtRImmediate, (XtPointer) False },
1008 { "cmail", "cmailGameName", XtRString, sizeof(String),
1009 XtOffset(AppDataPtr, cmailGameName), XtRString, "" },
1010 { "alwaysPromoteToQueen", "alwaysPromoteToQueen", XtRBoolean,
1011 sizeof(Boolean), XtOffset(AppDataPtr, alwaysPromoteToQueen),
1012 XtRImmediate, (XtPointer) False },
1013 { "oldSaveStyle", "oldSaveStyle", XtRBoolean,
1014 sizeof(Boolean), XtOffset(AppDataPtr, oldSaveStyle),
1015 XtRImmediate, (XtPointer) False },
1016 { "quietPlay", "quietPlay", XtRBoolean,
1017 sizeof(Boolean), XtOffset(AppDataPtr, quietPlay),
1018 XtRImmediate, (XtPointer) False },
1019 { "titleInWindow", "titleInWindow", XtRBoolean,
1020 sizeof(Boolean), XtOffset(AppDataPtr, titleInWindow),
1021 XtRImmediate, (XtPointer) False },
1022 { "localLineEditing", "localLineEditing", XtRBoolean,
1023 sizeof(Boolean), XtOffset(AppDataPtr, localLineEditing),
1024 XtRImmediate, (XtPointer) True }, /* not implemented, must be True */
1026 { "zippyTalk", "zippyTalk", XtRBoolean,
1027 sizeof(Boolean), XtOffset(AppDataPtr, zippyTalk),
1028 XtRImmediate, (XtPointer) ZIPPY_TALK },
1029 { "zippyPlay", "zippyPlay", XtRBoolean,
1030 sizeof(Boolean), XtOffset(AppDataPtr, zippyPlay),
1031 XtRImmediate, (XtPointer) ZIPPY_PLAY },
1032 { "zippyLines", "zippyLines", XtRString, sizeof(String),
1033 XtOffset(AppDataPtr, zippyLines), XtRString, ZIPPY_LINES },
1034 { "zippyPinhead", "zippyPinhead", XtRString, sizeof(String),
1035 XtOffset(AppDataPtr, zippyPinhead), XtRString, ZIPPY_PINHEAD },
1036 { "zippyPassword", "zippyPassword", XtRString, sizeof(String),
1037 XtOffset(AppDataPtr, zippyPassword), XtRString, ZIPPY_PASSWORD },
1038 { "zippyPassword2", "zippyPassword2", XtRString, sizeof(String),
1039 XtOffset(AppDataPtr, zippyPassword2), XtRString, ZIPPY_PASSWORD2 },
1040 { "zippyWrongPassword", "zippyWrongPassword", XtRString, sizeof(String),
1041 XtOffset(AppDataPtr, zippyWrongPassword), XtRString,
1042 ZIPPY_WRONG_PASSWORD },
1043 { "zippyAcceptOnly", "zippyAcceptOnly", XtRString, sizeof(String),
1044 XtOffset(AppDataPtr, zippyAcceptOnly), XtRString, ZIPPY_ACCEPT_ONLY },
1045 { "zippyUseI", "zippyUseI", XtRBoolean,
1046 sizeof(Boolean), XtOffset(AppDataPtr, zippyUseI),
1047 XtRImmediate, (XtPointer) ZIPPY_USE_I },
1048 { "zippyBughouse", "zippyBughouse", XtRInt,
1049 sizeof(int), XtOffset(AppDataPtr, zippyBughouse),
1050 XtRImmediate, (XtPointer) ZIPPY_BUGHOUSE },
1051 { "zippyNoplayCrafty", "zippyNoplayCrafty", XtRBoolean,
1052 sizeof(Boolean), XtOffset(AppDataPtr, zippyNoplayCrafty),
1053 XtRImmediate, (XtPointer) ZIPPY_NOPLAY_CRAFTY },
1054 { "zippyGameEnd", "zippyGameEnd", XtRString, sizeof(String),
1055 XtOffset(AppDataPtr, zippyGameEnd), XtRString, ZIPPY_GAME_END },
1056 { "zippyGameStart", "zippyGameStart", XtRString, sizeof(String),
1057 XtOffset(AppDataPtr, zippyGameStart), XtRString, ZIPPY_GAME_START },
1058 { "zippyAdjourn", "zippyAdjourn", XtRBoolean,
1059 sizeof(Boolean), XtOffset(AppDataPtr, zippyAdjourn),
1060 XtRImmediate, (XtPointer) ZIPPY_ADJOURN },
1061 { "zippyAbort", "zippyAbort", XtRBoolean,
1062 sizeof(Boolean), XtOffset(AppDataPtr, zippyAbort),
1063 XtRImmediate, (XtPointer) ZIPPY_ABORT },
1064 { "zippyVariants", "zippyVariants", XtRString, sizeof(String),
1065 XtOffset(AppDataPtr, zippyVariants), XtRString, ZIPPY_VARIANTS },
1066 { "zippyMaxGames", "zippyMaxGames", XtRInt, sizeof(int),
1067 XtOffset(AppDataPtr, zippyMaxGames), XtRImmediate,
1068 (XtPointer) ZIPPY_MAX_GAMES },
1069 { "zippyReplayTimeout", "zippyReplayTimeout", XtRInt, sizeof(int),
1070 XtOffset(AppDataPtr, zippyReplayTimeout), XtRImmediate,
1071 (XtPointer) ZIPPY_REPLAY_TIMEOUT },
1072 { "zippyShortGame", "zippyShortGame", XtRInt, sizeof(int),
1073 XtOffset(AppDataPtr, zippyShortGame), XtRImmediate,
1076 { "flashCount", "flashCount", XtRInt, sizeof(int),
1077 XtOffset(AppDataPtr, flashCount), XtRImmediate,
1078 (XtPointer) FLASH_COUNT },
1079 { "flashRate", "flashRate", XtRInt, sizeof(int),
1080 XtOffset(AppDataPtr, flashRate), XtRImmediate,
1081 (XtPointer) FLASH_RATE },
1082 { "pixmapDirectory", "pixmapDirectory", XtRString,
1083 sizeof(String), XtOffset(AppDataPtr, pixmapDirectory),
1085 { "msLoginDelay", "msLoginDelay", XtRInt, sizeof(int),
1086 XtOffset(AppDataPtr, msLoginDelay), XtRImmediate,
1087 (XtPointer) MS_LOGIN_DELAY },
1088 { "colorizeMessages", "colorizeMessages", XtRBoolean,
1089 sizeof(Boolean), XtOffset(AppDataPtr, colorize),
1090 XtRImmediate, (XtPointer) False },
1091 { "colorShout", "colorShout", XtRString,
1092 sizeof(String), XtOffset(AppDataPtr, colorShout),
1093 XtRString, COLOR_SHOUT },
1094 { "colorSShout", "colorSShout", XtRString,
1095 sizeof(String), XtOffset(AppDataPtr, colorSShout),
1096 XtRString, COLOR_SSHOUT },
1097 { "colorChannel1", "colorChannel1", XtRString,
1098 sizeof(String), XtOffset(AppDataPtr, colorChannel1),
1099 XtRString, COLOR_CHANNEL1 },
1100 { "colorChannel", "colorChannel", XtRString,
1101 sizeof(String), XtOffset(AppDataPtr, colorChannel),
1102 XtRString, COLOR_CHANNEL },
1103 { "colorKibitz", "colorKibitz", XtRString,
1104 sizeof(String), XtOffset(AppDataPtr, colorKibitz),
1105 XtRString, COLOR_KIBITZ },
1106 { "colorTell", "colorTell", XtRString,
1107 sizeof(String), XtOffset(AppDataPtr, colorTell),
1108 XtRString, COLOR_TELL },
1109 { "colorChallenge", "colorChallenge", XtRString,
1110 sizeof(String), XtOffset(AppDataPtr, colorChallenge),
1111 XtRString, COLOR_CHALLENGE },
1112 { "colorRequest", "colorRequest", XtRString,
1113 sizeof(String), XtOffset(AppDataPtr, colorRequest),
1114 XtRString, COLOR_REQUEST },
1115 { "colorSeek", "colorSeek", XtRString,
1116 sizeof(String), XtOffset(AppDataPtr, colorSeek),
1117 XtRString, COLOR_SEEK },
1118 { "colorNormal", "colorNormal", XtRString,
1119 sizeof(String), XtOffset(AppDataPtr, colorNormal),
1120 XtRString, COLOR_NORMAL },
1121 { "soundProgram", "soundProgram", XtRString,
1122 sizeof(String), XtOffset(AppDataPtr, soundProgram),
1123 XtRString, "play" },
1124 { "soundShout", "soundShout", XtRString,
1125 sizeof(String), XtOffset(AppDataPtr, soundShout),
1127 { "soundSShout", "soundSShout", XtRString,
1128 sizeof(String), XtOffset(AppDataPtr, soundSShout),
1130 { "soundChannel1", "soundChannel1", XtRString,
1131 sizeof(String), XtOffset(AppDataPtr, soundChannel1),
1133 { "soundChannel", "soundChannel", XtRString,
1134 sizeof(String), XtOffset(AppDataPtr, soundChannel),
1136 { "soundKibitz", "soundKibitz", XtRString,
1137 sizeof(String), XtOffset(AppDataPtr, soundKibitz),
1139 { "soundTell", "soundTell", XtRString,
1140 sizeof(String), XtOffset(AppDataPtr, soundTell),
1142 { "soundChallenge", "soundChallenge", XtRString,
1143 sizeof(String), XtOffset(AppDataPtr, soundChallenge),
1145 { "soundRequest", "soundRequest", XtRString,
1146 sizeof(String), XtOffset(AppDataPtr, soundRequest),
1148 { "soundSeek", "soundSeek", XtRString,
1149 sizeof(String), XtOffset(AppDataPtr, soundSeek),
1151 { "soundMove", "soundMove", XtRString,
1152 sizeof(String), XtOffset(AppDataPtr, soundMove),
1154 { "soundIcsWin", "soundIcsWin", XtRString,
1155 sizeof(String), XtOffset(AppDataPtr, soundIcsWin),
1157 { "soundIcsLoss", "soundIcsLoss", XtRString,
1158 sizeof(String), XtOffset(AppDataPtr, soundIcsLoss),
1160 { "soundIcsDraw", "soundIcsDraw", XtRString,
1161 sizeof(String), XtOffset(AppDataPtr, soundIcsDraw),
1163 { "soundIcsUnfinished", "soundIcsUnfinished", XtRString,
1164 sizeof(String), XtOffset(AppDataPtr, soundIcsUnfinished),
1166 { "soundIcsAlarm", "soundIcsAlarm", XtRString,
1167 sizeof(String), XtOffset(AppDataPtr, soundIcsAlarm),
1169 { "reuseFirst", "reuseFirst", XtRBoolean,
1170 sizeof(Boolean), XtOffset(AppDataPtr, reuseFirst),
1171 XtRImmediate, (XtPointer) True },
1172 { "reuseSecond", "reuseSecond", XtRBoolean,
1173 sizeof(Boolean), XtOffset(AppDataPtr, reuseSecond),
1174 XtRImmediate, (XtPointer) True },
1175 { "animateDragging", "animateDragging", XtRBoolean,
1176 sizeof(Boolean), XtOffset(AppDataPtr, animateDragging),
1177 XtRImmediate, (XtPointer) True },
1178 { "animateMoving", "animateMoving", XtRBoolean,
1179 sizeof(Boolean), XtOffset(AppDataPtr, animate),
1180 XtRImmediate, (XtPointer) True },
1181 { "animateSpeed", "animateSpeed", XtRInt,
1182 sizeof(int), XtOffset(AppDataPtr, animSpeed),
1183 XtRImmediate, (XtPointer)10 },
1184 { "popupExitMessage", "popupExitMessage", XtRBoolean,
1185 sizeof(Boolean), XtOffset(AppDataPtr, popupExitMessage),
1186 XtRImmediate, (XtPointer) True },
1187 { "popupMoveErrors", "popupMoveErrors", XtRBoolean,
1188 sizeof(Boolean), XtOffset(AppDataPtr, popupMoveErrors),
1189 XtRImmediate, (XtPointer) False },
1190 { "fontSizeTolerance", "fontSizeTolerance", XtRInt,
1191 sizeof(int), XtOffset(AppDataPtr, fontSizeTolerance),
1192 XtRImmediate, (XtPointer)4 },
1193 { "initialMode", "initialMode", XtRString,
1194 sizeof(String), XtOffset(AppDataPtr, initialMode),
1195 XtRImmediate, (XtPointer) "" },
1196 { "variant", "variant", XtRString,
1197 sizeof(String), XtOffset(AppDataPtr, variant),
1198 XtRImmediate, (XtPointer) "normal" },
1199 { "firstProtocolVersion", "firstProtocolVersion", XtRInt,
1200 sizeof(int), XtOffset(AppDataPtr, firstProtocolVersion),
1201 XtRImmediate, (XtPointer)PROTOVER },
1202 { "secondProtocolVersion", "secondProtocolVersion", XtRInt,
1203 sizeof(int), XtOffset(AppDataPtr, secondProtocolVersion),
1204 XtRImmediate, (XtPointer)PROTOVER },
1205 { "showButtonBar", "showButtonBar", XtRBoolean,
1206 sizeof(Boolean), XtOffset(AppDataPtr, showButtonBar),
1207 XtRImmediate, (XtPointer) True },
1208 { "lowTimeWarningColor", "lowTimeWarningColor", XtRString,
1209 sizeof(String), XtOffset(AppDataPtr, lowTimeWarningColor),
1210 XtRString, COLOR_LOWTIMEWARNING },
1211 { "lowTimeWarning", "lowTimeWarning", XtRBoolean,
1212 sizeof(Boolean), XtOffset(AppDataPtr, lowTimeWarning),
1213 XtRImmediate, (XtPointer) False },
1214 {"icsEngineAnalyze", "icsEngineAnalyze", XtRBoolean, /* [DM] icsEngineAnalyze */
1215 sizeof(Boolean), XtOffset(AppDataPtr, icsEngineAnalyze),
1216 XtRImmediate, (XtPointer) False },
1217 { "firstScoreAbs", "firstScoreAbs", XtRBoolean,
1218 sizeof(Boolean), XtOffset(AppDataPtr, firstScoreIsAbsolute),
1219 XtRImmediate, (XtPointer) False },
1220 { "secondScoreAbs", "secondScoreAbs", XtRBoolean,
1221 sizeof(Boolean), XtOffset(AppDataPtr, secondScoreIsAbsolute),
1222 XtRImmediate, (XtPointer) False },
1223 { "pgnExtendedInfo", "pgnExtendedInfo", XtRBoolean,
1224 sizeof(Boolean), XtOffset(AppDataPtr, saveExtendedInfoInPGN),
1225 XtRImmediate, (XtPointer) False },
1226 { "hideThinkingFromHuman", "hideThinkingFromHuman", XtRBoolean,
1227 sizeof(Boolean), XtOffset(AppDataPtr, hideThinkingFromHuman),
1228 XtRImmediate, (XtPointer) True },
1229 { "adjudicateLossThreshold", "adjudicateLossThreshold", XtRInt,
1230 sizeof(int), XtOffset(AppDataPtr, adjudicateLossThreshold),
1231 XtRImmediate, (XtPointer) 0},
1232 { "pgnEventHeader", "pgnEventHeader", XtRString,
1233 sizeof(String), XtOffset(AppDataPtr, pgnEventHeader),
1234 XtRImmediate, (XtPointer) "Computer Chess Game" },
1235 { "defaultFrcPosition", "defaultFrcPositon", XtRInt,
1236 sizeof(int), XtOffset(AppDataPtr, defaultFrcPosition),
1237 XtRImmediate, (XtPointer) -1},
1238 { "gameListTags", "gameListTags", XtRString,
1239 sizeof(String), XtOffset(AppDataPtr, gameListTags),
1240 XtRImmediate, (XtPointer) GLT_DEFAULT_TAGS },
1242 // [HGM] 4.3.xx options
1243 { "boardWidth", "boardWidth", XtRInt,
1244 sizeof(int), XtOffset(AppDataPtr, NrFiles),
1245 XtRImmediate, (XtPointer) -1},
1246 { "boardHeight", "boardHeight", XtRInt,
1247 sizeof(int), XtOffset(AppDataPtr, NrRanks),
1248 XtRImmediate, (XtPointer) -1},
1249 { "matchPause", "matchPause", XtRInt,
1250 sizeof(int), XtOffset(AppDataPtr, matchPause),
1251 XtRImmediate, (XtPointer) 10000},
1252 { "holdingsSize", "holdingsSize", XtRInt,
1253 sizeof(int), XtOffset(AppDataPtr, holdingsSize),
1254 XtRImmediate, (XtPointer) -1},
1255 { "flipBlack", "flipBlack", XtRBoolean,
1256 sizeof(Boolean), XtOffset(AppDataPtr, upsideDown),
1257 XtRImmediate, (XtPointer) False},
1258 { "allWhite", "allWhite", XtRBoolean,
1259 sizeof(Boolean), XtOffset(AppDataPtr, allWhite),
1260 XtRImmediate, (XtPointer) False},
1261 { "pieceToCharTable", "pieceToCharTable", XtRString,
1262 sizeof(String), XtOffset(AppDataPtr, pieceToCharTable),
1263 XtRImmediate, (XtPointer) 0},
1264 { "alphaRank", "alphaRank", XtRBoolean,
1265 sizeof(Boolean), XtOffset(AppDataPtr, alphaRank),
1266 XtRImmediate, (XtPointer) False},
1267 { "testClaims", "testClaims", XtRBoolean,
1268 sizeof(Boolean), XtOffset(AppDataPtr, testClaims),
1269 XtRImmediate, (XtPointer) True},
1270 { "checkMates", "checkMates", XtRBoolean,
1271 sizeof(Boolean), XtOffset(AppDataPtr, checkMates),
1272 XtRImmediate, (XtPointer) True},
1273 { "materialDraws", "materialDraws", XtRBoolean,
1274 sizeof(Boolean), XtOffset(AppDataPtr, materialDraws),
1275 XtRImmediate, (XtPointer) True},
1276 { "trivialDraws", "trivialDraws", XtRBoolean,
1277 sizeof(Boolean), XtOffset(AppDataPtr, trivialDraws),
1278 XtRImmediate, (XtPointer) False},
1279 { "ruleMoves", "ruleMoves", XtRInt,
1280 sizeof(int), XtOffset(AppDataPtr, ruleMoves),
1281 XtRImmediate, (XtPointer) 51},
1282 { "repeatsToDraw", "repeatsToDraw", XtRInt,
1283 sizeof(int), XtOffset(AppDataPtr, drawRepeats),
1284 XtRImmediate, (XtPointer) 6},
1285 { "engineDebugOutput", "engineDebugOutput", XtRInt,
1286 sizeof(int), XtOffset(AppDataPtr, engineComments),
1287 XtRImmediate, (XtPointer) 1},
1288 { "userName", "userName", XtRString,
1289 sizeof(int), XtOffset(AppDataPtr, userName),
1290 XtRImmediate, (XtPointer) 0},
1291 { "autoKibitz", "autoKibitz", XtRBoolean,
1292 sizeof(Boolean), XtOffset(AppDataPtr, autoKibitz),
1293 XtRImmediate, (XtPointer) False},
1294 { "firstTimeOdds", "firstTimeOdds", XtRInt,
1295 sizeof(int), XtOffset(AppDataPtr, firstTimeOdds),
1296 XtRImmediate, (XtPointer) 1},
1297 { "secondTimeOdds", "secondTimeOdds", XtRInt,
1298 sizeof(int), XtOffset(AppDataPtr, secondTimeOdds),
1299 XtRImmediate, (XtPointer) 1},
1300 { "timeOddsMode", "timeOddsMode", XtRInt,
1301 sizeof(int), XtOffset(AppDataPtr, timeOddsMode),
1302 XtRImmediate, (XtPointer) 0},
1303 { "firstAccumulateTC", "firstAccumulateTC", XtRInt,
1304 sizeof(int), XtOffset(AppDataPtr, firstAccumulateTC),
1305 XtRImmediate, (XtPointer) 1},
1306 { "secondAccumulateTC", "secondAccumulateTC", XtRInt,
1307 sizeof(int), XtOffset(AppDataPtr, secondAccumulateTC),
1308 XtRImmediate, (XtPointer) 1},
1309 { "firstNPS", "firstNPS", XtRInt,
1310 sizeof(int), XtOffset(AppDataPtr, firstNPS),
1311 XtRImmediate, (XtPointer) -1},
1312 { "secondNPS", "secondNPS", XtRInt,
1313 sizeof(int), XtOffset(AppDataPtr, secondNPS),
1314 XtRImmediate, (XtPointer) -1},
1315 { "serverMoves", "serverMoves", XtRString,
1316 sizeof(String), XtOffset(AppDataPtr, serverMovesName),
1317 XtRImmediate, (XtPointer) 0},
1318 { "serverPause", "serverPause", XtRInt,
1319 sizeof(int), XtOffset(AppDataPtr, serverPause),
1320 XtRImmediate, (XtPointer) 0},
1321 { "suppressLoadMoves", "suppressLoadMoves", XtRBoolean,
1322 sizeof(Boolean), XtOffset(AppDataPtr, suppressLoadMoves),
1323 XtRImmediate, (XtPointer) False},
1324 { "userName", "userName", XtRString,
1325 sizeof(String), XtOffset(AppDataPtr, userName),
1326 XtRImmediate, (XtPointer) 0},
1327 { "egtFormats", "egtFormats", XtRString,
1328 sizeof(String), XtOffset(AppDataPtr, egtFormats),
1329 XtRImmediate, (XtPointer) 0},
1330 { "rewindIndex", "rewindIndex", XtRInt,
1331 sizeof(int), XtOffset(AppDataPtr, rewindIndex),
1332 XtRImmediate, (XtPointer) 0},
1333 { "sameColorGames", "sameColorGames", XtRInt,
1334 sizeof(int), XtOffset(AppDataPtr, sameColorGames),
1335 XtRImmediate, (XtPointer) 0},
1336 { "smpCores", "smpCores", XtRInt,
1337 sizeof(int), XtOffset(AppDataPtr, smpCores),
1338 XtRImmediate, (XtPointer) 1},
1339 { "niceEngines", "niceEngines", XtRInt,
1340 sizeof(int), XtOffset(AppDataPtr, niceEngines),
1341 XtRImmediate, (XtPointer) 0},
1342 { "nameOfDebugFile", "nameOfDebugFile", XtRString,
1343 sizeof(String), XtOffset(AppDataPtr, nameOfDebugFile),
1344 XtRImmediate, (XtPointer) "xboard.debug"},
1345 { "engineDebugOutput", "engineDebugOutput", XtRInt,
1346 sizeof(int), XtOffset(AppDataPtr, engineComments),
1347 XtRImmediate, (XtPointer) 0},
1348 { "noGUI", "noGUI", XtRBoolean,
1349 sizeof(Boolean), XtOffset(AppDataPtr, noGUI),
1350 XtRImmediate, (XtPointer) 0},
1351 { "firstOptions", "firstOptions", XtRString,
1352 sizeof(String), XtOffset(AppDataPtr, firstOptions),
1353 XtRImmediate, (XtPointer) "" },
1354 { "secondOptions", "secondOptions", XtRString,
1355 sizeof(String), XtOffset(AppDataPtr, secondOptions),
1356 XtRImmediate, (XtPointer) "" },
1357 { "firstNeedsNoncompliantFEN", "firstNeedsNoncompliantFEN", XtRString,
1358 sizeof(String), XtOffset(AppDataPtr, fenOverride1),
1359 XtRImmediate, (XtPointer) 0 },
1360 { "secondNeedsNoncompliantFEN", "secondNeedsNoncompliantFEN", XtRString,
1361 sizeof(String), XtOffset(AppDataPtr, fenOverride2),
1362 XtRImmediate, (XtPointer) 0 },
1364 // [HGM] Winboard_x UCI options
1365 { "firstIsUCI", "firstIsUCI", XtRBoolean,
1366 sizeof(Boolean), XtOffset(AppDataPtr, firstIsUCI),
1367 XtRImmediate, (XtPointer) False},
1368 { "secondIsUCI", "secondIsUCI", XtRBoolean,
1369 sizeof(Boolean), XtOffset(AppDataPtr, secondIsUCI),
1370 XtRImmediate, (XtPointer) False},
1371 { "firstHasOwnBookUCI", "firstHasOwnBookUCI", XtRBoolean,
1372 sizeof(Boolean), XtOffset(AppDataPtr, firstHasOwnBookUCI),
1373 XtRImmediate, (XtPointer) True},
1374 { "secondHasOwnBookUCI", "secondHasOwnBookUCI", XtRBoolean,
1375 sizeof(Boolean), XtOffset(AppDataPtr, secondHasOwnBookUCI),
1376 XtRImmediate, (XtPointer) True},
1377 { "usePolyglotBook", "usePolyglotBook", XtRBoolean,
1378 sizeof(Boolean), XtOffset(AppDataPtr, usePolyglotBook),
1379 XtRImmediate, (XtPointer) False},
1380 { "defaultHashSize", "defaultHashSize", XtRInt,
1381 sizeof(int), XtOffset(AppDataPtr, defaultHashSize),
1382 XtRImmediate, (XtPointer) 64},
1383 { "defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XtRInt,
1384 sizeof(int), XtOffset(AppDataPtr, defaultCacheSizeEGTB),
1385 XtRImmediate, (XtPointer) 4},
1386 { "polyglotDir", "polyglotDir", XtRString,
1387 sizeof(String), XtOffset(AppDataPtr, polyglotDir),
1388 XtRImmediate, (XtPointer) "." },
1389 { "polyglotBook", "polyglotBook", XtRString,
1390 sizeof(String), XtOffset(AppDataPtr, polyglotBook),
1391 XtRImmediate, (XtPointer) "" },
1392 { "defaultPathEGTB", "defaultPathEGTB", XtRString,
1393 sizeof(String), XtOffset(AppDataPtr, defaultPathEGTB),
1394 XtRImmediate, (XtPointer) "/usr/local/share/egtb"},
1395 { "delayBeforeQuit", "delayBeforeQuit", XtRInt,
1396 sizeof(int), XtOffset(AppDataPtr, delayBeforeQuit),
1397 XtRImmediate, (XtPointer) 0},
1398 { "delayAfterQuit", "delayAfterQuit", XtRInt,
1399 sizeof(int), XtOffset(AppDataPtr, delayAfterQuit),
1400 XtRImmediate, (XtPointer) 0},
1403 XrmOptionDescRec shellOptions[] = {
1404 { "-whitePieceColor", "whitePieceColor", XrmoptionSepArg, NULL },
1405 { "-blackPieceColor", "blackPieceColor", XrmoptionSepArg, NULL },
1406 { "-lightSquareColor", "lightSquareColor", XrmoptionSepArg, NULL },
1407 { "-darkSquareColor", "darkSquareColor", XrmoptionSepArg, NULL },
1408 { "-highlightSquareColor", "highlightSquareColor", XrmoptionSepArg, NULL },
1409 { "-premoveHighlightColor", "premoveHighlightColor", XrmoptionSepArg,NULL},
1410 { "-movesPerSession", "movesPerSession", XrmoptionSepArg, NULL },
1411 { "-mps", "movesPerSession", XrmoptionSepArg, NULL },
1412 { "-timeIncrement", "timeIncrement", XrmoptionSepArg, NULL },
1413 { "-inc", "timeIncrement", XrmoptionSepArg, NULL },
1414 { "-initString", "initString", XrmoptionSepArg, NULL },
1415 { "-firstInitString", "initString", XrmoptionSepArg, NULL },
1416 { "-secondInitString", "secondInitString", XrmoptionSepArg, NULL },
1417 { "-firstComputerString", "firstComputerString", XrmoptionSepArg, NULL },
1418 { "-secondComputerString", "secondComputerString", XrmoptionSepArg, NULL },
1419 { "-firstChessProgram", "firstChessProgram", XrmoptionSepArg, NULL },
1420 { "-fcp", "firstChessProgram", XrmoptionSepArg, NULL },
1421 { "-secondChessProgram", "secondChessProgram", XrmoptionSepArg, NULL },
1422 { "-scp", "secondChessProgram", XrmoptionSepArg, NULL },
1423 { "-firstPlaysBlack", "firstPlaysBlack", XrmoptionSepArg, NULL },
1424 { "-fb", "firstPlaysBlack", XrmoptionNoArg, "True" },
1425 { "-xfb", "firstPlaysBlack", XrmoptionNoArg, "False" },
1426 { "-noChessProgram", "noChessProgram", XrmoptionSepArg, NULL },
1427 { "-ncp", "noChessProgram", XrmoptionNoArg, "True" },
1428 { "-xncp", "noChessProgram", XrmoptionNoArg, "False" },
1429 { "-firstHost", "firstHost", XrmoptionSepArg, NULL },
1430 { "-fh", "firstHost", XrmoptionSepArg, NULL },
1431 { "-secondHost", "secondHost", XrmoptionSepArg, NULL },
1432 { "-sh", "secondHost", XrmoptionSepArg, NULL },
1433 { "-firstDirectory", "firstDirectory", XrmoptionSepArg, NULL },
1434 { "-fd", "firstDirectory", XrmoptionSepArg, NULL },
1435 { "-secondDirectory", "secondDirectory", XrmoptionSepArg, NULL },
1436 { "-sd", "secondDirectory", XrmoptionSepArg, NULL },
1437 { "-bitmapDirectory", "bitmapDirectory", XrmoptionSepArg, NULL },
1438 { "-bm", "bitmapDirectory", XrmoptionSepArg, NULL },
1439 { "-remoteShell", "remoteShell", XrmoptionSepArg, NULL },
1440 { "-rsh", "remoteShell", XrmoptionSepArg, NULL },
1441 { "-remoteUser", "remoteUser", XrmoptionSepArg, NULL },
1442 { "-ruser", "remoteUser", XrmoptionSepArg, NULL },
1443 { "-timeDelay", "timeDelay", XrmoptionSepArg, NULL },
1444 { "-td", "timeDelay", XrmoptionSepArg, NULL },
1445 { "-timeControl", "timeControl", XrmoptionSepArg, NULL },
1446 { "-tc", "timeControl", XrmoptionSepArg, NULL },
1447 { "-internetChessServerMode", "internetChessServerMode",
1448 XrmoptionSepArg, NULL },
1449 { "-ics", "internetChessServerMode", XrmoptionNoArg, "True" },
1450 { "-xics", "internetChessServerMode", XrmoptionNoArg, "False" },
1451 { "-internetChessServerHost", "internetChessServerHost",
1452 XrmoptionSepArg, NULL },
1453 { "-icshost", "internetChessServerHost", XrmoptionSepArg, NULL },
1454 { "-internetChessServerPort", "internetChessServerPort",
1455 XrmoptionSepArg, NULL },
1456 { "-icsport", "internetChessServerPort", XrmoptionSepArg, NULL },
1457 { "-internetChessServerCommPort", "internetChessServerCommPort",
1458 XrmoptionSepArg, NULL },
1459 { "-icscomm", "internetChessServerCommPort", XrmoptionSepArg, NULL },
1460 { "-internetChessServerLogonScript", "internetChessServerLogonScript",
1461 XrmoptionSepArg, NULL },
1462 { "-icslogon", "internetChessServerLogonScript", XrmoptionSepArg, NULL },
1463 { "-internetChessServerHelper", "internetChessServerHelper",
1464 XrmoptionSepArg, NULL },
1465 { "-icshelper", "internetChessServerHelper", XrmoptionSepArg, NULL },
1466 { "-internetChessServerInputBox", "internetChessServerInputBox",
1467 XrmoptionSepArg, NULL },
1468 { "-icsinput", "internetChessServerInputBox", XrmoptionNoArg, "True" },
1469 { "-xicsinput", "internetChessServerInputBox", XrmoptionNoArg, "False" },
1470 { "-icsAlarm", "icsAlarm", XrmoptionSepArg, NULL },
1471 { "-alarm", "icsAlarm", XrmoptionNoArg, "True" },
1472 { "-xalarm", "icsAlarm", XrmoptionNoArg, "False" },
1473 { "-icsAlarmTime", "icsAlarmTime", XrmoptionSepArg, NULL },
1474 { "-useTelnet", "useTelnet", XrmoptionSepArg, NULL },
1475 { "-telnet", "useTelnet", XrmoptionNoArg, "True" },
1476 { "-xtelnet", "useTelnet", XrmoptionNoArg, "False" },
1477 { "-telnetProgram", "telnetProgram", XrmoptionSepArg, NULL },
1478 { "-gateway", "gateway", XrmoptionSepArg, NULL },
1479 { "-loadGameFile", "loadGameFile", XrmoptionSepArg, NULL },
1480 { "-lgf", "loadGameFile", XrmoptionSepArg, NULL },
1481 { "-loadGameIndex", "loadGameIndex", XrmoptionSepArg, NULL },
1482 { "-lgi", "loadGameIndex", XrmoptionSepArg, NULL },
1483 { "-saveGameFile", "saveGameFile", XrmoptionSepArg, NULL },
1484 { "-sgf", "saveGameFile", XrmoptionSepArg, NULL },
1485 { "-autoSaveGames", "autoSaveGames", XrmoptionSepArg, NULL },
1486 { "-autosave", "autoSaveGames", XrmoptionNoArg, "True" },
1487 { "-xautosave", "autoSaveGames", XrmoptionNoArg, "False" },
1488 { "-autoRaiseBoard", "autoRaiseBoard", XrmoptionSepArg, NULL },
1489 { "-autoraise", "autoRaiseBoard", XrmoptionNoArg, "True" },
1490 { "-xautoraise", "autoRaiseBoard", XrmoptionNoArg, "False" },
1491 { "-blindfold", "blindfold", XrmoptionSepArg, NULL },
1492 { "-blind", "blindfold", XrmoptionNoArg, "True" },
1493 { "-xblind", "blindfold", XrmoptionNoArg, "False" },
1494 { "-loadPositionFile", "loadPositionFile", XrmoptionSepArg, NULL },
1495 { "-lpf", "loadPositionFile", XrmoptionSepArg, NULL },
1496 { "-loadPositionIndex", "loadPositionIndex", XrmoptionSepArg, NULL },
1497 { "-lpi", "loadPositionIndex", XrmoptionSepArg, NULL },
1498 { "-savePositionFile", "savePositionFile", XrmoptionSepArg, NULL },
1499 { "-spf", "savePositionFile", XrmoptionSepArg, NULL },
1500 { "-matchMode", "matchMode", XrmoptionSepArg, NULL },
1501 { "-mm", "matchMode", XrmoptionNoArg, "True" },
1502 { "-xmm", "matchMode", XrmoptionNoArg, "False" },
1503 { "-matchGames", "matchGames", XrmoptionSepArg, NULL },
1504 { "-mg", "matchGames", XrmoptionSepArg, NULL },
1505 { "-monoMode", "monoMode", XrmoptionSepArg, NULL },
1506 { "-mono", "monoMode", XrmoptionNoArg, "True" },
1507 { "-xmono", "monoMode", XrmoptionNoArg, "False" },
1508 { "-debugMode", "debugMode", XrmoptionSepArg, NULL },
1509 { "-debug", "debugMode", XrmoptionNoArg, "True" },
1510 { "-xdebug", "debugMode", XrmoptionNoArg, "False" },
1511 { "-clockMode", "clockMode", XrmoptionSepArg, NULL },
1512 { "-clock", "clockMode", XrmoptionNoArg, "True" },
1513 { "-xclock", "clockMode", XrmoptionNoArg, "False" },
1514 { "-boardSize", "boardSize", XrmoptionSepArg, NULL },
1515 { "-size", "boardSize", XrmoptionSepArg, NULL },
1516 { "-searchTime", "searchTime", XrmoptionSepArg, NULL },
1517 { "-st", "searchTime", XrmoptionSepArg, NULL },
1518 { "-searchDepth", "searchDepth", XrmoptionSepArg, NULL },
1519 { "-depth", "searchDepth", XrmoptionSepArg, NULL },
1520 { "-showCoords", "showCoords", XrmoptionSepArg, NULL },
1521 { "-coords", "showCoords", XrmoptionNoArg, "True" },
1522 { "-xcoords", "showCoords", XrmoptionNoArg, "False" },
1524 { "-showJail", "showJail", XrmoptionSepArg, NULL },
1525 { "-jail", "showJail", XrmoptionNoArg, "1" },
1526 { "-sidejail", "showJail", XrmoptionNoArg, "2" },
1527 { "-xjail", "showJail", XrmoptionNoArg, "0" },
1529 { "-showThinking", "showThinking", XrmoptionSepArg, NULL },
1530 { "-thinking", "showThinking", XrmoptionNoArg, "True" },
1531 { "-xthinking", "showThinking", XrmoptionNoArg, "False" },
1532 { "-ponderNextMove", "ponderNextMove", XrmoptionSepArg, NULL },
1533 { "-ponder", "ponderNextMove", XrmoptionNoArg, "True" },
1534 { "-xponder", "ponderNextMove", XrmoptionNoArg, "False" },
1535 { "-periodicUpdates", "periodicUpdates", XrmoptionSepArg, NULL },
1536 { "-periodic", "periodicUpdates", XrmoptionNoArg, "True" },
1537 { "-xperiodic", "periodicUpdates", XrmoptionNoArg, "False" },
1538 { "-clockFont", "clockFont", XrmoptionSepArg, NULL },
1539 { "-coordFont", "coordFont", XrmoptionSepArg, NULL },
1540 { "-font", "font", XrmoptionSepArg, NULL },
1541 { "-ringBellAfterMoves", "ringBellAfterMoves", XrmoptionSepArg, NULL },
1542 { "-bell", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1543 { "-xbell", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1544 { "-movesound", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1545 { "-xmovesound", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1546 { "-autoCallFlag", "autoCallFlag", XrmoptionSepArg, NULL },
1547 { "-autoflag", "autoCallFlag", XrmoptionNoArg, "True" },
1548 { "-xautoflag", "autoCallFlag", XrmoptionNoArg, "False" },
1549 { "-autoFlipView", "autoFlipView", XrmoptionSepArg, NULL },
1550 { "-autoflip", "autoFlipView", XrmoptionNoArg, "True" },
1551 { "-xautoflip", "autoFlipView", XrmoptionNoArg, "False" },
1552 { "-autoObserve", "autoObserve", XrmoptionSepArg, NULL },
1553 { "-autobs", "autoObserve", XrmoptionNoArg, "True" },
1554 { "-xautobs", "autoObserve", XrmoptionNoArg, "False" },
1555 { "-autoComment", "autoComment", XrmoptionSepArg, NULL },
1556 { "-autocomm", "autoComment", XrmoptionNoArg, "True" },
1557 { "-xautocomm", "autoComment", XrmoptionNoArg, "False" },
1558 { "-getMoveList", "getMoveList", XrmoptionSepArg, NULL },
1559 { "-moves", "getMoveList", XrmoptionNoArg, "True" },
1560 { "-xmoves", "getMoveList", XrmoptionNoArg, "False" },
1562 { "-highlightDragging", "highlightDragging", XrmoptionSepArg, NULL },
1563 { "-highdrag", "highlightDragging", XrmoptionNoArg, "True" },
1564 { "-xhighdrag", "highlightDragging", XrmoptionNoArg, "False" },
1566 { "-highlightLastMove", "highlightLastMove", XrmoptionSepArg, NULL },
1567 { "-highlight", "highlightLastMove", XrmoptionNoArg, "True" },
1568 { "-xhighlight", "highlightLastMove", XrmoptionNoArg, "False" },
1569 { "-premove", "premove", XrmoptionSepArg, NULL },
1570 { "-pre", "premove", XrmoptionNoArg, "True" },
1571 { "-xpre", "premove", XrmoptionNoArg, "False" },
1572 { "-testLegality", "testLegality", XrmoptionSepArg, NULL },
1573 { "-legal", "testLegality", XrmoptionNoArg, "True" },
1574 { "-xlegal", "testLegality", XrmoptionNoArg, "False" },
1575 { "-flipView", "flipView", XrmoptionSepArg, NULL },
1576 { "-flip", "flipView", XrmoptionNoArg, "True" },
1577 { "-xflip", "flipView", XrmoptionNoArg, "False" },
1578 { "-cmail", "cmailGameName", XrmoptionSepArg, NULL },
1579 { "-alwaysPromoteToQueen", "alwaysPromoteToQueen",
1580 XrmoptionSepArg, NULL },
1581 { "-queen", "alwaysPromoteToQueen", XrmoptionNoArg, "True" },
1582 { "-xqueen", "alwaysPromoteToQueen", XrmoptionNoArg, "False" },
1583 { "-oldSaveStyle", "oldSaveStyle", XrmoptionSepArg, NULL },
1584 { "-oldsave", "oldSaveStyle", XrmoptionNoArg, "True" },
1585 { "-xoldsave", "oldSaveStyle", XrmoptionNoArg, "False" },
1586 { "-quietPlay", "quietPlay", XrmoptionSepArg, NULL },
1587 { "-quiet", "quietPlay", XrmoptionNoArg, "True" },
1588 { "-xquiet", "quietPlay", XrmoptionNoArg, "False" },
1589 { "-titleInWindow", "titleInWindow", XrmoptionSepArg, NULL },
1590 { "-title", "titleInWindow", XrmoptionNoArg, "True" },
1591 { "-xtitle", "titleInWindow", XrmoptionNoArg, "False" },
1593 { "-zippyTalk", "zippyTalk", XrmoptionSepArg, NULL },
1594 { "-zt", "zippyTalk", XrmoptionNoArg, "True" },
1595 { "-xzt", "zippyTalk", XrmoptionNoArg, "False" },
1596 { "-zippyPlay", "zippyPlay", XrmoptionSepArg, NULL },
1597 { "-zp", "zippyPlay", XrmoptionNoArg, "True" },
1598 { "-xzp", "zippyPlay", XrmoptionNoArg, "False" },
1599 { "-zippyLines", "zippyLines", XrmoptionSepArg, NULL },
1600 { "-zippyPinhead", "zippyPinhead", XrmoptionSepArg, NULL },
1601 { "-zippyPassword", "zippyPassword", XrmoptionSepArg, NULL },
1602 { "-zippyPassword2", "zippyPassword2", XrmoptionSepArg, NULL },
1603 { "-zippyWrongPassword", "zippyWrongPassword", XrmoptionSepArg, NULL },
1604 { "-zippyAcceptOnly", "zippyAcceptOnly", XrmoptionSepArg, NULL },
1605 { "-zippyUseI", "zippyUseI", XrmoptionSepArg, NULL },
1606 { "-zui", "zippyUseI", XrmoptionNoArg, "True" },
1607 { "-xzui", "zippyUseI", XrmoptionNoArg, "False" },
1608 { "-zippyBughouse", "zippyBughouse", XrmoptionSepArg, NULL },
1609 { "-zippyNoplayCrafty", "zippyNoplayCrafty", XrmoptionSepArg, NULL },
1610 { "-znc", "zippyNoplayCrafty", XrmoptionNoArg, "True" },
1611 { "-xznc", "zippyNoplayCrafty", XrmoptionNoArg, "False" },
1612 { "-zippyGameEnd", "zippyGameEnd", XrmoptionSepArg, NULL },
1613 { "-zippyGameStart", "zippyGameStart", XrmoptionSepArg, NULL },
1614 { "-zippyAdjourn", "zippyAdjourn", XrmoptionSepArg, NULL },
1615 { "-zadj", "zippyAdjourn", XrmoptionNoArg, "True" },
1616 { "-xzadj", "zippyAdjourn", XrmoptionNoArg, "False" },
1617 { "-zippyAbort", "zippyAbort", XrmoptionSepArg, NULL },
1618 { "-zab", "zippyAbort", XrmoptionNoArg, "True" },
1619 { "-xzab", "zippyAbort", XrmoptionNoArg, "False" },
1620 { "-zippyVariants", "zippyVariants", XrmoptionSepArg, NULL },
1621 { "-zippyMaxGames", "zippyMaxGames", XrmoptionSepArg, NULL },
1622 { "-zippyReplayTimeout", "zippyReplayTimeout", XrmoptionSepArg, NULL },
1623 { "-zippyShortGame", "zippyShortGame", XrmoptionSepArg, NULL },
1625 { "-flashCount", "flashCount", XrmoptionSepArg, NULL },
1626 { "-flash", "flashCount", XrmoptionNoArg, "3" },
1627 { "-xflash", "flashCount", XrmoptionNoArg, "0" },
1628 { "-flashRate", "flashRate", XrmoptionSepArg, NULL },
1629 { "-pixmapDirectory", "pixmapDirectory", XrmoptionSepArg, NULL },
1630 { "-msLoginDelay", "msLoginDelay", XrmoptionSepArg, NULL },
1631 { "-pixmap", "pixmapDirectory", XrmoptionSepArg, NULL },
1632 { "-colorizeMessages", "colorizeMessages", XrmoptionSepArg, NULL },
1633 { "-colorize", "colorizeMessages", XrmoptionNoArg, "True" },
1634 { "-xcolorize", "colorizeMessages", XrmoptionNoArg, "False" },
1635 { "-colorShout", "colorShout", XrmoptionSepArg, NULL },
1636 { "-colorSShout", "colorSShout", XrmoptionSepArg, NULL },
1637 { "-colorCShout", "colorSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1638 { "-colorChannel1", "colorChannel1", XrmoptionSepArg, NULL },
1639 { "-colorChannel", "colorChannel", XrmoptionSepArg, NULL },
1640 { "-colorKibitz", "colorKibitz", XrmoptionSepArg, NULL },
1641 { "-colorTell", "colorTell", XrmoptionSepArg, NULL },
1642 { "-colorChallenge", "colorChallenge", XrmoptionSepArg, NULL },
1643 { "-colorRequest", "colorRequest", XrmoptionSepArg, NULL },
1644 { "-colorSeek", "colorSeek", XrmoptionSepArg, NULL },
1645 { "-colorNormal", "colorNormal", XrmoptionSepArg, NULL },
1646 { "-soundProgram", "soundProgram", XrmoptionSepArg, NULL },
1647 { "-soundShout", "soundShout", XrmoptionSepArg, NULL },
1648 { "-soundSShout", "soundSShout", XrmoptionSepArg, NULL },
1649 { "-soundCShout", "soundSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1650 { "-soundChannel1", "soundChannel1", XrmoptionSepArg, NULL },
1651 { "-soundChannel", "soundChannel", XrmoptionSepArg, NULL },
1652 { "-soundKibitz", "soundKibitz", XrmoptionSepArg, NULL },
1653 { "-soundTell", "soundTell", XrmoptionSepArg, NULL },
1654 { "-soundChallenge", "soundChallenge", XrmoptionSepArg, NULL },
1655 { "-soundRequest", "soundRequest", XrmoptionSepArg, NULL },
1656 { "-soundSeek", "soundSeek", XrmoptionSepArg, NULL },
1657 { "-soundMove", "soundMove", XrmoptionSepArg, NULL },
1658 { "-soundIcsWin", "soundIcsWin", XrmoptionSepArg, NULL },
1659 { "-soundIcsLoss", "soundIcsLoss", XrmoptionSepArg, NULL },
1660 { "-soundIcsDraw", "soundIcsDraw", XrmoptionSepArg, NULL },
1661 { "-soundIcsUnfinished", "soundIcsUnfinished", XrmoptionSepArg, NULL },
1662 { "-soundIcsAlarm", "soundIcsAlarm", XrmoptionSepArg, NULL },
1663 { "-reuseFirst", "reuseFirst", XrmoptionSepArg, NULL },
1664 { "-reuseChessPrograms", "reuseFirst", XrmoptionSepArg, NULL }, /*compat*/
1665 { "-reuse", "reuseFirst", XrmoptionNoArg, "True" },
1666 { "-xreuse", "reuseFirst", XrmoptionNoArg, "False" },
1667 { "-reuseSecond", "reuseSecond", XrmoptionSepArg, NULL },
1668 { "-reuse2", "reuseSecond", XrmoptionNoArg, "True" },
1669 { "-xreuse2", "reuseSecond", XrmoptionNoArg, "False" },
1670 { "-animateMoving", "animateMoving", XrmoptionSepArg, NULL },
1671 { "-animate", "animateMoving", XrmoptionNoArg, "True" },
1672 { "-xanimate", "animateMoving", XrmoptionNoArg, "False" },
1673 { "-animateDragging", "animateDragging", XrmoptionSepArg, NULL },
1674 { "-drag", "animateDragging", XrmoptionNoArg, "True" },
1675 { "-xdrag", "animateDragging", XrmoptionNoArg, "False" },
1676 { "-animateSpeed", "animateSpeed", XrmoptionSepArg, NULL },
1677 { "-popupExitMessage", "popupExitMessage", XrmoptionSepArg, NULL },
1678 { "-exit", "popupExitMessage", XrmoptionNoArg, "True" },
1679 { "-xexit", "popupExitMessage", XrmoptionNoArg, "False" },
1680 { "-popupMoveErrors", "popupMoveErrors", XrmoptionSepArg, NULL },
1681 { "-popup", "popupMoveErrors", XrmoptionNoArg, "True" },
1682 { "-xpopup", "popupMoveErrors", XrmoptionNoArg, "False" },
1683 { "-fontSizeTolerance", "fontSizeTolerance", XrmoptionSepArg, NULL },
1684 { "-initialMode", "initialMode", XrmoptionSepArg, NULL },
1685 { "-mode", "initialMode", XrmoptionSepArg, NULL },
1686 { "-variant", "variant", XrmoptionSepArg, NULL },
1687 { "-firstProtocolVersion", "firstProtocolVersion", XrmoptionSepArg, NULL },
1688 { "-secondProtocolVersion","secondProtocolVersion",XrmoptionSepArg, NULL },
1689 { "-showButtonBar", "showButtonBar", XrmoptionSepArg, NULL },
1690 { "-buttons", "showButtonBar", XrmoptionNoArg, "True" },
1691 { "-xbuttons", "showButtonBar", XrmoptionNoArg, "False" },
1692 { "-lowTimeWarningColor", "lowTimeWarningColor", XrmoptionSepArg, NULL },
1693 { "-lowTimeWarning", "lowTimeWarning", XrmoptionSepArg, NULL },
1694 /* [AS,HR] New features */
1695 { "-firstScoreAbs", "firstScoreAbs", XrmoptionSepArg, NULL },
1696 { "-secondScoreAbs", "secondScoreAbs", XrmoptionSepArg, NULL },
1697 { "-pgnExtendedInfo", "pgnExtendedInfo", XrmoptionSepArg, NULL },
1698 { "-hideThinkingFromHuman", "hideThinkingFromHuman", XrmoptionSepArg, NULL },
1699 { "-adjudicateLossThreshold", "adjudicateLossThreshold", XrmoptionSepArg, NULL },
1700 { "-pgnEventHeader", "pgnEventHeader", XrmoptionSepArg, NULL },
1701 { "-firstIsUCI", "firstIsUCI", XrmoptionSepArg, NULL },
1702 { "-secondIsUCI", "secondIsUCI", XrmoptionSepArg, NULL },
1703 { "-fUCI", "firstIsUCI", XrmoptionNoArg, "True" },
1704 { "-sUCI", "secondIsUCI", XrmoptionNoArg, "True" },
1705 { "-firstHasOwnBookUCI", "firstHasOwnBookUCI", XrmoptionSepArg, NULL },
1706 { "-secondHasOwnBookUCI", "secondHasOwnBookUCI", XrmoptionSepArg, NULL },
1707 { "-fNoOwnBookUCI", "firstHasOwnBookUCI", XrmoptionNoArg, "False" },
1708 { "-sNoOwnBookUCI", "secondHasOwnBookUCI", XrmoptionNoArg, "False" },
1709 { "-firstXBook", "firstHasOwnBookUCI", XrmoptionNoArg, "False" },
1710 { "-secondXBook", "secondHasOwnBookUCI", XrmoptionNoArg, "False" },
1711 { "-polyglotDir", "polyglotDir", XrmoptionSepArg, NULL },
1712 { "-usePolyglotBook", "usePolyglotBook", XrmoptionSepArg, NULL },
1713 { "-polyglotBook", "polyglotBook", XrmoptionSepArg, NULL },
1714 { "-defaultHashSize", "defaultHashSize", XrmoptionSepArg, NULL },
1715 { "-defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XrmoptionSepArg, NULL },
1716 { "-defaultPathEGTB", "defaultPathEGTB", XrmoptionSepArg, NULL },
1717 { "-defaultFrcPosition", "defaultFrcPosition", XrmoptionSepArg, NULL },
1718 { "-gameListTags", "gameListTags", XrmoptionSepArg, NULL },
1719 // [HGM] I am sure AS added many more options, but we have to fish them out, from the list in winboard.c
1721 /* [HGM,HR] User-selectable board size */
1722 { "-boardWidth", "boardWidth", XrmoptionSepArg, NULL },
1723 { "-boardHeight", "boardHeight", XrmoptionSepArg, NULL },
1724 { "-matchPause", "matchPause", XrmoptionSepArg, NULL },
1726 /* [HGM] new arguments of 4.3.xx. All except first three are back-end options, which should work immediately */
1727 { "-holdingsSize", "holdingsSize", XrmoptionSepArg, NULL }, // requires extensive front-end changes to work
1728 { "-flipBlack", "flipBlack", XrmoptionSepArg, NULL }, // requires front-end changes to work
1729 { "-allWhite", "allWhite", XrmoptionSepArg, NULL }, // requires front-end changes to work
1730 { "-pieceToCharTable", "pieceToCharTable", XrmoptionSepArg, NULL },
1731 { "-alphaRank", "alphaRank", XrmoptionSepArg, NULL },
1732 { "-testClaims", "testClaims", XrmoptionSepArg, NULL },
1733 { "-checkMates", "checkMates", XrmoptionSepArg, NULL },
1734 { "-materialDraws", "materialDraws", XrmoptionSepArg, NULL },
1735 { "-trivialDraws", "trivialDraws", XrmoptionSepArg, NULL },
1736 { "-ruleMoves", "ruleMoves", XrmoptionSepArg, NULL },
1737 { "-repeatsToDraw", "repeatsToDraw", XrmoptionSepArg, NULL },
1738 { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL },
1739 { "-userName", "userName", XrmoptionSepArg, NULL },
1740 { "-autoKibitz", "autoKibitz", XrmoptionNoArg, "True" },
1741 { "-firstTimeOdds", "firstTimeOdds", XrmoptionSepArg, NULL },
1742 { "-secondTimeOdds", "secondTimeOdds", XrmoptionSepArg, NULL },
1743 { "-timeOddsMode", "timeOddsMode", XrmoptionSepArg, NULL },
1744 { "-firstAccumulateTC", "firstAccumulateTC", XrmoptionSepArg, NULL },
1745 { "-secondAccumulateTC", "secondAccumulateTC", XrmoptionSepArg, NULL },
1746 { "-firstNPS", "firstNPS", XrmoptionSepArg, NULL },
1747 { "-secondNPS", "secondNPS", XrmoptionSepArg, NULL },
1748 { "-serverMoves", "serverMoves", XrmoptionSepArg, NULL },
1749 { "-serverPause", "serverPause", XrmoptionSepArg, NULL },
1750 { "-suppressLoadMoves", "suppressLoadMoves", XrmoptionSepArg, NULL },
1751 { "-egtFormats", "egtFormats", XrmoptionSepArg, NULL },
1752 { "-userName", "userName", XrmoptionSepArg, NULL },
1753 { "-smpCores", "smpCores", XrmoptionSepArg, NULL },
1754 { "-sameColorGames", "sameColorGames", XrmoptionSepArg, NULL },
1755 { "-rewindIndex", "rewindIndex", XrmoptionSepArg, NULL },
1756 { "-niceEngines", "niceEngines", XrmoptionSepArg, NULL },
1757 { "-delayBeforeQuit", "delayBeforeQuit", XrmoptionSepArg, NULL },
1758 { "-delayAfterQuit", "delayAfterQuit", XrmoptionSepArg, NULL },
1759 { "-nameOfDebugFile", "nameOfDebugFile", XrmoptionSepArg, NULL },
1760 { "-debugFile", "nameOfDebugFile", XrmoptionSepArg, NULL },
1761 { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL },
1762 { "-noGUI", "noGUI", XrmoptionNoArg, "True" },
1763 { "-firstOptions", "firstOptions", XrmoptionSepArg, NULL },
1764 { "-secondOptions", "secondOptions", XrmoptionSepArg, NULL },
1765 { "-firstNeedsNoncompliantFEN", "firstNeedsNoncompliantFEN", XrmoptionSepArg, NULL },
1766 { "-secondNeedsNoncompliantFEN", "secondNeedsNoncompliantFEN", XrmoptionSepArg, NULL },
1770 XtActionsRec boardActions[] = {
1771 { "DrawPosition", DrawPositionProc },
1772 { "HandleUserMove", HandleUserMove },
1773 { "AnimateUserMove", AnimateUserMove },
1774 { "FileNameAction", FileNameAction },
1775 { "AskQuestionProc", AskQuestionProc },
1776 { "AskQuestionReplyAction", AskQuestionReplyAction },
1777 { "PieceMenuPopup", PieceMenuPopup },
1778 { "WhiteClock", WhiteClock },
1779 { "BlackClock", BlackClock },
1780 { "Iconify", Iconify },
1781 { "ResetProc", ResetProc },
1782 { "LoadGameProc", LoadGameProc },
1783 { "LoadNextGameProc", LoadNextGameProc },
1784 { "LoadPrevGameProc", LoadPrevGameProc },
1785 { "LoadSelectedProc", LoadSelectedProc },
1786 { "ReloadGameProc", ReloadGameProc },
1787 { "LoadPositionProc", LoadPositionProc },
1788 { "LoadNextPositionProc", LoadNextPositionProc },
1789 { "LoadPrevPositionProc", LoadPrevPositionProc },
1790 { "ReloadPositionProc", ReloadPositionProc },
1791 { "CopyPositionProc", CopyPositionProc },
1792 { "PastePositionProc", PastePositionProc },
1793 { "CopyGameProc", CopyGameProc },
1794 { "PasteGameProc", PasteGameProc },
1795 { "SaveGameProc", SaveGameProc },
1796 { "SavePositionProc", SavePositionProc },
1797 { "MailMoveProc", MailMoveProc },
1798 { "ReloadCmailMsgProc", ReloadCmailMsgProc },
1799 { "QuitProc", QuitProc },
1800 { "MachineWhiteProc", MachineWhiteProc },
1801 { "MachineBlackProc", MachineBlackProc },
1802 { "AnalysisModeProc", AnalyzeModeProc },
1803 { "AnalyzeFileProc", AnalyzeFileProc },
1804 { "TwoMachinesProc", TwoMachinesProc },
1805 { "IcsClientProc", IcsClientProc },
1806 { "EditGameProc", EditGameProc },
1807 { "EditPositionProc", EditPositionProc },
1808 { "TrainingProc", EditPositionProc },
1809 { "EngineOutputProc", EngineOutputProc}, // [HGM] Winboard_x engine-output window
1810 { "ShowGameListProc", ShowGameListProc },
1811 { "ShowMoveListProc", HistoryShowProc},
1812 { "EditTagsProc", EditCommentProc },
1813 { "EditCommentProc", EditCommentProc },
1814 { "IcsAlarmProc", IcsAlarmProc },
1815 { "IcsInputBoxProc", IcsInputBoxProc },
1816 { "PauseProc", PauseProc },
1817 { "AcceptProc", AcceptProc },
1818 { "DeclineProc", DeclineProc },
1819 { "RematchProc", RematchProc },
1820 { "CallFlagProc", CallFlagProc },
1821 { "DrawProc", DrawProc },
1822 { "AdjournProc", AdjournProc },
1823 { "AbortProc", AbortProc },
1824 { "ResignProc", ResignProc },
1825 { "AdjuWhiteProc", AdjuWhiteProc },
1826 { "AdjuBlackProc", AdjuBlackProc },
1827 { "AdjuDrawProc", AdjuDrawProc },
1828 { "EnterKeyProc", EnterKeyProc },
1829 { "StopObservingProc", StopObservingProc },
1830 { "StopExaminingProc", StopExaminingProc },
1831 { "BackwardProc", BackwardProc },
1832 { "ForwardProc", ForwardProc },
1833 { "ToStartProc", ToStartProc },
1834 { "ToEndProc", ToEndProc },
1835 { "RevertProc", RevertProc },
1836 { "TruncateGameProc", TruncateGameProc },
1837 { "MoveNowProc", MoveNowProc },
1838 { "RetractMoveProc", RetractMoveProc },
1839 { "AlwaysQueenProc", AlwaysQueenProc },
1840 { "AnimateDraggingProc", AnimateDraggingProc },
1841 { "AnimateMovingProc", AnimateMovingProc },
1842 { "AutoflagProc", AutoflagProc },
1843 { "AutoflipProc", AutoflipProc },
1844 { "AutobsProc", AutobsProc },
1845 { "AutoraiseProc", AutoraiseProc },
1846 { "AutosaveProc", AutosaveProc },
1847 { "BlindfoldProc", BlindfoldProc },
1848 { "FlashMovesProc", FlashMovesProc },
1849 { "FlipViewProc", FlipViewProc },
1850 { "GetMoveListProc", GetMoveListProc },
1852 { "HighlightDraggingProc", HighlightDraggingProc },
1854 { "HighlightLastMoveProc", HighlightLastMoveProc },
1855 { "IcsAlarmProc", IcsAlarmProc },
1856 { "MoveSoundProc", MoveSoundProc },
1857 { "OldSaveStyleProc", OldSaveStyleProc },
1858 { "PeriodicUpdatesProc", PeriodicUpdatesProc },
1859 { "PonderNextMoveProc", PonderNextMoveProc },
1860 { "PopupExitMessageProc", PopupExitMessageProc },
1861 { "PopupMoveErrorsProc", PopupMoveErrorsProc },
1862 { "PremoveProc", PremoveProc },
1863 { "QuietPlayProc", QuietPlayProc },
1864 { "ShowCoordsProc", ShowCoordsProc },
1865 { "ShowThinkingProc", ShowThinkingProc },
1866 { "HideThinkingProc", HideThinkingProc },
1867 { "TestLegalityProc", TestLegalityProc },
1868 { "InfoProc", InfoProc },
1869 { "ManProc", ManProc },
1870 { "HintProc", HintProc },
1871 { "BookProc", BookProc },
1872 { "AboutGameProc", AboutGameProc },
1873 { "AboutProc", AboutProc },
1874 { "DebugProc", DebugProc },
1875 { "NothingProc", NothingProc },
1876 { "CommentPopDown", (XtActionProc) CommentPopDown },
1877 { "EditCommentPopDown", (XtActionProc) EditCommentPopDown },
1878 { "TagsPopDown", (XtActionProc) TagsPopDown },
1879 { "ErrorPopDown", (XtActionProc) ErrorPopDown },
1880 { "ICSInputBoxPopDown", (XtActionProc) ICSInputBoxPopDown },
1881 { "AnalysisPopDown", (XtActionProc) AnalysisPopDown },
1882 { "FileNamePopDown", (XtActionProc) FileNamePopDown },
1883 { "AskQuestionPopDown", (XtActionProc) AskQuestionPopDown },
1884 { "GameListPopDown", (XtActionProc) GameListPopDown },
1885 { "PromotionPopDown", (XtActionProc) PromotionPopDown },
1886 { "HistoryPopDown", (XtActionProc) HistoryPopDown },
1887 { "EngineOutputPopDown", (XtActionProc) EngineOutputPopDown },
1888 { "ShufflePopDown", (XtActionProc) ShufflePopDown },
1889 { "EnginePopDown", (XtActionProc) EnginePopDown },
1890 { "UciPopDown", (XtActionProc) UciPopDown },
1891 { "TimeControlPopDown", (XtActionProc) TimeControlPopDown },
1892 { "NewVariantPopDown", (XtActionProc) NewVariantPopDown },
1893 { "SettingsPopDown", (XtActionProc) SettingsPopDown },
1896 char globalTranslations[] =
1897 ":<Key>R: ResignProc() \n \
1898 :<Key>r: ResetProc() \n \
1899 :<Key>g: LoadGameProc() \n \
1900 :<Key>N: LoadNextGameProc() \n \
1901 :<Key>P: LoadPrevGameProc() \n \
1902 :<Key>Q: QuitProc() \n \
1903 :<Key>F: ToEndProc() \n \
1904 :<Key>f: ForwardProc() \n \
1905 :<Key>B: ToStartProc() \n \
1906 :<Key>b: BackwardProc() \n \
1907 :<Key>p: PauseProc() \n \
1908 :<Key>d: DrawProc() \n \
1909 :<Key>t: CallFlagProc() \n \
1910 :<Key>i: Iconify() \n \
1911 :<Key>c: Iconify() \n \
1912 :<Key>v: FlipViewProc() \n \
1913 <KeyDown>Control_L: BackwardProc() \n \
1914 <KeyUp>Control_L: ForwardProc() \n \
1915 <KeyDown>Control_R: BackwardProc() \n \
1916 <KeyUp>Control_R: ForwardProc() \n \
1917 Shift<Key>1: AskQuestionProc(\"Direct command\",\
1918 \"Send to chess program:\",,1) \n \
1919 Shift<Key>2: AskQuestionProc(\"Direct command\",\
1920 \"Send to second chess program:\",,2) \n";
1922 char boardTranslations[] =
1923 "<Btn1Down>: HandleUserMove() \n \
1924 <Btn1Up>: HandleUserMove() \n \
1925 <Btn1Motion>: AnimateUserMove() \n \
1926 Shift<Btn2Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD)\
1927 PieceMenuPopup(menuB) \n \
1928 Any<Btn2Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD) \
1929 PieceMenuPopup(menuW) \n \
1930 Shift<Btn3Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD)\
1931 PieceMenuPopup(menuW) \n \
1932 Any<Btn3Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD) \
1933 PieceMenuPopup(menuB) \n";
1935 char whiteTranslations[] = "<BtnDown>: WhiteClock()\n";
1936 char blackTranslations[] = "<BtnDown>: BlackClock()\n";
1938 char ICSInputTranslations[] =
1939 "<Key>Return: EnterKeyProc() \n";
1941 String xboardResources[] = {
1942 "*fileName*value.translations: #override\\n <Key>Return: FileNameAction()",
1943 "*question*value.translations: #override\\n <Key>Return: AskQuestionReplyAction()",
1944 "*errorpopup*translations: #override\\n <Key>Return: ErrorPopDown()",
1949 /* Max possible square size */
1950 #define MAXSQSIZE 256
1952 static int xpm_avail[MAXSQSIZE];
1954 #ifdef HAVE_DIR_STRUCT
1956 /* Extract piece size from filename */
1958 xpm_getsize(name, len, ext)
1969 if ((p=strchr(name, '.')) == NULL ||
1970 StrCaseCmp(p+1, ext) != 0)
1976 while (*p && isdigit(*p))
1983 /* Setup xpm_avail */
1985 xpm_getavail(dirname, ext)
1993 for (i=0; i<MAXSQSIZE; ++i)
1996 if (appData.debugMode)
1997 fprintf(stderr, "XPM dir:%s:ext:%s:\n", dirname, ext);
1999 dir = opendir(dirname);
2002 fprintf(stderr, _("%s: Can't access XPM directory %s\n"),
2003 programName, dirname);
2007 while ((ent=readdir(dir)) != NULL) {
2008 i = xpm_getsize(ent->d_name, NAMLEN(ent), ext);
2009 if (i > 0 && i < MAXSQSIZE)
2019 xpm_print_avail(fp, ext)
2025 fprintf(fp, _("Available `%s' sizes:\n"), ext);
2026 for (i=1; i<MAXSQSIZE; ++i) {
2032 /* Return XPM piecesize closest to size */
2034 xpm_closest_to(dirname, size, ext)
2040 int sm_diff = MAXSQSIZE;
2044 xpm_getavail(dirname, ext);
2046 if (appData.debugMode)
2047 xpm_print_avail(stderr, ext);
2049 for (i=1; i<MAXSQSIZE; ++i) {
2052 diff = (diff<0) ? -diff : diff;
2053 if (diff < sm_diff) {
2061 fprintf(stderr, _("Error: No `%s' files!\n"), ext);
2067 #else /* !HAVE_DIR_STRUCT */
2068 /* If we are on a system without a DIR struct, we can't
2069 read the directory, so we can't collect a list of
2070 filenames, etc., so we can't do any size-fitting. */
2072 xpm_closest_to(dirname, size, ext)
2077 fprintf(stderr, _("\
2078 Warning: No DIR structure found on this system --\n\
2079 Unable to autosize for XPM/XIM pieces.\n\
2080 Please report this error to frankm@hiwaay.net.\n\
2081 Include system type & operating system in message.\n"));
2084 #endif /* HAVE_DIR_STRUCT */
2086 static char *cnames[9] = { "black", "red", "green", "yellow", "blue",
2087 "magenta", "cyan", "white" };
2091 TextColors textColors[(int)NColorClasses];
2093 /* String is: "fg, bg, attr". Which is 0, 1, 2 */
2095 parse_color(str, which)
2099 char *p, buf[100], *d;
2102 if (strlen(str) > 99) /* watch bounds on buf */
2107 for (i=0; i<which; ++i) {
2114 /* Could be looking at something like:
2116 .. in which case we want to stop on a comma also */
2117 while (*p && *p != ',' && !isalpha(*p) && !isdigit(*p))
2121 return -1; /* Use default for empty field */
2124 if (which == 2 || isdigit(*p))
2127 while (*p && isalpha(*p))
2132 for (i=0; i<8; ++i) {
2133 if (!StrCaseCmp(buf, cnames[i]))
2134 return which? (i+40) : (i+30);
2136 if (!StrCaseCmp(buf, "default")) return -1;
2138 fprintf(stderr, _("%s: unrecognized color %s\n"), programName, buf);
2143 parse_cpair(cc, str)
2147 if ((textColors[(int)cc].fg=parse_color(str, 0)) == -2) {
2148 fprintf(stderr, _("%s: can't parse foreground color in `%s'\n"),
2153 /* bg and attr are optional */
2154 textColors[(int)cc].bg = parse_color(str, 1);
2155 if ((textColors[(int)cc].attr = parse_color(str, 2)) < 0) {
2156 textColors[(int)cc].attr = 0;
2162 /* Arrange to catch delete-window events */
2163 Atom wm_delete_window;
2165 CatchDeleteWindow(Widget w, String procname)
2168 XSetWMProtocols(xDisplay, XtWindow(w), &wm_delete_window, 1);
2169 snprintf(buf, sizeof(buf), "<Message>WM_PROTOCOLS: %s() \n", procname);
2170 XtAugmentTranslations(w, XtParseTranslationTable(buf));
2177 XtSetArg(args[0], XtNiconic, False);
2178 XtSetValues(shellWidget, args, 1);
2180 XtPopup(shellWidget, XtGrabNone); /* Raise if lowered */
2184 // eventually, all layout determining code should go into a subroutine, but until then IDSIZE remains undefined
2186 #define BoardSize int
2187 void InitDrawingSizes(BoardSize boardSize, int flags)
2188 { // [HGM] resize is functional now, but for board format changes only (nr of ranks, files)
2189 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
2191 XtGeometryResult gres;
2194 if(!formWidget) return;
2197 * Enable shell resizing.
2199 shellArgs[0].value = (XtArgVal) &w;
2200 shellArgs[1].value = (XtArgVal) &h;
2201 XtGetValues(shellWidget, shellArgs, 2);
2203 shellArgs[4].value = 2*w; shellArgs[2].value = 10;
2204 shellArgs[5].value = 2*h; shellArgs[3].value = 10;
2205 XtSetValues(shellWidget, &shellArgs[2], 4);
2207 XtSetArg(args[0], XtNdefaultDistance, &sep);
2208 XtGetValues(formWidget, args, 1);
2210 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2211 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2214 XtSetArg(args[0], XtNwidth, boardWidth);
2215 XtSetArg(args[1], XtNheight, boardHeight);
2216 XtSetValues(boardWidget, args, 2);
2218 timerWidth = (boardWidth - sep) / 2;
2219 XtSetArg(args[0], XtNwidth, timerWidth);
2220 XtSetValues(whiteTimerWidget, args, 1);
2221 XtSetValues(blackTimerWidget, args, 1);
2223 XawFormDoLayout(formWidget, False);
2225 if (appData.titleInWindow) {
2227 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2228 XtSetArg(args[i], XtNheight, &h); i++;
2229 XtGetValues(titleWidget, args, i);
2231 w = boardWidth - 2*bor;
2233 XtSetArg(args[0], XtNwidth, &w);
2234 XtGetValues(menuBarWidget, args, 1);
2235 w = boardWidth - w - sep - 2*bor - 2; // WIDTH_FUDGE
2238 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
2239 if (gres != XtGeometryYes && appData.debugMode) {
2241 _("%s: titleWidget geometry error %d %d %d %d %d\n"),
2242 programName, gres, w, h, wr, hr);
2246 XawFormDoLayout(formWidget, True);
2249 * Inhibit shell resizing.
2251 shellArgs[0].value = w = (XtArgVal) boardWidth + marginW;
2252 shellArgs[1].value = h = (XtArgVal) boardHeight + marginH;
2253 shellArgs[4].value = shellArgs[2].value = w;
2254 shellArgs[5].value = shellArgs[3].value = h;
2255 XtSetValues(shellWidget, &shellArgs[0], 6);
2257 // [HGM] pieces: tailor piece bitmaps to needs of specific variant
2260 for(i=0; i<4; i++) {
2262 for(p=0; p<=(int)WhiteKing; p++)
2263 xpmPieceBitmap[i][p] = xpmPieceBitmap2[i][p]; // defaults
2264 if(gameInfo.variant == VariantShogi) {
2265 xpmPieceBitmap[i][(int)WhiteCannon] = xpmPieceBitmap2[i][(int)WhiteKing+1];
2266 xpmPieceBitmap[i][(int)WhiteNightrider] = xpmPieceBitmap2[i][(int)WhiteKing+2];
2267 xpmPieceBitmap[i][(int)WhiteSilver] = xpmPieceBitmap2[i][(int)WhiteKing+3];
2268 xpmPieceBitmap[i][(int)WhiteGrasshopper] = xpmPieceBitmap2[i][(int)WhiteKing+4];
2269 xpmPieceBitmap[i][(int)WhiteQueen] = xpmPieceBitmap2[i][(int)WhiteLance];
2272 if(gameInfo.variant == VariantGothic) {
2273 xpmPieceBitmap[i][(int)WhiteMarshall] = xpmPieceBitmap2[i][(int)WhiteSilver];
2277 // [HGM] why are thee ximMasks used at all? the ximPieceBitmaps seem to be never used!
2278 for(p=0; p<=(int)WhiteKing; p++)
2279 ximMaskPm[p] = ximMaskPm2[p]; // defaults
2280 if(gameInfo.variant == VariantShogi) {
2281 ximMaskPm[(int)WhiteCannon] = ximMaskPm2[(int)WhiteKing+1];
2282 ximMaskPm[(int)WhiteNightrider] = ximMaskPm2[(int)WhiteKing+2];
2283 ximMaskPm[(int)WhiteSilver] = ximMaskPm2[(int)WhiteKing+3];
2284 ximMaskPm[(int)WhiteGrasshopper] = ximMaskPm2[(int)WhiteKing+4];
2285 ximMaskPm[(int)WhiteQueen] = ximMaskPm2[(int)WhiteLance];
2288 if(gameInfo.variant == VariantGothic) {
2289 ximMaskPm[(int)WhiteMarshall] = ximMaskPm2[i][(int)WhiteSilver];
2295 for(i=0; i<2; i++) {
2297 for(p=0; p<=(int)WhiteKing; p++)
2298 pieceBitmap[i][p] = pieceBitmap2[i][p]; // defaults
2299 if(gameInfo.variant == VariantShogi) {
2300 pieceBitmap[i][(int)WhiteCannon] = pieceBitmap2[i][(int)WhiteKing+1];
2301 pieceBitmap[i][(int)WhiteNightrider] = pieceBitmap2[i][(int)WhiteKing+2];
2302 pieceBitmap[i][(int)WhiteSilver] = pieceBitmap2[i][(int)WhiteKing+3];
2303 pieceBitmap[i][(int)WhiteGrasshopper] = pieceBitmap2[i][(int)WhiteKing+4];
2304 pieceBitmap[i][(int)WhiteQueen] = pieceBitmap2[i][(int)WhiteLance];
2307 if(gameInfo.variant == VariantGothic) {
2308 pieceBitmap[i][(int)WhiteMarshall] = pieceBitmap2[i][(int)WhiteSilver];
2324 int i, j, clockFontPxlSize, coordFontPxlSize, fontPxlSize;
2325 XSetWindowAttributes window_attributes;
2327 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
2328 XrmValue vFrom, vTo;
2329 XtGeometryResult gres;
2332 int forceMono = False;
2335 // [HGM] before anything else, expand any indirection files amongst options
2336 char *argvCopy[1000]; // 1000 seems enough
2337 char newArgs[10000]; // holds actual characters
2340 srandom(time(0)); // [HGM] book: make random truly random
2343 for(i=0; i<argc; i++) {
2344 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2345 //fprintf(stderr, "arg %s\n", argv[i]);
2346 if(argv[i][0] != '@') argvCopy[j++] = argv[i]; else {
2348 FILE *f = fopen(argv[i]+1, "rb");
2349 if(f == NULL) { fprintf(stderr, _("ignore %s\n"), argv[i]); continue; } // do not expand non-existing
2350 argvCopy[j++] = newArgs + k; // get ready for first argument from file
2351 while((c = fgetc(f)) != EOF) { // each line of file inserts 1 argument in the list
2353 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2354 newArgs[k++] = 0; // terminate current arg
2355 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2356 argvCopy[j++] = newArgs + k; // get ready for next
2358 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2371 if(appData.debugMode,1) { // OK, appData is not initialized here yet...
2372 for(i=0; i<argc; i++) fprintf(stderr, "argv[%2d] = '%s'\n", i, argv[i]);
2378 setbuf(stdout, NULL);
2379 setbuf(stderr, NULL);
2382 programName = strrchr(argv[0], '/');
2383 if (programName == NULL)
2384 programName = argv[0];
2389 XtSetLanguageProc(NULL, NULL, NULL);
2390 bindtextdomain(PACKAGE, LOCALEDIR);
2391 textdomain(PACKAGE);
2395 XtAppInitialize(&appContext, "XBoard", shellOptions,
2396 XtNumber(shellOptions),
2397 &argc, argv, xboardResources, NULL, 0);
2399 fprintf(stderr, _("%s: unrecognized argument %s\n"),
2400 programName, argv[1]);
2401 fprintf(stderr, "Recognized options:\n");
2402 for(i = 0; i < XtNumber(shellOptions); i++) {
2403 j = fprintf(stderr, " %s%s", shellOptions[i].option,
2404 (shellOptions[i].argKind == XrmoptionSepArg
2406 if (i++ < XtNumber(shellOptions)) {
2407 fprintf(stderr, "%*c%s%s\n", 40 - j, ' ',
2408 shellOptions[i].option,
2409 (shellOptions[i].argKind == XrmoptionSepArg
2412 fprintf(stderr, "\n");
2418 if ((chessDir = (char *) getenv("CHESSDIR")) == NULL) {
2421 if (chdir(chessDir) != 0) {
2422 fprintf(stderr, _("%s: can't cd to CHESSDIR: "), programName);
2429 if (p == NULL) p = "/tmp";
2430 i = strlen(p) + strlen("/.xboardXXXXXx.pgn") + 1;
2431 gameCopyFilename = (char*) malloc(i);
2432 gamePasteFilename = (char*) malloc(i);
2433 snprintf(gameCopyFilename,i, "%s/.xboard%05uc.pgn", p, getpid());
2434 snprintf(gamePasteFilename,i, "%s/.xboard%05up.pgn", p, getpid());
2436 XtGetApplicationResources(shellWidget, (XtPointer) &appData,
2437 clientResources, XtNumber(clientResources),
2440 if (appData.debugMode && appData.nameOfDebugFile && strcmp(appData.nameOfDebugFile, "stderr")) {
2441 /* [DM] debug info to file [HGM] make the filename a command-line option, and allow it to remain stderr */
2442 if ((debugFP = fopen(appData.nameOfDebugFile, "w")) == NULL) {
2443 printf(_("Failed to open file '%s'\n"), appData.nameOfDebugFile);
2446 setbuf(debugFP, NULL);
2449 /* [HGM,HR] make sure board size is acceptable */
2450 if(appData.NrFiles > BOARD_SIZE ||
2451 appData.NrRanks > BOARD_SIZE )
2452 DisplayFatalError(_("Recompile with BOARD_SIZE > 12, to support this size"), 0, 2);
2455 /* This feature does not work; animation needs a rewrite */
2456 appData.highlightDragging = FALSE;
2460 xDisplay = XtDisplay(shellWidget);
2461 xScreen = DefaultScreen(xDisplay);
2462 wm_delete_window = XInternAtom(xDisplay, "WM_DELETE_WINDOW", True);
2464 gameInfo.variant = StringToVariant(appData.variant);
2465 InitPosition(FALSE);
2468 * Determine boardSize
2470 gameInfo.boardWidth = gameInfo.boardHeight = 8; // [HGM] boardsize: make sure we start as 8x8
2473 // [HGM] as long as we have not created the possibility to change size while running, start with requested size
2474 gameInfo.boardWidth = appData.NrFiles > 0 ? appData.NrFiles : 8;
2475 gameInfo.boardHeight = appData.NrRanks > 0 ? appData.NrRanks : 8;
2476 gameInfo.holdingsWidth = appData.holdingsSize > 0 ? 2 : 0;
2481 InitDrawingSizes(-1, 0); // [HGM] initsize: make this into a subroutine
2483 if (isdigit(appData.boardSize[0])) {
2484 i = sscanf(appData.boardSize, "%d,%d,%d,%d,%d,%d,%d", &squareSize,
2485 &lineGap, &clockFontPxlSize, &coordFontPxlSize,
2486 &fontPxlSize, &smallLayout, &tinyLayout);
2488 fprintf(stderr, _("%s: bad boardSize syntax %s\n"),
2489 programName, appData.boardSize);
2493 /* Find some defaults; use the nearest known size */
2494 SizeDefaults *szd, *nearest;
2495 int distance = 99999;
2496 nearest = szd = sizeDefaults;
2497 while (szd->name != NULL) {
2498 if (abs(szd->squareSize - squareSize) < distance) {
2500 distance = abs(szd->squareSize - squareSize);
2501 if (distance == 0) break;
2505 if (i < 2) lineGap = nearest->lineGap;
2506 if (i < 3) clockFontPxlSize = nearest->clockFontPxlSize;
2507 if (i < 4) coordFontPxlSize = nearest->coordFontPxlSize;
2508 if (i < 5) fontPxlSize = nearest->fontPxlSize;
2509 if (i < 6) smallLayout = nearest->smallLayout;
2510 if (i < 7) tinyLayout = nearest->tinyLayout;
2513 SizeDefaults *szd = sizeDefaults;
2514 if (*appData.boardSize == NULLCHAR) {
2515 while (DisplayWidth(xDisplay, xScreen) < szd->minScreenSize ||
2516 DisplayHeight(xDisplay, xScreen) < szd->minScreenSize) {
2519 if (szd->name == NULL) szd--;
2521 while (szd->name != NULL &&
2522 StrCaseCmp(szd->name, appData.boardSize) != 0) szd++;
2523 if (szd->name == NULL) {
2524 fprintf(stderr, _("%s: unrecognized boardSize name %s\n"),
2525 programName, appData.boardSize);
2529 squareSize = szd->squareSize;
2530 lineGap = szd->lineGap;
2531 clockFontPxlSize = szd->clockFontPxlSize;
2532 coordFontPxlSize = szd->coordFontPxlSize;
2533 fontPxlSize = szd->fontPxlSize;
2534 smallLayout = szd->smallLayout;
2535 tinyLayout = szd->tinyLayout;
2538 /* Now, using squareSize as a hint, find a good XPM/XIM set size */
2539 if (strlen(appData.pixmapDirectory) > 0) {
2540 p = ExpandPathName(appData.pixmapDirectory);
2542 fprintf(stderr, _("Error expanding path name \"%s\"\n"),
2543 appData.pixmapDirectory);
2546 if (appData.debugMode) {
2547 fprintf(stderr, _("\
2548 XBoard square size (hint): %d\n\
2549 %s fulldir:%s:\n"), squareSize, IMAGE_EXT, p);
2551 squareSize = xpm_closest_to(p, squareSize, IMAGE_EXT);
2552 if (appData.debugMode) {
2553 fprintf(stderr, _("Closest %s size: %d\n"), IMAGE_EXT, squareSize);
2557 /* [HR] height treated separately (hacked) */
2558 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2559 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2560 if (appData.showJail == 1) {
2561 /* Jail on top and bottom */
2562 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2563 XtSetArg(boardArgs[2], XtNheight,
2564 boardHeight + 2*(lineGap + squareSize));
2565 } else if (appData.showJail == 2) {
2567 XtSetArg(boardArgs[1], XtNwidth,
2568 boardWidth + 2*(lineGap + squareSize));
2569 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2572 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2573 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2577 * Determine what fonts to use.
2579 appData.clockFont = FindFont(appData.clockFont, clockFontPxlSize);
2580 clockFontID = XLoadFont(xDisplay, appData.clockFont);
2581 clockFontStruct = XQueryFont(xDisplay, clockFontID);
2582 appData.coordFont = FindFont(appData.coordFont, coordFontPxlSize);
2583 coordFontID = XLoadFont(xDisplay, appData.coordFont);
2584 coordFontStruct = XQueryFont(xDisplay, coordFontID);
2585 appData.font = FindFont(appData.font, fontPxlSize);
2586 countFontID = XLoadFont(xDisplay, appData.coordFont); // [HGM] holdings
2587 countFontStruct = XQueryFont(xDisplay, countFontID);
2588 // appData.font = FindFont(appData.font, fontPxlSize);
2590 xdb = XtDatabase(xDisplay);
2591 XrmPutStringResource(&xdb, "*font", appData.font);
2594 * Detect if there are not enough colors available and adapt.
2596 if (DefaultDepth(xDisplay, xScreen) <= 2) {
2597 appData.monoMode = True;
2600 if (!appData.monoMode) {
2601 vFrom.addr = (caddr_t) appData.lightSquareColor;
2602 vFrom.size = strlen(appData.lightSquareColor);
2603 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2604 if (vTo.addr == NULL) {
2605 appData.monoMode = True;
2608 lightSquareColor = *(Pixel *) vTo.addr;
2611 if (!appData.monoMode) {
2612 vFrom.addr = (caddr_t) appData.darkSquareColor;
2613 vFrom.size = strlen(appData.darkSquareColor);
2614 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2615 if (vTo.addr == NULL) {
2616 appData.monoMode = True;
2619 darkSquareColor = *(Pixel *) vTo.addr;
2622 if (!appData.monoMode) {
2623 vFrom.addr = (caddr_t) appData.whitePieceColor;
2624 vFrom.size = strlen(appData.whitePieceColor);
2625 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2626 if (vTo.addr == NULL) {
2627 appData.monoMode = True;
2630 whitePieceColor = *(Pixel *) vTo.addr;
2633 if (!appData.monoMode) {
2634 vFrom.addr = (caddr_t) appData.blackPieceColor;
2635 vFrom.size = strlen(appData.blackPieceColor);
2636 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2637 if (vTo.addr == NULL) {
2638 appData.monoMode = True;
2641 blackPieceColor = *(Pixel *) vTo.addr;
2645 if (!appData.monoMode) {
2646 vFrom.addr = (caddr_t) appData.highlightSquareColor;
2647 vFrom.size = strlen(appData.highlightSquareColor);
2648 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2649 if (vTo.addr == NULL) {
2650 appData.monoMode = True;
2653 highlightSquareColor = *(Pixel *) vTo.addr;
2657 if (!appData.monoMode) {
2658 vFrom.addr = (caddr_t) appData.premoveHighlightColor;
2659 vFrom.size = strlen(appData.premoveHighlightColor);
2660 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2661 if (vTo.addr == NULL) {
2662 appData.monoMode = True;
2665 premoveHighlightColor = *(Pixel *) vTo.addr;
2670 fprintf(stderr, _("%s: too few colors available; trying monochrome mode\n"),
2673 if (appData.bitmapDirectory == NULL ||
2674 appData.bitmapDirectory[0] == NULLCHAR)
2675 appData.bitmapDirectory = DEF_BITMAP_DIR;
2678 if (appData.lowTimeWarning && !appData.monoMode) {
2679 vFrom.addr = (caddr_t) appData.lowTimeWarningColor;
2680 vFrom.size = strlen(appData.lowTimeWarningColor);
2681 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2682 if (vTo.addr == NULL)
2683 appData.monoMode = True;
2685 lowTimeWarningColor = *(Pixel *) vTo.addr;
2688 if (appData.monoMode && appData.debugMode) {
2689 fprintf(stderr, _("white pixel = 0x%lx, black pixel = 0x%lx\n"),
2690 (unsigned long) XWhitePixel(xDisplay, xScreen),
2691 (unsigned long) XBlackPixel(xDisplay, xScreen));
2694 if (parse_cpair(ColorShout, appData.colorShout) < 0 ||
2695 parse_cpair(ColorSShout, appData.colorSShout) < 0 ||
2696 parse_cpair(ColorChannel1, appData.colorChannel1) < 0 ||
2697 parse_cpair(ColorChannel, appData.colorChannel) < 0 ||
2698 parse_cpair(ColorKibitz, appData.colorKibitz) < 0 ||
2699 parse_cpair(ColorTell, appData.colorTell) < 0 ||
2700 parse_cpair(ColorChallenge, appData.colorChallenge) < 0 ||
2701 parse_cpair(ColorRequest, appData.colorRequest) < 0 ||
2702 parse_cpair(ColorSeek, appData.colorSeek) < 0 ||
2703 parse_cpair(ColorNormal, appData.colorNormal) < 0)
2705 if (appData.colorize) {
2707 _("%s: can't parse color names; disabling colorization\n"),
2710 appData.colorize = FALSE;
2712 textColors[ColorNone].fg = textColors[ColorNone].bg = -1;
2713 textColors[ColorNone].attr = 0;
2715 XtAppAddActions(appContext, boardActions, XtNumber(boardActions));
2721 layoutName = "tinyLayout";
2722 } else if (smallLayout) {
2723 layoutName = "smallLayout";
2725 layoutName = "normalLayout";
2727 /* Outer layoutWidget is there only to provide a name for use in
2728 resources that depend on the layout style */
2730 XtCreateManagedWidget(layoutName, formWidgetClass, shellWidget,
2731 layoutArgs, XtNumber(layoutArgs));
2733 XtCreateManagedWidget("form", formWidgetClass, layoutWidget,
2734 formArgs, XtNumber(formArgs));
2735 XtSetArg(args[0], XtNdefaultDistance, &sep);
2736 XtGetValues(formWidget, args, 1);
2739 widgetList[j++] = menuBarWidget = CreateMenuBar(menuBar);
2740 XtSetArg(args[0], XtNtop, XtChainTop);
2741 XtSetArg(args[1], XtNbottom, XtChainTop);
2742 XtSetValues(menuBarWidget, args, 2);
2744 widgetList[j++] = whiteTimerWidget =
2745 XtCreateWidget("whiteTime", labelWidgetClass,
2746 formWidget, timerArgs, XtNumber(timerArgs));
2747 XtSetArg(args[0], XtNfont, clockFontStruct);
2748 XtSetArg(args[1], XtNtop, XtChainTop);
2749 XtSetArg(args[2], XtNbottom, XtChainTop);
2750 XtSetValues(whiteTimerWidget, args, 3);
2752 widgetList[j++] = blackTimerWidget =
2753 XtCreateWidget("blackTime", labelWidgetClass,
2754 formWidget, timerArgs, XtNumber(timerArgs));
2755 XtSetArg(args[0], XtNfont, clockFontStruct);
2756 XtSetArg(args[1], XtNtop, XtChainTop);
2757 XtSetArg(args[2], XtNbottom, XtChainTop);
2758 XtSetValues(blackTimerWidget, args, 3);
2760 if (appData.titleInWindow) {
2761 widgetList[j++] = titleWidget =
2762 XtCreateWidget("title", labelWidgetClass, formWidget,
2763 titleArgs, XtNumber(titleArgs));
2764 XtSetArg(args[0], XtNtop, XtChainTop);
2765 XtSetArg(args[1], XtNbottom, XtChainTop);
2766 XtSetValues(titleWidget, args, 2);
2769 if (appData.showButtonBar) {
2770 widgetList[j++] = buttonBarWidget = CreateButtonBar(buttonBar);
2771 XtSetArg(args[0], XtNleft, XtChainRight); // [HGM] glue to right window edge
2772 XtSetArg(args[1], XtNright, XtChainRight); // for good run-time sizing
2773 XtSetArg(args[2], XtNtop, XtChainTop);
2774 XtSetArg(args[3], XtNbottom, XtChainTop);
2775 XtSetValues(buttonBarWidget, args, 4);
2778 widgetList[j++] = messageWidget =
2779 XtCreateWidget("message", labelWidgetClass, formWidget,
2780 messageArgs, XtNumber(messageArgs));
2781 XtSetArg(args[0], XtNtop, XtChainTop);
2782 XtSetArg(args[1], XtNbottom, XtChainTop);
2783 XtSetValues(messageWidget, args, 2);
2785 widgetList[j++] = boardWidget =
2786 XtCreateWidget("board", widgetClass, formWidget, boardArgs,
2787 XtNumber(boardArgs));
2789 XtManageChildren(widgetList, j);
2791 timerWidth = (boardWidth - sep) / 2;
2792 XtSetArg(args[0], XtNwidth, timerWidth);
2793 XtSetValues(whiteTimerWidget, args, 1);
2794 XtSetValues(blackTimerWidget, args, 1);
2796 XtSetArg(args[0], XtNbackground, &timerBackgroundPixel);
2797 XtSetArg(args[1], XtNforeground, &timerForegroundPixel);
2798 XtGetValues(whiteTimerWidget, args, 2);
2800 if (appData.showButtonBar) {
2801 XtSetArg(args[0], XtNbackground, &buttonBackgroundPixel);
2802 XtSetArg(args[1], XtNforeground, &buttonForegroundPixel);
2803 XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
2807 * formWidget uses these constraints but they are stored
2811 XtSetArg(args[i], XtNfromHoriz, 0); i++;
2812 XtSetValues(menuBarWidget, args, i);
2813 if (appData.titleInWindow) {
2816 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2817 XtSetValues(whiteTimerWidget, args, i);
2819 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2820 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2821 XtSetValues(blackTimerWidget, args, i);
2823 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2824 XtSetArg(args[i], XtNjustify, XtJustifyLeft); i++;
2825 XtSetValues(titleWidget, args, i);
2827 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2828 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2829 XtSetValues(messageWidget, args, i);
2830 if (appData.showButtonBar) {
2832 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2833 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2834 XtSetValues(buttonBarWidget, args, i);
2838 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2839 XtSetValues(whiteTimerWidget, args, i);
2841 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2842 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2843 XtSetValues(blackTimerWidget, args, i);
2845 XtSetArg(args[i], XtNfromHoriz, menuBarWidget); i++;
2846 XtSetValues(titleWidget, args, i);
2848 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2849 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2850 XtSetValues(messageWidget, args, i);
2851 if (appData.showButtonBar) {
2853 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2854 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2855 XtSetValues(buttonBarWidget, args, i);
2860 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2861 XtSetValues(whiteTimerWidget, args, i);
2863 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2864 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2865 XtSetValues(blackTimerWidget, args, i);
2867 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2868 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2869 XtSetValues(messageWidget, args, i);
2870 if (appData.showButtonBar) {
2872 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2873 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2874 XtSetValues(buttonBarWidget, args, i);
2878 XtSetArg(args[0], XtNfromVert, messageWidget);
2879 XtSetArg(args[1], XtNtop, XtChainTop);
2880 XtSetArg(args[2], XtNbottom, XtChainBottom);
2881 XtSetArg(args[3], XtNleft, XtChainLeft);
2882 XtSetArg(args[4], XtNright, XtChainRight);
2883 XtSetValues(boardWidget, args, 5);
2885 XtRealizeWidget(shellWidget);
2888 * Correct the width of the message and title widgets.
2889 * It is not known why some systems need the extra fudge term.
2890 * The value "2" is probably larger than needed.
2892 XawFormDoLayout(formWidget, False);
2894 #define WIDTH_FUDGE 2
2896 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2897 XtSetArg(args[i], XtNheight, &h); i++;
2898 XtGetValues(messageWidget, args, i);
2899 if (appData.showButtonBar) {
2901 XtSetArg(args[i], XtNwidth, &w); i++;
2902 XtGetValues(buttonBarWidget, args, i);
2903 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2905 w = boardWidth - 2*bor + 1; /*!! +1 compensates for kludge below */
2908 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2909 if (gres != XtGeometryYes && appData.debugMode) {
2910 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2911 programName, gres, w, h, wr, hr);
2914 /* !! Horrible hack to work around bug in XFree86 4.0.1 (X11R6.4.3) */
2915 /* The size used for the child widget in layout lags one resize behind
2916 its true size, so we resize a second time, 1 pixel smaller. Yeech! */
2918 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2919 if (gres != XtGeometryYes && appData.debugMode) {
2920 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2921 programName, gres, w, h, wr, hr);
2924 XtSetArg(args[0], XtNleft, XtChainLeft); // [HGM] glue ends for good run-time sizing
2925 XtSetArg(args[1], XtNright, XtChainRight);
2926 XtSetValues(messageWidget, args, 2);
2928 if (appData.titleInWindow) {
2930 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2931 XtSetArg(args[i], XtNheight, &h); i++;
2932 XtGetValues(titleWidget, args, i);
2934 w = boardWidth - 2*bor;
2936 XtSetArg(args[0], XtNwidth, &w);
2937 XtGetValues(menuBarWidget, args, 1);
2938 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2941 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
2942 if (gres != XtGeometryYes && appData.debugMode) {
2944 _("%s: titleWidget geometry error %d %d %d %d %d\n"),
2945 programName, gres, w, h, wr, hr);
2948 XawFormDoLayout(formWidget, True);
2950 xBoardWindow = XtWindow(boardWidget);
2952 // [HGM] it seems the layout code ends here, but perhaps the color stuff is size independent and would
2953 // not need to go into InitDrawingSizes().
2957 * Create X checkmark bitmap and initialize option menu checks.
2959 ReadBitmap(&xMarkPixmap, "checkmark.bm",
2960 checkmark_bits, checkmark_width, checkmark_height);
2961 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
2962 if (appData.alwaysPromoteToQueen) {
2963 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
2966 if (appData.animateDragging) {
2967 XtSetValues(XtNameToWidget(menuBarWidget,
2968 "menuOptions.Animate Dragging"),
2971 if (appData.animate) {
2972 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
2975 if (appData.autoComment) {
2976 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
2979 if (appData.autoCallFlag) {
2980 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
2983 if (appData.autoFlipView) {
2984 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Auto Flip View"),
2987 if (appData.autoObserve) {
2988 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
2991 if (appData.autoRaiseBoard) {
2992 XtSetValues(XtNameToWidget(menuBarWidget,
2993 "menuOptions.Auto Raise Board"), args, 1);
2995 if (appData.autoSaveGames) {
2996 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
2999 if (appData.saveGameFile[0] != NULLCHAR) {
3000 /* Can't turn this off from menu */
3001 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
3003 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
3007 if (appData.blindfold) {
3008 XtSetValues(XtNameToWidget(menuBarWidget,
3009 "menuOptions.Blindfold"), args, 1);
3011 if (appData.flashCount > 0) {
3012 XtSetValues(XtNameToWidget(menuBarWidget,
3013 "menuOptions.Flash Moves"),
3016 if (appData.getMoveList) {
3017 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
3021 if (appData.highlightDragging) {
3022 XtSetValues(XtNameToWidget(menuBarWidget,
3023 "menuOptions.Highlight Dragging"),
3027 if (appData.highlightLastMove) {
3028 XtSetValues(XtNameToWidget(menuBarWidget,
3029 "menuOptions.Highlight Last Move"),
3032 if (appData.icsAlarm) {
3033 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.ICS Alarm"),
3036 if (appData.ringBellAfterMoves) {
3037 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
3040 if (appData.oldSaveStyle) {
3041 XtSetValues(XtNameToWidget(menuBarWidget,
3042 "menuOptions.Old Save Style"), args, 1);
3044 if (appData.periodicUpdates) {
3045 XtSetValues(XtNameToWidget(menuBarWidget,
3046 "menuOptions.Periodic Updates"), args, 1);
3048 if (appData.ponderNextMove) {
3049 XtSetValues(XtNameToWidget(menuBarWidget,
3050 "menuOptions.Ponder Next Move"), args, 1);
3052 if (appData.popupExitMessage) {
3053 XtSetValues(XtNameToWidget(menuBarWidget,
3054 "menuOptions.Popup Exit Message"), args, 1);
3056 if (appData.popupMoveErrors) {
3057 XtSetValues(XtNameToWidget(menuBarWidget,
3058 "menuOptions.Popup Move Errors"), args, 1);
3060 if (appData.premove) {
3061 XtSetValues(XtNameToWidget(menuBarWidget,
3062 "menuOptions.Premove"), args, 1);
3064 if (appData.quietPlay) {
3065 XtSetValues(XtNameToWidget(menuBarWidget,
3066 "menuOptions.Quiet Play"), args, 1);
3068 if (appData.showCoords) {
3069 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
3072 if (appData.hideThinkingFromHuman) {
3073 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
3076 if (appData.testLegality) {
3077 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Test Legality"),
3084 ReadBitmap(&wIconPixmap, "icon_white.bm",
3085 icon_white_bits, icon_white_width, icon_white_height);
3086 ReadBitmap(&bIconPixmap, "icon_black.bm",
3087 icon_black_bits, icon_black_width, icon_black_height);
3088 iconPixmap = wIconPixmap;
3090 XtSetArg(args[i], XtNiconPixmap, iconPixmap); i++;
3091 XtSetValues(shellWidget, args, i);
3094 * Create a cursor for the board widget.
3096 window_attributes.cursor = XCreateFontCursor(xDisplay, XC_hand2);
3097 XChangeWindowAttributes(xDisplay, xBoardWindow,
3098 CWCursor, &window_attributes);
3101 * Inhibit shell resizing.
3103 shellArgs[0].value = (XtArgVal) &w;
3104 shellArgs[1].value = (XtArgVal) &h;
3105 XtGetValues(shellWidget, shellArgs, 2);
3106 shellArgs[4].value = shellArgs[2].value = w;
3107 shellArgs[5].value = shellArgs[3].value = h;
3108 XtSetValues(shellWidget, &shellArgs[2], 4);
3109 marginW = w - boardWidth; // [HGM] needed to set new shellWidget size when we resize board
3110 marginH = h - boardHeight;
3112 CatchDeleteWindow(shellWidget, "QuitProc");
3117 if (appData.bitmapDirectory[0] != NULLCHAR) {
3124 /* Create regular pieces */
3125 if (!useImages) CreatePieces();
3130 if (appData.animate || appData.animateDragging)
3133 XtAugmentTranslations(formWidget,
3134 XtParseTranslationTable(globalTranslations));
3135 XtAugmentTranslations(boardWidget,
3136 XtParseTranslationTable(boardTranslations));
3137 XtAugmentTranslations(whiteTimerWidget,
3138 XtParseTranslationTable(whiteTranslations));
3139 XtAugmentTranslations(blackTimerWidget,
3140 XtParseTranslationTable(blackTranslations));
3142 /* Why is the following needed on some versions of X instead
3143 * of a translation? */
3144 XtAddEventHandler(boardWidget, ExposureMask, False,
3145 (XtEventHandler) EventProc, NULL);
3150 if (errorExitStatus == -1) {
3151 if (appData.icsActive) {
3152 /* We now wait until we see "login:" from the ICS before
3153 sending the logon script (problems with timestamp otherwise) */
3154 /*ICSInitScript();*/
3155 if (appData.icsInputBox) ICSInputBoxPopUp();
3158 signal(SIGINT, IntSigHandler);
3159 signal(SIGTERM, IntSigHandler);
3160 if (*appData.cmailGameName != NULLCHAR) {
3161 signal(SIGUSR1, CmailSigHandler);
3164 gameInfo.boardWidth = 0; // [HGM] pieces: kludge to ensure InitPosition() calls InitDrawingSizes()
3167 XtAppMainLoop(appContext);
3168 if (appData.debugMode) fclose(debugFP); // [DM] debug
3175 if (appData.icsActive && oldICSInteractionTitle != NULL) {
3176 DisplayIcsInteractionTitle(oldICSInteractionTitle);
3178 unlink(gameCopyFilename);
3179 unlink(gamePasteFilename);
3190 CmailSigHandler(sig)
3196 signal(SIGUSR1, SIG_IGN); /* suspend handler */
3198 /* Activate call-back function CmailSigHandlerCallBack() */
3199 OutputToProcess(cmailPR, (char *)(&dummy), sizeof(int), &error);
3201 signal(SIGUSR1, CmailSigHandler); /* re-activate handler */
3205 CmailSigHandlerCallBack(isr, closure, message, count, error)
3213 ReloadCmailMsgEvent(TRUE); /* Reload cmail msg */
3215 /**** end signal code ****/
3225 f = fopen(appData.icsLogon, "r");
3231 strcat(buf, appData.icsLogon);
3232 f = fopen(buf, "r");
3236 ProcessICSInitScript(f);
3243 EditCommentPopDown();
3254 SetMenuEnables(enab)
3258 if (!menuBarWidget) return;
3259 while (enab->name != NULL) {
3260 w = XtNameToWidget(menuBarWidget, enab->name);
3262 DisplayError(enab->name, 0);
3264 XtSetSensitive(w, enab->value);
3270 Enables icsEnables[] = {
3271 { "menuFile.Mail Move", False },
3272 { "menuFile.Reload CMail Message", False },
3273 { "menuMode.Machine Black", False },
3274 { "menuMode.Machine White", False },
3275 { "menuMode.Analysis Mode", False },
3276 { "menuMode.Analyze File", False },
3277 { "menuMode.Two Machines", False },
3279 { "menuHelp.Hint", False },
3280 { "menuHelp.Book", False },
3281 { "menuStep.Move Now", False },
3282 { "menuOptions.Periodic Updates", False },
3283 { "menuOptions.Hide Thinking", False },
3284 { "menuOptions.Ponder Next Move", False },
3289 Enables ncpEnables[] = {
3290 { "menuFile.Mail Move", False },
3291 { "menuFile.Reload CMail Message", False },
3292 { "menuMode.Machine White", False },
3293 { "menuMode.Machine Black", False },
3294 { "menuMode.Analysis Mode", False },
3295 { "menuMode.Analyze File", False },
3296 { "menuMode.Two Machines", False },
3297 { "menuMode.ICS Client", False },
3298 { "menuMode.ICS Input Box", False },
3299 { "Action", False },
3300 { "menuStep.Revert", False },
3301 { "menuStep.Move Now", False },
3302 { "menuStep.Retract Move", False },
3303 { "menuOptions.Auto Comment", False },
3304 { "menuOptions.Auto Flag", False },
3305 { "menuOptions.Auto Flip View", False },
3306 { "menuOptions.Auto Observe", False },
3307 { "menuOptions.Auto Raise Board", False },
3308 { "menuOptions.Get Move List", False },
3309 { "menuOptions.ICS Alarm", False },
3310 { "menuOptions.Move Sound", False },
3311 { "menuOptions.Quiet Play", False },
3312 { "menuOptions.Hide Thinking", False },
3313 { "menuOptions.Periodic Updates", False },
3314 { "menuOptions.Ponder Next Move", False },
3315 { "menuHelp.Hint", False },
3316 { "menuHelp.Book", False },
3320 Enables gnuEnables[] = {
3321 { "menuMode.ICS Client", False },
3322 { "menuMode.ICS Input Box", False },
3323 { "menuAction.Accept", False },
3324 { "menuAction.Decline", False },
3325 { "menuAction.Rematch", False },
3326 { "menuAction.Adjourn", False },
3327 { "menuAction.Stop Examining", False },
3328 { "menuAction.Stop Observing", False },
3329 { "menuStep.Revert", False },
3330 { "menuOptions.Auto Comment", False },
3331 { "menuOptions.Auto Observe", False },
3332 { "menuOptions.Auto Raise Board", False },
3333 { "menuOptions.Get Move List", False },
3334 { "menuOptions.Premove", False },
3335 { "menuOptions.Quiet Play", False },
3337 /* The next two options rely on SetCmailMode being called *after* */
3338 /* SetGNUMode so that when GNU is being used to give hints these */
3339 /* menu options are still available */
3341 { "menuFile.Mail Move", False },
3342 { "menuFile.Reload CMail Message", False },
3346 Enables cmailEnables[] = {
3348 { "menuAction.Call Flag", False },
3349 { "menuAction.Draw", True },
3350 { "menuAction.Adjourn", False },
3351 { "menuAction.Abort", False },
3352 { "menuAction.Stop Observing", False },
3353 { "menuAction.Stop Examining", False },
3354 { "menuFile.Mail Move", True },
3355 { "menuFile.Reload CMail Message", True },
3359 Enables trainingOnEnables[] = {
3360 { "menuMode.Edit Comment", False },
3361 { "menuMode.Pause", False },
3362 { "menuStep.Forward", False },
3363 { "menuStep.Backward", False },
3364 { "menuStep.Forward to End", False },
3365 { "menuStep.Back to Start", False },
3366 { "menuStep.Move Now", False },
3367 { "menuStep.Truncate Game", False },
3371 Enables trainingOffEnables[] = {
3372 { "menuMode.Edit Comment", True },
3373 { "menuMode.Pause", True },
3374 { "menuStep.Forward", True },
3375 { "menuStep.Backward", True },
3376 { "menuStep.Forward to End", True },
3377 { "menuStep.Back to Start", True },
3378 { "menuStep.Move Now", True },
3379 { "menuStep.Truncate Game", True },
3383 Enables machineThinkingEnables[] = {
3384 { "menuFile.Load Game", False },
3385 { "menuFile.Load Next Game", False },
3386 { "menuFile.Load Previous Game", False },
3387 { "menuFile.Reload Same Game", False },
3388 { "menuFile.Paste Game", False },
3389 { "menuFile.Load Position", False },
3390 { "menuFile.Load Next Position", False },
3391 { "menuFile.Load Previous Position", False },
3392 { "menuFile.Reload Same Position", False },
3393 { "menuFile.Paste Position", False },
3394 { "menuMode.Machine White", False },
3395 { "menuMode.Machine Black", False },
3396 { "menuMode.Two Machines", False },
3397 { "menuStep.Retract Move", False },
3401 Enables userThinkingEnables[] = {
3402 { "menuFile.Load Game", True },
3403 { "menuFile.Load Next Game", True },
3404 { "menuFile.Load Previous Game", True },
3405 { "menuFile.Reload Same Game", True },
3406 { "menuFile.Paste Game", True },
3407 { "menuFile.Load Position", True },
3408 { "menuFile.Load Next Position", True },
3409 { "menuFile.Load Previous Position", True },
3410 { "menuFile.Reload Same Position", True },
3411 { "menuFile.Paste Position", True },
3412 { "menuMode.Machine White", True },
3413 { "menuMode.Machine Black", True },
3414 { "menuMode.Two Machines", True },
3415 { "menuStep.Retract Move", True },
3421 SetMenuEnables(icsEnables);
3424 if (appData.zippyPlay && !appData.noChessProgram) /* [DM] icsEngineAnalyze */
3425 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Analysis Mode"), True);
3432 SetMenuEnables(ncpEnables);
3438 SetMenuEnables(gnuEnables);
3444 SetMenuEnables(cmailEnables);
3450 SetMenuEnables(trainingOnEnables);
3451 if (appData.showButtonBar) {
3452 XtSetSensitive(buttonBarWidget, False);
3458 SetTrainingModeOff()
3460 SetMenuEnables(trainingOffEnables);
3461 if (appData.showButtonBar) {
3462 XtSetSensitive(buttonBarWidget, True);
3467 SetUserThinkingEnables()
3469 if (appData.noChessProgram) return;
3470 SetMenuEnables(userThinkingEnables);
3474 SetMachineThinkingEnables()
3476 if (appData.noChessProgram) return;
3477 SetMenuEnables(machineThinkingEnables);
3479 case MachinePlaysBlack:
3480 case MachinePlaysWhite:
3481 case TwoMachinesPlay:
3482 XtSetSensitive(XtNameToWidget(menuBarWidget,
3483 ModeToWidgetName(gameMode)), True);
3490 #define Abs(n) ((n)<0 ? -(n) : (n))
3493 * Find a font that matches "pattern" that is as close as
3494 * possible to the targetPxlSize. Prefer fonts that are k
3495 * pixels smaller to fonts that are k pixels larger. The
3496 * pattern must be in the X Consortium standard format,
3497 * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".
3498 * The return value should be freed with XtFree when no
3501 char *FindFont(pattern, targetPxlSize)
3505 char **fonts, *p, *best, *scalable, *scalableTail;
3506 int i, j, nfonts, minerr, err, pxlSize;
3509 char **missing_list;
3511 char *def_string, *base_fnt_lst, strInt[3];
3513 XFontStruct **fnt_list;
3515 base_fnt_lst = calloc(1, strlen(pattern) + 3);
3516 sprintf(strInt, "%d", targetPxlSize);
3517 p = strstr(pattern, "--");
3518 strncpy(base_fnt_lst, pattern, p - pattern + 2);
3519 strcat(base_fnt_lst, strInt);
3520 strcat(base_fnt_lst, strchr(p + 2, '-'));
3522 if ((fntSet = XCreateFontSet(xDisplay,
3526 &def_string)) == NULL) {
3528 fprintf(stderr, _("Unable to create font set.\n"));
3532 nfonts = XFontsOfFontSet(fntSet, &fnt_list, &fonts);
3534 fonts = XListFonts(xDisplay, pattern, 999999, &nfonts);
3536 fprintf(stderr, _("%s: no fonts match pattern %s\n"),
3537 programName, pattern);
3545 for (i=0; i<nfonts; i++) {
3548 if (*p != '-') continue;
3550 if (*p == NULLCHAR) break;
3551 if (*p++ == '-') j++;
3553 if (j < 7) continue;
3556 scalable = fonts[i];
3559 err = pxlSize - targetPxlSize;
3560 if (Abs(err) < Abs(minerr) ||
3561 (minerr > 0 && err < 0 && -err == minerr)) {
3567 if (scalable && Abs(minerr) > appData.fontSizeTolerance) {
3568 /* If the error is too big and there is a scalable font,
3569 use the scalable font. */
3570 int headlen = scalableTail - scalable;
3571 p = (char *) XtMalloc(strlen(scalable) + 10);
3572 while (isdigit(*scalableTail)) scalableTail++;
3573 sprintf(p, "%.*s%d%s", headlen, scalable, targetPxlSize, scalableTail);
3575 p = (char *) XtMalloc(strlen(best) + 1);
3578 if (appData.debugMode) {
3579 fprintf(debugFP, _("resolved %s at pixel size %d\n to %s\n"),
3580 pattern, targetPxlSize, p);
3583 if (missing_count > 0)
3584 XFreeStringList(missing_list);
3585 XFreeFontSet(xDisplay, fntSet);
3587 XFreeFontNames(fonts);
3594 XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
3595 | GCBackground | GCFunction | GCPlaneMask;
3596 XGCValues gc_values;
3599 gc_values.plane_mask = AllPlanes;
3600 gc_values.line_width = lineGap;
3601 gc_values.line_style = LineSolid;
3602 gc_values.function = GXcopy;
3604 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3605 gc_values.background = XBlackPixel(xDisplay, xScreen);
3606 lineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3608 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3609 gc_values.background = XWhitePixel(xDisplay, xScreen);
3610 coordGC = XtGetGC(shellWidget, value_mask, &gc_values);
3611 XSetFont(xDisplay, coordGC, coordFontID);
3613 // [HGM] make font for holdings counts (white on black0
3614 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3615 gc_values.background = XBlackPixel(xDisplay, xScreen);
3616 countGC = XtGetGC(shellWidget, value_mask, &gc_values);
3617 XSetFont(xDisplay, countGC, countFontID);
3619 if (appData.monoMode) {
3620 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3621 gc_values.background = XWhitePixel(xDisplay, xScreen);
3622 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3624 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3625 gc_values.background = XBlackPixel(xDisplay, xScreen);
3626 lightSquareGC = wbPieceGC
3627 = XtGetGC(shellWidget, value_mask, &gc_values);
3629 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3630 gc_values.background = XWhitePixel(xDisplay, xScreen);
3631 darkSquareGC = bwPieceGC
3632 = XtGetGC(shellWidget, value_mask, &gc_values);
3634 if (DefaultDepth(xDisplay, xScreen) == 1) {
3635 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
3636 gc_values.function = GXcopyInverted;
3637 copyInvertedGC = XtGetGC(shellWidget, value_mask, &gc_values);
3638 gc_values.function = GXcopy;
3639 if (XBlackPixel(xDisplay, xScreen) == 1) {
3640 bwPieceGC = darkSquareGC;
3641 wbPieceGC = copyInvertedGC;
3643 bwPieceGC = copyInvertedGC;
3644 wbPieceGC = lightSquareGC;
3648 gc_values.foreground = highlightSquareColor;
3649 gc_values.background = highlightSquareColor;
3650 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3652 gc_values.foreground = premoveHighlightColor;
3653 gc_values.background = premoveHighlightColor;
3654 prelineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3656 gc_values.foreground = lightSquareColor;
3657 gc_values.background = darkSquareColor;
3658 lightSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3660 gc_values.foreground = darkSquareColor;
3661 gc_values.background = lightSquareColor;
3662 darkSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3664 gc_values.foreground = jailSquareColor;
3665 gc_values.background = jailSquareColor;
3666 jailSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3668 gc_values.foreground = whitePieceColor;
3669 gc_values.background = darkSquareColor;
3670 wdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3672 gc_values.foreground = whitePieceColor;
3673 gc_values.background = lightSquareColor;
3674 wlPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3676 gc_values.foreground = whitePieceColor;
3677 gc_values.background = jailSquareColor;
3678 wjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3680 gc_values.foreground = blackPieceColor;
3681 gc_values.background = darkSquareColor;
3682 bdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3684 gc_values.foreground = blackPieceColor;
3685 gc_values.background = lightSquareColor;
3686 blPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3688 gc_values.foreground = blackPieceColor;
3689 gc_values.background = jailSquareColor;
3690 bjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3694 void loadXIM(xim, xmask, filename, dest, mask)
3707 fp = fopen(filename, "rb");
3709 fprintf(stderr, _("%s: error loading XIM!\n"), programName);
3716 for (y=0; y<h; ++y) {
3717 for (x=0; x<h; ++x) {
3722 XPutPixel(xim, x, y, blackPieceColor);
3724 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3727 XPutPixel(xim, x, y, darkSquareColor);
3729 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3732 XPutPixel(xim, x, y, whitePieceColor);
3734 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3737 XPutPixel(xim, x, y, lightSquareColor);
3739 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3745 /* create Pixmap of piece */
3746 *dest = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3748 XPutImage(xDisplay, *dest, lightSquareGC, xim,
3751 /* create Pixmap of clipmask
3752 Note: We assume the white/black pieces have the same
3753 outline, so we make only 6 masks. This is okay
3754 since the XPM clipmask routines do the same. */
3756 temp = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3758 XPutImage(xDisplay, temp, lightSquareGC, xmask,
3761 /* now create the 1-bit version */
3762 *mask = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3765 values.foreground = 1;
3766 values.background = 0;
3768 /* Don't use XtGetGC, not read only */
3769 maskGC = XCreateGC(xDisplay, *mask,
3770 GCForeground | GCBackground, &values);
3771 XCopyPlane(xDisplay, temp, *mask, maskGC,
3772 0, 0, squareSize, squareSize, 0, 0, 1);
3773 XFreePixmap(xDisplay, temp);
3778 char pieceBitmapNames[] = "pnbrqfeacwmohijgdvlsukpnsl";
3780 void CreateXIMPieces()
3785 static char *ximkind[] = { "ll", "ld", "dl", "dd" };
3790 /* The XSynchronize calls were copied from CreatePieces.
3791 Not sure if needed, but can't hurt */
3792 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3795 /* temp needed by loadXIM() */
3796 ximtemp = XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3797 0, 0, ss, ss, AllPlanes, XYPixmap);
3799 if (strlen(appData.pixmapDirectory) == 0) {
3803 if (appData.monoMode) {
3804 DisplayFatalError(_("XIM pieces cannot be used in monochrome mode"),
3808 fprintf(stderr, _("\nLoading XIMs...\n"));
3810 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3811 fprintf(stderr, "%d", piece+1);
3812 for (kind=0; kind<4; kind++) {
3813 fprintf(stderr, ".");
3814 snprintf(buf, sizeof(buf), "%s/%s%c%s%u.xim",
3815 ExpandPathName(appData.pixmapDirectory),
3816 piece <= (int) WhiteKing ? "" : "w",
3817 pieceBitmapNames[piece],
3819 ximPieceBitmap[kind][piece] =
3820 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3821 0, 0, ss, ss, AllPlanes, XYPixmap);
3822 if (appData.debugMode)
3823 fprintf(stderr, _("(File:%s:) "), buf);
3824 loadXIM(ximPieceBitmap[kind][piece],
3826 &(xpmPieceBitmap2[kind][piece]),
3827 &(ximMaskPm2[piece]));
3828 if(piece <= (int)WhiteKing)
3829 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3831 fprintf(stderr," ");
3833 /* Load light and dark squares */
3834 /* If the LSQ and DSQ pieces don't exist, we will
3835 draw them with solid squares. */
3836 snprintf(buf,sizeof(buf), "%s/lsq%u.xim", ExpandPathName(appData.pixmapDirectory), ss);
3837 if (access(buf, 0) != 0) {
3841 fprintf(stderr, _("light square "));
3843 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3844 0, 0, ss, ss, AllPlanes, XYPixmap);
3845 if (appData.debugMode)
3846 fprintf(stderr, _("(File:%s:) "), buf);
3848 loadXIM(ximLightSquare, NULL, buf, &xpmLightSquare, NULL);
3849 fprintf(stderr, _("dark square "));
3850 snprintf(buf,sizeof(buf), "%s/dsq%u.xim",
3851 ExpandPathName(appData.pixmapDirectory), ss);
3852 if (appData.debugMode)
3853 fprintf(stderr, _("(File:%s:) "), buf);
3855 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3856 0, 0, ss, ss, AllPlanes, XYPixmap);
3857 loadXIM(ximDarkSquare, NULL, buf, &xpmDarkSquare, NULL);
3858 xpmJailSquare = xpmLightSquare;
3860 fprintf(stderr, _("Done.\n"));
3862 XSynchronize(xDisplay, False); /* Work-around for xlib/xt buffering bug */
3866 void CreateXPMPieces()
3870 u_int ss = squareSize;
3872 static char *xpmkind[] = { "ll", "ld", "dl", "dd" };
3873 XpmColorSymbol symbols[4];
3876 /* Apparently some versions of Xpm don't define XpmFormat at all --tpm */
3877 if (appData.debugMode) {
3878 fprintf(stderr, "XPM Library Version: %d.%d%c\n",
3879 XpmFormat, XpmVersion, (char)('a' + XpmRevision - 1));
3883 /* The XSynchronize calls were copied from CreatePieces.
3884 Not sure if needed, but can't hurt */
3885 XSynchronize(xDisplay, True); /* Work-around for xlib/xt buffering bug */
3887 /* Setup translations so piece colors match square colors */
3888 symbols[0].name = "light_piece";
3889 symbols[0].value = appData.whitePieceColor;
3890 symbols[1].name = "dark_piece";
3891 symbols[1].value = appData.blackPieceColor;
3892 symbols[2].name = "light_square";
3893 symbols[2].value = appData.lightSquareColor;
3894 symbols[3].name = "dark_square";
3895 symbols[3].value = appData.darkSquareColor;
3897 attr.valuemask = XpmColorSymbols;
3898 attr.colorsymbols = symbols;
3899 attr.numsymbols = 4;
3901 if (appData.monoMode) {
3902 DisplayFatalError(_("XPM pieces cannot be used in monochrome mode"),
3906 if (strlen(appData.pixmapDirectory) == 0) {
3907 XpmPieces* pieces = builtInXpms;
3910 while (pieces->size != squareSize && pieces->size) pieces++;
3911 if (!pieces->size) {
3912 fprintf(stderr, _("No builtin XPM pieces of size %d\n"), squareSize);
3915 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3916 for (kind=0; kind<4; kind++) {
3918 if ((r=XpmCreatePixmapFromData(xDisplay, xBoardWindow,
3919 pieces->xpm[piece][kind],
3920 &(xpmPieceBitmap2[kind][piece]),
3921 NULL, &attr)) != 0) {
3922 fprintf(stderr, _("Error %d loading XPM image \"%s\"\n"),
3926 if(piece <= (int) WhiteKing)
3927 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3931 xpmJailSquare = xpmLightSquare;
3935 fprintf(stderr, _("\nLoading XPMs...\n"));
3938 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3939 fprintf(stderr, "%d ", piece+1);
3940 for (kind=0; kind<4; kind++) {
3941 snprintf(buf, sizeof(buf), "%s/%s%c%s%u.xpm",
3942 ExpandPathName(appData.pixmapDirectory),
3943 piece > (int) WhiteKing ? "w" : "",
3944 pieceBitmapNames[piece],
3946 if (appData.debugMode) {
3947 fprintf(stderr, _("(File:%s:) "), buf);
3949 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3950 &(xpmPieceBitmap2[kind][piece]),
3951 NULL, &attr)) != 0) {
3952 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"),
3956 if(piece <= (int) WhiteKing)
3957 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3960 /* Load light and dark squares */
3961 /* If the LSQ and DSQ pieces don't exist, we will
3962 draw them with solid squares. */
3963 fprintf(stderr, _("light square "));
3964 snprintf(buf, sizeof(buf), "%s/lsq%u.xpm", ExpandPathName(appData.pixmapDirectory), ss);
3965 if (access(buf, 0) != 0) {
3969 if (appData.debugMode)
3970 fprintf(stderr, _("(File:%s:) "), buf);
3972 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3973 &xpmLightSquare, NULL, &attr)) != 0) {
3974 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
3977 fprintf(stderr, _("dark square "));
3978 snprintf(buf, sizeof(buf), "%s/dsq%u.xpm",
3979 ExpandPathName(appData.pixmapDirectory), ss);
3980 if (appData.debugMode) {
3981 fprintf(stderr, _("(File:%s:) "), buf);
3983 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3984 &xpmDarkSquare, NULL, &attr)) != 0) {
3985 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
3989 xpmJailSquare = xpmLightSquare;
3990 fprintf(stderr, _("Done.\n"));
3992 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3995 #endif /* HAVE_LIBXPM */
3998 /* No built-in bitmaps */
4003 u_int ss = squareSize;
4005 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
4008 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
4009 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
4010 sprintf(buf, "%s%c%u%c.bm", piece > (int)WhiteKing ? "w" : "",
4011 pieceBitmapNames[piece],
4012 ss, kind == SOLID ? 's' : 'o');
4013 ReadBitmap(&pieceBitmap2[kind][piece], buf, NULL, ss, ss);
4014 if(piece <= (int)WhiteKing)
4015 pieceBitmap[kind][piece] = pieceBitmap2[kind][piece];
4019 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
4023 /* With built-in bitmaps */
4026 BuiltInBits* bib = builtInBits;
4029 u_int ss = squareSize;
4031 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
4034 while (bib->squareSize != ss && bib->squareSize != 0) bib++;
4036 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
4037 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
4038 sprintf(buf, "%s%c%u%c.bm", piece > (int)WhiteKing ? "w" : "",
4039 pieceBitmapNames[piece],
4040 ss, kind == SOLID ? 's' : 'o');
4041 ReadBitmap(&pieceBitmap2[kind][piece], buf,
4042 bib->bits[kind][piece], ss, ss);
4043 if(piece <= (int)WhiteKing)
4044 pieceBitmap[kind][piece] = pieceBitmap2[kind][piece];
4048 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
4053 void ReadBitmap(pm, name, bits, wreq, hreq)
4056 unsigned char bits[];
4062 char msg[MSG_SIZ], fullname[MSG_SIZ];
4064 if (*appData.bitmapDirectory != NULLCHAR) {
4065 strcpy(fullname, appData.bitmapDirectory);
4066 strcat(fullname, "/");
4067 strcat(fullname, name);
4068 errcode = XReadBitmapFile(xDisplay, xBoardWindow, fullname,
4069 &w, &h, pm, &x_hot, &y_hot);
4070 fprintf(stderr, "load %s\n", name);
4071 if (errcode != BitmapSuccess) {
4073 case BitmapOpenFailed:
4074 snprintf(msg, sizeof(msg), _("Can't open bitmap file %s"), fullname);
4076 case BitmapFileInvalid:
4077 snprintf(msg, sizeof(msg), _("Invalid bitmap in file %s"), fullname);
4079 case BitmapNoMemory:
4080 snprintf(msg, sizeof(msg), _("Ran out of memory reading bitmap file %s"),
4084 snprintf(msg, sizeof(msg), _("Unknown XReadBitmapFile error %d on file %s"),
4088 fprintf(stderr, _("%s: %s...using built-in\n"),
4090 } else if (w != wreq || h != hreq) {
4092 _("%s: Bitmap %s is %dx%d, not %dx%d...using built-in\n"),
4093 programName, fullname, w, h, wreq, hreq);
4100 fprintf(stderr, _("%s: No built-in bitmap for %s; giving up\n"),
4104 ; // [HGM] bitmaps: make it non-fatal if we have no bitmap;
4106 *pm = XCreateBitmapFromData(xDisplay, xBoardWindow, (char *) bits,
4115 if (lineGap == 0) return;
4117 /* [HR] Split this into 2 loops for non-square boards. */
4119 for (i = 0; i < BOARD_HEIGHT + 1; i++) {
4120 gridSegments[i].x1 = 0;
4121 gridSegments[i].x2 =
4122 lineGap + BOARD_WIDTH * (squareSize + lineGap);
4123 gridSegments[i].y1 = gridSegments[i].y2
4124 = lineGap / 2 + (i * (squareSize + lineGap));
4127 for (j = 0; j < BOARD_WIDTH + 1; j++) {
4128 gridSegments[j + i].y1 = 0;
4129 gridSegments[j + i].y2 =
4130 lineGap + BOARD_HEIGHT * (squareSize + lineGap);
4131 gridSegments[j + i].x1 = gridSegments[j + i].x2
4132 = lineGap / 2 + (j * (squareSize + lineGap));
4136 static void MenuBarSelect(w, addr, index)
4141 XtActionProc proc = (XtActionProc) addr;
4143 (proc)(NULL, NULL, NULL, NULL);
4146 void CreateMenuBarPopup(parent, name, mb)
4156 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
4159 XtSetArg(args[j], XtNleftMargin, 20); j++;
4160 XtSetArg(args[j], XtNrightMargin, 20); j++;
4162 while (mi->string != NULL) {
4163 if (strcmp(mi->string, "----") == 0) {
4164 entry = XtCreateManagedWidget(mi->string, smeLineObjectClass,
4167 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string)));
4168 entry = XtCreateManagedWidget(mi->string, smeBSBObjectClass,
4170 XtAddCallback(entry, XtNcallback,
4171 (XtCallbackProc) MenuBarSelect,
4172 (caddr_t) mi->proc);
4178 Widget CreateMenuBar(mb)
4182 Widget anchor, menuBar;
4184 char menuName[MSG_SIZ];
4187 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
4188 XtSetArg(args[j], XtNvSpace, 0); j++;
4189 XtSetArg(args[j], XtNborderWidth, 0); j++;
4190 menuBar = XtCreateWidget("menuBar", boxWidgetClass,
4191 formWidget, args, j);
4193 while (mb->name != NULL) {
4194 strcpy(menuName, "menu");
4195 strcat(menuName, mb->name);
4197 XtSetArg(args[j], XtNmenuName, XtNewString(menuName)); j++;
4200 shortName[0] = _(mb->name)[0];
4201 shortName[1] = NULLCHAR;
4202 XtSetArg(args[j], XtNlabel, XtNewString(shortName)); j++;
4205 XtSetArg(args[j], XtNlabel, XtNewString(_(mb->name))); j++;
4208 XtSetArg(args[j], XtNborderWidth, 0); j++;
4209 anchor = XtCreateManagedWidget(mb->name, menuButtonWidgetClass,
4211 CreateMenuBarPopup(menuBar, menuName, mb);
4217 Widget CreateButtonBar(mi)
4221 Widget button, buttonBar;
4225 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
4227 XtSetArg(args[j], XtNhSpace, 0); j++;
4229 XtSetArg(args[j], XtNborderWidth, 0); j++;
4230 XtSetArg(args[j], XtNvSpace, 0); j++;
4231 buttonBar = XtCreateWidget("buttonBar", boxWidgetClass,
4232 formWidget, args, j);
4234 while (mi->string != NULL) {
4237 XtSetArg(args[j], XtNinternalWidth, 2); j++;
4238 XtSetArg(args[j], XtNborderWidth, 0); j++;
4240 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string))); j++;
4241 button = XtCreateManagedWidget(mi->string, commandWidgetClass,
4242 buttonBar, args, j);
4243 XtAddCallback(button, XtNcallback,
4244 (XtCallbackProc) MenuBarSelect,
4245 (caddr_t) mi->proc);
4252 CreatePieceMenu(name, color)
4259 ChessSquare selection;
4261 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
4262 boardWidget, args, 0);
4264 for (i = 0; i < PIECE_MENU_SIZE; i++) {
4265 String item = pieceMenuStrings[color][i];
4267 if (strcmp(item, "----") == 0) {
4268 entry = XtCreateManagedWidget(item, smeLineObjectClass,
4271 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
4272 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
4274 selection = pieceMenuTranslation[color][i];
4275 XtAddCallback(entry, XtNcallback,
4276 (XtCallbackProc) PieceMenuSelect,
4277 (caddr_t) selection);
4278 if (selection == WhitePawn || selection == BlackPawn) {
4279 XtSetArg(args[0], XtNpopupOnEntry, entry);
4280 XtSetValues(menu, args, 1);
4293 ChessSquare selection;
4295 whitePieceMenu = CreatePieceMenu("menuW", 0);
4296 blackPieceMenu = CreatePieceMenu("menuB", 1);
4298 XtRegisterGrabAction(PieceMenuPopup, True,
4299 (unsigned)(ButtonPressMask|ButtonReleaseMask),
4300 GrabModeAsync, GrabModeAsync);
4302 XtSetArg(args[0], XtNlabel, _("Drop"));
4303 dropMenu = XtCreatePopupShell("menuD", simpleMenuWidgetClass,
4304 boardWidget, args, 1);
4305 for (i = 0; i < DROP_MENU_SIZE; i++) {
4306 String item = dropMenuStrings[i];
4308 if (strcmp(item, "----") == 0) {
4309 entry = XtCreateManagedWidget(item, smeLineObjectClass,
4312 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
4313 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
4315 selection = dropMenuTranslation[i];
4316 XtAddCallback(entry, XtNcallback,
4317 (XtCallbackProc) DropMenuSelect,
4318 (caddr_t) selection);
4323 void SetupDropMenu()
4331 for (i=0; i<sizeof(dmEnables)/sizeof(DropMenuEnables); i++) {
4332 entry = XtNameToWidget(dropMenu, dmEnables[i].widget);
4333 p = strchr(gameMode == IcsPlayingWhite ? white_holding : black_holding,
4334 dmEnables[i].piece);
4335 XtSetSensitive(entry, p != NULL || !appData.testLegality
4336 /*!!temp:*/ || (gameInfo.variant == VariantCrazyhouse
4337 && !appData.icsActive));
4339 while (p && *p++ == dmEnables[i].piece) count++;
4340 snprintf(label, sizeof(label), "%s %d", dmEnables[i].widget, count);
4342 XtSetArg(args[j], XtNlabel, label); j++;
4343 XtSetValues(entry, args, j);
4347 void PieceMenuPopup(w, event, params, num_params)
4351 Cardinal *num_params;
4354 if (event->type != ButtonPress) return;
4355 if (errorUp) ErrorPopDown();
4359 whichMenu = params[0];
4361 case IcsPlayingWhite:
4362 case IcsPlayingBlack:
4364 case MachinePlaysWhite:
4365 case MachinePlaysBlack:
4366 if (appData.testLegality &&
4367 gameInfo.variant != VariantBughouse &&
4368 gameInfo.variant != VariantCrazyhouse) return;
4370 whichMenu = "menuD";
4376 if (((pmFromX = EventToSquare(event->xbutton.x, BOARD_WIDTH)) < 0) ||
4377 ((pmFromY = EventToSquare(event->xbutton.y, BOARD_HEIGHT)) < 0)) {
4378 pmFromX = pmFromY = -1;
4382 pmFromX = BOARD_WIDTH - 1 - pmFromX;
4384 pmFromY = BOARD_HEIGHT - 1 - pmFromY;
4386 XtPopupSpringLoaded(XtNameToWidget(boardWidget, whichMenu));
4389 static void PieceMenuSelect(w, piece, junk)
4394 if (pmFromX < 0 || pmFromY < 0) return;
4395 EditPositionMenuEvent(piece, pmFromX, pmFromY);
4398 static void DropMenuSelect(w, piece, junk)
4403 if (pmFromX < 0 || pmFromY < 0) return;
4404 DropMenuEvent(piece, pmFromX, pmFromY);
4407 void WhiteClock(w, event, prms, nprms)
4413 if (gameMode == EditPosition || gameMode == IcsExamining) {
4414 SetWhiteToPlayEvent();
4415 } else if (gameMode == IcsPlayingBlack || gameMode == MachinePlaysWhite) {
4420 void BlackClock(w, event, prms, nprms)
4426 if (gameMode == EditPosition || gameMode == IcsExamining) {
4427 SetBlackToPlayEvent();
4428 } else if (gameMode == IcsPlayingWhite || gameMode == MachinePlaysBlack) {
4435 * If the user selects on a border boundary, return -1; if off the board,
4436 * return -2. Otherwise map the event coordinate to the square.
4438 int EventToSquare(x, limit)
4446 if ((x % (squareSize + lineGap)) >= squareSize)
4448 x /= (squareSize + lineGap);
4454 static void do_flash_delay(msec)
4460 static void drawHighlight(file, rank, gc)
4466 if (lineGap == 0 || appData.blindfold) return;
4469 x = lineGap/2 + ((BOARD_WIDTH-1)-file) *
4470 (squareSize + lineGap);
4471 y = lineGap/2 + rank * (squareSize + lineGap);
4473 x = lineGap/2 + file * (squareSize + lineGap);
4474 y = lineGap/2 + ((BOARD_HEIGHT-1)-rank) *
4475 (squareSize + lineGap);
4478 XDrawRectangle(xDisplay, xBoardWindow, gc, x, y,
4479 squareSize+lineGap, squareSize+lineGap);
4482 int hi1X = -1, hi1Y = -1, hi2X = -1, hi2Y = -1;
4483 int pm1X = -1, pm1Y = -1, pm2X = -1, pm2Y = -1;
4486 SetHighlights(fromX, fromY, toX, toY)
4487 int fromX, fromY, toX, toY;
4489 if (hi1X != fromX || hi1Y != fromY) {
4490 if (hi1X >= 0 && hi1Y >= 0) {
4491 drawHighlight(hi1X, hi1Y, lineGC);
4493 if (fromX >= 0 && fromY >= 0) {
4494 drawHighlight(fromX, fromY, highlineGC);
4497 if (hi2X != toX || hi2Y != toY) {
4498 if (hi2X >= 0 && hi2Y >= 0) {
4499 drawHighlight(hi2X, hi2Y, lineGC);
4501 if (toX >= 0 && toY >= 0) {
4502 drawHighlight(toX, toY, highlineGC);
4514 SetHighlights(-1, -1, -1, -1);
4519 SetPremoveHighlights(fromX, fromY, toX, toY)
4520 int fromX, fromY, toX, toY;
4522 if (pm1X != fromX || pm1Y != fromY) {
4523 if (pm1X >= 0 && pm1Y >= 0) {
4524 drawHighlight(pm1X, pm1Y, lineGC);
4526 if (fromX >= 0 && fromY >= 0) {
4527 drawHighlight(fromX, fromY, prelineGC);
4530 if (pm2X != toX || pm2Y != toY) {
4531 if (pm2X >= 0 && pm2Y >= 0) {
4532 drawHighlight(pm2X, pm2Y, lineGC);
4534 if (toX >= 0 && toY >= 0) {
4535 drawHighlight(toX, toY, prelineGC);
4545 ClearPremoveHighlights()
4547 SetPremoveHighlights(-1, -1, -1, -1);
4550 static void BlankSquare(x, y, color, piece, dest)
4555 if (useImages && useImageSqs) {
4559 pm = xpmLightSquare;
4564 case 2: /* neutral */
4569 XCopyArea(xDisplay, pm, dest, wlPieceGC, 0, 0,
4570 squareSize, squareSize, x, y);
4580 case 2: /* neutral */
4585 XFillRectangle(xDisplay, dest, gc, x, y, squareSize, squareSize);
4590 I split out the routines to draw a piece so that I could
4591 make a generic flash routine.
4593 static void monoDrawPiece_1bit(piece, square_color, x, y, dest)
4595 int square_color, x, y;
4598 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
4599 switch (square_color) {
4601 case 2: /* neutral */
4603 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
4604 ? *pieceToOutline(piece)
4605 : *pieceToSolid(piece),
4606 dest, bwPieceGC, 0, 0,
4607 squareSize, squareSize, x, y);
4610 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
4611 ? *pieceToSolid(piece)
4612 : *pieceToOutline(piece),
4613 dest, wbPieceGC, 0, 0,
4614 squareSize, squareSize, x, y);
4619 static void monoDrawPiece(piece, square_color, x, y, dest)
4621 int square_color, x, y;
4624 switch (square_color) {
4626 case 2: /* neutral */
4628 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
4629 ? *pieceToOutline(piece)
4630 : *pieceToSolid(piece),
4631 dest, bwPieceGC, 0, 0,
4632 squareSize, squareSize, x, y, 1);
4635 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
4636 ? *pieceToSolid(piece)
4637 : *pieceToOutline(piece),
4638 dest, wbPieceGC, 0, 0,
4639 squareSize, squareSize, x, y, 1);
4644 static void colorDrawPiece(piece, square_color, x, y, dest)
4646 int square_color, x, y;
4649 if(pieceToSolid(piece) == NULL) return; // [HGM] bitmaps: make it non-fatal if we have no bitmap;
4650 switch (square_color) {
4652 XCopyPlane(xDisplay, *pieceToSolid(piece),
4653 dest, (int) piece < (int) BlackPawn
4654 ? wlPieceGC : blPieceGC, 0, 0,
4655 squareSize, squareSize, x, y, 1);
4658 XCopyPlane(xDisplay, *pieceToSolid(piece),
4659 dest, (int) piece < (int) BlackPawn
4660 ? wdPieceGC : bdPieceGC, 0, 0,
4661 squareSize, squareSize, x, y, 1);
4663 case 2: /* neutral */
4665 XCopyPlane(xDisplay, *pieceToSolid(piece),
4666 dest, (int) piece < (int) BlackPawn
4667 ? wjPieceGC : bjPieceGC, 0, 0,
4668 squareSize, squareSize, x, y, 1);
4673 static void colorDrawPieceImage(piece, square_color, x, y, dest)
4675 int square_color, x, y;
4680 switch (square_color) {
4682 case 2: /* neutral */
4684 if ((int)piece < (int) BlackPawn) {
4692 if ((int)piece < (int) BlackPawn) {
4700 XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
4701 dest, wlPieceGC, 0, 0,
4702 squareSize, squareSize, x, y);
4705 typedef void (*DrawFunc)();
4707 DrawFunc ChooseDrawFunc()
4709 if (appData.monoMode) {
4710 if (DefaultDepth(xDisplay, xScreen) == 1) {
4711 return monoDrawPiece_1bit;
4713 return monoDrawPiece;
4717 return colorDrawPieceImage;
4719 return colorDrawPiece;
4723 /* [HR] determine square color depending on chess variant. */
4724 static int SquareColor(row, column)
4729 if (gameInfo.variant == VariantXiangqi) {
4730 if (column >= 3 && column <= 5 && row >= 0 && row <= 2) {
4732 } else if (column >= 3 && column <= 5 && row >= 7 && row <= 9) {
4734 } else if (row <= 4) {
4740 square_color = ((column + row) % 2) == 1;
4743 /* [hgm] holdings: next line makes all holdings squares light */
4744 if(column < BOARD_LEFT || column >= BOARD_RGHT) square_color = 1;
4746 return square_color;
4749 void DrawSquare(row, column, piece, do_flash)
4750 int row, column, do_flash;
4753 int square_color, x, y, direction, font_ascent, font_descent;
4756 XCharStruct overall;
4760 /* Calculate delay in milliseconds (2-delays per complete flash) */
4761 flash_delay = 500 / appData.flashRate;
4764 x = lineGap + ((BOARD_WIDTH-1)-column) *
4765 (squareSize + lineGap);
4766 y = lineGap + row * (squareSize + lineGap);
4768 x = lineGap + column * (squareSize + lineGap);
4769 y = lineGap + ((BOARD_HEIGHT-1)-row) *
4770 (squareSize + lineGap);
4773 square_color = SquareColor(row, column);
4775 if ( // [HGM] holdings: blank out area between board and holdings
4776 column == BOARD_LEFT-1 || column == BOARD_RGHT
4777 || (column == BOARD_LEFT-2 && row < BOARD_HEIGHT-gameInfo.holdingsSize)
4778 || (column == BOARD_RGHT+1 && row >= gameInfo.holdingsSize) ) {
4779 BlankSquare(x, y, 2, EmptySquare, xBoardWindow);
4781 // [HGM] print piece counts next to holdings
4782 string[1] = NULLCHAR;
4783 if (column == (flipView ? BOARD_LEFT-1 : BOARD_RGHT) && piece > 1 ) {
4784 string[0] = '0' + piece;
4785 XTextExtents(countFontStruct, string, 1, &direction,
4786 &font_ascent, &font_descent, &overall);
4787 if (appData.monoMode) {
4788 XDrawImageString(xDisplay, xBoardWindow, countGC,
4789 x + squareSize - overall.width - 2,
4790 y + font_ascent + 1, string, 1);
4792 XDrawString(xDisplay, xBoardWindow, countGC,
4793 x + squareSize - overall.width - 2,
4794 y + font_ascent + 1, string, 1);
4797 if (column == (flipView ? BOARD_RGHT : BOARD_LEFT-1) && piece > 1) {
4798 string[0] = '0' + piece;
4799 XTextExtents(countFontStruct, string, 1, &direction,
4800 &font_ascent, &font_descent, &overall);
4801 if (appData.monoMode) {
4802 XDrawImageString(xDisplay, xBoardWindow, countGC,
4803 x + 2, y + font_ascent + 1, string, 1);
4805 XDrawString(xDisplay, xBoardWindow, countGC,
4806 x + 2, y + font_ascent + 1, string, 1);
4810 if (piece == EmptySquare || appData.blindfold) {
4811 BlankSquare(x, y, square_color, piece, xBoardWindow);
4813 drawfunc = ChooseDrawFunc();
4814 if (do_flash && appData.flashCount > 0) {
4815 for (i=0; i<appData.flashCount; ++i) {
4817 drawfunc(piece, square_color, x, y, xBoardWindow);
4818 XSync(xDisplay, False);
4819 do_flash_delay(flash_delay);
4821 BlankSquare(x, y, square_color, piece, xBoardWindow);
4822 XSync(xDisplay, False);
4823 do_flash_delay(flash_delay);
4826 drawfunc(piece, square_color, x, y, xBoardWindow);
4830 string[1] = NULLCHAR;
4831 if (appData.showCoords && row == (flipView ? BOARD_HEIGHT-1 : 0)
4832 && column >= BOARD_LEFT && column < BOARD_RGHT) {
4833 string[0] = 'a' + column - BOARD_LEFT;
4834 XTextExtents(coordFontStruct, string, 1, &direction,
4835 &font_ascent, &font_descent, &overall);
4836 if (appData.monoMode) {
4837 XDrawImageString(xDisplay, xBoardWindow, coordGC,
4838 x + squareSize - overall.width - 2,
4839 y + squareSize - font_descent - 1, string, 1);
4841 XDrawString(xDisplay, xBoardWindow, coordGC,
4842 x + squareSize - overall.width - 2,
4843 y + squareSize - font_descent - 1, string, 1);
4846 if (appData.showCoords && column == (flipView ? BOARD_RGHT-1 : BOARD_LEFT)) {
4847 string[0] = ONE + row;
4848 XTextExtents(coordFontStruct, string, 1, &direction,
4849 &font_ascent, &font_descent, &overall);
4850 if (appData.monoMode) {
4851 XDrawImageString(xDisplay, xBoardWindow, coordGC,
4852 x + 2, y + font_ascent + 1, string, 1);
4854 XDrawString(xDisplay, xBoardWindow, coordGC,
4855 x + 2, y + font_ascent + 1, string, 1);
4861 /* Why is this needed on some versions of X? */
4862 void EventProc(widget, unused, event)
4867 if (!XtIsRealized(widget))
4870 switch (event->type) {
4872 if (event->xexpose.count > 0) return; /* no clipping is done */
4873 XDrawPosition(widget, True, NULL);
4881 void DrawPosition(fullRedraw, board)
4882 /*Boolean*/int fullRedraw;
4885 XDrawPosition(boardWidget, fullRedraw, board);
4888 /* Returns 1 if there are "too many" differences between b1 and b2
4889 (i.e. more than 1 move was made) */
4890 static int too_many_diffs(b1, b2)
4896 for (i=0; i<BOARD_HEIGHT; ++i) {
4897 for (j=0; j<BOARD_WIDTH; ++j) {
4898 if (b1[i][j] != b2[i][j]) {
4899 if (++c > 4) /* Castling causes 4 diffs */
4908 /* Matrix describing castling maneuvers */
4909 /* Row, ColRookFrom, ColKingFrom, ColRookTo, ColKingTo */
4910 static int castling_matrix[4][5] = {
4911 { 0, 0, 4, 3, 2 }, /* 0-0-0, white */
4912 { 0, 7, 4, 5, 6 }, /* 0-0, white */
4913 { 7, 0, 4, 3, 2 }, /* 0-0-0, black */
4914 { 7, 7, 4, 5, 6 } /* 0-0, black */
4917 /* Checks whether castling occurred. If it did, *rrow and *rcol
4918 are set to the destination (row,col) of the rook that moved.
4920 Returns 1 if castling occurred, 0 if not.
4922 Note: Only handles a max of 1 castling move, so be sure
4923 to call too_many_diffs() first.
4925 static int check_castle_draw(newb, oldb, rrow, rcol)
4932 /* For each type of castling... */
4933 for (i=0; i<4; ++i) {
4934 r = castling_matrix[i];
4936 /* Check the 4 squares involved in the castling move */
4938 for (j=1; j<=4; ++j) {
4939 if (newb[r[0]][r[j]] == oldb[r[0]][r[j]]) {
4946 /* All 4 changed, so it must be a castling move */
4955 static int damage[BOARD_SIZE][BOARD_SIZE];
4958 * event handler for redrawing the board
4960 void XDrawPosition(w, repaint, board)
4962 /*Boolean*/int repaint;
4966 static int lastFlipView = 0;
4967 static int lastBoardValid = 0;
4968 static Board lastBoard;
4972 if (board == NULL) {
4973 if (!lastBoardValid) return;
4976 if (!lastBoardValid || lastFlipView != flipView) {
4977 XtSetArg(args[0], XtNleftBitmap, (flipView ? xMarkPixmap : None));
4978 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flip View"),
4983 * It would be simpler to clear the window with XClearWindow()
4984 * but this causes a very distracting flicker.
4987 if (!repaint && lastBoardValid && lastFlipView == flipView) {
4989 /* If too much changes (begin observing new game, etc.), don't
4991 do_flash = too_many_diffs(board, lastBoard) ? 0 : 1;
4993 /* Special check for castling so we don't flash both the king
4994 and the rook (just flash the king). */
4996 if (check_castle_draw(board, lastBoard, &rrow, &rcol)) {
4997 /* Draw rook with NO flashing. King will be drawn flashing later */
4998 DrawSquare(rrow, rcol, board[rrow][rcol], 0);
4999 lastBoard[rrow][rcol] = board[rrow][rcol];
5003 /* First pass -- Draw (newly) empty squares and repair damage.
5004 This prevents you from having a piece show up twice while it
5005 is flashing on its new square */
5006 for (i = 0; i < BOARD_HEIGHT; i++)
5007 for (j = 0; j < BOARD_WIDTH; j++)
5008 if ((board[i][j] != lastBoard[i][j] && board[i][j] == EmptySquare)
5010 DrawSquare(i, j, board[i][j], 0);
5011 damage[i][j] = False;
5014 /* Second pass -- Draw piece(s) in new position and flash them */
5015 for (i = 0; i < BOARD_HEIGHT; i++)
5016 for (j = 0; j < BOARD_WIDTH; j++)
5017 if (board[i][j] != lastBoard[i][j]) {
5018 DrawSquare(i, j, board[i][j], do_flash);
5022 XDrawSegments(xDisplay, xBoardWindow, lineGC,
5023 gridSegments, BOARD_HEIGHT + BOARD_WIDTH + 2);
5025 for (i = 0; i < BOARD_HEIGHT; i++)
5026 for (j = 0; j < BOARD_WIDTH; j++) {
5027 DrawSquare(i, j, board[i][j], 0);
5028 damage[i][j] = False;
5032 CopyBoard(lastBoard, board);
5034 lastFlipView = flipView;
5036 /* Draw highlights */
5037 if (pm1X >= 0 && pm1Y >= 0) {
5038 drawHighlight(pm1X, pm1Y, prelineGC);
5040 if (pm2X >= 0 && pm2Y >= 0) {
5041 drawHighlight(pm2X, pm2Y, prelineGC);
5043 if (hi1X >= 0 && hi1Y >= 0) {
5044 drawHighlight(hi1X, hi1Y, highlineGC);
5046 if (hi2X >= 0 && hi2Y >= 0) {
5047 drawHighlight(hi2X, hi2Y, highlineGC);
5050 /* If piece being dragged around board, must redraw that too */
5053 XSync(xDisplay, False);
5058 * event handler for redrawing the board
5060 void DrawPositionProc(w, event, prms, nprms)
5066 XDrawPosition(w, True, NULL);
5071 * event handler for parsing user moves
5073 // [HGM] This routine will need quite some reworking. Although the backend still supports the old
5074 // way of doing things, by calling UserMoveEvent() to test the legality of the move and then perform
5075 // it at the end, and doing all kind of preliminary tests here (e.g. to weed out self-captures), it
5076 // should be made to use the new way, of calling UserMoveTest early to determine the legality of the
5077 // move, (which will weed out the illegal selfcaptures and moves into the holdings, and flag promotions),
5078 // and at the end FinishMove() to perform the move after optional promotion popups.
5079 // For now I patched it to allow self-capture with King, and suppress clicks between board and holdings.
5080 void HandleUserMove(w, event, prms, nprms)
5087 Boolean saveAnimate;
5088 static int second = 0;
5090 if (w != boardWidget || errorExitStatus != -1) return;
5092 if (event->type == ButtonPress) ErrorPopDown();
5095 if (event->type == ButtonPress) {
5096 XtPopdown(promotionShell);
5097 XtDestroyWidget(promotionShell);
5098 promotionUp = False;
5106 x = EventToSquare(event->xbutton.x, BOARD_WIDTH);
5107 y = EventToSquare(event->xbutton.y, BOARD_HEIGHT);
5108 if (!flipView && y >= 0) {
5109 y = BOARD_HEIGHT - 1 - y;
5111 if (flipView && x >= 0) {
5112 x = BOARD_WIDTH - 1 - x;
5115 /* [HGM] holdings: next 5 lines: ignore all clicks between board and holdings */
5116 if(event->type == ButtonPress
5117 && ( x == BOARD_LEFT-1 || x == BOARD_RGHT
5118 || x == BOARD_LEFT-2 && y < BOARD_HEIGHT-gameInfo.holdingsSize
5119 || x == BOARD_RGHT+1 && y >= gameInfo.holdingsSize) )
5123 if (event->type == ButtonPress) {
5125 if (OKToStartUserMove(x, y)) {
5129 DragPieceBegin(event->xbutton.x, event->xbutton.y);
5130 if (appData.highlightDragging) {
5131 SetHighlights(x, y, -1, -1);
5139 if (event->type == ButtonPress && gameMode != EditPosition &&
5144 /* Check if clicking again on the same color piece */
5145 fromP = boards[currentMove][fromY][fromX];
5146 toP = boards[currentMove][y][x];
5147 if ((WhitePawn <= fromP && fromP < WhiteKing && // [HGM] this test should go, as UserMoveTest now does it.
5148 WhitePawn <= toP && toP <= WhiteKing) || // For now I made it less critical by exempting King
5149 (BlackPawn <= fromP && fromP < BlackKing && // moves, to not interfere with FRC castlings.
5150 BlackPawn <= toP && toP <= BlackKing)) {
5151 /* Clicked again on same color piece -- changed his mind */
5152 second = (x == fromX && y == fromY);
5153 if (appData.highlightDragging) {
5154 SetHighlights(x, y, -1, -1);
5158 if (OKToStartUserMove(x, y)) {
5161 DragPieceBegin(event->xbutton.x, event->xbutton.y);
5167 if (event->type == ButtonRelease && x == fromX && y == fromY) {
5168 DragPieceEnd(event->xbutton.x, event->xbutton.y);
5169 if (appData.animateDragging) {
5170 /* Undo animation damage if any */
5171 DrawPosition(FALSE, NULL);
5174 /* Second up/down in same square; just abort move */
5179 ClearPremoveHighlights();
5181 /* First upclick in same square; start click-click mode */
5182 SetHighlights(x, y, -1, -1);
5187 /* Completed move */
5190 saveAnimate = appData.animate;
5191 if (event->type == ButtonPress) {
5192 /* Finish clickclick move */
5193 if (appData.animate || appData.highlightLastMove) {
5194 SetHighlights(fromX, fromY, toX, toY);
5199 /* Finish drag move */
5200 if (appData.highlightLastMove) {
5201 SetHighlights(fromX, fromY, toX, toY);
5205 DragPieceEnd(event->xbutton.x, event->xbutton.y);
5206 /* Don't animate move and drag both */
5207 appData.animate = FALSE;
5209 if (IsPromotion(fromX, fromY, toX, toY)) {
5210 if (appData.alwaysPromoteToQueen) {
5211 UserMoveEvent(fromX, fromY, toX, toY, 'q');
5212 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
5213 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
5216 SetHighlights(fromX, fromY, toX, toY);
5220 UserMoveEvent(fromX, fromY, toX, toY, NULLCHAR);
5221 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
5222 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
5225 appData.animate = saveAnimate;
5226 if (appData.animate || appData.animateDragging) {
5227 /* Undo animation damage if needed */
5228 DrawPosition(FALSE, NULL);
5232 void AnimateUserMove (Widget w, XEvent * event,
5233 String * params, Cardinal * nParams)
5235 DragPieceMove(event->xmotion.x, event->xmotion.y);
5238 Widget CommentCreate(name, text, mutable, callback, lines)
5240 int /*Boolean*/ mutable;
5241 XtCallbackProc callback;
5245 Widget shell, layout, form, edit, b_ok, b_cancel, b_clear, b_close, b_edit;
5250 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5251 XtGetValues(boardWidget, args, j);
5254 XtSetArg(args[j], XtNresizable, True); j++;
5257 XtCreatePopupShell(name, topLevelShellWidgetClass,
5258 shellWidget, args, j);
5261 XtCreatePopupShell(name, transientShellWidgetClass,
5262 shellWidget, args, j);
5265 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
5266 layoutArgs, XtNumber(layoutArgs));
5268 XtCreateManagedWidget("form", formWidgetClass, layout,
5269 formArgs, XtNumber(formArgs));
5273 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
5274 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
5276 XtSetArg(args[j], XtNstring, text); j++;
5277 XtSetArg(args[j], XtNtop, XtChainTop); j++;
5278 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5279 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5280 XtSetArg(args[j], XtNright, XtChainRight); j++;
5281 XtSetArg(args[j], XtNresizable, True); j++;
5282 XtSetArg(args[j], XtNwidth, bw_width); j++; /*force wider than buttons*/
5284 XtSetArg(args[j], XtNscrollVertical, XawtextScrollWhenNeeded); j++;
5286 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
5287 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
5289 XtSetArg(args[j], XtNautoFill, True); j++;
5290 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
5292 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
5296 XtSetArg(args[j], XtNfromVert, edit); j++;
5297 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5298 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5299 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5300 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5302 XtCreateManagedWidget(_("ok"), commandWidgetClass, form, args, j);
5303 XtAddCallback(b_ok, XtNcallback, callback, (XtPointer) 0);
5306 XtSetArg(args[j], XtNfromVert, edit); j++;
5307 XtSetArg(args[j], XtNfromHoriz, b_ok); j++;
5308 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5309 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5310 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5311 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5313 XtCreateManagedWidget(_("cancel"), commandWidgetClass, form, args, j);
5314 XtAddCallback(b_cancel, XtNcallback, callback, (XtPointer) 0);
5317 XtSetArg(args[j], XtNfromVert, edit); j++;
5318 XtSetArg(args[j], XtNfromHoriz, b_cancel); j++;
5319 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5320 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5321 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5322 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5324 XtCreateManagedWidget(_("clear"), commandWidgetClass, form, args, j);
5325 XtAddCallback(b_clear, XtNcallback, callback, (XtPointer) 0);
5328 XtSetArg(args[j], XtNfromVert, edit); j++;
5329 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5330 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5331 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5332 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5334 XtCreateManagedWidget(_("close"), commandWidgetClass, form, args, j);
5335 XtAddCallback(b_close, XtNcallback, callback, (XtPointer) 0);
5338 XtSetArg(args[j], XtNfromVert, edit); j++;
5339 XtSetArg(args[j], XtNfromHoriz, b_close); j++;
5340 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5341 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5342 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5343 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5345 XtCreateManagedWidget(_("edit"), commandWidgetClass, form, args, j);
5346 XtAddCallback(b_edit, XtNcallback, callback, (XtPointer) 0);
5349 XtRealizeWidget(shell);
5351 if (commentX == -1) {
5354 Dimension pw_height;
5355 Dimension ew_height;
5358 XtSetArg(args[j], XtNheight, &ew_height); j++;
5359 XtGetValues(edit, args, j);
5362 XtSetArg(args[j], XtNheight, &pw_height); j++;
5363 XtGetValues(shell, args, j);
5364 commentH = pw_height + (lines - 1) * ew_height;
5365 commentW = bw_width - 16;
5367 XSync(xDisplay, False);
5369 /* This code seems to tickle an X bug if it is executed too soon
5370 after xboard starts up. The coordinates get transformed as if
5371 the main window was positioned at (0, 0).
5373 XtTranslateCoords(shellWidget,
5374 (bw_width - commentW) / 2, 0 - commentH / 2,
5375 &commentX, &commentY);
5377 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
5378 RootWindowOfScreen(XtScreen(shellWidget)),
5379 (bw_width - commentW) / 2, 0 - commentH / 2,
5384 if (commentY < 0) commentY = 0; /*avoid positioning top offscreen*/
5387 XtSetArg(args[j], XtNheight, commentH); j++;
5388 XtSetArg(args[j], XtNwidth, commentW); j++;
5389 XtSetArg(args[j], XtNx, commentX); j++;
5390 XtSetArg(args[j], XtNy, commentY); j++;
5391 XtSetValues(shell, args, j);
5392 XtSetKeyboardFocus(shell, edit);
5397 /* Used for analysis window and ICS input window */
5398 Widget MiscCreate(name, text, mutable, callback, lines)
5400 int /*Boolean*/ mutable;
5401 XtCallbackProc callback;
5405 Widget shell, layout, form, edit;
5407 Dimension bw_width, pw_height, ew_height, w, h;
5413 XtSetArg(args[j], XtNresizable, True); j++;
5416 XtCreatePopupShell(name, topLevelShellWidgetClass,
5417 shellWidget, args, j);
5420 XtCreatePopupShell(name, transientShellWidgetClass,
5421 shellWidget, args, j);
5424 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
5425 layoutArgs, XtNumber(layoutArgs));
5427 XtCreateManagedWidget("form", formWidgetClass, layout,
5428 formArgs, XtNumber(formArgs));
5432 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
5433 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
5435 XtSetArg(args[j], XtNstring, text); j++;
5436 XtSetArg(args[j], XtNtop, XtChainTop); j++;
5437 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5438 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5439 XtSetArg(args[j], XtNright, XtChainRight); j++;
5440 XtSetArg(args[j], XtNresizable, True); j++;
5442 XtSetArg(args[j], XtNscrollVertical, XawtextScrollWhenNeeded); j++;
5444 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
5445 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
5447 XtSetArg(args[j], XtNautoFill, True); j++;
5448 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
5450 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
5452 XtRealizeWidget(shell);
5455 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5456 XtGetValues(boardWidget, args, j);
5459 XtSetArg(args[j], XtNheight, &ew_height); j++;
5460 XtGetValues(edit, args, j);
5463 XtSetArg(args[j], XtNheight, &pw_height); j++;
5464 XtGetValues(shell, args, j);
5465 h = pw_height + (lines - 1) * ew_height;
5468 XSync(xDisplay, False);
5470 /* This code seems to tickle an X bug if it is executed too soon
5471 after xboard starts up. The coordinates get transformed as if
5472 the main window was positioned at (0, 0).
5474 XtTranslateCoords(shellWidget, (bw_width - w) / 2, 0 - h / 2, &x, &y);
5476 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
5477 RootWindowOfScreen(XtScreen(shellWidget)),
5478 (bw_width - w) / 2, 0 - h / 2, &xx, &yy, &junk);
5482 if (y < 0) y = 0; /*avoid positioning top offscreen*/
5485 XtSetArg(args[j], XtNheight, h); j++;
5486 XtSetArg(args[j], XtNwidth, w); j++;
5487 XtSetArg(args[j], XtNx, x); j++;
5488 XtSetArg(args[j], XtNy, y); j++;
5489 XtSetValues(shell, args, j);
5495 static int savedIndex; /* gross that this is global */
5497 void EditCommentPopUp(index, title, text)
5506 if (text == NULL) text = "";
5508 if (editShell == NULL) {
5510 CommentCreate(title, text, True, EditCommentCallback, 4);
5511 XtRealizeWidget(editShell);
5512 CatchDeleteWindow(editShell, "EditCommentPopDown");
5514 edit = XtNameToWidget(editShell, "*form.text");
5516 XtSetArg(args[j], XtNstring, text); j++;
5517 XtSetValues(edit, args, j);
5519 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5520 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5521 XtSetValues(editShell, args, j);
5524 XtPopup(editShell, XtGrabNone);
5528 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
5529 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
5533 void EditCommentCallback(w, client_data, call_data)
5535 XtPointer client_data, call_data;
5543 XtSetArg(args[j], XtNlabel, &name); j++;
5544 XtGetValues(w, args, j);
5546 if (strcmp(name, _("ok")) == 0) {
5547 edit = XtNameToWidget(editShell, "*form.text");
5549 XtSetArg(args[j], XtNstring, &val); j++;
5550 XtGetValues(edit, args, j);
5551 ReplaceComment(savedIndex, val);
5552 EditCommentPopDown();
5553 } else if (strcmp(name, _("cancel")) == 0) {
5554 EditCommentPopDown();
5555 } else if (strcmp(name, _("clear")) == 0) {
5556 edit = XtNameToWidget(editShell, "*form.text");
5557 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
5558 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
5562 void EditCommentPopDown()
5567 if (!editUp) return;
5569 XtSetArg(args[j], XtNx, &commentX); j++;
5570 XtSetArg(args[j], XtNy, &commentY); j++;
5571 XtSetArg(args[j], XtNheight, &commentH); j++;
5572 XtSetArg(args[j], XtNwidth, &commentW); j++;
5573 XtGetValues(editShell, args, j);
5574 XtPopdown(editShell);
5577 XtSetArg(args[j], XtNleftBitmap, None); j++;
5578 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
5582 void ICSInputBoxPopUp()
5587 char *title = _("ICS Input");
5590 if (ICSInputShell == NULL) {
5591 ICSInputShell = MiscCreate(title, "", True, NULL, 1);
5592 tr = XtParseTranslationTable(ICSInputTranslations);
5593 edit = XtNameToWidget(ICSInputShell, "*form.text");
5594 XtOverrideTranslations(edit, tr);
5595 XtRealizeWidget(ICSInputShell);
5596 CatchDeleteWindow(ICSInputShell, "ICSInputBoxPopDown");
5599 edit = XtNameToWidget(ICSInputShell, "*form.text");
5601 XtSetArg(args[j], XtNstring, ""); j++;
5602 XtSetValues(edit, args, j);
5604 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5605 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5606 XtSetValues(ICSInputShell, args, j);
5609 XtPopup(ICSInputShell, XtGrabNone);
5610 XtSetKeyboardFocus(ICSInputShell, edit);
5612 ICSInputBoxUp = True;
5614 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
5615 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
5619 void ICSInputSendText()
5626 edit = XtNameToWidget(ICSInputShell, "*form.text");
5628 XtSetArg(args[j], XtNstring, &val); j++;
5629 XtGetValues(edit, args, j);
5630 SendMultiLineToICS(val);
5631 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
5632 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
5635 void ICSInputBoxPopDown()
5640 if (!ICSInputBoxUp) return;
5642 XtPopdown(ICSInputShell);
5643 ICSInputBoxUp = False;
5645 XtSetArg(args[j], XtNleftBitmap, None); j++;
5646 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
5650 void CommentPopUp(title, text)
5657 if (commentShell == NULL) {
5659 CommentCreate(title, text, False, CommentCallback, 4);
5660 XtRealizeWidget(commentShell);
5661 CatchDeleteWindow(commentShell, "CommentPopDown");
5663 edit = XtNameToWidget(commentShell, "*form.text");
5665 XtSetArg(args[j], XtNstring, text); j++;
5666 XtSetValues(edit, args, j);
5668 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5669 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5670 XtSetValues(commentShell, args, j);
5673 XtPopup(commentShell, XtGrabNone);
5674 XSync(xDisplay, False);
5679 void AnalysisPopUp(title, text)
5686 if (analysisShell == NULL) {
5687 analysisShell = MiscCreate(title, text, False, NULL, 4);
5688 XtRealizeWidget(analysisShell);
5689 CatchDeleteWindow(analysisShell, "AnalysisPopDown");
5692 edit = XtNameToWidget(analysisShell, "*form.text");
5694 XtSetArg(args[j], XtNstring, text); j++;
5695 XtSetValues(edit, args, j);
5697 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5698 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5699 XtSetValues(analysisShell, args, j);
5703 XtPopup(analysisShell, XtGrabNone);
5705 XSync(xDisplay, False);
5710 void CommentCallback(w, client_data, call_data)
5712 XtPointer client_data, call_data;
5719 XtSetArg(args[j], XtNlabel, &name); j++;
5720 XtGetValues(w, args, j);
5722 if (strcmp(name, _("close")) == 0) {
5724 } else if (strcmp(name, _("edit")) == 0) {
5731 void CommentPopDown()
5736 if (!commentUp) return;
5738 XtSetArg(args[j], XtNx, &commentX); j++;
5739 XtSetArg(args[j], XtNy, &commentY); j++;
5740 XtSetArg(args[j], XtNwidth, &commentW); j++;
5741 XtSetArg(args[j], XtNheight, &commentH); j++;
5742 XtGetValues(commentShell, args, j);
5743 XtPopdown(commentShell);
5744 XSync(xDisplay, False);
5748 void AnalysisPopDown()
5750 if (!analysisUp) return;
5751 XtPopdown(analysisShell);
5752 XSync(xDisplay, False);
5754 if (appData.icsEngineAnalyze) ExitAnalyzeMode(); /* [DM] icsEngineAnalyze */
5758 void FileNamePopUp(label, def, proc, openMode)
5765 Widget popup, layout, dialog, edit;
5771 fileProc = proc; /* I can't see a way not */
5772 fileOpenMode = openMode; /* to use globals here */
5775 XtSetArg(args[i], XtNresizable, True); i++;
5776 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
5777 XtSetArg(args[i], XtNtitle, XtNewString(_("File name prompt"))); i++;
5778 fileNameShell = popup =
5779 XtCreatePopupShell("File name prompt", transientShellWidgetClass,
5780 shellWidget, args, i);
5783 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
5784 layoutArgs, XtNumber(layoutArgs));
5787 XtSetArg(args[i], XtNlabel, label); i++;
5788 XtSetArg(args[i], XtNvalue, def); i++;
5789 XtSetArg(args[i], XtNborderWidth, 0); i++;
5790 dialog = XtCreateManagedWidget("fileName", dialogWidgetClass,
5793 XawDialogAddButton(dialog, _("ok"), FileNameCallback, (XtPointer) dialog);
5794 XawDialogAddButton(dialog, _("cancel"), FileNameCallback,
5795 (XtPointer) dialog);
5797 XtRealizeWidget(popup);
5798 CatchDeleteWindow(popup, "FileNamePopDown");
5800 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
5801 &x, &y, &win_x, &win_y, &mask);
5803 XtSetArg(args[0], XtNx, x - 10);
5804 XtSetArg(args[1], XtNy, y - 30);
5805 XtSetValues(popup, args, 2);
5807 XtPopup(popup, XtGrabExclusive);
5810 edit = XtNameToWidget(dialog, "*value");
5811 XtSetKeyboardFocus(popup, edit);
5814 void FileNamePopDown()
5816 if (!filenameUp) return;
5817 XtPopdown(fileNameShell);
5818 XtDestroyWidget(fileNameShell);
5823 void FileNameCallback(w, client_data, call_data)
5825 XtPointer client_data, call_data;
5830 XtSetArg(args[0], XtNlabel, &name);
5831 XtGetValues(w, args, 1);
5833 if (strcmp(name, _("cancel")) == 0) {
5838 FileNameAction(w, NULL, NULL, NULL);
5841 void FileNameAction(w, event, prms, nprms)
5853 name = XawDialogGetValueString(w = XtParent(w));
5855 if ((name != NULL) && (*name != NULLCHAR)) {
5857 XtPopdown(w = XtParent(XtParent(w)));
5861 p = strrchr(buf, ' ');
5868 fullname = ExpandPathName(buf);
5870 ErrorPopUp(_("Error"), _("Can't open file"), FALSE);
5873 f = fopen(fullname, fileOpenMode);
5875 DisplayError(_("Failed to open file"), errno);
5877 (void) (*fileProc)(f, index, buf);
5884 XtPopdown(w = XtParent(XtParent(w)));
5890 void PromotionPopUp()
5893 Widget dialog, layout;
5895 Dimension bw_width, pw_width;
5899 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5900 XtGetValues(boardWidget, args, j);
5903 XtSetArg(args[j], XtNresizable, True); j++;
5904 XtSetArg(args[j], XtNtitle, XtNewString(_("Promotion"))); j++;
5906 XtCreatePopupShell("Promotion", transientShellWidgetClass,
5907 shellWidget, args, j);
5909 XtCreateManagedWidget(layoutName, formWidgetClass, promotionShell,
5910 layoutArgs, XtNumber(layoutArgs));
5913 XtSetArg(args[j], XtNlabel, _("Promote to what?")); j++;
5914 XtSetArg(args[j], XtNborderWidth, 0); j++;
5915 dialog = XtCreateManagedWidget("promotion", dialogWidgetClass,
5918 if(gameInfo.variant != VariantShogi) {
5919 XawDialogAddButton(dialog, _("Queen"), PromotionCallback,
5920 (XtPointer) dialog);
5921 XawDialogAddButton(dialog, _("Rook"), PromotionCallback,
5922 (XtPointer) dialog);
5923 XawDialogAddButton(dialog, _("Bishop"), PromotionCallback,
5924 (XtPointer) dialog);
5925 XawDialogAddButton(dialog, _("Knight"), PromotionCallback,
5926 (XtPointer) dialog);
5927 if (!appData.testLegality || gameInfo.variant == VariantSuicide ||
5928 gameInfo.variant == VariantGiveaway) {
5929 XawDialogAddButton(dialog, _("King"), PromotionCallback,
5930 (XtPointer) dialog);
5932 if(gameInfo.variant == VariantCapablanca ||
5933 gameInfo.variant == VariantGothic ||
5934 gameInfo.variant == VariantCapaRandom) {
5935 XawDialogAddButton(dialog, _("Archbishop"), PromotionCallback,
5936 (XtPointer) dialog);
5937 XawDialogAddButton(dialog, _("Chancellor"), PromotionCallback,
5938 (XtPointer) dialog);
5940 } else // [HGM] shogi
5942 XawDialogAddButton(dialog, _("Promote"), PromotionCallback,
5943 (XtPointer) dialog);
5944 XawDialogAddButton(dialog, _("Defer"), PromotionCallback,
5945 (XtPointer) dialog);
5947 XawDialogAddButton(dialog, _("cancel"), PromotionCallback,
5948 (XtPointer) dialog);
5950 XtRealizeWidget(promotionShell);
5951 CatchDeleteWindow(promotionShell, "PromotionPopDown");
5954 XtSetArg(args[j], XtNwidth, &pw_width); j++;
5955 XtGetValues(promotionShell, args, j);
5957 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
5958 lineGap + squareSize/3 +
5959 ((toY == BOARD_HEIGHT-1) ^ (flipView) ?
5960 0 : 6*(squareSize + lineGap)), &x, &y);
5963 XtSetArg(args[j], XtNx, x); j++;
5964 XtSetArg(args[j], XtNy, y); j++;
5965 XtSetValues(promotionShell, args, j);
5967 XtPopup(promotionShell, XtGrabNone);
5972 void PromotionPopDown()
5974 if (!promotionUp) return;
5975 XtPopdown(promotionShell);
5976 XtDestroyWidget(promotionShell);
5977 promotionUp = False;
5980 void PromotionCallback(w, client_data, call_data)
5982 XtPointer client_data, call_data;
5988 XtSetArg(args[0], XtNlabel, &name);
5989 XtGetValues(w, args, 1);
5993 if (fromX == -1) return;
5995 if (strcmp(name, _("cancel")) == 0) {
5999 } else if (strcmp(name, _("Knight")) == 0) {
6001 } else if (strcmp(name, _("Promote")) == 0) {
6003 } else if (strcmp(name, _("Defer")) == 0) {
6006 promoChar = ToLower(name[0]);
6009 UserMoveEvent(fromX, fromY, toX, toY, promoChar);
6011 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
6012 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
6017 void ErrorCallback(w, client_data, call_data)
6019 XtPointer client_data, call_data;
6022 XtPopdown(w = XtParent(XtParent(XtParent(w))));
6024 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
6030 if (!errorUp) return;
6032 XtPopdown(errorShell);
6033 XtDestroyWidget(errorShell);
6034 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
6037 void ErrorPopUp(title, label, modal)
6038 char *title, *label;
6042 Widget dialog, layout;
6046 Dimension bw_width, pw_width;
6047 Dimension pw_height;
6051 XtSetArg(args[i], XtNresizable, True); i++;
6052 XtSetArg(args[i], XtNtitle, title); i++;
6054 XtCreatePopupShell("errorpopup", transientShellWidgetClass,
6055 shellWidget, args, i);
6057 XtCreateManagedWidget(layoutName, formWidgetClass, errorShell,
6058 layoutArgs, XtNumber(layoutArgs));
6061 XtSetArg(args[i], XtNlabel, label); i++;
6062 XtSetArg(args[i], XtNborderWidth, 0); i++;
6063 dialog = XtCreateManagedWidget("dialog", dialogWidgetClass,
6066 XawDialogAddButton(dialog, _("ok"), ErrorCallback, (XtPointer) dialog);
6068 XtRealizeWidget(errorShell);
6069 CatchDeleteWindow(errorShell, "ErrorPopDown");
6072 XtSetArg(args[i], XtNwidth, &bw_width); i++;
6073 XtGetValues(boardWidget, args, i);
6075 XtSetArg(args[i], XtNwidth, &pw_width); i++;
6076 XtSetArg(args[i], XtNheight, &pw_height); i++;
6077 XtGetValues(errorShell, args, i);
6080 /* This code seems to tickle an X bug if it is executed too soon
6081 after xboard starts up. The coordinates get transformed as if
6082 the main window was positioned at (0, 0).
6084 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
6085 0 - pw_height + squareSize / 3, &x, &y);
6087 XTranslateCoordinates(xDisplay, XtWindow(boardWidget),
6088 RootWindowOfScreen(XtScreen(boardWidget)),
6089 (bw_width - pw_width) / 2,
6090 0 - pw_height + squareSize / 3, &xx, &yy, &junk);
6094 if (y < 0) y = 0; /*avoid positioning top offscreen*/
6097 XtSetArg(args[i], XtNx, x); i++;
6098 XtSetArg(args[i], XtNy, y); i++;
6099 XtSetValues(errorShell, args, i);
6102 XtPopup(errorShell, modal ? XtGrabExclusive : XtGrabNone);
6105 /* Disable all user input other than deleting the window */
6106 static int frozen = 0;
6110 /* Grab by a widget that doesn't accept input */
6111 XtAddGrab(messageWidget, TRUE, FALSE);
6115 /* Undo a FreezeUI */
6118 if (!frozen) return;
6119 XtRemoveGrab(messageWidget);
6123 char *ModeToWidgetName(mode)
6127 case BeginningOfGame:
6128 if (appData.icsActive)
6129 return "menuMode.ICS Client";
6130 else if (appData.noChessProgram ||
6131 *appData.cmailGameName != NULLCHAR)
6132 return "menuMode.Edit Game";
6134 return "menuMode.Machine Black";
6135 case MachinePlaysBlack:
6136 return "menuMode.Machine Black";
6137 case MachinePlaysWhite:
6138 return "menuMode.Machine White";
6140 return "menuMode.Analysis Mode";
6142 return "menuMode.Analyze File";
6143 case TwoMachinesPlay:
6144 return "menuMode.Two Machines";
6146 return "menuMode.Edit Game";
6147 case PlayFromGameFile:
6148 return "menuFile.Load Game";
6150 return "menuMode.Edit Position";
6152 return "menuMode.Training";
6153 case IcsPlayingWhite:
6154 case IcsPlayingBlack:
6158 return "menuMode.ICS Client";
6165 void ModeHighlight()
6168 static int oldPausing = FALSE;
6169 static GameMode oldmode = (GameMode) -1;
6172 if (!boardWidget || !XtIsRealized(boardWidget)) return;
6174 if (pausing != oldPausing) {
6175 oldPausing = pausing;
6177 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6179 XtSetArg(args[0], XtNleftBitmap, None);
6181 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Pause"),
6184 if (appData.showButtonBar) {
6187 XtSetArg(args[0], XtNbackground, buttonForegroundPixel);
6188 XtSetArg(args[1], XtNforeground, buttonBackgroundPixel);
6190 XtSetArg(args[0], XtNbackground, buttonBackgroundPixel);
6191 XtSetArg(args[1], XtNforeground, buttonForegroundPixel);
6194 /* Always toggle, don't set. Previous code messes up when
6195 invoked while the button is pressed, as releasing it
6196 toggles the state again. */
6199 XtSetArg(args[0], XtNbackground, &oldbg);
6200 XtSetArg(args[1], XtNforeground, &oldfg);
6201 XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON),
6203 XtSetArg(args[0], XtNbackground, oldfg);
6204 XtSetArg(args[1], XtNforeground, oldbg);
6207 XtSetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
6211 wname = ModeToWidgetName(oldmode);
6212 if (wname != NULL) {
6213 XtSetArg(args[0], XtNleftBitmap, None);
6214 XtSetValues(XtNameToWidget(menuBarWidget, wname), args, 1);
6216 wname = ModeToWidgetName(gameMode);
6217 if (wname != NULL) {
6218 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6219 XtSetValues(XtNameToWidget(menuBarWidget, wname), args, 1);
6223 /* Maybe all the enables should be handled here, not just this one */
6224 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Training"),
6225 gameMode == Training || gameMode == PlayFromGameFile);
6230 * Button/menu procedures
6232 void ResetProc(w, event, prms, nprms)
6242 int LoadGamePopUp(f, gameNumber, title)
6247 cmailMsgLoaded = FALSE;
6248 if (gameNumber == 0) {
6249 int error = GameListBuild(f);
6251 DisplayError(_("Cannot build game list"), error);
6252 } else if (!ListEmpty(&gameList) &&
6253 ((ListGame *) gameList.tailPred)->number > 1) {
6254 GameListPopUp(f, title);
6260 return LoadGame(f, gameNumber, title, FALSE);
6263 void LoadGameProc(w, event, prms, nprms)
6269 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
6272 FileNamePopUp(_("Load game file name?"), "", LoadGamePopUp, "rb");
6275 void LoadNextGameProc(w, event, prms, nprms)
6284 void LoadPrevGameProc(w, event, prms, nprms)
6293 void ReloadGameProc(w, event, prms, nprms)
6302 void LoadNextPositionProc(w, event, prms, nprms)
6311 void LoadPrevPositionProc(w, event, prms, nprms)
6320 void ReloadPositionProc(w, event, prms, nprms)
6329 void LoadPositionProc(w, event, prms, nprms)
6335 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
6338 FileNamePopUp(_("Load position file name?"), "", LoadPosition, "rb");
6341 void SaveGameProc(w, event, prms, nprms)
6347 FileNamePopUp(_("Save game file name?"),
6348 DefaultFileName(appData.oldSaveStyle ? "game" : "pgn"),
6352 void SavePositionProc(w, event, prms, nprms)
6358 FileNamePopUp(_("Save position file name?"),
6359 DefaultFileName(appData.oldSaveStyle ? "pos" : "fen"),
6363 void ReloadCmailMsgProc(w, event, prms, nprms)
6369 ReloadCmailMsgEvent(FALSE);
6372 void MailMoveProc(w, event, prms, nprms)
6381 /* this variable is shared between CopyPositionProc and SendPositionSelection */
6382 static char *selected_fen_position=NULL;
6385 SendPositionSelection(Widget w, Atom *selection, Atom *target,
6386 Atom *type_return, XtPointer *value_return,
6387 unsigned long *length_return, int *format_return)
6389 char *selection_tmp;
6391 if (!selected_fen_position) return False; /* should never happen */
6392 if (*target == XA_STRING){
6393 /* note: since no XtSelectionDoneProc was registered, Xt will
6394 * automatically call XtFree on the value returned. So have to
6395 * make a copy of it allocated with XtMalloc */
6396 selection_tmp= XtMalloc(strlen(selected_fen_position)+16);
6397 strcpy(selection_tmp, selected_fen_position);
6399 *value_return=selection_tmp;
6400 *length_return=strlen(selection_tmp);
6401 *type_return=XA_STRING;
6402 *format_return = 8; /* bits per byte */
6409 /* note: when called from menu all parameters are NULL, so no clue what the
6410 * Widget which was clicked on was, or what the click event was
6412 void CopyPositionProc(w, event, prms, nprms)
6420 if (selected_fen_position) free(selected_fen_position);
6421 selected_fen_position = (char *)PositionToFEN(currentMove, NULL);
6422 if (!selected_fen_position) return;
6423 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
6425 SendPositionSelection,
6426 NULL/* lose_ownership_proc */ ,
6427 NULL/* transfer_done_proc */);
6429 free(selected_fen_position);
6430 selected_fen_position=NULL;
6434 /* function called when the data to Paste is ready */
6436 PastePositionCB(Widget w, XtPointer client_data, Atom *selection,
6437 Atom *type, XtPointer value, unsigned long *len, int *format)
6440 if (value==NULL || *len==0) return; /* nothing had been selected to copy */
6441 fenstr[*len]='\0'; /* normally this string is terminated, but be safe */
6442 EditPositionPasteFEN(fenstr);
6446 /* called when Paste Position button is pressed,
6447 * all parameters will be NULL */
6448 void PastePositionProc(w, event, prms, nprms)
6454 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
6455 /* (XtSelectionCallbackProc) */ PastePositionCB,
6456 NULL, /* client_data passed to PastePositionCB */
6458 /* better to use the time field from the event that triggered the
6459 * call to this function, but that isn't trivial to get
6467 SendGameSelection(Widget w, Atom *selection, Atom *target,
6468 Atom *type_return, XtPointer *value_return,
6469 unsigned long *length_return, int *format_return)
6471 char *selection_tmp;
6473 if (*target == XA_STRING){
6474 FILE* f = fopen(gameCopyFilename, "r");
6477 if (f == NULL) return False;
6481 selection_tmp = XtMalloc(len + 1);
6482 count = fread(selection_tmp, 1, len, f);
6484 XtFree(selection_tmp);
6487 selection_tmp[len] = NULLCHAR;
6488 *value_return = selection_tmp;
6489 *length_return = len;
6490 *type_return = XA_STRING;
6491 *format_return = 8; /* bits per byte */
6498 /* note: when called from menu all parameters are NULL, so no clue what the
6499 * Widget which was clicked on was, or what the click event was
6501 void CopyGameProc(w, event, prms, nprms)
6509 ret = SaveGameToFile(gameCopyFilename, FALSE);
6512 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
6515 NULL/* lose_ownership_proc */ ,
6516 NULL/* transfer_done_proc */);
6519 /* function called when the data to Paste is ready */
6521 PasteGameCB(Widget w, XtPointer client_data, Atom *selection,
6522 Atom *type, XtPointer value, unsigned long *len, int *format)
6525 if (value == NULL || *len == 0) {
6526 return; /* nothing had been selected to copy */
6528 f = fopen(gamePasteFilename, "w");
6530 DisplayError(_("Can't open temp file"), errno);
6533 fwrite(value, 1, *len, f);
6536 LoadGameFromFile(gamePasteFilename, 0, gamePasteFilename, TRUE);
6539 /* called when Paste Game button is pressed,
6540 * all parameters will be NULL */
6541 void PasteGameProc(w, event, prms, nprms)
6547 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
6548 /* (XtSelectionCallbackProc) */ PasteGameCB,
6549 NULL, /* client_data passed to PasteGameCB */
6551 /* better to use the time field from the event that triggered the
6552 * call to this function, but that isn't trivial to get
6562 SaveGameProc(NULL, NULL, NULL, NULL);
6566 void QuitProc(w, event, prms, nprms)
6575 void PauseProc(w, event, prms, nprms)
6585 void MachineBlackProc(w, event, prms, nprms)
6591 MachineBlackEvent();
6594 void MachineWhiteProc(w, event, prms, nprms)
6600 MachineWhiteEvent();
6603 void AnalyzeModeProc(w, event, prms, nprms)
6611 if (!first.analysisSupport) {
6612 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
6613 DisplayError(buf, 0);
6616 /* [DM] icsEngineAnalyze [HGM] This is horrible code; reverse the gameMode and isEngineAnalyze tests! */
6617 if (appData.icsActive) {
6618 if (gameMode != IcsObserving) {
6619 sprintf(buf,_("You are not observing a game"));
6620 DisplayError(buf, 0);
6622 if (appData.icsEngineAnalyze) {
6623 if (appData.debugMode)
6624 fprintf(debugFP, _("Found unexpected active ICS engine analyze \n"));
6630 /* if enable, use want disable icsEngineAnalyze */
6631 if (appData.icsEngineAnalyze) {
6636 appData.icsEngineAnalyze = TRUE;
6637 if (appData.debugMode)
6638 fprintf(debugFP, _("ICS engine analyze starting... \n"));
6640 if (!appData.showThinking)
6641 ShowThinkingProc(w,event,prms,nprms);
6646 void AnalyzeFileProc(w, event, prms, nprms)
6652 if (!first.analysisSupport) {
6654 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
6655 DisplayError(buf, 0);
6660 if (!appData.showThinking)
6661 ShowThinkingProc(w,event,prms,nprms);
6664 FileNamePopUp(_("File to analyze"), "", LoadGamePopUp, "rb");
6665 AnalysisPeriodicEvent(1);
6668 void TwoMachinesProc(w, event, prms, nprms)
6677 void IcsClientProc(w, event, prms, nprms)
6686 void EditGameProc(w, event, prms, nprms)
6695 void EditPositionProc(w, event, prms, nprms)
6701 EditPositionEvent();
6704 void TrainingProc(w, event, prms, nprms)
6713 void EditCommentProc(w, event, prms, nprms)
6720 EditCommentPopDown();
6726 void IcsInputBoxProc(w, event, prms, nprms)
6732 if (ICSInputBoxUp) {
6733 ICSInputBoxPopDown();
6739 void AcceptProc(w, event, prms, nprms)
6748 void DeclineProc(w, event, prms, nprms)
6757 void RematchProc(w, event, prms, nprms)
6766 void CallFlagProc(w, event, prms, nprms)
6775 void DrawProc(w, event, prms, nprms)
6784 void AbortProc(w, event, prms, nprms)
6793 void AdjournProc(w, event, prms, nprms)
6802 void ResignProc(w, event, prms, nprms)
6811 void AdjuWhiteProc(w, event, prms, nprms)
6817 UserAdjudicationEvent(+1);
6820 void AdjuBlackProc(w, event, prms, nprms)
6826 UserAdjudicationEvent(-1);
6829 void AdjuDrawProc(w, event, prms, nprms)
6835 UserAdjudicationEvent(0);
6838 void EnterKeyProc(w, event, prms, nprms)
6844 if (ICSInputBoxUp == True)
6848 void StopObservingProc(w, event, prms, nprms)
6854 StopObservingEvent();
6857 void StopExaminingProc(w, event, prms, nprms)
6863 StopExaminingEvent();
6867 void ForwardProc(w, event, prms, nprms)
6877 void BackwardProc(w, event, prms, nprms)
6886 void ToStartProc(w, event, prms, nprms)
6895 void ToEndProc(w, event, prms, nprms)
6904 void RevertProc(w, event, prms, nprms)
6913 void TruncateGameProc(w, event, prms, nprms)
6919 TruncateGameEvent();
6921 void RetractMoveProc(w, event, prms, nprms)
6930 void MoveNowProc(w, event, prms, nprms)
6940 void AlwaysQueenProc(w, event, prms, nprms)
6948 appData.alwaysPromoteToQueen = !appData.alwaysPromoteToQueen;
6950 if (appData.alwaysPromoteToQueen) {
6951 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6953 XtSetArg(args[0], XtNleftBitmap, None);
6955 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
6959 void AnimateDraggingProc(w, event, prms, nprms)
6967 appData.animateDragging = !appData.animateDragging;
6969 if (appData.animateDragging) {
6970 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6973 XtSetArg(args[0], XtNleftBitmap, None);
6975 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Dragging"),
6979 void AnimateMovingProc(w, event, prms, nprms)
6987 appData.animate = !appData.animate;
6989 if (appData.animate) {
6990 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6993 XtSetArg(args[0], XtNleftBitmap, None);
6995 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
6999 void AutocommProc(w, event, prms, nprms)
7007 appData.autoComment = !appData.autoComment;
7009 if (appData.autoComment) {
7010 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7012 XtSetArg(args[0], XtNleftBitmap, None);
7014 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
7019 void AutoflagProc(w, event, prms, nprms)
7027 appData.autoCallFlag = !appData.autoCallFlag;
7029 if (appData.autoCallFlag) {
7030 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7032 XtSetArg(args[0], XtNleftBitmap, None);
7034 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
7038 void AutoflipProc(w, event, prms, nprms)
7046 appData.autoFlipView = !appData.autoFlipView;
7048 if (appData.autoFlipView) {
7049 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7051 XtSetArg(args[0], XtNleftBitmap, None);
7053 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flip View"),
7057 void AutobsProc(w, event, prms, nprms)
7065 appData.autoObserve = !appData.autoObserve;
7067 if (appData.autoObserve) {
7068 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7070 XtSetArg(args[0], XtNleftBitmap, None);
7072 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
7076 void AutoraiseProc(w, event, prms, nprms)
7084 appData.autoRaiseBoard = !appData.autoRaiseBoard;
7086 if (appData.autoRaiseBoard) {
7087 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7089 XtSetArg(args[0], XtNleftBitmap, None);
7091 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Raise Board"),
7095 void AutosaveProc(w, event, prms, nprms)
7103 appData.autoSaveGames = !appData.autoSaveGames;
7105 if (appData.autoSaveGames) {
7106 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7108 XtSetArg(args[0], XtNleftBitmap, None);
7110 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
7114 void BlindfoldProc(w, event, prms, nprms)
7122 appData.blindfold = !appData.blindfold;
7124 if (appData.blindfold) {
7125 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7127 XtSetArg(args[0], XtNleftBitmap, None);
7129 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Blindfold"),
7132 DrawPosition(True, NULL);
7135 void TestLegalityProc(w, event, prms, nprms)
7143 appData.testLegality = !appData.testLegality;
7145 if (appData.testLegality) {
7146 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7148 XtSetArg(args[0], XtNleftBitmap, None);
7150 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Test Legality"),
7155 void FlashMovesProc(w, event, prms, nprms)
7163 if (appData.flashCount == 0) {
7164 appData.flashCount = 3;
7166 appData.flashCount = -appData.flashCount;
7169 if (appData.flashCount > 0) {
7170 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7172 XtSetArg(args[0], XtNleftBitmap, None);
7174 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flash Moves"),
7178 void FlipViewProc(w, event, prms, nprms)
7184 flipView = !flipView;
7185 DrawPosition(True, NULL);
7188 void GetMoveListProc(w, event, prms, nprms)
7196 appData.getMoveList = !appData.getMoveList;
7198 if (appData.getMoveList) {
7199 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7202 XtSetArg(args[0], XtNleftBitmap, None);
7204 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
7209 void HighlightDraggingProc(w, event, prms, nprms)
7217 appData.highlightDragging = !appData.highlightDragging;
7219 if (appData.highlightDragging) {
7220 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7222 XtSetArg(args[0], XtNleftBitmap, None);
7224 XtSetValues(XtNameToWidget(menuBarWidget,
7225 "menuOptions.Highlight Dragging"), args, 1);
7229 void HighlightLastMoveProc(w, event, prms, nprms)
7237 appData.highlightLastMove = !appData.highlightLastMove;
7239 if (appData.highlightLastMove) {
7240 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7242 XtSetArg(args[0], XtNleftBitmap, None);
7244 XtSetValues(XtNameToWidget(menuBarWidget,
7245 "menuOptions.Highlight Last Move"), args, 1);
7248 void IcsAlarmProc(w, event, prms, nprms)
7256 appData.icsAlarm = !appData.icsAlarm;
7258 if (appData.icsAlarm) {
7259 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7261 XtSetArg(args[0], XtNleftBitmap, None);
7263 XtSetValues(XtNameToWidget(menuBarWidget,
7264 "menuOptions.ICS Alarm"), args, 1);
7267 void MoveSoundProc(w, event, prms, nprms)
7275 appData.ringBellAfterMoves = !appData.ringBellAfterMoves;
7277 if (appData.ringBellAfterMoves) {
7278 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7280 XtSetArg(args[0], XtNleftBitmap, None);
7282 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
7287 void OldSaveStyleProc(w, event, prms, nprms)
7295 appData.oldSaveStyle = !appData.oldSaveStyle;
7297 if (appData.oldSaveStyle) {
7298 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7300 XtSetArg(args[0], XtNleftBitmap, None);
7302 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Old Save Style"),
7306 void PeriodicUpdatesProc(w, event, prms, nprms)
7314 PeriodicUpdatesEvent(!appData.periodicUpdates);
7316 if (appData.periodicUpdates) {
7317 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7319 XtSetArg(args[0], XtNleftBitmap, None);
7321 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Periodic Updates"),
7325 void PonderNextMoveProc(w, event, prms, nprms)
7333 PonderNextMoveEvent(!appData.ponderNextMove);
7335 if (appData.ponderNextMove) {
7336 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7338 XtSetArg(args[0], XtNleftBitmap, None);
7340 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Ponder Next Move"),
7344 void PopupExitMessageProc(w, event, prms, nprms)
7352 appData.popupExitMessage = !appData.popupExitMessage;
7354 if (appData.popupExitMessage) {
7355 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7357 XtSetArg(args[0], XtNleftBitmap, None);
7359 XtSetValues(XtNameToWidget(menuBarWidget,
7360 "menuOptions.Popup Exit Message"), args, 1);
7363 void PopupMoveErrorsProc(w, event, prms, nprms)
7371 appData.popupMoveErrors = !appData.popupMoveErrors;
7373 if (appData.popupMoveErrors) {
7374 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7376 XtSetArg(args[0], XtNleftBitmap, None);
7378 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Popup Move Errors"),
7382 void PremoveProc(w, event, prms, nprms)
7390 appData.premove = !appData.premove;
7392 if (appData.premove) {
7393 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7395 XtSetArg(args[0], XtNleftBitmap, None);
7397 XtSetValues(XtNameToWidget(menuBarWidget,
7398 "menuOptions.Premove"), args, 1);
7401 void QuietPlayProc(w, event, prms, nprms)
7409 appData.quietPlay = !appData.quietPlay;
7411 if (appData.quietPlay) {
7412 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7414 XtSetArg(args[0], XtNleftBitmap, None);
7416 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Quiet Play"),
7420 void ShowCoordsProc(w, event, prms, nprms)
7428 appData.showCoords = !appData.showCoords;
7430 if (appData.showCoords) {
7431 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7433 XtSetArg(args[0], XtNleftBitmap, None);
7435 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
7438 DrawPosition(True, NULL);
7441 void ShowThinkingProc(w, event, prms, nprms)
7449 appData.showThinking = !appData.showThinking; // [HGM] thinking: tken out of ShowThinkingEvent
7450 ShowThinkingEvent();
7452 // [HGM] thinking: currently no suc menu item; replaced by Hide Thinking (From Human)
7453 if (appData.showThinking) {
7454 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7456 XtSetArg(args[0], XtNleftBitmap, None);
7458 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Thinking"),
7463 void HideThinkingProc(w, event, prms, nprms)
7471 appData.hideThinkingFromHuman = !appData.hideThinkingFromHuman; // [HGM] thinking: tken out of ShowThinkingEvent
7472 ShowThinkingEvent();
7474 if (appData.hideThinkingFromHuman) {
7475 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7477 XtSetArg(args[0], XtNleftBitmap, None);
7479 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
7483 void InfoProc(w, event, prms, nprms)
7490 snprintf(buf, sizeof(buf), "xterm -e info --directory %s --directory . -f %s &",
7495 void ManProc(w, event, prms, nprms)
7503 if (nprms && *nprms > 0)
7507 snprintf(buf, sizeof(buf), "xterm -e man %s &", name);
7511 void HintProc(w, event, prms, nprms)
7520 void BookProc(w, event, prms, nprms)
7529 void AboutProc(w, event, prms, nprms)
7537 char *zippy = " (with Zippy code)";
7541 snprintf(buf, sizeof(buf), "%s%s\n\n%s\n%s\n%s\n\n%s%s\n%s",
7542 programVersion, zippy,
7543 "Copyright 1991 Digital Equipment Corporation",
7544 "Enhancements Copyright 1992-2009 Free Software Foundation",
7545 "Enhancements Copyright 2005 Alessandro Scotti",
7546 PACKAGE, " is free software and carries NO WARRANTY;",
7547 "see the file COPYING for more information.");
7548 ErrorPopUp(_("About XBoard"), buf, FALSE);
7551 void DebugProc(w, event, prms, nprms)
7557 appData.debugMode = !appData.debugMode;
7560 void AboutGameProc(w, event, prms, nprms)
7569 void NothingProc(w, event, prms, nprms)
7578 void Iconify(w, event, prms, nprms)
7587 XtSetArg(args[0], XtNiconic, True);
7588 XtSetValues(shellWidget, args, 1);
7591 void DisplayMessage(message, extMessage)
7592 char *message, *extMessage;
7599 snprintf(buf, sizeof(buf), "%s %s", message, extMessage);
7602 message = extMessage;
7605 XtSetArg(arg, XtNlabel, message);
7606 XtSetValues(messageWidget, &arg, 1);
7609 void DisplayTitle(text)
7614 char title[MSG_SIZ];
7617 if (text == NULL) text = "";
7619 if (appData.titleInWindow) {
7621 XtSetArg(args[i], XtNlabel, text); i++;
7622 XtSetValues(titleWidget, args, i);
7625 if (*text != NULLCHAR) {
7627 strcpy(title, text);
7628 } else if (appData.icsActive) {
7629 snprintf(icon, sizeof(icon), "%s", appData.icsHost);
7630 snprintf(title, sizeof(title), "%s: %s", programName, appData.icsHost);
7631 } else if (appData.cmailGameName[0] != NULLCHAR) {
7632 snprintf(icon, sizeof(icon), "%s", "CMail");
7633 snprintf(title,sizeof(title), "%s: %s", programName, "CMail");
7635 // [HGM] license: This stuff should really be done in back-end, but WinBoard already had a pop-up for it
7636 } else if (gameInfo.variant == VariantGothic) {
7637 strcpy(icon, programName);
7638 strcpy(title, GOTHIC);
7641 } else if (gameInfo.variant == VariantFalcon) {
7642 strcpy(icon, programName);
7643 strcpy(title, FALCON);
7645 } else if (appData.noChessProgram) {
7646 strcpy(icon, programName);
7647 strcpy(title, programName);
7649 strcpy(icon, first.tidy);
7650 snprintf(title,sizeof(title), "%s: %s", programName, first.tidy);
7653 XtSetArg(args[i], XtNiconName, (XtArgVal) icon); i++;
7654 XtSetArg(args[i], XtNtitle, (XtArgVal) title); i++;
7655 XtSetValues(shellWidget, args, i);
7659 void DisplayError(message, error)
7666 if (appData.debugMode || appData.matchMode) {
7667 fprintf(stderr, "%s: %s\n", programName, message);
7670 if (appData.debugMode || appData.matchMode) {
7671 fprintf(stderr, "%s: %s: %s\n",
7672 programName, message, strerror(error));
7674 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
7677 ErrorPopUp(_("Error"), message, FALSE);
7681 void DisplayMoveError(message)
7686 DrawPosition(FALSE, NULL);
7687 if (appData.debugMode || appData.matchMode) {
7688 fprintf(stderr, "%s: %s\n", programName, message);
7690 if (appData.popupMoveErrors) {
7691 ErrorPopUp(_("Error"), message, FALSE);
7693 DisplayMessage(message, "");
7698 void DisplayFatalError(message, error, status)
7704 errorExitStatus = status;
7706 fprintf(stderr, "%s: %s\n", programName, message);
7708 fprintf(stderr, "%s: %s: %s\n",
7709 programName, message, strerror(error));
7710 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
7713 if (appData.popupExitMessage && boardWidget && XtIsRealized(boardWidget)) {
7714 ErrorPopUp(status ? _("Fatal Error") : _("Exiting"), message, TRUE);
7720 void DisplayInformation(message)
7724 ErrorPopUp(_("Information"), message, TRUE);
7727 void DisplayNote(message)
7731 ErrorPopUp(_("Note"), message, FALSE);
7735 NullXErrorCheck(dpy, error_event)
7737 XErrorEvent *error_event;
7742 void DisplayIcsInteractionTitle(message)
7745 if (oldICSInteractionTitle == NULL) {
7746 /* Magic to find the old window title, adapted from vim */
7747 char *wina = getenv("WINDOWID");
7749 Window win = (Window) atoi(wina);
7750 Window root, parent, *children;
7751 unsigned int nchildren;
7752 int (*oldHandler)() = XSetErrorHandler(NullXErrorCheck);
7754 if (XFetchName(xDisplay, win, &oldICSInteractionTitle)) break;
7755 if (!XQueryTree(xDisplay, win, &root, &parent,
7756 &children, &nchildren)) break;
7757 if (children) XFree((void *)children);
7758 if (parent == root || parent == 0) break;
7761 XSetErrorHandler(oldHandler);
7763 if (oldICSInteractionTitle == NULL) {
7764 oldICSInteractionTitle = "xterm";
7767 printf("\033]0;%s\007", message);
7771 char pendingReplyPrefix[MSG_SIZ];
7772 ProcRef pendingReplyPR;
7774 void AskQuestionProc(w, event, prms, nprms)
7781 fprintf(stderr, _("AskQuestionProc needed 4 parameters, got %d\n"),
7785 AskQuestionEvent(prms[0], prms[1], prms[2], prms[3]);
7788 void AskQuestionPopDown()
7790 if (!askQuestionUp) return;
7791 XtPopdown(askQuestionShell);
7792 XtDestroyWidget(askQuestionShell);
7793 askQuestionUp = False;
7796 void AskQuestionReplyAction(w, event, prms, nprms)
7806 reply = XawDialogGetValueString(w = XtParent(w));
7807 strcpy(buf, pendingReplyPrefix);
7808 if (*buf) strcat(buf, " ");
7811 OutputToProcess(pendingReplyPR, buf, strlen(buf), &err);
7812 AskQuestionPopDown();
7814 if (err) DisplayFatalError(_("Error writing to chess program"), err, 0);
7817 void AskQuestionCallback(w, client_data, call_data)
7819 XtPointer client_data, call_data;
7824 XtSetArg(args[0], XtNlabel, &name);
7825 XtGetValues(w, args, 1);
7827 if (strcmp(name, _("cancel")) == 0) {
7828 AskQuestionPopDown();
7830 AskQuestionReplyAction(w, NULL, NULL, NULL);
7834 void AskQuestion(title, question, replyPrefix, pr)
7835 char *title, *question, *replyPrefix;
7839 Widget popup, layout, dialog, edit;
7845 strcpy(pendingReplyPrefix, replyPrefix);
7846 pendingReplyPR = pr;
7849 XtSetArg(args[i], XtNresizable, True); i++;
7850 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
7851 askQuestionShell = popup =
7852 XtCreatePopupShell(title, transientShellWidgetClass,
7853 shellWidget, args, i);
7856 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
7857 layoutArgs, XtNumber(layoutArgs));
7860 XtSetArg(args[i], XtNlabel, question); i++;
7861 XtSetArg(args[i], XtNvalue, ""); i++;
7862 XtSetArg(args[i], XtNborderWidth, 0); i++;
7863 dialog = XtCreateManagedWidget("question", dialogWidgetClass,
7866 XawDialogAddButton(dialog, _("enter"), AskQuestionCallback,
7867 (XtPointer) dialog);
7868 XawDialogAddButton(dialog, _("cancel"), AskQuestionCallback,
7869 (XtPointer) dialog);
7871 XtRealizeWidget(popup);
7872 CatchDeleteWindow(popup, "AskQuestionPopDown");
7874 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
7875 &x, &y, &win_x, &win_y, &mask);
7877 XtSetArg(args[0], XtNx, x - 10);
7878 XtSetArg(args[1], XtNy, y - 30);
7879 XtSetValues(popup, args, 2);
7881 XtPopup(popup, XtGrabExclusive);
7882 askQuestionUp = True;
7884 edit = XtNameToWidget(dialog, "*value");
7885 XtSetKeyboardFocus(popup, edit);
7893 if (*name == NULLCHAR) {
7895 } else if (strcmp(name, "$") == 0) {
7896 putc(BELLCHAR, stderr);
7899 snprintf(buf, sizeof(buf), "%s '%s' &", appData.soundProgram, name);
7907 PlaySound(appData.soundMove);
7913 PlaySound(appData.soundIcsWin);
7919 PlaySound(appData.soundIcsLoss);
7925 PlaySound(appData.soundIcsDraw);
7929 PlayIcsUnfinishedSound()
7931 PlaySound(appData.soundIcsUnfinished);
7937 PlaySound(appData.soundIcsAlarm);
7943 system("stty echo");
7949 system("stty -echo");
7953 Colorize(cc, continuation)
7958 int count, outCount, error;
7960 if (textColors[(int)cc].bg > 0) {
7961 if (textColors[(int)cc].fg > 0) {
7962 sprintf(buf, "\033[0;%d;%d;%dm", textColors[(int)cc].attr,
7963 textColors[(int)cc].fg, textColors[(int)cc].bg);
7965 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
7966 textColors[(int)cc].bg);
7969 if (textColors[(int)cc].fg > 0) {
7970 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
7971 textColors[(int)cc].fg);
7973 sprintf(buf, "\033[0;%dm", textColors[(int)cc].attr);
7976 count = strlen(buf);
7977 outCount = OutputToProcess(NoProc, buf, count, &error);
7978 if (outCount < count) {
7979 DisplayFatalError(_("Error writing to display"), error, 1);
7982 if (continuation) return;
7985 PlaySound(appData.soundShout);
7988 PlaySound(appData.soundSShout);
7991 PlaySound(appData.soundChannel1);
7994 PlaySound(appData.soundChannel);
7997 PlaySound(appData.soundKibitz);
8000 PlaySound(appData.soundTell);
8002 case ColorChallenge:
8003 PlaySound(appData.soundChallenge);
8006 PlaySound(appData.soundRequest);
8009 PlaySound(appData.soundSeek);
8020 return getpwuid(getuid())->pw_name;
8023 static char *ExpandPathName(path)
8026 static char static_buf[2000];
8027 char *d, *s, buf[2000];
8033 while (*s && isspace(*s))
8042 if (*(s+1) == '/') {
8043 strcpy(d, getpwuid(getuid())->pw_dir);
8048 *strchr(buf, '/') = 0;
8049 pwd = getpwnam(buf);
8052 fprintf(stderr, _("ERROR: Unknown user %s (in path %s)\n"),
8056 strcpy(d, pwd->pw_dir);
8057 strcat(d, strchr(s+1, '/'));
8068 static char host_name[MSG_SIZ];
8070 #if HAVE_GETHOSTNAME
8071 gethostname(host_name, MSG_SIZ);
8073 #else /* not HAVE_GETHOSTNAME */
8074 # if HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H
8075 sysinfo(SI_HOSTNAME, host_name, MSG_SIZ);
8077 # else /* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
8079 # endif/* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
8080 #endif /* not HAVE_GETHOSTNAME */
8083 XtIntervalId delayedEventTimerXID = 0;
8084 DelayedEventCallback delayedEventCallback = 0;
8089 delayedEventTimerXID = 0;
8090 delayedEventCallback();
8094 ScheduleDelayedEvent(cb, millisec)
8095 DelayedEventCallback cb; long millisec;
8097 delayedEventCallback = cb;
8098 delayedEventTimerXID =
8099 XtAppAddTimeOut(appContext, millisec,
8100 (XtTimerCallbackProc) FireDelayedEvent, (XtPointer) 0);
8103 DelayedEventCallback
8106 if (delayedEventTimerXID) {
8107 return delayedEventCallback;
8114 CancelDelayedEvent()
8116 if (delayedEventTimerXID) {
8117 XtRemoveTimeOut(delayedEventTimerXID);
8118 delayedEventTimerXID = 0;
8122 XtIntervalId loadGameTimerXID = 0;
8124 int LoadGameTimerRunning()
8126 return loadGameTimerXID != 0;
8129 int StopLoadGameTimer()
8131 if (loadGameTimerXID != 0) {
8132 XtRemoveTimeOut(loadGameTimerXID);
8133 loadGameTimerXID = 0;
8141 LoadGameTimerCallback(arg, id)
8145 loadGameTimerXID = 0;
8150 StartLoadGameTimer(millisec)
8154 XtAppAddTimeOut(appContext, millisec,
8155 (XtTimerCallbackProc) LoadGameTimerCallback,
8159 XtIntervalId analysisClockXID = 0;
8162 AnalysisClockCallback(arg, id)
8166 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile
8167 || appData.icsEngineAnalyze) { // [DM]
8168 AnalysisPeriodicEvent(0);
8169 StartAnalysisClock();
8174 StartAnalysisClock()
8177 XtAppAddTimeOut(appContext, 2000,
8178 (XtTimerCallbackProc) AnalysisClockCallback,
8182 XtIntervalId clockTimerXID = 0;
8184 int ClockTimerRunning()
8186 return clockTimerXID != 0;
8189 int StopClockTimer()
8191 if (clockTimerXID != 0) {
8192 XtRemoveTimeOut(clockTimerXID);
8201 ClockTimerCallback(arg, id)
8210 StartClockTimer(millisec)
8214 XtAppAddTimeOut(appContext, millisec,
8215 (XtTimerCallbackProc) ClockTimerCallback,
8220 DisplayTimerLabel(w, color, timer, highlight)
8229 /* check for low time warning */
8230 Pixel foregroundOrWarningColor = timerForegroundPixel;
8233 appData.lowTimeWarning &&
8234 (timer / 1000) < appData.icsAlarmTime)
8235 foregroundOrWarningColor = lowTimeWarningColor;
8237 if (appData.clockMode) {
8238 sprintf(buf, "%s: %s", color, TimeString(timer));
8239 XtSetArg(args[0], XtNlabel, buf);
8241 sprintf(buf, "%s ", color);
8242 XtSetArg(args[0], XtNlabel, buf);
8247 XtSetArg(args[1], XtNbackground, foregroundOrWarningColor);
8248 XtSetArg(args[2], XtNforeground, timerBackgroundPixel);
8250 XtSetArg(args[1], XtNbackground, timerBackgroundPixel);
8251 XtSetArg(args[2], XtNforeground, foregroundOrWarningColor);
8254 XtSetValues(w, args, 3);
8258 DisplayWhiteClock(timeRemaining, highlight)
8264 if(appData.noGUI) return;
8265 DisplayTimerLabel(whiteTimerWidget, _("White"), timeRemaining, highlight);
8266 if (highlight && iconPixmap == bIconPixmap) {
8267 iconPixmap = wIconPixmap;
8268 XtSetArg(args[0], XtNiconPixmap, iconPixmap);
8269 XtSetValues(shellWidget, args, 1);
8274 DisplayBlackClock(timeRemaining, highlight)
8280 if(appData.noGUI) return;
8281 DisplayTimerLabel(blackTimerWidget, _("Black"), timeRemaining, highlight);
8282 if (highlight && iconPixmap == wIconPixmap) {
8283 iconPixmap = bIconPixmap;
8284 XtSetArg(args[0], XtNiconPixmap, iconPixmap);
8285 XtSetValues(shellWidget, args, 1);
8303 int StartChildProcess(cmdLine, dir, pr)
8310 int to_prog[2], from_prog[2];
8314 if (appData.debugMode) {
8315 fprintf(stderr, "StartChildProcess (dir=\"%s\") %s\n",dir, cmdLine);
8318 /* We do NOT feed the cmdLine to the shell; we just
8319 parse it into blank-separated arguments in the
8320 most simple-minded way possible.
8323 strcpy(buf, cmdLine);
8328 if (p == NULL) break;
8333 SetUpChildIO(to_prog, from_prog);
8335 if ((pid = fork()) == 0) {
8337 // [HGM] PSWBTM: made order resistant against case where fd of created pipe was 0 or 1
8338 close(to_prog[1]); // first close the unused pipe ends
8339 close(from_prog[0]);
8340 dup2(to_prog[0], 0); // to_prog was created first, nd is the only one to use 0 or 1
8341 dup2(from_prog[1], 1);
8342 if(to_prog[0] >= 2) close(to_prog[0]); // if 0 or 1, the dup2 already cosed the original
8343 close(from_prog[1]); // and closing again loses one of the pipes!
8344 if(fileno(stderr) >= 2) // better safe than sorry...
8345 dup2(1, fileno(stderr)); /* force stderr to the pipe */
8347 if (dir[0] != NULLCHAR && chdir(dir) != 0) {
8352 nice(appData.niceEngines); // [HGM] nice: adjust priority of engine proc
8354 execvp(argv[0], argv);
8356 /* If we get here, exec failed */
8361 /* Parent process */
8363 close(from_prog[1]);
8365 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8368 cp->fdFrom = from_prog[0];
8369 cp->fdTo = to_prog[1];
8374 // [HGM] kill: implement the 'hard killing' of AS's Winboard_x
8375 static RETSIGTYPE AlarmCallBack(int n)
8381 DestroyChildProcess(pr, signalType)
8385 ChildProc *cp = (ChildProc *) pr;
8387 if (cp->kind != CPReal) return;
8389 if (signalType == 10) { // [HGM] kill: if it does not terminate in 3 sec, kill
8390 signal(SIGALRM, AlarmCallBack);
8392 if(wait((int *) 0) == -1) { // process does not terminate on its own accord
8393 kill(cp->pid, SIGKILL); // kill it forcefully
8394 wait((int *) 0); // and wait again
8398 kill(cp->pid, signalType == 9 ? SIGKILL : SIGTERM); // [HGM] kill: use hard kill if so requested
8400 /* Process is exiting either because of the kill or because of
8401 a quit command sent by the backend; either way, wait for it to die.
8410 InterruptChildProcess(pr)
8413 ChildProc *cp = (ChildProc *) pr;
8415 if (cp->kind != CPReal) return;
8416 (void) kill(cp->pid, SIGINT); /* stop it thinking */
8419 int OpenTelnet(host, port, pr)
8424 char cmdLine[MSG_SIZ];
8426 if (port[0] == NULLCHAR) {
8427 snprintf(cmdLine, sizeof(cmdLine), "%s %s", appData.telnetProgram, host);
8429 snprintf(cmdLine, sizeof(cmdLine), "%s %s %s", appData.telnetProgram, host, port);
8431 return StartChildProcess(cmdLine, "", pr);
8434 int OpenTCP(host, port, pr)
8440 DisplayFatalError(_("Socket support is not configured in"), 0, 2);
8441 #else /* !OMIT_SOCKETS */
8443 struct sockaddr_in sa;
8445 unsigned short uport;
8448 if ((s = socket(AF_INET, SOCK_STREAM, 6)) < 0) {
8452 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
8453 sa.sin_family = AF_INET;
8454 sa.sin_addr.s_addr = INADDR_ANY;
8455 uport = (unsigned short) 0;
8456 sa.sin_port = htons(uport);
8457 if (bind(s, (struct sockaddr *) &sa, sizeof(struct sockaddr_in)) < 0) {
8461 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
8462 if (!(hp = gethostbyname(host))) {
8464 if (sscanf(host, "%d.%d.%d.%d", &b0, &b1, &b2, &b3) == 4) {
8465 hp = (struct hostent *) calloc(1, sizeof(struct hostent));
8466 hp->h_addrtype = AF_INET;
8468 hp->h_addr_list = (char **) calloc(2, sizeof(char *));
8469 hp->h_addr_list[0] = (char *) malloc(4);
8470 hp->h_addr_list[0][0] = b0;
8471 hp->h_addr_list[0][1] = b1;
8472 hp->h_addr_list[0][2] = b2;
8473 hp->h_addr_list[0][3] = b3;
8478 sa.sin_family = hp->h_addrtype;
8479 uport = (unsigned short) atoi(port);
8480 sa.sin_port = htons(uport);
8481 memcpy((char *) &sa.sin_addr, hp->h_addr, hp->h_length);
8483 if (connect(s, (struct sockaddr *) &sa,
8484 sizeof(struct sockaddr_in)) < 0) {
8488 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8495 #endif /* !OMIT_SOCKETS */
8500 int OpenCommPort(name, pr)
8507 fd = open(name, 2, 0);
8508 if (fd < 0) return errno;
8510 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8520 int OpenLoopback(pr)
8526 SetUpChildIO(to, from);
8528 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8531 cp->fdFrom = to[0]; /* note not from[0]; we are doing a loopback */
8538 int OpenRcmd(host, user, cmd, pr)
8539 char *host, *user, *cmd;
8542 DisplayFatalError(_("internal rcmd not implemented for Unix"), 0, 1);
8546 #define INPUT_SOURCE_BUF_SIZE 8192
8555 char buf[INPUT_SOURCE_BUF_SIZE];
8560 DoInputCallback(closure, source, xid)
8565 InputSource *is = (InputSource *) closure;
8570 if (is->lineByLine) {
8571 count = read(is->fd, is->unused,
8572 INPUT_SOURCE_BUF_SIZE - (is->unused - is->buf));
8574 (is->func)(is, is->closure, is->buf, count, count ? errno : 0);
8577 is->unused += count;
8579 while (p < is->unused) {
8580 q = memchr(p, '\n', is->unused - p);
8581 if (q == NULL) break;
8583 (is->func)(is, is->closure, p, q - p, 0);
8587 while (p < is->unused) {
8592 count = read(is->fd, is->buf, INPUT_SOURCE_BUF_SIZE);
8597 (is->func)(is, is->closure, is->buf, count, error);
8601 InputSourceRef AddInputSource(pr, lineByLine, func, closure)
8608 ChildProc *cp = (ChildProc *) pr;
8610 is = (InputSource *) calloc(1, sizeof(InputSource));
8611 is->lineByLine = lineByLine;
8615 is->fd = fileno(stdin);
8617 is->kind = cp->kind;
8618 is->fd = cp->fdFrom;
8621 is->unused = is->buf;
8624 is->xid = XtAppAddInput(appContext, is->fd,
8625 (XtPointer) (XtInputReadMask),
8626 (XtInputCallbackProc) DoInputCallback,
8628 is->closure = closure;
8629 return (InputSourceRef) is;
8633 RemoveInputSource(isr)
8636 InputSource *is = (InputSource *) isr;
8638 if (is->xid == 0) return;
8639 XtRemoveInput(is->xid);
8643 int OutputToProcess(pr, message, count, outError)
8649 ChildProc *cp = (ChildProc *) pr;
8653 outCount = fwrite(message, 1, count, stdout);
8655 outCount = write(cp->fdTo, message, count);
8665 /* Output message to process, with "ms" milliseconds of delay
8666 between each character. This is needed when sending the logon
8667 script to ICC, which for some reason doesn't like the
8668 instantaneous send. */
8669 int OutputToProcessDelayed(pr, message, count, outError, msdelay)
8676 ChildProc *cp = (ChildProc *) pr;
8681 r = write(cp->fdTo, message++, 1);
8694 /**** Animation code by Hugh Fisher, DCS, ANU.
8696 Known problem: if a window overlapping the board is
8697 moved away while a piece is being animated underneath,
8698 the newly exposed area won't be updated properly.
8699 I can live with this.
8701 Known problem: if you look carefully at the animation
8702 of pieces in mono mode, they are being drawn as solid
8703 shapes without interior detail while moving. Fixing
8704 this would be a major complication for minimal return.
8707 /* Masks for XPM pieces. Black and white pieces can have
8708 different shapes, but in the interest of retaining my
8709 sanity pieces must have the same outline on both light
8710 and dark squares, and all pieces must use the same
8711 background square colors/images. */
8713 static int xpmDone = 0;
8716 CreateAnimMasks (pieceDepth)
8723 unsigned long plane;
8726 /* Need a bitmap just to get a GC with right depth */
8727 buf = XCreatePixmap(xDisplay, xBoardWindow,
8729 values.foreground = 1;
8730 values.background = 0;
8731 /* Don't use XtGetGC, not read only */
8732 maskGC = XCreateGC(xDisplay, buf,
8733 GCForeground | GCBackground, &values);
8734 XFreePixmap(xDisplay, buf);
8736 buf = XCreatePixmap(xDisplay, xBoardWindow,
8737 squareSize, squareSize, pieceDepth);
8738 values.foreground = XBlackPixel(xDisplay, xScreen);
8739 values.background = XWhitePixel(xDisplay, xScreen);
8740 bufGC = XCreateGC(xDisplay, buf,
8741 GCForeground | GCBackground, &values);
8743 for (piece = WhitePawn; piece <= BlackKing; piece++) {
8744 /* Begin with empty mask */
8745 if(!xpmDone) // [HGM] pieces: keep using existing
8746 xpmMask[piece] = XCreatePixmap(xDisplay, xBoardWindow,
8747 squareSize, squareSize, 1);
8748 XSetFunction(xDisplay, maskGC, GXclear);
8749 XFillRectangle(xDisplay, xpmMask[piece], maskGC,
8750 0, 0, squareSize, squareSize);
8752 /* Take a copy of the piece */
8757 XSetFunction(xDisplay, bufGC, GXcopy);
8758 XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % (int)BlackPawn],
8760 0, 0, squareSize, squareSize, 0, 0);
8762 /* XOR the background (light) over the piece */
8763 XSetFunction(xDisplay, bufGC, GXxor);
8765 XCopyArea(xDisplay, xpmLightSquare, buf, bufGC,
8766 0, 0, squareSize, squareSize, 0, 0);
8768 XSetForeground(xDisplay, bufGC, lightSquareColor);
8769 XFillRectangle(xDisplay, buf, bufGC, 0, 0, squareSize, squareSize);
8772 /* We now have an inverted piece image with the background
8773 erased. Construct mask by just selecting all the non-zero
8774 pixels - no need to reconstruct the original image. */
8775 XSetFunction(xDisplay, maskGC, GXor);
8777 /* Might be quicker to download an XImage and create bitmap
8778 data from it rather than this N copies per piece, but it
8779 only takes a fraction of a second and there is a much
8780 longer delay for loading the pieces. */
8781 for (n = 0; n < pieceDepth; n ++) {
8782 XCopyPlane(xDisplay, buf, xpmMask[piece], maskGC,
8783 0, 0, squareSize, squareSize,
8789 XFreePixmap(xDisplay, buf);
8790 XFreeGC(xDisplay, bufGC);
8791 XFreeGC(xDisplay, maskGC);
8795 InitAnimState (anim, info)
8797 XWindowAttributes * info;
8802 /* Each buffer is square size, same depth as window */
8803 anim->saveBuf = XCreatePixmap(xDisplay, xBoardWindow,
8804 squareSize, squareSize, info->depth);
8805 anim->newBuf = XCreatePixmap(xDisplay, xBoardWindow,
8806 squareSize, squareSize, info->depth);
8808 /* Create a plain GC for blitting */
8809 mask = GCForeground | GCBackground | GCFunction |
8810 GCPlaneMask | GCGraphicsExposures;
8811 values.foreground = XBlackPixel(xDisplay, xScreen);
8812 values.background = XWhitePixel(xDisplay, xScreen);
8813 values.function = GXcopy;
8814 values.plane_mask = AllPlanes;
8815 values.graphics_exposures = False;
8816 anim->blitGC = XCreateGC(xDisplay, xBoardWindow, mask, &values);
8818 /* Piece will be copied from an existing context at
8819 the start of each new animation/drag. */
8820 anim->pieceGC = XCreateGC(xDisplay, xBoardWindow, 0, &values);
8822 /* Outline will be a read-only copy of an existing */
8823 anim->outlineGC = None;
8829 static VariantClass old = (VariantClass) -1; // [HGM] pieces: redo every time variant changes
8830 XWindowAttributes info;
8832 if (xpmDone && gameInfo.variant == old) return;
8833 if(xpmDone) old = gameInfo.variant; // first time pieces might not be created yet
8834 XGetWindowAttributes(xDisplay, xBoardWindow, &info);
8836 InitAnimState(&game, &info);
8837 InitAnimState(&player, &info);
8839 /* For XPM pieces, we need bitmaps to use as masks. */
8841 CreateAnimMasks(info.depth);
8847 static Boolean frameWaiting;
8849 static RETSIGTYPE FrameAlarm (sig)
8852 frameWaiting = False;
8853 /* In case System-V style signals. Needed?? */
8854 signal(SIGALRM, FrameAlarm);
8861 struct itimerval delay;
8863 XSync(xDisplay, False);
8866 frameWaiting = True;
8867 signal(SIGALRM, FrameAlarm);
8868 delay.it_interval.tv_sec =
8869 delay.it_value.tv_sec = time / 1000;
8870 delay.it_interval.tv_usec =
8871 delay.it_value.tv_usec = (time % 1000) * 1000;
8872 setitimer(ITIMER_REAL, &delay, NULL);
8874 /* Ugh -- busy-wait! --tpm */
8875 while (frameWaiting);
8877 while (frameWaiting) pause();
8879 delay.it_interval.tv_sec = delay.it_value.tv_sec = 0;
8880 delay.it_interval.tv_usec = delay.it_value.tv_usec = 0;
8881 setitimer(ITIMER_REAL, &delay, NULL);
8891 XSync(xDisplay, False);
8893 usleep(time * 1000);
8898 /* Convert board position to corner of screen rect and color */
8901 ScreenSquare(column, row, pt, color)
8902 int column; int row; XPoint * pt; int * color;
8905 pt->x = lineGap + ((BOARD_WIDTH-1)-column) * (squareSize + lineGap);
8906 pt->y = lineGap + row * (squareSize + lineGap);
8908 pt->x = lineGap + column * (squareSize + lineGap);
8909 pt->y = lineGap + ((BOARD_HEIGHT-1)-row) * (squareSize + lineGap);
8911 *color = SquareColor(row, column);
8914 /* Convert window coords to square */
8917 BoardSquare(x, y, column, row)
8918 int x; int y; int * column; int * row;
8920 *column = EventToSquare(x, BOARD_WIDTH);
8921 if (flipView && *column >= 0)
8922 *column = BOARD_WIDTH - 1 - *column;
8923 *row = EventToSquare(y, BOARD_HEIGHT);
8924 if (!flipView && *row >= 0)
8925 *row = BOARD_HEIGHT - 1 - *row;
8930 #undef Max /* just in case */
8932 #define Max(a, b) ((a) > (b) ? (a) : (b))
8933 #define Min(a, b) ((a) < (b) ? (a) : (b))
8936 SetRect(rect, x, y, width, height)
8937 XRectangle * rect; int x; int y; int width; int height;
8941 rect->width = width;
8942 rect->height = height;
8945 /* Test if two frames overlap. If they do, return
8946 intersection rect within old and location of
8947 that rect within new. */
8950 Intersect(old, new, size, area, pt)
8951 XPoint * old; XPoint * new;
8952 int size; XRectangle * area; XPoint * pt;
8954 if (old->x > new->x + size || new->x > old->x + size ||
8955 old->y > new->y + size || new->y > old->y + size) {
8958 SetRect(area, Max(new->x - old->x, 0), Max(new->y - old->y, 0),
8959 size - abs(old->x - new->x), size - abs(old->y - new->y));
8960 pt->x = Max(old->x - new->x, 0);
8961 pt->y = Max(old->y - new->y, 0);
8966 /* For two overlapping frames, return the rect(s)
8967 in the old that do not intersect with the new. */
8970 CalcUpdateRects(old, new, size, update, nUpdates)
8971 XPoint * old; XPoint * new; int size;
8972 XRectangle update[]; int * nUpdates;
8976 /* If old = new (shouldn't happen) then nothing to draw */
8977 if (old->x == new->x && old->y == new->y) {
8981 /* Work out what bits overlap. Since we know the rects
8982 are the same size we don't need a full intersect calc. */
8984 /* Top or bottom edge? */
8985 if (new->y > old->y) {
8986 SetRect(&(update[count]), old->x, old->y, size, new->y - old->y);
8988 } else if (old->y > new->y) {
8989 SetRect(&(update[count]), old->x, old->y + size - (old->y - new->y),
8990 size, old->y - new->y);
8993 /* Left or right edge - don't overlap any update calculated above. */
8994 if (new->x > old->x) {
8995 SetRect(&(update[count]), old->x, Max(new->y, old->y),
8996 new->x - old->x, size - abs(new->y - old->y));
8998 } else if (old->x > new->x) {
8999 SetRect(&(update[count]), new->x + size, Max(new->y, old->y),
9000 old->x - new->x, size - abs(new->y - old->y));
9007 /* Generate a series of frame coords from start->mid->finish.
9008 The movement rate doubles until the half way point is
9009 reached, then halves back down to the final destination,
9010 which gives a nice slow in/out effect. The algorithmn
9011 may seem to generate too many intermediates for short
9012 moves, but remember that the purpose is to attract the
9013 viewers attention to the piece about to be moved and
9014 then to where it ends up. Too few frames would be less
9018 Tween(start, mid, finish, factor, frames, nFrames)
9019 XPoint * start; XPoint * mid;
9020 XPoint * finish; int factor;
9021 XPoint frames[]; int * nFrames;
9023 int fraction, n, count;
9027 /* Slow in, stepping 1/16th, then 1/8th, ... */
9029 for (n = 0; n < factor; n++)
9031 for (n = 0; n < factor; n++) {
9032 frames[count].x = start->x + (mid->x - start->x) / fraction;
9033 frames[count].y = start->y + (mid->y - start->y) / fraction;
9035 fraction = fraction / 2;
9039 frames[count] = *mid;
9042 /* Slow out, stepping 1/2, then 1/4, ... */
9044 for (n = 0; n < factor; n++) {
9045 frames[count].x = finish->x - (finish->x - mid->x) / fraction;
9046 frames[count].y = finish->y - (finish->y - mid->y) / fraction;
9048 fraction = fraction * 2;
9053 /* Draw a piece on the screen without disturbing what's there */
9056 SelectGCMask(piece, clip, outline, mask)
9057 ChessSquare piece; GC * clip; GC * outline; Pixmap * mask;
9061 /* Bitmap for piece being moved. */
9062 if (appData.monoMode) {
9063 *mask = *pieceToSolid(piece);
9064 } else if (useImages) {
9066 *mask = xpmMask[piece];
9068 *mask = ximMaskPm[piece];
9071 *mask = *pieceToSolid(piece);
9074 /* GC for piece being moved. Square color doesn't matter, but
9075 since it gets modified we make a copy of the original. */
9077 if (appData.monoMode)
9082 if (appData.monoMode)
9087 XCopyGC(xDisplay, source, 0xFFFFFFFF, *clip);
9089 /* Outline only used in mono mode and is not modified */
9091 *outline = bwPieceGC;
9093 *outline = wbPieceGC;
9097 OverlayPiece(piece, clip, outline, dest)
9098 ChessSquare piece; GC clip; GC outline; Drawable dest;
9103 /* Draw solid rectangle which will be clipped to shape of piece */
9104 XFillRectangle(xDisplay, dest, clip,
9105 0, 0, squareSize, squareSize);
9106 if (appData.monoMode)
9107 /* Also draw outline in contrasting color for black
9108 on black / white on white cases */
9109 XCopyPlane(xDisplay, *pieceToOutline(piece), dest, outline,
9110 0, 0, squareSize, squareSize, 0, 0, 1);
9112 /* Copy the piece */
9117 XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
9119 0, 0, squareSize, squareSize,
9124 /* Animate the movement of a single piece */
9127 BeginAnimation(anim, piece, startColor, start)
9135 /* The old buffer is initialised with the start square (empty) */
9136 BlankSquare(0, 0, startColor, EmptySquare, anim->saveBuf);
9137 anim->prevFrame = *start;
9139 /* The piece will be drawn using its own bitmap as a matte */
9140 SelectGCMask(piece, &anim->pieceGC, &anim->outlineGC, &mask);
9141 XSetClipMask(xDisplay, anim->pieceGC, mask);
9145 AnimationFrame(anim, frame, piece)
9150 XRectangle updates[4];
9155 /* Save what we are about to draw into the new buffer */
9156 XCopyArea(xDisplay, xBoardWindow, anim->newBuf, anim->blitGC,
9157 frame->x, frame->y, squareSize, squareSize,
9160 /* Erase bits of the previous frame */
9161 if (Intersect(&anim->prevFrame, frame, squareSize, &overlap, &pt)) {
9162 /* Where the new frame overlapped the previous,
9163 the contents in newBuf are wrong. */
9164 XCopyArea(xDisplay, anim->saveBuf, anim->newBuf, anim->blitGC,
9165 overlap.x, overlap.y,
9166 overlap.width, overlap.height,
9168 /* Repaint the areas in the old that don't overlap new */
9169 CalcUpdateRects(&anim->prevFrame, frame, squareSize, updates, &count);
9170 for (i = 0; i < count; i++)
9171 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9172 updates[i].x - anim->prevFrame.x,
9173 updates[i].y - anim->prevFrame.y,
9174 updates[i].width, updates[i].height,
9175 updates[i].x, updates[i].y);
9177 /* Easy when no overlap */
9178 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9179 0, 0, squareSize, squareSize,
9180 anim->prevFrame.x, anim->prevFrame.y);
9183 /* Save this frame for next time round */
9184 XCopyArea(xDisplay, anim->newBuf, anim->saveBuf, anim->blitGC,
9185 0, 0, squareSize, squareSize,
9187 anim->prevFrame = *frame;
9189 /* Draw piece over original screen contents, not current,
9190 and copy entire rect. Wipes out overlapping piece images. */
9191 OverlayPiece(piece, anim->pieceGC, anim->outlineGC, anim->newBuf);
9192 XCopyArea(xDisplay, anim->newBuf, xBoardWindow, anim->blitGC,
9193 0, 0, squareSize, squareSize,
9194 frame->x, frame->y);
9198 EndAnimation (anim, finish)
9202 XRectangle updates[4];
9207 /* The main code will redraw the final square, so we
9208 only need to erase the bits that don't overlap. */
9209 if (Intersect(&anim->prevFrame, finish, squareSize, &overlap, &pt)) {
9210 CalcUpdateRects(&anim->prevFrame, finish, squareSize, updates, &count);
9211 for (i = 0; i < count; i++)
9212 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9213 updates[i].x - anim->prevFrame.x,
9214 updates[i].y - anim->prevFrame.y,
9215 updates[i].width, updates[i].height,
9216 updates[i].x, updates[i].y);
9218 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9219 0, 0, squareSize, squareSize,
9220 anim->prevFrame.x, anim->prevFrame.y);
9225 FrameSequence(anim, piece, startColor, start, finish, frames, nFrames)
9227 ChessSquare piece; int startColor;
9228 XPoint * start; XPoint * finish;
9229 XPoint frames[]; int nFrames;
9233 BeginAnimation(anim, piece, startColor, start);
9234 for (n = 0; n < nFrames; n++) {
9235 AnimationFrame(anim, &(frames[n]), piece);
9236 FrameDelay(appData.animSpeed);
9238 EndAnimation(anim, finish);
9241 /* Main control logic for deciding what to animate and how */
9244 AnimateMove(board, fromX, fromY, toX, toY)
9253 XPoint start, finish, mid;
9254 XPoint frames[kFactor * 2 + 1];
9255 int nFrames, startColor, endColor;
9257 /* Are we animating? */
9258 if (!appData.animate || appData.blindfold)
9261 if(board[toY][toX] == WhiteRook && board[fromY][fromX] == WhiteKing ||
9262 board[toY][toX] == BlackRook && board[fromY][fromX] == BlackKing)
9263 return; // [HGM] FRC: no animtion of FRC castlings, as to-square is not true to-square
9265 if (fromY < 0 || fromX < 0 || toX < 0 || toY < 0) return;
9266 piece = board[fromY][fromX];
9267 if (piece >= EmptySquare) return;
9272 hop = (piece == WhiteKnight || piece == BlackKnight);
9275 if (appData.debugMode) {
9276 fprintf(debugFP, hop ? _("AnimateMove: piece %d hops from %d,%d to %d,%d \n") :
9277 _("AnimateMove: piece %d slides from %d,%d to %d,%d \n"),
9278 piece, fromX, fromY, toX, toY); }
9280 ScreenSquare(fromX, fromY, &start, &startColor);
9281 ScreenSquare(toX, toY, &finish, &endColor);
9284 /* Knight: make diagonal movement then straight */
9285 if (abs(toY - fromY) < abs(toX - fromX)) {
9286 mid.x = start.x + (finish.x - start.x) / 2;
9290 mid.y = start.y + (finish.y - start.y) / 2;
9293 mid.x = start.x + (finish.x - start.x) / 2;
9294 mid.y = start.y + (finish.y - start.y) / 2;
9297 /* Don't use as many frames for very short moves */
9298 if (abs(toY - fromY) + abs(toX - fromX) <= 2)
9299 Tween(&start, &mid, &finish, kFactor - 1, frames, &nFrames);
9301 Tween(&start, &mid, &finish, kFactor, frames, &nFrames);
9302 FrameSequence(&game, piece, startColor, &start, &finish, frames, nFrames);
9304 /* Be sure end square is redrawn */
9305 damage[toY][toX] = True;
9309 DragPieceBegin(x, y)
9312 int boardX, boardY, color;
9315 /* Are we animating? */
9316 if (!appData.animateDragging || appData.blindfold)
9319 /* Figure out which square we start in and the
9320 mouse position relative to top left corner. */
9321 BoardSquare(x, y, &boardX, &boardY);
9322 player.startBoardX = boardX;
9323 player.startBoardY = boardY;
9324 ScreenSquare(boardX, boardY, &corner, &color);
9325 player.startSquare = corner;
9326 player.startColor = color;
9328 /* Start from exactly where the piece is. This can be confusing
9329 if you start dragging far from the center of the square; most
9330 or all of the piece can be over a different square from the one
9331 the mouse pointer is in. */
9332 player.mouseDelta.x = x - corner.x;
9333 player.mouseDelta.y = y - corner.y;
9335 /* As soon as we start dragging, the piece will jump slightly to
9336 be centered over the mouse pointer. */
9337 player.mouseDelta.x = squareSize/2;
9338 player.mouseDelta.y = squareSize/2;
9340 /* Initialise animation */
9341 player.dragPiece = PieceForSquare(boardX, boardY);
9343 if (player.dragPiece >= 0 && player.dragPiece < EmptySquare) {
9344 player.dragActive = True;
9345 BeginAnimation(&player, player.dragPiece, color, &corner);
9346 /* Mark this square as needing to be redrawn. Note that
9347 we don't remove the piece though, since logically (ie
9348 as seen by opponent) the move hasn't been made yet. */
9349 if(boardX == BOARD_RGHT+1 && PieceForSquare(boardX-1, boardY) > 1 ||
9350 boardX == BOARD_LEFT-2 && PieceForSquare(boardX+1, boardY) > 1)
9351 XCopyArea(xDisplay, xBoardWindow, player.saveBuf, player.blitGC,
9352 corner.x, corner.y, squareSize, squareSize,
9353 0, 0); // [HGM] zh: unstack in stead of grab
9354 damage[boardY][boardX] = True;
9356 player.dragActive = False;
9366 /* Are we animating? */
9367 if (!appData.animateDragging || appData.blindfold)
9371 if (! player.dragActive)
9373 /* Move piece, maintaining same relative position
9374 of mouse within square */
9375 corner.x = x - player.mouseDelta.x;
9376 corner.y = y - player.mouseDelta.y;
9377 AnimationFrame(&player, &corner, player.dragPiece);
9379 if (appData.highlightDragging) {
9381 BoardSquare(x, y, &boardX, &boardY);
9382 SetHighlights(fromX, fromY, boardX, boardY);
9391 int boardX, boardY, color;
9394 /* Are we animating? */
9395 if (!appData.animateDragging || appData.blindfold)
9399 if (! player.dragActive)
9401 /* Last frame in sequence is square piece is
9402 placed on, which may not match mouse exactly. */
9403 BoardSquare(x, y, &boardX, &boardY);
9404 ScreenSquare(boardX, boardY, &corner, &color);
9405 EndAnimation(&player, &corner);
9407 /* Be sure end square is redrawn */
9408 damage[boardY][boardX] = True;
9410 /* This prevents weird things happening with fast successive
9411 clicks which on my Sun at least can cause motion events
9412 without corresponding press/release. */
9413 player.dragActive = False;
9416 /* Handle expose event while piece being dragged */
9421 if (!player.dragActive || appData.blindfold)
9424 /* What we're doing: logically, the move hasn't been made yet,
9425 so the piece is still in it's original square. But visually
9426 it's being dragged around the board. So we erase the square
9427 that the piece is on and draw it at the last known drag point. */
9428 BlankSquare(player.startSquare.x, player.startSquare.y,
9429 player.startColor, EmptySquare, xBoardWindow);
9430 AnimationFrame(&player, &player.prevFrame, player.dragPiece);
9431 damage[player.startBoardY][player.startBoardX] = TRUE;
9435 SetProgramStats( FrontEndProgramStats * stats )
9438 // [HGM] done, but perhaps backend should call this directly?
9439 EngineOutputUpdate( stats );