2 * xboard.c -- X front end for XBoard
3 * $Id: xboard.c,v 2.2 2003/11/06 07:22:14 mann Exp $
5 * Copyright 1991 by Digital Equipment Corporation, Maynard,
6 * Massachusetts. Enhancements Copyright
7 * 1992-2001,2002,2003,2004,2005,2006,2007,2008,2009 Free Software
10 * The following terms apply to Digital Equipment Corporation's copyright
12 * ------------------------------------------------------------------------
15 * Permission to use, copy, modify, and distribute this software and its
16 * documentation for any purpose and without fee is hereby granted,
17 * provided that the above copyright notice appear in all copies and that
18 * both that copyright notice and this permission notice appear in
19 * supporting documentation, and that the name of Digital not be
20 * used in advertising or publicity pertaining to distribution of the
21 * software without specific, written prior permission.
23 * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
24 * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
25 * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
26 * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
27 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
28 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
30 * ------------------------------------------------------------------------
32 * The following terms apply to the enhanced version of XBoard
33 * distributed by the Free Software Foundation:
34 * ------------------------------------------------------------------------
36 * GNU XBoard is free software: you can redistribute it and/or modify
37 * it under the terms of the GNU General Public License as published by
38 * the Free Software Foundation, either version 3 of the License, or (at
39 * your option) any later version.
41 * GNU XBoard is distributed in the hope that it will be useful, but
42 * WITHOUT ANY WARRANTY; without even the implied warranty of
43 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
44 * General Public License for more details.
46 * You should have received a copy of the GNU General Public License
47 * along with this program. If not, see http://www.gnu.org/licenses/. *
49 *------------------------------------------------------------------------
50 ** See the file ChangeLog for a revision history. */
58 #include <sys/types.h>
63 # if HAVE_SYS_SOCKET_H
64 # include <sys/socket.h>
65 # include <netinet/in.h>
67 # else /* not HAVE_SYS_SOCKET_H */
68 # if HAVE_LAN_SOCKET_H
69 # include <lan/socket.h>
71 # include <lan/netdb.h>
72 # else /* not HAVE_LAN_SOCKET_H */
73 # define OMIT_SOCKETS 1
74 # endif /* not HAVE_LAN_SOCKET_H */
75 # endif /* not HAVE_SYS_SOCKET_H */
76 #endif /* !OMIT_SOCKETS */
81 #else /* not STDC_HEADERS */
82 extern char *getenv();
85 # else /* not HAVE_STRING_H */
87 # endif /* not HAVE_STRING_H */
88 #endif /* not STDC_HEADERS */
91 # include <sys/fcntl.h>
92 #else /* not HAVE_SYS_FCNTL_H */
95 # endif /* HAVE_FCNTL_H */
96 #endif /* not HAVE_SYS_FCNTL_H */
98 #if HAVE_SYS_SYSTEMINFO_H
99 # include <sys/systeminfo.h>
100 #endif /* HAVE_SYS_SYSTEMINFO_H */
102 #if TIME_WITH_SYS_TIME
103 # include <sys/time.h>
107 # include <sys/time.h>
118 # include <sys/wait.h>
123 # define NAMLEN(dirent) strlen((dirent)->d_name)
124 # define HAVE_DIR_STRUCT
126 # define dirent direct
127 # define NAMLEN(dirent) (dirent)->d_namlen
129 # include <sys/ndir.h>
130 # define HAVE_DIR_STRUCT
133 # include <sys/dir.h>
134 # define HAVE_DIR_STRUCT
138 # define HAVE_DIR_STRUCT
142 #include <X11/Intrinsic.h>
143 #include <X11/StringDefs.h>
144 #include <X11/Shell.h>
145 #include <X11/cursorfont.h>
146 #include <X11/Xatom.h>
148 #include <X11/Xaw3d/Dialog.h>
149 #include <X11/Xaw3d/Form.h>
150 #include <X11/Xaw3d/List.h>
151 #include <X11/Xaw3d/Label.h>
152 #include <X11/Xaw3d/SimpleMenu.h>
153 #include <X11/Xaw3d/SmeBSB.h>
154 #include <X11/Xaw3d/SmeLine.h>
155 #include <X11/Xaw3d/Box.h>
156 #include <X11/Xaw3d/MenuButton.h>
157 #include <X11/Xaw3d/Text.h>
158 #include <X11/Xaw3d/AsciiText.h>
160 #include <X11/Xaw/Dialog.h>
161 #include <X11/Xaw/Form.h>
162 #include <X11/Xaw/List.h>
163 #include <X11/Xaw/Label.h>
164 #include <X11/Xaw/SimpleMenu.h>
165 #include <X11/Xaw/SmeBSB.h>
166 #include <X11/Xaw/SmeLine.h>
167 #include <X11/Xaw/Box.h>
168 #include <X11/Xaw/MenuButton.h>
169 #include <X11/Xaw/Text.h>
170 #include <X11/Xaw/AsciiText.h>
173 // [HGM] bitmaps: put before incuding the bitmaps / pixmaps, to know how many piece types there are.
178 #include "pixmaps/pixmaps.h"
179 #define IMAGE_EXT "xpm"
181 #define IMAGE_EXT "xim"
182 #include "bitmaps/bitmaps.h"
185 #include "bitmaps/icon_white.bm"
186 #include "bitmaps/icon_black.bm"
187 #include "bitmaps/checkmark.bm"
189 #include "frontend.h"
194 #include "xgamelist.h"
195 #include "xhistory.h"
196 #include "xedittags.h"
199 // must be moved to xengineoutput.h
201 void EngineOutputProc P((Widget w, XEvent *event,
202 String *prms, Cardinal *nprms));
204 void EngineOutputPopDown();
211 #define usleep(t) _sleep2(((t)+500)/1000)
215 # define _(s) gettext (s)
216 # define N_(s) gettext_noop (s)
232 int main P((int argc, char **argv));
233 RETSIGTYPE CmailSigHandler P((int sig));
234 RETSIGTYPE IntSigHandler P((int sig));
235 void CreateGCs P((void));
236 void CreateXIMPieces P((void));
237 void CreateXPMPieces P((void));
238 void CreatePieces P((void));
239 void CreatePieceMenus P((void));
240 Widget CreateMenuBar P((Menu *mb));
241 Widget CreateButtonBar P ((MenuItem *mi));
242 char *FindFont P((char *pattern, int targetPxlSize));
243 void PieceMenuPopup P((Widget w, XEvent *event,
244 String *params, Cardinal *num_params));
245 static void PieceMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
246 static void DropMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
247 void ReadBitmap P((Pixmap *pm, String name, unsigned char bits[],
248 u_int wreq, u_int hreq));
249 void CreateGrid P((void));
250 int EventToSquare P((int x, int limit));
251 void DrawSquare P((int row, int column, ChessSquare piece, int do_flash));
252 void EventProc P((Widget widget, caddr_t unused, XEvent *event));
253 void HandleUserMove P((Widget w, XEvent *event,
254 String *prms, Cardinal *nprms));
255 void AnimateUserMove P((Widget w, XEvent * event,
256 String * params, Cardinal * nParams));
257 void WhiteClock P((Widget w, XEvent *event,
258 String *prms, Cardinal *nprms));
259 void BlackClock P((Widget w, XEvent *event,
260 String *prms, Cardinal *nprms));
261 void DrawPositionProc P((Widget w, XEvent *event,
262 String *prms, Cardinal *nprms));
263 void XDrawPosition P((Widget w, /*Boolean*/int repaint,
265 void CommentPopUp P((char *title, char *label));
266 void CommentPopDown P((void));
267 void CommentCallback P((Widget w, XtPointer client_data,
268 XtPointer call_data));
269 void ICSInputBoxPopUp P((void));
270 void ICSInputBoxPopDown P((void));
271 void FileNamePopUp P((char *label, char *def,
272 FileProc proc, char *openMode));
273 void FileNamePopDown P((void));
274 void FileNameCallback P((Widget w, XtPointer client_data,
275 XtPointer call_data));
276 void FileNameAction P((Widget w, XEvent *event,
277 String *prms, Cardinal *nprms));
278 void AskQuestionReplyAction P((Widget w, XEvent *event,
279 String *prms, Cardinal *nprms));
280 void AskQuestionProc P((Widget w, XEvent *event,
281 String *prms, Cardinal *nprms));
282 void AskQuestionPopDown P((void));
283 void PromotionPopUp P((void));
284 void PromotionPopDown P((void));
285 void PromotionCallback P((Widget w, XtPointer client_data,
286 XtPointer call_data));
287 void EditCommentPopDown P((void));
288 void EditCommentCallback P((Widget w, XtPointer client_data,
289 XtPointer call_data));
290 void SelectCommand P((Widget w, XtPointer client_data, XtPointer call_data));
291 void ResetProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
292 void LoadGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
293 void LoadNextGameProc P((Widget w, XEvent *event, String *prms,
295 void LoadPrevGameProc P((Widget w, XEvent *event, String *prms,
297 void ReloadGameProc P((Widget w, XEvent *event, String *prms,
299 void LoadPositionProc P((Widget w, XEvent *event,
300 String *prms, Cardinal *nprms));
301 void LoadNextPositionProc P((Widget w, XEvent *event, String *prms,
303 void LoadPrevPositionProc P((Widget w, XEvent *event, String *prms,
305 void ReloadPositionProc P((Widget w, XEvent *event, String *prms,
307 void CopyPositionProc P((Widget w, XEvent *event, String *prms,
309 void PastePositionProc P((Widget w, XEvent *event, String *prms,
311 void CopyGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
312 void PasteGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
313 void SaveGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
314 void SavePositionProc P((Widget w, XEvent *event,
315 String *prms, Cardinal *nprms));
316 void MailMoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
317 void ReloadCmailMsgProc P((Widget w, XEvent *event, String *prms,
319 void QuitProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
320 void PauseProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
321 void MachineBlackProc P((Widget w, XEvent *event, String *prms,
323 void MachineWhiteProc P((Widget w, XEvent *event,
324 String *prms, Cardinal *nprms));
325 void AnalyzeModeProc P((Widget w, XEvent *event,
326 String *prms, Cardinal *nprms));
327 void AnalyzeFileProc P((Widget w, XEvent *event,
328 String *prms, Cardinal *nprms));
329 void TwoMachinesProc P((Widget w, XEvent *event, String *prms,
331 void IcsClientProc P((Widget w, XEvent *event, String *prms,
333 void EditGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
334 void EditPositionProc P((Widget w, XEvent *event,
335 String *prms, Cardinal *nprms));
336 void TrainingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
337 void EditCommentProc P((Widget w, XEvent *event,
338 String *prms, Cardinal *nprms));
339 void IcsInputBoxProc P((Widget w, XEvent *event,
340 String *prms, Cardinal *nprms));
341 void AcceptProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
342 void DeclineProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
343 void RematchProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
344 void CallFlagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
345 void DrawProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
346 void AbortProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
347 void AdjournProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
348 void ResignProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
349 void AdjuWhiteProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
350 void AdjuBlackProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
351 void AdjuDrawProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
352 void EnterKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
353 void StopObservingProc P((Widget w, XEvent *event, String *prms,
355 void StopExaminingProc P((Widget w, XEvent *event, String *prms,
357 void BackwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
358 void ForwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
359 void ToStartProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
360 void ToEndProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
361 void RevertProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
362 void TruncateGameProc P((Widget w, XEvent *event, String *prms,
364 void RetractMoveProc P((Widget w, XEvent *event, String *prms,
366 void MoveNowProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
367 void AlwaysQueenProc P((Widget w, XEvent *event, String *prms,
369 void AnimateDraggingProc P((Widget w, XEvent *event, String *prms,
371 void AnimateMovingProc P((Widget w, XEvent *event, String *prms,
373 void AutocommProc P((Widget w, XEvent *event, String *prms,
375 void AutoflagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
376 void AutoflipProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
377 void AutobsProc P((Widget w, XEvent *event, String *prms,
379 void AutoraiseProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
380 void AutosaveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
381 void BlindfoldProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
382 void FlashMovesProc P((Widget w, XEvent *event, String *prms,
384 void FlipViewProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
385 void GetMoveListProc P((Widget w, XEvent *event, String *prms,
387 void HighlightDraggingProc P((Widget w, XEvent *event, String *prms,
389 void HighlightLastMoveProc P((Widget w, XEvent *event, String *prms,
391 void MoveSoundProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
392 void IcsAlarmProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
393 void OldSaveStyleProc P((Widget w, XEvent *event, String *prms,
395 void PeriodicUpdatesProc P((Widget w, XEvent *event, String *prms,
397 void PonderNextMoveProc P((Widget w, XEvent *event, String *prms,
399 void PopupMoveErrorsProc P((Widget w, XEvent *event, String *prms,
401 void PopupExitMessageProc P((Widget w, XEvent *event, String *prms,
403 void PremoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
404 void QuietPlayProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
405 void ShowCoordsProc P((Widget w, XEvent *event, String *prms,
407 void ShowThinkingProc P((Widget w, XEvent *event, String *prms,
409 void HideThinkingProc P((Widget w, XEvent *event, String *prms,
411 void TestLegalityProc P((Widget w, XEvent *event, String *prms,
413 void InfoProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
414 void ManProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
415 void HintProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
416 void BookProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
417 void AboutGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
418 void AboutProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
419 void DebugProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
420 void NothingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
421 void Iconify P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
422 void DisplayMove P((int moveNumber));
423 void DisplayTitle P((char *title));
424 void ICSInitScript P((void));
425 int LoadGamePopUp P((FILE *f, int gameNumber, char *title));
426 void ErrorPopUp P((char *title, char *text, int modal));
427 void ErrorPopDown P((void));
428 static char *ExpandPathName P((char *path));
429 static void CreateAnimVars P((void));
430 static void DragPieceBegin P((int x, int y));
431 static void DragPieceMove P((int x, int y));
432 static void DragPieceEnd P((int x, int y));
433 static void DrawDragPiece P((void));
434 char *ModeToWidgetName P((GameMode mode));
435 void EngineOutputUpdate( FrontEndProgramStats * stats );
436 void ShuffleMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
437 void EngineMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
438 void UciMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
439 void TimeControlProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
440 void NewVariantProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
441 void FirstSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
442 void SecondSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
443 void ShufflePopDown P(());
444 void EnginePopDown P(());
445 void UciPopDown P(());
446 void TimeControlPopDown P(());
447 void NewVariantPopDown P(());
448 void SettingsPopDown P(());
450 * XBoard depends on Xt R4 or higher
452 int xtVersion = XtSpecificationRelease;
457 Pixel lightSquareColor, darkSquareColor, whitePieceColor, blackPieceColor,
458 jailSquareColor, highlightSquareColor, premoveHighlightColor;
459 Pixel lowTimeWarningColor;
460 GC lightSquareGC, darkSquareGC, jailSquareGC, lineGC, wdPieceGC, wlPieceGC,
461 bdPieceGC, blPieceGC, wbPieceGC, bwPieceGC, coordGC, highlineGC,
462 wjPieceGC, bjPieceGC, prelineGC, countGC;
463 Pixmap iconPixmap, wIconPixmap, bIconPixmap, xMarkPixmap;
464 Widget shellWidget, layoutWidget, formWidget, boardWidget, messageWidget,
465 whiteTimerWidget, blackTimerWidget, titleWidget, widgetList[16],
466 commentShell, promotionShell, whitePieceMenu, blackPieceMenu, dropMenu,
467 menuBarWidget, buttonBarWidget, editShell, errorShell, analysisShell,
468 ICSInputShell, fileNameShell, askQuestionShell;
469 XSegment gridSegments[(BOARD_SIZE + 1) * 2];
470 XSegment jailGridSegments[(BOARD_SIZE + 3) * 2];
471 Font clockFontID, coordFontID, countFontID;
472 XFontStruct *clockFontStruct, *coordFontStruct, *countFontStruct;
473 XtAppContext appContext;
475 char *oldICSInteractionTitle;
479 char installDir[] = "."; // [HGM] UCI: needed for UCI; probably needs run-time initializtion
481 Position commentX = -1, commentY = -1;
482 Dimension commentW, commentH;
484 int squareSize, smallLayout = 0, tinyLayout = 0,
485 marginW, marginH, // [HGM] for run-time resizing
486 fromX = -1, fromY = -1, toX, toY, commentUp = False, analysisUp = False,
487 ICSInputBoxUp = False, askQuestionUp = False,
488 filenameUp = False, promotionUp = False, pmFromX = -1, pmFromY = -1,
489 editUp = False, errorUp = False, errorExitStatus = -1, lineGap;
490 Pixel timerForegroundPixel, timerBackgroundPixel;
491 Pixel buttonForegroundPixel, buttonBackgroundPixel;
492 char *chessDir, *programName, *programVersion,
493 *gameCopyFilename, *gamePasteFilename;
497 Pixmap pieceBitmap[2][(int)BlackPawn];
498 Pixmap 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(PRODUCT, LOCALEDIR);
2391 textdomain(PRODUCT);
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);
3166 XtAppMainLoop(appContext);
3167 if (appData.debugMode) fclose(debugFP); // [DM] debug
3174 if (appData.icsActive && oldICSInteractionTitle != NULL) {
3175 DisplayIcsInteractionTitle(oldICSInteractionTitle);
3177 unlink(gameCopyFilename);
3178 unlink(gamePasteFilename);
3189 CmailSigHandler(sig)
3195 signal(SIGUSR1, SIG_IGN); /* suspend handler */
3197 /* Activate call-back function CmailSigHandlerCallBack() */
3198 OutputToProcess(cmailPR, (char *)(&dummy), sizeof(int), &error);
3200 signal(SIGUSR1, CmailSigHandler); /* re-activate handler */
3204 CmailSigHandlerCallBack(isr, closure, message, count, error)
3212 ReloadCmailMsgEvent(TRUE); /* Reload cmail msg */
3214 /**** end signal code ****/
3224 f = fopen(appData.icsLogon, "r");
3230 strcat(buf, appData.icsLogon);
3231 f = fopen(buf, "r");
3235 ProcessICSInitScript(f);
3242 EditCommentPopDown();
3253 SetMenuEnables(enab)
3257 if (!menuBarWidget) return;
3258 while (enab->name != NULL) {
3259 w = XtNameToWidget(menuBarWidget, enab->name);
3261 DisplayError(enab->name, 0);
3263 XtSetSensitive(w, enab->value);
3269 Enables icsEnables[] = {
3270 { "menuFile.Mail Move", False },
3271 { "menuFile.Reload CMail Message", False },
3272 { "menuMode.Machine Black", False },
3273 { "menuMode.Machine White", False },
3274 { "menuMode.Analysis Mode", False },
3275 { "menuMode.Analyze File", False },
3276 { "menuMode.Two Machines", False },
3278 { "menuHelp.Hint", False },
3279 { "menuHelp.Book", False },
3280 { "menuStep.Move Now", False },
3281 { "menuOptions.Periodic Updates", False },
3282 { "menuOptions.Hide Thinking", False },
3283 { "menuOptions.Ponder Next Move", False },
3288 Enables ncpEnables[] = {
3289 { "menuFile.Mail Move", False },
3290 { "menuFile.Reload CMail Message", False },
3291 { "menuMode.Machine White", False },
3292 { "menuMode.Machine Black", False },
3293 { "menuMode.Analysis Mode", False },
3294 { "menuMode.Analyze File", False },
3295 { "menuMode.Two Machines", False },
3296 { "menuMode.ICS Client", False },
3297 { "menuMode.ICS Input Box", False },
3298 { "Action", False },
3299 { "menuStep.Revert", False },
3300 { "menuStep.Move Now", False },
3301 { "menuStep.Retract Move", False },
3302 { "menuOptions.Auto Comment", False },
3303 { "menuOptions.Auto Flag", False },
3304 { "menuOptions.Auto Flip View", False },
3305 { "menuOptions.Auto Observe", False },
3306 { "menuOptions.Auto Raise Board", False },
3307 { "menuOptions.Get Move List", False },
3308 { "menuOptions.ICS Alarm", False },
3309 { "menuOptions.Move Sound", False },
3310 { "menuOptions.Quiet Play", False },
3311 { "menuOptions.Hide Thinking", False },
3312 { "menuOptions.Periodic Updates", False },
3313 { "menuOptions.Ponder Next Move", False },
3314 { "menuHelp.Hint", False },
3315 { "menuHelp.Book", False },
3319 Enables gnuEnables[] = {
3320 { "menuMode.ICS Client", False },
3321 { "menuMode.ICS Input Box", False },
3322 { "menuAction.Accept", False },
3323 { "menuAction.Decline", False },
3324 { "menuAction.Rematch", False },
3325 { "menuAction.Adjourn", False },
3326 { "menuAction.Stop Examining", False },
3327 { "menuAction.Stop Observing", False },
3328 { "menuStep.Revert", False },
3329 { "menuOptions.Auto Comment", False },
3330 { "menuOptions.Auto Observe", False },
3331 { "menuOptions.Auto Raise Board", False },
3332 { "menuOptions.Get Move List", False },
3333 { "menuOptions.Premove", False },
3334 { "menuOptions.Quiet Play", False },
3336 /* The next two options rely on SetCmailMode being called *after* */
3337 /* SetGNUMode so that when GNU is being used to give hints these */
3338 /* menu options are still available */
3340 { "menuFile.Mail Move", False },
3341 { "menuFile.Reload CMail Message", False },
3345 Enables cmailEnables[] = {
3347 { "menuAction.Call Flag", False },
3348 { "menuAction.Draw", True },
3349 { "menuAction.Adjourn", False },
3350 { "menuAction.Abort", False },
3351 { "menuAction.Stop Observing", False },
3352 { "menuAction.Stop Examining", False },
3353 { "menuFile.Mail Move", True },
3354 { "menuFile.Reload CMail Message", True },
3358 Enables trainingOnEnables[] = {
3359 { "menuMode.Edit Comment", False },
3360 { "menuMode.Pause", False },
3361 { "menuStep.Forward", False },
3362 { "menuStep.Backward", False },
3363 { "menuStep.Forward to End", False },
3364 { "menuStep.Back to Start", False },
3365 { "menuStep.Move Now", False },
3366 { "menuStep.Truncate Game", False },
3370 Enables trainingOffEnables[] = {
3371 { "menuMode.Edit Comment", True },
3372 { "menuMode.Pause", True },
3373 { "menuStep.Forward", True },
3374 { "menuStep.Backward", True },
3375 { "menuStep.Forward to End", True },
3376 { "menuStep.Back to Start", True },
3377 { "menuStep.Move Now", True },
3378 { "menuStep.Truncate Game", True },
3382 Enables machineThinkingEnables[] = {
3383 { "menuFile.Load Game", False },
3384 { "menuFile.Load Next Game", False },
3385 { "menuFile.Load Previous Game", False },
3386 { "menuFile.Reload Same Game", False },
3387 { "menuFile.Paste Game", False },
3388 { "menuFile.Load Position", False },
3389 { "menuFile.Load Next Position", False },
3390 { "menuFile.Load Previous Position", False },
3391 { "menuFile.Reload Same Position", False },
3392 { "menuFile.Paste Position", False },
3393 { "menuMode.Machine White", False },
3394 { "menuMode.Machine Black", False },
3395 { "menuMode.Two Machines", False },
3396 { "menuStep.Retract Move", False },
3400 Enables userThinkingEnables[] = {
3401 { "menuFile.Load Game", True },
3402 { "menuFile.Load Next Game", True },
3403 { "menuFile.Load Previous Game", True },
3404 { "menuFile.Reload Same Game", True },
3405 { "menuFile.Paste Game", True },
3406 { "menuFile.Load Position", True },
3407 { "menuFile.Load Next Position", True },
3408 { "menuFile.Load Previous Position", True },
3409 { "menuFile.Reload Same Position", True },
3410 { "menuFile.Paste Position", True },
3411 { "menuMode.Machine White", True },
3412 { "menuMode.Machine Black", True },
3413 { "menuMode.Two Machines", True },
3414 { "menuStep.Retract Move", True },
3420 SetMenuEnables(icsEnables);
3423 if (appData.zippyPlay && !appData.noChessProgram) /* [DM] icsEngineAnalyze */
3424 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Analysis Mode"), True);
3431 SetMenuEnables(ncpEnables);
3437 SetMenuEnables(gnuEnables);
3443 SetMenuEnables(cmailEnables);
3449 SetMenuEnables(trainingOnEnables);
3450 if (appData.showButtonBar) {
3451 XtSetSensitive(buttonBarWidget, False);
3457 SetTrainingModeOff()
3459 SetMenuEnables(trainingOffEnables);
3460 if (appData.showButtonBar) {
3461 XtSetSensitive(buttonBarWidget, True);
3466 SetUserThinkingEnables()
3468 if (appData.noChessProgram) return;
3469 SetMenuEnables(userThinkingEnables);
3473 SetMachineThinkingEnables()
3475 if (appData.noChessProgram) return;
3476 SetMenuEnables(machineThinkingEnables);
3478 case MachinePlaysBlack:
3479 case MachinePlaysWhite:
3480 case TwoMachinesPlay:
3481 XtSetSensitive(XtNameToWidget(menuBarWidget,
3482 ModeToWidgetName(gameMode)), True);
3489 #define Abs(n) ((n)<0 ? -(n) : (n))
3492 * Find a font that matches "pattern" that is as close as
3493 * possible to the targetPxlSize. Prefer fonts that are k
3494 * pixels smaller to fonts that are k pixels larger. The
3495 * pattern must be in the X Consortium standard format,
3496 * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".
3497 * The return value should be freed with XtFree when no
3500 char *FindFont(pattern, targetPxlSize)
3504 char **fonts, *p, *best, *scalable, *scalableTail;
3505 int i, j, nfonts, minerr, err, pxlSize;
3508 char **missing_list;
3510 char *def_string, *base_fnt_lst, strInt[3];
3512 XFontStruct **fnt_list;
3514 base_fnt_lst = calloc(1, strlen(pattern) + 3);
3515 sprintf(strInt, "%d", targetPxlSize);
3516 p = strstr(pattern, "--");
3517 strncpy(base_fnt_lst, pattern, p - pattern + 2);
3518 strcat(base_fnt_lst, strInt);
3519 strcat(base_fnt_lst, strchr(p + 2, '-'));
3521 if ((fntSet = XCreateFontSet(xDisplay,
3525 &def_string)) == NULL) {
3527 fprintf(stderr, _("Unable to create font set.\n"));
3531 nfonts = XFontsOfFontSet(fntSet, &fnt_list, &fonts);
3533 fonts = XListFonts(xDisplay, pattern, 999999, &nfonts);
3535 fprintf(stderr, _("%s: no fonts match pattern %s\n"),
3536 programName, pattern);
3544 for (i=0; i<nfonts; i++) {
3547 if (*p != '-') continue;
3549 if (*p == NULLCHAR) break;
3550 if (*p++ == '-') j++;
3552 if (j < 7) continue;
3555 scalable = fonts[i];
3558 err = pxlSize - targetPxlSize;
3559 if (Abs(err) < Abs(minerr) ||
3560 (minerr > 0 && err < 0 && -err == minerr)) {
3566 if (scalable && Abs(minerr) > appData.fontSizeTolerance) {
3567 /* If the error is too big and there is a scalable font,
3568 use the scalable font. */
3569 int headlen = scalableTail - scalable;
3570 p = (char *) XtMalloc(strlen(scalable) + 10);
3571 while (isdigit(*scalableTail)) scalableTail++;
3572 sprintf(p, "%.*s%d%s", headlen, scalable, targetPxlSize, scalableTail);
3574 p = (char *) XtMalloc(strlen(best) + 1);
3577 if (appData.debugMode) {
3578 fprintf(debugFP, _("resolved %s at pixel size %d\n to %s\n"),
3579 pattern, targetPxlSize, p);
3582 if (missing_count > 0)
3583 XFreeStringList(missing_list);
3584 XFreeFontSet(xDisplay, fntSet);
3586 XFreeFontNames(fonts);
3593 XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
3594 | GCBackground | GCFunction | GCPlaneMask;
3595 XGCValues gc_values;
3598 gc_values.plane_mask = AllPlanes;
3599 gc_values.line_width = lineGap;
3600 gc_values.line_style = LineSolid;
3601 gc_values.function = GXcopy;
3603 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3604 gc_values.background = XBlackPixel(xDisplay, xScreen);
3605 lineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3607 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3608 gc_values.background = XWhitePixel(xDisplay, xScreen);
3609 coordGC = XtGetGC(shellWidget, value_mask, &gc_values);
3610 XSetFont(xDisplay, coordGC, coordFontID);
3612 // [HGM] make font for holdings counts (white on black0
3613 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3614 gc_values.background = XBlackPixel(xDisplay, xScreen);
3615 countGC = XtGetGC(shellWidget, value_mask, &gc_values);
3616 XSetFont(xDisplay, countGC, countFontID);
3618 if (appData.monoMode) {
3619 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3620 gc_values.background = XWhitePixel(xDisplay, xScreen);
3621 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3623 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3624 gc_values.background = XBlackPixel(xDisplay, xScreen);
3625 lightSquareGC = wbPieceGC
3626 = XtGetGC(shellWidget, value_mask, &gc_values);
3628 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3629 gc_values.background = XWhitePixel(xDisplay, xScreen);
3630 darkSquareGC = bwPieceGC
3631 = XtGetGC(shellWidget, value_mask, &gc_values);
3633 if (DefaultDepth(xDisplay, xScreen) == 1) {
3634 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
3635 gc_values.function = GXcopyInverted;
3636 copyInvertedGC = XtGetGC(shellWidget, value_mask, &gc_values);
3637 gc_values.function = GXcopy;
3638 if (XBlackPixel(xDisplay, xScreen) == 1) {
3639 bwPieceGC = darkSquareGC;
3640 wbPieceGC = copyInvertedGC;
3642 bwPieceGC = copyInvertedGC;
3643 wbPieceGC = lightSquareGC;
3647 gc_values.foreground = highlightSquareColor;
3648 gc_values.background = highlightSquareColor;
3649 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3651 gc_values.foreground = premoveHighlightColor;
3652 gc_values.background = premoveHighlightColor;
3653 prelineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3655 gc_values.foreground = lightSquareColor;
3656 gc_values.background = darkSquareColor;
3657 lightSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3659 gc_values.foreground = darkSquareColor;
3660 gc_values.background = lightSquareColor;
3661 darkSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3663 gc_values.foreground = jailSquareColor;
3664 gc_values.background = jailSquareColor;
3665 jailSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3667 gc_values.foreground = whitePieceColor;
3668 gc_values.background = darkSquareColor;
3669 wdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3671 gc_values.foreground = whitePieceColor;
3672 gc_values.background = lightSquareColor;
3673 wlPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3675 gc_values.foreground = whitePieceColor;
3676 gc_values.background = jailSquareColor;
3677 wjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3679 gc_values.foreground = blackPieceColor;
3680 gc_values.background = darkSquareColor;
3681 bdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3683 gc_values.foreground = blackPieceColor;
3684 gc_values.background = lightSquareColor;
3685 blPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3687 gc_values.foreground = blackPieceColor;
3688 gc_values.background = jailSquareColor;
3689 bjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3693 void loadXIM(xim, xmask, filename, dest, mask)
3706 fp = fopen(filename, "rb");
3708 fprintf(stderr, _("%s: error loading XIM!\n"), programName);
3715 for (y=0; y<h; ++y) {
3716 for (x=0; x<h; ++x) {
3721 XPutPixel(xim, x, y, blackPieceColor);
3723 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3726 XPutPixel(xim, x, y, darkSquareColor);
3728 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3731 XPutPixel(xim, x, y, whitePieceColor);
3733 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3736 XPutPixel(xim, x, y, lightSquareColor);
3738 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3744 /* create Pixmap of piece */
3745 *dest = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3747 XPutImage(xDisplay, *dest, lightSquareGC, xim,
3750 /* create Pixmap of clipmask
3751 Note: We assume the white/black pieces have the same
3752 outline, so we make only 6 masks. This is okay
3753 since the XPM clipmask routines do the same. */
3755 temp = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3757 XPutImage(xDisplay, temp, lightSquareGC, xmask,
3760 /* now create the 1-bit version */
3761 *mask = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3764 values.foreground = 1;
3765 values.background = 0;
3767 /* Don't use XtGetGC, not read only */
3768 maskGC = XCreateGC(xDisplay, *mask,
3769 GCForeground | GCBackground, &values);
3770 XCopyPlane(xDisplay, temp, *mask, maskGC,
3771 0, 0, squareSize, squareSize, 0, 0, 1);
3772 XFreePixmap(xDisplay, temp);
3777 char pieceBitmapNames[] = "pnbrqfeacwmohijgdvlsukpnsl";
3779 void CreateXIMPieces()
3784 static char *ximkind[] = { "ll", "ld", "dl", "dd" };
3789 /* The XSynchronize calls were copied from CreatePieces.
3790 Not sure if needed, but can't hurt */
3791 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3794 /* temp needed by loadXIM() */
3795 ximtemp = XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3796 0, 0, ss, ss, AllPlanes, XYPixmap);
3798 if (strlen(appData.pixmapDirectory) == 0) {
3802 if (appData.monoMode) {
3803 DisplayFatalError(_("XIM pieces cannot be used in monochrome mode"),
3807 fprintf(stderr, _("\nLoading XIMs...\n"));
3809 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3810 fprintf(stderr, "%d", piece+1);
3811 for (kind=0; kind<4; kind++) {
3812 fprintf(stderr, ".");
3813 snprintf(buf, sizeof(buf), "%s/%s%c%s%u.xim",
3814 ExpandPathName(appData.pixmapDirectory),
3815 piece <= (int) WhiteKing ? "" : "w",
3816 pieceBitmapNames[piece],
3818 ximPieceBitmap[kind][piece] =
3819 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3820 0, 0, ss, ss, AllPlanes, XYPixmap);
3821 if (appData.debugMode)
3822 fprintf(stderr, _("(File:%s:) "), buf);
3823 loadXIM(ximPieceBitmap[kind][piece],
3825 &(xpmPieceBitmap2[kind][piece]),
3826 &(ximMaskPm2[piece]));
3827 if(piece <= (int)WhiteKing)
3828 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3830 fprintf(stderr," ");
3832 /* Load light and dark squares */
3833 /* If the LSQ and DSQ pieces don't exist, we will
3834 draw them with solid squares. */
3835 snprintf(buf,sizeof(buf), "%s/lsq%u.xim", ExpandPathName(appData.pixmapDirectory), ss);
3836 if (access(buf, 0) != 0) {
3840 fprintf(stderr, _("light square "));
3842 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3843 0, 0, ss, ss, AllPlanes, XYPixmap);
3844 if (appData.debugMode)
3845 fprintf(stderr, _("(File:%s:) "), buf);
3847 loadXIM(ximLightSquare, NULL, buf, &xpmLightSquare, NULL);
3848 fprintf(stderr, _("dark square "));
3849 snprintf(buf,sizeof(buf), "%s/dsq%u.xim",
3850 ExpandPathName(appData.pixmapDirectory), ss);
3851 if (appData.debugMode)
3852 fprintf(stderr, _("(File:%s:) "), buf);
3854 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3855 0, 0, ss, ss, AllPlanes, XYPixmap);
3856 loadXIM(ximDarkSquare, NULL, buf, &xpmDarkSquare, NULL);
3857 xpmJailSquare = xpmLightSquare;
3859 fprintf(stderr, _("Done.\n"));
3861 XSynchronize(xDisplay, False); /* Work-around for xlib/xt buffering bug */
3865 void CreateXPMPieces()
3869 u_int ss = squareSize;
3871 static char *xpmkind[] = { "ll", "ld", "dl", "dd" };
3872 XpmColorSymbol symbols[4];
3875 /* Apparently some versions of Xpm don't define XpmFormat at all --tpm */
3876 if (appData.debugMode) {
3877 fprintf(stderr, "XPM Library Version: %d.%d%c\n",
3878 XpmFormat, XpmVersion, (char)('a' + XpmRevision - 1));
3882 /* The XSynchronize calls were copied from CreatePieces.
3883 Not sure if needed, but can't hurt */
3884 XSynchronize(xDisplay, True); /* Work-around for xlib/xt buffering bug */
3886 /* Setup translations so piece colors match square colors */
3887 symbols[0].name = "light_piece";
3888 symbols[0].value = appData.whitePieceColor;
3889 symbols[1].name = "dark_piece";
3890 symbols[1].value = appData.blackPieceColor;
3891 symbols[2].name = "light_square";
3892 symbols[2].value = appData.lightSquareColor;
3893 symbols[3].name = "dark_square";
3894 symbols[3].value = appData.darkSquareColor;
3896 attr.valuemask = XpmColorSymbols;
3897 attr.colorsymbols = symbols;
3898 attr.numsymbols = 4;
3900 if (appData.monoMode) {
3901 DisplayFatalError(_("XPM pieces cannot be used in monochrome mode"),
3905 if (strlen(appData.pixmapDirectory) == 0) {
3906 XpmPieces* pieces = builtInXpms;
3909 while (pieces->size != squareSize && pieces->size) pieces++;
3910 if (!pieces->size) {
3911 fprintf(stderr, _("No builtin XPM pieces of size %d\n"), squareSize);
3914 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3915 for (kind=0; kind<4; kind++) {
3917 if ((r=XpmCreatePixmapFromData(xDisplay, xBoardWindow,
3918 pieces->xpm[piece][kind],
3919 &(xpmPieceBitmap2[kind][piece]),
3920 NULL, &attr)) != 0) {
3921 fprintf(stderr, _("Error %d loading XPM image \"%s\"\n"),
3925 if(piece <= (int) WhiteKing)
3926 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3930 xpmJailSquare = xpmLightSquare;
3934 fprintf(stderr, _("\nLoading XPMs...\n"));
3937 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3938 fprintf(stderr, "%d ", piece+1);
3939 for (kind=0; kind<4; kind++) {
3940 snprintf(buf, sizeof(buf), "%s/%s%c%s%u.xpm",
3941 ExpandPathName(appData.pixmapDirectory),
3942 piece > (int) WhiteKing ? "w" : "",
3943 pieceBitmapNames[piece],
3945 if (appData.debugMode) {
3946 fprintf(stderr, _("(File:%s:) "), buf);
3948 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3949 &(xpmPieceBitmap2[kind][piece]),
3950 NULL, &attr)) != 0) {
3951 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"),
3955 if(piece <= (int) WhiteKing)
3956 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3959 /* Load light and dark squares */
3960 /* If the LSQ and DSQ pieces don't exist, we will
3961 draw them with solid squares. */
3962 fprintf(stderr, _("light square "));
3963 snprintf(buf, sizeof(buf), "%s/lsq%u.xpm", ExpandPathName(appData.pixmapDirectory), ss);
3964 if (access(buf, 0) != 0) {
3968 if (appData.debugMode)
3969 fprintf(stderr, _("(File:%s:) "), buf);
3971 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3972 &xpmLightSquare, NULL, &attr)) != 0) {
3973 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
3976 fprintf(stderr, _("dark square "));
3977 snprintf(buf, sizeof(buf), "%s/dsq%u.xpm",
3978 ExpandPathName(appData.pixmapDirectory), ss);
3979 if (appData.debugMode) {
3980 fprintf(stderr, _("(File:%s:) "), buf);
3982 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3983 &xpmDarkSquare, NULL, &attr)) != 0) {
3984 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
3988 xpmJailSquare = xpmLightSquare;
3989 fprintf(stderr, _("Done.\n"));
3991 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3994 #endif /* HAVE_LIBXPM */
3997 /* No built-in bitmaps */
4002 u_int ss = squareSize;
4004 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
4007 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
4008 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
4009 sprintf(buf, "%s%c%u%c.bm", piece > (int)WhiteKing ? "w" : "",
4010 pieceBitmapNames[piece],
4011 ss, kind == SOLID ? 's' : 'o');
4012 ReadBitmap(&pieceBitmap2[kind][piece], buf, NULL, ss, ss);
4013 if(piece <= (int)WhiteKing)
4014 pieceBitmap[kind][piece] = pieceBitmap2[kind][piece];
4018 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
4022 /* With built-in bitmaps */
4025 BuiltInBits* bib = builtInBits;
4028 u_int ss = squareSize;
4030 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
4033 while (bib->squareSize != ss && bib->squareSize != 0) bib++;
4035 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
4036 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
4037 sprintf(buf, "%s%c%u%c.bm", piece > (int)WhiteKing ? "w" : "",
4038 pieceBitmapNames[piece],
4039 ss, kind == SOLID ? 's' : 'o');
4040 ReadBitmap(&pieceBitmap2[kind][piece], buf,
4041 bib->bits[kind][piece], ss, ss);
4042 if(piece <= (int)WhiteKing)
4043 pieceBitmap[kind][piece] = pieceBitmap2[kind][piece];
4047 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
4052 void ReadBitmap(pm, name, bits, wreq, hreq)
4055 unsigned char bits[];
4061 char msg[MSG_SIZ], fullname[MSG_SIZ];
4063 if (*appData.bitmapDirectory != NULLCHAR) {
4064 strcpy(fullname, appData.bitmapDirectory);
4065 strcat(fullname, "/");
4066 strcat(fullname, name);
4067 errcode = XReadBitmapFile(xDisplay, xBoardWindow, fullname,
4068 &w, &h, pm, &x_hot, &y_hot);
4069 fprintf(stderr, "load %s\n", name);
4070 if (errcode != BitmapSuccess) {
4072 case BitmapOpenFailed:
4073 snprintf(msg, sizeof(msg), _("Can't open bitmap file %s"), fullname);
4075 case BitmapFileInvalid:
4076 snprintf(msg, sizeof(msg), _("Invalid bitmap in file %s"), fullname);
4078 case BitmapNoMemory:
4079 snprintf(msg, sizeof(msg), _("Ran out of memory reading bitmap file %s"),
4083 snprintf(msg, sizeof(msg), _("Unknown XReadBitmapFile error %d on file %s"),
4087 fprintf(stderr, _("%s: %s...using built-in\n"),
4089 } else if (w != wreq || h != hreq) {
4091 _("%s: Bitmap %s is %dx%d, not %dx%d...using built-in\n"),
4092 programName, fullname, w, h, wreq, hreq);
4099 fprintf(stderr, _("%s: No built-in bitmap for %s; giving up\n"),
4103 ; // [HGM] bitmaps: make it non-fatal if we have no bitmap;
4105 *pm = XCreateBitmapFromData(xDisplay, xBoardWindow, (char *) bits,
4114 if (lineGap == 0) return;
4116 /* [HR] Split this into 2 loops for non-square boards. */
4118 for (i = 0; i < BOARD_HEIGHT + 1; i++) {
4119 gridSegments[i].x1 = 0;
4120 gridSegments[i].x2 =
4121 lineGap + BOARD_WIDTH * (squareSize + lineGap);
4122 gridSegments[i].y1 = gridSegments[i].y2
4123 = lineGap / 2 + (i * (squareSize + lineGap));
4126 for (j = 0; j < BOARD_WIDTH + 1; j++) {
4127 gridSegments[j + i].y1 = 0;
4128 gridSegments[j + i].y2 =
4129 lineGap + BOARD_HEIGHT * (squareSize + lineGap);
4130 gridSegments[j + i].x1 = gridSegments[j + i].x2
4131 = lineGap / 2 + (j * (squareSize + lineGap));
4135 static void MenuBarSelect(w, addr, index)
4140 XtActionProc proc = (XtActionProc) addr;
4142 (proc)(NULL, NULL, NULL, NULL);
4145 void CreateMenuBarPopup(parent, name, mb)
4155 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
4158 XtSetArg(args[j], XtNleftMargin, 20); j++;
4159 XtSetArg(args[j], XtNrightMargin, 20); j++;
4161 while (mi->string != NULL) {
4162 if (strcmp(mi->string, "----") == 0) {
4163 entry = XtCreateManagedWidget(mi->string, smeLineObjectClass,
4166 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string)));
4167 entry = XtCreateManagedWidget(mi->string, smeBSBObjectClass,
4169 XtAddCallback(entry, XtNcallback,
4170 (XtCallbackProc) MenuBarSelect,
4171 (caddr_t) mi->proc);
4177 Widget CreateMenuBar(mb)
4181 Widget anchor, menuBar;
4183 char menuName[MSG_SIZ];
4186 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
4187 XtSetArg(args[j], XtNvSpace, 0); j++;
4188 XtSetArg(args[j], XtNborderWidth, 0); j++;
4189 menuBar = XtCreateWidget("menuBar", boxWidgetClass,
4190 formWidget, args, j);
4192 while (mb->name != NULL) {
4193 strcpy(menuName, "menu");
4194 strcat(menuName, mb->name);
4196 XtSetArg(args[j], XtNmenuName, XtNewString(menuName)); j++;
4199 shortName[0] = _(mb->name)[0];
4200 shortName[1] = NULLCHAR;
4201 XtSetArg(args[j], XtNlabel, XtNewString(shortName)); j++;
4204 XtSetArg(args[j], XtNlabel, XtNewString(_(mb->name))); j++;
4207 XtSetArg(args[j], XtNborderWidth, 0); j++;
4208 anchor = XtCreateManagedWidget(mb->name, menuButtonWidgetClass,
4210 CreateMenuBarPopup(menuBar, menuName, mb);
4216 Widget CreateButtonBar(mi)
4220 Widget button, buttonBar;
4224 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
4226 XtSetArg(args[j], XtNhSpace, 0); j++;
4228 XtSetArg(args[j], XtNborderWidth, 0); j++;
4229 XtSetArg(args[j], XtNvSpace, 0); j++;
4230 buttonBar = XtCreateWidget("buttonBar", boxWidgetClass,
4231 formWidget, args, j);
4233 while (mi->string != NULL) {
4236 XtSetArg(args[j], XtNinternalWidth, 2); j++;
4237 XtSetArg(args[j], XtNborderWidth, 0); j++;
4239 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string))); j++;
4240 button = XtCreateManagedWidget(mi->string, commandWidgetClass,
4241 buttonBar, args, j);
4242 XtAddCallback(button, XtNcallback,
4243 (XtCallbackProc) MenuBarSelect,
4244 (caddr_t) mi->proc);
4251 CreatePieceMenu(name, color)
4258 ChessSquare selection;
4260 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
4261 boardWidget, args, 0);
4263 for (i = 0; i < PIECE_MENU_SIZE; i++) {
4264 String item = pieceMenuStrings[color][i];
4266 if (strcmp(item, "----") == 0) {
4267 entry = XtCreateManagedWidget(item, smeLineObjectClass,
4270 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
4271 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
4273 selection = pieceMenuTranslation[color][i];
4274 XtAddCallback(entry, XtNcallback,
4275 (XtCallbackProc) PieceMenuSelect,
4276 (caddr_t) selection);
4277 if (selection == WhitePawn || selection == BlackPawn) {
4278 XtSetArg(args[0], XtNpopupOnEntry, entry);
4279 XtSetValues(menu, args, 1);
4292 ChessSquare selection;
4294 whitePieceMenu = CreatePieceMenu("menuW", 0);
4295 blackPieceMenu = CreatePieceMenu("menuB", 1);
4297 XtRegisterGrabAction(PieceMenuPopup, True,
4298 (unsigned)(ButtonPressMask|ButtonReleaseMask),
4299 GrabModeAsync, GrabModeAsync);
4301 XtSetArg(args[0], XtNlabel, _("Drop"));
4302 dropMenu = XtCreatePopupShell("menuD", simpleMenuWidgetClass,
4303 boardWidget, args, 1);
4304 for (i = 0; i < DROP_MENU_SIZE; i++) {
4305 String item = dropMenuStrings[i];
4307 if (strcmp(item, "----") == 0) {
4308 entry = XtCreateManagedWidget(item, smeLineObjectClass,
4311 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
4312 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
4314 selection = dropMenuTranslation[i];
4315 XtAddCallback(entry, XtNcallback,
4316 (XtCallbackProc) DropMenuSelect,
4317 (caddr_t) selection);
4322 void SetupDropMenu()
4330 for (i=0; i<sizeof(dmEnables)/sizeof(DropMenuEnables); i++) {
4331 entry = XtNameToWidget(dropMenu, dmEnables[i].widget);
4332 p = strchr(gameMode == IcsPlayingWhite ? white_holding : black_holding,
4333 dmEnables[i].piece);
4334 XtSetSensitive(entry, p != NULL || !appData.testLegality
4335 /*!!temp:*/ || (gameInfo.variant == VariantCrazyhouse
4336 && !appData.icsActive));
4338 while (p && *p++ == dmEnables[i].piece) count++;
4339 snprintf(label, sizeof(label), "%s %d", dmEnables[i].widget, count);
4341 XtSetArg(args[j], XtNlabel, label); j++;
4342 XtSetValues(entry, args, j);
4346 void PieceMenuPopup(w, event, params, num_params)
4350 Cardinal *num_params;
4353 if (event->type != ButtonPress) return;
4354 if (errorUp) ErrorPopDown();
4358 whichMenu = params[0];
4360 case IcsPlayingWhite:
4361 case IcsPlayingBlack:
4363 case MachinePlaysWhite:
4364 case MachinePlaysBlack:
4365 if (appData.testLegality &&
4366 gameInfo.variant != VariantBughouse &&
4367 gameInfo.variant != VariantCrazyhouse) return;
4369 whichMenu = "menuD";
4375 if (((pmFromX = EventToSquare(event->xbutton.x, BOARD_WIDTH)) < 0) ||
4376 ((pmFromY = EventToSquare(event->xbutton.y, BOARD_HEIGHT)) < 0)) {
4377 pmFromX = pmFromY = -1;
4381 pmFromX = BOARD_WIDTH - 1 - pmFromX;
4383 pmFromY = BOARD_HEIGHT - 1 - pmFromY;
4385 XtPopupSpringLoaded(XtNameToWidget(boardWidget, whichMenu));
4388 static void PieceMenuSelect(w, piece, junk)
4393 if (pmFromX < 0 || pmFromY < 0) return;
4394 EditPositionMenuEvent(piece, pmFromX, pmFromY);
4397 static void DropMenuSelect(w, piece, junk)
4402 if (pmFromX < 0 || pmFromY < 0) return;
4403 DropMenuEvent(piece, pmFromX, pmFromY);
4406 void WhiteClock(w, event, prms, nprms)
4412 if (gameMode == EditPosition || gameMode == IcsExamining) {
4413 SetWhiteToPlayEvent();
4414 } else if (gameMode == IcsPlayingBlack || gameMode == MachinePlaysWhite) {
4419 void BlackClock(w, event, prms, nprms)
4425 if (gameMode == EditPosition || gameMode == IcsExamining) {
4426 SetBlackToPlayEvent();
4427 } else if (gameMode == IcsPlayingWhite || gameMode == MachinePlaysBlack) {
4434 * If the user selects on a border boundary, return -1; if off the board,
4435 * return -2. Otherwise map the event coordinate to the square.
4437 int EventToSquare(x, limit)
4445 if ((x % (squareSize + lineGap)) >= squareSize)
4447 x /= (squareSize + lineGap);
4453 static void do_flash_delay(msec)
4459 static void drawHighlight(file, rank, gc)
4465 if (lineGap == 0 || appData.blindfold) return;
4468 x = lineGap/2 + ((BOARD_WIDTH-1)-file) *
4469 (squareSize + lineGap);
4470 y = lineGap/2 + rank * (squareSize + lineGap);
4472 x = lineGap/2 + file * (squareSize + lineGap);
4473 y = lineGap/2 + ((BOARD_HEIGHT-1)-rank) *
4474 (squareSize + lineGap);
4477 XDrawRectangle(xDisplay, xBoardWindow, gc, x, y,
4478 squareSize+lineGap, squareSize+lineGap);
4481 int hi1X = -1, hi1Y = -1, hi2X = -1, hi2Y = -1;
4482 int pm1X = -1, pm1Y = -1, pm2X = -1, pm2Y = -1;
4485 SetHighlights(fromX, fromY, toX, toY)
4486 int fromX, fromY, toX, toY;
4488 if (hi1X != fromX || hi1Y != fromY) {
4489 if (hi1X >= 0 && hi1Y >= 0) {
4490 drawHighlight(hi1X, hi1Y, lineGC);
4492 if (fromX >= 0 && fromY >= 0) {
4493 drawHighlight(fromX, fromY, highlineGC);
4496 if (hi2X != toX || hi2Y != toY) {
4497 if (hi2X >= 0 && hi2Y >= 0) {
4498 drawHighlight(hi2X, hi2Y, lineGC);
4500 if (toX >= 0 && toY >= 0) {
4501 drawHighlight(toX, toY, highlineGC);
4513 SetHighlights(-1, -1, -1, -1);
4518 SetPremoveHighlights(fromX, fromY, toX, toY)
4519 int fromX, fromY, toX, toY;
4521 if (pm1X != fromX || pm1Y != fromY) {
4522 if (pm1X >= 0 && pm1Y >= 0) {
4523 drawHighlight(pm1X, pm1Y, lineGC);
4525 if (fromX >= 0 && fromY >= 0) {
4526 drawHighlight(fromX, fromY, prelineGC);
4529 if (pm2X != toX || pm2Y != toY) {
4530 if (pm2X >= 0 && pm2Y >= 0) {
4531 drawHighlight(pm2X, pm2Y, lineGC);
4533 if (toX >= 0 && toY >= 0) {
4534 drawHighlight(toX, toY, prelineGC);
4544 ClearPremoveHighlights()
4546 SetPremoveHighlights(-1, -1, -1, -1);
4549 static void BlankSquare(x, y, color, piece, dest)
4554 if (useImages && useImageSqs) {
4558 pm = xpmLightSquare;
4563 case 2: /* neutral */
4568 XCopyArea(xDisplay, pm, dest, wlPieceGC, 0, 0,
4569 squareSize, squareSize, x, y);
4579 case 2: /* neutral */
4584 XFillRectangle(xDisplay, dest, gc, x, y, squareSize, squareSize);
4589 I split out the routines to draw a piece so that I could
4590 make a generic flash routine.
4592 static void monoDrawPiece_1bit(piece, square_color, x, y, dest)
4594 int square_color, x, y;
4597 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
4598 switch (square_color) {
4600 case 2: /* neutral */
4602 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
4603 ? *pieceToOutline(piece)
4604 : *pieceToSolid(piece),
4605 dest, bwPieceGC, 0, 0,
4606 squareSize, squareSize, x, y);
4609 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
4610 ? *pieceToSolid(piece)
4611 : *pieceToOutline(piece),
4612 dest, wbPieceGC, 0, 0,
4613 squareSize, squareSize, x, y);
4618 static void monoDrawPiece(piece, square_color, x, y, dest)
4620 int square_color, x, y;
4623 switch (square_color) {
4625 case 2: /* neutral */
4627 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
4628 ? *pieceToOutline(piece)
4629 : *pieceToSolid(piece),
4630 dest, bwPieceGC, 0, 0,
4631 squareSize, squareSize, x, y, 1);
4634 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
4635 ? *pieceToSolid(piece)
4636 : *pieceToOutline(piece),
4637 dest, wbPieceGC, 0, 0,
4638 squareSize, squareSize, x, y, 1);
4643 static void colorDrawPiece(piece, square_color, x, y, dest)
4645 int square_color, x, y;
4648 if(pieceToSolid(piece) == NULL) return; // [HGM] bitmaps: make it non-fatal if we have no bitmap;
4649 switch (square_color) {
4651 XCopyPlane(xDisplay, *pieceToSolid(piece),
4652 dest, (int) piece < (int) BlackPawn
4653 ? wlPieceGC : blPieceGC, 0, 0,
4654 squareSize, squareSize, x, y, 1);
4657 XCopyPlane(xDisplay, *pieceToSolid(piece),
4658 dest, (int) piece < (int) BlackPawn
4659 ? wdPieceGC : bdPieceGC, 0, 0,
4660 squareSize, squareSize, x, y, 1);
4662 case 2: /* neutral */
4664 XCopyPlane(xDisplay, *pieceToSolid(piece),
4665 dest, (int) piece < (int) BlackPawn
4666 ? wjPieceGC : bjPieceGC, 0, 0,
4667 squareSize, squareSize, x, y, 1);
4672 static void colorDrawPieceImage(piece, square_color, x, y, dest)
4674 int square_color, x, y;
4679 switch (square_color) {
4681 case 2: /* neutral */
4683 if ((int)piece < (int) BlackPawn) {
4691 if ((int)piece < (int) BlackPawn) {
4699 XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
4700 dest, wlPieceGC, 0, 0,
4701 squareSize, squareSize, x, y);
4704 typedef void (*DrawFunc)();
4706 DrawFunc ChooseDrawFunc()
4708 if (appData.monoMode) {
4709 if (DefaultDepth(xDisplay, xScreen) == 1) {
4710 return monoDrawPiece_1bit;
4712 return monoDrawPiece;
4716 return colorDrawPieceImage;
4718 return colorDrawPiece;
4722 /* [HR] determine square color depending on chess variant. */
4723 static int SquareColor(row, column)
4728 if (gameInfo.variant == VariantXiangqi) {
4729 if (column >= 3 && column <= 5 && row >= 0 && row <= 2) {
4731 } else if (column >= 3 && column <= 5 && row >= 7 && row <= 9) {
4733 } else if (row <= 4) {
4739 square_color = ((column + row) % 2) == 1;
4742 /* [hgm] holdings: next line makes all holdings squares light */
4743 if(column < BOARD_LEFT || column >= BOARD_RGHT) square_color = 1;
4745 return square_color;
4748 void DrawSquare(row, column, piece, do_flash)
4749 int row, column, do_flash;
4752 int square_color, x, y, direction, font_ascent, font_descent;
4755 XCharStruct overall;
4759 /* Calculate delay in milliseconds (2-delays per complete flash) */
4760 flash_delay = 500 / appData.flashRate;
4763 x = lineGap + ((BOARD_WIDTH-1)-column) *
4764 (squareSize + lineGap);
4765 y = lineGap + row * (squareSize + lineGap);
4767 x = lineGap + column * (squareSize + lineGap);
4768 y = lineGap + ((BOARD_HEIGHT-1)-row) *
4769 (squareSize + lineGap);
4772 square_color = SquareColor(row, column);
4774 if ( // [HGM] holdings: blank out area between board and holdings
4775 column == BOARD_LEFT-1 || column == BOARD_RGHT
4776 || (column == BOARD_LEFT-2 && row < BOARD_HEIGHT-gameInfo.holdingsSize)
4777 || (column == BOARD_RGHT+1 && row >= gameInfo.holdingsSize) ) {
4778 BlankSquare(x, y, 2, EmptySquare, xBoardWindow);
4780 // [HGM] print piece counts next to holdings
4781 string[1] = NULLCHAR;
4782 if (column == (flipView ? BOARD_LEFT-1 : BOARD_RGHT) && piece > 1 ) {
4783 string[0] = '0' + piece;
4784 XTextExtents(countFontStruct, string, 1, &direction,
4785 &font_ascent, &font_descent, &overall);
4786 if (appData.monoMode) {
4787 XDrawImageString(xDisplay, xBoardWindow, countGC,
4788 x + squareSize - overall.width - 2,
4789 y + font_ascent + 1, string, 1);
4791 XDrawString(xDisplay, xBoardWindow, countGC,
4792 x + squareSize - overall.width - 2,
4793 y + font_ascent + 1, string, 1);
4796 if (column == (flipView ? BOARD_RGHT : BOARD_LEFT-1) && piece > 1) {
4797 string[0] = '0' + piece;
4798 XTextExtents(countFontStruct, string, 1, &direction,
4799 &font_ascent, &font_descent, &overall);
4800 if (appData.monoMode) {
4801 XDrawImageString(xDisplay, xBoardWindow, countGC,
4802 x + 2, y + font_ascent + 1, string, 1);
4804 XDrawString(xDisplay, xBoardWindow, countGC,
4805 x + 2, y + font_ascent + 1, string, 1);
4809 if (piece == EmptySquare || appData.blindfold) {
4810 BlankSquare(x, y, square_color, piece, xBoardWindow);
4812 drawfunc = ChooseDrawFunc();
4813 if (do_flash && appData.flashCount > 0) {
4814 for (i=0; i<appData.flashCount; ++i) {
4816 drawfunc(piece, square_color, x, y, xBoardWindow);
4817 XSync(xDisplay, False);
4818 do_flash_delay(flash_delay);
4820 BlankSquare(x, y, square_color, piece, xBoardWindow);
4821 XSync(xDisplay, False);
4822 do_flash_delay(flash_delay);
4825 drawfunc(piece, square_color, x, y, xBoardWindow);
4829 string[1] = NULLCHAR;
4830 if (appData.showCoords && row == (flipView ? BOARD_HEIGHT-1 : 0)
4831 && column >= BOARD_LEFT && column < BOARD_RGHT) {
4832 string[0] = 'a' + column - BOARD_LEFT;
4833 XTextExtents(coordFontStruct, string, 1, &direction,
4834 &font_ascent, &font_descent, &overall);
4835 if (appData.monoMode) {
4836 XDrawImageString(xDisplay, xBoardWindow, coordGC,
4837 x + squareSize - overall.width - 2,
4838 y + squareSize - font_descent - 1, string, 1);
4840 XDrawString(xDisplay, xBoardWindow, coordGC,
4841 x + squareSize - overall.width - 2,
4842 y + squareSize - font_descent - 1, string, 1);
4845 if (appData.showCoords && column == (flipView ? BOARD_RGHT-1 : BOARD_LEFT)) {
4846 string[0] = ONE + row;
4847 XTextExtents(coordFontStruct, string, 1, &direction,
4848 &font_ascent, &font_descent, &overall);
4849 if (appData.monoMode) {
4850 XDrawImageString(xDisplay, xBoardWindow, coordGC,
4851 x + 2, y + font_ascent + 1, string, 1);
4853 XDrawString(xDisplay, xBoardWindow, coordGC,
4854 x + 2, y + font_ascent + 1, string, 1);
4860 /* Why is this needed on some versions of X? */
4861 void EventProc(widget, unused, event)
4866 if (!XtIsRealized(widget))
4869 switch (event->type) {
4871 if (event->xexpose.count > 0) return; /* no clipping is done */
4872 XDrawPosition(widget, True, NULL);
4880 void DrawPosition(fullRedraw, board)
4881 /*Boolean*/int fullRedraw;
4884 XDrawPosition(boardWidget, fullRedraw, board);
4887 /* Returns 1 if there are "too many" differences between b1 and b2
4888 (i.e. more than 1 move was made) */
4889 static int too_many_diffs(b1, b2)
4895 for (i=0; i<BOARD_HEIGHT; ++i) {
4896 for (j=0; j<BOARD_WIDTH; ++j) {
4897 if (b1[i][j] != b2[i][j]) {
4898 if (++c > 4) /* Castling causes 4 diffs */
4907 /* Matrix describing castling maneuvers */
4908 /* Row, ColRookFrom, ColKingFrom, ColRookTo, ColKingTo */
4909 static int castling_matrix[4][5] = {
4910 { 0, 0, 4, 3, 2 }, /* 0-0-0, white */
4911 { 0, 7, 4, 5, 6 }, /* 0-0, white */
4912 { 7, 0, 4, 3, 2 }, /* 0-0-0, black */
4913 { 7, 7, 4, 5, 6 } /* 0-0, black */
4916 /* Checks whether castling occurred. If it did, *rrow and *rcol
4917 are set to the destination (row,col) of the rook that moved.
4919 Returns 1 if castling occurred, 0 if not.
4921 Note: Only handles a max of 1 castling move, so be sure
4922 to call too_many_diffs() first.
4924 static int check_castle_draw(newb, oldb, rrow, rcol)
4931 /* For each type of castling... */
4932 for (i=0; i<4; ++i) {
4933 r = castling_matrix[i];
4935 /* Check the 4 squares involved in the castling move */
4937 for (j=1; j<=4; ++j) {
4938 if (newb[r[0]][r[j]] == oldb[r[0]][r[j]]) {
4945 /* All 4 changed, so it must be a castling move */
4954 static int damage[BOARD_SIZE][BOARD_SIZE];
4957 * event handler for redrawing the board
4959 void XDrawPosition(w, repaint, board)
4961 /*Boolean*/int repaint;
4965 static int lastFlipView = 0;
4966 static int lastBoardValid = 0;
4967 static Board lastBoard;
4971 if (board == NULL) {
4972 if (!lastBoardValid) return;
4975 if (!lastBoardValid || lastFlipView != flipView) {
4976 XtSetArg(args[0], XtNleftBitmap, (flipView ? xMarkPixmap : None));
4977 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flip View"),
4982 * It would be simpler to clear the window with XClearWindow()
4983 * but this causes a very distracting flicker.
4986 if (!repaint && lastBoardValid && lastFlipView == flipView) {
4988 /* If too much changes (begin observing new game, etc.), don't
4990 do_flash = too_many_diffs(board, lastBoard) ? 0 : 1;
4992 /* Special check for castling so we don't flash both the king
4993 and the rook (just flash the king). */
4995 if (check_castle_draw(board, lastBoard, &rrow, &rcol)) {
4996 /* Draw rook with NO flashing. King will be drawn flashing later */
4997 DrawSquare(rrow, rcol, board[rrow][rcol], 0);
4998 lastBoard[rrow][rcol] = board[rrow][rcol];
5002 /* First pass -- Draw (newly) empty squares and repair damage.
5003 This prevents you from having a piece show up twice while it
5004 is flashing on its new square */
5005 for (i = 0; i < BOARD_HEIGHT; i++)
5006 for (j = 0; j < BOARD_WIDTH; j++)
5007 if ((board[i][j] != lastBoard[i][j] && board[i][j] == EmptySquare)
5009 DrawSquare(i, j, board[i][j], 0);
5010 damage[i][j] = False;
5013 /* Second pass -- Draw piece(s) in new position and flash them */
5014 for (i = 0; i < BOARD_HEIGHT; i++)
5015 for (j = 0; j < BOARD_WIDTH; j++)
5016 if (board[i][j] != lastBoard[i][j]) {
5017 DrawSquare(i, j, board[i][j], do_flash);
5021 XDrawSegments(xDisplay, xBoardWindow, lineGC,
5022 gridSegments, BOARD_HEIGHT + BOARD_WIDTH + 2);
5024 for (i = 0; i < BOARD_HEIGHT; i++)
5025 for (j = 0; j < BOARD_WIDTH; j++) {
5026 DrawSquare(i, j, board[i][j], 0);
5027 damage[i][j] = False;
5031 CopyBoard(lastBoard, board);
5033 lastFlipView = flipView;
5035 /* Draw highlights */
5036 if (pm1X >= 0 && pm1Y >= 0) {
5037 drawHighlight(pm1X, pm1Y, prelineGC);
5039 if (pm2X >= 0 && pm2Y >= 0) {
5040 drawHighlight(pm2X, pm2Y, prelineGC);
5042 if (hi1X >= 0 && hi1Y >= 0) {
5043 drawHighlight(hi1X, hi1Y, highlineGC);
5045 if (hi2X >= 0 && hi2Y >= 0) {
5046 drawHighlight(hi2X, hi2Y, highlineGC);
5049 /* If piece being dragged around board, must redraw that too */
5052 XSync(xDisplay, False);
5057 * event handler for redrawing the board
5059 void DrawPositionProc(w, event, prms, nprms)
5065 XDrawPosition(w, True, NULL);
5070 * event handler for parsing user moves
5072 // [HGM] This routine will need quite some reworking. Although the backend still supports the old
5073 // way of doing things, by calling UserMoveEvent() to test the legality of the move and then perform
5074 // it at the end, and doing all kind of preliminary tests here (e.g. to weed out self-captures), it
5075 // should be made to use the new way, of calling UserMoveTest early to determine the legality of the
5076 // move, (which will weed out the illegal selfcaptures and moves into the holdings, and flag promotions),
5077 // and at the end FinishMove() to perform the move after optional promotion popups.
5078 // For now I patched it to allow self-capture with King, and suppress clicks between board and holdings.
5079 void HandleUserMove(w, event, prms, nprms)
5086 Boolean saveAnimate;
5087 static int second = 0;
5089 if (w != boardWidget || errorExitStatus != -1) return;
5091 if (event->type == ButtonPress) ErrorPopDown();
5094 if (event->type == ButtonPress) {
5095 XtPopdown(promotionShell);
5096 XtDestroyWidget(promotionShell);
5097 promotionUp = False;
5105 x = EventToSquare(event->xbutton.x, BOARD_WIDTH);
5106 y = EventToSquare(event->xbutton.y, BOARD_HEIGHT);
5107 if (!flipView && y >= 0) {
5108 y = BOARD_HEIGHT - 1 - y;
5110 if (flipView && x >= 0) {
5111 x = BOARD_WIDTH - 1 - x;
5114 /* [HGM] holdings: next 5 lines: ignore all clicks between board and holdings */
5115 if(event->type == ButtonPress
5116 && ( x == BOARD_LEFT-1 || x == BOARD_RGHT
5117 || x == BOARD_LEFT-2 && y < BOARD_HEIGHT-gameInfo.holdingsSize
5118 || x == BOARD_RGHT+1 && y >= gameInfo.holdingsSize) )
5122 if (event->type == ButtonPress) {
5124 if (OKToStartUserMove(x, y)) {
5128 DragPieceBegin(event->xbutton.x, event->xbutton.y);
5129 if (appData.highlightDragging) {
5130 SetHighlights(x, y, -1, -1);
5138 if (event->type == ButtonPress && gameMode != EditPosition &&
5143 /* Check if clicking again on the same color piece */
5144 fromP = boards[currentMove][fromY][fromX];
5145 toP = boards[currentMove][y][x];
5146 if ((WhitePawn <= fromP && fromP < WhiteKing && // [HGM] this test should go, as UserMoveTest now does it.
5147 WhitePawn <= toP && toP <= WhiteKing) || // For now I made it less critical by exempting King
5148 (BlackPawn <= fromP && fromP < BlackKing && // moves, to not interfere with FRC castlings.
5149 BlackPawn <= toP && toP <= BlackKing)) {
5150 /* Clicked again on same color piece -- changed his mind */
5151 second = (x == fromX && y == fromY);
5152 if (appData.highlightDragging) {
5153 SetHighlights(x, y, -1, -1);
5157 if (OKToStartUserMove(x, y)) {
5160 DragPieceBegin(event->xbutton.x, event->xbutton.y);
5166 if (event->type == ButtonRelease && x == fromX && y == fromY) {
5167 DragPieceEnd(event->xbutton.x, event->xbutton.y);
5168 if (appData.animateDragging) {
5169 /* Undo animation damage if any */
5170 DrawPosition(FALSE, NULL);
5173 /* Second up/down in same square; just abort move */
5178 ClearPremoveHighlights();
5180 /* First upclick in same square; start click-click mode */
5181 SetHighlights(x, y, -1, -1);
5186 /* Completed move */
5189 saveAnimate = appData.animate;
5190 if (event->type == ButtonPress) {
5191 /* Finish clickclick move */
5192 if (appData.animate || appData.highlightLastMove) {
5193 SetHighlights(fromX, fromY, toX, toY);
5198 /* Finish drag move */
5199 if (appData.highlightLastMove) {
5200 SetHighlights(fromX, fromY, toX, toY);
5204 DragPieceEnd(event->xbutton.x, event->xbutton.y);
5205 /* Don't animate move and drag both */
5206 appData.animate = FALSE;
5208 if (IsPromotion(fromX, fromY, toX, toY)) {
5209 if (appData.alwaysPromoteToQueen) {
5210 UserMoveEvent(fromX, fromY, toX, toY, 'q');
5211 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
5212 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
5215 SetHighlights(fromX, fromY, toX, toY);
5219 UserMoveEvent(fromX, fromY, toX, toY, NULLCHAR);
5220 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
5221 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
5224 appData.animate = saveAnimate;
5225 if (appData.animate || appData.animateDragging) {
5226 /* Undo animation damage if needed */
5227 DrawPosition(FALSE, NULL);
5231 void AnimateUserMove (Widget w, XEvent * event,
5232 String * params, Cardinal * nParams)
5234 DragPieceMove(event->xmotion.x, event->xmotion.y);
5237 Widget CommentCreate(name, text, mutable, callback, lines)
5239 int /*Boolean*/ mutable;
5240 XtCallbackProc callback;
5244 Widget shell, layout, form, edit, b_ok, b_cancel, b_clear, b_close, b_edit;
5249 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5250 XtGetValues(boardWidget, args, j);
5253 XtSetArg(args[j], XtNresizable, True); j++;
5256 XtCreatePopupShell(name, topLevelShellWidgetClass,
5257 shellWidget, args, j);
5260 XtCreatePopupShell(name, transientShellWidgetClass,
5261 shellWidget, args, j);
5264 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
5265 layoutArgs, XtNumber(layoutArgs));
5267 XtCreateManagedWidget("form", formWidgetClass, layout,
5268 formArgs, XtNumber(formArgs));
5272 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
5273 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
5275 XtSetArg(args[j], XtNstring, text); j++;
5276 XtSetArg(args[j], XtNtop, XtChainTop); j++;
5277 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5278 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5279 XtSetArg(args[j], XtNright, XtChainRight); j++;
5280 XtSetArg(args[j], XtNresizable, True); j++;
5281 XtSetArg(args[j], XtNwidth, bw_width); j++; /*force wider than buttons*/
5283 XtSetArg(args[j], XtNscrollVertical, XawtextScrollWhenNeeded); j++;
5285 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
5286 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
5288 XtSetArg(args[j], XtNautoFill, True); j++;
5289 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
5291 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
5295 XtSetArg(args[j], XtNfromVert, edit); j++;
5296 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5297 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5298 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5299 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5301 XtCreateManagedWidget(_("ok"), commandWidgetClass, form, args, j);
5302 XtAddCallback(b_ok, XtNcallback, callback, (XtPointer) 0);
5305 XtSetArg(args[j], XtNfromVert, edit); j++;
5306 XtSetArg(args[j], XtNfromHoriz, b_ok); j++;
5307 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5308 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5309 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5310 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5312 XtCreateManagedWidget(_("cancel"), commandWidgetClass, form, args, j);
5313 XtAddCallback(b_cancel, XtNcallback, callback, (XtPointer) 0);
5316 XtSetArg(args[j], XtNfromVert, edit); j++;
5317 XtSetArg(args[j], XtNfromHoriz, b_cancel); j++;
5318 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5319 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5320 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5321 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5323 XtCreateManagedWidget(_("clear"), commandWidgetClass, form, args, j);
5324 XtAddCallback(b_clear, XtNcallback, callback, (XtPointer) 0);
5327 XtSetArg(args[j], XtNfromVert, edit); j++;
5328 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5329 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5330 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5331 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5333 XtCreateManagedWidget(_("close"), commandWidgetClass, form, args, j);
5334 XtAddCallback(b_close, XtNcallback, callback, (XtPointer) 0);
5337 XtSetArg(args[j], XtNfromVert, edit); j++;
5338 XtSetArg(args[j], XtNfromHoriz, b_close); j++;
5339 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5340 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5341 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5342 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5344 XtCreateManagedWidget(_("edit"), commandWidgetClass, form, args, j);
5345 XtAddCallback(b_edit, XtNcallback, callback, (XtPointer) 0);
5348 XtRealizeWidget(shell);
5350 if (commentX == -1) {
5353 Dimension pw_height;
5354 Dimension ew_height;
5357 XtSetArg(args[j], XtNheight, &ew_height); j++;
5358 XtGetValues(edit, args, j);
5361 XtSetArg(args[j], XtNheight, &pw_height); j++;
5362 XtGetValues(shell, args, j);
5363 commentH = pw_height + (lines - 1) * ew_height;
5364 commentW = bw_width - 16;
5366 XSync(xDisplay, False);
5368 /* This code seems to tickle an X bug if it is executed too soon
5369 after xboard starts up. The coordinates get transformed as if
5370 the main window was positioned at (0, 0).
5372 XtTranslateCoords(shellWidget,
5373 (bw_width - commentW) / 2, 0 - commentH / 2,
5374 &commentX, &commentY);
5376 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
5377 RootWindowOfScreen(XtScreen(shellWidget)),
5378 (bw_width - commentW) / 2, 0 - commentH / 2,
5383 if (commentY < 0) commentY = 0; /*avoid positioning top offscreen*/
5386 XtSetArg(args[j], XtNheight, commentH); j++;
5387 XtSetArg(args[j], XtNwidth, commentW); j++;
5388 XtSetArg(args[j], XtNx, commentX); j++;
5389 XtSetArg(args[j], XtNy, commentY); j++;
5390 XtSetValues(shell, args, j);
5391 XtSetKeyboardFocus(shell, edit);
5396 /* Used for analysis window and ICS input window */
5397 Widget MiscCreate(name, text, mutable, callback, lines)
5399 int /*Boolean*/ mutable;
5400 XtCallbackProc callback;
5404 Widget shell, layout, form, edit;
5406 Dimension bw_width, pw_height, ew_height, w, h;
5412 XtSetArg(args[j], XtNresizable, True); j++;
5415 XtCreatePopupShell(name, topLevelShellWidgetClass,
5416 shellWidget, args, j);
5419 XtCreatePopupShell(name, transientShellWidgetClass,
5420 shellWidget, args, j);
5423 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
5424 layoutArgs, XtNumber(layoutArgs));
5426 XtCreateManagedWidget("form", formWidgetClass, layout,
5427 formArgs, XtNumber(formArgs));
5431 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
5432 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
5434 XtSetArg(args[j], XtNstring, text); j++;
5435 XtSetArg(args[j], XtNtop, XtChainTop); j++;
5436 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5437 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5438 XtSetArg(args[j], XtNright, XtChainRight); j++;
5439 XtSetArg(args[j], XtNresizable, True); j++;
5441 XtSetArg(args[j], XtNscrollVertical, XawtextScrollWhenNeeded); j++;
5443 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
5444 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
5446 XtSetArg(args[j], XtNautoFill, True); j++;
5447 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
5449 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
5451 XtRealizeWidget(shell);
5454 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5455 XtGetValues(boardWidget, args, j);
5458 XtSetArg(args[j], XtNheight, &ew_height); j++;
5459 XtGetValues(edit, args, j);
5462 XtSetArg(args[j], XtNheight, &pw_height); j++;
5463 XtGetValues(shell, args, j);
5464 h = pw_height + (lines - 1) * ew_height;
5467 XSync(xDisplay, False);
5469 /* This code seems to tickle an X bug if it is executed too soon
5470 after xboard starts up. The coordinates get transformed as if
5471 the main window was positioned at (0, 0).
5473 XtTranslateCoords(shellWidget, (bw_width - w) / 2, 0 - h / 2, &x, &y);
5475 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
5476 RootWindowOfScreen(XtScreen(shellWidget)),
5477 (bw_width - w) / 2, 0 - h / 2, &xx, &yy, &junk);
5481 if (y < 0) y = 0; /*avoid positioning top offscreen*/
5484 XtSetArg(args[j], XtNheight, h); j++;
5485 XtSetArg(args[j], XtNwidth, w); j++;
5486 XtSetArg(args[j], XtNx, x); j++;
5487 XtSetArg(args[j], XtNy, y); j++;
5488 XtSetValues(shell, args, j);
5494 static int savedIndex; /* gross that this is global */
5496 void EditCommentPopUp(index, title, text)
5505 if (text == NULL) text = "";
5507 if (editShell == NULL) {
5509 CommentCreate(title, text, True, EditCommentCallback, 4);
5510 XtRealizeWidget(editShell);
5511 CatchDeleteWindow(editShell, "EditCommentPopDown");
5513 edit = XtNameToWidget(editShell, "*form.text");
5515 XtSetArg(args[j], XtNstring, text); j++;
5516 XtSetValues(edit, args, j);
5518 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5519 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5520 XtSetValues(editShell, args, j);
5523 XtPopup(editShell, XtGrabNone);
5527 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
5528 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
5532 void EditCommentCallback(w, client_data, call_data)
5534 XtPointer client_data, call_data;
5542 XtSetArg(args[j], XtNlabel, &name); j++;
5543 XtGetValues(w, args, j);
5545 if (strcmp(name, _("ok")) == 0) {
5546 edit = XtNameToWidget(editShell, "*form.text");
5548 XtSetArg(args[j], XtNstring, &val); j++;
5549 XtGetValues(edit, args, j);
5550 ReplaceComment(savedIndex, val);
5551 EditCommentPopDown();
5552 } else if (strcmp(name, _("cancel")) == 0) {
5553 EditCommentPopDown();
5554 } else if (strcmp(name, _("clear")) == 0) {
5555 edit = XtNameToWidget(editShell, "*form.text");
5556 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
5557 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
5561 void EditCommentPopDown()
5566 if (!editUp) return;
5568 XtSetArg(args[j], XtNx, &commentX); j++;
5569 XtSetArg(args[j], XtNy, &commentY); j++;
5570 XtSetArg(args[j], XtNheight, &commentH); j++;
5571 XtSetArg(args[j], XtNwidth, &commentW); j++;
5572 XtGetValues(editShell, args, j);
5573 XtPopdown(editShell);
5576 XtSetArg(args[j], XtNleftBitmap, None); j++;
5577 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
5581 void ICSInputBoxPopUp()
5586 char *title = _("ICS Input");
5589 if (ICSInputShell == NULL) {
5590 ICSInputShell = MiscCreate(title, "", True, NULL, 1);
5591 tr = XtParseTranslationTable(ICSInputTranslations);
5592 edit = XtNameToWidget(ICSInputShell, "*form.text");
5593 XtOverrideTranslations(edit, tr);
5594 XtRealizeWidget(ICSInputShell);
5595 CatchDeleteWindow(ICSInputShell, "ICSInputBoxPopDown");
5598 edit = XtNameToWidget(ICSInputShell, "*form.text");
5600 XtSetArg(args[j], XtNstring, ""); j++;
5601 XtSetValues(edit, args, j);
5603 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5604 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5605 XtSetValues(ICSInputShell, args, j);
5608 XtPopup(ICSInputShell, XtGrabNone);
5609 XtSetKeyboardFocus(ICSInputShell, edit);
5611 ICSInputBoxUp = True;
5613 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
5614 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
5618 void ICSInputSendText()
5625 edit = XtNameToWidget(ICSInputShell, "*form.text");
5627 XtSetArg(args[j], XtNstring, &val); j++;
5628 XtGetValues(edit, args, j);
5629 SendMultiLineToICS(val);
5630 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
5631 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
5634 void ICSInputBoxPopDown()
5639 if (!ICSInputBoxUp) return;
5641 XtPopdown(ICSInputShell);
5642 ICSInputBoxUp = False;
5644 XtSetArg(args[j], XtNleftBitmap, None); j++;
5645 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
5649 void CommentPopUp(title, text)
5656 if (commentShell == NULL) {
5658 CommentCreate(title, text, False, CommentCallback, 4);
5659 XtRealizeWidget(commentShell);
5660 CatchDeleteWindow(commentShell, "CommentPopDown");
5662 edit = XtNameToWidget(commentShell, "*form.text");
5664 XtSetArg(args[j], XtNstring, text); j++;
5665 XtSetValues(edit, args, j);
5667 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5668 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5669 XtSetValues(commentShell, args, j);
5672 XtPopup(commentShell, XtGrabNone);
5673 XSync(xDisplay, False);
5678 void AnalysisPopUp(title, text)
5685 if (analysisShell == NULL) {
5686 analysisShell = MiscCreate(title, text, False, NULL, 4);
5687 XtRealizeWidget(analysisShell);
5688 CatchDeleteWindow(analysisShell, "AnalysisPopDown");
5691 edit = XtNameToWidget(analysisShell, "*form.text");
5693 XtSetArg(args[j], XtNstring, text); j++;
5694 XtSetValues(edit, args, j);
5696 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5697 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5698 XtSetValues(analysisShell, args, j);
5702 XtPopup(analysisShell, XtGrabNone);
5704 XSync(xDisplay, False);
5709 void CommentCallback(w, client_data, call_data)
5711 XtPointer client_data, call_data;
5718 XtSetArg(args[j], XtNlabel, &name); j++;
5719 XtGetValues(w, args, j);
5721 if (strcmp(name, _("close")) == 0) {
5723 } else if (strcmp(name, _("edit")) == 0) {
5730 void CommentPopDown()
5735 if (!commentUp) return;
5737 XtSetArg(args[j], XtNx, &commentX); j++;
5738 XtSetArg(args[j], XtNy, &commentY); j++;
5739 XtSetArg(args[j], XtNwidth, &commentW); j++;
5740 XtSetArg(args[j], XtNheight, &commentH); j++;
5741 XtGetValues(commentShell, args, j);
5742 XtPopdown(commentShell);
5743 XSync(xDisplay, False);
5747 void AnalysisPopDown()
5749 if (!analysisUp) return;
5750 XtPopdown(analysisShell);
5751 XSync(xDisplay, False);
5753 if (appData.icsEngineAnalyze) ExitAnalyzeMode(); /* [DM] icsEngineAnalyze */
5757 void FileNamePopUp(label, def, proc, openMode)
5764 Widget popup, layout, dialog, edit;
5770 fileProc = proc; /* I can't see a way not */
5771 fileOpenMode = openMode; /* to use globals here */
5774 XtSetArg(args[i], XtNresizable, True); i++;
5775 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
5776 XtSetArg(args[i], XtNtitle, XtNewString(_("File name prompt"))); i++;
5777 fileNameShell = popup =
5778 XtCreatePopupShell("File name prompt", transientShellWidgetClass,
5779 shellWidget, args, i);
5782 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
5783 layoutArgs, XtNumber(layoutArgs));
5786 XtSetArg(args[i], XtNlabel, label); i++;
5787 XtSetArg(args[i], XtNvalue, def); i++;
5788 XtSetArg(args[i], XtNborderWidth, 0); i++;
5789 dialog = XtCreateManagedWidget("fileName", dialogWidgetClass,
5792 XawDialogAddButton(dialog, _("ok"), FileNameCallback, (XtPointer) dialog);
5793 XawDialogAddButton(dialog, _("cancel"), FileNameCallback,
5794 (XtPointer) dialog);
5796 XtRealizeWidget(popup);
5797 CatchDeleteWindow(popup, "FileNamePopDown");
5799 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
5800 &x, &y, &win_x, &win_y, &mask);
5802 XtSetArg(args[0], XtNx, x - 10);
5803 XtSetArg(args[1], XtNy, y - 30);
5804 XtSetValues(popup, args, 2);
5806 XtPopup(popup, XtGrabExclusive);
5809 edit = XtNameToWidget(dialog, "*value");
5810 XtSetKeyboardFocus(popup, edit);
5813 void FileNamePopDown()
5815 if (!filenameUp) return;
5816 XtPopdown(fileNameShell);
5817 XtDestroyWidget(fileNameShell);
5822 void FileNameCallback(w, client_data, call_data)
5824 XtPointer client_data, call_data;
5829 XtSetArg(args[0], XtNlabel, &name);
5830 XtGetValues(w, args, 1);
5832 if (strcmp(name, _("cancel")) == 0) {
5837 FileNameAction(w, NULL, NULL, NULL);
5840 void FileNameAction(w, event, prms, nprms)
5852 name = XawDialogGetValueString(w = XtParent(w));
5854 if ((name != NULL) && (*name != NULLCHAR)) {
5856 XtPopdown(w = XtParent(XtParent(w)));
5860 p = strrchr(buf, ' ');
5867 fullname = ExpandPathName(buf);
5869 ErrorPopUp(_("Error"), _("Can't open file"), FALSE);
5872 f = fopen(fullname, fileOpenMode);
5874 DisplayError(_("Failed to open file"), errno);
5876 (void) (*fileProc)(f, index, buf);
5883 XtPopdown(w = XtParent(XtParent(w)));
5889 void PromotionPopUp()
5892 Widget dialog, layout;
5894 Dimension bw_width, pw_width;
5898 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5899 XtGetValues(boardWidget, args, j);
5902 XtSetArg(args[j], XtNresizable, True); j++;
5903 XtSetArg(args[j], XtNtitle, XtNewString(_("Promotion"))); j++;
5905 XtCreatePopupShell("Promotion", transientShellWidgetClass,
5906 shellWidget, args, j);
5908 XtCreateManagedWidget(layoutName, formWidgetClass, promotionShell,
5909 layoutArgs, XtNumber(layoutArgs));
5912 XtSetArg(args[j], XtNlabel, _("Promote to what?")); j++;
5913 XtSetArg(args[j], XtNborderWidth, 0); j++;
5914 dialog = XtCreateManagedWidget("promotion", dialogWidgetClass,
5917 if(gameInfo.variant != VariantShogi) {
5918 XawDialogAddButton(dialog, _("Queen"), PromotionCallback,
5919 (XtPointer) dialog);
5920 XawDialogAddButton(dialog, _("Rook"), PromotionCallback,
5921 (XtPointer) dialog);
5922 XawDialogAddButton(dialog, _("Bishop"), PromotionCallback,
5923 (XtPointer) dialog);
5924 XawDialogAddButton(dialog, _("Knight"), PromotionCallback,
5925 (XtPointer) dialog);
5926 if (!appData.testLegality || gameInfo.variant == VariantSuicide ||
5927 gameInfo.variant == VariantGiveaway) {
5928 XawDialogAddButton(dialog, _("King"), PromotionCallback,
5929 (XtPointer) dialog);
5931 if(gameInfo.variant == VariantCapablanca ||
5932 gameInfo.variant == VariantGothic ||
5933 gameInfo.variant == VariantCapaRandom) {
5934 XawDialogAddButton(dialog, _("Archbishop"), PromotionCallback,
5935 (XtPointer) dialog);
5936 XawDialogAddButton(dialog, _("Chancellor"), PromotionCallback,
5937 (XtPointer) dialog);
5939 } else // [HGM] shogi
5941 XawDialogAddButton(dialog, _("Promote"), PromotionCallback,
5942 (XtPointer) dialog);
5943 XawDialogAddButton(dialog, _("Defer"), PromotionCallback,
5944 (XtPointer) dialog);
5946 XawDialogAddButton(dialog, _("cancel"), PromotionCallback,
5947 (XtPointer) dialog);
5949 XtRealizeWidget(promotionShell);
5950 CatchDeleteWindow(promotionShell, "PromotionPopDown");
5953 XtSetArg(args[j], XtNwidth, &pw_width); j++;
5954 XtGetValues(promotionShell, args, j);
5956 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
5957 lineGap + squareSize/3 +
5958 ((toY == BOARD_HEIGHT-1) ^ (flipView) ?
5959 0 : 6*(squareSize + lineGap)), &x, &y);
5962 XtSetArg(args[j], XtNx, x); j++;
5963 XtSetArg(args[j], XtNy, y); j++;
5964 XtSetValues(promotionShell, args, j);
5966 XtPopup(promotionShell, XtGrabNone);
5971 void PromotionPopDown()
5973 if (!promotionUp) return;
5974 XtPopdown(promotionShell);
5975 XtDestroyWidget(promotionShell);
5976 promotionUp = False;
5979 void PromotionCallback(w, client_data, call_data)
5981 XtPointer client_data, call_data;
5987 XtSetArg(args[0], XtNlabel, &name);
5988 XtGetValues(w, args, 1);
5992 if (fromX == -1) return;
5994 if (strcmp(name, _("cancel")) == 0) {
5998 } else if (strcmp(name, _("Knight")) == 0) {
6000 } else if (strcmp(name, _("Promote")) == 0) {
6002 } else if (strcmp(name, _("Defer")) == 0) {
6005 promoChar = ToLower(name[0]);
6008 UserMoveEvent(fromX, fromY, toX, toY, promoChar);
6010 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
6011 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
6016 void ErrorCallback(w, client_data, call_data)
6018 XtPointer client_data, call_data;
6021 XtPopdown(w = XtParent(XtParent(XtParent(w))));
6023 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
6029 if (!errorUp) return;
6031 XtPopdown(errorShell);
6032 XtDestroyWidget(errorShell);
6033 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
6036 void ErrorPopUp(title, label, modal)
6037 char *title, *label;
6041 Widget dialog, layout;
6045 Dimension bw_width, pw_width;
6046 Dimension pw_height;
6050 XtSetArg(args[i], XtNresizable, True); i++;
6051 XtSetArg(args[i], XtNtitle, title); i++;
6053 XtCreatePopupShell("errorpopup", transientShellWidgetClass,
6054 shellWidget, args, i);
6056 XtCreateManagedWidget(layoutName, formWidgetClass, errorShell,
6057 layoutArgs, XtNumber(layoutArgs));
6060 XtSetArg(args[i], XtNlabel, label); i++;
6061 XtSetArg(args[i], XtNborderWidth, 0); i++;
6062 dialog = XtCreateManagedWidget("dialog", dialogWidgetClass,
6065 XawDialogAddButton(dialog, _("ok"), ErrorCallback, (XtPointer) dialog);
6067 XtRealizeWidget(errorShell);
6068 CatchDeleteWindow(errorShell, "ErrorPopDown");
6071 XtSetArg(args[i], XtNwidth, &bw_width); i++;
6072 XtGetValues(boardWidget, args, i);
6074 XtSetArg(args[i], XtNwidth, &pw_width); i++;
6075 XtSetArg(args[i], XtNheight, &pw_height); i++;
6076 XtGetValues(errorShell, args, i);
6079 /* This code seems to tickle an X bug if it is executed too soon
6080 after xboard starts up. The coordinates get transformed as if
6081 the main window was positioned at (0, 0).
6083 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
6084 0 - pw_height + squareSize / 3, &x, &y);
6086 XTranslateCoordinates(xDisplay, XtWindow(boardWidget),
6087 RootWindowOfScreen(XtScreen(boardWidget)),
6088 (bw_width - pw_width) / 2,
6089 0 - pw_height + squareSize / 3, &xx, &yy, &junk);
6093 if (y < 0) y = 0; /*avoid positioning top offscreen*/
6096 XtSetArg(args[i], XtNx, x); i++;
6097 XtSetArg(args[i], XtNy, y); i++;
6098 XtSetValues(errorShell, args, i);
6101 XtPopup(errorShell, modal ? XtGrabExclusive : XtGrabNone);
6104 /* Disable all user input other than deleting the window */
6105 static int frozen = 0;
6109 /* Grab by a widget that doesn't accept input */
6110 XtAddGrab(messageWidget, TRUE, FALSE);
6114 /* Undo a FreezeUI */
6117 if (!frozen) return;
6118 XtRemoveGrab(messageWidget);
6122 char *ModeToWidgetName(mode)
6126 case BeginningOfGame:
6127 if (appData.icsActive)
6128 return "menuMode.ICS Client";
6129 else if (appData.noChessProgram ||
6130 *appData.cmailGameName != NULLCHAR)
6131 return "menuMode.Edit Game";
6133 return "menuMode.Machine Black";
6134 case MachinePlaysBlack:
6135 return "menuMode.Machine Black";
6136 case MachinePlaysWhite:
6137 return "menuMode.Machine White";
6139 return "menuMode.Analysis Mode";
6141 return "menuMode.Analyze File";
6142 case TwoMachinesPlay:
6143 return "menuMode.Two Machines";
6145 return "menuMode.Edit Game";
6146 case PlayFromGameFile:
6147 return "menuFile.Load Game";
6149 return "menuMode.Edit Position";
6151 return "menuMode.Training";
6152 case IcsPlayingWhite:
6153 case IcsPlayingBlack:
6157 return "menuMode.ICS Client";
6164 void ModeHighlight()
6167 static int oldPausing = FALSE;
6168 static GameMode oldmode = (GameMode) -1;
6171 if (!boardWidget || !XtIsRealized(boardWidget)) return;
6173 if (pausing != oldPausing) {
6174 oldPausing = pausing;
6176 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6178 XtSetArg(args[0], XtNleftBitmap, None);
6180 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Pause"),
6183 if (appData.showButtonBar) {
6186 XtSetArg(args[0], XtNbackground, buttonForegroundPixel);
6187 XtSetArg(args[1], XtNforeground, buttonBackgroundPixel);
6189 XtSetArg(args[0], XtNbackground, buttonBackgroundPixel);
6190 XtSetArg(args[1], XtNforeground, buttonForegroundPixel);
6193 /* Always toggle, don't set. Previous code messes up when
6194 invoked while the button is pressed, as releasing it
6195 toggles the state again. */
6198 XtSetArg(args[0], XtNbackground, &oldbg);
6199 XtSetArg(args[1], XtNforeground, &oldfg);
6200 XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON),
6202 XtSetArg(args[0], XtNbackground, oldfg);
6203 XtSetArg(args[1], XtNforeground, oldbg);
6206 XtSetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
6210 wname = ModeToWidgetName(oldmode);
6211 if (wname != NULL) {
6212 XtSetArg(args[0], XtNleftBitmap, None);
6213 XtSetValues(XtNameToWidget(menuBarWidget, wname), args, 1);
6215 wname = ModeToWidgetName(gameMode);
6216 if (wname != NULL) {
6217 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6218 XtSetValues(XtNameToWidget(menuBarWidget, wname), args, 1);
6222 /* Maybe all the enables should be handled here, not just this one */
6223 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Training"),
6224 gameMode == Training || gameMode == PlayFromGameFile);
6229 * Button/menu procedures
6231 void ResetProc(w, event, prms, nprms)
6241 int LoadGamePopUp(f, gameNumber, title)
6246 cmailMsgLoaded = FALSE;
6247 if (gameNumber == 0) {
6248 int error = GameListBuild(f);
6250 DisplayError(_("Cannot build game list"), error);
6251 } else if (!ListEmpty(&gameList) &&
6252 ((ListGame *) gameList.tailPred)->number > 1) {
6253 GameListPopUp(f, title);
6259 return LoadGame(f, gameNumber, title, FALSE);
6262 void LoadGameProc(w, event, prms, nprms)
6268 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
6271 FileNamePopUp(_("Load game file name?"), "", LoadGamePopUp, "rb");
6274 void LoadNextGameProc(w, event, prms, nprms)
6283 void LoadPrevGameProc(w, event, prms, nprms)
6292 void ReloadGameProc(w, event, prms, nprms)
6301 void LoadNextPositionProc(w, event, prms, nprms)
6310 void LoadPrevPositionProc(w, event, prms, nprms)
6319 void ReloadPositionProc(w, event, prms, nprms)
6328 void LoadPositionProc(w, event, prms, nprms)
6334 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
6337 FileNamePopUp(_("Load position file name?"), "", LoadPosition, "rb");
6340 void SaveGameProc(w, event, prms, nprms)
6346 FileNamePopUp(_("Save game file name?"),
6347 DefaultFileName(appData.oldSaveStyle ? "game" : "pgn"),
6351 void SavePositionProc(w, event, prms, nprms)
6357 FileNamePopUp(_("Save position file name?"),
6358 DefaultFileName(appData.oldSaveStyle ? "pos" : "fen"),
6362 void ReloadCmailMsgProc(w, event, prms, nprms)
6368 ReloadCmailMsgEvent(FALSE);
6371 void MailMoveProc(w, event, prms, nprms)
6380 /* this variable is shared between CopyPositionProc and SendPositionSelection */
6381 static char *selected_fen_position=NULL;
6384 SendPositionSelection(Widget w, Atom *selection, Atom *target,
6385 Atom *type_return, XtPointer *value_return,
6386 unsigned long *length_return, int *format_return)
6388 char *selection_tmp;
6390 if (!selected_fen_position) return False; /* should never happen */
6391 if (*target == XA_STRING){
6392 /* note: since no XtSelectionDoneProc was registered, Xt will
6393 * automatically call XtFree on the value returned. So have to
6394 * make a copy of it allocated with XtMalloc */
6395 selection_tmp= XtMalloc(strlen(selected_fen_position)+16);
6396 strcpy(selection_tmp, selected_fen_position);
6398 *value_return=selection_tmp;
6399 *length_return=strlen(selection_tmp);
6400 *type_return=XA_STRING;
6401 *format_return = 8; /* bits per byte */
6408 /* note: when called from menu all parameters are NULL, so no clue what the
6409 * Widget which was clicked on was, or what the click event was
6411 void CopyPositionProc(w, event, prms, nprms)
6419 if (selected_fen_position) free(selected_fen_position);
6420 selected_fen_position = (char *)PositionToFEN(currentMove, NULL);
6421 if (!selected_fen_position) return;
6422 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
6424 SendPositionSelection,
6425 NULL/* lose_ownership_proc */ ,
6426 NULL/* transfer_done_proc */);
6428 free(selected_fen_position);
6429 selected_fen_position=NULL;
6433 /* function called when the data to Paste is ready */
6435 PastePositionCB(Widget w, XtPointer client_data, Atom *selection,
6436 Atom *type, XtPointer value, unsigned long *len, int *format)
6439 if (value==NULL || *len==0) return; /* nothing had been selected to copy */
6440 fenstr[*len]='\0'; /* normally this string is terminated, but be safe */
6441 EditPositionPasteFEN(fenstr);
6445 /* called when Paste Position button is pressed,
6446 * all parameters will be NULL */
6447 void PastePositionProc(w, event, prms, nprms)
6453 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
6454 /* (XtSelectionCallbackProc) */ PastePositionCB,
6455 NULL, /* client_data passed to PastePositionCB */
6457 /* better to use the time field from the event that triggered the
6458 * call to this function, but that isn't trivial to get
6466 SendGameSelection(Widget w, Atom *selection, Atom *target,
6467 Atom *type_return, XtPointer *value_return,
6468 unsigned long *length_return, int *format_return)
6470 char *selection_tmp;
6472 if (*target == XA_STRING){
6473 FILE* f = fopen(gameCopyFilename, "r");
6476 if (f == NULL) return False;
6480 selection_tmp = XtMalloc(len + 1);
6481 count = fread(selection_tmp, 1, len, f);
6483 XtFree(selection_tmp);
6486 selection_tmp[len] = NULLCHAR;
6487 *value_return = selection_tmp;
6488 *length_return = len;
6489 *type_return = XA_STRING;
6490 *format_return = 8; /* bits per byte */
6497 /* note: when called from menu all parameters are NULL, so no clue what the
6498 * Widget which was clicked on was, or what the click event was
6500 void CopyGameProc(w, event, prms, nprms)
6508 ret = SaveGameToFile(gameCopyFilename, FALSE);
6511 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
6514 NULL/* lose_ownership_proc */ ,
6515 NULL/* transfer_done_proc */);
6518 /* function called when the data to Paste is ready */
6520 PasteGameCB(Widget w, XtPointer client_data, Atom *selection,
6521 Atom *type, XtPointer value, unsigned long *len, int *format)
6524 if (value == NULL || *len == 0) {
6525 return; /* nothing had been selected to copy */
6527 f = fopen(gamePasteFilename, "w");
6529 DisplayError(_("Can't open temp file"), errno);
6532 fwrite(value, 1, *len, f);
6535 LoadGameFromFile(gamePasteFilename, 0, gamePasteFilename, TRUE);
6538 /* called when Paste Game button is pressed,
6539 * all parameters will be NULL */
6540 void PasteGameProc(w, event, prms, nprms)
6546 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
6547 /* (XtSelectionCallbackProc) */ PasteGameCB,
6548 NULL, /* client_data passed to PasteGameCB */
6550 /* better to use the time field from the event that triggered the
6551 * call to this function, but that isn't trivial to get
6561 SaveGameProc(NULL, NULL, NULL, NULL);
6565 void QuitProc(w, event, prms, nprms)
6574 void PauseProc(w, event, prms, nprms)
6584 void MachineBlackProc(w, event, prms, nprms)
6590 MachineBlackEvent();
6593 void MachineWhiteProc(w, event, prms, nprms)
6599 MachineWhiteEvent();
6602 void AnalyzeModeProc(w, event, prms, nprms)
6610 if (!first.analysisSupport) {
6611 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
6612 DisplayError(buf, 0);
6615 /* [DM] icsEngineAnalyze [HGM] This is horrible code; reverse the gameMode and isEngineAnalyze tests! */
6616 if (appData.icsActive) {
6617 if (gameMode != IcsObserving) {
6618 sprintf(buf,_("You are not observing a game"));
6619 DisplayError(buf, 0);
6621 if (appData.icsEngineAnalyze) {
6622 if (appData.debugMode)
6623 fprintf(debugFP, _("Found unexpected active ICS engine analyze \n"));
6629 /* if enable, use want disable icsEngineAnalyze */
6630 if (appData.icsEngineAnalyze) {
6635 appData.icsEngineAnalyze = TRUE;
6636 if (appData.debugMode)
6637 fprintf(debugFP, _("ICS engine analyze starting... \n"));
6639 if (!appData.showThinking)
6640 ShowThinkingProc(w,event,prms,nprms);
6645 void AnalyzeFileProc(w, event, prms, nprms)
6651 if (!first.analysisSupport) {
6653 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
6654 DisplayError(buf, 0);
6659 if (!appData.showThinking)
6660 ShowThinkingProc(w,event,prms,nprms);
6663 FileNamePopUp(_("File to analyze"), "", LoadGamePopUp, "rb");
6664 AnalysisPeriodicEvent(1);
6667 void TwoMachinesProc(w, event, prms, nprms)
6676 void IcsClientProc(w, event, prms, nprms)
6685 void EditGameProc(w, event, prms, nprms)
6694 void EditPositionProc(w, event, prms, nprms)
6700 EditPositionEvent();
6703 void TrainingProc(w, event, prms, nprms)
6712 void EditCommentProc(w, event, prms, nprms)
6719 EditCommentPopDown();
6725 void IcsInputBoxProc(w, event, prms, nprms)
6731 if (ICSInputBoxUp) {
6732 ICSInputBoxPopDown();
6738 void AcceptProc(w, event, prms, nprms)
6747 void DeclineProc(w, event, prms, nprms)
6756 void RematchProc(w, event, prms, nprms)
6765 void CallFlagProc(w, event, prms, nprms)
6774 void DrawProc(w, event, prms, nprms)
6783 void AbortProc(w, event, prms, nprms)
6792 void AdjournProc(w, event, prms, nprms)
6801 void ResignProc(w, event, prms, nprms)
6810 void AdjuWhiteProc(w, event, prms, nprms)
6816 UserAdjudicationEvent(+1);
6819 void AdjuBlackProc(w, event, prms, nprms)
6825 UserAdjudicationEvent(-1);
6828 void AdjuDrawProc(w, event, prms, nprms)
6834 UserAdjudicationEvent(0);
6837 void EnterKeyProc(w, event, prms, nprms)
6843 if (ICSInputBoxUp == True)
6847 void StopObservingProc(w, event, prms, nprms)
6853 StopObservingEvent();
6856 void StopExaminingProc(w, event, prms, nprms)
6862 StopExaminingEvent();
6866 void ForwardProc(w, event, prms, nprms)
6876 void BackwardProc(w, event, prms, nprms)
6885 void ToStartProc(w, event, prms, nprms)
6894 void ToEndProc(w, event, prms, nprms)
6903 void RevertProc(w, event, prms, nprms)
6912 void TruncateGameProc(w, event, prms, nprms)
6918 TruncateGameEvent();
6920 void RetractMoveProc(w, event, prms, nprms)
6929 void MoveNowProc(w, event, prms, nprms)
6939 void AlwaysQueenProc(w, event, prms, nprms)
6947 appData.alwaysPromoteToQueen = !appData.alwaysPromoteToQueen;
6949 if (appData.alwaysPromoteToQueen) {
6950 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6952 XtSetArg(args[0], XtNleftBitmap, None);
6954 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
6958 void AnimateDraggingProc(w, event, prms, nprms)
6966 appData.animateDragging = !appData.animateDragging;
6968 if (appData.animateDragging) {
6969 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6972 XtSetArg(args[0], XtNleftBitmap, None);
6974 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Dragging"),
6978 void AnimateMovingProc(w, event, prms, nprms)
6986 appData.animate = !appData.animate;
6988 if (appData.animate) {
6989 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6992 XtSetArg(args[0], XtNleftBitmap, None);
6994 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
6998 void AutocommProc(w, event, prms, nprms)
7006 appData.autoComment = !appData.autoComment;
7008 if (appData.autoComment) {
7009 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7011 XtSetArg(args[0], XtNleftBitmap, None);
7013 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
7018 void AutoflagProc(w, event, prms, nprms)
7026 appData.autoCallFlag = !appData.autoCallFlag;
7028 if (appData.autoCallFlag) {
7029 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7031 XtSetArg(args[0], XtNleftBitmap, None);
7033 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
7037 void AutoflipProc(w, event, prms, nprms)
7045 appData.autoFlipView = !appData.autoFlipView;
7047 if (appData.autoFlipView) {
7048 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7050 XtSetArg(args[0], XtNleftBitmap, None);
7052 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flip View"),
7056 void AutobsProc(w, event, prms, nprms)
7064 appData.autoObserve = !appData.autoObserve;
7066 if (appData.autoObserve) {
7067 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7069 XtSetArg(args[0], XtNleftBitmap, None);
7071 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
7075 void AutoraiseProc(w, event, prms, nprms)
7083 appData.autoRaiseBoard = !appData.autoRaiseBoard;
7085 if (appData.autoRaiseBoard) {
7086 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7088 XtSetArg(args[0], XtNleftBitmap, None);
7090 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Raise Board"),
7094 void AutosaveProc(w, event, prms, nprms)
7102 appData.autoSaveGames = !appData.autoSaveGames;
7104 if (appData.autoSaveGames) {
7105 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7107 XtSetArg(args[0], XtNleftBitmap, None);
7109 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
7113 void BlindfoldProc(w, event, prms, nprms)
7121 appData.blindfold = !appData.blindfold;
7123 if (appData.blindfold) {
7124 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7126 XtSetArg(args[0], XtNleftBitmap, None);
7128 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Blindfold"),
7131 DrawPosition(True, NULL);
7134 void TestLegalityProc(w, event, prms, nprms)
7142 appData.testLegality = !appData.testLegality;
7144 if (appData.testLegality) {
7145 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7147 XtSetArg(args[0], XtNleftBitmap, None);
7149 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Test Legality"),
7154 void FlashMovesProc(w, event, prms, nprms)
7162 if (appData.flashCount == 0) {
7163 appData.flashCount = 3;
7165 appData.flashCount = -appData.flashCount;
7168 if (appData.flashCount > 0) {
7169 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7171 XtSetArg(args[0], XtNleftBitmap, None);
7173 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flash Moves"),
7177 void FlipViewProc(w, event, prms, nprms)
7183 flipView = !flipView;
7184 DrawPosition(True, NULL);
7187 void GetMoveListProc(w, event, prms, nprms)
7195 appData.getMoveList = !appData.getMoveList;
7197 if (appData.getMoveList) {
7198 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7201 XtSetArg(args[0], XtNleftBitmap, None);
7203 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
7208 void HighlightDraggingProc(w, event, prms, nprms)
7216 appData.highlightDragging = !appData.highlightDragging;
7218 if (appData.highlightDragging) {
7219 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7221 XtSetArg(args[0], XtNleftBitmap, None);
7223 XtSetValues(XtNameToWidget(menuBarWidget,
7224 "menuOptions.Highlight Dragging"), args, 1);
7228 void HighlightLastMoveProc(w, event, prms, nprms)
7236 appData.highlightLastMove = !appData.highlightLastMove;
7238 if (appData.highlightLastMove) {
7239 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7241 XtSetArg(args[0], XtNleftBitmap, None);
7243 XtSetValues(XtNameToWidget(menuBarWidget,
7244 "menuOptions.Highlight Last Move"), args, 1);
7247 void IcsAlarmProc(w, event, prms, nprms)
7255 appData.icsAlarm = !appData.icsAlarm;
7257 if (appData.icsAlarm) {
7258 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7260 XtSetArg(args[0], XtNleftBitmap, None);
7262 XtSetValues(XtNameToWidget(menuBarWidget,
7263 "menuOptions.ICS Alarm"), args, 1);
7266 void MoveSoundProc(w, event, prms, nprms)
7274 appData.ringBellAfterMoves = !appData.ringBellAfterMoves;
7276 if (appData.ringBellAfterMoves) {
7277 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7279 XtSetArg(args[0], XtNleftBitmap, None);
7281 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
7286 void OldSaveStyleProc(w, event, prms, nprms)
7294 appData.oldSaveStyle = !appData.oldSaveStyle;
7296 if (appData.oldSaveStyle) {
7297 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7299 XtSetArg(args[0], XtNleftBitmap, None);
7301 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Old Save Style"),
7305 void PeriodicUpdatesProc(w, event, prms, nprms)
7313 PeriodicUpdatesEvent(!appData.periodicUpdates);
7315 if (appData.periodicUpdates) {
7316 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7318 XtSetArg(args[0], XtNleftBitmap, None);
7320 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Periodic Updates"),
7324 void PonderNextMoveProc(w, event, prms, nprms)
7332 PonderNextMoveEvent(!appData.ponderNextMove);
7334 if (appData.ponderNextMove) {
7335 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7337 XtSetArg(args[0], XtNleftBitmap, None);
7339 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Ponder Next Move"),
7343 void PopupExitMessageProc(w, event, prms, nprms)
7351 appData.popupExitMessage = !appData.popupExitMessage;
7353 if (appData.popupExitMessage) {
7354 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7356 XtSetArg(args[0], XtNleftBitmap, None);
7358 XtSetValues(XtNameToWidget(menuBarWidget,
7359 "menuOptions.Popup Exit Message"), args, 1);
7362 void PopupMoveErrorsProc(w, event, prms, nprms)
7370 appData.popupMoveErrors = !appData.popupMoveErrors;
7372 if (appData.popupMoveErrors) {
7373 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7375 XtSetArg(args[0], XtNleftBitmap, None);
7377 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Popup Move Errors"),
7381 void PremoveProc(w, event, prms, nprms)
7389 appData.premove = !appData.premove;
7391 if (appData.premove) {
7392 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7394 XtSetArg(args[0], XtNleftBitmap, None);
7396 XtSetValues(XtNameToWidget(menuBarWidget,
7397 "menuOptions.Premove"), args, 1);
7400 void QuietPlayProc(w, event, prms, nprms)
7408 appData.quietPlay = !appData.quietPlay;
7410 if (appData.quietPlay) {
7411 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7413 XtSetArg(args[0], XtNleftBitmap, None);
7415 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Quiet Play"),
7419 void ShowCoordsProc(w, event, prms, nprms)
7427 appData.showCoords = !appData.showCoords;
7429 if (appData.showCoords) {
7430 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7432 XtSetArg(args[0], XtNleftBitmap, None);
7434 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
7437 DrawPosition(True, NULL);
7440 void ShowThinkingProc(w, event, prms, nprms)
7448 appData.showThinking = !appData.showThinking; // [HGM] thinking: tken out of ShowThinkingEvent
7449 ShowThinkingEvent();
7451 // [HGM] thinking: currently no suc menu item; replaced by Hide Thinking (From Human)
7452 if (appData.showThinking) {
7453 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7455 XtSetArg(args[0], XtNleftBitmap, None);
7457 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Thinking"),
7462 void HideThinkingProc(w, event, prms, nprms)
7470 appData.hideThinkingFromHuman = !appData.hideThinkingFromHuman; // [HGM] thinking: tken out of ShowThinkingEvent
7471 ShowThinkingEvent();
7473 if (appData.hideThinkingFromHuman) {
7474 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7476 XtSetArg(args[0], XtNleftBitmap, None);
7478 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
7482 void InfoProc(w, event, prms, nprms)
7489 snprintf(buf, sizeof(buf), "xterm -e info --directory %s --directory . -f %s &",
7494 void ManProc(w, event, prms, nprms)
7502 if (nprms && *nprms > 0)
7506 snprintf(buf, sizeof(buf), "xterm -e man %s &", name);
7510 void HintProc(w, event, prms, nprms)
7519 void BookProc(w, event, prms, nprms)
7528 void AboutProc(w, event, prms, nprms)
7536 char *zippy = " (with Zippy code)";
7540 snprintf(buf, sizeof(buf), "%s%s\n\n%s\n%s\n%s\n\n%s%s\n%s",
7541 programVersion, zippy,
7542 "Copyright 1991 Digital Equipment Corporation",
7543 "Enhancements Copyright 1992-2009 Free Software Foundation",
7544 "Enhancements Copyright 2005 Alessandro Scotti",
7545 PRODUCT, " is free software and carries NO WARRANTY;",
7546 "see the file COPYING for more information.");
7547 ErrorPopUp(_("About XBoard"), buf, FALSE);
7550 void DebugProc(w, event, prms, nprms)
7556 appData.debugMode = !appData.debugMode;
7559 void AboutGameProc(w, event, prms, nprms)
7568 void NothingProc(w, event, prms, nprms)
7577 void Iconify(w, event, prms, nprms)
7586 XtSetArg(args[0], XtNiconic, True);
7587 XtSetValues(shellWidget, args, 1);
7590 void DisplayMessage(message, extMessage)
7591 char *message, *extMessage;
7598 snprintf(buf, sizeof(buf), "%s %s", message, extMessage);
7601 message = extMessage;
7604 XtSetArg(arg, XtNlabel, message);
7605 XtSetValues(messageWidget, &arg, 1);
7608 void DisplayTitle(text)
7613 char title[MSG_SIZ];
7616 if (text == NULL) text = "";
7618 if (appData.titleInWindow) {
7620 XtSetArg(args[i], XtNlabel, text); i++;
7621 XtSetValues(titleWidget, args, i);
7624 if (*text != NULLCHAR) {
7626 strcpy(title, text);
7627 } else if (appData.icsActive) {
7628 snprintf(icon, sizeof(icon), "%s", appData.icsHost);
7629 snprintf(title, sizeof(title), "%s: %s", programName, appData.icsHost);
7630 } else if (appData.cmailGameName[0] != NULLCHAR) {
7631 snprintf(icon, sizeof(icon), "%s", "CMail");
7632 snprintf(title,sizeof(title), "%s: %s", programName, "CMail");
7634 // [HGM] license: This stuff should really be done in back-end, but WinBoard already had a pop-up for it
7635 } else if (gameInfo.variant == VariantGothic) {
7636 strcpy(icon, programName);
7637 strcpy(title, GOTHIC);
7640 } else if (gameInfo.variant == VariantFalcon) {
7641 strcpy(icon, programName);
7642 strcpy(title, FALCON);
7644 } else if (appData.noChessProgram) {
7645 strcpy(icon, programName);
7646 strcpy(title, programName);
7648 strcpy(icon, first.tidy);
7649 snprintf(title,sizeof(title), "%s: %s", programName, first.tidy);
7652 XtSetArg(args[i], XtNiconName, (XtArgVal) icon); i++;
7653 XtSetArg(args[i], XtNtitle, (XtArgVal) title); i++;
7654 XtSetValues(shellWidget, args, i);
7658 void DisplayError(message, error)
7665 if (appData.debugMode || appData.matchMode) {
7666 fprintf(stderr, "%s: %s\n", programName, message);
7669 if (appData.debugMode || appData.matchMode) {
7670 fprintf(stderr, "%s: %s: %s\n",
7671 programName, message, strerror(error));
7673 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
7676 ErrorPopUp(_("Error"), message, FALSE);
7680 void DisplayMoveError(message)
7685 DrawPosition(FALSE, NULL);
7686 if (appData.debugMode || appData.matchMode) {
7687 fprintf(stderr, "%s: %s\n", programName, message);
7689 if (appData.popupMoveErrors) {
7690 ErrorPopUp(_("Error"), message, FALSE);
7692 DisplayMessage(message, "");
7697 void DisplayFatalError(message, error, status)
7703 errorExitStatus = status;
7705 fprintf(stderr, "%s: %s\n", programName, message);
7707 fprintf(stderr, "%s: %s: %s\n",
7708 programName, message, strerror(error));
7709 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
7712 if (appData.popupExitMessage && boardWidget && XtIsRealized(boardWidget)) {
7713 ErrorPopUp(status ? _("Fatal Error") : _("Exiting"), message, TRUE);
7719 void DisplayInformation(message)
7723 ErrorPopUp(_("Information"), message, TRUE);
7726 void DisplayNote(message)
7730 ErrorPopUp(_("Note"), message, FALSE);
7734 NullXErrorCheck(dpy, error_event)
7736 XErrorEvent *error_event;
7741 void DisplayIcsInteractionTitle(message)
7744 if (oldICSInteractionTitle == NULL) {
7745 /* Magic to find the old window title, adapted from vim */
7746 char *wina = getenv("WINDOWID");
7748 Window win = (Window) atoi(wina);
7749 Window root, parent, *children;
7750 unsigned int nchildren;
7751 int (*oldHandler)() = XSetErrorHandler(NullXErrorCheck);
7753 if (XFetchName(xDisplay, win, &oldICSInteractionTitle)) break;
7754 if (!XQueryTree(xDisplay, win, &root, &parent,
7755 &children, &nchildren)) break;
7756 if (children) XFree((void *)children);
7757 if (parent == root || parent == 0) break;
7760 XSetErrorHandler(oldHandler);
7762 if (oldICSInteractionTitle == NULL) {
7763 oldICSInteractionTitle = "xterm";
7766 printf("\033]0;%s\007", message);
7770 char pendingReplyPrefix[MSG_SIZ];
7771 ProcRef pendingReplyPR;
7773 void AskQuestionProc(w, event, prms, nprms)
7780 fprintf(stderr, _("AskQuestionProc needed 4 parameters, got %d\n"),
7784 AskQuestionEvent(prms[0], prms[1], prms[2], prms[3]);
7787 void AskQuestionPopDown()
7789 if (!askQuestionUp) return;
7790 XtPopdown(askQuestionShell);
7791 XtDestroyWidget(askQuestionShell);
7792 askQuestionUp = False;
7795 void AskQuestionReplyAction(w, event, prms, nprms)
7805 reply = XawDialogGetValueString(w = XtParent(w));
7806 strcpy(buf, pendingReplyPrefix);
7807 if (*buf) strcat(buf, " ");
7810 OutputToProcess(pendingReplyPR, buf, strlen(buf), &err);
7811 AskQuestionPopDown();
7813 if (err) DisplayFatalError(_("Error writing to chess program"), err, 0);
7816 void AskQuestionCallback(w, client_data, call_data)
7818 XtPointer client_data, call_data;
7823 XtSetArg(args[0], XtNlabel, &name);
7824 XtGetValues(w, args, 1);
7826 if (strcmp(name, _("cancel")) == 0) {
7827 AskQuestionPopDown();
7829 AskQuestionReplyAction(w, NULL, NULL, NULL);
7833 void AskQuestion(title, question, replyPrefix, pr)
7834 char *title, *question, *replyPrefix;
7838 Widget popup, layout, dialog, edit;
7844 strcpy(pendingReplyPrefix, replyPrefix);
7845 pendingReplyPR = pr;
7848 XtSetArg(args[i], XtNresizable, True); i++;
7849 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
7850 askQuestionShell = popup =
7851 XtCreatePopupShell(title, transientShellWidgetClass,
7852 shellWidget, args, i);
7855 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
7856 layoutArgs, XtNumber(layoutArgs));
7859 XtSetArg(args[i], XtNlabel, question); i++;
7860 XtSetArg(args[i], XtNvalue, ""); i++;
7861 XtSetArg(args[i], XtNborderWidth, 0); i++;
7862 dialog = XtCreateManagedWidget("question", dialogWidgetClass,
7865 XawDialogAddButton(dialog, _("enter"), AskQuestionCallback,
7866 (XtPointer) dialog);
7867 XawDialogAddButton(dialog, _("cancel"), AskQuestionCallback,
7868 (XtPointer) dialog);
7870 XtRealizeWidget(popup);
7871 CatchDeleteWindow(popup, "AskQuestionPopDown");
7873 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
7874 &x, &y, &win_x, &win_y, &mask);
7876 XtSetArg(args[0], XtNx, x - 10);
7877 XtSetArg(args[1], XtNy, y - 30);
7878 XtSetValues(popup, args, 2);
7880 XtPopup(popup, XtGrabExclusive);
7881 askQuestionUp = True;
7883 edit = XtNameToWidget(dialog, "*value");
7884 XtSetKeyboardFocus(popup, edit);
7892 if (*name == NULLCHAR) {
7894 } else if (strcmp(name, "$") == 0) {
7895 putc(BELLCHAR, stderr);
7898 snprintf(buf, sizeof(buf), "%s '%s' &", appData.soundProgram, name);
7906 PlaySound(appData.soundMove);
7912 PlaySound(appData.soundIcsWin);
7918 PlaySound(appData.soundIcsLoss);
7924 PlaySound(appData.soundIcsDraw);
7928 PlayIcsUnfinishedSound()
7930 PlaySound(appData.soundIcsUnfinished);
7936 PlaySound(appData.soundIcsAlarm);
7942 system("stty echo");
7948 system("stty -echo");
7952 Colorize(cc, continuation)
7957 int count, outCount, error;
7959 if (textColors[(int)cc].bg > 0) {
7960 if (textColors[(int)cc].fg > 0) {
7961 sprintf(buf, "\033[0;%d;%d;%dm", textColors[(int)cc].attr,
7962 textColors[(int)cc].fg, textColors[(int)cc].bg);
7964 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
7965 textColors[(int)cc].bg);
7968 if (textColors[(int)cc].fg > 0) {
7969 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
7970 textColors[(int)cc].fg);
7972 sprintf(buf, "\033[0;%dm", textColors[(int)cc].attr);
7975 count = strlen(buf);
7976 outCount = OutputToProcess(NoProc, buf, count, &error);
7977 if (outCount < count) {
7978 DisplayFatalError(_("Error writing to display"), error, 1);
7981 if (continuation) return;
7984 PlaySound(appData.soundShout);
7987 PlaySound(appData.soundSShout);
7990 PlaySound(appData.soundChannel1);
7993 PlaySound(appData.soundChannel);
7996 PlaySound(appData.soundKibitz);
7999 PlaySound(appData.soundTell);
8001 case ColorChallenge:
8002 PlaySound(appData.soundChallenge);
8005 PlaySound(appData.soundRequest);
8008 PlaySound(appData.soundSeek);
8019 return getpwuid(getuid())->pw_name;
8022 static char *ExpandPathName(path)
8025 static char static_buf[2000];
8026 char *d, *s, buf[2000];
8032 while (*s && isspace(*s))
8041 if (*(s+1) == '/') {
8042 strcpy(d, getpwuid(getuid())->pw_dir);
8047 *strchr(buf, '/') = 0;
8048 pwd = getpwnam(buf);
8051 fprintf(stderr, _("ERROR: Unknown user %s (in path %s)\n"),
8055 strcpy(d, pwd->pw_dir);
8056 strcat(d, strchr(s+1, '/'));
8067 static char host_name[MSG_SIZ];
8069 #if HAVE_GETHOSTNAME
8070 gethostname(host_name, MSG_SIZ);
8072 #else /* not HAVE_GETHOSTNAME */
8073 # if HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H
8074 sysinfo(SI_HOSTNAME, host_name, MSG_SIZ);
8076 # else /* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
8078 # endif/* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
8079 #endif /* not HAVE_GETHOSTNAME */
8082 XtIntervalId delayedEventTimerXID = 0;
8083 DelayedEventCallback delayedEventCallback = 0;
8088 delayedEventTimerXID = 0;
8089 delayedEventCallback();
8093 ScheduleDelayedEvent(cb, millisec)
8094 DelayedEventCallback cb; long millisec;
8096 delayedEventCallback = cb;
8097 delayedEventTimerXID =
8098 XtAppAddTimeOut(appContext, millisec,
8099 (XtTimerCallbackProc) FireDelayedEvent, (XtPointer) 0);
8102 DelayedEventCallback
8105 if (delayedEventTimerXID) {
8106 return delayedEventCallback;
8113 CancelDelayedEvent()
8115 if (delayedEventTimerXID) {
8116 XtRemoveTimeOut(delayedEventTimerXID);
8117 delayedEventTimerXID = 0;
8121 XtIntervalId loadGameTimerXID = 0;
8123 int LoadGameTimerRunning()
8125 return loadGameTimerXID != 0;
8128 int StopLoadGameTimer()
8130 if (loadGameTimerXID != 0) {
8131 XtRemoveTimeOut(loadGameTimerXID);
8132 loadGameTimerXID = 0;
8140 LoadGameTimerCallback(arg, id)
8144 loadGameTimerXID = 0;
8149 StartLoadGameTimer(millisec)
8153 XtAppAddTimeOut(appContext, millisec,
8154 (XtTimerCallbackProc) LoadGameTimerCallback,
8158 XtIntervalId analysisClockXID = 0;
8161 AnalysisClockCallback(arg, id)
8165 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile
8166 || appData.icsEngineAnalyze) { // [DM]
8167 AnalysisPeriodicEvent(0);
8168 StartAnalysisClock();
8173 StartAnalysisClock()
8176 XtAppAddTimeOut(appContext, 2000,
8177 (XtTimerCallbackProc) AnalysisClockCallback,
8181 XtIntervalId clockTimerXID = 0;
8183 int ClockTimerRunning()
8185 return clockTimerXID != 0;
8188 int StopClockTimer()
8190 if (clockTimerXID != 0) {
8191 XtRemoveTimeOut(clockTimerXID);
8200 ClockTimerCallback(arg, id)
8209 StartClockTimer(millisec)
8213 XtAppAddTimeOut(appContext, millisec,
8214 (XtTimerCallbackProc) ClockTimerCallback,
8219 DisplayTimerLabel(w, color, timer, highlight)
8228 Pixel foregroundOrWarningColor = timerForegroundPixel;
8231 && appData.lowTimeWarning
8232 && (timer / 1000) < appData.icsAlarmTime)
8234 foregroundOrWarningColor = lowTimeWarningColor;
8236 if (appData.clockMode) {
8237 sprintf(buf, "%s: %s", color, TimeString(timer));
8238 XtSetArg(args[0], XtNlabel, buf);
8240 sprintf(buf, "%s ", color);
8241 XtSetArg(args[0], XtNlabel, buf);
8246 XtSetArg(args[1], XtNbackground, foregroundOrWarningColor);
8247 XtSetArg(args[2], XtNforeground, timerBackgroundPixel);
8249 XtSetArg(args[1], XtNbackground, timerBackgroundPixel);
8250 XtSetArg(args[2], XtNforeground, foregroundOrWarningColor);
8253 XtSetValues(w, args, 3);
8257 DisplayWhiteClock(timeRemaining, highlight)
8263 if(appData.noGUI) return;
8264 DisplayTimerLabel(whiteTimerWidget, _("White"), timeRemaining, highlight);
8265 if (highlight && iconPixmap == bIconPixmap) {
8266 iconPixmap = wIconPixmap;
8267 XtSetArg(args[0], XtNiconPixmap, iconPixmap);
8268 XtSetValues(shellWidget, args, 1);
8273 DisplayBlackClock(timeRemaining, highlight)
8279 if(appData.noGUI) return;
8280 DisplayTimerLabel(blackTimerWidget, _("Black"), timeRemaining, highlight);
8281 if (highlight && iconPixmap == wIconPixmap) {
8282 iconPixmap = bIconPixmap;
8283 XtSetArg(args[0], XtNiconPixmap, iconPixmap);
8284 XtSetValues(shellWidget, args, 1);
8302 int StartChildProcess(cmdLine, dir, pr)
8309 int to_prog[2], from_prog[2];
8313 if (appData.debugMode) {
8314 fprintf(stderr, "StartChildProcess (dir=\"%s\") %s\n",dir, cmdLine);
8317 /* We do NOT feed the cmdLine to the shell; we just
8318 parse it into blank-separated arguments in the
8319 most simple-minded way possible.
8322 strcpy(buf, cmdLine);
8327 if (p == NULL) break;
8332 SetUpChildIO(to_prog, from_prog);
8334 if ((pid = fork()) == 0) {
8336 // [HGM] PSWBTM: made order resistant against case where fd of created pipe was 0 or 1
8337 close(to_prog[1]); // first close the unused pipe ends
8338 close(from_prog[0]);
8339 dup2(to_prog[0], 0); // to_prog was created first, nd is the only one to use 0 or 1
8340 dup2(from_prog[1], 1);
8341 if(to_prog[0] >= 2) close(to_prog[0]); // if 0 or 1, the dup2 already cosed the original
8342 close(from_prog[1]); // and closing again loses one of the pipes!
8343 if(fileno(stderr) >= 2) // better safe than sorry...
8344 dup2(1, fileno(stderr)); /* force stderr to the pipe */
8346 if (dir[0] != NULLCHAR && chdir(dir) != 0) {
8351 nice(appData.niceEngines); // [HGM] nice: adjust priority of engine proc
8353 execvp(argv[0], argv);
8355 /* If we get here, exec failed */
8360 /* Parent process */
8362 close(from_prog[1]);
8364 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8367 cp->fdFrom = from_prog[0];
8368 cp->fdTo = to_prog[1];
8373 // [HGM] kill: implement the 'hard killing' of AS's Winboard_x
8374 static RETSIGTYPE AlarmCallBack(int n)
8380 DestroyChildProcess(pr, signalType)
8384 ChildProc *cp = (ChildProc *) pr;
8386 if (cp->kind != CPReal) return;
8388 if (signalType == 10) { // [HGM] kill: if it does not terminate in 3 sec, kill
8389 signal(SIGALRM, AlarmCallBack);
8391 if(wait((int *) 0) == -1) { // process does not terminate on its own accord
8392 kill(cp->pid, SIGKILL); // kill it forcefully
8393 wait((int *) 0); // and wait again
8397 kill(cp->pid, signalType == 9 ? SIGKILL : SIGTERM); // [HGM] kill: use hard kill if so requested
8399 /* Process is exiting either because of the kill or because of
8400 a quit command sent by the backend; either way, wait for it to die.
8409 InterruptChildProcess(pr)
8412 ChildProc *cp = (ChildProc *) pr;
8414 if (cp->kind != CPReal) return;
8415 (void) kill(cp->pid, SIGINT); /* stop it thinking */
8418 int OpenTelnet(host, port, pr)
8423 char cmdLine[MSG_SIZ];
8425 if (port[0] == NULLCHAR) {
8426 snprintf(cmdLine, sizeof(cmdLine), "%s %s", appData.telnetProgram, host);
8428 snprintf(cmdLine, sizeof(cmdLine), "%s %s %s", appData.telnetProgram, host, port);
8430 return StartChildProcess(cmdLine, "", pr);
8433 int OpenTCP(host, port, pr)
8439 DisplayFatalError(_("Socket support is not configured in"), 0, 2);
8440 #else /* !OMIT_SOCKETS */
8442 struct sockaddr_in sa;
8444 unsigned short uport;
8447 if ((s = socket(AF_INET, SOCK_STREAM, 6)) < 0) {
8451 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
8452 sa.sin_family = AF_INET;
8453 sa.sin_addr.s_addr = INADDR_ANY;
8454 uport = (unsigned short) 0;
8455 sa.sin_port = htons(uport);
8456 if (bind(s, (struct sockaddr *) &sa, sizeof(struct sockaddr_in)) < 0) {
8460 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
8461 if (!(hp = gethostbyname(host))) {
8463 if (sscanf(host, "%d.%d.%d.%d", &b0, &b1, &b2, &b3) == 4) {
8464 hp = (struct hostent *) calloc(1, sizeof(struct hostent));
8465 hp->h_addrtype = AF_INET;
8467 hp->h_addr_list = (char **) calloc(2, sizeof(char *));
8468 hp->h_addr_list[0] = (char *) malloc(4);
8469 hp->h_addr_list[0][0] = b0;
8470 hp->h_addr_list[0][1] = b1;
8471 hp->h_addr_list[0][2] = b2;
8472 hp->h_addr_list[0][3] = b3;
8477 sa.sin_family = hp->h_addrtype;
8478 uport = (unsigned short) atoi(port);
8479 sa.sin_port = htons(uport);
8480 memcpy((char *) &sa.sin_addr, hp->h_addr, hp->h_length);
8482 if (connect(s, (struct sockaddr *) &sa,
8483 sizeof(struct sockaddr_in)) < 0) {
8487 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8494 #endif /* !OMIT_SOCKETS */
8499 int OpenCommPort(name, pr)
8506 fd = open(name, 2, 0);
8507 if (fd < 0) return errno;
8509 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8519 int OpenLoopback(pr)
8525 SetUpChildIO(to, from);
8527 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8530 cp->fdFrom = to[0]; /* note not from[0]; we are doing a loopback */
8537 int OpenRcmd(host, user, cmd, pr)
8538 char *host, *user, *cmd;
8541 DisplayFatalError(_("internal rcmd not implemented for Unix"), 0, 1);
8545 #define INPUT_SOURCE_BUF_SIZE 8192
8554 char buf[INPUT_SOURCE_BUF_SIZE];
8559 DoInputCallback(closure, source, xid)
8564 InputSource *is = (InputSource *) closure;
8569 if (is->lineByLine) {
8570 count = read(is->fd, is->unused,
8571 INPUT_SOURCE_BUF_SIZE - (is->unused - is->buf));
8573 (is->func)(is, is->closure, is->buf, count, count ? errno : 0);
8576 is->unused += count;
8578 while (p < is->unused) {
8579 q = memchr(p, '\n', is->unused - p);
8580 if (q == NULL) break;
8582 (is->func)(is, is->closure, p, q - p, 0);
8586 while (p < is->unused) {
8591 count = read(is->fd, is->buf, INPUT_SOURCE_BUF_SIZE);
8596 (is->func)(is, is->closure, is->buf, count, error);
8600 InputSourceRef AddInputSource(pr, lineByLine, func, closure)
8607 ChildProc *cp = (ChildProc *) pr;
8609 is = (InputSource *) calloc(1, sizeof(InputSource));
8610 is->lineByLine = lineByLine;
8614 is->fd = fileno(stdin);
8616 is->kind = cp->kind;
8617 is->fd = cp->fdFrom;
8620 is->unused = is->buf;
8623 is->xid = XtAppAddInput(appContext, is->fd,
8624 (XtPointer) (XtInputReadMask),
8625 (XtInputCallbackProc) DoInputCallback,
8627 is->closure = closure;
8628 return (InputSourceRef) is;
8632 RemoveInputSource(isr)
8635 InputSource *is = (InputSource *) isr;
8637 if (is->xid == 0) return;
8638 XtRemoveInput(is->xid);
8642 int OutputToProcess(pr, message, count, outError)
8648 ChildProc *cp = (ChildProc *) pr;
8652 outCount = fwrite(message, 1, count, stdout);
8654 outCount = write(cp->fdTo, message, count);
8664 /* Output message to process, with "ms" milliseconds of delay
8665 between each character. This is needed when sending the logon
8666 script to ICC, which for some reason doesn't like the
8667 instantaneous send. */
8668 int OutputToProcessDelayed(pr, message, count, outError, msdelay)
8675 ChildProc *cp = (ChildProc *) pr;
8680 r = write(cp->fdTo, message++, 1);
8693 /**** Animation code by Hugh Fisher, DCS, ANU.
8695 Known problem: if a window overlapping the board is
8696 moved away while a piece is being animated underneath,
8697 the newly exposed area won't be updated properly.
8698 I can live with this.
8700 Known problem: if you look carefully at the animation
8701 of pieces in mono mode, they are being drawn as solid
8702 shapes without interior detail while moving. Fixing
8703 this would be a major complication for minimal return.
8706 /* Masks for XPM pieces. Black and white pieces can have
8707 different shapes, but in the interest of retaining my
8708 sanity pieces must have the same outline on both light
8709 and dark squares, and all pieces must use the same
8710 background square colors/images. */
8712 static int xpmDone = 0;
8715 CreateAnimMasks (pieceDepth)
8722 unsigned long plane;
8725 /* Need a bitmap just to get a GC with right depth */
8726 buf = XCreatePixmap(xDisplay, xBoardWindow,
8728 values.foreground = 1;
8729 values.background = 0;
8730 /* Don't use XtGetGC, not read only */
8731 maskGC = XCreateGC(xDisplay, buf,
8732 GCForeground | GCBackground, &values);
8733 XFreePixmap(xDisplay, buf);
8735 buf = XCreatePixmap(xDisplay, xBoardWindow,
8736 squareSize, squareSize, pieceDepth);
8737 values.foreground = XBlackPixel(xDisplay, xScreen);
8738 values.background = XWhitePixel(xDisplay, xScreen);
8739 bufGC = XCreateGC(xDisplay, buf,
8740 GCForeground | GCBackground, &values);
8742 for (piece = WhitePawn; piece <= BlackKing; piece++) {
8743 /* Begin with empty mask */
8744 if(!xpmDone) // [HGM] pieces: keep using existing
8745 xpmMask[piece] = XCreatePixmap(xDisplay, xBoardWindow,
8746 squareSize, squareSize, 1);
8747 XSetFunction(xDisplay, maskGC, GXclear);
8748 XFillRectangle(xDisplay, xpmMask[piece], maskGC,
8749 0, 0, squareSize, squareSize);
8751 /* Take a copy of the piece */
8756 XSetFunction(xDisplay, bufGC, GXcopy);
8757 XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % (int)BlackPawn],
8759 0, 0, squareSize, squareSize, 0, 0);
8761 /* XOR the background (light) over the piece */
8762 XSetFunction(xDisplay, bufGC, GXxor);
8764 XCopyArea(xDisplay, xpmLightSquare, buf, bufGC,
8765 0, 0, squareSize, squareSize, 0, 0);
8767 XSetForeground(xDisplay, bufGC, lightSquareColor);
8768 XFillRectangle(xDisplay, buf, bufGC, 0, 0, squareSize, squareSize);
8771 /* We now have an inverted piece image with the background
8772 erased. Construct mask by just selecting all the non-zero
8773 pixels - no need to reconstruct the original image. */
8774 XSetFunction(xDisplay, maskGC, GXor);
8776 /* Might be quicker to download an XImage and create bitmap
8777 data from it rather than this N copies per piece, but it
8778 only takes a fraction of a second and there is a much
8779 longer delay for loading the pieces. */
8780 for (n = 0; n < pieceDepth; n ++) {
8781 XCopyPlane(xDisplay, buf, xpmMask[piece], maskGC,
8782 0, 0, squareSize, squareSize,
8788 XFreePixmap(xDisplay, buf);
8789 XFreeGC(xDisplay, bufGC);
8790 XFreeGC(xDisplay, maskGC);
8794 InitAnimState (anim, info)
8796 XWindowAttributes * info;
8801 /* Each buffer is square size, same depth as window */
8802 anim->saveBuf = XCreatePixmap(xDisplay, xBoardWindow,
8803 squareSize, squareSize, info->depth);
8804 anim->newBuf = XCreatePixmap(xDisplay, xBoardWindow,
8805 squareSize, squareSize, info->depth);
8807 /* Create a plain GC for blitting */
8808 mask = GCForeground | GCBackground | GCFunction |
8809 GCPlaneMask | GCGraphicsExposures;
8810 values.foreground = XBlackPixel(xDisplay, xScreen);
8811 values.background = XWhitePixel(xDisplay, xScreen);
8812 values.function = GXcopy;
8813 values.plane_mask = AllPlanes;
8814 values.graphics_exposures = False;
8815 anim->blitGC = XCreateGC(xDisplay, xBoardWindow, mask, &values);
8817 /* Piece will be copied from an existing context at
8818 the start of each new animation/drag. */
8819 anim->pieceGC = XCreateGC(xDisplay, xBoardWindow, 0, &values);
8821 /* Outline will be a read-only copy of an existing */
8822 anim->outlineGC = None;
8828 static VariantClass old = (VariantClass) -1; // [HGM] pieces: redo every time variant changes
8829 XWindowAttributes info;
8831 if (xpmDone && gameInfo.variant == old) return;
8832 if(xpmDone) old = gameInfo.variant; // first time pieces might not be created yet
8833 XGetWindowAttributes(xDisplay, xBoardWindow, &info);
8835 InitAnimState(&game, &info);
8836 InitAnimState(&player, &info);
8838 /* For XPM pieces, we need bitmaps to use as masks. */
8840 CreateAnimMasks(info.depth);
8846 static Boolean frameWaiting;
8848 static RETSIGTYPE FrameAlarm (sig)
8851 frameWaiting = False;
8852 /* In case System-V style signals. Needed?? */
8853 signal(SIGALRM, FrameAlarm);
8860 struct itimerval delay;
8862 XSync(xDisplay, False);
8865 frameWaiting = True;
8866 signal(SIGALRM, FrameAlarm);
8867 delay.it_interval.tv_sec =
8868 delay.it_value.tv_sec = time / 1000;
8869 delay.it_interval.tv_usec =
8870 delay.it_value.tv_usec = (time % 1000) * 1000;
8871 setitimer(ITIMER_REAL, &delay, NULL);
8873 /* Ugh -- busy-wait! --tpm */
8874 while (frameWaiting);
8876 while (frameWaiting) pause();
8878 delay.it_interval.tv_sec = delay.it_value.tv_sec = 0;
8879 delay.it_interval.tv_usec = delay.it_value.tv_usec = 0;
8880 setitimer(ITIMER_REAL, &delay, NULL);
8890 XSync(xDisplay, False);
8892 usleep(time * 1000);
8897 /* Convert board position to corner of screen rect and color */
8900 ScreenSquare(column, row, pt, color)
8901 int column; int row; XPoint * pt; int * color;
8904 pt->x = lineGap + ((BOARD_WIDTH-1)-column) * (squareSize + lineGap);
8905 pt->y = lineGap + row * (squareSize + lineGap);
8907 pt->x = lineGap + column * (squareSize + lineGap);
8908 pt->y = lineGap + ((BOARD_HEIGHT-1)-row) * (squareSize + lineGap);
8910 *color = SquareColor(row, column);
8913 /* Convert window coords to square */
8916 BoardSquare(x, y, column, row)
8917 int x; int y; int * column; int * row;
8919 *column = EventToSquare(x, BOARD_WIDTH);
8920 if (flipView && *column >= 0)
8921 *column = BOARD_WIDTH - 1 - *column;
8922 *row = EventToSquare(y, BOARD_HEIGHT);
8923 if (!flipView && *row >= 0)
8924 *row = BOARD_HEIGHT - 1 - *row;
8929 #undef Max /* just in case */
8931 #define Max(a, b) ((a) > (b) ? (a) : (b))
8932 #define Min(a, b) ((a) < (b) ? (a) : (b))
8935 SetRect(rect, x, y, width, height)
8936 XRectangle * rect; int x; int y; int width; int height;
8940 rect->width = width;
8941 rect->height = height;
8944 /* Test if two frames overlap. If they do, return
8945 intersection rect within old and location of
8946 that rect within new. */
8949 Intersect(old, new, size, area, pt)
8950 XPoint * old; XPoint * new;
8951 int size; XRectangle * area; XPoint * pt;
8953 if (old->x > new->x + size || new->x > old->x + size ||
8954 old->y > new->y + size || new->y > old->y + size) {
8957 SetRect(area, Max(new->x - old->x, 0), Max(new->y - old->y, 0),
8958 size - abs(old->x - new->x), size - abs(old->y - new->y));
8959 pt->x = Max(old->x - new->x, 0);
8960 pt->y = Max(old->y - new->y, 0);
8965 /* For two overlapping frames, return the rect(s)
8966 in the old that do not intersect with the new. */
8969 CalcUpdateRects(old, new, size, update, nUpdates)
8970 XPoint * old; XPoint * new; int size;
8971 XRectangle update[]; int * nUpdates;
8975 /* If old = new (shouldn't happen) then nothing to draw */
8976 if (old->x == new->x && old->y == new->y) {
8980 /* Work out what bits overlap. Since we know the rects
8981 are the same size we don't need a full intersect calc. */
8983 /* Top or bottom edge? */
8984 if (new->y > old->y) {
8985 SetRect(&(update[count]), old->x, old->y, size, new->y - old->y);
8987 } else if (old->y > new->y) {
8988 SetRect(&(update[count]), old->x, old->y + size - (old->y - new->y),
8989 size, old->y - new->y);
8992 /* Left or right edge - don't overlap any update calculated above. */
8993 if (new->x > old->x) {
8994 SetRect(&(update[count]), old->x, Max(new->y, old->y),
8995 new->x - old->x, size - abs(new->y - old->y));
8997 } else if (old->x > new->x) {
8998 SetRect(&(update[count]), new->x + size, Max(new->y, old->y),
8999 old->x - new->x, size - abs(new->y - old->y));
9006 /* Generate a series of frame coords from start->mid->finish.
9007 The movement rate doubles until the half way point is
9008 reached, then halves back down to the final destination,
9009 which gives a nice slow in/out effect. The algorithmn
9010 may seem to generate too many intermediates for short
9011 moves, but remember that the purpose is to attract the
9012 viewers attention to the piece about to be moved and
9013 then to where it ends up. Too few frames would be less
9017 Tween(start, mid, finish, factor, frames, nFrames)
9018 XPoint * start; XPoint * mid;
9019 XPoint * finish; int factor;
9020 XPoint frames[]; int * nFrames;
9022 int fraction, n, count;
9026 /* Slow in, stepping 1/16th, then 1/8th, ... */
9028 for (n = 0; n < factor; n++)
9030 for (n = 0; n < factor; n++) {
9031 frames[count].x = start->x + (mid->x - start->x) / fraction;
9032 frames[count].y = start->y + (mid->y - start->y) / fraction;
9034 fraction = fraction / 2;
9038 frames[count] = *mid;
9041 /* Slow out, stepping 1/2, then 1/4, ... */
9043 for (n = 0; n < factor; n++) {
9044 frames[count].x = finish->x - (finish->x - mid->x) / fraction;
9045 frames[count].y = finish->y - (finish->y - mid->y) / fraction;
9047 fraction = fraction * 2;
9052 /* Draw a piece on the screen without disturbing what's there */
9055 SelectGCMask(piece, clip, outline, mask)
9056 ChessSquare piece; GC * clip; GC * outline; Pixmap * mask;
9060 /* Bitmap for piece being moved. */
9061 if (appData.monoMode) {
9062 *mask = *pieceToSolid(piece);
9063 } else if (useImages) {
9065 *mask = xpmMask[piece];
9067 *mask = ximMaskPm[piece];
9070 *mask = *pieceToSolid(piece);
9073 /* GC for piece being moved. Square color doesn't matter, but
9074 since it gets modified we make a copy of the original. */
9076 if (appData.monoMode)
9081 if (appData.monoMode)
9086 XCopyGC(xDisplay, source, 0xFFFFFFFF, *clip);
9088 /* Outline only used in mono mode and is not modified */
9090 *outline = bwPieceGC;
9092 *outline = wbPieceGC;
9096 OverlayPiece(piece, clip, outline, dest)
9097 ChessSquare piece; GC clip; GC outline; Drawable dest;
9102 /* Draw solid rectangle which will be clipped to shape of piece */
9103 XFillRectangle(xDisplay, dest, clip,
9104 0, 0, squareSize, squareSize);
9105 if (appData.monoMode)
9106 /* Also draw outline in contrasting color for black
9107 on black / white on white cases */
9108 XCopyPlane(xDisplay, *pieceToOutline(piece), dest, outline,
9109 0, 0, squareSize, squareSize, 0, 0, 1);
9111 /* Copy the piece */
9116 XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
9118 0, 0, squareSize, squareSize,
9123 /* Animate the movement of a single piece */
9126 BeginAnimation(anim, piece, startColor, start)
9134 /* The old buffer is initialised with the start square (empty) */
9135 BlankSquare(0, 0, startColor, EmptySquare, anim->saveBuf);
9136 anim->prevFrame = *start;
9138 /* The piece will be drawn using its own bitmap as a matte */
9139 SelectGCMask(piece, &anim->pieceGC, &anim->outlineGC, &mask);
9140 XSetClipMask(xDisplay, anim->pieceGC, mask);
9144 AnimationFrame(anim, frame, piece)
9149 XRectangle updates[4];
9154 /* Save what we are about to draw into the new buffer */
9155 XCopyArea(xDisplay, xBoardWindow, anim->newBuf, anim->blitGC,
9156 frame->x, frame->y, squareSize, squareSize,
9159 /* Erase bits of the previous frame */
9160 if (Intersect(&anim->prevFrame, frame, squareSize, &overlap, &pt)) {
9161 /* Where the new frame overlapped the previous,
9162 the contents in newBuf are wrong. */
9163 XCopyArea(xDisplay, anim->saveBuf, anim->newBuf, anim->blitGC,
9164 overlap.x, overlap.y,
9165 overlap.width, overlap.height,
9167 /* Repaint the areas in the old that don't overlap new */
9168 CalcUpdateRects(&anim->prevFrame, frame, squareSize, updates, &count);
9169 for (i = 0; i < count; i++)
9170 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9171 updates[i].x - anim->prevFrame.x,
9172 updates[i].y - anim->prevFrame.y,
9173 updates[i].width, updates[i].height,
9174 updates[i].x, updates[i].y);
9176 /* Easy when no overlap */
9177 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9178 0, 0, squareSize, squareSize,
9179 anim->prevFrame.x, anim->prevFrame.y);
9182 /* Save this frame for next time round */
9183 XCopyArea(xDisplay, anim->newBuf, anim->saveBuf, anim->blitGC,
9184 0, 0, squareSize, squareSize,
9186 anim->prevFrame = *frame;
9188 /* Draw piece over original screen contents, not current,
9189 and copy entire rect. Wipes out overlapping piece images. */
9190 OverlayPiece(piece, anim->pieceGC, anim->outlineGC, anim->newBuf);
9191 XCopyArea(xDisplay, anim->newBuf, xBoardWindow, anim->blitGC,
9192 0, 0, squareSize, squareSize,
9193 frame->x, frame->y);
9197 EndAnimation (anim, finish)
9201 XRectangle updates[4];
9206 /* The main code will redraw the final square, so we
9207 only need to erase the bits that don't overlap. */
9208 if (Intersect(&anim->prevFrame, finish, squareSize, &overlap, &pt)) {
9209 CalcUpdateRects(&anim->prevFrame, finish, squareSize, updates, &count);
9210 for (i = 0; i < count; i++)
9211 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9212 updates[i].x - anim->prevFrame.x,
9213 updates[i].y - anim->prevFrame.y,
9214 updates[i].width, updates[i].height,
9215 updates[i].x, updates[i].y);
9217 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9218 0, 0, squareSize, squareSize,
9219 anim->prevFrame.x, anim->prevFrame.y);
9224 FrameSequence(anim, piece, startColor, start, finish, frames, nFrames)
9226 ChessSquare piece; int startColor;
9227 XPoint * start; XPoint * finish;
9228 XPoint frames[]; int nFrames;
9232 BeginAnimation(anim, piece, startColor, start);
9233 for (n = 0; n < nFrames; n++) {
9234 AnimationFrame(anim, &(frames[n]), piece);
9235 FrameDelay(appData.animSpeed);
9237 EndAnimation(anim, finish);
9240 /* Main control logic for deciding what to animate and how */
9243 AnimateMove(board, fromX, fromY, toX, toY)
9252 XPoint start, finish, mid;
9253 XPoint frames[kFactor * 2 + 1];
9254 int nFrames, startColor, endColor;
9256 /* Are we animating? */
9257 if (!appData.animate || appData.blindfold)
9260 if (fromY < 0 || fromX < 0 || toX < 0 || toY < 0) return;
9261 piece = board[fromY][fromX];
9262 if (piece >= EmptySquare) return;
9267 hop = (piece == WhiteKnight || piece == BlackKnight);
9270 if (appData.debugMode) {
9271 fprintf(debugFP, hop ? _("AnimateMove: piece %d hops from %d,%d to %d,%d \n") :
9272 _("AnimateMove: piece %d slides from %d,%d to %d,%d \n"),
9273 piece, fromX, fromY, toX, toY); }
9275 ScreenSquare(fromX, fromY, &start, &startColor);
9276 ScreenSquare(toX, toY, &finish, &endColor);
9279 /* Knight: make diagonal movement then straight */
9280 if (abs(toY - fromY) < abs(toX - fromX)) {
9281 mid.x = start.x + (finish.x - start.x) / 2;
9285 mid.y = start.y + (finish.y - start.y) / 2;
9288 mid.x = start.x + (finish.x - start.x) / 2;
9289 mid.y = start.y + (finish.y - start.y) / 2;
9292 /* Don't use as many frames for very short moves */
9293 if (abs(toY - fromY) + abs(toX - fromX) <= 2)
9294 Tween(&start, &mid, &finish, kFactor - 1, frames, &nFrames);
9296 Tween(&start, &mid, &finish, kFactor, frames, &nFrames);
9297 FrameSequence(&game, piece, startColor, &start, &finish, frames, nFrames);
9299 /* Be sure end square is redrawn */
9300 damage[toY][toX] = True;
9304 DragPieceBegin(x, y)
9307 int boardX, boardY, color;
9310 /* Are we animating? */
9311 if (!appData.animateDragging || appData.blindfold)
9314 /* Figure out which square we start in and the
9315 mouse position relative to top left corner. */
9316 BoardSquare(x, y, &boardX, &boardY);
9317 player.startBoardX = boardX;
9318 player.startBoardY = boardY;
9319 ScreenSquare(boardX, boardY, &corner, &color);
9320 player.startSquare = corner;
9321 player.startColor = color;
9323 /* Start from exactly where the piece is. This can be confusing
9324 if you start dragging far from the center of the square; most
9325 or all of the piece can be over a different square from the one
9326 the mouse pointer is in. */
9327 player.mouseDelta.x = x - corner.x;
9328 player.mouseDelta.y = y - corner.y;
9330 /* As soon as we start dragging, the piece will jump slightly to
9331 be centered over the mouse pointer. */
9332 player.mouseDelta.x = squareSize/2;
9333 player.mouseDelta.y = squareSize/2;
9335 /* Initialise animation */
9336 player.dragPiece = PieceForSquare(boardX, boardY);
9338 if (player.dragPiece >= 0 && player.dragPiece < EmptySquare) {
9339 player.dragActive = True;
9340 BeginAnimation(&player, player.dragPiece, color, &corner);
9341 /* Mark this square as needing to be redrawn. Note that
9342 we don't remove the piece though, since logically (ie
9343 as seen by opponent) the move hasn't been made yet. */
9344 if(boardX == BOARD_RGHT+1 && PieceForSquare(boardX-1, boardY) > 1 ||
9345 boardX == BOARD_LEFT-2 && PieceForSquare(boardX+1, boardY) > 1)
9346 XCopyArea(xDisplay, xBoardWindow, player.saveBuf, player.blitGC,
9347 corner.x, corner.y, squareSize, squareSize,
9348 0, 0); // [HGM] zh: unstack in stead of grab
9349 damage[boardY][boardX] = True;
9351 player.dragActive = False;
9361 /* Are we animating? */
9362 if (!appData.animateDragging || appData.blindfold)
9366 if (! player.dragActive)
9368 /* Move piece, maintaining same relative position
9369 of mouse within square */
9370 corner.x = x - player.mouseDelta.x;
9371 corner.y = y - player.mouseDelta.y;
9372 AnimationFrame(&player, &corner, player.dragPiece);
9374 if (appData.highlightDragging) {
9376 BoardSquare(x, y, &boardX, &boardY);
9377 SetHighlights(fromX, fromY, boardX, boardY);
9386 int boardX, boardY, color;
9389 /* Are we animating? */
9390 if (!appData.animateDragging || appData.blindfold)
9394 if (! player.dragActive)
9396 /* Last frame in sequence is square piece is
9397 placed on, which may not match mouse exactly. */
9398 BoardSquare(x, y, &boardX, &boardY);
9399 ScreenSquare(boardX, boardY, &corner, &color);
9400 EndAnimation(&player, &corner);
9402 /* Be sure end square is redrawn */
9403 damage[boardY][boardX] = True;
9405 /* This prevents weird things happening with fast successive
9406 clicks which on my Sun at least can cause motion events
9407 without corresponding press/release. */
9408 player.dragActive = False;
9411 /* Handle expose event while piece being dragged */
9416 if (!player.dragActive || appData.blindfold)
9419 /* What we're doing: logically, the move hasn't been made yet,
9420 so the piece is still in it's original square. But visually
9421 it's being dragged around the board. So we erase the square
9422 that the piece is on and draw it at the last known drag point. */
9423 BlankSquare(player.startSquare.x, player.startSquare.y,
9424 player.startColor, EmptySquare, xBoardWindow);
9425 AnimationFrame(&player, &player.prevFrame, player.dragPiece);
9426 damage[player.startBoardY][player.startBoardX] = TRUE;
9430 SetProgramStats( FrontEndProgramStats * stats )
9433 // [HGM] done, but perhaps backend should call this directly?
9434 EngineOutputUpdate( stats );