2 * xboard.c -- X front end for XBoard
4 * Copyright 1991 by Digital Equipment Corporation, Maynard,
7 * Enhancements Copyright 1992-2001, 2002, 2003, 2004, 2005, 2006,
8 * 2007, 2008, 2009 Free Software Foundation, Inc.
10 * The following terms apply to Digital Equipment Corporation's copyright
12 * ------------------------------------------------------------------------
15 * Permission to use, copy, modify, and distribute this software and its
16 * documentation for any purpose and without fee is hereby granted,
17 * provided that the above copyright notice appear in all copies and that
18 * both that copyright notice and this permission notice appear in
19 * supporting documentation, and that the name of Digital not be
20 * used in advertising or publicity pertaining to distribution of the
21 * software without specific, written prior permission.
23 * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
24 * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
25 * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
26 * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
27 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
28 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
30 * ------------------------------------------------------------------------
32 * The following terms apply to the enhanced version of XBoard
33 * distributed by the Free Software Foundation:
34 * ------------------------------------------------------------------------
36 * GNU XBoard is free software: you can redistribute it and/or modify
37 * it under the terms of the GNU General Public License as published by
38 * the Free Software Foundation, either version 3 of the License, or (at
39 * your option) any later version.
41 * GNU XBoard is distributed in the hope that it will be useful, but
42 * WITHOUT ANY WARRANTY; without even the implied warranty of
43 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
44 * General Public License for more details.
46 * You should have received a copy of the GNU General Public License
47 * along with this program. If not, see http://www.gnu.org/licenses/. *
49 *------------------------------------------------------------------------
50 ** See the file ChangeLog for a revision history. */
58 #include <sys/types.h>
63 # if HAVE_SYS_SOCKET_H
64 # include <sys/socket.h>
65 # include <netinet/in.h>
67 # else /* not HAVE_SYS_SOCKET_H */
68 # if HAVE_LAN_SOCKET_H
69 # include <lan/socket.h>
71 # include <lan/netdb.h>
72 # else /* not HAVE_LAN_SOCKET_H */
73 # define OMIT_SOCKETS 1
74 # endif /* not HAVE_LAN_SOCKET_H */
75 # endif /* not HAVE_SYS_SOCKET_H */
76 #endif /* !OMIT_SOCKETS */
81 #else /* not STDC_HEADERS */
82 extern char *getenv();
85 # else /* not HAVE_STRING_H */
87 # endif /* not HAVE_STRING_H */
88 #endif /* not STDC_HEADERS */
91 # include <sys/fcntl.h>
92 #else /* not HAVE_SYS_FCNTL_H */
95 # endif /* HAVE_FCNTL_H */
96 #endif /* not HAVE_SYS_FCNTL_H */
98 #if HAVE_SYS_SYSTEMINFO_H
99 # include <sys/systeminfo.h>
100 #endif /* HAVE_SYS_SYSTEMINFO_H */
102 #if TIME_WITH_SYS_TIME
103 # include <sys/time.h>
107 # include <sys/time.h>
118 # include <sys/wait.h>
123 # define NAMLEN(dirent) strlen((dirent)->d_name)
124 # define HAVE_DIR_STRUCT
126 # define dirent direct
127 # define NAMLEN(dirent) (dirent)->d_namlen
129 # include <sys/ndir.h>
130 # define HAVE_DIR_STRUCT
133 # include <sys/dir.h>
134 # define HAVE_DIR_STRUCT
138 # define HAVE_DIR_STRUCT
142 #include <X11/Intrinsic.h>
143 #include <X11/StringDefs.h>
144 #include <X11/Shell.h>
145 #include <X11/cursorfont.h>
146 #include <X11/Xatom.h>
148 #include <X11/Xaw3d/Dialog.h>
149 #include <X11/Xaw3d/Form.h>
150 #include <X11/Xaw3d/List.h>
151 #include <X11/Xaw3d/Label.h>
152 #include <X11/Xaw3d/SimpleMenu.h>
153 #include <X11/Xaw3d/SmeBSB.h>
154 #include <X11/Xaw3d/SmeLine.h>
155 #include <X11/Xaw3d/Box.h>
156 #include <X11/Xaw3d/MenuButton.h>
157 #include <X11/Xaw3d/Text.h>
158 #include <X11/Xaw3d/AsciiText.h>
160 #include <X11/Xaw/Dialog.h>
161 #include <X11/Xaw/Form.h>
162 #include <X11/Xaw/List.h>
163 #include <X11/Xaw/Label.h>
164 #include <X11/Xaw/SimpleMenu.h>
165 #include <X11/Xaw/SmeBSB.h>
166 #include <X11/Xaw/SmeLine.h>
167 #include <X11/Xaw/Box.h>
168 #include <X11/Xaw/MenuButton.h>
169 #include <X11/Xaw/Text.h>
170 #include <X11/Xaw/AsciiText.h>
173 // [HGM] bitmaps: put before incuding the bitmaps / pixmaps, to know how many piece types there are.
178 #include "pixmaps/pixmaps.h"
179 #define IMAGE_EXT "xpm"
181 #define IMAGE_EXT "xim"
182 #include "bitmaps/bitmaps.h"
185 #include "bitmaps/icon_white.bm"
186 #include "bitmaps/icon_black.bm"
187 #include "bitmaps/checkmark.bm"
189 #include "frontend.h"
194 #include "xgamelist.h"
195 #include "xhistory.h"
196 #include "xedittags.h"
199 // must be moved to xengineoutput.h
201 void EngineOutputProc P((Widget w, XEvent *event,
202 String *prms, Cardinal *nprms));
204 void EngineOutputPopDown();
211 #define usleep(t) _sleep2(((t)+500)/1000)
215 # define _(s) gettext (s)
216 # define N_(s) gettext_noop (s)
232 int main P((int argc, char **argv));
233 RETSIGTYPE CmailSigHandler P((int sig));
234 RETSIGTYPE IntSigHandler P((int sig));
235 void CreateGCs P((void));
236 void CreateXIMPieces P((void));
237 void CreateXPMPieces P((void));
238 void CreatePieces P((void));
239 void CreatePieceMenus P((void));
240 Widget CreateMenuBar P((Menu *mb));
241 Widget CreateButtonBar P ((MenuItem *mi));
242 char *FindFont P((char *pattern, int targetPxlSize));
243 void PieceMenuPopup P((Widget w, XEvent *event,
244 String *params, Cardinal *num_params));
245 static void PieceMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
246 static void DropMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
247 void ReadBitmap P((Pixmap *pm, String name, unsigned char bits[],
248 u_int wreq, u_int hreq));
249 void CreateGrid P((void));
250 int EventToSquare P((int x, int limit));
251 void DrawSquare P((int row, int column, ChessSquare piece, int do_flash));
252 void EventProc P((Widget widget, caddr_t unused, XEvent *event));
253 void HandleUserMove P((Widget w, XEvent *event,
254 String *prms, Cardinal *nprms));
255 void AnimateUserMove P((Widget w, XEvent * event,
256 String * params, Cardinal * nParams));
257 void WhiteClock P((Widget w, XEvent *event,
258 String *prms, Cardinal *nprms));
259 void BlackClock P((Widget w, XEvent *event,
260 String *prms, Cardinal *nprms));
261 void DrawPositionProc P((Widget w, XEvent *event,
262 String *prms, Cardinal *nprms));
263 void XDrawPosition P((Widget w, /*Boolean*/int repaint,
265 void CommentPopUp P((char *title, char *label));
266 void CommentPopDown P((void));
267 void CommentCallback P((Widget w, XtPointer client_data,
268 XtPointer call_data));
269 void ICSInputBoxPopUp P((void));
270 void ICSInputBoxPopDown P((void));
271 void FileNamePopUp P((char *label, char *def,
272 FileProc proc, char *openMode));
273 void FileNamePopDown P((void));
274 void FileNameCallback P((Widget w, XtPointer client_data,
275 XtPointer call_data));
276 void FileNameAction P((Widget w, XEvent *event,
277 String *prms, Cardinal *nprms));
278 void AskQuestionReplyAction P((Widget w, XEvent *event,
279 String *prms, Cardinal *nprms));
280 void AskQuestionProc P((Widget w, XEvent *event,
281 String *prms, Cardinal *nprms));
282 void AskQuestionPopDown P((void));
283 void PromotionPopUp P((void));
284 void PromotionPopDown P((void));
285 void PromotionCallback P((Widget w, XtPointer client_data,
286 XtPointer call_data));
287 void EditCommentPopDown P((void));
288 void EditCommentCallback P((Widget w, XtPointer client_data,
289 XtPointer call_data));
290 void SelectCommand P((Widget w, XtPointer client_data, XtPointer call_data));
291 void ResetProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
292 void LoadGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
293 void LoadNextGameProc P((Widget w, XEvent *event, String *prms,
295 void LoadPrevGameProc P((Widget w, XEvent *event, String *prms,
297 void ReloadGameProc P((Widget w, XEvent *event, String *prms,
299 void LoadPositionProc P((Widget w, XEvent *event,
300 String *prms, Cardinal *nprms));
301 void LoadNextPositionProc P((Widget w, XEvent *event, String *prms,
303 void LoadPrevPositionProc P((Widget w, XEvent *event, String *prms,
305 void ReloadPositionProc P((Widget w, XEvent *event, String *prms,
307 void CopyPositionProc P((Widget w, XEvent *event, String *prms,
309 void PastePositionProc P((Widget w, XEvent *event, String *prms,
311 void CopyGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
312 void PasteGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
313 void SaveGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
314 void SavePositionProc P((Widget w, XEvent *event,
315 String *prms, Cardinal *nprms));
316 void MailMoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
317 void ReloadCmailMsgProc P((Widget w, XEvent *event, String *prms,
319 void QuitProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
320 void PauseProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
321 void MachineBlackProc P((Widget w, XEvent *event, String *prms,
323 void MachineWhiteProc P((Widget w, XEvent *event,
324 String *prms, Cardinal *nprms));
325 void AnalyzeModeProc P((Widget w, XEvent *event,
326 String *prms, Cardinal *nprms));
327 void AnalyzeFileProc P((Widget w, XEvent *event,
328 String *prms, Cardinal *nprms));
329 void TwoMachinesProc P((Widget w, XEvent *event, String *prms,
331 void IcsClientProc P((Widget w, XEvent *event, String *prms,
333 void EditGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
334 void EditPositionProc P((Widget w, XEvent *event,
335 String *prms, Cardinal *nprms));
336 void TrainingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
337 void EditCommentProc P((Widget w, XEvent *event,
338 String *prms, Cardinal *nprms));
339 void IcsInputBoxProc P((Widget w, XEvent *event,
340 String *prms, Cardinal *nprms));
341 void AcceptProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
342 void DeclineProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
343 void RematchProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
344 void CallFlagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
345 void DrawProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
346 void AbortProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
347 void AdjournProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
348 void ResignProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
349 void AdjuWhiteProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
350 void AdjuBlackProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
351 void AdjuDrawProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
352 void EnterKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
353 void StopObservingProc P((Widget w, XEvent *event, String *prms,
355 void StopExaminingProc P((Widget w, XEvent *event, String *prms,
357 void BackwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
358 void ForwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
359 void ToStartProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
360 void ToEndProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
361 void RevertProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
362 void TruncateGameProc P((Widget w, XEvent *event, String *prms,
364 void RetractMoveProc P((Widget w, XEvent *event, String *prms,
366 void MoveNowProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
367 void AlwaysQueenProc P((Widget w, XEvent *event, String *prms,
369 void AnimateDraggingProc P((Widget w, XEvent *event, String *prms,
371 void AnimateMovingProc P((Widget w, XEvent *event, String *prms,
373 void AutocommProc P((Widget w, XEvent *event, String *prms,
375 void AutoflagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
376 void AutoflipProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
377 void AutobsProc P((Widget w, XEvent *event, String *prms,
379 void AutoraiseProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
380 void AutosaveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
381 void BlindfoldProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
382 void FlashMovesProc P((Widget w, XEvent *event, String *prms,
384 void FlipViewProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
385 void GetMoveListProc P((Widget w, XEvent *event, String *prms,
387 void HighlightDraggingProc P((Widget w, XEvent *event, String *prms,
389 void HighlightLastMoveProc P((Widget w, XEvent *event, String *prms,
391 void MoveSoundProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
392 void IcsAlarmProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
393 void OldSaveStyleProc P((Widget w, XEvent *event, String *prms,
395 void PeriodicUpdatesProc P((Widget w, XEvent *event, String *prms,
397 void PonderNextMoveProc P((Widget w, XEvent *event, String *prms,
399 void PopupMoveErrorsProc P((Widget w, XEvent *event, String *prms,
401 void PopupExitMessageProc P((Widget w, XEvent *event, String *prms,
403 void PremoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
404 void QuietPlayProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
405 void ShowCoordsProc P((Widget w, XEvent *event, String *prms,
407 void ShowThinkingProc P((Widget w, XEvent *event, String *prms,
409 void HideThinkingProc P((Widget w, XEvent *event, String *prms,
411 void TestLegalityProc P((Widget w, XEvent *event, String *prms,
413 void InfoProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
414 void ManProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
415 void HintProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
416 void BookProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
417 void AboutGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
418 void AboutProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
419 void DebugProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
420 void NothingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
421 void Iconify P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
422 void DisplayMove P((int moveNumber));
423 void DisplayTitle P((char *title));
424 void ICSInitScript P((void));
425 int LoadGamePopUp P((FILE *f, int gameNumber, char *title));
426 void ErrorPopUp P((char *title, char *text, int modal));
427 void ErrorPopDown P((void));
428 static char *ExpandPathName P((char *path));
429 static void CreateAnimVars P((void));
430 static void DragPieceBegin P((int x, int y));
431 static void DragPieceMove P((int x, int y));
432 static void DragPieceEnd P((int x, int y));
433 static void DrawDragPiece P((void));
434 char *ModeToWidgetName P((GameMode mode));
435 void EngineOutputUpdate( FrontEndProgramStats * stats );
436 void ShuffleMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
437 void EngineMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
438 void UciMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
439 void TimeControlProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
440 void NewVariantProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
441 void FirstSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
442 void SecondSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
443 void ShufflePopDown P(());
444 void EnginePopDown P(());
445 void UciPopDown P(());
446 void TimeControlPopDown P(());
447 void NewVariantPopDown P(());
448 void SettingsPopDown P(());
450 * XBoard depends on Xt R4 or higher
452 int xtVersion = XtSpecificationRelease;
457 Pixel lightSquareColor, darkSquareColor, whitePieceColor, blackPieceColor,
458 jailSquareColor, highlightSquareColor, premoveHighlightColor;
459 Pixel lowTimeWarningColor;
460 GC lightSquareGC, darkSquareGC, jailSquareGC, lineGC, wdPieceGC, wlPieceGC,
461 bdPieceGC, blPieceGC, wbPieceGC, bwPieceGC, coordGC, highlineGC,
462 wjPieceGC, bjPieceGC, prelineGC, countGC;
463 Pixmap iconPixmap, wIconPixmap, bIconPixmap, xMarkPixmap;
464 Widget shellWidget, layoutWidget, formWidget, boardWidget, messageWidget,
465 whiteTimerWidget, blackTimerWidget, titleWidget, widgetList[16],
466 commentShell, promotionShell, whitePieceMenu, blackPieceMenu, dropMenu,
467 menuBarWidget, buttonBarWidget, editShell, errorShell, analysisShell,
468 ICSInputShell, fileNameShell, askQuestionShell;
469 XSegment gridSegments[(BOARD_SIZE + 1) * 2];
470 XSegment jailGridSegments[(BOARD_SIZE + 3) * 2];
471 Font clockFontID, coordFontID, countFontID;
472 XFontStruct *clockFontStruct, *coordFontStruct, *countFontStruct;
473 XtAppContext appContext;
475 char *oldICSInteractionTitle;
479 char installDir[] = "."; // [HGM] UCI: needed for UCI; probably needs run-time initializtion
481 Position commentX = -1, commentY = -1;
482 Dimension commentW, commentH;
484 int squareSize, smallLayout = 0, tinyLayout = 0,
485 marginW, marginH, // [HGM] for run-time resizing
486 fromX = -1, fromY = -1, toX, toY, commentUp = False, analysisUp = False,
487 ICSInputBoxUp = False, askQuestionUp = False,
488 filenameUp = False, promotionUp = False, pmFromX = -1, pmFromY = -1,
489 editUp = False, errorUp = False, errorExitStatus = -1, lineGap;
490 Pixel timerForegroundPixel, timerBackgroundPixel;
491 Pixel buttonForegroundPixel, buttonBackgroundPixel;
492 char *chessDir, *programName, *programVersion,
493 *gameCopyFilename, *gamePasteFilename;
497 Pixmap pieceBitmap[2][(int)BlackPawn];
498 Pixmap pieceBitmap2[2][(int)BlackPawn+4]; /* [HGM] pieces */
499 Pixmap xpmPieceBitmap[4][(int)BlackPawn]; /* LL, LD, DL, DD actually used*/
500 Pixmap xpmPieceBitmap2[4][(int)BlackPawn+4]; /* LL, LD, DL, DD set to select from */
501 Pixmap xpmLightSquare, xpmDarkSquare, xpmJailSquare;
502 int useImages, useImageSqs;
503 XImage *ximPieceBitmap[4][(int)BlackPawn+4]; /* LL, LD, DL, DD */
504 Pixmap ximMaskPm[(int)BlackPawn]; /* clipmasks, used for XIM pieces */
505 Pixmap ximMaskPm2[(int)BlackPawn+4]; /* clipmasks, used for XIM pieces */
506 XImage *ximLightSquare, *ximDarkSquare;
509 #define pieceToSolid(piece) &pieceBitmap[SOLID][(piece) % (int)BlackPawn]
510 #define pieceToOutline(piece) &pieceBitmap[OUTLINE][(piece) % (int)BlackPawn]
512 #define White(piece) ((int)(piece) < (int)BlackPawn)
514 /* Variables for doing smooth animation. This whole thing
515 would be much easier if the board was double-buffered,
516 but that would require a fairly major rewrite. */
521 GC blitGC, pieceGC, outlineGC;
522 XPoint startSquare, prevFrame, mouseDelta;
526 int startBoardX, startBoardY;
529 /* There can be two pieces being animated at once: a player
530 can begin dragging a piece before the remote opponent has moved. */
532 static AnimState game, player;
534 /* Bitmaps for use as masks when drawing XPM pieces.
535 Need one for each black and white piece. */
536 static Pixmap xpmMask[BlackKing + 1];
538 /* This magic number is the number of intermediate frames used
539 in each half of the animation. For short moves it's reduced
540 by 1. The total number of frames will be factor * 2 + 1. */
543 SizeDefaults sizeDefaults[] = SIZE_DEFAULTS;
545 MenuItem fileMenu[] = {
546 {N_("New Game"), ResetProc},
547 {N_("New Shuffle Game ..."), ShuffleMenuProc},
548 {N_("New Variant ..."), NewVariantProc}, // [HGM] variant: not functional yet
549 {"----", NothingProc},
550 {N_("Load Game"), LoadGameProc},
551 {N_("Load Next Game"), LoadNextGameProc},
552 {N_("Load Previous Game"), LoadPrevGameProc},
553 {N_("Reload Same Game"), ReloadGameProc},
554 {N_("Save Game"), SaveGameProc},
555 {"----", NothingProc},
556 {N_("Copy Game"), CopyGameProc},
557 {N_("Paste Game"), PasteGameProc},
558 {"----", NothingProc},
559 {N_("Load Position"), LoadPositionProc},
560 {N_("Load Next Position"), LoadNextPositionProc},
561 {N_("Load Previous Position"), LoadPrevPositionProc},
562 {N_("Reload Same Position"), ReloadPositionProc},
563 {N_("Save Position"), SavePositionProc},
564 {"----", NothingProc},
565 {N_("Copy Position"), CopyPositionProc},
566 {N_("Paste Position"), PastePositionProc},
567 {"----", NothingProc},
568 {N_("Mail Move"), MailMoveProc},
569 {N_("Reload CMail Message"), ReloadCmailMsgProc},
570 {"----", NothingProc},
571 {N_("Exit"), QuitProc},
575 MenuItem modeMenu[] = {
576 {N_("Machine White"), MachineWhiteProc},
577 {N_("Machine Black"), MachineBlackProc},
578 {N_("Two Machines"), TwoMachinesProc},
579 {N_("Analysis Mode"), AnalyzeModeProc},
580 {N_("Analyze File"), AnalyzeFileProc },
581 {N_("ICS Client"), IcsClientProc},
582 {N_("Edit Game"), EditGameProc},
583 {N_("Edit Position"), EditPositionProc},
584 {N_("Training"), TrainingProc},
585 {"----", NothingProc},
586 {N_("Show Engine Output"), EngineOutputProc},
587 {N_("Show Evaluation Graph"), NothingProc}, // [HGM] evalgr: not functional yet
588 {N_("Show Game List"), ShowGameListProc},
589 {"Show Move History", HistoryShowProc}, // [HGM] hist: activate 4.2.7 code
590 {"----", NothingProc},
591 {N_("Edit Tags"), EditTagsProc},
592 {N_("Edit Comment"), EditCommentProc},
593 {N_("ICS Input Box"), IcsInputBoxProc},
594 {N_("Pause"), PauseProc},
598 MenuItem actionMenu[] = {
599 {N_("Accept"), AcceptProc},
600 {N_("Decline"), DeclineProc},
601 {N_("Rematch"), RematchProc},
602 {"----", NothingProc},
603 {N_("Call Flag"), CallFlagProc},
604 {N_("Draw"), DrawProc},
605 {N_("Adjourn"), AdjournProc},
606 {N_("Abort"), AbortProc},
607 {N_("Resign"), ResignProc},
608 {"----", NothingProc},
609 {N_("Stop Observing"), StopObservingProc},
610 {N_("Stop Examining"), StopExaminingProc},
611 {"----", NothingProc},
612 {N_("Adjudicate to White"), AdjuWhiteProc},
613 {N_("Adjudicate to Black"), AdjuBlackProc},
614 {N_("Adjudicate Draw"), AdjuDrawProc},
618 MenuItem stepMenu[] = {
619 {N_("Backward"), BackwardProc},
620 {N_("Forward"), ForwardProc},
621 {N_("Back to Start"), ToStartProc},
622 {N_("Forward to End"), ToEndProc},
623 {N_("Revert"), RevertProc},
624 {N_("Truncate Game"), TruncateGameProc},
625 {"----", NothingProc},
626 {N_("Move Now"), MoveNowProc},
627 {N_("Retract Move"), RetractMoveProc},
631 MenuItem optionsMenu[] = {
632 {N_("Flip View"), FlipViewProc},
633 {"----", NothingProc},
634 {N_("Adjudications ..."), EngineMenuProc},
635 {N_("General Settings ..."), UciMenuProc},
636 {N_("Engine #1 Settings ..."), FirstSettingsProc},
637 {N_("Engine #2 Settings ..."), SecondSettingsProc},
638 {N_("Time Control ..."), TimeControlProc},
639 {"----", NothingProc},
640 {N_("Always Queen"), AlwaysQueenProc},
641 {N_("Animate Dragging"), AnimateDraggingProc},
642 {N_("Animate Moving"), AnimateMovingProc},
643 {N_("Auto Comment"), AutocommProc},
644 {N_("Auto Flag"), AutoflagProc},
645 {N_("Auto Flip View"), AutoflipProc},
646 {N_("Auto Observe"), AutobsProc},
647 {N_("Auto Raise Board"), AutoraiseProc},
648 {N_("Auto Save"), AutosaveProc},
649 {N_("Blindfold"), BlindfoldProc},
650 {N_("Flash Moves"), FlashMovesProc},
651 {N_("Get Move List"), GetMoveListProc},
653 {N_("Highlight Dragging"), HighlightDraggingProc},
655 {N_("Highlight Last Move"), HighlightLastMoveProc},
656 {N_("Move Sound"), MoveSoundProc},
657 {N_("ICS Alarm"), IcsAlarmProc},
658 {N_("Old Save Style"), OldSaveStyleProc},
659 {N_("Periodic Updates"), PeriodicUpdatesProc},
660 {N_("Ponder Next Move"), PonderNextMoveProc},
661 {N_("Popup Exit Message"), PopupExitMessageProc},
662 {N_("Popup Move Errors"), PopupMoveErrorsProc},
663 {N_("Premove"), PremoveProc},
664 {N_("Quiet Play"), QuietPlayProc},
665 {N_("Show Coords"), ShowCoordsProc},
666 {N_("Hide Thinking"), HideThinkingProc},
667 {N_("Test Legality"), TestLegalityProc},
671 MenuItem helpMenu[] = {
672 {N_("Info XBoard"), InfoProc},
673 {N_("Man XBoard"), ManProc},
674 {"----", NothingProc},
675 {N_("Hint"), HintProc},
676 {N_("Book"), BookProc},
677 {"----", NothingProc},
678 {N_("About XBoard"), AboutProc},
683 {N_("File"), fileMenu},
684 {N_("Mode"), modeMenu},
685 {N_("Action"), actionMenu},
686 {N_("Step"), stepMenu},
687 {N_("Options"), optionsMenu},
688 {N_("Help"), helpMenu},
692 #define PAUSE_BUTTON N_("P")
693 MenuItem buttonBar[] = {
696 {PAUSE_BUTTON, PauseProc},
702 #define PIECE_MENU_SIZE 18
703 String pieceMenuStrings[2][PIECE_MENU_SIZE] = {
704 { N_("White"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
705 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
706 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
707 N_("Empty square"), N_("Clear board") },
708 { N_("Black"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
709 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
710 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
711 N_("Empty square"), N_("Clear board") }
713 /* must be in same order as PieceMenuStrings! */
714 ChessSquare pieceMenuTranslation[2][PIECE_MENU_SIZE] = {
715 { WhitePlay, (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
716 WhiteRook, WhiteQueen, WhiteKing, (ChessSquare) 0, WhiteAlfil,
717 WhiteCannon, WhiteAngel, WhiteMarshall, (ChessSquare) 0,
718 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
719 { BlackPlay, (ChessSquare) 0, BlackPawn, BlackKnight, BlackBishop,
720 BlackRook, BlackQueen, BlackKing, (ChessSquare) 0, BlackAlfil,
721 BlackCannon, BlackAngel, BlackMarshall, (ChessSquare) 0,
722 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
725 #define DROP_MENU_SIZE 6
726 String dropMenuStrings[DROP_MENU_SIZE] = {
727 "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"), N_("Queen")
729 /* must be in same order as PieceMenuStrings! */
730 ChessSquare dropMenuTranslation[DROP_MENU_SIZE] = {
731 (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
732 WhiteRook, WhiteQueen
740 DropMenuEnables dmEnables[] = {
758 { XtNborderWidth, 0 },
759 { XtNdefaultDistance, 0 },
763 { XtNborderWidth, 0 },
764 { XtNresizable, (XtArgVal) True },
768 { XtNborderWidth, 0 },
774 { XtNjustify, (XtArgVal) XtJustifyRight },
775 { XtNlabel, (XtArgVal) "..." },
776 { XtNresizable, (XtArgVal) True },
777 { XtNresize, (XtArgVal) False }
780 Arg messageArgs[] = {
781 { XtNjustify, (XtArgVal) XtJustifyLeft },
782 { XtNlabel, (XtArgVal) "..." },
783 { XtNresizable, (XtArgVal) True },
784 { XtNresize, (XtArgVal) False }
788 { XtNborderWidth, 0 },
789 { XtNjustify, (XtArgVal) XtJustifyLeft }
792 XtResource clientResources[] = {
793 { "whitePieceColor", "whitePieceColor", XtRString, sizeof(String),
794 XtOffset(AppDataPtr, whitePieceColor), XtRString,
796 { "blackPieceColor", "blackPieceColor", XtRString, sizeof(String),
797 XtOffset(AppDataPtr, blackPieceColor), XtRString,
799 { "lightSquareColor", "lightSquareColor", XtRString,
800 sizeof(String), XtOffset(AppDataPtr, lightSquareColor),
801 XtRString, LIGHT_SQUARE_COLOR },
802 { "darkSquareColor", "darkSquareColor", XtRString, sizeof(String),
803 XtOffset(AppDataPtr, darkSquareColor), XtRString,
805 { "highlightSquareColor", "highlightSquareColor", XtRString,
806 sizeof(String), XtOffset(AppDataPtr, highlightSquareColor),
807 XtRString, HIGHLIGHT_SQUARE_COLOR },
808 { "premoveHighlightColor", "premoveHighlightColor", XtRString,
809 sizeof(String), XtOffset(AppDataPtr, premoveHighlightColor),
810 XtRString, PREMOVE_HIGHLIGHT_COLOR },
811 { "movesPerSession", "movesPerSession", XtRInt, sizeof(int),
812 XtOffset(AppDataPtr, movesPerSession), XtRImmediate,
813 (XtPointer) MOVES_PER_SESSION },
814 { "timeIncrement", "timeIncrement", XtRInt, sizeof(int),
815 XtOffset(AppDataPtr, timeIncrement), XtRImmediate,
816 (XtPointer) TIME_INCREMENT },
817 { "initString", "initString", XtRString, sizeof(String),
818 XtOffset(AppDataPtr, initString), XtRString, INIT_STRING },
819 { "secondInitString", "secondInitString", XtRString, sizeof(String),
820 XtOffset(AppDataPtr, secondInitString), XtRString, INIT_STRING },
821 { "firstComputerString", "firstComputerString", XtRString,
822 sizeof(String), XtOffset(AppDataPtr, firstComputerString), XtRString,
824 { "secondComputerString", "secondComputerString", XtRString,
825 sizeof(String), XtOffset(AppDataPtr, secondComputerString), XtRString,
827 { "firstChessProgram", "firstChessProgram", XtRString,
828 sizeof(String), XtOffset(AppDataPtr, firstChessProgram),
829 XtRString, FIRST_CHESS_PROGRAM },
830 { "secondChessProgram", "secondChessProgram", XtRString,
831 sizeof(String), XtOffset(AppDataPtr, secondChessProgram),
832 XtRString, SECOND_CHESS_PROGRAM },
833 { "firstPlaysBlack", "firstPlaysBlack", XtRBoolean,
834 sizeof(Boolean), XtOffset(AppDataPtr, firstPlaysBlack),
835 XtRImmediate, (XtPointer) False },
836 { "noChessProgram", "noChessProgram", XtRBoolean,
837 sizeof(Boolean), XtOffset(AppDataPtr, noChessProgram),
838 XtRImmediate, (XtPointer) False },
839 { "firstHost", "firstHost", XtRString, sizeof(String),
840 XtOffset(AppDataPtr, firstHost), XtRString, FIRST_HOST },
841 { "secondHost", "secondHost", XtRString, sizeof(String),
842 XtOffset(AppDataPtr, secondHost), XtRString, SECOND_HOST },
843 { "firstDirectory", "firstDirectory", XtRString, sizeof(String),
844 XtOffset(AppDataPtr, firstDirectory), XtRString, "." },
845 { "secondDirectory", "secondDirectory", XtRString, sizeof(String),
846 XtOffset(AppDataPtr, secondDirectory), XtRString, "." },
847 { "bitmapDirectory", "bitmapDirectory", XtRString,
848 sizeof(String), XtOffset(AppDataPtr, bitmapDirectory),
850 { "remoteShell", "remoteShell", XtRString, sizeof(String),
851 XtOffset(AppDataPtr, remoteShell), XtRString, REMOTE_SHELL },
852 { "remoteUser", "remoteUser", XtRString, sizeof(String),
853 XtOffset(AppDataPtr, remoteUser), XtRString, "" },
854 { "timeDelay", "timeDelay", XtRFloat, sizeof(float),
855 XtOffset(AppDataPtr, timeDelay), XtRString,
856 (XtPointer) TIME_DELAY_QUOTE },
857 { "timeControl", "timeControl", XtRString, sizeof(String),
858 XtOffset(AppDataPtr, timeControl), XtRString,
859 (XtPointer) TIME_CONTROL },
860 { "internetChessServerMode", "internetChessServerMode",
861 XtRBoolean, sizeof(Boolean),
862 XtOffset(AppDataPtr, icsActive), XtRImmediate,
864 { "internetChessServerHost", "internetChessServerHost",
865 XtRString, sizeof(String),
866 XtOffset(AppDataPtr, icsHost),
867 XtRString, (XtPointer) ICS_HOST },
868 { "internetChessServerPort", "internetChessServerPort",
869 XtRString, sizeof(String),
870 XtOffset(AppDataPtr, icsPort), XtRString,
871 (XtPointer) ICS_PORT },
872 { "internetChessServerCommPort", "internetChessServerCommPort",
873 XtRString, sizeof(String),
874 XtOffset(AppDataPtr, icsCommPort), XtRString,
876 { "internetChessServerLogonScript", "internetChessServerLogonScript",
877 XtRString, sizeof(String),
878 XtOffset(AppDataPtr, icsLogon), XtRString,
880 { "internetChessServerHelper", "internetChessServerHelper",
881 XtRString, sizeof(String),
882 XtOffset(AppDataPtr, icsHelper), XtRString, "" },
883 { "internetChessServerInputBox", "internetChessServerInputBox",
884 XtRBoolean, sizeof(Boolean),
885 XtOffset(AppDataPtr, icsInputBox), XtRImmediate,
887 { "icsAlarm", "icsAlarm",
888 XtRBoolean, sizeof(Boolean),
889 XtOffset(AppDataPtr, icsAlarm), XtRImmediate,
891 { "icsAlarmTime", "icsAlarmTime",
893 XtOffset(AppDataPtr, icsAlarmTime), XtRImmediate,
895 { "useTelnet", "useTelnet", XtRBoolean, sizeof(Boolean),
896 XtOffset(AppDataPtr, useTelnet), XtRImmediate,
898 { "telnetProgram", "telnetProgram", XtRString, sizeof(String),
899 XtOffset(AppDataPtr, telnetProgram), XtRString, TELNET_PROGRAM },
900 { "gateway", "gateway", XtRString, sizeof(String),
901 XtOffset(AppDataPtr, gateway), XtRString, "" },
902 { "loadGameFile", "loadGameFile", XtRString, sizeof(String),
903 XtOffset(AppDataPtr, loadGameFile), XtRString, "" },
904 { "loadGameIndex", "loadGameIndex",
906 XtOffset(AppDataPtr, loadGameIndex), XtRImmediate,
908 { "saveGameFile", "saveGameFile", XtRString, sizeof(String),
909 XtOffset(AppDataPtr, saveGameFile), XtRString, "" },
910 { "autoRaiseBoard", "autoRaiseBoard", XtRBoolean,
911 sizeof(Boolean), XtOffset(AppDataPtr, autoRaiseBoard),
912 XtRImmediate, (XtPointer) True },
913 { "autoSaveGames", "autoSaveGames", XtRBoolean,
914 sizeof(Boolean), XtOffset(AppDataPtr, autoSaveGames),
915 XtRImmediate, (XtPointer) False },
916 { "blindfold", "blindfold", XtRBoolean,
917 sizeof(Boolean), XtOffset(AppDataPtr, blindfold),
918 XtRImmediate, (XtPointer) False },
919 { "loadPositionFile", "loadPositionFile", XtRString,
920 sizeof(String), XtOffset(AppDataPtr, loadPositionFile),
922 { "loadPositionIndex", "loadPositionIndex",
924 XtOffset(AppDataPtr, loadPositionIndex), XtRImmediate,
926 { "savePositionFile", "savePositionFile", XtRString,
927 sizeof(String), XtOffset(AppDataPtr, savePositionFile),
929 { "matchMode", "matchMode", XtRBoolean, sizeof(Boolean),
930 XtOffset(AppDataPtr, matchMode), XtRImmediate, (XtPointer) False },
931 { "matchGames", "matchGames", XtRInt, sizeof(int),
932 XtOffset(AppDataPtr, matchGames), XtRImmediate,
934 { "monoMode", "monoMode", XtRBoolean, sizeof(Boolean),
935 XtOffset(AppDataPtr, monoMode), XtRImmediate,
937 { "debugMode", "debugMode", XtRBoolean, sizeof(Boolean),
938 XtOffset(AppDataPtr, debugMode), XtRImmediate,
940 { "clockMode", "clockMode", XtRBoolean, sizeof(Boolean),
941 XtOffset(AppDataPtr, clockMode), XtRImmediate,
943 { "boardSize", "boardSize", XtRString, sizeof(String),
944 XtOffset(AppDataPtr, boardSize), XtRString, "" },
945 { "searchTime", "searchTime", XtRString, sizeof(String),
946 XtOffset(AppDataPtr, searchTime), XtRString,
948 { "searchDepth", "searchDepth", XtRInt, sizeof(int),
949 XtOffset(AppDataPtr, searchDepth), XtRImmediate,
951 { "showCoords", "showCoords", XtRBoolean, sizeof(Boolean),
952 XtOffset(AppDataPtr, showCoords), XtRImmediate,
954 { "showJail", "showJail", XtRInt, sizeof(int),
955 XtOffset(AppDataPtr, showJail), XtRImmediate,
957 { "showThinking", "showThinking", XtRBoolean, sizeof(Boolean),
958 XtOffset(AppDataPtr, showThinking), XtRImmediate,
960 { "ponderNextMove", "ponderNextMove", XtRBoolean, sizeof(Boolean),
961 XtOffset(AppDataPtr, ponderNextMove), XtRImmediate,
963 { "periodicUpdates", "periodicUpdates", XtRBoolean, sizeof(Boolean),
964 XtOffset(AppDataPtr, periodicUpdates), XtRImmediate,
966 { "clockFont", "clockFont", XtRString, sizeof(String),
967 XtOffset(AppDataPtr, clockFont), XtRString, CLOCK_FONT },
968 { "coordFont", "coordFont", XtRString, sizeof(String),
969 XtOffset(AppDataPtr, coordFont), XtRString, COORD_FONT },
970 { "font", "font", XtRString, sizeof(String),
971 XtOffset(AppDataPtr, font), XtRString, DEFAULT_FONT },
972 { "ringBellAfterMoves", "ringBellAfterMoves",
973 XtRBoolean, sizeof(Boolean),
974 XtOffset(AppDataPtr, ringBellAfterMoves),
975 XtRImmediate, (XtPointer) False },
976 { "autoCallFlag", "autoCallFlag", XtRBoolean,
977 sizeof(Boolean), XtOffset(AppDataPtr, autoCallFlag),
978 XtRImmediate, (XtPointer) False },
979 { "autoFlipView", "autoFlipView", XtRBoolean,
980 sizeof(Boolean), XtOffset(AppDataPtr, autoFlipView),
981 XtRImmediate, (XtPointer) True },
982 { "autoObserve", "autoObserve", XtRBoolean,
983 sizeof(Boolean), XtOffset(AppDataPtr, autoObserve),
984 XtRImmediate, (XtPointer) False },
985 { "autoComment", "autoComment", XtRBoolean,
986 sizeof(Boolean), XtOffset(AppDataPtr, autoComment),
987 XtRImmediate, (XtPointer) False },
988 { "getMoveList", "getMoveList", XtRBoolean,
989 sizeof(Boolean), XtOffset(AppDataPtr, getMoveList),
990 XtRImmediate, (XtPointer) True },
992 { "highlightDragging", "highlightDragging", XtRBoolean,
993 sizeof(Boolean), XtOffset(AppDataPtr, highlightDragging),
994 XtRImmediate, (XtPointer) False },
996 { "highlightLastMove", "highlightLastMove", XtRBoolean,
997 sizeof(Boolean), XtOffset(AppDataPtr, highlightLastMove),
998 XtRImmediate, (XtPointer) False },
999 { "premove", "premove", XtRBoolean,
1000 sizeof(Boolean), XtOffset(AppDataPtr, premove),
1001 XtRImmediate, (XtPointer) True },
1002 { "testLegality", "testLegality", XtRBoolean,
1003 sizeof(Boolean), XtOffset(AppDataPtr, testLegality),
1004 XtRImmediate, (XtPointer) True },
1005 { "flipView", "flipView", XtRBoolean,
1006 sizeof(Boolean), XtOffset(AppDataPtr, flipView),
1007 XtRImmediate, (XtPointer) False },
1008 { "cmail", "cmailGameName", XtRString, sizeof(String),
1009 XtOffset(AppDataPtr, cmailGameName), XtRString, "" },
1010 { "alwaysPromoteToQueen", "alwaysPromoteToQueen", XtRBoolean,
1011 sizeof(Boolean), XtOffset(AppDataPtr, alwaysPromoteToQueen),
1012 XtRImmediate, (XtPointer) False },
1013 { "oldSaveStyle", "oldSaveStyle", XtRBoolean,
1014 sizeof(Boolean), XtOffset(AppDataPtr, oldSaveStyle),
1015 XtRImmediate, (XtPointer) False },
1016 { "quietPlay", "quietPlay", XtRBoolean,
1017 sizeof(Boolean), XtOffset(AppDataPtr, quietPlay),
1018 XtRImmediate, (XtPointer) False },
1019 { "titleInWindow", "titleInWindow", XtRBoolean,
1020 sizeof(Boolean), XtOffset(AppDataPtr, titleInWindow),
1021 XtRImmediate, (XtPointer) False },
1022 { "localLineEditing", "localLineEditing", XtRBoolean,
1023 sizeof(Boolean), XtOffset(AppDataPtr, localLineEditing),
1024 XtRImmediate, (XtPointer) True }, /* not implemented, must be True */
1026 { "zippyTalk", "zippyTalk", XtRBoolean,
1027 sizeof(Boolean), XtOffset(AppDataPtr, zippyTalk),
1028 XtRImmediate, (XtPointer) ZIPPY_TALK },
1029 { "zippyPlay", "zippyPlay", XtRBoolean,
1030 sizeof(Boolean), XtOffset(AppDataPtr, zippyPlay),
1031 XtRImmediate, (XtPointer) ZIPPY_PLAY },
1032 { "zippyLines", "zippyLines", XtRString, sizeof(String),
1033 XtOffset(AppDataPtr, zippyLines), XtRString, ZIPPY_LINES },
1034 { "zippyPinhead", "zippyPinhead", XtRString, sizeof(String),
1035 XtOffset(AppDataPtr, zippyPinhead), XtRString, ZIPPY_PINHEAD },
1036 { "zippyPassword", "zippyPassword", XtRString, sizeof(String),
1037 XtOffset(AppDataPtr, zippyPassword), XtRString, ZIPPY_PASSWORD },
1038 { "zippyPassword2", "zippyPassword2", XtRString, sizeof(String),
1039 XtOffset(AppDataPtr, zippyPassword2), XtRString, ZIPPY_PASSWORD2 },
1040 { "zippyWrongPassword", "zippyWrongPassword", XtRString, sizeof(String),
1041 XtOffset(AppDataPtr, zippyWrongPassword), XtRString,
1042 ZIPPY_WRONG_PASSWORD },
1043 { "zippyAcceptOnly", "zippyAcceptOnly", XtRString, sizeof(String),
1044 XtOffset(AppDataPtr, zippyAcceptOnly), XtRString, ZIPPY_ACCEPT_ONLY },
1045 { "zippyUseI", "zippyUseI", XtRBoolean,
1046 sizeof(Boolean), XtOffset(AppDataPtr, zippyUseI),
1047 XtRImmediate, (XtPointer) ZIPPY_USE_I },
1048 { "zippyBughouse", "zippyBughouse", XtRInt,
1049 sizeof(int), XtOffset(AppDataPtr, zippyBughouse),
1050 XtRImmediate, (XtPointer) ZIPPY_BUGHOUSE },
1051 { "zippyNoplayCrafty", "zippyNoplayCrafty", XtRBoolean,
1052 sizeof(Boolean), XtOffset(AppDataPtr, zippyNoplayCrafty),
1053 XtRImmediate, (XtPointer) ZIPPY_NOPLAY_CRAFTY },
1054 { "zippyGameEnd", "zippyGameEnd", XtRString, sizeof(String),
1055 XtOffset(AppDataPtr, zippyGameEnd), XtRString, ZIPPY_GAME_END },
1056 { "zippyGameStart", "zippyGameStart", XtRString, sizeof(String),
1057 XtOffset(AppDataPtr, zippyGameStart), XtRString, ZIPPY_GAME_START },
1058 { "zippyAdjourn", "zippyAdjourn", XtRBoolean,
1059 sizeof(Boolean), XtOffset(AppDataPtr, zippyAdjourn),
1060 XtRImmediate, (XtPointer) ZIPPY_ADJOURN },
1061 { "zippyAbort", "zippyAbort", XtRBoolean,
1062 sizeof(Boolean), XtOffset(AppDataPtr, zippyAbort),
1063 XtRImmediate, (XtPointer) ZIPPY_ABORT },
1064 { "zippyVariants", "zippyVariants", XtRString, sizeof(String),
1065 XtOffset(AppDataPtr, zippyVariants), XtRString, ZIPPY_VARIANTS },
1066 { "zippyMaxGames", "zippyMaxGames", XtRInt, sizeof(int),
1067 XtOffset(AppDataPtr, zippyMaxGames), XtRImmediate,
1068 (XtPointer) ZIPPY_MAX_GAMES },
1069 { "zippyReplayTimeout", "zippyReplayTimeout", XtRInt, sizeof(int),
1070 XtOffset(AppDataPtr, zippyReplayTimeout), XtRImmediate,
1071 (XtPointer) ZIPPY_REPLAY_TIMEOUT },
1072 { "zippyShortGame", "zippyShortGame", XtRInt, sizeof(int),
1073 XtOffset(AppDataPtr, zippyShortGame), XtRImmediate,
1076 { "flashCount", "flashCount", XtRInt, sizeof(int),
1077 XtOffset(AppDataPtr, flashCount), XtRImmediate,
1078 (XtPointer) FLASH_COUNT },
1079 { "flashRate", "flashRate", XtRInt, sizeof(int),
1080 XtOffset(AppDataPtr, flashRate), XtRImmediate,
1081 (XtPointer) FLASH_RATE },
1082 { "pixmapDirectory", "pixmapDirectory", XtRString,
1083 sizeof(String), XtOffset(AppDataPtr, pixmapDirectory),
1085 { "msLoginDelay", "msLoginDelay", XtRInt, sizeof(int),
1086 XtOffset(AppDataPtr, msLoginDelay), XtRImmediate,
1087 (XtPointer) MS_LOGIN_DELAY },
1088 { "colorizeMessages", "colorizeMessages", XtRBoolean,
1089 sizeof(Boolean), XtOffset(AppDataPtr, colorize),
1090 XtRImmediate, (XtPointer) False },
1091 { "colorShout", "colorShout", XtRString,
1092 sizeof(String), XtOffset(AppDataPtr, colorShout),
1093 XtRString, COLOR_SHOUT },
1094 { "colorSShout", "colorSShout", XtRString,
1095 sizeof(String), XtOffset(AppDataPtr, colorSShout),
1096 XtRString, COLOR_SSHOUT },
1097 { "colorChannel1", "colorChannel1", XtRString,
1098 sizeof(String), XtOffset(AppDataPtr, colorChannel1),
1099 XtRString, COLOR_CHANNEL1 },
1100 { "colorChannel", "colorChannel", XtRString,
1101 sizeof(String), XtOffset(AppDataPtr, colorChannel),
1102 XtRString, COLOR_CHANNEL },
1103 { "colorKibitz", "colorKibitz", XtRString,
1104 sizeof(String), XtOffset(AppDataPtr, colorKibitz),
1105 XtRString, COLOR_KIBITZ },
1106 { "colorTell", "colorTell", XtRString,
1107 sizeof(String), XtOffset(AppDataPtr, colorTell),
1108 XtRString, COLOR_TELL },
1109 { "colorChallenge", "colorChallenge", XtRString,
1110 sizeof(String), XtOffset(AppDataPtr, colorChallenge),
1111 XtRString, COLOR_CHALLENGE },
1112 { "colorRequest", "colorRequest", XtRString,
1113 sizeof(String), XtOffset(AppDataPtr, colorRequest),
1114 XtRString, COLOR_REQUEST },
1115 { "colorSeek", "colorSeek", XtRString,
1116 sizeof(String), XtOffset(AppDataPtr, colorSeek),
1117 XtRString, COLOR_SEEK },
1118 { "colorNormal", "colorNormal", XtRString,
1119 sizeof(String), XtOffset(AppDataPtr, colorNormal),
1120 XtRString, COLOR_NORMAL },
1121 { "soundProgram", "soundProgram", XtRString,
1122 sizeof(String), XtOffset(AppDataPtr, soundProgram),
1123 XtRString, "play" },
1124 { "soundShout", "soundShout", XtRString,
1125 sizeof(String), XtOffset(AppDataPtr, soundShout),
1127 { "soundSShout", "soundSShout", XtRString,
1128 sizeof(String), XtOffset(AppDataPtr, soundSShout),
1130 { "soundChannel1", "soundChannel1", XtRString,
1131 sizeof(String), XtOffset(AppDataPtr, soundChannel1),
1133 { "soundChannel", "soundChannel", XtRString,
1134 sizeof(String), XtOffset(AppDataPtr, soundChannel),
1136 { "soundKibitz", "soundKibitz", XtRString,
1137 sizeof(String), XtOffset(AppDataPtr, soundKibitz),
1139 { "soundTell", "soundTell", XtRString,
1140 sizeof(String), XtOffset(AppDataPtr, soundTell),
1142 { "soundChallenge", "soundChallenge", XtRString,
1143 sizeof(String), XtOffset(AppDataPtr, soundChallenge),
1145 { "soundRequest", "soundRequest", XtRString,
1146 sizeof(String), XtOffset(AppDataPtr, soundRequest),
1148 { "soundSeek", "soundSeek", XtRString,
1149 sizeof(String), XtOffset(AppDataPtr, soundSeek),
1151 { "soundMove", "soundMove", XtRString,
1152 sizeof(String), XtOffset(AppDataPtr, soundMove),
1154 { "soundIcsWin", "soundIcsWin", XtRString,
1155 sizeof(String), XtOffset(AppDataPtr, soundIcsWin),
1157 { "soundIcsLoss", "soundIcsLoss", XtRString,
1158 sizeof(String), XtOffset(AppDataPtr, soundIcsLoss),
1160 { "soundIcsDraw", "soundIcsDraw", XtRString,
1161 sizeof(String), XtOffset(AppDataPtr, soundIcsDraw),
1163 { "soundIcsUnfinished", "soundIcsUnfinished", XtRString,
1164 sizeof(String), XtOffset(AppDataPtr, soundIcsUnfinished),
1166 { "soundIcsAlarm", "soundIcsAlarm", XtRString,
1167 sizeof(String), XtOffset(AppDataPtr, soundIcsAlarm),
1169 { "reuseFirst", "reuseFirst", XtRBoolean,
1170 sizeof(Boolean), XtOffset(AppDataPtr, reuseFirst),
1171 XtRImmediate, (XtPointer) True },
1172 { "reuseSecond", "reuseSecond", XtRBoolean,
1173 sizeof(Boolean), XtOffset(AppDataPtr, reuseSecond),
1174 XtRImmediate, (XtPointer) True },
1175 { "animateDragging", "animateDragging", XtRBoolean,
1176 sizeof(Boolean), XtOffset(AppDataPtr, animateDragging),
1177 XtRImmediate, (XtPointer) True },
1178 { "animateMoving", "animateMoving", XtRBoolean,
1179 sizeof(Boolean), XtOffset(AppDataPtr, animate),
1180 XtRImmediate, (XtPointer) True },
1181 { "animateSpeed", "animateSpeed", XtRInt,
1182 sizeof(int), XtOffset(AppDataPtr, animSpeed),
1183 XtRImmediate, (XtPointer)10 },
1184 { "popupExitMessage", "popupExitMessage", XtRBoolean,
1185 sizeof(Boolean), XtOffset(AppDataPtr, popupExitMessage),
1186 XtRImmediate, (XtPointer) True },
1187 { "popupMoveErrors", "popupMoveErrors", XtRBoolean,
1188 sizeof(Boolean), XtOffset(AppDataPtr, popupMoveErrors),
1189 XtRImmediate, (XtPointer) False },
1190 { "fontSizeTolerance", "fontSizeTolerance", XtRInt,
1191 sizeof(int), XtOffset(AppDataPtr, fontSizeTolerance),
1192 XtRImmediate, (XtPointer)4 },
1193 { "initialMode", "initialMode", XtRString,
1194 sizeof(String), XtOffset(AppDataPtr, initialMode),
1195 XtRImmediate, (XtPointer) "" },
1196 { "variant", "variant", XtRString,
1197 sizeof(String), XtOffset(AppDataPtr, variant),
1198 XtRImmediate, (XtPointer) "normal" },
1199 { "firstProtocolVersion", "firstProtocolVersion", XtRInt,
1200 sizeof(int), XtOffset(AppDataPtr, firstProtocolVersion),
1201 XtRImmediate, (XtPointer)PROTOVER },
1202 { "secondProtocolVersion", "secondProtocolVersion", XtRInt,
1203 sizeof(int), XtOffset(AppDataPtr, secondProtocolVersion),
1204 XtRImmediate, (XtPointer)PROTOVER },
1205 { "showButtonBar", "showButtonBar", XtRBoolean,
1206 sizeof(Boolean), XtOffset(AppDataPtr, showButtonBar),
1207 XtRImmediate, (XtPointer) True },
1208 { "lowTimeWarningColor", "lowTimeWarningColor", XtRString,
1209 sizeof(String), XtOffset(AppDataPtr, lowTimeWarningColor),
1210 XtRString, COLOR_LOWTIMEWARNING },
1211 { "lowTimeWarning", "lowTimeWarning", XtRBoolean,
1212 sizeof(Boolean), XtOffset(AppDataPtr, lowTimeWarning),
1213 XtRImmediate, (XtPointer) False },
1214 {"icsEngineAnalyze", "icsEngineAnalyze", XtRBoolean, /* [DM] icsEngineAnalyze */
1215 sizeof(Boolean), XtOffset(AppDataPtr, icsEngineAnalyze),
1216 XtRImmediate, (XtPointer) False },
1217 { "firstScoreAbs", "firstScoreAbs", XtRBoolean,
1218 sizeof(Boolean), XtOffset(AppDataPtr, firstScoreIsAbsolute),
1219 XtRImmediate, (XtPointer) False },
1220 { "secondScoreAbs", "secondScoreAbs", XtRBoolean,
1221 sizeof(Boolean), XtOffset(AppDataPtr, secondScoreIsAbsolute),
1222 XtRImmediate, (XtPointer) False },
1223 { "pgnExtendedInfo", "pgnExtendedInfo", XtRBoolean,
1224 sizeof(Boolean), XtOffset(AppDataPtr, saveExtendedInfoInPGN),
1225 XtRImmediate, (XtPointer) False },
1226 { "hideThinkingFromHuman", "hideThinkingFromHuman", XtRBoolean,
1227 sizeof(Boolean), XtOffset(AppDataPtr, hideThinkingFromHuman),
1228 XtRImmediate, (XtPointer) True },
1229 { "adjudicateLossThreshold", "adjudicateLossThreshold", XtRInt,
1230 sizeof(int), XtOffset(AppDataPtr, adjudicateLossThreshold),
1231 XtRImmediate, (XtPointer) 0},
1232 { "adjudicateDrawMoves", "adjudicateDrawMoves", XtRInt,
1233 sizeof(int), XtOffset(AppDataPtr, adjudicateDrawMoves),
1234 XtRImmediate, (XtPointer) 0},
1235 { "pgnEventHeader", "pgnEventHeader", XtRString,
1236 sizeof(String), XtOffset(AppDataPtr, pgnEventHeader),
1237 XtRImmediate, (XtPointer) "Computer Chess Game" },
1238 { "defaultFrcPosition", "defaultFrcPositon", XtRInt,
1239 sizeof(int), XtOffset(AppDataPtr, defaultFrcPosition),
1240 XtRImmediate, (XtPointer) -1},
1241 { "gameListTags", "gameListTags", XtRString,
1242 sizeof(String), XtOffset(AppDataPtr, gameListTags),
1243 XtRImmediate, (XtPointer) GLT_DEFAULT_TAGS },
1245 // [HGM] 4.3.xx options
1246 { "boardWidth", "boardWidth", XtRInt,
1247 sizeof(int), XtOffset(AppDataPtr, NrFiles),
1248 XtRImmediate, (XtPointer) -1},
1249 { "boardHeight", "boardHeight", XtRInt,
1250 sizeof(int), XtOffset(AppDataPtr, NrRanks),
1251 XtRImmediate, (XtPointer) -1},
1252 { "matchPause", "matchPause", XtRInt,
1253 sizeof(int), XtOffset(AppDataPtr, matchPause),
1254 XtRImmediate, (XtPointer) 10000},
1255 { "holdingsSize", "holdingsSize", XtRInt,
1256 sizeof(int), XtOffset(AppDataPtr, holdingsSize),
1257 XtRImmediate, (XtPointer) -1},
1258 { "flipBlack", "flipBlack", XtRBoolean,
1259 sizeof(Boolean), XtOffset(AppDataPtr, upsideDown),
1260 XtRImmediate, (XtPointer) False},
1261 { "allWhite", "allWhite", XtRBoolean,
1262 sizeof(Boolean), XtOffset(AppDataPtr, allWhite),
1263 XtRImmediate, (XtPointer) False},
1264 { "pieceToCharTable", "pieceToCharTable", XtRString,
1265 sizeof(String), XtOffset(AppDataPtr, pieceToCharTable),
1266 XtRImmediate, (XtPointer) 0},
1267 { "alphaRank", "alphaRank", XtRBoolean,
1268 sizeof(Boolean), XtOffset(AppDataPtr, alphaRank),
1269 XtRImmediate, (XtPointer) False},
1270 { "testClaims", "testClaims", XtRBoolean,
1271 sizeof(Boolean), XtOffset(AppDataPtr, testClaims),
1272 XtRImmediate, (XtPointer) True},
1273 { "checkMates", "checkMates", XtRBoolean,
1274 sizeof(Boolean), XtOffset(AppDataPtr, checkMates),
1275 XtRImmediate, (XtPointer) True},
1276 { "materialDraws", "materialDraws", XtRBoolean,
1277 sizeof(Boolean), XtOffset(AppDataPtr, materialDraws),
1278 XtRImmediate, (XtPointer) True},
1279 { "trivialDraws", "trivialDraws", XtRBoolean,
1280 sizeof(Boolean), XtOffset(AppDataPtr, trivialDraws),
1281 XtRImmediate, (XtPointer) False},
1282 { "ruleMoves", "ruleMoves", XtRInt,
1283 sizeof(int), XtOffset(AppDataPtr, ruleMoves),
1284 XtRImmediate, (XtPointer) 51},
1285 { "repeatsToDraw", "repeatsToDraw", XtRInt,
1286 sizeof(int), XtOffset(AppDataPtr, drawRepeats),
1287 XtRImmediate, (XtPointer) 6},
1288 { "engineDebugOutput", "engineDebugOutput", XtRInt,
1289 sizeof(int), XtOffset(AppDataPtr, engineComments),
1290 XtRImmediate, (XtPointer) 1},
1291 { "userName", "userName", XtRString,
1292 sizeof(int), XtOffset(AppDataPtr, userName),
1293 XtRImmediate, (XtPointer) 0},
1294 { "autoKibitz", "autoKibitz", XtRBoolean,
1295 sizeof(Boolean), XtOffset(AppDataPtr, autoKibitz),
1296 XtRImmediate, (XtPointer) False},
1297 { "firstTimeOdds", "firstTimeOdds", XtRInt,
1298 sizeof(int), XtOffset(AppDataPtr, firstTimeOdds),
1299 XtRImmediate, (XtPointer) 1},
1300 { "secondTimeOdds", "secondTimeOdds", XtRInt,
1301 sizeof(int), XtOffset(AppDataPtr, secondTimeOdds),
1302 XtRImmediate, (XtPointer) 1},
1303 { "timeOddsMode", "timeOddsMode", XtRInt,
1304 sizeof(int), XtOffset(AppDataPtr, timeOddsMode),
1305 XtRImmediate, (XtPointer) 0},
1306 { "firstAccumulateTC", "firstAccumulateTC", XtRInt,
1307 sizeof(int), XtOffset(AppDataPtr, firstAccumulateTC),
1308 XtRImmediate, (XtPointer) 1},
1309 { "secondAccumulateTC", "secondAccumulateTC", XtRInt,
1310 sizeof(int), XtOffset(AppDataPtr, secondAccumulateTC),
1311 XtRImmediate, (XtPointer) 1},
1312 { "firstNPS", "firstNPS", XtRInt,
1313 sizeof(int), XtOffset(AppDataPtr, firstNPS),
1314 XtRImmediate, (XtPointer) -1},
1315 { "secondNPS", "secondNPS", XtRInt,
1316 sizeof(int), XtOffset(AppDataPtr, secondNPS),
1317 XtRImmediate, (XtPointer) -1},
1318 { "serverMoves", "serverMoves", XtRString,
1319 sizeof(String), XtOffset(AppDataPtr, serverMovesName),
1320 XtRImmediate, (XtPointer) 0},
1321 { "serverPause", "serverPause", XtRInt,
1322 sizeof(int), XtOffset(AppDataPtr, serverPause),
1323 XtRImmediate, (XtPointer) 0},
1324 { "suppressLoadMoves", "suppressLoadMoves", XtRBoolean,
1325 sizeof(Boolean), XtOffset(AppDataPtr, suppressLoadMoves),
1326 XtRImmediate, (XtPointer) False},
1327 { "userName", "userName", XtRString,
1328 sizeof(String), XtOffset(AppDataPtr, userName),
1329 XtRImmediate, (XtPointer) 0},
1330 { "egtFormats", "egtFormats", XtRString,
1331 sizeof(String), XtOffset(AppDataPtr, egtFormats),
1332 XtRImmediate, (XtPointer) 0},
1333 { "rewindIndex", "rewindIndex", XtRInt,
1334 sizeof(int), XtOffset(AppDataPtr, rewindIndex),
1335 XtRImmediate, (XtPointer) 0},
1336 { "sameColorGames", "sameColorGames", XtRInt,
1337 sizeof(int), XtOffset(AppDataPtr, sameColorGames),
1338 XtRImmediate, (XtPointer) 0},
1339 { "smpCores", "smpCores", XtRInt,
1340 sizeof(int), XtOffset(AppDataPtr, smpCores),
1341 XtRImmediate, (XtPointer) 1},
1342 { "niceEngines", "niceEngines", XtRInt,
1343 sizeof(int), XtOffset(AppDataPtr, niceEngines),
1344 XtRImmediate, (XtPointer) 0},
1345 { "nameOfDebugFile", "nameOfDebugFile", XtRString,
1346 sizeof(String), XtOffset(AppDataPtr, nameOfDebugFile),
1347 XtRImmediate, (XtPointer) "xboard.debug"},
1348 { "engineDebugOutput", "engineDebugOutput", XtRInt,
1349 sizeof(int), XtOffset(AppDataPtr, engineComments),
1350 XtRImmediate, (XtPointer) 0},
1351 { "noGUI", "noGUI", XtRBoolean,
1352 sizeof(Boolean), XtOffset(AppDataPtr, noGUI),
1353 XtRImmediate, (XtPointer) 0},
1354 { "firstOptions", "firstOptions", XtRString,
1355 sizeof(String), XtOffset(AppDataPtr, firstOptions),
1356 XtRImmediate, (XtPointer) "" },
1357 { "secondOptions", "secondOptions", XtRString,
1358 sizeof(String), XtOffset(AppDataPtr, secondOptions),
1359 XtRImmediate, (XtPointer) "" },
1360 { "firstNeedsNoncompliantFEN", "firstNeedsNoncompliantFEN", XtRString,
1361 sizeof(String), XtOffset(AppDataPtr, fenOverride1),
1362 XtRImmediate, (XtPointer) 0 },
1363 { "secondNeedsNoncompliantFEN", "secondNeedsNoncompliantFEN", XtRString,
1364 sizeof(String), XtOffset(AppDataPtr, fenOverride2),
1365 XtRImmediate, (XtPointer) 0 },
1367 // [HGM] Winboard_x UCI options
1368 { "firstIsUCI", "firstIsUCI", XtRBoolean,
1369 sizeof(Boolean), XtOffset(AppDataPtr, firstIsUCI),
1370 XtRImmediate, (XtPointer) False},
1371 { "secondIsUCI", "secondIsUCI", XtRBoolean,
1372 sizeof(Boolean), XtOffset(AppDataPtr, secondIsUCI),
1373 XtRImmediate, (XtPointer) False},
1374 { "firstHasOwnBookUCI", "firstHasOwnBookUCI", XtRBoolean,
1375 sizeof(Boolean), XtOffset(AppDataPtr, firstHasOwnBookUCI),
1376 XtRImmediate, (XtPointer) True},
1377 { "secondHasOwnBookUCI", "secondHasOwnBookUCI", XtRBoolean,
1378 sizeof(Boolean), XtOffset(AppDataPtr, secondHasOwnBookUCI),
1379 XtRImmediate, (XtPointer) True},
1380 { "usePolyglotBook", "usePolyglotBook", XtRBoolean,
1381 sizeof(Boolean), XtOffset(AppDataPtr, usePolyglotBook),
1382 XtRImmediate, (XtPointer) False},
1383 { "defaultHashSize", "defaultHashSize", XtRInt,
1384 sizeof(int), XtOffset(AppDataPtr, defaultHashSize),
1385 XtRImmediate, (XtPointer) 64},
1386 { "defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XtRInt,
1387 sizeof(int), XtOffset(AppDataPtr, defaultCacheSizeEGTB),
1388 XtRImmediate, (XtPointer) 4},
1389 { "polyglotDir", "polyglotDir", XtRString,
1390 sizeof(String), XtOffset(AppDataPtr, polyglotDir),
1391 XtRImmediate, (XtPointer) "." },
1392 { "polyglotBook", "polyglotBook", XtRString,
1393 sizeof(String), XtOffset(AppDataPtr, polyglotBook),
1394 XtRImmediate, (XtPointer) "" },
1395 { "defaultPathEGTB", "defaultPathEGTB", XtRString,
1396 sizeof(String), XtOffset(AppDataPtr, defaultPathEGTB),
1397 XtRImmediate, (XtPointer) "/usr/local/share/egtb"},
1398 { "delayBeforeQuit", "delayBeforeQuit", XtRInt,
1399 sizeof(int), XtOffset(AppDataPtr, delayBeforeQuit),
1400 XtRImmediate, (XtPointer) 0},
1401 { "delayAfterQuit", "delayAfterQuit", XtRInt,
1402 sizeof(int), XtOffset(AppDataPtr, delayAfterQuit),
1403 XtRImmediate, (XtPointer) 0},
1406 XrmOptionDescRec shellOptions[] = {
1407 { "-whitePieceColor", "whitePieceColor", XrmoptionSepArg, NULL },
1408 { "-blackPieceColor", "blackPieceColor", XrmoptionSepArg, NULL },
1409 { "-lightSquareColor", "lightSquareColor", XrmoptionSepArg, NULL },
1410 { "-darkSquareColor", "darkSquareColor", XrmoptionSepArg, NULL },
1411 { "-highlightSquareColor", "highlightSquareColor", XrmoptionSepArg, NULL },
1412 { "-premoveHighlightColor", "premoveHighlightColor", XrmoptionSepArg,NULL},
1413 { "-movesPerSession", "movesPerSession", XrmoptionSepArg, NULL },
1414 { "-mps", "movesPerSession", XrmoptionSepArg, NULL },
1415 { "-timeIncrement", "timeIncrement", XrmoptionSepArg, NULL },
1416 { "-inc", "timeIncrement", XrmoptionSepArg, NULL },
1417 { "-initString", "initString", XrmoptionSepArg, NULL },
1418 { "-firstInitString", "initString", XrmoptionSepArg, NULL },
1419 { "-secondInitString", "secondInitString", XrmoptionSepArg, NULL },
1420 { "-firstComputerString", "firstComputerString", XrmoptionSepArg, NULL },
1421 { "-secondComputerString", "secondComputerString", XrmoptionSepArg, NULL },
1422 { "-firstChessProgram", "firstChessProgram", XrmoptionSepArg, NULL },
1423 { "-fcp", "firstChessProgram", XrmoptionSepArg, NULL },
1424 { "-secondChessProgram", "secondChessProgram", XrmoptionSepArg, NULL },
1425 { "-scp", "secondChessProgram", XrmoptionSepArg, NULL },
1426 { "-firstPlaysBlack", "firstPlaysBlack", XrmoptionSepArg, NULL },
1427 { "-fb", "firstPlaysBlack", XrmoptionNoArg, "True" },
1428 { "-xfb", "firstPlaysBlack", XrmoptionNoArg, "False" },
1429 { "-noChessProgram", "noChessProgram", XrmoptionSepArg, NULL },
1430 { "-ncp", "noChessProgram", XrmoptionNoArg, "True" },
1431 { "-xncp", "noChessProgram", XrmoptionNoArg, "False" },
1432 { "-firstHost", "firstHost", XrmoptionSepArg, NULL },
1433 { "-fh", "firstHost", XrmoptionSepArg, NULL },
1434 { "-secondHost", "secondHost", XrmoptionSepArg, NULL },
1435 { "-sh", "secondHost", XrmoptionSepArg, NULL },
1436 { "-firstDirectory", "firstDirectory", XrmoptionSepArg, NULL },
1437 { "-fd", "firstDirectory", XrmoptionSepArg, NULL },
1438 { "-secondDirectory", "secondDirectory", XrmoptionSepArg, NULL },
1439 { "-sd", "secondDirectory", XrmoptionSepArg, NULL },
1440 { "-bitmapDirectory", "bitmapDirectory", XrmoptionSepArg, NULL },
1441 { "-bm", "bitmapDirectory", XrmoptionSepArg, NULL },
1442 { "-remoteShell", "remoteShell", XrmoptionSepArg, NULL },
1443 { "-rsh", "remoteShell", XrmoptionSepArg, NULL },
1444 { "-remoteUser", "remoteUser", XrmoptionSepArg, NULL },
1445 { "-ruser", "remoteUser", XrmoptionSepArg, NULL },
1446 { "-timeDelay", "timeDelay", XrmoptionSepArg, NULL },
1447 { "-td", "timeDelay", XrmoptionSepArg, NULL },
1448 { "-timeControl", "timeControl", XrmoptionSepArg, NULL },
1449 { "-tc", "timeControl", XrmoptionSepArg, NULL },
1450 { "-internetChessServerMode", "internetChessServerMode",
1451 XrmoptionSepArg, NULL },
1452 { "-ics", "internetChessServerMode", XrmoptionNoArg, "True" },
1453 { "-xics", "internetChessServerMode", XrmoptionNoArg, "False" },
1454 { "-internetChessServerHost", "internetChessServerHost",
1455 XrmoptionSepArg, NULL },
1456 { "-icshost", "internetChessServerHost", XrmoptionSepArg, NULL },
1457 { "-internetChessServerPort", "internetChessServerPort",
1458 XrmoptionSepArg, NULL },
1459 { "-icsport", "internetChessServerPort", XrmoptionSepArg, NULL },
1460 { "-internetChessServerCommPort", "internetChessServerCommPort",
1461 XrmoptionSepArg, NULL },
1462 { "-icscomm", "internetChessServerCommPort", XrmoptionSepArg, NULL },
1463 { "-internetChessServerLogonScript", "internetChessServerLogonScript",
1464 XrmoptionSepArg, NULL },
1465 { "-icslogon", "internetChessServerLogonScript", XrmoptionSepArg, NULL },
1466 { "-internetChessServerHelper", "internetChessServerHelper",
1467 XrmoptionSepArg, NULL },
1468 { "-icshelper", "internetChessServerHelper", XrmoptionSepArg, NULL },
1469 { "-internetChessServerInputBox", "internetChessServerInputBox",
1470 XrmoptionSepArg, NULL },
1471 { "-icsinput", "internetChessServerInputBox", XrmoptionNoArg, "True" },
1472 { "-xicsinput", "internetChessServerInputBox", XrmoptionNoArg, "False" },
1473 { "-icsAlarm", "icsAlarm", XrmoptionSepArg, NULL },
1474 { "-alarm", "icsAlarm", XrmoptionNoArg, "True" },
1475 { "-xalarm", "icsAlarm", XrmoptionNoArg, "False" },
1476 { "-icsAlarmTime", "icsAlarmTime", XrmoptionSepArg, NULL },
1477 { "-useTelnet", "useTelnet", XrmoptionSepArg, NULL },
1478 { "-telnet", "useTelnet", XrmoptionNoArg, "True" },
1479 { "-xtelnet", "useTelnet", XrmoptionNoArg, "False" },
1480 { "-telnetProgram", "telnetProgram", XrmoptionSepArg, NULL },
1481 { "-gateway", "gateway", XrmoptionSepArg, NULL },
1482 { "-loadGameFile", "loadGameFile", XrmoptionSepArg, NULL },
1483 { "-lgf", "loadGameFile", XrmoptionSepArg, NULL },
1484 { "-loadGameIndex", "loadGameIndex", XrmoptionSepArg, NULL },
1485 { "-lgi", "loadGameIndex", XrmoptionSepArg, NULL },
1486 { "-saveGameFile", "saveGameFile", XrmoptionSepArg, NULL },
1487 { "-sgf", "saveGameFile", XrmoptionSepArg, NULL },
1488 { "-autoSaveGames", "autoSaveGames", XrmoptionSepArg, NULL },
1489 { "-autosave", "autoSaveGames", XrmoptionNoArg, "True" },
1490 { "-xautosave", "autoSaveGames", XrmoptionNoArg, "False" },
1491 { "-autoRaiseBoard", "autoRaiseBoard", XrmoptionSepArg, NULL },
1492 { "-autoraise", "autoRaiseBoard", XrmoptionNoArg, "True" },
1493 { "-xautoraise", "autoRaiseBoard", XrmoptionNoArg, "False" },
1494 { "-blindfold", "blindfold", XrmoptionSepArg, NULL },
1495 { "-blind", "blindfold", XrmoptionNoArg, "True" },
1496 { "-xblind", "blindfold", XrmoptionNoArg, "False" },
1497 { "-loadPositionFile", "loadPositionFile", XrmoptionSepArg, NULL },
1498 { "-lpf", "loadPositionFile", XrmoptionSepArg, NULL },
1499 { "-loadPositionIndex", "loadPositionIndex", XrmoptionSepArg, NULL },
1500 { "-lpi", "loadPositionIndex", XrmoptionSepArg, NULL },
1501 { "-savePositionFile", "savePositionFile", XrmoptionSepArg, NULL },
1502 { "-spf", "savePositionFile", XrmoptionSepArg, NULL },
1503 { "-matchMode", "matchMode", XrmoptionSepArg, NULL },
1504 { "-mm", "matchMode", XrmoptionNoArg, "True" },
1505 { "-xmm", "matchMode", XrmoptionNoArg, "False" },
1506 { "-matchGames", "matchGames", XrmoptionSepArg, NULL },
1507 { "-mg", "matchGames", XrmoptionSepArg, NULL },
1508 { "-monoMode", "monoMode", XrmoptionSepArg, NULL },
1509 { "-mono", "monoMode", XrmoptionNoArg, "True" },
1510 { "-xmono", "monoMode", XrmoptionNoArg, "False" },
1511 { "-debugMode", "debugMode", XrmoptionSepArg, NULL },
1512 { "-debug", "debugMode", XrmoptionNoArg, "True" },
1513 { "-xdebug", "debugMode", XrmoptionNoArg, "False" },
1514 { "-clockMode", "clockMode", XrmoptionSepArg, NULL },
1515 { "-clock", "clockMode", XrmoptionNoArg, "True" },
1516 { "-xclock", "clockMode", XrmoptionNoArg, "False" },
1517 { "-boardSize", "boardSize", XrmoptionSepArg, NULL },
1518 { "-size", "boardSize", XrmoptionSepArg, NULL },
1519 { "-searchTime", "searchTime", XrmoptionSepArg, NULL },
1520 { "-st", "searchTime", XrmoptionSepArg, NULL },
1521 { "-searchDepth", "searchDepth", XrmoptionSepArg, NULL },
1522 { "-depth", "searchDepth", XrmoptionSepArg, NULL },
1523 { "-showCoords", "showCoords", XrmoptionSepArg, NULL },
1524 { "-coords", "showCoords", XrmoptionNoArg, "True" },
1525 { "-xcoords", "showCoords", XrmoptionNoArg, "False" },
1527 { "-showJail", "showJail", XrmoptionSepArg, NULL },
1528 { "-jail", "showJail", XrmoptionNoArg, "1" },
1529 { "-sidejail", "showJail", XrmoptionNoArg, "2" },
1530 { "-xjail", "showJail", XrmoptionNoArg, "0" },
1532 { "-showThinking", "showThinking", XrmoptionSepArg, NULL },
1533 { "-thinking", "showThinking", XrmoptionNoArg, "True" },
1534 { "-xthinking", "showThinking", XrmoptionNoArg, "False" },
1535 { "-ponderNextMove", "ponderNextMove", XrmoptionSepArg, NULL },
1536 { "-ponder", "ponderNextMove", XrmoptionNoArg, "True" },
1537 { "-xponder", "ponderNextMove", XrmoptionNoArg, "False" },
1538 { "-periodicUpdates", "periodicUpdates", XrmoptionSepArg, NULL },
1539 { "-periodic", "periodicUpdates", XrmoptionNoArg, "True" },
1540 { "-xperiodic", "periodicUpdates", XrmoptionNoArg, "False" },
1541 { "-clockFont", "clockFont", XrmoptionSepArg, NULL },
1542 { "-coordFont", "coordFont", XrmoptionSepArg, NULL },
1543 { "-font", "font", XrmoptionSepArg, NULL },
1544 { "-ringBellAfterMoves", "ringBellAfterMoves", XrmoptionSepArg, NULL },
1545 { "-bell", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1546 { "-xbell", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1547 { "-movesound", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1548 { "-xmovesound", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1549 { "-autoCallFlag", "autoCallFlag", XrmoptionSepArg, NULL },
1550 { "-autoflag", "autoCallFlag", XrmoptionNoArg, "True" },
1551 { "-xautoflag", "autoCallFlag", XrmoptionNoArg, "False" },
1552 { "-autoFlipView", "autoFlipView", XrmoptionSepArg, NULL },
1553 { "-autoflip", "autoFlipView", XrmoptionNoArg, "True" },
1554 { "-xautoflip", "autoFlipView", XrmoptionNoArg, "False" },
1555 { "-autoObserve", "autoObserve", XrmoptionSepArg, NULL },
1556 { "-autobs", "autoObserve", XrmoptionNoArg, "True" },
1557 { "-xautobs", "autoObserve", XrmoptionNoArg, "False" },
1558 { "-autoComment", "autoComment", XrmoptionSepArg, NULL },
1559 { "-autocomm", "autoComment", XrmoptionNoArg, "True" },
1560 { "-xautocomm", "autoComment", XrmoptionNoArg, "False" },
1561 { "-getMoveList", "getMoveList", XrmoptionSepArg, NULL },
1562 { "-moves", "getMoveList", XrmoptionNoArg, "True" },
1563 { "-xmoves", "getMoveList", XrmoptionNoArg, "False" },
1565 { "-highlightDragging", "highlightDragging", XrmoptionSepArg, NULL },
1566 { "-highdrag", "highlightDragging", XrmoptionNoArg, "True" },
1567 { "-xhighdrag", "highlightDragging", XrmoptionNoArg, "False" },
1569 { "-highlightLastMove", "highlightLastMove", XrmoptionSepArg, NULL },
1570 { "-highlight", "highlightLastMove", XrmoptionNoArg, "True" },
1571 { "-xhighlight", "highlightLastMove", XrmoptionNoArg, "False" },
1572 { "-premove", "premove", XrmoptionSepArg, NULL },
1573 { "-pre", "premove", XrmoptionNoArg, "True" },
1574 { "-xpre", "premove", XrmoptionNoArg, "False" },
1575 { "-testLegality", "testLegality", XrmoptionSepArg, NULL },
1576 { "-legal", "testLegality", XrmoptionNoArg, "True" },
1577 { "-xlegal", "testLegality", XrmoptionNoArg, "False" },
1578 { "-flipView", "flipView", XrmoptionSepArg, NULL },
1579 { "-flip", "flipView", XrmoptionNoArg, "True" },
1580 { "-xflip", "flipView", XrmoptionNoArg, "False" },
1581 { "-cmail", "cmailGameName", XrmoptionSepArg, NULL },
1582 { "-alwaysPromoteToQueen", "alwaysPromoteToQueen",
1583 XrmoptionSepArg, NULL },
1584 { "-queen", "alwaysPromoteToQueen", XrmoptionNoArg, "True" },
1585 { "-xqueen", "alwaysPromoteToQueen", XrmoptionNoArg, "False" },
1586 { "-oldSaveStyle", "oldSaveStyle", XrmoptionSepArg, NULL },
1587 { "-oldsave", "oldSaveStyle", XrmoptionNoArg, "True" },
1588 { "-xoldsave", "oldSaveStyle", XrmoptionNoArg, "False" },
1589 { "-quietPlay", "quietPlay", XrmoptionSepArg, NULL },
1590 { "-quiet", "quietPlay", XrmoptionNoArg, "True" },
1591 { "-xquiet", "quietPlay", XrmoptionNoArg, "False" },
1592 { "-titleInWindow", "titleInWindow", XrmoptionSepArg, NULL },
1593 { "-title", "titleInWindow", XrmoptionNoArg, "True" },
1594 { "-xtitle", "titleInWindow", XrmoptionNoArg, "False" },
1596 { "-zippyTalk", "zippyTalk", XrmoptionSepArg, NULL },
1597 { "-zt", "zippyTalk", XrmoptionNoArg, "True" },
1598 { "-xzt", "zippyTalk", XrmoptionNoArg, "False" },
1599 { "-zippyPlay", "zippyPlay", XrmoptionSepArg, NULL },
1600 { "-zp", "zippyPlay", XrmoptionNoArg, "True" },
1601 { "-xzp", "zippyPlay", XrmoptionNoArg, "False" },
1602 { "-zippyLines", "zippyLines", XrmoptionSepArg, NULL },
1603 { "-zippyPinhead", "zippyPinhead", XrmoptionSepArg, NULL },
1604 { "-zippyPassword", "zippyPassword", XrmoptionSepArg, NULL },
1605 { "-zippyPassword2", "zippyPassword2", XrmoptionSepArg, NULL },
1606 { "-zippyWrongPassword", "zippyWrongPassword", XrmoptionSepArg, NULL },
1607 { "-zippyAcceptOnly", "zippyAcceptOnly", XrmoptionSepArg, NULL },
1608 { "-zippyUseI", "zippyUseI", XrmoptionSepArg, NULL },
1609 { "-zui", "zippyUseI", XrmoptionNoArg, "True" },
1610 { "-xzui", "zippyUseI", XrmoptionNoArg, "False" },
1611 { "-zippyBughouse", "zippyBughouse", XrmoptionSepArg, NULL },
1612 { "-zippyNoplayCrafty", "zippyNoplayCrafty", XrmoptionSepArg, NULL },
1613 { "-znc", "zippyNoplayCrafty", XrmoptionNoArg, "True" },
1614 { "-xznc", "zippyNoplayCrafty", XrmoptionNoArg, "False" },
1615 { "-zippyGameEnd", "zippyGameEnd", XrmoptionSepArg, NULL },
1616 { "-zippyGameStart", "zippyGameStart", XrmoptionSepArg, NULL },
1617 { "-zippyAdjourn", "zippyAdjourn", XrmoptionSepArg, NULL },
1618 { "-zadj", "zippyAdjourn", XrmoptionNoArg, "True" },
1619 { "-xzadj", "zippyAdjourn", XrmoptionNoArg, "False" },
1620 { "-zippyAbort", "zippyAbort", XrmoptionSepArg, NULL },
1621 { "-zab", "zippyAbort", XrmoptionNoArg, "True" },
1622 { "-xzab", "zippyAbort", XrmoptionNoArg, "False" },
1623 { "-zippyVariants", "zippyVariants", XrmoptionSepArg, NULL },
1624 { "-zippyMaxGames", "zippyMaxGames", XrmoptionSepArg, NULL },
1625 { "-zippyReplayTimeout", "zippyReplayTimeout", XrmoptionSepArg, NULL },
1626 { "-zippyShortGame", "zippyShortGame", XrmoptionSepArg, NULL },
1628 { "-flashCount", "flashCount", XrmoptionSepArg, NULL },
1629 { "-flash", "flashCount", XrmoptionNoArg, "3" },
1630 { "-xflash", "flashCount", XrmoptionNoArg, "0" },
1631 { "-flashRate", "flashRate", XrmoptionSepArg, NULL },
1632 { "-pixmapDirectory", "pixmapDirectory", XrmoptionSepArg, NULL },
1633 { "-msLoginDelay", "msLoginDelay", XrmoptionSepArg, NULL },
1634 { "-pixmap", "pixmapDirectory", XrmoptionSepArg, NULL },
1635 { "-colorizeMessages", "colorizeMessages", XrmoptionSepArg, NULL },
1636 { "-colorize", "colorizeMessages", XrmoptionNoArg, "True" },
1637 { "-xcolorize", "colorizeMessages", XrmoptionNoArg, "False" },
1638 { "-colorShout", "colorShout", XrmoptionSepArg, NULL },
1639 { "-colorSShout", "colorSShout", XrmoptionSepArg, NULL },
1640 { "-colorCShout", "colorSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1641 { "-colorChannel1", "colorChannel1", XrmoptionSepArg, NULL },
1642 { "-colorChannel", "colorChannel", XrmoptionSepArg, NULL },
1643 { "-colorKibitz", "colorKibitz", XrmoptionSepArg, NULL },
1644 { "-colorTell", "colorTell", XrmoptionSepArg, NULL },
1645 { "-colorChallenge", "colorChallenge", XrmoptionSepArg, NULL },
1646 { "-colorRequest", "colorRequest", XrmoptionSepArg, NULL },
1647 { "-colorSeek", "colorSeek", XrmoptionSepArg, NULL },
1648 { "-colorNormal", "colorNormal", XrmoptionSepArg, NULL },
1649 { "-soundProgram", "soundProgram", XrmoptionSepArg, NULL },
1650 { "-soundShout", "soundShout", XrmoptionSepArg, NULL },
1651 { "-soundSShout", "soundSShout", XrmoptionSepArg, NULL },
1652 { "-soundCShout", "soundSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1653 { "-soundChannel1", "soundChannel1", XrmoptionSepArg, NULL },
1654 { "-soundChannel", "soundChannel", XrmoptionSepArg, NULL },
1655 { "-soundKibitz", "soundKibitz", XrmoptionSepArg, NULL },
1656 { "-soundTell", "soundTell", XrmoptionSepArg, NULL },
1657 { "-soundChallenge", "soundChallenge", XrmoptionSepArg, NULL },
1658 { "-soundRequest", "soundRequest", XrmoptionSepArg, NULL },
1659 { "-soundSeek", "soundSeek", XrmoptionSepArg, NULL },
1660 { "-soundMove", "soundMove", XrmoptionSepArg, NULL },
1661 { "-soundIcsWin", "soundIcsWin", XrmoptionSepArg, NULL },
1662 { "-soundIcsLoss", "soundIcsLoss", XrmoptionSepArg, NULL },
1663 { "-soundIcsDraw", "soundIcsDraw", XrmoptionSepArg, NULL },
1664 { "-soundIcsUnfinished", "soundIcsUnfinished", XrmoptionSepArg, NULL },
1665 { "-soundIcsAlarm", "soundIcsAlarm", XrmoptionSepArg, NULL },
1666 { "-reuseFirst", "reuseFirst", XrmoptionSepArg, NULL },
1667 { "-reuseChessPrograms", "reuseFirst", XrmoptionSepArg, NULL }, /*compat*/
1668 { "-reuse", "reuseFirst", XrmoptionNoArg, "True" },
1669 { "-xreuse", "reuseFirst", XrmoptionNoArg, "False" },
1670 { "-reuseSecond", "reuseSecond", XrmoptionSepArg, NULL },
1671 { "-reuse2", "reuseSecond", XrmoptionNoArg, "True" },
1672 { "-xreuse2", "reuseSecond", XrmoptionNoArg, "False" },
1673 { "-animateMoving", "animateMoving", XrmoptionSepArg, NULL },
1674 { "-animate", "animateMoving", XrmoptionNoArg, "True" },
1675 { "-xanimate", "animateMoving", XrmoptionNoArg, "False" },
1676 { "-animateDragging", "animateDragging", XrmoptionSepArg, NULL },
1677 { "-drag", "animateDragging", XrmoptionNoArg, "True" },
1678 { "-xdrag", "animateDragging", XrmoptionNoArg, "False" },
1679 { "-animateSpeed", "animateSpeed", XrmoptionSepArg, NULL },
1680 { "-popupExitMessage", "popupExitMessage", XrmoptionSepArg, NULL },
1681 { "-exit", "popupExitMessage", XrmoptionNoArg, "True" },
1682 { "-xexit", "popupExitMessage", XrmoptionNoArg, "False" },
1683 { "-popupMoveErrors", "popupMoveErrors", XrmoptionSepArg, NULL },
1684 { "-popup", "popupMoveErrors", XrmoptionNoArg, "True" },
1685 { "-xpopup", "popupMoveErrors", XrmoptionNoArg, "False" },
1686 { "-fontSizeTolerance", "fontSizeTolerance", XrmoptionSepArg, NULL },
1687 { "-initialMode", "initialMode", XrmoptionSepArg, NULL },
1688 { "-mode", "initialMode", XrmoptionSepArg, NULL },
1689 { "-variant", "variant", XrmoptionSepArg, NULL },
1690 { "-firstProtocolVersion", "firstProtocolVersion", XrmoptionSepArg, NULL },
1691 { "-secondProtocolVersion","secondProtocolVersion",XrmoptionSepArg, NULL },
1692 { "-showButtonBar", "showButtonBar", XrmoptionSepArg, NULL },
1693 { "-buttons", "showButtonBar", XrmoptionNoArg, "True" },
1694 { "-xbuttons", "showButtonBar", XrmoptionNoArg, "False" },
1695 { "-lowTimeWarningColor", "lowTimeWarningColor", XrmoptionSepArg, NULL },
1696 { "-lowTimeWarning", "lowTimeWarning", XrmoptionSepArg, NULL },
1697 /* [AS,HR] New features */
1698 { "-firstScoreAbs", "firstScoreAbs", XrmoptionSepArg, NULL },
1699 { "-secondScoreAbs", "secondScoreAbs", XrmoptionSepArg, NULL },
1700 { "-pgnExtendedInfo", "pgnExtendedInfo", XrmoptionSepArg, NULL },
1701 { "-hideThinkingFromHuman", "hideThinkingFromHuman", XrmoptionSepArg, NULL },
1702 { "-adjudicateLossThreshold", "adjudicateLossThreshold", XrmoptionSepArg, NULL },
1703 { "-adjudicateDrawMoves", "adjudicateDrawMoves", XrmoptionSepArg, NULL },
1704 { "-pgnEventHeader", "pgnEventHeader", XrmoptionSepArg, NULL },
1705 { "-firstIsUCI", "firstIsUCI", XrmoptionSepArg, NULL },
1706 { "-secondIsUCI", "secondIsUCI", XrmoptionSepArg, NULL },
1707 { "-fUCI", "firstIsUCI", XrmoptionNoArg, "True" },
1708 { "-sUCI", "secondIsUCI", XrmoptionNoArg, "True" },
1709 { "-firstHasOwnBookUCI", "firstHasOwnBookUCI", XrmoptionSepArg, NULL },
1710 { "-secondHasOwnBookUCI", "secondHasOwnBookUCI", XrmoptionSepArg, NULL },
1711 { "-fNoOwnBookUCI", "firstHasOwnBookUCI", XrmoptionNoArg, "False" },
1712 { "-sNoOwnBookUCI", "secondHasOwnBookUCI", XrmoptionNoArg, "False" },
1713 { "-firstXBook", "firstHasOwnBookUCI", XrmoptionNoArg, "False" },
1714 { "-secondXBook", "secondHasOwnBookUCI", XrmoptionNoArg, "False" },
1715 { "-polyglotDir", "polyglotDir", XrmoptionSepArg, NULL },
1716 { "-usePolyglotBook", "usePolyglotBook", XrmoptionSepArg, NULL },
1717 { "-polyglotBook", "polyglotBook", XrmoptionSepArg, NULL },
1718 { "-defaultHashSize", "defaultHashSize", XrmoptionSepArg, NULL },
1719 { "-defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XrmoptionSepArg, NULL },
1720 { "-defaultPathEGTB", "defaultPathEGTB", XrmoptionSepArg, NULL },
1721 { "-defaultFrcPosition", "defaultFrcPosition", XrmoptionSepArg, NULL },
1722 { "-gameListTags", "gameListTags", XrmoptionSepArg, NULL },
1723 // [HGM] I am sure AS added many more options, but we have to fish them out, from the list in winboard.c
1725 /* [HGM,HR] User-selectable board size */
1726 { "-boardWidth", "boardWidth", XrmoptionSepArg, NULL },
1727 { "-boardHeight", "boardHeight", XrmoptionSepArg, NULL },
1728 { "-matchPause", "matchPause", XrmoptionSepArg, NULL },
1730 /* [HGM] new arguments of 4.3.xx. All except first three are back-end options, which should work immediately */
1731 { "-holdingsSize", "holdingsSize", XrmoptionSepArg, NULL }, // requires extensive front-end changes to work
1732 { "-flipBlack", "flipBlack", XrmoptionSepArg, NULL }, // requires front-end changes to work
1733 { "-allWhite", "allWhite", XrmoptionSepArg, NULL }, // requires front-end changes to work
1734 { "-pieceToCharTable", "pieceToCharTable", XrmoptionSepArg, NULL },
1735 { "-alphaRank", "alphaRank", XrmoptionSepArg, NULL },
1736 { "-testClaims", "testClaims", XrmoptionSepArg, NULL },
1737 { "-checkMates", "checkMates", XrmoptionSepArg, NULL },
1738 { "-materialDraws", "materialDraws", XrmoptionSepArg, NULL },
1739 { "-trivialDraws", "trivialDraws", XrmoptionSepArg, NULL },
1740 { "-ruleMoves", "ruleMoves", XrmoptionSepArg, NULL },
1741 { "-repeatsToDraw", "repeatsToDraw", XrmoptionSepArg, NULL },
1742 { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL },
1743 { "-userName", "userName", XrmoptionSepArg, NULL },
1744 { "-autoKibitz", "autoKibitz", XrmoptionNoArg, "True" },
1745 { "-firstTimeOdds", "firstTimeOdds", XrmoptionSepArg, NULL },
1746 { "-secondTimeOdds", "secondTimeOdds", XrmoptionSepArg, NULL },
1747 { "-timeOddsMode", "timeOddsMode", XrmoptionSepArg, NULL },
1748 { "-firstAccumulateTC", "firstAccumulateTC", XrmoptionSepArg, NULL },
1749 { "-secondAccumulateTC", "secondAccumulateTC", XrmoptionSepArg, NULL },
1750 { "-firstNPS", "firstNPS", XrmoptionSepArg, NULL },
1751 { "-secondNPS", "secondNPS", XrmoptionSepArg, NULL },
1752 { "-serverMoves", "serverMoves", XrmoptionSepArg, NULL },
1753 { "-serverPause", "serverPause", XrmoptionSepArg, NULL },
1754 { "-suppressLoadMoves", "suppressLoadMoves", XrmoptionSepArg, NULL },
1755 { "-egtFormats", "egtFormats", XrmoptionSepArg, NULL },
1756 { "-userName", "userName", XrmoptionSepArg, NULL },
1757 { "-smpCores", "smpCores", XrmoptionSepArg, NULL },
1758 { "-sameColorGames", "sameColorGames", XrmoptionSepArg, NULL },
1759 { "-rewindIndex", "rewindIndex", XrmoptionSepArg, NULL },
1760 { "-niceEngines", "niceEngines", XrmoptionSepArg, NULL },
1761 { "-delayBeforeQuit", "delayBeforeQuit", XrmoptionSepArg, NULL },
1762 { "-delayAfterQuit", "delayAfterQuit", XrmoptionSepArg, NULL },
1763 { "-nameOfDebugFile", "nameOfDebugFile", XrmoptionSepArg, NULL },
1764 { "-debugFile", "nameOfDebugFile", XrmoptionSepArg, NULL },
1765 { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL },
1766 { "-noGUI", "noGUI", XrmoptionNoArg, "True" },
1767 { "-firstOptions", "firstOptions", XrmoptionSepArg, NULL },
1768 { "-secondOptions", "secondOptions", XrmoptionSepArg, NULL },
1769 { "-firstNeedsNoncompliantFEN", "firstNeedsNoncompliantFEN", XrmoptionSepArg, NULL },
1770 { "-secondNeedsNoncompliantFEN", "secondNeedsNoncompliantFEN", XrmoptionSepArg, NULL },
1774 XtActionsRec boardActions[] = {
1775 { "DrawPosition", DrawPositionProc },
1776 { "HandleUserMove", HandleUserMove },
1777 { "AnimateUserMove", AnimateUserMove },
1778 { "FileNameAction", FileNameAction },
1779 { "AskQuestionProc", AskQuestionProc },
1780 { "AskQuestionReplyAction", AskQuestionReplyAction },
1781 { "PieceMenuPopup", PieceMenuPopup },
1782 { "WhiteClock", WhiteClock },
1783 { "BlackClock", BlackClock },
1784 { "Iconify", Iconify },
1785 { "ResetProc", ResetProc },
1786 { "LoadGameProc", LoadGameProc },
1787 { "LoadNextGameProc", LoadNextGameProc },
1788 { "LoadPrevGameProc", LoadPrevGameProc },
1789 { "LoadSelectedProc", LoadSelectedProc },
1790 { "ReloadGameProc", ReloadGameProc },
1791 { "LoadPositionProc", LoadPositionProc },
1792 { "LoadNextPositionProc", LoadNextPositionProc },
1793 { "LoadPrevPositionProc", LoadPrevPositionProc },
1794 { "ReloadPositionProc", ReloadPositionProc },
1795 { "CopyPositionProc", CopyPositionProc },
1796 { "PastePositionProc", PastePositionProc },
1797 { "CopyGameProc", CopyGameProc },
1798 { "PasteGameProc", PasteGameProc },
1799 { "SaveGameProc", SaveGameProc },
1800 { "SavePositionProc", SavePositionProc },
1801 { "MailMoveProc", MailMoveProc },
1802 { "ReloadCmailMsgProc", ReloadCmailMsgProc },
1803 { "QuitProc", QuitProc },
1804 { "MachineWhiteProc", MachineWhiteProc },
1805 { "MachineBlackProc", MachineBlackProc },
1806 { "AnalysisModeProc", AnalyzeModeProc },
1807 { "AnalyzeFileProc", AnalyzeFileProc },
1808 { "TwoMachinesProc", TwoMachinesProc },
1809 { "IcsClientProc", IcsClientProc },
1810 { "EditGameProc", EditGameProc },
1811 { "EditPositionProc", EditPositionProc },
1812 { "TrainingProc", EditPositionProc },
1813 { "EngineOutputProc", EngineOutputProc}, // [HGM] Winboard_x engine-output window
1814 { "ShowGameListProc", ShowGameListProc },
1815 { "ShowMoveListProc", HistoryShowProc},
1816 { "EditTagsProc", EditCommentProc },
1817 { "EditCommentProc", EditCommentProc },
1818 { "IcsAlarmProc", IcsAlarmProc },
1819 { "IcsInputBoxProc", IcsInputBoxProc },
1820 { "PauseProc", PauseProc },
1821 { "AcceptProc", AcceptProc },
1822 { "DeclineProc", DeclineProc },
1823 { "RematchProc", RematchProc },
1824 { "CallFlagProc", CallFlagProc },
1825 { "DrawProc", DrawProc },
1826 { "AdjournProc", AdjournProc },
1827 { "AbortProc", AbortProc },
1828 { "ResignProc", ResignProc },
1829 { "AdjuWhiteProc", AdjuWhiteProc },
1830 { "AdjuBlackProc", AdjuBlackProc },
1831 { "AdjuDrawProc", AdjuDrawProc },
1832 { "EnterKeyProc", EnterKeyProc },
1833 { "StopObservingProc", StopObservingProc },
1834 { "StopExaminingProc", StopExaminingProc },
1835 { "BackwardProc", BackwardProc },
1836 { "ForwardProc", ForwardProc },
1837 { "ToStartProc", ToStartProc },
1838 { "ToEndProc", ToEndProc },
1839 { "RevertProc", RevertProc },
1840 { "TruncateGameProc", TruncateGameProc },
1841 { "MoveNowProc", MoveNowProc },
1842 { "RetractMoveProc", RetractMoveProc },
1843 { "AlwaysQueenProc", AlwaysQueenProc },
1844 { "AnimateDraggingProc", AnimateDraggingProc },
1845 { "AnimateMovingProc", AnimateMovingProc },
1846 { "AutoflagProc", AutoflagProc },
1847 { "AutoflipProc", AutoflipProc },
1848 { "AutobsProc", AutobsProc },
1849 { "AutoraiseProc", AutoraiseProc },
1850 { "AutosaveProc", AutosaveProc },
1851 { "BlindfoldProc", BlindfoldProc },
1852 { "FlashMovesProc", FlashMovesProc },
1853 { "FlipViewProc", FlipViewProc },
1854 { "GetMoveListProc", GetMoveListProc },
1856 { "HighlightDraggingProc", HighlightDraggingProc },
1858 { "HighlightLastMoveProc", HighlightLastMoveProc },
1859 { "IcsAlarmProc", IcsAlarmProc },
1860 { "MoveSoundProc", MoveSoundProc },
1861 { "OldSaveStyleProc", OldSaveStyleProc },
1862 { "PeriodicUpdatesProc", PeriodicUpdatesProc },
1863 { "PonderNextMoveProc", PonderNextMoveProc },
1864 { "PopupExitMessageProc", PopupExitMessageProc },
1865 { "PopupMoveErrorsProc", PopupMoveErrorsProc },
1866 { "PremoveProc", PremoveProc },
1867 { "QuietPlayProc", QuietPlayProc },
1868 { "ShowCoordsProc", ShowCoordsProc },
1869 { "ShowThinkingProc", ShowThinkingProc },
1870 { "HideThinkingProc", HideThinkingProc },
1871 { "TestLegalityProc", TestLegalityProc },
1872 { "InfoProc", InfoProc },
1873 { "ManProc", ManProc },
1874 { "HintProc", HintProc },
1875 { "BookProc", BookProc },
1876 { "AboutGameProc", AboutGameProc },
1877 { "AboutProc", AboutProc },
1878 { "DebugProc", DebugProc },
1879 { "NothingProc", NothingProc },
1880 { "CommentPopDown", (XtActionProc) CommentPopDown },
1881 { "EditCommentPopDown", (XtActionProc) EditCommentPopDown },
1882 { "TagsPopDown", (XtActionProc) TagsPopDown },
1883 { "ErrorPopDown", (XtActionProc) ErrorPopDown },
1884 { "ICSInputBoxPopDown", (XtActionProc) ICSInputBoxPopDown },
1885 { "AnalysisPopDown", (XtActionProc) AnalysisPopDown },
1886 { "FileNamePopDown", (XtActionProc) FileNamePopDown },
1887 { "AskQuestionPopDown", (XtActionProc) AskQuestionPopDown },
1888 { "GameListPopDown", (XtActionProc) GameListPopDown },
1889 { "PromotionPopDown", (XtActionProc) PromotionPopDown },
1890 { "HistoryPopDown", (XtActionProc) HistoryPopDown },
1891 { "EngineOutputPopDown", (XtActionProc) EngineOutputPopDown },
1892 { "ShufflePopDown", (XtActionProc) ShufflePopDown },
1893 { "EnginePopDown", (XtActionProc) EnginePopDown },
1894 { "UciPopDown", (XtActionProc) UciPopDown },
1895 { "TimeControlPopDown", (XtActionProc) TimeControlPopDown },
1896 { "NewVariantPopDown", (XtActionProc) NewVariantPopDown },
1897 { "SettingsPopDown", (XtActionProc) SettingsPopDown },
1900 char globalTranslations[] =
1901 ":<Key>R: ResignProc() \n \
1902 :<Key>r: ResetProc() \n \
1903 :<Key>g: LoadGameProc() \n \
1904 :<Key>N: LoadNextGameProc() \n \
1905 :<Key>P: LoadPrevGameProc() \n \
1906 :<Key>Q: QuitProc() \n \
1907 :<Key>F: ToEndProc() \n \
1908 :<Key>f: ForwardProc() \n \
1909 :<Key>B: ToStartProc() \n \
1910 :<Key>b: BackwardProc() \n \
1911 :<Key>p: PauseProc() \n \
1912 :<Key>d: DrawProc() \n \
1913 :<Key>t: CallFlagProc() \n \
1914 :<Key>i: Iconify() \n \
1915 :<Key>c: Iconify() \n \
1916 :<Key>v: FlipViewProc() \n \
1917 <KeyDown>Control_L: BackwardProc() \n \
1918 <KeyUp>Control_L: ForwardProc() \n \
1919 <KeyDown>Control_R: BackwardProc() \n \
1920 <KeyUp>Control_R: ForwardProc() \n \
1921 Shift<Key>1: AskQuestionProc(\"Direct command\",\
1922 \"Send to chess program:\",,1) \n \
1923 Shift<Key>2: AskQuestionProc(\"Direct command\",\
1924 \"Send to second chess program:\",,2) \n";
1926 char boardTranslations[] =
1927 "<Btn1Down>: HandleUserMove() \n \
1928 <Btn1Up>: HandleUserMove() \n \
1929 <Btn1Motion>: AnimateUserMove() \n \
1930 Shift<Btn2Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD)\
1931 PieceMenuPopup(menuB) \n \
1932 Any<Btn2Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD) \
1933 PieceMenuPopup(menuW) \n \
1934 Shift<Btn3Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD)\
1935 PieceMenuPopup(menuW) \n \
1936 Any<Btn3Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD) \
1937 PieceMenuPopup(menuB) \n";
1939 char whiteTranslations[] = "<BtnDown>: WhiteClock()\n";
1940 char blackTranslations[] = "<BtnDown>: BlackClock()\n";
1942 char ICSInputTranslations[] =
1943 "<Key>Return: EnterKeyProc() \n";
1945 String xboardResources[] = {
1946 "*fileName*value.translations: #override\\n <Key>Return: FileNameAction()",
1947 "*question*value.translations: #override\\n <Key>Return: AskQuestionReplyAction()",
1948 "*errorpopup*translations: #override\\n <Key>Return: ErrorPopDown()",
1953 /* Max possible square size */
1954 #define MAXSQSIZE 256
1956 static int xpm_avail[MAXSQSIZE];
1958 #ifdef HAVE_DIR_STRUCT
1960 /* Extract piece size from filename */
1962 xpm_getsize(name, len, ext)
1973 if ((p=strchr(name, '.')) == NULL ||
1974 StrCaseCmp(p+1, ext) != 0)
1980 while (*p && isdigit(*p))
1987 /* Setup xpm_avail */
1989 xpm_getavail(dirname, ext)
1997 for (i=0; i<MAXSQSIZE; ++i)
2000 if (appData.debugMode)
2001 fprintf(stderr, "XPM dir:%s:ext:%s:\n", dirname, ext);
2003 dir = opendir(dirname);
2006 fprintf(stderr, _("%s: Can't access XPM directory %s\n"),
2007 programName, dirname);
2011 while ((ent=readdir(dir)) != NULL) {
2012 i = xpm_getsize(ent->d_name, NAMLEN(ent), ext);
2013 if (i > 0 && i < MAXSQSIZE)
2023 xpm_print_avail(fp, ext)
2029 fprintf(fp, _("Available `%s' sizes:\n"), ext);
2030 for (i=1; i<MAXSQSIZE; ++i) {
2036 /* Return XPM piecesize closest to size */
2038 xpm_closest_to(dirname, size, ext)
2044 int sm_diff = MAXSQSIZE;
2048 xpm_getavail(dirname, ext);
2050 if (appData.debugMode)
2051 xpm_print_avail(stderr, ext);
2053 for (i=1; i<MAXSQSIZE; ++i) {
2056 diff = (diff<0) ? -diff : diff;
2057 if (diff < sm_diff) {
2065 fprintf(stderr, _("Error: No `%s' files!\n"), ext);
2071 #else /* !HAVE_DIR_STRUCT */
2072 /* If we are on a system without a DIR struct, we can't
2073 read the directory, so we can't collect a list of
2074 filenames, etc., so we can't do any size-fitting. */
2076 xpm_closest_to(dirname, size, ext)
2081 fprintf(stderr, _("\
2082 Warning: No DIR structure found on this system --\n\
2083 Unable to autosize for XPM/XIM pieces.\n\
2084 Please report this error to frankm@hiwaay.net.\n\
2085 Include system type & operating system in message.\n"));
2088 #endif /* HAVE_DIR_STRUCT */
2090 static char *cnames[9] = { "black", "red", "green", "yellow", "blue",
2091 "magenta", "cyan", "white" };
2095 TextColors textColors[(int)NColorClasses];
2097 /* String is: "fg, bg, attr". Which is 0, 1, 2 */
2099 parse_color(str, which)
2103 char *p, buf[100], *d;
2106 if (strlen(str) > 99) /* watch bounds on buf */
2111 for (i=0; i<which; ++i) {
2118 /* Could be looking at something like:
2120 .. in which case we want to stop on a comma also */
2121 while (*p && *p != ',' && !isalpha(*p) && !isdigit(*p))
2125 return -1; /* Use default for empty field */
2128 if (which == 2 || isdigit(*p))
2131 while (*p && isalpha(*p))
2136 for (i=0; i<8; ++i) {
2137 if (!StrCaseCmp(buf, cnames[i]))
2138 return which? (i+40) : (i+30);
2140 if (!StrCaseCmp(buf, "default")) return -1;
2142 fprintf(stderr, _("%s: unrecognized color %s\n"), programName, buf);
2147 parse_cpair(cc, str)
2151 if ((textColors[(int)cc].fg=parse_color(str, 0)) == -2) {
2152 fprintf(stderr, _("%s: can't parse foreground color in `%s'\n"),
2157 /* bg and attr are optional */
2158 textColors[(int)cc].bg = parse_color(str, 1);
2159 if ((textColors[(int)cc].attr = parse_color(str, 2)) < 0) {
2160 textColors[(int)cc].attr = 0;
2166 /* Arrange to catch delete-window events */
2167 Atom wm_delete_window;
2169 CatchDeleteWindow(Widget w, String procname)
2172 XSetWMProtocols(xDisplay, XtWindow(w), &wm_delete_window, 1);
2173 snprintf(buf, sizeof(buf), "<Message>WM_PROTOCOLS: %s() \n", procname);
2174 XtAugmentTranslations(w, XtParseTranslationTable(buf));
2181 XtSetArg(args[0], XtNiconic, False);
2182 XtSetValues(shellWidget, args, 1);
2184 XtPopup(shellWidget, XtGrabNone); /* Raise if lowered */
2188 // eventually, all layout determining code should go into a subroutine, but until then IDSIZE remains undefined
2190 #define BoardSize int
2191 void InitDrawingSizes(BoardSize boardSize, int flags)
2192 { // [HGM] resize is functional now, but for board format changes only (nr of ranks, files)
2193 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
2195 XtGeometryResult gres;
2198 if(!formWidget) return;
2201 * Enable shell resizing.
2203 shellArgs[0].value = (XtArgVal) &w;
2204 shellArgs[1].value = (XtArgVal) &h;
2205 XtGetValues(shellWidget, shellArgs, 2);
2207 shellArgs[4].value = 2*w; shellArgs[2].value = 10;
2208 shellArgs[5].value = 2*h; shellArgs[3].value = 10;
2209 XtSetValues(shellWidget, &shellArgs[2], 4);
2211 XtSetArg(args[0], XtNdefaultDistance, &sep);
2212 XtGetValues(formWidget, args, 1);
2214 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2215 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2218 XtSetArg(args[0], XtNwidth, boardWidth);
2219 XtSetArg(args[1], XtNheight, boardHeight);
2220 XtSetValues(boardWidget, args, 2);
2222 timerWidth = (boardWidth - sep) / 2;
2223 XtSetArg(args[0], XtNwidth, timerWidth);
2224 XtSetValues(whiteTimerWidget, args, 1);
2225 XtSetValues(blackTimerWidget, args, 1);
2227 XawFormDoLayout(formWidget, False);
2229 if (appData.titleInWindow) {
2231 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2232 XtSetArg(args[i], XtNheight, &h); i++;
2233 XtGetValues(titleWidget, args, i);
2235 w = boardWidth - 2*bor;
2237 XtSetArg(args[0], XtNwidth, &w);
2238 XtGetValues(menuBarWidget, args, 1);
2239 w = boardWidth - w - sep - 2*bor - 2; // WIDTH_FUDGE
2242 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
2243 if (gres != XtGeometryYes && appData.debugMode) {
2245 _("%s: titleWidget geometry error %d %d %d %d %d\n"),
2246 programName, gres, w, h, wr, hr);
2250 XawFormDoLayout(formWidget, True);
2253 * Inhibit shell resizing.
2255 shellArgs[0].value = w = (XtArgVal) boardWidth + marginW;
2256 shellArgs[1].value = h = (XtArgVal) boardHeight + marginH;
2257 shellArgs[4].value = shellArgs[2].value = w;
2258 shellArgs[5].value = shellArgs[3].value = h;
2259 XtSetValues(shellWidget, &shellArgs[0], 6);
2261 // [HGM] pieces: tailor piece bitmaps to needs of specific variant
2264 for(i=0; i<4; i++) {
2266 for(p=0; p<=(int)WhiteKing; p++)
2267 xpmPieceBitmap[i][p] = xpmPieceBitmap2[i][p]; // defaults
2268 if(gameInfo.variant == VariantShogi) {
2269 xpmPieceBitmap[i][(int)WhiteCannon] = xpmPieceBitmap2[i][(int)WhiteKing+1];
2270 xpmPieceBitmap[i][(int)WhiteNightrider] = xpmPieceBitmap2[i][(int)WhiteKing+2];
2271 xpmPieceBitmap[i][(int)WhiteSilver] = xpmPieceBitmap2[i][(int)WhiteKing+3];
2272 xpmPieceBitmap[i][(int)WhiteGrasshopper] = xpmPieceBitmap2[i][(int)WhiteKing+4];
2273 xpmPieceBitmap[i][(int)WhiteQueen] = xpmPieceBitmap2[i][(int)WhiteLance];
2276 if(gameInfo.variant == VariantGothic) {
2277 xpmPieceBitmap[i][(int)WhiteMarshall] = xpmPieceBitmap2[i][(int)WhiteSilver];
2281 // [HGM] why are thee ximMasks used at all? the ximPieceBitmaps seem to be never used!
2282 for(p=0; p<=(int)WhiteKing; p++)
2283 ximMaskPm[p] = ximMaskPm2[p]; // defaults
2284 if(gameInfo.variant == VariantShogi) {
2285 ximMaskPm[(int)WhiteCannon] = ximMaskPm2[(int)WhiteKing+1];
2286 ximMaskPm[(int)WhiteNightrider] = ximMaskPm2[(int)WhiteKing+2];
2287 ximMaskPm[(int)WhiteSilver] = ximMaskPm2[(int)WhiteKing+3];
2288 ximMaskPm[(int)WhiteGrasshopper] = ximMaskPm2[(int)WhiteKing+4];
2289 ximMaskPm[(int)WhiteQueen] = ximMaskPm2[(int)WhiteLance];
2292 if(gameInfo.variant == VariantGothic) {
2293 ximMaskPm[(int)WhiteMarshall] = ximMaskPm2[i][(int)WhiteSilver];
2299 for(i=0; i<2; i++) {
2301 for(p=0; p<=(int)WhiteKing; p++)
2302 pieceBitmap[i][p] = pieceBitmap2[i][p]; // defaults
2303 if(gameInfo.variant == VariantShogi) {
2304 pieceBitmap[i][(int)WhiteCannon] = pieceBitmap2[i][(int)WhiteKing+1];
2305 pieceBitmap[i][(int)WhiteNightrider] = pieceBitmap2[i][(int)WhiteKing+2];
2306 pieceBitmap[i][(int)WhiteSilver] = pieceBitmap2[i][(int)WhiteKing+3];
2307 pieceBitmap[i][(int)WhiteGrasshopper] = pieceBitmap2[i][(int)WhiteKing+4];
2308 pieceBitmap[i][(int)WhiteQueen] = pieceBitmap2[i][(int)WhiteLance];
2311 if(gameInfo.variant == VariantGothic) {
2312 pieceBitmap[i][(int)WhiteMarshall] = pieceBitmap2[i][(int)WhiteSilver];
2323 void EscapeExpand(char *p, char *q)
2324 { // [HGM] initstring: routine to shape up string arguments
2325 while(*p++ = *q++) if(p[-1] == '\\')
2327 case 'n': p[-1] = '\n'; break;
2328 case 'r': p[-1] = '\r'; break;
2329 case 't': p[-1] = '\t'; break;
2330 case '\\': p[-1] = '\\'; break;
2331 case 0: *p = 0; return;
2332 default: p[-1] = q[-1]; break;
2341 int i, j, clockFontPxlSize, coordFontPxlSize, fontPxlSize;
2342 XSetWindowAttributes window_attributes;
2344 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
2345 XrmValue vFrom, vTo;
2346 XtGeometryResult gres;
2349 int forceMono = False;
2352 // [HGM] before anything else, expand any indirection files amongst options
2353 char *argvCopy[1000]; // 1000 seems enough
2354 char newArgs[10000]; // holds actual characters
2357 srandom(time(0)); // [HGM] book: make random truly random
2360 for(i=0; i<argc; i++) {
2361 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2362 //fprintf(stderr, "arg %s\n", argv[i]);
2363 if(argv[i][0] != '@') argvCopy[j++] = argv[i]; else {
2365 FILE *f = fopen(argv[i]+1, "rb");
2366 if(f == NULL) { fprintf(stderr, _("ignore %s\n"), argv[i]); continue; } // do not expand non-existing
2367 argvCopy[j++] = newArgs + k; // get ready for first argument from file
2368 while((c = fgetc(f)) != EOF) { // each line of file inserts 1 argument in the list
2370 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2371 newArgs[k++] = 0; // terminate current arg
2372 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2373 argvCopy[j++] = newArgs + k; // get ready for next
2375 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2388 if(appData.debugMode,1) { // OK, appData is not initialized here yet...
2389 for(i=0; i<argc; i++) fprintf(stderr, "argv[%2d] = '%s'\n", i, argv[i]);
2394 setbuf(stdout, NULL);
2395 setbuf(stderr, NULL);
2398 programName = strrchr(argv[0], '/');
2399 if (programName == NULL)
2400 programName = argv[0];
2405 XtSetLanguageProc(NULL, NULL, NULL);
2406 bindtextdomain(PACKAGE, LOCALEDIR);
2407 textdomain(PACKAGE);
2411 XtAppInitialize(&appContext, "XBoard", shellOptions,
2412 XtNumber(shellOptions),
2413 &argc, argv, xboardResources, NULL, 0);
2415 fprintf(stderr, _("%s: unrecognized argument %s\n"),
2416 programName, argv[1]);
2417 fprintf(stderr, "Recognized options:\n");
2418 for(i = 0; i < XtNumber(shellOptions); i++) {
2419 j = fprintf(stderr, " %s%s", shellOptions[i].option,
2420 (shellOptions[i].argKind == XrmoptionSepArg
2422 if (i++ < XtNumber(shellOptions)) {
2423 fprintf(stderr, "%*c%s%s\n", 40 - j, ' ',
2424 shellOptions[i].option,
2425 (shellOptions[i].argKind == XrmoptionSepArg
2428 fprintf(stderr, "\n");
2435 if (p == NULL) p = "/tmp";
2436 i = strlen(p) + strlen("/.xboardXXXXXx.pgn") + 1;
2437 gameCopyFilename = (char*) malloc(i);
2438 gamePasteFilename = (char*) malloc(i);
2439 snprintf(gameCopyFilename,i, "%s/.xboard%05uc.pgn", p, getpid());
2440 snprintf(gamePasteFilename,i, "%s/.xboard%05up.pgn", p, getpid());
2442 XtGetApplicationResources(shellWidget, (XtPointer) &appData,
2443 clientResources, XtNumber(clientResources),
2446 { // [HGM] initstring: kludge to fix bad bug. expand '\n' characters in init string and computer string.
2447 static char buf[MSG_SIZ];
2448 EscapeExpand(buf, appData.initString);
2449 appData.initString = strdup(buf);
2450 EscapeExpand(buf, appData.secondInitString);
2451 appData.secondInitString = strdup(buf);
2452 EscapeExpand(buf, appData.firstComputerString);
2453 appData.firstComputerString = strdup(buf);
2454 EscapeExpand(buf, appData.secondComputerString);
2455 appData.secondComputerString = strdup(buf);
2458 if ((chessDir = (char *) getenv("CHESSDIR")) == NULL) {
2461 if (chdir(chessDir) != 0) {
2462 fprintf(stderr, _("%s: can't cd to CHESSDIR: "), programName);
2468 if (appData.debugMode && appData.nameOfDebugFile && strcmp(appData.nameOfDebugFile, "stderr")) {
2469 /* [DM] debug info to file [HGM] make the filename a command-line option, and allow it to remain stderr */
2470 if ((debugFP = fopen(appData.nameOfDebugFile, "w")) == NULL) {
2471 printf(_("Failed to open file '%s'\n"), appData.nameOfDebugFile);
2474 setbuf(debugFP, NULL);
2477 /* [HGM,HR] make sure board size is acceptable */
2478 if(appData.NrFiles > BOARD_SIZE ||
2479 appData.NrRanks > BOARD_SIZE )
2480 DisplayFatalError(_("Recompile with BOARD_SIZE > 12, to support this size"), 0, 2);
2483 /* This feature does not work; animation needs a rewrite */
2484 appData.highlightDragging = FALSE;
2488 xDisplay = XtDisplay(shellWidget);
2489 xScreen = DefaultScreen(xDisplay);
2490 wm_delete_window = XInternAtom(xDisplay, "WM_DELETE_WINDOW", True);
2492 gameInfo.variant = StringToVariant(appData.variant);
2493 InitPosition(FALSE);
2496 * Determine boardSize
2498 gameInfo.boardWidth = gameInfo.boardHeight = 8; // [HGM] boardsize: make sure we start as 8x8
2501 // [HGM] as long as we have not created the possibility to change size while running, start with requested size
2502 gameInfo.boardWidth = appData.NrFiles > 0 ? appData.NrFiles : 8;
2503 gameInfo.boardHeight = appData.NrRanks > 0 ? appData.NrRanks : 8;
2504 gameInfo.holdingsWidth = appData.holdingsSize > 0 ? 2 : 0;
2509 InitDrawingSizes(-1, 0); // [HGM] initsize: make this into a subroutine
2511 if (isdigit(appData.boardSize[0])) {
2512 i = sscanf(appData.boardSize, "%d,%d,%d,%d,%d,%d,%d", &squareSize,
2513 &lineGap, &clockFontPxlSize, &coordFontPxlSize,
2514 &fontPxlSize, &smallLayout, &tinyLayout);
2516 fprintf(stderr, _("%s: bad boardSize syntax %s\n"),
2517 programName, appData.boardSize);
2521 /* Find some defaults; use the nearest known size */
2522 SizeDefaults *szd, *nearest;
2523 int distance = 99999;
2524 nearest = szd = sizeDefaults;
2525 while (szd->name != NULL) {
2526 if (abs(szd->squareSize - squareSize) < distance) {
2528 distance = abs(szd->squareSize - squareSize);
2529 if (distance == 0) break;
2533 if (i < 2) lineGap = nearest->lineGap;
2534 if (i < 3) clockFontPxlSize = nearest->clockFontPxlSize;
2535 if (i < 4) coordFontPxlSize = nearest->coordFontPxlSize;
2536 if (i < 5) fontPxlSize = nearest->fontPxlSize;
2537 if (i < 6) smallLayout = nearest->smallLayout;
2538 if (i < 7) tinyLayout = nearest->tinyLayout;
2541 SizeDefaults *szd = sizeDefaults;
2542 if (*appData.boardSize == NULLCHAR) {
2543 while (DisplayWidth(xDisplay, xScreen) < szd->minScreenSize ||
2544 DisplayHeight(xDisplay, xScreen) < szd->minScreenSize) {
2547 if (szd->name == NULL) szd--;
2549 while (szd->name != NULL &&
2550 StrCaseCmp(szd->name, appData.boardSize) != 0) szd++;
2551 if (szd->name == NULL) {
2552 fprintf(stderr, _("%s: unrecognized boardSize name %s\n"),
2553 programName, appData.boardSize);
2557 squareSize = szd->squareSize;
2558 lineGap = szd->lineGap;
2559 clockFontPxlSize = szd->clockFontPxlSize;
2560 coordFontPxlSize = szd->coordFontPxlSize;
2561 fontPxlSize = szd->fontPxlSize;
2562 smallLayout = szd->smallLayout;
2563 tinyLayout = szd->tinyLayout;
2566 /* Now, using squareSize as a hint, find a good XPM/XIM set size */
2567 if (strlen(appData.pixmapDirectory) > 0) {
2568 p = ExpandPathName(appData.pixmapDirectory);
2570 fprintf(stderr, _("Error expanding path name \"%s\"\n"),
2571 appData.pixmapDirectory);
2574 if (appData.debugMode) {
2575 fprintf(stderr, _("\
2576 XBoard square size (hint): %d\n\
2577 %s fulldir:%s:\n"), squareSize, IMAGE_EXT, p);
2579 squareSize = xpm_closest_to(p, squareSize, IMAGE_EXT);
2580 if (appData.debugMode) {
2581 fprintf(stderr, _("Closest %s size: %d\n"), IMAGE_EXT, squareSize);
2585 /* [HR] height treated separately (hacked) */
2586 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2587 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2588 if (appData.showJail == 1) {
2589 /* Jail on top and bottom */
2590 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2591 XtSetArg(boardArgs[2], XtNheight,
2592 boardHeight + 2*(lineGap + squareSize));
2593 } else if (appData.showJail == 2) {
2595 XtSetArg(boardArgs[1], XtNwidth,
2596 boardWidth + 2*(lineGap + squareSize));
2597 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2600 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2601 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2605 * Determine what fonts to use.
2607 appData.clockFont = FindFont(appData.clockFont, clockFontPxlSize);
2608 clockFontID = XLoadFont(xDisplay, appData.clockFont);
2609 clockFontStruct = XQueryFont(xDisplay, clockFontID);
2610 appData.coordFont = FindFont(appData.coordFont, coordFontPxlSize);
2611 coordFontID = XLoadFont(xDisplay, appData.coordFont);
2612 coordFontStruct = XQueryFont(xDisplay, coordFontID);
2613 appData.font = FindFont(appData.font, fontPxlSize);
2614 countFontID = XLoadFont(xDisplay, appData.coordFont); // [HGM] holdings
2615 countFontStruct = XQueryFont(xDisplay, countFontID);
2616 // appData.font = FindFont(appData.font, fontPxlSize);
2618 xdb = XtDatabase(xDisplay);
2619 XrmPutStringResource(&xdb, "*font", appData.font);
2622 * Detect if there are not enough colors available and adapt.
2624 if (DefaultDepth(xDisplay, xScreen) <= 2) {
2625 appData.monoMode = True;
2628 if (!appData.monoMode) {
2629 vFrom.addr = (caddr_t) appData.lightSquareColor;
2630 vFrom.size = strlen(appData.lightSquareColor);
2631 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2632 if (vTo.addr == NULL) {
2633 appData.monoMode = True;
2636 lightSquareColor = *(Pixel *) vTo.addr;
2639 if (!appData.monoMode) {
2640 vFrom.addr = (caddr_t) appData.darkSquareColor;
2641 vFrom.size = strlen(appData.darkSquareColor);
2642 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2643 if (vTo.addr == NULL) {
2644 appData.monoMode = True;
2647 darkSquareColor = *(Pixel *) vTo.addr;
2650 if (!appData.monoMode) {
2651 vFrom.addr = (caddr_t) appData.whitePieceColor;
2652 vFrom.size = strlen(appData.whitePieceColor);
2653 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2654 if (vTo.addr == NULL) {
2655 appData.monoMode = True;
2658 whitePieceColor = *(Pixel *) vTo.addr;
2661 if (!appData.monoMode) {
2662 vFrom.addr = (caddr_t) appData.blackPieceColor;
2663 vFrom.size = strlen(appData.blackPieceColor);
2664 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2665 if (vTo.addr == NULL) {
2666 appData.monoMode = True;
2669 blackPieceColor = *(Pixel *) vTo.addr;
2673 if (!appData.monoMode) {
2674 vFrom.addr = (caddr_t) appData.highlightSquareColor;
2675 vFrom.size = strlen(appData.highlightSquareColor);
2676 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2677 if (vTo.addr == NULL) {
2678 appData.monoMode = True;
2681 highlightSquareColor = *(Pixel *) vTo.addr;
2685 if (!appData.monoMode) {
2686 vFrom.addr = (caddr_t) appData.premoveHighlightColor;
2687 vFrom.size = strlen(appData.premoveHighlightColor);
2688 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2689 if (vTo.addr == NULL) {
2690 appData.monoMode = True;
2693 premoveHighlightColor = *(Pixel *) vTo.addr;
2698 fprintf(stderr, _("%s: too few colors available; trying monochrome mode\n"),
2701 if (appData.bitmapDirectory == NULL ||
2702 appData.bitmapDirectory[0] == NULLCHAR)
2703 appData.bitmapDirectory = DEF_BITMAP_DIR;
2706 if (appData.lowTimeWarning && !appData.monoMode) {
2707 vFrom.addr = (caddr_t) appData.lowTimeWarningColor;
2708 vFrom.size = strlen(appData.lowTimeWarningColor);
2709 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2710 if (vTo.addr == NULL)
2711 appData.monoMode = True;
2713 lowTimeWarningColor = *(Pixel *) vTo.addr;
2716 if (appData.monoMode && appData.debugMode) {
2717 fprintf(stderr, _("white pixel = 0x%lx, black pixel = 0x%lx\n"),
2718 (unsigned long) XWhitePixel(xDisplay, xScreen),
2719 (unsigned long) XBlackPixel(xDisplay, xScreen));
2722 if (parse_cpair(ColorShout, appData.colorShout) < 0 ||
2723 parse_cpair(ColorSShout, appData.colorSShout) < 0 ||
2724 parse_cpair(ColorChannel1, appData.colorChannel1) < 0 ||
2725 parse_cpair(ColorChannel, appData.colorChannel) < 0 ||
2726 parse_cpair(ColorKibitz, appData.colorKibitz) < 0 ||
2727 parse_cpair(ColorTell, appData.colorTell) < 0 ||
2728 parse_cpair(ColorChallenge, appData.colorChallenge) < 0 ||
2729 parse_cpair(ColorRequest, appData.colorRequest) < 0 ||
2730 parse_cpair(ColorSeek, appData.colorSeek) < 0 ||
2731 parse_cpair(ColorNormal, appData.colorNormal) < 0)
2733 if (appData.colorize) {
2735 _("%s: can't parse color names; disabling colorization\n"),
2738 appData.colorize = FALSE;
2740 textColors[ColorNone].fg = textColors[ColorNone].bg = -1;
2741 textColors[ColorNone].attr = 0;
2743 XtAppAddActions(appContext, boardActions, XtNumber(boardActions));
2749 layoutName = "tinyLayout";
2750 } else if (smallLayout) {
2751 layoutName = "smallLayout";
2753 layoutName = "normalLayout";
2755 /* Outer layoutWidget is there only to provide a name for use in
2756 resources that depend on the layout style */
2758 XtCreateManagedWidget(layoutName, formWidgetClass, shellWidget,
2759 layoutArgs, XtNumber(layoutArgs));
2761 XtCreateManagedWidget("form", formWidgetClass, layoutWidget,
2762 formArgs, XtNumber(formArgs));
2763 XtSetArg(args[0], XtNdefaultDistance, &sep);
2764 XtGetValues(formWidget, args, 1);
2767 widgetList[j++] = menuBarWidget = CreateMenuBar(menuBar);
2768 XtSetArg(args[0], XtNtop, XtChainTop);
2769 XtSetArg(args[1], XtNbottom, XtChainTop);
2770 XtSetValues(menuBarWidget, args, 2);
2772 widgetList[j++] = whiteTimerWidget =
2773 XtCreateWidget("whiteTime", labelWidgetClass,
2774 formWidget, timerArgs, XtNumber(timerArgs));
2775 XtSetArg(args[0], XtNfont, clockFontStruct);
2776 XtSetArg(args[1], XtNtop, XtChainTop);
2777 XtSetArg(args[2], XtNbottom, XtChainTop);
2778 XtSetValues(whiteTimerWidget, args, 3);
2780 widgetList[j++] = blackTimerWidget =
2781 XtCreateWidget("blackTime", labelWidgetClass,
2782 formWidget, timerArgs, XtNumber(timerArgs));
2783 XtSetArg(args[0], XtNfont, clockFontStruct);
2784 XtSetArg(args[1], XtNtop, XtChainTop);
2785 XtSetArg(args[2], XtNbottom, XtChainTop);
2786 XtSetValues(blackTimerWidget, args, 3);
2788 if (appData.titleInWindow) {
2789 widgetList[j++] = titleWidget =
2790 XtCreateWidget("title", labelWidgetClass, formWidget,
2791 titleArgs, XtNumber(titleArgs));
2792 XtSetArg(args[0], XtNtop, XtChainTop);
2793 XtSetArg(args[1], XtNbottom, XtChainTop);
2794 XtSetValues(titleWidget, args, 2);
2797 if (appData.showButtonBar) {
2798 widgetList[j++] = buttonBarWidget = CreateButtonBar(buttonBar);
2799 XtSetArg(args[0], XtNleft, XtChainRight); // [HGM] glue to right window edge
2800 XtSetArg(args[1], XtNright, XtChainRight); // for good run-time sizing
2801 XtSetArg(args[2], XtNtop, XtChainTop);
2802 XtSetArg(args[3], XtNbottom, XtChainTop);
2803 XtSetValues(buttonBarWidget, args, 4);
2806 widgetList[j++] = messageWidget =
2807 XtCreateWidget("message", labelWidgetClass, formWidget,
2808 messageArgs, XtNumber(messageArgs));
2809 XtSetArg(args[0], XtNtop, XtChainTop);
2810 XtSetArg(args[1], XtNbottom, XtChainTop);
2811 XtSetValues(messageWidget, args, 2);
2813 widgetList[j++] = boardWidget =
2814 XtCreateWidget("board", widgetClass, formWidget, boardArgs,
2815 XtNumber(boardArgs));
2817 XtManageChildren(widgetList, j);
2819 timerWidth = (boardWidth - sep) / 2;
2820 XtSetArg(args[0], XtNwidth, timerWidth);
2821 XtSetValues(whiteTimerWidget, args, 1);
2822 XtSetValues(blackTimerWidget, args, 1);
2824 XtSetArg(args[0], XtNbackground, &timerBackgroundPixel);
2825 XtSetArg(args[1], XtNforeground, &timerForegroundPixel);
2826 XtGetValues(whiteTimerWidget, args, 2);
2828 if (appData.showButtonBar) {
2829 XtSetArg(args[0], XtNbackground, &buttonBackgroundPixel);
2830 XtSetArg(args[1], XtNforeground, &buttonForegroundPixel);
2831 XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
2835 * formWidget uses these constraints but they are stored
2839 XtSetArg(args[i], XtNfromHoriz, 0); i++;
2840 XtSetValues(menuBarWidget, args, i);
2841 if (appData.titleInWindow) {
2844 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2845 XtSetValues(whiteTimerWidget, args, i);
2847 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2848 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2849 XtSetValues(blackTimerWidget, args, i);
2851 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2852 XtSetArg(args[i], XtNjustify, XtJustifyLeft); i++;
2853 XtSetValues(titleWidget, args, i);
2855 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2856 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2857 XtSetValues(messageWidget, args, i);
2858 if (appData.showButtonBar) {
2860 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2861 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2862 XtSetValues(buttonBarWidget, args, i);
2866 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2867 XtSetValues(whiteTimerWidget, args, i);
2869 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2870 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2871 XtSetValues(blackTimerWidget, args, i);
2873 XtSetArg(args[i], XtNfromHoriz, menuBarWidget); i++;
2874 XtSetValues(titleWidget, args, i);
2876 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2877 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2878 XtSetValues(messageWidget, args, i);
2879 if (appData.showButtonBar) {
2881 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2882 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2883 XtSetValues(buttonBarWidget, args, i);
2888 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2889 XtSetValues(whiteTimerWidget, args, i);
2891 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2892 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2893 XtSetValues(blackTimerWidget, args, i);
2895 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2896 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2897 XtSetValues(messageWidget, args, i);
2898 if (appData.showButtonBar) {
2900 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2901 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2902 XtSetValues(buttonBarWidget, args, i);
2906 XtSetArg(args[0], XtNfromVert, messageWidget);
2907 XtSetArg(args[1], XtNtop, XtChainTop);
2908 XtSetArg(args[2], XtNbottom, XtChainBottom);
2909 XtSetArg(args[3], XtNleft, XtChainLeft);
2910 XtSetArg(args[4], XtNright, XtChainRight);
2911 XtSetValues(boardWidget, args, 5);
2913 XtRealizeWidget(shellWidget);
2916 * Correct the width of the message and title widgets.
2917 * It is not known why some systems need the extra fudge term.
2918 * The value "2" is probably larger than needed.
2920 XawFormDoLayout(formWidget, False);
2922 #define WIDTH_FUDGE 2
2924 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2925 XtSetArg(args[i], XtNheight, &h); i++;
2926 XtGetValues(messageWidget, args, i);
2927 if (appData.showButtonBar) {
2929 XtSetArg(args[i], XtNwidth, &w); i++;
2930 XtGetValues(buttonBarWidget, args, i);
2931 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2933 w = boardWidth - 2*bor + 1; /*!! +1 compensates for kludge below */
2936 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2937 if (gres != XtGeometryYes && appData.debugMode) {
2938 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2939 programName, gres, w, h, wr, hr);
2942 /* !! Horrible hack to work around bug in XFree86 4.0.1 (X11R6.4.3) */
2943 /* The size used for the child widget in layout lags one resize behind
2944 its true size, so we resize a second time, 1 pixel smaller. Yeech! */
2946 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2947 if (gres != XtGeometryYes && appData.debugMode) {
2948 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2949 programName, gres, w, h, wr, hr);
2952 XtSetArg(args[0], XtNleft, XtChainLeft); // [HGM] glue ends for good run-time sizing
2953 XtSetArg(args[1], XtNright, XtChainRight);
2954 XtSetValues(messageWidget, args, 2);
2956 if (appData.titleInWindow) {
2958 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2959 XtSetArg(args[i], XtNheight, &h); i++;
2960 XtGetValues(titleWidget, args, i);
2962 w = boardWidth - 2*bor;
2964 XtSetArg(args[0], XtNwidth, &w);
2965 XtGetValues(menuBarWidget, args, 1);
2966 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2969 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
2970 if (gres != XtGeometryYes && appData.debugMode) {
2972 _("%s: titleWidget geometry error %d %d %d %d %d\n"),
2973 programName, gres, w, h, wr, hr);
2976 XawFormDoLayout(formWidget, True);
2978 xBoardWindow = XtWindow(boardWidget);
2980 // [HGM] it seems the layout code ends here, but perhaps the color stuff is size independent and would
2981 // not need to go into InitDrawingSizes().
2985 * Create X checkmark bitmap and initialize option menu checks.
2987 ReadBitmap(&xMarkPixmap, "checkmark.bm",
2988 checkmark_bits, checkmark_width, checkmark_height);
2989 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
2990 if (appData.alwaysPromoteToQueen) {
2991 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
2994 if (appData.animateDragging) {
2995 XtSetValues(XtNameToWidget(menuBarWidget,
2996 "menuOptions.Animate Dragging"),
2999 if (appData.animate) {
3000 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
3003 if (appData.autoComment) {
3004 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
3007 if (appData.autoCallFlag) {
3008 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
3011 if (appData.autoFlipView) {
3012 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Auto Flip View"),
3015 if (appData.autoObserve) {
3016 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
3019 if (appData.autoRaiseBoard) {
3020 XtSetValues(XtNameToWidget(menuBarWidget,
3021 "menuOptions.Auto Raise Board"), args, 1);
3023 if (appData.autoSaveGames) {
3024 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
3027 if (appData.saveGameFile[0] != NULLCHAR) {
3028 /* Can't turn this off from menu */
3029 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
3031 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
3035 if (appData.blindfold) {
3036 XtSetValues(XtNameToWidget(menuBarWidget,
3037 "menuOptions.Blindfold"), args, 1);
3039 if (appData.flashCount > 0) {
3040 XtSetValues(XtNameToWidget(menuBarWidget,
3041 "menuOptions.Flash Moves"),
3044 if (appData.getMoveList) {
3045 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
3049 if (appData.highlightDragging) {
3050 XtSetValues(XtNameToWidget(menuBarWidget,
3051 "menuOptions.Highlight Dragging"),
3055 if (appData.highlightLastMove) {
3056 XtSetValues(XtNameToWidget(menuBarWidget,
3057 "menuOptions.Highlight Last Move"),
3060 if (appData.icsAlarm) {
3061 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.ICS Alarm"),
3064 if (appData.ringBellAfterMoves) {
3065 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
3068 if (appData.oldSaveStyle) {
3069 XtSetValues(XtNameToWidget(menuBarWidget,
3070 "menuOptions.Old Save Style"), args, 1);
3072 if (appData.periodicUpdates) {
3073 XtSetValues(XtNameToWidget(menuBarWidget,
3074 "menuOptions.Periodic Updates"), args, 1);
3076 if (appData.ponderNextMove) {
3077 XtSetValues(XtNameToWidget(menuBarWidget,
3078 "menuOptions.Ponder Next Move"), args, 1);
3080 if (appData.popupExitMessage) {
3081 XtSetValues(XtNameToWidget(menuBarWidget,
3082 "menuOptions.Popup Exit Message"), args, 1);
3084 if (appData.popupMoveErrors) {
3085 XtSetValues(XtNameToWidget(menuBarWidget,
3086 "menuOptions.Popup Move Errors"), args, 1);
3088 if (appData.premove) {
3089 XtSetValues(XtNameToWidget(menuBarWidget,
3090 "menuOptions.Premove"), args, 1);
3092 if (appData.quietPlay) {
3093 XtSetValues(XtNameToWidget(menuBarWidget,
3094 "menuOptions.Quiet Play"), args, 1);
3096 if (appData.showCoords) {
3097 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
3100 if (appData.hideThinkingFromHuman) {
3101 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
3104 if (appData.testLegality) {
3105 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Test Legality"),
3112 ReadBitmap(&wIconPixmap, "icon_white.bm",
3113 icon_white_bits, icon_white_width, icon_white_height);
3114 ReadBitmap(&bIconPixmap, "icon_black.bm",
3115 icon_black_bits, icon_black_width, icon_black_height);
3116 iconPixmap = wIconPixmap;
3118 XtSetArg(args[i], XtNiconPixmap, iconPixmap); i++;
3119 XtSetValues(shellWidget, args, i);
3122 * Create a cursor for the board widget.
3124 window_attributes.cursor = XCreateFontCursor(xDisplay, XC_hand2);
3125 XChangeWindowAttributes(xDisplay, xBoardWindow,
3126 CWCursor, &window_attributes);
3129 * Inhibit shell resizing.
3131 shellArgs[0].value = (XtArgVal) &w;
3132 shellArgs[1].value = (XtArgVal) &h;
3133 XtGetValues(shellWidget, shellArgs, 2);
3134 shellArgs[4].value = shellArgs[2].value = w;
3135 shellArgs[5].value = shellArgs[3].value = h;
3136 XtSetValues(shellWidget, &shellArgs[2], 4);
3137 marginW = w - boardWidth; // [HGM] needed to set new shellWidget size when we resize board
3138 marginH = h - boardHeight;
3140 CatchDeleteWindow(shellWidget, "QuitProc");
3145 if (appData.bitmapDirectory[0] != NULLCHAR) {
3152 /* Create regular pieces */
3153 if (!useImages) CreatePieces();
3158 if (appData.animate || appData.animateDragging)
3161 XtAugmentTranslations(formWidget,
3162 XtParseTranslationTable(globalTranslations));
3163 XtAugmentTranslations(boardWidget,
3164 XtParseTranslationTable(boardTranslations));
3165 XtAugmentTranslations(whiteTimerWidget,
3166 XtParseTranslationTable(whiteTranslations));
3167 XtAugmentTranslations(blackTimerWidget,
3168 XtParseTranslationTable(blackTranslations));
3170 /* Why is the following needed on some versions of X instead
3171 * of a translation? */
3172 XtAddEventHandler(boardWidget, ExposureMask, False,
3173 (XtEventHandler) EventProc, NULL);
3178 if (errorExitStatus == -1) {
3179 if (appData.icsActive) {
3180 /* We now wait until we see "login:" from the ICS before
3181 sending the logon script (problems with timestamp otherwise) */
3182 /*ICSInitScript();*/
3183 if (appData.icsInputBox) ICSInputBoxPopUp();
3186 signal(SIGINT, IntSigHandler);
3187 signal(SIGTERM, IntSigHandler);
3188 if (*appData.cmailGameName != NULLCHAR) {
3189 signal(SIGUSR1, CmailSigHandler);
3192 gameInfo.boardWidth = 0; // [HGM] pieces: kludge to ensure InitPosition() calls InitDrawingSizes()
3195 XtAppMainLoop(appContext);
3196 if (appData.debugMode) fclose(debugFP); // [DM] debug
3203 if (appData.icsActive && oldICSInteractionTitle != NULL) {
3204 DisplayIcsInteractionTitle(oldICSInteractionTitle);
3206 unlink(gameCopyFilename);
3207 unlink(gamePasteFilename);
3218 CmailSigHandler(sig)
3224 signal(SIGUSR1, SIG_IGN); /* suspend handler */
3226 /* Activate call-back function CmailSigHandlerCallBack() */
3227 OutputToProcess(cmailPR, (char *)(&dummy), sizeof(int), &error);
3229 signal(SIGUSR1, CmailSigHandler); /* re-activate handler */
3233 CmailSigHandlerCallBack(isr, closure, message, count, error)
3241 ReloadCmailMsgEvent(TRUE); /* Reload cmail msg */
3243 /**** end signal code ****/
3253 f = fopen(appData.icsLogon, "r");
3259 strcat(buf, appData.icsLogon);
3260 f = fopen(buf, "r");
3264 ProcessICSInitScript(f);
3271 EditCommentPopDown();
3282 SetMenuEnables(enab)
3286 if (!menuBarWidget) return;
3287 while (enab->name != NULL) {
3288 w = XtNameToWidget(menuBarWidget, enab->name);
3290 DisplayError(enab->name, 0);
3292 XtSetSensitive(w, enab->value);
3298 Enables icsEnables[] = {
3299 { "menuFile.Mail Move", False },
3300 { "menuFile.Reload CMail Message", False },
3301 { "menuMode.Machine Black", False },
3302 { "menuMode.Machine White", False },
3303 { "menuMode.Analysis Mode", False },
3304 { "menuMode.Analyze File", False },
3305 { "menuMode.Two Machines", False },
3307 { "menuHelp.Hint", False },
3308 { "menuHelp.Book", False },
3309 { "menuStep.Move Now", False },
3310 { "menuOptions.Periodic Updates", False },
3311 { "menuOptions.Hide Thinking", False },
3312 { "menuOptions.Ponder Next Move", False },
3317 Enables ncpEnables[] = {
3318 { "menuFile.Mail Move", False },
3319 { "menuFile.Reload CMail Message", False },
3320 { "menuMode.Machine White", False },
3321 { "menuMode.Machine Black", False },
3322 { "menuMode.Analysis Mode", False },
3323 { "menuMode.Analyze File", False },
3324 { "menuMode.Two Machines", False },
3325 { "menuMode.ICS Client", False },
3326 { "menuMode.ICS Input Box", False },
3327 { "Action", False },
3328 { "menuStep.Revert", False },
3329 { "menuStep.Move Now", False },
3330 { "menuStep.Retract Move", False },
3331 { "menuOptions.Auto Comment", False },
3332 { "menuOptions.Auto Flag", False },
3333 { "menuOptions.Auto Flip View", False },
3334 { "menuOptions.Auto Observe", False },
3335 { "menuOptions.Auto Raise Board", False },
3336 { "menuOptions.Get Move List", False },
3337 { "menuOptions.ICS Alarm", False },
3338 { "menuOptions.Move Sound", False },
3339 { "menuOptions.Quiet Play", False },
3340 { "menuOptions.Hide Thinking", False },
3341 { "menuOptions.Periodic Updates", False },
3342 { "menuOptions.Ponder Next Move", False },
3343 { "menuHelp.Hint", False },
3344 { "menuHelp.Book", False },
3348 Enables gnuEnables[] = {
3349 { "menuMode.ICS Client", False },
3350 { "menuMode.ICS Input Box", False },
3351 { "menuAction.Accept", False },
3352 { "menuAction.Decline", False },
3353 { "menuAction.Rematch", False },
3354 { "menuAction.Adjourn", False },
3355 { "menuAction.Stop Examining", False },
3356 { "menuAction.Stop Observing", False },
3357 { "menuStep.Revert", False },
3358 { "menuOptions.Auto Comment", False },
3359 { "menuOptions.Auto Observe", False },
3360 { "menuOptions.Auto Raise Board", False },
3361 { "menuOptions.Get Move List", False },
3362 { "menuOptions.Premove", False },
3363 { "menuOptions.Quiet Play", False },
3365 /* The next two options rely on SetCmailMode being called *after* */
3366 /* SetGNUMode so that when GNU is being used to give hints these */
3367 /* menu options are still available */
3369 { "menuFile.Mail Move", False },
3370 { "menuFile.Reload CMail Message", False },
3374 Enables cmailEnables[] = {
3376 { "menuAction.Call Flag", False },
3377 { "menuAction.Draw", True },
3378 { "menuAction.Adjourn", False },
3379 { "menuAction.Abort", False },
3380 { "menuAction.Stop Observing", False },
3381 { "menuAction.Stop Examining", False },
3382 { "menuFile.Mail Move", True },
3383 { "menuFile.Reload CMail Message", True },
3387 Enables trainingOnEnables[] = {
3388 { "menuMode.Edit Comment", False },
3389 { "menuMode.Pause", False },
3390 { "menuStep.Forward", False },
3391 { "menuStep.Backward", False },
3392 { "menuStep.Forward to End", False },
3393 { "menuStep.Back to Start", False },
3394 { "menuStep.Move Now", False },
3395 { "menuStep.Truncate Game", False },
3399 Enables trainingOffEnables[] = {
3400 { "menuMode.Edit Comment", True },
3401 { "menuMode.Pause", True },
3402 { "menuStep.Forward", True },
3403 { "menuStep.Backward", True },
3404 { "menuStep.Forward to End", True },
3405 { "menuStep.Back to Start", True },
3406 { "menuStep.Move Now", True },
3407 { "menuStep.Truncate Game", True },
3411 Enables machineThinkingEnables[] = {
3412 { "menuFile.Load Game", False },
3413 { "menuFile.Load Next Game", False },
3414 { "menuFile.Load Previous Game", False },
3415 { "menuFile.Reload Same Game", False },
3416 { "menuFile.Paste Game", False },
3417 { "menuFile.Load Position", False },
3418 { "menuFile.Load Next Position", False },
3419 { "menuFile.Load Previous Position", False },
3420 { "menuFile.Reload Same Position", False },
3421 { "menuFile.Paste Position", False },
3422 { "menuMode.Machine White", False },
3423 { "menuMode.Machine Black", False },
3424 { "menuMode.Two Machines", False },
3425 { "menuStep.Retract Move", False },
3429 Enables userThinkingEnables[] = {
3430 { "menuFile.Load Game", True },
3431 { "menuFile.Load Next Game", True },
3432 { "menuFile.Load Previous Game", True },
3433 { "menuFile.Reload Same Game", True },
3434 { "menuFile.Paste Game", True },
3435 { "menuFile.Load Position", True },
3436 { "menuFile.Load Next Position", True },
3437 { "menuFile.Load Previous Position", True },
3438 { "menuFile.Reload Same Position", True },
3439 { "menuFile.Paste Position", True },
3440 { "menuMode.Machine White", True },
3441 { "menuMode.Machine Black", True },
3442 { "menuMode.Two Machines", True },
3443 { "menuStep.Retract Move", True },
3449 SetMenuEnables(icsEnables);
3452 if (appData.zippyPlay && !appData.noChessProgram) /* [DM] icsEngineAnalyze */
3453 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Analysis Mode"), True);
3460 SetMenuEnables(ncpEnables);
3466 SetMenuEnables(gnuEnables);
3472 SetMenuEnables(cmailEnables);
3478 SetMenuEnables(trainingOnEnables);
3479 if (appData.showButtonBar) {
3480 XtSetSensitive(buttonBarWidget, False);
3486 SetTrainingModeOff()
3488 SetMenuEnables(trainingOffEnables);
3489 if (appData.showButtonBar) {
3490 XtSetSensitive(buttonBarWidget, True);
3495 SetUserThinkingEnables()
3497 if (appData.noChessProgram) return;
3498 SetMenuEnables(userThinkingEnables);
3502 SetMachineThinkingEnables()
3504 if (appData.noChessProgram) return;
3505 SetMenuEnables(machineThinkingEnables);
3507 case MachinePlaysBlack:
3508 case MachinePlaysWhite:
3509 case TwoMachinesPlay:
3510 XtSetSensitive(XtNameToWidget(menuBarWidget,
3511 ModeToWidgetName(gameMode)), True);
3518 #define Abs(n) ((n)<0 ? -(n) : (n))
3521 * Find a font that matches "pattern" that is as close as
3522 * possible to the targetPxlSize. Prefer fonts that are k
3523 * pixels smaller to fonts that are k pixels larger. The
3524 * pattern must be in the X Consortium standard format,
3525 * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".
3526 * The return value should be freed with XtFree when no
3529 char *FindFont(pattern, targetPxlSize)
3533 char **fonts, *p, *best, *scalable, *scalableTail;
3534 int i, j, nfonts, minerr, err, pxlSize;
3537 char **missing_list;
3539 char *def_string, *base_fnt_lst, strInt[3];
3541 XFontStruct **fnt_list;
3543 base_fnt_lst = calloc(1, strlen(pattern) + 3);
3544 sprintf(strInt, "%d", targetPxlSize);
3545 p = strstr(pattern, "--");
3546 strncpy(base_fnt_lst, pattern, p - pattern + 2);
3547 strcat(base_fnt_lst, strInt);
3548 strcat(base_fnt_lst, strchr(p + 2, '-'));
3550 if ((fntSet = XCreateFontSet(xDisplay,
3554 &def_string)) == NULL) {
3556 fprintf(stderr, _("Unable to create font set.\n"));
3560 nfonts = XFontsOfFontSet(fntSet, &fnt_list, &fonts);
3562 fonts = XListFonts(xDisplay, pattern, 999999, &nfonts);
3564 fprintf(stderr, _("%s: no fonts match pattern %s\n"),
3565 programName, pattern);
3573 for (i=0; i<nfonts; i++) {
3576 if (*p != '-') continue;
3578 if (*p == NULLCHAR) break;
3579 if (*p++ == '-') j++;
3581 if (j < 7) continue;
3584 scalable = fonts[i];
3587 err = pxlSize - targetPxlSize;
3588 if (Abs(err) < Abs(minerr) ||
3589 (minerr > 0 && err < 0 && -err == minerr)) {
3595 if (scalable && Abs(minerr) > appData.fontSizeTolerance) {
3596 /* If the error is too big and there is a scalable font,
3597 use the scalable font. */
3598 int headlen = scalableTail - scalable;
3599 p = (char *) XtMalloc(strlen(scalable) + 10);
3600 while (isdigit(*scalableTail)) scalableTail++;
3601 sprintf(p, "%.*s%d%s", headlen, scalable, targetPxlSize, scalableTail);
3603 p = (char *) XtMalloc(strlen(best) + 1);
3606 if (appData.debugMode) {
3607 fprintf(debugFP, _("resolved %s at pixel size %d\n to %s\n"),
3608 pattern, targetPxlSize, p);
3611 if (missing_count > 0)
3612 XFreeStringList(missing_list);
3613 XFreeFontSet(xDisplay, fntSet);
3615 XFreeFontNames(fonts);
3622 XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
3623 | GCBackground | GCFunction | GCPlaneMask;
3624 XGCValues gc_values;
3627 gc_values.plane_mask = AllPlanes;
3628 gc_values.line_width = lineGap;
3629 gc_values.line_style = LineSolid;
3630 gc_values.function = GXcopy;
3632 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3633 gc_values.background = XBlackPixel(xDisplay, xScreen);
3634 lineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3636 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3637 gc_values.background = XWhitePixel(xDisplay, xScreen);
3638 coordGC = XtGetGC(shellWidget, value_mask, &gc_values);
3639 XSetFont(xDisplay, coordGC, coordFontID);
3641 // [HGM] make font for holdings counts (white on black0
3642 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3643 gc_values.background = XBlackPixel(xDisplay, xScreen);
3644 countGC = XtGetGC(shellWidget, value_mask, &gc_values);
3645 XSetFont(xDisplay, countGC, countFontID);
3647 if (appData.monoMode) {
3648 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3649 gc_values.background = XWhitePixel(xDisplay, xScreen);
3650 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3652 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3653 gc_values.background = XBlackPixel(xDisplay, xScreen);
3654 lightSquareGC = wbPieceGC
3655 = XtGetGC(shellWidget, value_mask, &gc_values);
3657 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3658 gc_values.background = XWhitePixel(xDisplay, xScreen);
3659 darkSquareGC = bwPieceGC
3660 = XtGetGC(shellWidget, value_mask, &gc_values);
3662 if (DefaultDepth(xDisplay, xScreen) == 1) {
3663 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
3664 gc_values.function = GXcopyInverted;
3665 copyInvertedGC = XtGetGC(shellWidget, value_mask, &gc_values);
3666 gc_values.function = GXcopy;
3667 if (XBlackPixel(xDisplay, xScreen) == 1) {
3668 bwPieceGC = darkSquareGC;
3669 wbPieceGC = copyInvertedGC;
3671 bwPieceGC = copyInvertedGC;
3672 wbPieceGC = lightSquareGC;
3676 gc_values.foreground = highlightSquareColor;
3677 gc_values.background = highlightSquareColor;
3678 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3680 gc_values.foreground = premoveHighlightColor;
3681 gc_values.background = premoveHighlightColor;
3682 prelineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3684 gc_values.foreground = lightSquareColor;
3685 gc_values.background = darkSquareColor;
3686 lightSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3688 gc_values.foreground = darkSquareColor;
3689 gc_values.background = lightSquareColor;
3690 darkSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3692 gc_values.foreground = jailSquareColor;
3693 gc_values.background = jailSquareColor;
3694 jailSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3696 gc_values.foreground = whitePieceColor;
3697 gc_values.background = darkSquareColor;
3698 wdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3700 gc_values.foreground = whitePieceColor;
3701 gc_values.background = lightSquareColor;
3702 wlPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3704 gc_values.foreground = whitePieceColor;
3705 gc_values.background = jailSquareColor;
3706 wjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3708 gc_values.foreground = blackPieceColor;
3709 gc_values.background = darkSquareColor;
3710 bdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3712 gc_values.foreground = blackPieceColor;
3713 gc_values.background = lightSquareColor;
3714 blPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3716 gc_values.foreground = blackPieceColor;
3717 gc_values.background = jailSquareColor;
3718 bjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3722 void loadXIM(xim, xmask, filename, dest, mask)
3735 fp = fopen(filename, "rb");
3737 fprintf(stderr, _("%s: error loading XIM!\n"), programName);
3744 for (y=0; y<h; ++y) {
3745 for (x=0; x<h; ++x) {
3750 XPutPixel(xim, x, y, blackPieceColor);
3752 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3755 XPutPixel(xim, x, y, darkSquareColor);
3757 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3760 XPutPixel(xim, x, y, whitePieceColor);
3762 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3765 XPutPixel(xim, x, y, lightSquareColor);
3767 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3773 /* create Pixmap of piece */
3774 *dest = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3776 XPutImage(xDisplay, *dest, lightSquareGC, xim,
3779 /* create Pixmap of clipmask
3780 Note: We assume the white/black pieces have the same
3781 outline, so we make only 6 masks. This is okay
3782 since the XPM clipmask routines do the same. */
3784 temp = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3786 XPutImage(xDisplay, temp, lightSquareGC, xmask,
3789 /* now create the 1-bit version */
3790 *mask = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3793 values.foreground = 1;
3794 values.background = 0;
3796 /* Don't use XtGetGC, not read only */
3797 maskGC = XCreateGC(xDisplay, *mask,
3798 GCForeground | GCBackground, &values);
3799 XCopyPlane(xDisplay, temp, *mask, maskGC,
3800 0, 0, squareSize, squareSize, 0, 0, 1);
3801 XFreePixmap(xDisplay, temp);
3806 char pieceBitmapNames[] = "pnbrqfeacwmohijgdvlsukpnsl";
3808 void CreateXIMPieces()
3813 static char *ximkind[] = { "ll", "ld", "dl", "dd" };
3818 /* The XSynchronize calls were copied from CreatePieces.
3819 Not sure if needed, but can't hurt */
3820 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3823 /* temp needed by loadXIM() */
3824 ximtemp = XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3825 0, 0, ss, ss, AllPlanes, XYPixmap);
3827 if (strlen(appData.pixmapDirectory) == 0) {
3831 if (appData.monoMode) {
3832 DisplayFatalError(_("XIM pieces cannot be used in monochrome mode"),
3836 fprintf(stderr, _("\nLoading XIMs...\n"));
3838 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3839 fprintf(stderr, "%d", piece+1);
3840 for (kind=0; kind<4; kind++) {
3841 fprintf(stderr, ".");
3842 snprintf(buf, sizeof(buf), "%s/%s%c%s%u.xim",
3843 ExpandPathName(appData.pixmapDirectory),
3844 piece <= (int) WhiteKing ? "" : "w",
3845 pieceBitmapNames[piece],
3847 ximPieceBitmap[kind][piece] =
3848 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3849 0, 0, ss, ss, AllPlanes, XYPixmap);
3850 if (appData.debugMode)
3851 fprintf(stderr, _("(File:%s:) "), buf);
3852 loadXIM(ximPieceBitmap[kind][piece],
3854 &(xpmPieceBitmap2[kind][piece]),
3855 &(ximMaskPm2[piece]));
3856 if(piece <= (int)WhiteKing)
3857 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3859 fprintf(stderr," ");
3861 /* Load light and dark squares */
3862 /* If the LSQ and DSQ pieces don't exist, we will
3863 draw them with solid squares. */
3864 snprintf(buf,sizeof(buf), "%s/lsq%u.xim", ExpandPathName(appData.pixmapDirectory), ss);
3865 if (access(buf, 0) != 0) {
3869 fprintf(stderr, _("light square "));
3871 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3872 0, 0, ss, ss, AllPlanes, XYPixmap);
3873 if (appData.debugMode)
3874 fprintf(stderr, _("(File:%s:) "), buf);
3876 loadXIM(ximLightSquare, NULL, buf, &xpmLightSquare, NULL);
3877 fprintf(stderr, _("dark square "));
3878 snprintf(buf,sizeof(buf), "%s/dsq%u.xim",
3879 ExpandPathName(appData.pixmapDirectory), ss);
3880 if (appData.debugMode)
3881 fprintf(stderr, _("(File:%s:) "), buf);
3883 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3884 0, 0, ss, ss, AllPlanes, XYPixmap);
3885 loadXIM(ximDarkSquare, NULL, buf, &xpmDarkSquare, NULL);
3886 xpmJailSquare = xpmLightSquare;
3888 fprintf(stderr, _("Done.\n"));
3890 XSynchronize(xDisplay, False); /* Work-around for xlib/xt buffering bug */
3894 void CreateXPMPieces()
3898 u_int ss = squareSize;
3900 static char *xpmkind[] = { "ll", "ld", "dl", "dd" };
3901 XpmColorSymbol symbols[4];
3904 /* Apparently some versions of Xpm don't define XpmFormat at all --tpm */
3905 if (appData.debugMode) {
3906 fprintf(stderr, "XPM Library Version: %d.%d%c\n",
3907 XpmFormat, XpmVersion, (char)('a' + XpmRevision - 1));
3911 /* The XSynchronize calls were copied from CreatePieces.
3912 Not sure if needed, but can't hurt */
3913 XSynchronize(xDisplay, True); /* Work-around for xlib/xt buffering bug */
3915 /* Setup translations so piece colors match square colors */
3916 symbols[0].name = "light_piece";
3917 symbols[0].value = appData.whitePieceColor;
3918 symbols[1].name = "dark_piece";
3919 symbols[1].value = appData.blackPieceColor;
3920 symbols[2].name = "light_square";
3921 symbols[2].value = appData.lightSquareColor;
3922 symbols[3].name = "dark_square";
3923 symbols[3].value = appData.darkSquareColor;
3925 attr.valuemask = XpmColorSymbols;
3926 attr.colorsymbols = symbols;
3927 attr.numsymbols = 4;
3929 if (appData.monoMode) {
3930 DisplayFatalError(_("XPM pieces cannot be used in monochrome mode"),
3934 if (strlen(appData.pixmapDirectory) == 0) {
3935 XpmPieces* pieces = builtInXpms;
3938 while (pieces->size != squareSize && pieces->size) pieces++;
3939 if (!pieces->size) {
3940 fprintf(stderr, _("No builtin XPM pieces of size %d\n"), squareSize);
3943 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3944 for (kind=0; kind<4; kind++) {
3946 if ((r=XpmCreatePixmapFromData(xDisplay, xBoardWindow,
3947 pieces->xpm[piece][kind],
3948 &(xpmPieceBitmap2[kind][piece]),
3949 NULL, &attr)) != 0) {
3950 fprintf(stderr, _("Error %d loading XPM image \"%s\"\n"),
3954 if(piece <= (int) WhiteKing)
3955 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3959 xpmJailSquare = xpmLightSquare;
3963 fprintf(stderr, _("\nLoading XPMs...\n"));
3966 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3967 fprintf(stderr, "%d ", piece+1);
3968 for (kind=0; kind<4; kind++) {
3969 snprintf(buf, sizeof(buf), "%s/%s%c%s%u.xpm",
3970 ExpandPathName(appData.pixmapDirectory),
3971 piece > (int) WhiteKing ? "w" : "",
3972 pieceBitmapNames[piece],
3974 if (appData.debugMode) {
3975 fprintf(stderr, _("(File:%s:) "), buf);
3977 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3978 &(xpmPieceBitmap2[kind][piece]),
3979 NULL, &attr)) != 0) {
3980 if(piece != (int)WhiteKing && piece > (int)WhiteQueen) {
3981 // [HGM] missing: read of unorthodox piece failed; substitute King.
3982 snprintf(buf, sizeof(buf), "%s/k%s%u.xpm",
3983 ExpandPathName(appData.pixmapDirectory),
3985 if (appData.debugMode) {
3986 fprintf(stderr, _("(Replace by File:%s:) "), buf);
3988 r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3989 &(xpmPieceBitmap2[kind][piece]),
3993 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"),
3998 if(piece <= (int) WhiteKing)
3999 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
4002 /* Load light and dark squares */
4003 /* If the LSQ and DSQ pieces don't exist, we will
4004 draw them with solid squares. */
4005 fprintf(stderr, _("light square "));
4006 snprintf(buf, sizeof(buf), "%s/lsq%u.xpm", ExpandPathName(appData.pixmapDirectory), ss);
4007 if (access(buf, 0) != 0) {
4011 if (appData.debugMode)
4012 fprintf(stderr, _("(File:%s:) "), buf);
4014 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
4015 &xpmLightSquare, NULL, &attr)) != 0) {
4016 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
4019 fprintf(stderr, _("dark square "));
4020 snprintf(buf, sizeof(buf), "%s/dsq%u.xpm",
4021 ExpandPathName(appData.pixmapDirectory), ss);
4022 if (appData.debugMode) {
4023 fprintf(stderr, _("(File:%s:) "), buf);
4025 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
4026 &xpmDarkSquare, NULL, &attr)) != 0) {
4027 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
4031 xpmJailSquare = xpmLightSquare;
4032 fprintf(stderr, _("Done.\n"));
4034 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
4037 #endif /* HAVE_LIBXPM */
4040 /* No built-in bitmaps */
4045 u_int ss = squareSize;
4047 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
4050 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
4051 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
4052 sprintf(buf, "%s%c%u%c.bm", piece > (int)WhiteKing ? "w" : "",
4053 pieceBitmapNames[piece],
4054 ss, kind == SOLID ? 's' : 'o');
4055 ReadBitmap(&pieceBitmap2[kind][piece], buf, NULL, ss, ss);
4056 if(piece <= (int)WhiteKing)
4057 pieceBitmap[kind][piece] = pieceBitmap2[kind][piece];
4061 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
4065 /* With built-in bitmaps */
4068 BuiltInBits* bib = builtInBits;
4071 u_int ss = squareSize;
4073 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
4076 while (bib->squareSize != ss && bib->squareSize != 0) bib++;
4078 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
4079 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
4080 sprintf(buf, "%s%c%u%c.bm", piece > (int)WhiteKing ? "w" : "",
4081 pieceBitmapNames[piece],
4082 ss, kind == SOLID ? 's' : 'o');
4083 ReadBitmap(&pieceBitmap2[kind][piece], buf,
4084 bib->bits[kind][piece], ss, ss);
4085 if(piece <= (int)WhiteKing)
4086 pieceBitmap[kind][piece] = pieceBitmap2[kind][piece];
4090 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
4095 void ReadBitmap(pm, name, bits, wreq, hreq)
4098 unsigned char bits[];
4104 char msg[MSG_SIZ], fullname[MSG_SIZ];
4106 if (*appData.bitmapDirectory != NULLCHAR) {
4107 strcpy(fullname, appData.bitmapDirectory);
4108 strcat(fullname, "/");
4109 strcat(fullname, name);
4110 errcode = XReadBitmapFile(xDisplay, xBoardWindow, fullname,
4111 &w, &h, pm, &x_hot, &y_hot);
4112 fprintf(stderr, "load %s\n", name);
4113 if (errcode != BitmapSuccess) {
4115 case BitmapOpenFailed:
4116 snprintf(msg, sizeof(msg), _("Can't open bitmap file %s"), fullname);
4118 case BitmapFileInvalid:
4119 snprintf(msg, sizeof(msg), _("Invalid bitmap in file %s"), fullname);
4121 case BitmapNoMemory:
4122 snprintf(msg, sizeof(msg), _("Ran out of memory reading bitmap file %s"),
4126 snprintf(msg, sizeof(msg), _("Unknown XReadBitmapFile error %d on file %s"),
4130 fprintf(stderr, _("%s: %s...using built-in\n"),
4132 } else if (w != wreq || h != hreq) {
4134 _("%s: Bitmap %s is %dx%d, not %dx%d...using built-in\n"),
4135 programName, fullname, w, h, wreq, hreq);
4142 fprintf(stderr, _("%s: No built-in bitmap for %s; giving up\n"),
4146 ; // [HGM] bitmaps: make it non-fatal if we have no bitmap;
4148 *pm = XCreateBitmapFromData(xDisplay, xBoardWindow, (char *) bits,
4157 if (lineGap == 0) return;
4159 /* [HR] Split this into 2 loops for non-square boards. */
4161 for (i = 0; i < BOARD_HEIGHT + 1; i++) {
4162 gridSegments[i].x1 = 0;
4163 gridSegments[i].x2 =
4164 lineGap + BOARD_WIDTH * (squareSize + lineGap);
4165 gridSegments[i].y1 = gridSegments[i].y2
4166 = lineGap / 2 + (i * (squareSize + lineGap));
4169 for (j = 0; j < BOARD_WIDTH + 1; j++) {
4170 gridSegments[j + i].y1 = 0;
4171 gridSegments[j + i].y2 =
4172 lineGap + BOARD_HEIGHT * (squareSize + lineGap);
4173 gridSegments[j + i].x1 = gridSegments[j + i].x2
4174 = lineGap / 2 + (j * (squareSize + lineGap));
4178 static void MenuBarSelect(w, addr, index)
4183 XtActionProc proc = (XtActionProc) addr;
4185 (proc)(NULL, NULL, NULL, NULL);
4188 void CreateMenuBarPopup(parent, name, mb)
4198 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
4201 XtSetArg(args[j], XtNleftMargin, 20); j++;
4202 XtSetArg(args[j], XtNrightMargin, 20); j++;
4204 while (mi->string != NULL) {
4205 if (strcmp(mi->string, "----") == 0) {
4206 entry = XtCreateManagedWidget(mi->string, smeLineObjectClass,
4209 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string)));
4210 entry = XtCreateManagedWidget(mi->string, smeBSBObjectClass,
4212 XtAddCallback(entry, XtNcallback,
4213 (XtCallbackProc) MenuBarSelect,
4214 (caddr_t) mi->proc);
4220 Widget CreateMenuBar(mb)
4224 Widget anchor, menuBar;
4226 char menuName[MSG_SIZ];
4229 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
4230 XtSetArg(args[j], XtNvSpace, 0); j++;
4231 XtSetArg(args[j], XtNborderWidth, 0); j++;
4232 menuBar = XtCreateWidget("menuBar", boxWidgetClass,
4233 formWidget, args, j);
4235 while (mb->name != NULL) {
4236 strcpy(menuName, "menu");
4237 strcat(menuName, mb->name);
4239 XtSetArg(args[j], XtNmenuName, XtNewString(menuName)); j++;
4242 shortName[0] = _(mb->name)[0];
4243 shortName[1] = NULLCHAR;
4244 XtSetArg(args[j], XtNlabel, XtNewString(shortName)); j++;
4247 XtSetArg(args[j], XtNlabel, XtNewString(_(mb->name))); j++;
4250 XtSetArg(args[j], XtNborderWidth, 0); j++;
4251 anchor = XtCreateManagedWidget(mb->name, menuButtonWidgetClass,
4253 CreateMenuBarPopup(menuBar, menuName, mb);
4259 Widget CreateButtonBar(mi)
4263 Widget button, buttonBar;
4267 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
4269 XtSetArg(args[j], XtNhSpace, 0); j++;
4271 XtSetArg(args[j], XtNborderWidth, 0); j++;
4272 XtSetArg(args[j], XtNvSpace, 0); j++;
4273 buttonBar = XtCreateWidget("buttonBar", boxWidgetClass,
4274 formWidget, args, j);
4276 while (mi->string != NULL) {
4279 XtSetArg(args[j], XtNinternalWidth, 2); j++;
4280 XtSetArg(args[j], XtNborderWidth, 0); j++;
4282 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string))); j++;
4283 button = XtCreateManagedWidget(mi->string, commandWidgetClass,
4284 buttonBar, args, j);
4285 XtAddCallback(button, XtNcallback,
4286 (XtCallbackProc) MenuBarSelect,
4287 (caddr_t) mi->proc);
4294 CreatePieceMenu(name, color)
4301 ChessSquare selection;
4303 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
4304 boardWidget, args, 0);
4306 for (i = 0; i < PIECE_MENU_SIZE; i++) {
4307 String item = pieceMenuStrings[color][i];
4309 if (strcmp(item, "----") == 0) {
4310 entry = XtCreateManagedWidget(item, smeLineObjectClass,
4313 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
4314 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
4316 selection = pieceMenuTranslation[color][i];
4317 XtAddCallback(entry, XtNcallback,
4318 (XtCallbackProc) PieceMenuSelect,
4319 (caddr_t) selection);
4320 if (selection == WhitePawn || selection == BlackPawn) {
4321 XtSetArg(args[0], XtNpopupOnEntry, entry);
4322 XtSetValues(menu, args, 1);
4335 ChessSquare selection;
4337 whitePieceMenu = CreatePieceMenu("menuW", 0);
4338 blackPieceMenu = CreatePieceMenu("menuB", 1);
4340 XtRegisterGrabAction(PieceMenuPopup, True,
4341 (unsigned)(ButtonPressMask|ButtonReleaseMask),
4342 GrabModeAsync, GrabModeAsync);
4344 XtSetArg(args[0], XtNlabel, _("Drop"));
4345 dropMenu = XtCreatePopupShell("menuD", simpleMenuWidgetClass,
4346 boardWidget, args, 1);
4347 for (i = 0; i < DROP_MENU_SIZE; i++) {
4348 String item = dropMenuStrings[i];
4350 if (strcmp(item, "----") == 0) {
4351 entry = XtCreateManagedWidget(item, smeLineObjectClass,
4354 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
4355 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
4357 selection = dropMenuTranslation[i];
4358 XtAddCallback(entry, XtNcallback,
4359 (XtCallbackProc) DropMenuSelect,
4360 (caddr_t) selection);
4365 void SetupDropMenu()
4373 for (i=0; i<sizeof(dmEnables)/sizeof(DropMenuEnables); i++) {
4374 entry = XtNameToWidget(dropMenu, dmEnables[i].widget);
4375 p = strchr(gameMode == IcsPlayingWhite ? white_holding : black_holding,
4376 dmEnables[i].piece);
4377 XtSetSensitive(entry, p != NULL || !appData.testLegality
4378 /*!!temp:*/ || (gameInfo.variant == VariantCrazyhouse
4379 && !appData.icsActive));
4381 while (p && *p++ == dmEnables[i].piece) count++;
4382 snprintf(label, sizeof(label), "%s %d", dmEnables[i].widget, count);
4384 XtSetArg(args[j], XtNlabel, label); j++;
4385 XtSetValues(entry, args, j);
4389 void PieceMenuPopup(w, event, params, num_params)
4393 Cardinal *num_params;
4396 if (event->type != ButtonPress) return;
4397 if (errorUp) ErrorPopDown();
4401 whichMenu = params[0];
4403 case IcsPlayingWhite:
4404 case IcsPlayingBlack:
4406 case MachinePlaysWhite:
4407 case MachinePlaysBlack:
4408 if (appData.testLegality &&
4409 gameInfo.variant != VariantBughouse &&
4410 gameInfo.variant != VariantCrazyhouse) return;
4412 whichMenu = "menuD";
4418 if (((pmFromX = EventToSquare(event->xbutton.x, BOARD_WIDTH)) < 0) ||
4419 ((pmFromY = EventToSquare(event->xbutton.y, BOARD_HEIGHT)) < 0)) {
4420 pmFromX = pmFromY = -1;
4424 pmFromX = BOARD_WIDTH - 1 - pmFromX;
4426 pmFromY = BOARD_HEIGHT - 1 - pmFromY;
4428 XtPopupSpringLoaded(XtNameToWidget(boardWidget, whichMenu));
4431 static void PieceMenuSelect(w, piece, junk)
4436 if (pmFromX < 0 || pmFromY < 0) return;
4437 EditPositionMenuEvent(piece, pmFromX, pmFromY);
4440 static void DropMenuSelect(w, piece, junk)
4445 if (pmFromX < 0 || pmFromY < 0) return;
4446 DropMenuEvent(piece, pmFromX, pmFromY);
4449 void WhiteClock(w, event, prms, nprms)
4455 if (gameMode == EditPosition || gameMode == IcsExamining) {
4456 SetWhiteToPlayEvent();
4457 } else if (gameMode == IcsPlayingBlack || gameMode == MachinePlaysWhite) {
4462 void BlackClock(w, event, prms, nprms)
4468 if (gameMode == EditPosition || gameMode == IcsExamining) {
4469 SetBlackToPlayEvent();
4470 } else if (gameMode == IcsPlayingWhite || gameMode == MachinePlaysBlack) {
4477 * If the user selects on a border boundary, return -1; if off the board,
4478 * return -2. Otherwise map the event coordinate to the square.
4480 int EventToSquare(x, limit)
4488 if ((x % (squareSize + lineGap)) >= squareSize)
4490 x /= (squareSize + lineGap);
4496 static void do_flash_delay(msec)
4502 static void drawHighlight(file, rank, gc)
4508 if (lineGap == 0 || appData.blindfold) return;
4511 x = lineGap/2 + ((BOARD_WIDTH-1)-file) *
4512 (squareSize + lineGap);
4513 y = lineGap/2 + rank * (squareSize + lineGap);
4515 x = lineGap/2 + file * (squareSize + lineGap);
4516 y = lineGap/2 + ((BOARD_HEIGHT-1)-rank) *
4517 (squareSize + lineGap);
4520 XDrawRectangle(xDisplay, xBoardWindow, gc, x, y,
4521 squareSize+lineGap, squareSize+lineGap);
4524 int hi1X = -1, hi1Y = -1, hi2X = -1, hi2Y = -1;
4525 int pm1X = -1, pm1Y = -1, pm2X = -1, pm2Y = -1;
4528 SetHighlights(fromX, fromY, toX, toY)
4529 int fromX, fromY, toX, toY;
4531 if (hi1X != fromX || hi1Y != fromY) {
4532 if (hi1X >= 0 && hi1Y >= 0) {
4533 drawHighlight(hi1X, hi1Y, lineGC);
4535 if (fromX >= 0 && fromY >= 0) {
4536 drawHighlight(fromX, fromY, highlineGC);
4539 if (hi2X != toX || hi2Y != toY) {
4540 if (hi2X >= 0 && hi2Y >= 0) {
4541 drawHighlight(hi2X, hi2Y, lineGC);
4543 if (toX >= 0 && toY >= 0) {
4544 drawHighlight(toX, toY, highlineGC);
4556 SetHighlights(-1, -1, -1, -1);
4561 SetPremoveHighlights(fromX, fromY, toX, toY)
4562 int fromX, fromY, toX, toY;
4564 if (pm1X != fromX || pm1Y != fromY) {
4565 if (pm1X >= 0 && pm1Y >= 0) {
4566 drawHighlight(pm1X, pm1Y, lineGC);
4568 if (fromX >= 0 && fromY >= 0) {
4569 drawHighlight(fromX, fromY, prelineGC);
4572 if (pm2X != toX || pm2Y != toY) {
4573 if (pm2X >= 0 && pm2Y >= 0) {
4574 drawHighlight(pm2X, pm2Y, lineGC);
4576 if (toX >= 0 && toY >= 0) {
4577 drawHighlight(toX, toY, prelineGC);
4587 ClearPremoveHighlights()
4589 SetPremoveHighlights(-1, -1, -1, -1);
4592 static void BlankSquare(x, y, color, piece, dest)
4597 if (useImages && useImageSqs) {
4601 pm = xpmLightSquare;
4606 case 2: /* neutral */
4611 XCopyArea(xDisplay, pm, dest, wlPieceGC, 0, 0,
4612 squareSize, squareSize, x, y);
4622 case 2: /* neutral */
4627 XFillRectangle(xDisplay, dest, gc, x, y, squareSize, squareSize);
4632 I split out the routines to draw a piece so that I could
4633 make a generic flash routine.
4635 static void monoDrawPiece_1bit(piece, square_color, x, y, dest)
4637 int square_color, x, y;
4640 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
4641 switch (square_color) {
4643 case 2: /* neutral */
4645 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
4646 ? *pieceToOutline(piece)
4647 : *pieceToSolid(piece),
4648 dest, bwPieceGC, 0, 0,
4649 squareSize, squareSize, x, y);
4652 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
4653 ? *pieceToSolid(piece)
4654 : *pieceToOutline(piece),
4655 dest, wbPieceGC, 0, 0,
4656 squareSize, squareSize, x, y);
4661 static void monoDrawPiece(piece, square_color, x, y, dest)
4663 int square_color, x, y;
4666 switch (square_color) {
4668 case 2: /* neutral */
4670 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
4671 ? *pieceToOutline(piece)
4672 : *pieceToSolid(piece),
4673 dest, bwPieceGC, 0, 0,
4674 squareSize, squareSize, x, y, 1);
4677 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
4678 ? *pieceToSolid(piece)
4679 : *pieceToOutline(piece),
4680 dest, wbPieceGC, 0, 0,
4681 squareSize, squareSize, x, y, 1);
4686 static void colorDrawPiece(piece, square_color, x, y, dest)
4688 int square_color, x, y;
4691 if(pieceToSolid(piece) == NULL) return; // [HGM] bitmaps: make it non-fatal if we have no bitmap;
4692 switch (square_color) {
4694 XCopyPlane(xDisplay, *pieceToSolid(piece),
4695 dest, (int) piece < (int) BlackPawn
4696 ? wlPieceGC : blPieceGC, 0, 0,
4697 squareSize, squareSize, x, y, 1);
4700 XCopyPlane(xDisplay, *pieceToSolid(piece),
4701 dest, (int) piece < (int) BlackPawn
4702 ? wdPieceGC : bdPieceGC, 0, 0,
4703 squareSize, squareSize, x, y, 1);
4705 case 2: /* neutral */
4707 XCopyPlane(xDisplay, *pieceToSolid(piece),
4708 dest, (int) piece < (int) BlackPawn
4709 ? wjPieceGC : bjPieceGC, 0, 0,
4710 squareSize, squareSize, x, y, 1);
4715 static void colorDrawPieceImage(piece, square_color, x, y, dest)
4717 int square_color, x, y;
4722 switch (square_color) {
4724 case 2: /* neutral */
4726 if ((int)piece < (int) BlackPawn) {
4734 if ((int)piece < (int) BlackPawn) {
4742 XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
4743 dest, wlPieceGC, 0, 0,
4744 squareSize, squareSize, x, y);
4747 typedef void (*DrawFunc)();
4749 DrawFunc ChooseDrawFunc()
4751 if (appData.monoMode) {
4752 if (DefaultDepth(xDisplay, xScreen) == 1) {
4753 return monoDrawPiece_1bit;
4755 return monoDrawPiece;
4759 return colorDrawPieceImage;
4761 return colorDrawPiece;
4765 /* [HR] determine square color depending on chess variant. */
4766 static int SquareColor(row, column)
4771 if (gameInfo.variant == VariantXiangqi) {
4772 if (column >= 3 && column <= 5 && row >= 0 && row <= 2) {
4774 } else if (column >= 3 && column <= 5 && row >= 7 && row <= 9) {
4776 } else if (row <= 4) {
4782 square_color = ((column + row) % 2) == 1;
4785 /* [hgm] holdings: next line makes all holdings squares light */
4786 if(column < BOARD_LEFT || column >= BOARD_RGHT) square_color = 1;
4788 return square_color;
4791 void DrawSquare(row, column, piece, do_flash)
4792 int row, column, do_flash;
4795 int square_color, x, y, direction, font_ascent, font_descent;
4798 XCharStruct overall;
4802 /* Calculate delay in milliseconds (2-delays per complete flash) */
4803 flash_delay = 500 / appData.flashRate;
4806 x = lineGap + ((BOARD_WIDTH-1)-column) *
4807 (squareSize + lineGap);
4808 y = lineGap + row * (squareSize + lineGap);
4810 x = lineGap + column * (squareSize + lineGap);
4811 y = lineGap + ((BOARD_HEIGHT-1)-row) *
4812 (squareSize + lineGap);
4815 square_color = SquareColor(row, column);
4817 if ( // [HGM] holdings: blank out area between board and holdings
4818 column == BOARD_LEFT-1 || column == BOARD_RGHT
4819 || (column == BOARD_LEFT-2 && row < BOARD_HEIGHT-gameInfo.holdingsSize)
4820 || (column == BOARD_RGHT+1 && row >= gameInfo.holdingsSize) ) {
4821 BlankSquare(x, y, 2, EmptySquare, xBoardWindow);
4823 // [HGM] print piece counts next to holdings
4824 string[1] = NULLCHAR;
4825 if (column == (flipView ? BOARD_LEFT-1 : BOARD_RGHT) && piece > 1 ) {
4826 string[0] = '0' + piece;
4827 XTextExtents(countFontStruct, string, 1, &direction,
4828 &font_ascent, &font_descent, &overall);
4829 if (appData.monoMode) {
4830 XDrawImageString(xDisplay, xBoardWindow, countGC,
4831 x + squareSize - overall.width - 2,
4832 y + font_ascent + 1, string, 1);
4834 XDrawString(xDisplay, xBoardWindow, countGC,
4835 x + squareSize - overall.width - 2,
4836 y + font_ascent + 1, string, 1);
4839 if (column == (flipView ? BOARD_RGHT : BOARD_LEFT-1) && piece > 1) {
4840 string[0] = '0' + piece;
4841 XTextExtents(countFontStruct, string, 1, &direction,
4842 &font_ascent, &font_descent, &overall);
4843 if (appData.monoMode) {
4844 XDrawImageString(xDisplay, xBoardWindow, countGC,
4845 x + 2, y + font_ascent + 1, string, 1);
4847 XDrawString(xDisplay, xBoardWindow, countGC,
4848 x + 2, y + font_ascent + 1, string, 1);
4852 if (piece == EmptySquare || appData.blindfold) {
4853 BlankSquare(x, y, square_color, piece, xBoardWindow);
4855 drawfunc = ChooseDrawFunc();
4856 if (do_flash && appData.flashCount > 0) {
4857 for (i=0; i<appData.flashCount; ++i) {
4859 drawfunc(piece, square_color, x, y, xBoardWindow);
4860 XSync(xDisplay, False);
4861 do_flash_delay(flash_delay);
4863 BlankSquare(x, y, square_color, piece, xBoardWindow);
4864 XSync(xDisplay, False);
4865 do_flash_delay(flash_delay);
4868 drawfunc(piece, square_color, x, y, xBoardWindow);
4872 string[1] = NULLCHAR;
4873 if (appData.showCoords && row == (flipView ? BOARD_HEIGHT-1 : 0)
4874 && column >= BOARD_LEFT && column < BOARD_RGHT) {
4875 string[0] = 'a' + column - BOARD_LEFT;
4876 XTextExtents(coordFontStruct, string, 1, &direction,
4877 &font_ascent, &font_descent, &overall);
4878 if (appData.monoMode) {
4879 XDrawImageString(xDisplay, xBoardWindow, coordGC,
4880 x + squareSize - overall.width - 2,
4881 y + squareSize - font_descent - 1, string, 1);
4883 XDrawString(xDisplay, xBoardWindow, coordGC,
4884 x + squareSize - overall.width - 2,
4885 y + squareSize - font_descent - 1, string, 1);
4888 if (appData.showCoords && column == (flipView ? BOARD_RGHT-1 : BOARD_LEFT)) {
4889 string[0] = ONE + row;
4890 XTextExtents(coordFontStruct, string, 1, &direction,
4891 &font_ascent, &font_descent, &overall);
4892 if (appData.monoMode) {
4893 XDrawImageString(xDisplay, xBoardWindow, coordGC,
4894 x + 2, y + font_ascent + 1, string, 1);
4896 XDrawString(xDisplay, xBoardWindow, coordGC,
4897 x + 2, y + font_ascent + 1, string, 1);
4903 /* Why is this needed on some versions of X? */
4904 void EventProc(widget, unused, event)
4909 if (!XtIsRealized(widget))
4912 switch (event->type) {
4914 if (event->xexpose.count > 0) return; /* no clipping is done */
4915 XDrawPosition(widget, True, NULL);
4923 void DrawPosition(fullRedraw, board)
4924 /*Boolean*/int fullRedraw;
4927 XDrawPosition(boardWidget, fullRedraw, board);
4930 /* Returns 1 if there are "too many" differences between b1 and b2
4931 (i.e. more than 1 move was made) */
4932 static int too_many_diffs(b1, b2)
4938 for (i=0; i<BOARD_HEIGHT; ++i) {
4939 for (j=0; j<BOARD_WIDTH; ++j) {
4940 if (b1[i][j] != b2[i][j]) {
4941 if (++c > 4) /* Castling causes 4 diffs */
4950 /* Matrix describing castling maneuvers */
4951 /* Row, ColRookFrom, ColKingFrom, ColRookTo, ColKingTo */
4952 static int castling_matrix[4][5] = {
4953 { 0, 0, 4, 3, 2 }, /* 0-0-0, white */
4954 { 0, 7, 4, 5, 6 }, /* 0-0, white */
4955 { 7, 0, 4, 3, 2 }, /* 0-0-0, black */
4956 { 7, 7, 4, 5, 6 } /* 0-0, black */
4959 /* Checks whether castling occurred. If it did, *rrow and *rcol
4960 are set to the destination (row,col) of the rook that moved.
4962 Returns 1 if castling occurred, 0 if not.
4964 Note: Only handles a max of 1 castling move, so be sure
4965 to call too_many_diffs() first.
4967 static int check_castle_draw(newb, oldb, rrow, rcol)
4974 /* For each type of castling... */
4975 for (i=0; i<4; ++i) {
4976 r = castling_matrix[i];
4978 /* Check the 4 squares involved in the castling move */
4980 for (j=1; j<=4; ++j) {
4981 if (newb[r[0]][r[j]] == oldb[r[0]][r[j]]) {
4988 /* All 4 changed, so it must be a castling move */
4997 static int damage[BOARD_SIZE][BOARD_SIZE];
5000 * event handler for redrawing the board
5002 void XDrawPosition(w, repaint, board)
5004 /*Boolean*/int repaint;
5008 static int lastFlipView = 0;
5009 static int lastBoardValid = 0;
5010 static Board lastBoard;
5014 if (board == NULL) {
5015 if (!lastBoardValid) return;
5018 if (!lastBoardValid || lastFlipView != flipView) {
5019 XtSetArg(args[0], XtNleftBitmap, (flipView ? xMarkPixmap : None));
5020 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flip View"),
5025 * It would be simpler to clear the window with XClearWindow()
5026 * but this causes a very distracting flicker.
5029 if (!repaint && lastBoardValid && lastFlipView == flipView) {
5031 /* If too much changes (begin observing new game, etc.), don't
5033 do_flash = too_many_diffs(board, lastBoard) ? 0 : 1;
5035 /* Special check for castling so we don't flash both the king
5036 and the rook (just flash the king). */
5038 if (check_castle_draw(board, lastBoard, &rrow, &rcol)) {
5039 /* Draw rook with NO flashing. King will be drawn flashing later */
5040 DrawSquare(rrow, rcol, board[rrow][rcol], 0);
5041 lastBoard[rrow][rcol] = board[rrow][rcol];
5045 /* First pass -- Draw (newly) empty squares and repair damage.
5046 This prevents you from having a piece show up twice while it
5047 is flashing on its new square */
5048 for (i = 0; i < BOARD_HEIGHT; i++)
5049 for (j = 0; j < BOARD_WIDTH; j++)
5050 if ((board[i][j] != lastBoard[i][j] && board[i][j] == EmptySquare)
5052 DrawSquare(i, j, board[i][j], 0);
5053 damage[i][j] = False;
5056 /* Second pass -- Draw piece(s) in new position and flash them */
5057 for (i = 0; i < BOARD_HEIGHT; i++)
5058 for (j = 0; j < BOARD_WIDTH; j++)
5059 if (board[i][j] != lastBoard[i][j]) {
5060 DrawSquare(i, j, board[i][j], do_flash);
5064 XDrawSegments(xDisplay, xBoardWindow, lineGC,
5065 gridSegments, BOARD_HEIGHT + BOARD_WIDTH + 2);
5067 for (i = 0; i < BOARD_HEIGHT; i++)
5068 for (j = 0; j < BOARD_WIDTH; j++) {
5069 DrawSquare(i, j, board[i][j], 0);
5070 damage[i][j] = False;
5074 CopyBoard(lastBoard, board);
5076 lastFlipView = flipView;
5078 /* Draw highlights */
5079 if (pm1X >= 0 && pm1Y >= 0) {
5080 drawHighlight(pm1X, pm1Y, prelineGC);
5082 if (pm2X >= 0 && pm2Y >= 0) {
5083 drawHighlight(pm2X, pm2Y, prelineGC);
5085 if (hi1X >= 0 && hi1Y >= 0) {
5086 drawHighlight(hi1X, hi1Y, highlineGC);
5088 if (hi2X >= 0 && hi2Y >= 0) {
5089 drawHighlight(hi2X, hi2Y, highlineGC);
5092 /* If piece being dragged around board, must redraw that too */
5095 XSync(xDisplay, False);
5100 * event handler for redrawing the board
5102 void DrawPositionProc(w, event, prms, nprms)
5108 XDrawPosition(w, True, NULL);
5113 * event handler for parsing user moves
5115 // [HGM] This routine will need quite some reworking. Although the backend still supports the old
5116 // way of doing things, by calling UserMoveEvent() to test the legality of the move and then perform
5117 // it at the end, and doing all kind of preliminary tests here (e.g. to weed out self-captures), it
5118 // should be made to use the new way, of calling UserMoveTest early to determine the legality of the
5119 // move, (which will weed out the illegal selfcaptures and moves into the holdings, and flag promotions),
5120 // and at the end FinishMove() to perform the move after optional promotion popups.
5121 // For now I patched it to allow self-capture with King, and suppress clicks between board and holdings.
5122 void HandleUserMove(w, event, prms, nprms)
5129 Boolean saveAnimate;
5130 static int second = 0;
5132 if (w != boardWidget || errorExitStatus != -1) return;
5134 if (event->type == ButtonPress) ErrorPopDown();
5137 if (event->type == ButtonPress) {
5138 XtPopdown(promotionShell);
5139 XtDestroyWidget(promotionShell);
5140 promotionUp = False;
5148 x = EventToSquare(event->xbutton.x, BOARD_WIDTH);
5149 y = EventToSquare(event->xbutton.y, BOARD_HEIGHT);
5150 if (!flipView && y >= 0) {
5151 y = BOARD_HEIGHT - 1 - y;
5153 if (flipView && x >= 0) {
5154 x = BOARD_WIDTH - 1 - x;
5157 /* [HGM] holdings: next 5 lines: ignore all clicks between board and holdings */
5158 if(event->type == ButtonPress
5159 && ( x == BOARD_LEFT-1 || x == BOARD_RGHT
5160 || x == BOARD_LEFT-2 && y < BOARD_HEIGHT-gameInfo.holdingsSize
5161 || x == BOARD_RGHT+1 && y >= gameInfo.holdingsSize) )
5165 if (event->type == ButtonPress) {
5167 if (OKToStartUserMove(x, y)) {
5171 DragPieceBegin(event->xbutton.x, event->xbutton.y);
5172 if (appData.highlightDragging) {
5173 SetHighlights(x, y, -1, -1);
5181 if (event->type == ButtonPress && gameMode != EditPosition &&
5187 /* Check if clicking again on the same color piece */
5188 fromP = boards[currentMove][fromY][fromX];
5189 toP = boards[currentMove][y][x];
5190 frc = gameInfo.variant == VariantFischeRandom || gameInfo.variant == VariantCapaRandom;
5191 if ((WhitePawn <= fromP && fromP <= WhiteKing && // [HGM] this test should go, as UserMoveTest now does it.
5192 WhitePawn <= toP && toP <= WhiteKing &&
5193 !(fromP == WhiteKing && toP == WhiteRook && frc)) ||
5194 (BlackPawn <= fromP && fromP <= BlackKing &&
5195 BlackPawn <= toP && toP <= BlackKing &&
5196 !(fromP == BlackKing && toP == BlackRook && frc))) {
5197 /* Clicked again on same color piece -- changed his mind */
5198 second = (x == fromX && y == fromY);
5199 if (appData.highlightDragging) {
5200 SetHighlights(x, y, -1, -1);
5204 if (OKToStartUserMove(x, y)) {
5207 DragPieceBegin(event->xbutton.x, event->xbutton.y);
5213 if (event->type == ButtonRelease && x == fromX && y == fromY) {
5214 DragPieceEnd(event->xbutton.x, event->xbutton.y);
5215 if (appData.animateDragging) {
5216 /* Undo animation damage if any */
5217 DrawPosition(FALSE, NULL);
5220 /* Second up/down in same square; just abort move */
5225 ClearPremoveHighlights();
5227 /* First upclick in same square; start click-click mode */
5228 SetHighlights(x, y, -1, -1);
5233 /* Completed move */
5236 saveAnimate = appData.animate;
5237 if (event->type == ButtonPress) {
5238 /* Finish clickclick move */
5239 if (appData.animate || appData.highlightLastMove) {
5240 SetHighlights(fromX, fromY, toX, toY);
5245 /* Finish drag move */
5246 if (appData.highlightLastMove) {
5247 SetHighlights(fromX, fromY, toX, toY);
5251 DragPieceEnd(event->xbutton.x, event->xbutton.y);
5252 /* Don't animate move and drag both */
5253 appData.animate = FALSE;
5255 if (IsPromotion(fromX, fromY, toX, toY)) {
5256 if (appData.alwaysPromoteToQueen) {
5257 UserMoveEvent(fromX, fromY, toX, toY, 'q');
5258 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
5259 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
5262 SetHighlights(fromX, fromY, toX, toY);
5266 UserMoveEvent(fromX, fromY, toX, toY, NULLCHAR);
5267 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
5268 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
5271 appData.animate = saveAnimate;
5272 if (appData.animate || appData.animateDragging) {
5273 /* Undo animation damage if needed */
5274 DrawPosition(FALSE, NULL);
5278 void AnimateUserMove (Widget w, XEvent * event,
5279 String * params, Cardinal * nParams)
5281 DragPieceMove(event->xmotion.x, event->xmotion.y);
5284 Widget CommentCreate(name, text, mutable, callback, lines)
5286 int /*Boolean*/ mutable;
5287 XtCallbackProc callback;
5291 Widget shell, layout, form, edit, b_ok, b_cancel, b_clear, b_close, b_edit;
5296 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5297 XtGetValues(boardWidget, args, j);
5300 XtSetArg(args[j], XtNresizable, True); j++;
5303 XtCreatePopupShell(name, topLevelShellWidgetClass,
5304 shellWidget, args, j);
5307 XtCreatePopupShell(name, transientShellWidgetClass,
5308 shellWidget, args, j);
5311 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
5312 layoutArgs, XtNumber(layoutArgs));
5314 XtCreateManagedWidget("form", formWidgetClass, layout,
5315 formArgs, XtNumber(formArgs));
5319 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
5320 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
5322 XtSetArg(args[j], XtNstring, text); j++;
5323 XtSetArg(args[j], XtNtop, XtChainTop); j++;
5324 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5325 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5326 XtSetArg(args[j], XtNright, XtChainRight); j++;
5327 XtSetArg(args[j], XtNresizable, True); j++;
5328 XtSetArg(args[j], XtNwidth, bw_width); j++; /*force wider than buttons*/
5330 XtSetArg(args[j], XtNscrollVertical, XawtextScrollWhenNeeded); j++;
5332 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
5333 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
5335 XtSetArg(args[j], XtNautoFill, True); j++;
5336 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
5338 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
5342 XtSetArg(args[j], XtNfromVert, edit); j++;
5343 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5344 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5345 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5346 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5348 XtCreateManagedWidget(_("ok"), commandWidgetClass, form, args, j);
5349 XtAddCallback(b_ok, XtNcallback, callback, (XtPointer) 0);
5352 XtSetArg(args[j], XtNfromVert, edit); j++;
5353 XtSetArg(args[j], XtNfromHoriz, b_ok); j++;
5354 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5355 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5356 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5357 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5359 XtCreateManagedWidget(_("cancel"), commandWidgetClass, form, args, j);
5360 XtAddCallback(b_cancel, XtNcallback, callback, (XtPointer) 0);
5363 XtSetArg(args[j], XtNfromVert, edit); j++;
5364 XtSetArg(args[j], XtNfromHoriz, b_cancel); j++;
5365 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5366 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5367 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5368 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5370 XtCreateManagedWidget(_("clear"), commandWidgetClass, form, args, j);
5371 XtAddCallback(b_clear, XtNcallback, callback, (XtPointer) 0);
5374 XtSetArg(args[j], XtNfromVert, edit); j++;
5375 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5376 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5377 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5378 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5380 XtCreateManagedWidget(_("close"), commandWidgetClass, form, args, j);
5381 XtAddCallback(b_close, XtNcallback, callback, (XtPointer) 0);
5384 XtSetArg(args[j], XtNfromVert, edit); j++;
5385 XtSetArg(args[j], XtNfromHoriz, b_close); j++;
5386 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5387 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5388 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5389 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5391 XtCreateManagedWidget(_("edit"), commandWidgetClass, form, args, j);
5392 XtAddCallback(b_edit, XtNcallback, callback, (XtPointer) 0);
5395 XtRealizeWidget(shell);
5397 if (commentX == -1) {
5400 Dimension pw_height;
5401 Dimension ew_height;
5404 XtSetArg(args[j], XtNheight, &ew_height); j++;
5405 XtGetValues(edit, args, j);
5408 XtSetArg(args[j], XtNheight, &pw_height); j++;
5409 XtGetValues(shell, args, j);
5410 commentH = pw_height + (lines - 1) * ew_height;
5411 commentW = bw_width - 16;
5413 XSync(xDisplay, False);
5415 /* This code seems to tickle an X bug if it is executed too soon
5416 after xboard starts up. The coordinates get transformed as if
5417 the main window was positioned at (0, 0).
5419 XtTranslateCoords(shellWidget,
5420 (bw_width - commentW) / 2, 0 - commentH / 2,
5421 &commentX, &commentY);
5423 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
5424 RootWindowOfScreen(XtScreen(shellWidget)),
5425 (bw_width - commentW) / 2, 0 - commentH / 2,
5430 if (commentY < 0) commentY = 0; /*avoid positioning top offscreen*/
5433 XtSetArg(args[j], XtNheight, commentH); j++;
5434 XtSetArg(args[j], XtNwidth, commentW); j++;
5435 XtSetArg(args[j], XtNx, commentX); j++;
5436 XtSetArg(args[j], XtNy, commentY); j++;
5437 XtSetValues(shell, args, j);
5438 XtSetKeyboardFocus(shell, edit);
5443 /* Used for analysis window and ICS input window */
5444 Widget MiscCreate(name, text, mutable, callback, lines)
5446 int /*Boolean*/ mutable;
5447 XtCallbackProc callback;
5451 Widget shell, layout, form, edit;
5453 Dimension bw_width, pw_height, ew_height, w, h;
5459 XtSetArg(args[j], XtNresizable, True); j++;
5462 XtCreatePopupShell(name, topLevelShellWidgetClass,
5463 shellWidget, args, j);
5466 XtCreatePopupShell(name, transientShellWidgetClass,
5467 shellWidget, args, j);
5470 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
5471 layoutArgs, XtNumber(layoutArgs));
5473 XtCreateManagedWidget("form", formWidgetClass, layout,
5474 formArgs, XtNumber(formArgs));
5478 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
5479 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
5481 XtSetArg(args[j], XtNstring, text); j++;
5482 XtSetArg(args[j], XtNtop, XtChainTop); j++;
5483 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5484 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5485 XtSetArg(args[j], XtNright, XtChainRight); j++;
5486 XtSetArg(args[j], XtNresizable, True); j++;
5488 XtSetArg(args[j], XtNscrollVertical, XawtextScrollWhenNeeded); j++;
5490 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
5491 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
5493 XtSetArg(args[j], XtNautoFill, True); j++;
5494 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
5496 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
5498 XtRealizeWidget(shell);
5501 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5502 XtGetValues(boardWidget, args, j);
5505 XtSetArg(args[j], XtNheight, &ew_height); j++;
5506 XtGetValues(edit, args, j);
5509 XtSetArg(args[j], XtNheight, &pw_height); j++;
5510 XtGetValues(shell, args, j);
5511 h = pw_height + (lines - 1) * ew_height;
5514 XSync(xDisplay, False);
5516 /* This code seems to tickle an X bug if it is executed too soon
5517 after xboard starts up. The coordinates get transformed as if
5518 the main window was positioned at (0, 0).
5520 XtTranslateCoords(shellWidget, (bw_width - w) / 2, 0 - h / 2, &x, &y);
5522 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
5523 RootWindowOfScreen(XtScreen(shellWidget)),
5524 (bw_width - w) / 2, 0 - h / 2, &xx, &yy, &junk);
5528 if (y < 0) y = 0; /*avoid positioning top offscreen*/
5531 XtSetArg(args[j], XtNheight, h); j++;
5532 XtSetArg(args[j], XtNwidth, w); j++;
5533 XtSetArg(args[j], XtNx, x); j++;
5534 XtSetArg(args[j], XtNy, y); j++;
5535 XtSetValues(shell, args, j);
5541 static int savedIndex; /* gross that this is global */
5543 void EditCommentPopUp(index, title, text)
5552 if (text == NULL) text = "";
5554 if (editShell == NULL) {
5556 CommentCreate(title, text, True, EditCommentCallback, 4);
5557 XtRealizeWidget(editShell);
5558 CatchDeleteWindow(editShell, "EditCommentPopDown");
5560 edit = XtNameToWidget(editShell, "*form.text");
5562 XtSetArg(args[j], XtNstring, text); j++;
5563 XtSetValues(edit, args, j);
5565 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5566 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5567 XtSetValues(editShell, args, j);
5570 XtPopup(editShell, XtGrabNone);
5574 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
5575 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
5579 void EditCommentCallback(w, client_data, call_data)
5581 XtPointer client_data, call_data;
5589 XtSetArg(args[j], XtNlabel, &name); j++;
5590 XtGetValues(w, args, j);
5592 if (strcmp(name, _("ok")) == 0) {
5593 edit = XtNameToWidget(editShell, "*form.text");
5595 XtSetArg(args[j], XtNstring, &val); j++;
5596 XtGetValues(edit, args, j);
5597 ReplaceComment(savedIndex, val);
5598 EditCommentPopDown();
5599 } else if (strcmp(name, _("cancel")) == 0) {
5600 EditCommentPopDown();
5601 } else if (strcmp(name, _("clear")) == 0) {
5602 edit = XtNameToWidget(editShell, "*form.text");
5603 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
5604 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
5608 void EditCommentPopDown()
5613 if (!editUp) return;
5615 XtSetArg(args[j], XtNx, &commentX); j++;
5616 XtSetArg(args[j], XtNy, &commentY); j++;
5617 XtSetArg(args[j], XtNheight, &commentH); j++;
5618 XtSetArg(args[j], XtNwidth, &commentW); j++;
5619 XtGetValues(editShell, args, j);
5620 XtPopdown(editShell);
5623 XtSetArg(args[j], XtNleftBitmap, None); j++;
5624 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
5628 void ICSInputBoxPopUp()
5633 char *title = _("ICS Input");
5636 if (ICSInputShell == NULL) {
5637 ICSInputShell = MiscCreate(title, "", True, NULL, 1);
5638 tr = XtParseTranslationTable(ICSInputTranslations);
5639 edit = XtNameToWidget(ICSInputShell, "*form.text");
5640 XtOverrideTranslations(edit, tr);
5641 XtRealizeWidget(ICSInputShell);
5642 CatchDeleteWindow(ICSInputShell, "ICSInputBoxPopDown");
5645 edit = XtNameToWidget(ICSInputShell, "*form.text");
5647 XtSetArg(args[j], XtNstring, ""); j++;
5648 XtSetValues(edit, args, j);
5650 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5651 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5652 XtSetValues(ICSInputShell, args, j);
5655 XtPopup(ICSInputShell, XtGrabNone);
5656 XtSetKeyboardFocus(ICSInputShell, edit);
5658 ICSInputBoxUp = True;
5660 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
5661 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
5665 void ICSInputSendText()
5672 edit = XtNameToWidget(ICSInputShell, "*form.text");
5674 XtSetArg(args[j], XtNstring, &val); j++;
5675 XtGetValues(edit, args, j);
5676 SendMultiLineToICS(val);
5677 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
5678 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
5681 void ICSInputBoxPopDown()
5686 if (!ICSInputBoxUp) return;
5688 XtPopdown(ICSInputShell);
5689 ICSInputBoxUp = False;
5691 XtSetArg(args[j], XtNleftBitmap, None); j++;
5692 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
5696 void CommentPopUp(title, text)
5703 if (commentShell == NULL) {
5705 CommentCreate(title, text, False, CommentCallback, 4);
5706 XtRealizeWidget(commentShell);
5707 CatchDeleteWindow(commentShell, "CommentPopDown");
5709 edit = XtNameToWidget(commentShell, "*form.text");
5711 XtSetArg(args[j], XtNstring, text); j++;
5712 XtSetValues(edit, args, j);
5714 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5715 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5716 XtSetValues(commentShell, args, j);
5719 XtPopup(commentShell, XtGrabNone);
5720 XSync(xDisplay, False);
5725 void AnalysisPopUp(title, text)
5732 if (analysisShell == NULL) {
5733 analysisShell = MiscCreate(title, text, False, NULL, 4);
5734 XtRealizeWidget(analysisShell);
5735 CatchDeleteWindow(analysisShell, "AnalysisPopDown");
5738 edit = XtNameToWidget(analysisShell, "*form.text");
5740 XtSetArg(args[j], XtNstring, text); j++;
5741 XtSetValues(edit, args, j);
5743 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5744 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5745 XtSetValues(analysisShell, args, j);
5749 XtPopup(analysisShell, XtGrabNone);
5751 XSync(xDisplay, False);
5756 void CommentCallback(w, client_data, call_data)
5758 XtPointer client_data, call_data;
5765 XtSetArg(args[j], XtNlabel, &name); j++;
5766 XtGetValues(w, args, j);
5768 if (strcmp(name, _("close")) == 0) {
5770 } else if (strcmp(name, _("edit")) == 0) {
5777 void CommentPopDown()
5782 if (!commentUp) return;
5784 XtSetArg(args[j], XtNx, &commentX); j++;
5785 XtSetArg(args[j], XtNy, &commentY); j++;
5786 XtSetArg(args[j], XtNwidth, &commentW); j++;
5787 XtSetArg(args[j], XtNheight, &commentH); j++;
5788 XtGetValues(commentShell, args, j);
5789 XtPopdown(commentShell);
5790 XSync(xDisplay, False);
5794 void AnalysisPopDown()
5796 if (!analysisUp) return;
5797 XtPopdown(analysisShell);
5798 XSync(xDisplay, False);
5800 if (appData.icsEngineAnalyze) ExitAnalyzeMode(); /* [DM] icsEngineAnalyze */
5804 void FileNamePopUp(label, def, proc, openMode)
5811 Widget popup, layout, dialog, edit;
5817 fileProc = proc; /* I can't see a way not */
5818 fileOpenMode = openMode; /* to use globals here */
5821 XtSetArg(args[i], XtNresizable, True); i++;
5822 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
5823 XtSetArg(args[i], XtNtitle, XtNewString(_("File name prompt"))); i++;
5824 fileNameShell = popup =
5825 XtCreatePopupShell("File name prompt", transientShellWidgetClass,
5826 shellWidget, args, i);
5829 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
5830 layoutArgs, XtNumber(layoutArgs));
5833 XtSetArg(args[i], XtNlabel, label); i++;
5834 XtSetArg(args[i], XtNvalue, def); i++;
5835 XtSetArg(args[i], XtNborderWidth, 0); i++;
5836 dialog = XtCreateManagedWidget("fileName", dialogWidgetClass,
5839 XawDialogAddButton(dialog, _("ok"), FileNameCallback, (XtPointer) dialog);
5840 XawDialogAddButton(dialog, _("cancel"), FileNameCallback,
5841 (XtPointer) dialog);
5843 XtRealizeWidget(popup);
5844 CatchDeleteWindow(popup, "FileNamePopDown");
5846 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
5847 &x, &y, &win_x, &win_y, &mask);
5849 XtSetArg(args[0], XtNx, x - 10);
5850 XtSetArg(args[1], XtNy, y - 30);
5851 XtSetValues(popup, args, 2);
5853 XtPopup(popup, XtGrabExclusive);
5856 edit = XtNameToWidget(dialog, "*value");
5857 XtSetKeyboardFocus(popup, edit);
5860 void FileNamePopDown()
5862 if (!filenameUp) return;
5863 XtPopdown(fileNameShell);
5864 XtDestroyWidget(fileNameShell);
5869 void FileNameCallback(w, client_data, call_data)
5871 XtPointer client_data, call_data;
5876 XtSetArg(args[0], XtNlabel, &name);
5877 XtGetValues(w, args, 1);
5879 if (strcmp(name, _("cancel")) == 0) {
5884 FileNameAction(w, NULL, NULL, NULL);
5887 void FileNameAction(w, event, prms, nprms)
5899 name = XawDialogGetValueString(w = XtParent(w));
5901 if ((name != NULL) && (*name != NULLCHAR)) {
5903 XtPopdown(w = XtParent(XtParent(w)));
5907 p = strrchr(buf, ' ');
5914 fullname = ExpandPathName(buf);
5916 ErrorPopUp(_("Error"), _("Can't open file"), FALSE);
5919 f = fopen(fullname, fileOpenMode);
5921 DisplayError(_("Failed to open file"), errno);
5923 (void) (*fileProc)(f, index, buf);
5930 XtPopdown(w = XtParent(XtParent(w)));
5936 void PromotionPopUp()
5939 Widget dialog, layout;
5941 Dimension bw_width, pw_width;
5945 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5946 XtGetValues(boardWidget, args, j);
5949 XtSetArg(args[j], XtNresizable, True); j++;
5950 XtSetArg(args[j], XtNtitle, XtNewString(_("Promotion"))); j++;
5952 XtCreatePopupShell("Promotion", transientShellWidgetClass,
5953 shellWidget, args, j);
5955 XtCreateManagedWidget(layoutName, formWidgetClass, promotionShell,
5956 layoutArgs, XtNumber(layoutArgs));
5959 XtSetArg(args[j], XtNlabel, _("Promote to what?")); j++;
5960 XtSetArg(args[j], XtNborderWidth, 0); j++;
5961 dialog = XtCreateManagedWidget("promotion", dialogWidgetClass,
5964 if(gameInfo.variant != VariantShogi) {
5965 XawDialogAddButton(dialog, _("Queen"), PromotionCallback,
5966 (XtPointer) dialog);
5967 XawDialogAddButton(dialog, _("Rook"), PromotionCallback,
5968 (XtPointer) dialog);
5969 XawDialogAddButton(dialog, _("Bishop"), PromotionCallback,
5970 (XtPointer) dialog);
5971 XawDialogAddButton(dialog, _("Knight"), PromotionCallback,
5972 (XtPointer) dialog);
5973 if (!appData.testLegality || gameInfo.variant == VariantSuicide ||
5974 gameInfo.variant == VariantGiveaway) {
5975 XawDialogAddButton(dialog, _("King"), PromotionCallback,
5976 (XtPointer) dialog);
5978 if(gameInfo.variant == VariantCapablanca ||
5979 gameInfo.variant == VariantGothic ||
5980 gameInfo.variant == VariantCapaRandom) {
5981 XawDialogAddButton(dialog, _("Archbishop"), PromotionCallback,
5982 (XtPointer) dialog);
5983 XawDialogAddButton(dialog, _("Chancellor"), PromotionCallback,
5984 (XtPointer) dialog);
5986 } else // [HGM] shogi
5988 XawDialogAddButton(dialog, _("Promote"), PromotionCallback,
5989 (XtPointer) dialog);
5990 XawDialogAddButton(dialog, _("Defer"), PromotionCallback,
5991 (XtPointer) dialog);
5993 XawDialogAddButton(dialog, _("cancel"), PromotionCallback,
5994 (XtPointer) dialog);
5996 XtRealizeWidget(promotionShell);
5997 CatchDeleteWindow(promotionShell, "PromotionPopDown");
6000 XtSetArg(args[j], XtNwidth, &pw_width); j++;
6001 XtGetValues(promotionShell, args, j);
6003 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
6004 lineGap + squareSize/3 +
6005 ((toY == BOARD_HEIGHT-1) ^ (flipView) ?
6006 0 : 6*(squareSize + lineGap)), &x, &y);
6009 XtSetArg(args[j], XtNx, x); j++;
6010 XtSetArg(args[j], XtNy, y); j++;
6011 XtSetValues(promotionShell, args, j);
6013 XtPopup(promotionShell, XtGrabNone);
6018 void PromotionPopDown()
6020 if (!promotionUp) return;
6021 XtPopdown(promotionShell);
6022 XtDestroyWidget(promotionShell);
6023 promotionUp = False;
6026 void PromotionCallback(w, client_data, call_data)
6028 XtPointer client_data, call_data;
6034 XtSetArg(args[0], XtNlabel, &name);
6035 XtGetValues(w, args, 1);
6039 if (fromX == -1) return;
6041 if (strcmp(name, _("cancel")) == 0) {
6045 } else if (strcmp(name, _("Knight")) == 0) {
6047 } else if (strcmp(name, _("Promote")) == 0) {
6049 } else if (strcmp(name, _("Defer")) == 0) {
6052 promoChar = ToLower(name[0]);
6055 UserMoveEvent(fromX, fromY, toX, toY, promoChar);
6057 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
6058 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
6063 void ErrorCallback(w, client_data, call_data)
6065 XtPointer client_data, call_data;
6068 XtPopdown(w = XtParent(XtParent(XtParent(w))));
6070 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
6076 if (!errorUp) return;
6078 XtPopdown(errorShell);
6079 XtDestroyWidget(errorShell);
6080 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
6083 void ErrorPopUp(title, label, modal)
6084 char *title, *label;
6088 Widget dialog, layout;
6092 Dimension bw_width, pw_width;
6093 Dimension pw_height;
6097 XtSetArg(args[i], XtNresizable, True); i++;
6098 XtSetArg(args[i], XtNtitle, title); i++;
6100 XtCreatePopupShell("errorpopup", transientShellWidgetClass,
6101 shellWidget, args, i);
6103 XtCreateManagedWidget(layoutName, formWidgetClass, errorShell,
6104 layoutArgs, XtNumber(layoutArgs));
6107 XtSetArg(args[i], XtNlabel, label); i++;
6108 XtSetArg(args[i], XtNborderWidth, 0); i++;
6109 dialog = XtCreateManagedWidget("dialog", dialogWidgetClass,
6112 XawDialogAddButton(dialog, _("ok"), ErrorCallback, (XtPointer) dialog);
6114 XtRealizeWidget(errorShell);
6115 CatchDeleteWindow(errorShell, "ErrorPopDown");
6118 XtSetArg(args[i], XtNwidth, &bw_width); i++;
6119 XtGetValues(boardWidget, args, i);
6121 XtSetArg(args[i], XtNwidth, &pw_width); i++;
6122 XtSetArg(args[i], XtNheight, &pw_height); i++;
6123 XtGetValues(errorShell, args, i);
6126 /* This code seems to tickle an X bug if it is executed too soon
6127 after xboard starts up. The coordinates get transformed as if
6128 the main window was positioned at (0, 0).
6130 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
6131 0 - pw_height + squareSize / 3, &x, &y);
6133 XTranslateCoordinates(xDisplay, XtWindow(boardWidget),
6134 RootWindowOfScreen(XtScreen(boardWidget)),
6135 (bw_width - pw_width) / 2,
6136 0 - pw_height + squareSize / 3, &xx, &yy, &junk);
6140 if (y < 0) y = 0; /*avoid positioning top offscreen*/
6143 XtSetArg(args[i], XtNx, x); i++;
6144 XtSetArg(args[i], XtNy, y); i++;
6145 XtSetValues(errorShell, args, i);
6148 XtPopup(errorShell, modal ? XtGrabExclusive : XtGrabNone);
6151 /* Disable all user input other than deleting the window */
6152 static int frozen = 0;
6156 /* Grab by a widget that doesn't accept input */
6157 XtAddGrab(messageWidget, TRUE, FALSE);
6161 /* Undo a FreezeUI */
6164 if (!frozen) return;
6165 XtRemoveGrab(messageWidget);
6169 char *ModeToWidgetName(mode)
6173 case BeginningOfGame:
6174 if (appData.icsActive)
6175 return "menuMode.ICS Client";
6176 else if (appData.noChessProgram ||
6177 *appData.cmailGameName != NULLCHAR)
6178 return "menuMode.Edit Game";
6180 return "menuMode.Machine Black";
6181 case MachinePlaysBlack:
6182 return "menuMode.Machine Black";
6183 case MachinePlaysWhite:
6184 return "menuMode.Machine White";
6186 return "menuMode.Analysis Mode";
6188 return "menuMode.Analyze File";
6189 case TwoMachinesPlay:
6190 return "menuMode.Two Machines";
6192 return "menuMode.Edit Game";
6193 case PlayFromGameFile:
6194 return "menuFile.Load Game";
6196 return "menuMode.Edit Position";
6198 return "menuMode.Training";
6199 case IcsPlayingWhite:
6200 case IcsPlayingBlack:
6204 return "menuMode.ICS Client";
6211 void ModeHighlight()
6214 static int oldPausing = FALSE;
6215 static GameMode oldmode = (GameMode) -1;
6218 if (!boardWidget || !XtIsRealized(boardWidget)) return;
6220 if (pausing != oldPausing) {
6221 oldPausing = pausing;
6223 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6225 XtSetArg(args[0], XtNleftBitmap, None);
6227 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Pause"),
6230 if (appData.showButtonBar) {
6233 XtSetArg(args[0], XtNbackground, buttonForegroundPixel);
6234 XtSetArg(args[1], XtNforeground, buttonBackgroundPixel);
6236 XtSetArg(args[0], XtNbackground, buttonBackgroundPixel);
6237 XtSetArg(args[1], XtNforeground, buttonForegroundPixel);
6240 /* Always toggle, don't set. Previous code messes up when
6241 invoked while the button is pressed, as releasing it
6242 toggles the state again. */
6245 XtSetArg(args[0], XtNbackground, &oldbg);
6246 XtSetArg(args[1], XtNforeground, &oldfg);
6247 XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON),
6249 XtSetArg(args[0], XtNbackground, oldfg);
6250 XtSetArg(args[1], XtNforeground, oldbg);
6253 XtSetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
6257 wname = ModeToWidgetName(oldmode);
6258 if (wname != NULL) {
6259 XtSetArg(args[0], XtNleftBitmap, None);
6260 XtSetValues(XtNameToWidget(menuBarWidget, wname), args, 1);
6262 wname = ModeToWidgetName(gameMode);
6263 if (wname != NULL) {
6264 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6265 XtSetValues(XtNameToWidget(menuBarWidget, wname), args, 1);
6269 /* Maybe all the enables should be handled here, not just this one */
6270 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Training"),
6271 gameMode == Training || gameMode == PlayFromGameFile);
6276 * Button/menu procedures
6278 void ResetProc(w, event, prms, nprms)
6288 int LoadGamePopUp(f, gameNumber, title)
6293 cmailMsgLoaded = FALSE;
6294 if (gameNumber == 0) {
6295 int error = GameListBuild(f);
6297 DisplayError(_("Cannot build game list"), error);
6298 } else if (!ListEmpty(&gameList) &&
6299 ((ListGame *) gameList.tailPred)->number > 1) {
6300 GameListPopUp(f, title);
6306 return LoadGame(f, gameNumber, title, FALSE);
6309 void LoadGameProc(w, event, prms, nprms)
6315 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
6318 FileNamePopUp(_("Load game file name?"), "", LoadGamePopUp, "rb");
6321 void LoadNextGameProc(w, event, prms, nprms)
6330 void LoadPrevGameProc(w, event, prms, nprms)
6339 void ReloadGameProc(w, event, prms, nprms)
6348 void LoadNextPositionProc(w, event, prms, nprms)
6357 void LoadPrevPositionProc(w, event, prms, nprms)
6366 void ReloadPositionProc(w, event, prms, nprms)
6375 void LoadPositionProc(w, event, prms, nprms)
6381 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
6384 FileNamePopUp(_("Load position file name?"), "", LoadPosition, "rb");
6387 void SaveGameProc(w, event, prms, nprms)
6393 FileNamePopUp(_("Save game file name?"),
6394 DefaultFileName(appData.oldSaveStyle ? "game" : "pgn"),
6398 void SavePositionProc(w, event, prms, nprms)
6404 FileNamePopUp(_("Save position file name?"),
6405 DefaultFileName(appData.oldSaveStyle ? "pos" : "fen"),
6409 void ReloadCmailMsgProc(w, event, prms, nprms)
6415 ReloadCmailMsgEvent(FALSE);
6418 void MailMoveProc(w, event, prms, nprms)
6427 /* this variable is shared between CopyPositionProc and SendPositionSelection */
6428 static char *selected_fen_position=NULL;
6431 SendPositionSelection(Widget w, Atom *selection, Atom *target,
6432 Atom *type_return, XtPointer *value_return,
6433 unsigned long *length_return, int *format_return)
6435 char *selection_tmp;
6437 if (!selected_fen_position) return False; /* should never happen */
6438 if (*target == XA_STRING){
6439 /* note: since no XtSelectionDoneProc was registered, Xt will
6440 * automatically call XtFree on the value returned. So have to
6441 * make a copy of it allocated with XtMalloc */
6442 selection_tmp= XtMalloc(strlen(selected_fen_position)+16);
6443 strcpy(selection_tmp, selected_fen_position);
6445 *value_return=selection_tmp;
6446 *length_return=strlen(selection_tmp);
6447 *type_return=XA_STRING;
6448 *format_return = 8; /* bits per byte */
6455 /* note: when called from menu all parameters are NULL, so no clue what the
6456 * Widget which was clicked on was, or what the click event was
6458 void CopyPositionProc(w, event, prms, nprms)
6466 if (selected_fen_position) free(selected_fen_position);
6467 selected_fen_position = (char *)PositionToFEN(currentMove, NULL);
6468 if (!selected_fen_position) return;
6469 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
6471 SendPositionSelection,
6472 NULL/* lose_ownership_proc */ ,
6473 NULL/* transfer_done_proc */);
6475 free(selected_fen_position);
6476 selected_fen_position=NULL;
6480 /* function called when the data to Paste is ready */
6482 PastePositionCB(Widget w, XtPointer client_data, Atom *selection,
6483 Atom *type, XtPointer value, unsigned long *len, int *format)
6486 if (value==NULL || *len==0) return; /* nothing had been selected to copy */
6487 fenstr[*len]='\0'; /* normally this string is terminated, but be safe */
6488 EditPositionPasteFEN(fenstr);
6492 /* called when Paste Position button is pressed,
6493 * all parameters will be NULL */
6494 void PastePositionProc(w, event, prms, nprms)
6500 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
6501 /* (XtSelectionCallbackProc) */ PastePositionCB,
6502 NULL, /* client_data passed to PastePositionCB */
6504 /* better to use the time field from the event that triggered the
6505 * call to this function, but that isn't trivial to get
6513 SendGameSelection(Widget w, Atom *selection, Atom *target,
6514 Atom *type_return, XtPointer *value_return,
6515 unsigned long *length_return, int *format_return)
6517 char *selection_tmp;
6519 if (*target == XA_STRING){
6520 FILE* f = fopen(gameCopyFilename, "r");
6523 if (f == NULL) return False;
6527 selection_tmp = XtMalloc(len + 1);
6528 count = fread(selection_tmp, 1, len, f);
6530 XtFree(selection_tmp);
6533 selection_tmp[len] = NULLCHAR;
6534 *value_return = selection_tmp;
6535 *length_return = len;
6536 *type_return = XA_STRING;
6537 *format_return = 8; /* bits per byte */
6544 /* note: when called from menu all parameters are NULL, so no clue what the
6545 * Widget which was clicked on was, or what the click event was
6547 void CopyGameProc(w, event, prms, nprms)
6555 ret = SaveGameToFile(gameCopyFilename, FALSE);
6558 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
6561 NULL/* lose_ownership_proc */ ,
6562 NULL/* transfer_done_proc */);
6565 /* function called when the data to Paste is ready */
6567 PasteGameCB(Widget w, XtPointer client_data, Atom *selection,
6568 Atom *type, XtPointer value, unsigned long *len, int *format)
6571 if (value == NULL || *len == 0) {
6572 return; /* nothing had been selected to copy */
6574 f = fopen(gamePasteFilename, "w");
6576 DisplayError(_("Can't open temp file"), errno);
6579 fwrite(value, 1, *len, f);
6582 LoadGameFromFile(gamePasteFilename, 0, gamePasteFilename, TRUE);
6585 /* called when Paste Game button is pressed,
6586 * all parameters will be NULL */
6587 void PasteGameProc(w, event, prms, nprms)
6593 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
6594 /* (XtSelectionCallbackProc) */ PasteGameCB,
6595 NULL, /* client_data passed to PasteGameCB */
6597 /* better to use the time field from the event that triggered the
6598 * call to this function, but that isn't trivial to get
6608 SaveGameProc(NULL, NULL, NULL, NULL);
6612 void QuitProc(w, event, prms, nprms)
6621 void PauseProc(w, event, prms, nprms)
6631 void MachineBlackProc(w, event, prms, nprms)
6637 MachineBlackEvent();
6640 void MachineWhiteProc(w, event, prms, nprms)
6646 MachineWhiteEvent();
6649 void AnalyzeModeProc(w, event, prms, nprms)
6657 if (!first.analysisSupport) {
6658 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
6659 DisplayError(buf, 0);
6662 /* [DM] icsEngineAnalyze [HGM] This is horrible code; reverse the gameMode and isEngineAnalyze tests! */
6663 if (appData.icsActive) {
6664 if (gameMode != IcsObserving) {
6665 sprintf(buf,_("You are not observing a game"));
6666 DisplayError(buf, 0);
6668 if (appData.icsEngineAnalyze) {
6669 if (appData.debugMode)
6670 fprintf(debugFP, _("Found unexpected active ICS engine analyze \n"));
6676 /* if enable, use want disable icsEngineAnalyze */
6677 if (appData.icsEngineAnalyze) {
6682 appData.icsEngineAnalyze = TRUE;
6683 if (appData.debugMode)
6684 fprintf(debugFP, _("ICS engine analyze starting... \n"));
6686 if (!appData.showThinking)
6687 ShowThinkingProc(w,event,prms,nprms);
6692 void AnalyzeFileProc(w, event, prms, nprms)
6698 if (!first.analysisSupport) {
6700 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
6701 DisplayError(buf, 0);
6706 if (!appData.showThinking)
6707 ShowThinkingProc(w,event,prms,nprms);
6710 FileNamePopUp(_("File to analyze"), "", LoadGamePopUp, "rb");
6711 AnalysisPeriodicEvent(1);
6714 void TwoMachinesProc(w, event, prms, nprms)
6723 void IcsClientProc(w, event, prms, nprms)
6732 void EditGameProc(w, event, prms, nprms)
6741 void EditPositionProc(w, event, prms, nprms)
6747 EditPositionEvent();
6750 void TrainingProc(w, event, prms, nprms)
6759 void EditCommentProc(w, event, prms, nprms)
6766 EditCommentPopDown();
6772 void IcsInputBoxProc(w, event, prms, nprms)
6778 if (ICSInputBoxUp) {
6779 ICSInputBoxPopDown();
6785 void AcceptProc(w, event, prms, nprms)
6794 void DeclineProc(w, event, prms, nprms)
6803 void RematchProc(w, event, prms, nprms)
6812 void CallFlagProc(w, event, prms, nprms)
6821 void DrawProc(w, event, prms, nprms)
6830 void AbortProc(w, event, prms, nprms)
6839 void AdjournProc(w, event, prms, nprms)
6848 void ResignProc(w, event, prms, nprms)
6857 void AdjuWhiteProc(w, event, prms, nprms)
6863 UserAdjudicationEvent(+1);
6866 void AdjuBlackProc(w, event, prms, nprms)
6872 UserAdjudicationEvent(-1);
6875 void AdjuDrawProc(w, event, prms, nprms)
6881 UserAdjudicationEvent(0);
6884 void EnterKeyProc(w, event, prms, nprms)
6890 if (ICSInputBoxUp == True)
6894 void StopObservingProc(w, event, prms, nprms)
6900 StopObservingEvent();
6903 void StopExaminingProc(w, event, prms, nprms)
6909 StopExaminingEvent();
6913 void ForwardProc(w, event, prms, nprms)
6923 void BackwardProc(w, event, prms, nprms)
6932 void ToStartProc(w, event, prms, nprms)
6941 void ToEndProc(w, event, prms, nprms)
6950 void RevertProc(w, event, prms, nprms)
6959 void TruncateGameProc(w, event, prms, nprms)
6965 TruncateGameEvent();
6967 void RetractMoveProc(w, event, prms, nprms)
6976 void MoveNowProc(w, event, prms, nprms)
6986 void AlwaysQueenProc(w, event, prms, nprms)
6994 appData.alwaysPromoteToQueen = !appData.alwaysPromoteToQueen;
6996 if (appData.alwaysPromoteToQueen) {
6997 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6999 XtSetArg(args[0], XtNleftBitmap, None);
7001 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
7005 void AnimateDraggingProc(w, event, prms, nprms)
7013 appData.animateDragging = !appData.animateDragging;
7015 if (appData.animateDragging) {
7016 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7019 XtSetArg(args[0], XtNleftBitmap, None);
7021 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Dragging"),
7025 void AnimateMovingProc(w, event, prms, nprms)
7033 appData.animate = !appData.animate;
7035 if (appData.animate) {
7036 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7039 XtSetArg(args[0], XtNleftBitmap, None);
7041 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
7045 void AutocommProc(w, event, prms, nprms)
7053 appData.autoComment = !appData.autoComment;
7055 if (appData.autoComment) {
7056 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7058 XtSetArg(args[0], XtNleftBitmap, None);
7060 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
7065 void AutoflagProc(w, event, prms, nprms)
7073 appData.autoCallFlag = !appData.autoCallFlag;
7075 if (appData.autoCallFlag) {
7076 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7078 XtSetArg(args[0], XtNleftBitmap, None);
7080 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
7084 void AutoflipProc(w, event, prms, nprms)
7092 appData.autoFlipView = !appData.autoFlipView;
7094 if (appData.autoFlipView) {
7095 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7097 XtSetArg(args[0], XtNleftBitmap, None);
7099 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flip View"),
7103 void AutobsProc(w, event, prms, nprms)
7111 appData.autoObserve = !appData.autoObserve;
7113 if (appData.autoObserve) {
7114 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7116 XtSetArg(args[0], XtNleftBitmap, None);
7118 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
7122 void AutoraiseProc(w, event, prms, nprms)
7130 appData.autoRaiseBoard = !appData.autoRaiseBoard;
7132 if (appData.autoRaiseBoard) {
7133 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7135 XtSetArg(args[0], XtNleftBitmap, None);
7137 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Raise Board"),
7141 void AutosaveProc(w, event, prms, nprms)
7149 appData.autoSaveGames = !appData.autoSaveGames;
7151 if (appData.autoSaveGames) {
7152 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7154 XtSetArg(args[0], XtNleftBitmap, None);
7156 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
7160 void BlindfoldProc(w, event, prms, nprms)
7168 appData.blindfold = !appData.blindfold;
7170 if (appData.blindfold) {
7171 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7173 XtSetArg(args[0], XtNleftBitmap, None);
7175 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Blindfold"),
7178 DrawPosition(True, NULL);
7181 void TestLegalityProc(w, event, prms, nprms)
7189 appData.testLegality = !appData.testLegality;
7191 if (appData.testLegality) {
7192 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7194 XtSetArg(args[0], XtNleftBitmap, None);
7196 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Test Legality"),
7201 void FlashMovesProc(w, event, prms, nprms)
7209 if (appData.flashCount == 0) {
7210 appData.flashCount = 3;
7212 appData.flashCount = -appData.flashCount;
7215 if (appData.flashCount > 0) {
7216 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7218 XtSetArg(args[0], XtNleftBitmap, None);
7220 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flash Moves"),
7224 void FlipViewProc(w, event, prms, nprms)
7230 flipView = !flipView;
7231 DrawPosition(True, NULL);
7234 void GetMoveListProc(w, event, prms, nprms)
7242 appData.getMoveList = !appData.getMoveList;
7244 if (appData.getMoveList) {
7245 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7248 XtSetArg(args[0], XtNleftBitmap, None);
7250 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
7255 void HighlightDraggingProc(w, event, prms, nprms)
7263 appData.highlightDragging = !appData.highlightDragging;
7265 if (appData.highlightDragging) {
7266 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7268 XtSetArg(args[0], XtNleftBitmap, None);
7270 XtSetValues(XtNameToWidget(menuBarWidget,
7271 "menuOptions.Highlight Dragging"), args, 1);
7275 void HighlightLastMoveProc(w, event, prms, nprms)
7283 appData.highlightLastMove = !appData.highlightLastMove;
7285 if (appData.highlightLastMove) {
7286 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7288 XtSetArg(args[0], XtNleftBitmap, None);
7290 XtSetValues(XtNameToWidget(menuBarWidget,
7291 "menuOptions.Highlight Last Move"), args, 1);
7294 void IcsAlarmProc(w, event, prms, nprms)
7302 appData.icsAlarm = !appData.icsAlarm;
7304 if (appData.icsAlarm) {
7305 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7307 XtSetArg(args[0], XtNleftBitmap, None);
7309 XtSetValues(XtNameToWidget(menuBarWidget,
7310 "menuOptions.ICS Alarm"), args, 1);
7313 void MoveSoundProc(w, event, prms, nprms)
7321 appData.ringBellAfterMoves = !appData.ringBellAfterMoves;
7323 if (appData.ringBellAfterMoves) {
7324 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7326 XtSetArg(args[0], XtNleftBitmap, None);
7328 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
7333 void OldSaveStyleProc(w, event, prms, nprms)
7341 appData.oldSaveStyle = !appData.oldSaveStyle;
7343 if (appData.oldSaveStyle) {
7344 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7346 XtSetArg(args[0], XtNleftBitmap, None);
7348 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Old Save Style"),
7352 void PeriodicUpdatesProc(w, event, prms, nprms)
7360 PeriodicUpdatesEvent(!appData.periodicUpdates);
7362 if (appData.periodicUpdates) {
7363 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7365 XtSetArg(args[0], XtNleftBitmap, None);
7367 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Periodic Updates"),
7371 void PonderNextMoveProc(w, event, prms, nprms)
7379 PonderNextMoveEvent(!appData.ponderNextMove);
7381 if (appData.ponderNextMove) {
7382 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7384 XtSetArg(args[0], XtNleftBitmap, None);
7386 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Ponder Next Move"),
7390 void PopupExitMessageProc(w, event, prms, nprms)
7398 appData.popupExitMessage = !appData.popupExitMessage;
7400 if (appData.popupExitMessage) {
7401 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7403 XtSetArg(args[0], XtNleftBitmap, None);
7405 XtSetValues(XtNameToWidget(menuBarWidget,
7406 "menuOptions.Popup Exit Message"), args, 1);
7409 void PopupMoveErrorsProc(w, event, prms, nprms)
7417 appData.popupMoveErrors = !appData.popupMoveErrors;
7419 if (appData.popupMoveErrors) {
7420 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7422 XtSetArg(args[0], XtNleftBitmap, None);
7424 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Popup Move Errors"),
7428 void PremoveProc(w, event, prms, nprms)
7436 appData.premove = !appData.premove;
7438 if (appData.premove) {
7439 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7441 XtSetArg(args[0], XtNleftBitmap, None);
7443 XtSetValues(XtNameToWidget(menuBarWidget,
7444 "menuOptions.Premove"), args, 1);
7447 void QuietPlayProc(w, event, prms, nprms)
7455 appData.quietPlay = !appData.quietPlay;
7457 if (appData.quietPlay) {
7458 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7460 XtSetArg(args[0], XtNleftBitmap, None);
7462 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Quiet Play"),
7466 void ShowCoordsProc(w, event, prms, nprms)
7474 appData.showCoords = !appData.showCoords;
7476 if (appData.showCoords) {
7477 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7479 XtSetArg(args[0], XtNleftBitmap, None);
7481 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
7484 DrawPosition(True, NULL);
7487 void ShowThinkingProc(w, event, prms, nprms)
7495 appData.showThinking = !appData.showThinking; // [HGM] thinking: tken out of ShowThinkingEvent
7496 ShowThinkingEvent();
7498 // [HGM] thinking: currently no suc menu item; replaced by Hide Thinking (From Human)
7499 if (appData.showThinking) {
7500 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7502 XtSetArg(args[0], XtNleftBitmap, None);
7504 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Thinking"),
7509 void HideThinkingProc(w, event, prms, nprms)
7517 appData.hideThinkingFromHuman = !appData.hideThinkingFromHuman; // [HGM] thinking: tken out of ShowThinkingEvent
7518 ShowThinkingEvent();
7520 if (appData.hideThinkingFromHuman) {
7521 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7523 XtSetArg(args[0], XtNleftBitmap, None);
7525 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
7529 void InfoProc(w, event, prms, nprms)
7536 snprintf(buf, sizeof(buf), "xterm -e info --directory %s --directory . -f %s &",
7541 void ManProc(w, event, prms, nprms)
7549 if (nprms && *nprms > 0)
7553 snprintf(buf, sizeof(buf), "xterm -e man %s &", name);
7557 void HintProc(w, event, prms, nprms)
7566 void BookProc(w, event, prms, nprms)
7575 void AboutProc(w, event, prms, nprms)
7583 char *zippy = " (with Zippy code)";
7587 snprintf(buf, sizeof(buf), "%s%s\n\n%s\n%s\n%s\n\n%s%s\n%s",
7588 programVersion, zippy,
7589 "Copyright 1991 Digital Equipment Corporation",
7590 "Enhancements Copyright 1992-2009 Free Software Foundation",
7591 "Enhancements Copyright 2005 Alessandro Scotti",
7592 PACKAGE, " is free software and carries NO WARRANTY;",
7593 "see the file COPYING for more information.");
7594 ErrorPopUp(_("About XBoard"), buf, FALSE);
7597 void DebugProc(w, event, prms, nprms)
7603 appData.debugMode = !appData.debugMode;
7606 void AboutGameProc(w, event, prms, nprms)
7615 void NothingProc(w, event, prms, nprms)
7624 void Iconify(w, event, prms, nprms)
7633 XtSetArg(args[0], XtNiconic, True);
7634 XtSetValues(shellWidget, args, 1);
7637 void DisplayMessage(message, extMessage)
7638 char *message, *extMessage;
7645 snprintf(buf, sizeof(buf), "%s %s", message, extMessage);
7648 message = extMessage;
7651 XtSetArg(arg, XtNlabel, message);
7652 XtSetValues(messageWidget, &arg, 1);
7655 void DisplayTitle(text)
7660 char title[MSG_SIZ];
7663 if (text == NULL) text = "";
7665 if (appData.titleInWindow) {
7667 XtSetArg(args[i], XtNlabel, text); i++;
7668 XtSetValues(titleWidget, args, i);
7671 if (*text != NULLCHAR) {
7673 strcpy(title, text);
7674 } else if (appData.icsActive) {
7675 snprintf(icon, sizeof(icon), "%s", appData.icsHost);
7676 snprintf(title, sizeof(title), "%s: %s", programName, appData.icsHost);
7677 } else if (appData.cmailGameName[0] != NULLCHAR) {
7678 snprintf(icon, sizeof(icon), "%s", "CMail");
7679 snprintf(title,sizeof(title), "%s: %s", programName, "CMail");
7681 // [HGM] license: This stuff should really be done in back-end, but WinBoard already had a pop-up for it
7682 } else if (gameInfo.variant == VariantGothic) {
7683 strcpy(icon, programName);
7684 strcpy(title, GOTHIC);
7687 } else if (gameInfo.variant == VariantFalcon) {
7688 strcpy(icon, programName);
7689 strcpy(title, FALCON);
7691 } else if (appData.noChessProgram) {
7692 strcpy(icon, programName);
7693 strcpy(title, programName);
7695 strcpy(icon, first.tidy);
7696 snprintf(title,sizeof(title), "%s: %s", programName, first.tidy);
7699 XtSetArg(args[i], XtNiconName, (XtArgVal) icon); i++;
7700 XtSetArg(args[i], XtNtitle, (XtArgVal) title); i++;
7701 XtSetValues(shellWidget, args, i);
7705 void DisplayError(message, error)
7712 if (appData.debugMode || appData.matchMode) {
7713 fprintf(stderr, "%s: %s\n", programName, message);
7716 if (appData.debugMode || appData.matchMode) {
7717 fprintf(stderr, "%s: %s: %s\n",
7718 programName, message, strerror(error));
7720 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
7723 ErrorPopUp(_("Error"), message, FALSE);
7727 void DisplayMoveError(message)
7732 DrawPosition(FALSE, NULL);
7733 if (appData.debugMode || appData.matchMode) {
7734 fprintf(stderr, "%s: %s\n", programName, message);
7736 if (appData.popupMoveErrors) {
7737 ErrorPopUp(_("Error"), message, FALSE);
7739 DisplayMessage(message, "");
7744 void DisplayFatalError(message, error, status)
7750 errorExitStatus = status;
7752 fprintf(stderr, "%s: %s\n", programName, message);
7754 fprintf(stderr, "%s: %s: %s\n",
7755 programName, message, strerror(error));
7756 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
7759 if (appData.popupExitMessage && boardWidget && XtIsRealized(boardWidget)) {
7760 ErrorPopUp(status ? _("Fatal Error") : _("Exiting"), message, TRUE);
7766 void DisplayInformation(message)
7770 ErrorPopUp(_("Information"), message, TRUE);
7773 void DisplayNote(message)
7777 ErrorPopUp(_("Note"), message, FALSE);
7781 NullXErrorCheck(dpy, error_event)
7783 XErrorEvent *error_event;
7788 void DisplayIcsInteractionTitle(message)
7791 if (oldICSInteractionTitle == NULL) {
7792 /* Magic to find the old window title, adapted from vim */
7793 char *wina = getenv("WINDOWID");
7795 Window win = (Window) atoi(wina);
7796 Window root, parent, *children;
7797 unsigned int nchildren;
7798 int (*oldHandler)() = XSetErrorHandler(NullXErrorCheck);
7800 if (XFetchName(xDisplay, win, &oldICSInteractionTitle)) break;
7801 if (!XQueryTree(xDisplay, win, &root, &parent,
7802 &children, &nchildren)) break;
7803 if (children) XFree((void *)children);
7804 if (parent == root || parent == 0) break;
7807 XSetErrorHandler(oldHandler);
7809 if (oldICSInteractionTitle == NULL) {
7810 oldICSInteractionTitle = "xterm";
7813 printf("\033]0;%s\007", message);
7817 char pendingReplyPrefix[MSG_SIZ];
7818 ProcRef pendingReplyPR;
7820 void AskQuestionProc(w, event, prms, nprms)
7827 fprintf(stderr, _("AskQuestionProc needed 4 parameters, got %d\n"),
7831 AskQuestionEvent(prms[0], prms[1], prms[2], prms[3]);
7834 void AskQuestionPopDown()
7836 if (!askQuestionUp) return;
7837 XtPopdown(askQuestionShell);
7838 XtDestroyWidget(askQuestionShell);
7839 askQuestionUp = False;
7842 void AskQuestionReplyAction(w, event, prms, nprms)
7852 reply = XawDialogGetValueString(w = XtParent(w));
7853 strcpy(buf, pendingReplyPrefix);
7854 if (*buf) strcat(buf, " ");
7857 OutputToProcess(pendingReplyPR, buf, strlen(buf), &err);
7858 AskQuestionPopDown();
7860 if (err) DisplayFatalError(_("Error writing to chess program"), err, 0);
7863 void AskQuestionCallback(w, client_data, call_data)
7865 XtPointer client_data, call_data;
7870 XtSetArg(args[0], XtNlabel, &name);
7871 XtGetValues(w, args, 1);
7873 if (strcmp(name, _("cancel")) == 0) {
7874 AskQuestionPopDown();
7876 AskQuestionReplyAction(w, NULL, NULL, NULL);
7880 void AskQuestion(title, question, replyPrefix, pr)
7881 char *title, *question, *replyPrefix;
7885 Widget popup, layout, dialog, edit;
7891 strcpy(pendingReplyPrefix, replyPrefix);
7892 pendingReplyPR = pr;
7895 XtSetArg(args[i], XtNresizable, True); i++;
7896 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
7897 askQuestionShell = popup =
7898 XtCreatePopupShell(title, transientShellWidgetClass,
7899 shellWidget, args, i);
7902 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
7903 layoutArgs, XtNumber(layoutArgs));
7906 XtSetArg(args[i], XtNlabel, question); i++;
7907 XtSetArg(args[i], XtNvalue, ""); i++;
7908 XtSetArg(args[i], XtNborderWidth, 0); i++;
7909 dialog = XtCreateManagedWidget("question", dialogWidgetClass,
7912 XawDialogAddButton(dialog, _("enter"), AskQuestionCallback,
7913 (XtPointer) dialog);
7914 XawDialogAddButton(dialog, _("cancel"), AskQuestionCallback,
7915 (XtPointer) dialog);
7917 XtRealizeWidget(popup);
7918 CatchDeleteWindow(popup, "AskQuestionPopDown");
7920 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
7921 &x, &y, &win_x, &win_y, &mask);
7923 XtSetArg(args[0], XtNx, x - 10);
7924 XtSetArg(args[1], XtNy, y - 30);
7925 XtSetValues(popup, args, 2);
7927 XtPopup(popup, XtGrabExclusive);
7928 askQuestionUp = True;
7930 edit = XtNameToWidget(dialog, "*value");
7931 XtSetKeyboardFocus(popup, edit);
7939 if (*name == NULLCHAR) {
7941 } else if (strcmp(name, "$") == 0) {
7942 putc(BELLCHAR, stderr);
7945 snprintf(buf, sizeof(buf), "%s '%s' &", appData.soundProgram, name);
7953 PlaySound(appData.soundMove);
7959 PlaySound(appData.soundIcsWin);
7965 PlaySound(appData.soundIcsLoss);
7971 PlaySound(appData.soundIcsDraw);
7975 PlayIcsUnfinishedSound()
7977 PlaySound(appData.soundIcsUnfinished);
7983 PlaySound(appData.soundIcsAlarm);
7989 system("stty echo");
7995 system("stty -echo");
7999 Colorize(cc, continuation)
8004 int count, outCount, error;
8006 if (textColors[(int)cc].bg > 0) {
8007 if (textColors[(int)cc].fg > 0) {
8008 sprintf(buf, "\033[0;%d;%d;%dm", textColors[(int)cc].attr,
8009 textColors[(int)cc].fg, textColors[(int)cc].bg);
8011 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
8012 textColors[(int)cc].bg);
8015 if (textColors[(int)cc].fg > 0) {
8016 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
8017 textColors[(int)cc].fg);
8019 sprintf(buf, "\033[0;%dm", textColors[(int)cc].attr);
8022 count = strlen(buf);
8023 outCount = OutputToProcess(NoProc, buf, count, &error);
8024 if (outCount < count) {
8025 DisplayFatalError(_("Error writing to display"), error, 1);
8028 if (continuation) return;
8031 PlaySound(appData.soundShout);
8034 PlaySound(appData.soundSShout);
8037 PlaySound(appData.soundChannel1);
8040 PlaySound(appData.soundChannel);
8043 PlaySound(appData.soundKibitz);
8046 PlaySound(appData.soundTell);
8048 case ColorChallenge:
8049 PlaySound(appData.soundChallenge);
8052 PlaySound(appData.soundRequest);
8055 PlaySound(appData.soundSeek);
8066 return getpwuid(getuid())->pw_name;
8069 static char *ExpandPathName(path)
8072 static char static_buf[2000];
8073 char *d, *s, buf[2000];
8079 while (*s && isspace(*s))
8088 if (*(s+1) == '/') {
8089 strcpy(d, getpwuid(getuid())->pw_dir);
8094 *strchr(buf, '/') = 0;
8095 pwd = getpwnam(buf);
8098 fprintf(stderr, _("ERROR: Unknown user %s (in path %s)\n"),
8102 strcpy(d, pwd->pw_dir);
8103 strcat(d, strchr(s+1, '/'));
8114 static char host_name[MSG_SIZ];
8116 #if HAVE_GETHOSTNAME
8117 gethostname(host_name, MSG_SIZ);
8119 #else /* not HAVE_GETHOSTNAME */
8120 # if HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H
8121 sysinfo(SI_HOSTNAME, host_name, MSG_SIZ);
8123 # else /* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
8125 # endif/* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
8126 #endif /* not HAVE_GETHOSTNAME */
8129 XtIntervalId delayedEventTimerXID = 0;
8130 DelayedEventCallback delayedEventCallback = 0;
8135 delayedEventTimerXID = 0;
8136 delayedEventCallback();
8140 ScheduleDelayedEvent(cb, millisec)
8141 DelayedEventCallback cb; long millisec;
8143 delayedEventCallback = cb;
8144 delayedEventTimerXID =
8145 XtAppAddTimeOut(appContext, millisec,
8146 (XtTimerCallbackProc) FireDelayedEvent, (XtPointer) 0);
8149 DelayedEventCallback
8152 if (delayedEventTimerXID) {
8153 return delayedEventCallback;
8160 CancelDelayedEvent()
8162 if (delayedEventTimerXID) {
8163 XtRemoveTimeOut(delayedEventTimerXID);
8164 delayedEventTimerXID = 0;
8168 XtIntervalId loadGameTimerXID = 0;
8170 int LoadGameTimerRunning()
8172 return loadGameTimerXID != 0;
8175 int StopLoadGameTimer()
8177 if (loadGameTimerXID != 0) {
8178 XtRemoveTimeOut(loadGameTimerXID);
8179 loadGameTimerXID = 0;
8187 LoadGameTimerCallback(arg, id)
8191 loadGameTimerXID = 0;
8196 StartLoadGameTimer(millisec)
8200 XtAppAddTimeOut(appContext, millisec,
8201 (XtTimerCallbackProc) LoadGameTimerCallback,
8205 XtIntervalId analysisClockXID = 0;
8208 AnalysisClockCallback(arg, id)
8212 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile
8213 || appData.icsEngineAnalyze) { // [DM]
8214 AnalysisPeriodicEvent(0);
8215 StartAnalysisClock();
8220 StartAnalysisClock()
8223 XtAppAddTimeOut(appContext, 2000,
8224 (XtTimerCallbackProc) AnalysisClockCallback,
8228 XtIntervalId clockTimerXID = 0;
8230 int ClockTimerRunning()
8232 return clockTimerXID != 0;
8235 int StopClockTimer()
8237 if (clockTimerXID != 0) {
8238 XtRemoveTimeOut(clockTimerXID);
8247 ClockTimerCallback(arg, id)
8256 StartClockTimer(millisec)
8260 XtAppAddTimeOut(appContext, millisec,
8261 (XtTimerCallbackProc) ClockTimerCallback,
8266 DisplayTimerLabel(w, color, timer, highlight)
8275 /* check for low time warning */
8276 Pixel foregroundOrWarningColor = timerForegroundPixel;
8279 appData.lowTimeWarning &&
8280 (timer / 1000) < appData.icsAlarmTime)
8281 foregroundOrWarningColor = lowTimeWarningColor;
8283 if (appData.clockMode) {
8284 sprintf(buf, "%s: %s", color, TimeString(timer));
8285 XtSetArg(args[0], XtNlabel, buf);
8287 sprintf(buf, "%s ", color);
8288 XtSetArg(args[0], XtNlabel, buf);
8293 XtSetArg(args[1], XtNbackground, foregroundOrWarningColor);
8294 XtSetArg(args[2], XtNforeground, timerBackgroundPixel);
8296 XtSetArg(args[1], XtNbackground, timerBackgroundPixel);
8297 XtSetArg(args[2], XtNforeground, foregroundOrWarningColor);
8300 XtSetValues(w, args, 3);
8304 DisplayWhiteClock(timeRemaining, highlight)
8310 if(appData.noGUI) return;
8311 DisplayTimerLabel(whiteTimerWidget, _("White"), timeRemaining, highlight);
8312 if (highlight && iconPixmap == bIconPixmap) {
8313 iconPixmap = wIconPixmap;
8314 XtSetArg(args[0], XtNiconPixmap, iconPixmap);
8315 XtSetValues(shellWidget, args, 1);
8320 DisplayBlackClock(timeRemaining, highlight)
8326 if(appData.noGUI) return;
8327 DisplayTimerLabel(blackTimerWidget, _("Black"), timeRemaining, highlight);
8328 if (highlight && iconPixmap == wIconPixmap) {
8329 iconPixmap = bIconPixmap;
8330 XtSetArg(args[0], XtNiconPixmap, iconPixmap);
8331 XtSetValues(shellWidget, args, 1);
8349 int StartChildProcess(cmdLine, dir, pr)
8356 int to_prog[2], from_prog[2];
8360 if (appData.debugMode) {
8361 fprintf(stderr, "StartChildProcess (dir=\"%s\") %s\n",dir, cmdLine);
8364 /* We do NOT feed the cmdLine to the shell; we just
8365 parse it into blank-separated arguments in the
8366 most simple-minded way possible.
8369 strcpy(buf, cmdLine);
8374 if (p == NULL) break;
8379 SetUpChildIO(to_prog, from_prog);
8381 if ((pid = fork()) == 0) {
8383 // [HGM] PSWBTM: made order resistant against case where fd of created pipe was 0 or 1
8384 close(to_prog[1]); // first close the unused pipe ends
8385 close(from_prog[0]);
8386 dup2(to_prog[0], 0); // to_prog was created first, nd is the only one to use 0 or 1
8387 dup2(from_prog[1], 1);
8388 if(to_prog[0] >= 2) close(to_prog[0]); // if 0 or 1, the dup2 already cosed the original
8389 close(from_prog[1]); // and closing again loses one of the pipes!
8390 if(fileno(stderr) >= 2) // better safe than sorry...
8391 dup2(1, fileno(stderr)); /* force stderr to the pipe */
8393 if (dir[0] != NULLCHAR && chdir(dir) != 0) {
8398 nice(appData.niceEngines); // [HGM] nice: adjust priority of engine proc
8400 execvp(argv[0], argv);
8402 /* If we get here, exec failed */
8407 /* Parent process */
8409 close(from_prog[1]);
8411 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8414 cp->fdFrom = from_prog[0];
8415 cp->fdTo = to_prog[1];
8420 // [HGM] kill: implement the 'hard killing' of AS's Winboard_x
8421 static RETSIGTYPE AlarmCallBack(int n)
8427 DestroyChildProcess(pr, signalType)
8431 ChildProc *cp = (ChildProc *) pr;
8433 if (cp->kind != CPReal) return;
8435 if (signalType == 10) { // [HGM] kill: if it does not terminate in 3 sec, kill
8436 signal(SIGALRM, AlarmCallBack);
8438 if(wait((int *) 0) == -1) { // process does not terminate on its own accord
8439 kill(cp->pid, SIGKILL); // kill it forcefully
8440 wait((int *) 0); // and wait again
8444 kill(cp->pid, signalType == 9 ? SIGKILL : SIGTERM); // [HGM] kill: use hard kill if so requested
8446 /* Process is exiting either because of the kill or because of
8447 a quit command sent by the backend; either way, wait for it to die.
8456 InterruptChildProcess(pr)
8459 ChildProc *cp = (ChildProc *) pr;
8461 if (cp->kind != CPReal) return;
8462 (void) kill(cp->pid, SIGINT); /* stop it thinking */
8465 int OpenTelnet(host, port, pr)
8470 char cmdLine[MSG_SIZ];
8472 if (port[0] == NULLCHAR) {
8473 snprintf(cmdLine, sizeof(cmdLine), "%s %s", appData.telnetProgram, host);
8475 snprintf(cmdLine, sizeof(cmdLine), "%s %s %s", appData.telnetProgram, host, port);
8477 return StartChildProcess(cmdLine, "", pr);
8480 int OpenTCP(host, port, pr)
8486 DisplayFatalError(_("Socket support is not configured in"), 0, 2);
8487 #else /* !OMIT_SOCKETS */
8489 struct sockaddr_in sa;
8491 unsigned short uport;
8494 if ((s = socket(AF_INET, SOCK_STREAM, 6)) < 0) {
8498 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
8499 sa.sin_family = AF_INET;
8500 sa.sin_addr.s_addr = INADDR_ANY;
8501 uport = (unsigned short) 0;
8502 sa.sin_port = htons(uport);
8503 if (bind(s, (struct sockaddr *) &sa, sizeof(struct sockaddr_in)) < 0) {
8507 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
8508 if (!(hp = gethostbyname(host))) {
8510 if (sscanf(host, "%d.%d.%d.%d", &b0, &b1, &b2, &b3) == 4) {
8511 hp = (struct hostent *) calloc(1, sizeof(struct hostent));
8512 hp->h_addrtype = AF_INET;
8514 hp->h_addr_list = (char **) calloc(2, sizeof(char *));
8515 hp->h_addr_list[0] = (char *) malloc(4);
8516 hp->h_addr_list[0][0] = b0;
8517 hp->h_addr_list[0][1] = b1;
8518 hp->h_addr_list[0][2] = b2;
8519 hp->h_addr_list[0][3] = b3;
8524 sa.sin_family = hp->h_addrtype;
8525 uport = (unsigned short) atoi(port);
8526 sa.sin_port = htons(uport);
8527 memcpy((char *) &sa.sin_addr, hp->h_addr, hp->h_length);
8529 if (connect(s, (struct sockaddr *) &sa,
8530 sizeof(struct sockaddr_in)) < 0) {
8534 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8541 #endif /* !OMIT_SOCKETS */
8546 int OpenCommPort(name, pr)
8553 fd = open(name, 2, 0);
8554 if (fd < 0) return errno;
8556 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8566 int OpenLoopback(pr)
8572 SetUpChildIO(to, from);
8574 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8577 cp->fdFrom = to[0]; /* note not from[0]; we are doing a loopback */
8584 int OpenRcmd(host, user, cmd, pr)
8585 char *host, *user, *cmd;
8588 DisplayFatalError(_("internal rcmd not implemented for Unix"), 0, 1);
8592 #define INPUT_SOURCE_BUF_SIZE 8192
8601 char buf[INPUT_SOURCE_BUF_SIZE];
8606 DoInputCallback(closure, source, xid)
8611 InputSource *is = (InputSource *) closure;
8616 if (is->lineByLine) {
8617 count = read(is->fd, is->unused,
8618 INPUT_SOURCE_BUF_SIZE - (is->unused - is->buf));
8620 (is->func)(is, is->closure, is->buf, count, count ? errno : 0);
8623 is->unused += count;
8625 while (p < is->unused) {
8626 q = memchr(p, '\n', is->unused - p);
8627 if (q == NULL) break;
8629 (is->func)(is, is->closure, p, q - p, 0);
8633 while (p < is->unused) {
8638 count = read(is->fd, is->buf, INPUT_SOURCE_BUF_SIZE);
8643 (is->func)(is, is->closure, is->buf, count, error);
8647 InputSourceRef AddInputSource(pr, lineByLine, func, closure)
8654 ChildProc *cp = (ChildProc *) pr;
8656 is = (InputSource *) calloc(1, sizeof(InputSource));
8657 is->lineByLine = lineByLine;
8661 is->fd = fileno(stdin);
8663 is->kind = cp->kind;
8664 is->fd = cp->fdFrom;
8667 is->unused = is->buf;
8670 is->xid = XtAppAddInput(appContext, is->fd,
8671 (XtPointer) (XtInputReadMask),
8672 (XtInputCallbackProc) DoInputCallback,
8674 is->closure = closure;
8675 return (InputSourceRef) is;
8679 RemoveInputSource(isr)
8682 InputSource *is = (InputSource *) isr;
8684 if (is->xid == 0) return;
8685 XtRemoveInput(is->xid);
8689 int OutputToProcess(pr, message, count, outError)
8695 ChildProc *cp = (ChildProc *) pr;
8699 outCount = fwrite(message, 1, count, stdout);
8701 outCount = write(cp->fdTo, message, count);
8711 /* Output message to process, with "ms" milliseconds of delay
8712 between each character. This is needed when sending the logon
8713 script to ICC, which for some reason doesn't like the
8714 instantaneous send. */
8715 int OutputToProcessDelayed(pr, message, count, outError, msdelay)
8722 ChildProc *cp = (ChildProc *) pr;
8727 r = write(cp->fdTo, message++, 1);
8740 /**** Animation code by Hugh Fisher, DCS, ANU.
8742 Known problem: if a window overlapping the board is
8743 moved away while a piece is being animated underneath,
8744 the newly exposed area won't be updated properly.
8745 I can live with this.
8747 Known problem: if you look carefully at the animation
8748 of pieces in mono mode, they are being drawn as solid
8749 shapes without interior detail while moving. Fixing
8750 this would be a major complication for minimal return.
8753 /* Masks for XPM pieces. Black and white pieces can have
8754 different shapes, but in the interest of retaining my
8755 sanity pieces must have the same outline on both light
8756 and dark squares, and all pieces must use the same
8757 background square colors/images. */
8759 static int xpmDone = 0;
8762 CreateAnimMasks (pieceDepth)
8769 unsigned long plane;
8772 /* Need a bitmap just to get a GC with right depth */
8773 buf = XCreatePixmap(xDisplay, xBoardWindow,
8775 values.foreground = 1;
8776 values.background = 0;
8777 /* Don't use XtGetGC, not read only */
8778 maskGC = XCreateGC(xDisplay, buf,
8779 GCForeground | GCBackground, &values);
8780 XFreePixmap(xDisplay, buf);
8782 buf = XCreatePixmap(xDisplay, xBoardWindow,
8783 squareSize, squareSize, pieceDepth);
8784 values.foreground = XBlackPixel(xDisplay, xScreen);
8785 values.background = XWhitePixel(xDisplay, xScreen);
8786 bufGC = XCreateGC(xDisplay, buf,
8787 GCForeground | GCBackground, &values);
8789 for (piece = WhitePawn; piece <= BlackKing; piece++) {
8790 /* Begin with empty mask */
8791 if(!xpmDone) // [HGM] pieces: keep using existing
8792 xpmMask[piece] = XCreatePixmap(xDisplay, xBoardWindow,
8793 squareSize, squareSize, 1);
8794 XSetFunction(xDisplay, maskGC, GXclear);
8795 XFillRectangle(xDisplay, xpmMask[piece], maskGC,
8796 0, 0, squareSize, squareSize);
8798 /* Take a copy of the piece */
8803 XSetFunction(xDisplay, bufGC, GXcopy);
8804 XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % (int)BlackPawn],
8806 0, 0, squareSize, squareSize, 0, 0);
8808 /* XOR the background (light) over the piece */
8809 XSetFunction(xDisplay, bufGC, GXxor);
8811 XCopyArea(xDisplay, xpmLightSquare, buf, bufGC,
8812 0, 0, squareSize, squareSize, 0, 0);
8814 XSetForeground(xDisplay, bufGC, lightSquareColor);
8815 XFillRectangle(xDisplay, buf, bufGC, 0, 0, squareSize, squareSize);
8818 /* We now have an inverted piece image with the background
8819 erased. Construct mask by just selecting all the non-zero
8820 pixels - no need to reconstruct the original image. */
8821 XSetFunction(xDisplay, maskGC, GXor);
8823 /* Might be quicker to download an XImage and create bitmap
8824 data from it rather than this N copies per piece, but it
8825 only takes a fraction of a second and there is a much
8826 longer delay for loading the pieces. */
8827 for (n = 0; n < pieceDepth; n ++) {
8828 XCopyPlane(xDisplay, buf, xpmMask[piece], maskGC,
8829 0, 0, squareSize, squareSize,
8835 XFreePixmap(xDisplay, buf);
8836 XFreeGC(xDisplay, bufGC);
8837 XFreeGC(xDisplay, maskGC);
8841 InitAnimState (anim, info)
8843 XWindowAttributes * info;
8848 /* Each buffer is square size, same depth as window */
8849 anim->saveBuf = XCreatePixmap(xDisplay, xBoardWindow,
8850 squareSize, squareSize, info->depth);
8851 anim->newBuf = XCreatePixmap(xDisplay, xBoardWindow,
8852 squareSize, squareSize, info->depth);
8854 /* Create a plain GC for blitting */
8855 mask = GCForeground | GCBackground | GCFunction |
8856 GCPlaneMask | GCGraphicsExposures;
8857 values.foreground = XBlackPixel(xDisplay, xScreen);
8858 values.background = XWhitePixel(xDisplay, xScreen);
8859 values.function = GXcopy;
8860 values.plane_mask = AllPlanes;
8861 values.graphics_exposures = False;
8862 anim->blitGC = XCreateGC(xDisplay, xBoardWindow, mask, &values);
8864 /* Piece will be copied from an existing context at
8865 the start of each new animation/drag. */
8866 anim->pieceGC = XCreateGC(xDisplay, xBoardWindow, 0, &values);
8868 /* Outline will be a read-only copy of an existing */
8869 anim->outlineGC = None;
8875 static VariantClass old = (VariantClass) -1; // [HGM] pieces: redo every time variant changes
8876 XWindowAttributes info;
8878 if (xpmDone && gameInfo.variant == old) return;
8879 if(xpmDone) old = gameInfo.variant; // first time pieces might not be created yet
8880 XGetWindowAttributes(xDisplay, xBoardWindow, &info);
8882 InitAnimState(&game, &info);
8883 InitAnimState(&player, &info);
8885 /* For XPM pieces, we need bitmaps to use as masks. */
8887 CreateAnimMasks(info.depth);
8893 static Boolean frameWaiting;
8895 static RETSIGTYPE FrameAlarm (sig)
8898 frameWaiting = False;
8899 /* In case System-V style signals. Needed?? */
8900 signal(SIGALRM, FrameAlarm);
8907 struct itimerval delay;
8909 XSync(xDisplay, False);
8912 frameWaiting = True;
8913 signal(SIGALRM, FrameAlarm);
8914 delay.it_interval.tv_sec =
8915 delay.it_value.tv_sec = time / 1000;
8916 delay.it_interval.tv_usec =
8917 delay.it_value.tv_usec = (time % 1000) * 1000;
8918 setitimer(ITIMER_REAL, &delay, NULL);
8920 /* Ugh -- busy-wait! --tpm */
8921 while (frameWaiting);
8923 while (frameWaiting) pause();
8925 delay.it_interval.tv_sec = delay.it_value.tv_sec = 0;
8926 delay.it_interval.tv_usec = delay.it_value.tv_usec = 0;
8927 setitimer(ITIMER_REAL, &delay, NULL);
8937 XSync(xDisplay, False);
8939 usleep(time * 1000);
8944 /* Convert board position to corner of screen rect and color */
8947 ScreenSquare(column, row, pt, color)
8948 int column; int row; XPoint * pt; int * color;
8951 pt->x = lineGap + ((BOARD_WIDTH-1)-column) * (squareSize + lineGap);
8952 pt->y = lineGap + row * (squareSize + lineGap);
8954 pt->x = lineGap + column * (squareSize + lineGap);
8955 pt->y = lineGap + ((BOARD_HEIGHT-1)-row) * (squareSize + lineGap);
8957 *color = SquareColor(row, column);
8960 /* Convert window coords to square */
8963 BoardSquare(x, y, column, row)
8964 int x; int y; int * column; int * row;
8966 *column = EventToSquare(x, BOARD_WIDTH);
8967 if (flipView && *column >= 0)
8968 *column = BOARD_WIDTH - 1 - *column;
8969 *row = EventToSquare(y, BOARD_HEIGHT);
8970 if (!flipView && *row >= 0)
8971 *row = BOARD_HEIGHT - 1 - *row;
8976 #undef Max /* just in case */
8978 #define Max(a, b) ((a) > (b) ? (a) : (b))
8979 #define Min(a, b) ((a) < (b) ? (a) : (b))
8982 SetRect(rect, x, y, width, height)
8983 XRectangle * rect; int x; int y; int width; int height;
8987 rect->width = width;
8988 rect->height = height;
8991 /* Test if two frames overlap. If they do, return
8992 intersection rect within old and location of
8993 that rect within new. */
8996 Intersect(old, new, size, area, pt)
8997 XPoint * old; XPoint * new;
8998 int size; XRectangle * area; XPoint * pt;
9000 if (old->x > new->x + size || new->x > old->x + size ||
9001 old->y > new->y + size || new->y > old->y + size) {
9004 SetRect(area, Max(new->x - old->x, 0), Max(new->y - old->y, 0),
9005 size - abs(old->x - new->x), size - abs(old->y - new->y));
9006 pt->x = Max(old->x - new->x, 0);
9007 pt->y = Max(old->y - new->y, 0);
9012 /* For two overlapping frames, return the rect(s)
9013 in the old that do not intersect with the new. */
9016 CalcUpdateRects(old, new, size, update, nUpdates)
9017 XPoint * old; XPoint * new; int size;
9018 XRectangle update[]; int * nUpdates;
9022 /* If old = new (shouldn't happen) then nothing to draw */
9023 if (old->x == new->x && old->y == new->y) {
9027 /* Work out what bits overlap. Since we know the rects
9028 are the same size we don't need a full intersect calc. */
9030 /* Top or bottom edge? */
9031 if (new->y > old->y) {
9032 SetRect(&(update[count]), old->x, old->y, size, new->y - old->y);
9034 } else if (old->y > new->y) {
9035 SetRect(&(update[count]), old->x, old->y + size - (old->y - new->y),
9036 size, old->y - new->y);
9039 /* Left or right edge - don't overlap any update calculated above. */
9040 if (new->x > old->x) {
9041 SetRect(&(update[count]), old->x, Max(new->y, old->y),
9042 new->x - old->x, size - abs(new->y - old->y));
9044 } else if (old->x > new->x) {
9045 SetRect(&(update[count]), new->x + size, Max(new->y, old->y),
9046 old->x - new->x, size - abs(new->y - old->y));
9053 /* Generate a series of frame coords from start->mid->finish.
9054 The movement rate doubles until the half way point is
9055 reached, then halves back down to the final destination,
9056 which gives a nice slow in/out effect. The algorithmn
9057 may seem to generate too many intermediates for short
9058 moves, but remember that the purpose is to attract the
9059 viewers attention to the piece about to be moved and
9060 then to where it ends up. Too few frames would be less
9064 Tween(start, mid, finish, factor, frames, nFrames)
9065 XPoint * start; XPoint * mid;
9066 XPoint * finish; int factor;
9067 XPoint frames[]; int * nFrames;
9069 int fraction, n, count;
9073 /* Slow in, stepping 1/16th, then 1/8th, ... */
9075 for (n = 0; n < factor; n++)
9077 for (n = 0; n < factor; n++) {
9078 frames[count].x = start->x + (mid->x - start->x) / fraction;
9079 frames[count].y = start->y + (mid->y - start->y) / fraction;
9081 fraction = fraction / 2;
9085 frames[count] = *mid;
9088 /* Slow out, stepping 1/2, then 1/4, ... */
9090 for (n = 0; n < factor; n++) {
9091 frames[count].x = finish->x - (finish->x - mid->x) / fraction;
9092 frames[count].y = finish->y - (finish->y - mid->y) / fraction;
9094 fraction = fraction * 2;
9099 /* Draw a piece on the screen without disturbing what's there */
9102 SelectGCMask(piece, clip, outline, mask)
9103 ChessSquare piece; GC * clip; GC * outline; Pixmap * mask;
9107 /* Bitmap for piece being moved. */
9108 if (appData.monoMode) {
9109 *mask = *pieceToSolid(piece);
9110 } else if (useImages) {
9112 *mask = xpmMask[piece];
9114 *mask = ximMaskPm[piece];
9117 *mask = *pieceToSolid(piece);
9120 /* GC for piece being moved. Square color doesn't matter, but
9121 since it gets modified we make a copy of the original. */
9123 if (appData.monoMode)
9128 if (appData.monoMode)
9133 XCopyGC(xDisplay, source, 0xFFFFFFFF, *clip);
9135 /* Outline only used in mono mode and is not modified */
9137 *outline = bwPieceGC;
9139 *outline = wbPieceGC;
9143 OverlayPiece(piece, clip, outline, dest)
9144 ChessSquare piece; GC clip; GC outline; Drawable dest;
9149 /* Draw solid rectangle which will be clipped to shape of piece */
9150 XFillRectangle(xDisplay, dest, clip,
9151 0, 0, squareSize, squareSize);
9152 if (appData.monoMode)
9153 /* Also draw outline in contrasting color for black
9154 on black / white on white cases */
9155 XCopyPlane(xDisplay, *pieceToOutline(piece), dest, outline,
9156 0, 0, squareSize, squareSize, 0, 0, 1);
9158 /* Copy the piece */
9163 XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
9165 0, 0, squareSize, squareSize,
9170 /* Animate the movement of a single piece */
9173 BeginAnimation(anim, piece, startColor, start)
9181 /* The old buffer is initialised with the start square (empty) */
9182 BlankSquare(0, 0, startColor, EmptySquare, anim->saveBuf);
9183 anim->prevFrame = *start;
9185 /* The piece will be drawn using its own bitmap as a matte */
9186 SelectGCMask(piece, &anim->pieceGC, &anim->outlineGC, &mask);
9187 XSetClipMask(xDisplay, anim->pieceGC, mask);
9191 AnimationFrame(anim, frame, piece)
9196 XRectangle updates[4];
9201 /* Save what we are about to draw into the new buffer */
9202 XCopyArea(xDisplay, xBoardWindow, anim->newBuf, anim->blitGC,
9203 frame->x, frame->y, squareSize, squareSize,
9206 /* Erase bits of the previous frame */
9207 if (Intersect(&anim->prevFrame, frame, squareSize, &overlap, &pt)) {
9208 /* Where the new frame overlapped the previous,
9209 the contents in newBuf are wrong. */
9210 XCopyArea(xDisplay, anim->saveBuf, anim->newBuf, anim->blitGC,
9211 overlap.x, overlap.y,
9212 overlap.width, overlap.height,
9214 /* Repaint the areas in the old that don't overlap new */
9215 CalcUpdateRects(&anim->prevFrame, frame, squareSize, updates, &count);
9216 for (i = 0; i < count; i++)
9217 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9218 updates[i].x - anim->prevFrame.x,
9219 updates[i].y - anim->prevFrame.y,
9220 updates[i].width, updates[i].height,
9221 updates[i].x, updates[i].y);
9223 /* Easy when no overlap */
9224 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9225 0, 0, squareSize, squareSize,
9226 anim->prevFrame.x, anim->prevFrame.y);
9229 /* Save this frame for next time round */
9230 XCopyArea(xDisplay, anim->newBuf, anim->saveBuf, anim->blitGC,
9231 0, 0, squareSize, squareSize,
9233 anim->prevFrame = *frame;
9235 /* Draw piece over original screen contents, not current,
9236 and copy entire rect. Wipes out overlapping piece images. */
9237 OverlayPiece(piece, anim->pieceGC, anim->outlineGC, anim->newBuf);
9238 XCopyArea(xDisplay, anim->newBuf, xBoardWindow, anim->blitGC,
9239 0, 0, squareSize, squareSize,
9240 frame->x, frame->y);
9244 EndAnimation (anim, finish)
9248 XRectangle updates[4];
9253 /* The main code will redraw the final square, so we
9254 only need to erase the bits that don't overlap. */
9255 if (Intersect(&anim->prevFrame, finish, squareSize, &overlap, &pt)) {
9256 CalcUpdateRects(&anim->prevFrame, finish, squareSize, updates, &count);
9257 for (i = 0; i < count; i++)
9258 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9259 updates[i].x - anim->prevFrame.x,
9260 updates[i].y - anim->prevFrame.y,
9261 updates[i].width, updates[i].height,
9262 updates[i].x, updates[i].y);
9264 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9265 0, 0, squareSize, squareSize,
9266 anim->prevFrame.x, anim->prevFrame.y);
9271 FrameSequence(anim, piece, startColor, start, finish, frames, nFrames)
9273 ChessSquare piece; int startColor;
9274 XPoint * start; XPoint * finish;
9275 XPoint frames[]; int nFrames;
9279 BeginAnimation(anim, piece, startColor, start);
9280 for (n = 0; n < nFrames; n++) {
9281 AnimationFrame(anim, &(frames[n]), piece);
9282 FrameDelay(appData.animSpeed);
9284 EndAnimation(anim, finish);
9287 /* Main control logic for deciding what to animate and how */
9290 AnimateMove(board, fromX, fromY, toX, toY)
9299 XPoint start, finish, mid;
9300 XPoint frames[kFactor * 2 + 1];
9301 int nFrames, startColor, endColor;
9303 /* Are we animating? */
9304 if (!appData.animate || appData.blindfold)
9307 if(board[toY][toX] == WhiteRook && board[fromY][fromX] == WhiteKing ||
9308 board[toY][toX] == BlackRook && board[fromY][fromX] == BlackKing)
9309 return; // [HGM] FRC: no animtion of FRC castlings, as to-square is not true to-square
9311 if (fromY < 0 || fromX < 0 || toX < 0 || toY < 0) return;
9312 piece = board[fromY][fromX];
9313 if (piece >= EmptySquare) return;
9318 hop = (piece == WhiteKnight || piece == BlackKnight);
9321 if (appData.debugMode) {
9322 fprintf(debugFP, hop ? _("AnimateMove: piece %d hops from %d,%d to %d,%d \n") :
9323 _("AnimateMove: piece %d slides from %d,%d to %d,%d \n"),
9324 piece, fromX, fromY, toX, toY); }
9326 ScreenSquare(fromX, fromY, &start, &startColor);
9327 ScreenSquare(toX, toY, &finish, &endColor);
9330 /* Knight: make diagonal movement then straight */
9331 if (abs(toY - fromY) < abs(toX - fromX)) {
9332 mid.x = start.x + (finish.x - start.x) / 2;
9336 mid.y = start.y + (finish.y - start.y) / 2;
9339 mid.x = start.x + (finish.x - start.x) / 2;
9340 mid.y = start.y + (finish.y - start.y) / 2;
9343 /* Don't use as many frames for very short moves */
9344 if (abs(toY - fromY) + abs(toX - fromX) <= 2)
9345 Tween(&start, &mid, &finish, kFactor - 1, frames, &nFrames);
9347 Tween(&start, &mid, &finish, kFactor, frames, &nFrames);
9348 FrameSequence(&game, piece, startColor, &start, &finish, frames, nFrames);
9350 /* Be sure end square is redrawn */
9351 damage[toY][toX] = True;
9355 DragPieceBegin(x, y)
9358 int boardX, boardY, color;
9361 /* Are we animating? */
9362 if (!appData.animateDragging || appData.blindfold)
9365 /* Figure out which square we start in and the
9366 mouse position relative to top left corner. */
9367 BoardSquare(x, y, &boardX, &boardY);
9368 player.startBoardX = boardX;
9369 player.startBoardY = boardY;
9370 ScreenSquare(boardX, boardY, &corner, &color);
9371 player.startSquare = corner;
9372 player.startColor = color;
9374 /* Start from exactly where the piece is. This can be confusing
9375 if you start dragging far from the center of the square; most
9376 or all of the piece can be over a different square from the one
9377 the mouse pointer is in. */
9378 player.mouseDelta.x = x - corner.x;
9379 player.mouseDelta.y = y - corner.y;
9381 /* As soon as we start dragging, the piece will jump slightly to
9382 be centered over the mouse pointer. */
9383 player.mouseDelta.x = squareSize/2;
9384 player.mouseDelta.y = squareSize/2;
9386 /* Initialise animation */
9387 player.dragPiece = PieceForSquare(boardX, boardY);
9389 if (player.dragPiece >= 0 && player.dragPiece < EmptySquare) {
9390 player.dragActive = True;
9391 BeginAnimation(&player, player.dragPiece, color, &corner);
9392 /* Mark this square as needing to be redrawn. Note that
9393 we don't remove the piece though, since logically (ie
9394 as seen by opponent) the move hasn't been made yet. */
9395 if(boardX == BOARD_RGHT+1 && PieceForSquare(boardX-1, boardY) > 1 ||
9396 boardX == BOARD_LEFT-2 && PieceForSquare(boardX+1, boardY) > 1)
9397 XCopyArea(xDisplay, xBoardWindow, player.saveBuf, player.blitGC,
9398 corner.x, corner.y, squareSize, squareSize,
9399 0, 0); // [HGM] zh: unstack in stead of grab
9400 damage[boardY][boardX] = True;
9402 player.dragActive = False;
9412 /* Are we animating? */
9413 if (!appData.animateDragging || appData.blindfold)
9417 if (! player.dragActive)
9419 /* Move piece, maintaining same relative position
9420 of mouse within square */
9421 corner.x = x - player.mouseDelta.x;
9422 corner.y = y - player.mouseDelta.y;
9423 AnimationFrame(&player, &corner, player.dragPiece);
9425 if (appData.highlightDragging) {
9427 BoardSquare(x, y, &boardX, &boardY);
9428 SetHighlights(fromX, fromY, boardX, boardY);
9437 int boardX, boardY, color;
9440 /* Are we animating? */
9441 if (!appData.animateDragging || appData.blindfold)
9445 if (! player.dragActive)
9447 /* Last frame in sequence is square piece is
9448 placed on, which may not match mouse exactly. */
9449 BoardSquare(x, y, &boardX, &boardY);
9450 ScreenSquare(boardX, boardY, &corner, &color);
9451 EndAnimation(&player, &corner);
9453 /* Be sure end square is redrawn */
9454 damage[boardY][boardX] = True;
9456 /* This prevents weird things happening with fast successive
9457 clicks which on my Sun at least can cause motion events
9458 without corresponding press/release. */
9459 player.dragActive = False;
9462 /* Handle expose event while piece being dragged */
9467 if (!player.dragActive || appData.blindfold)
9470 /* What we're doing: logically, the move hasn't been made yet,
9471 so the piece is still in it's original square. But visually
9472 it's being dragged around the board. So we erase the square
9473 that the piece is on and draw it at the last known drag point. */
9474 BlankSquare(player.startSquare.x, player.startSquare.y,
9475 player.startColor, EmptySquare, xBoardWindow);
9476 AnimationFrame(&player, &player.prevFrame, player.dragPiece);
9477 damage[player.startBoardY][player.startBoardX] = TRUE;
9481 SetProgramStats( FrontEndProgramStats * stats )
9484 // [HGM] done, but perhaps backend should call this directly?
9485 EngineOutputUpdate( stats );