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) 1},
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},
1404 { "keepAlive", "keepAlive", XtRInt,
1405 sizeof(int), XtOffset(AppDataPtr, keepAlive),
1406 XtRImmediate, (XtPointer) 0},
1409 XrmOptionDescRec shellOptions[] = {
1410 { "-whitePieceColor", "whitePieceColor", XrmoptionSepArg, NULL },
1411 { "-blackPieceColor", "blackPieceColor", XrmoptionSepArg, NULL },
1412 { "-lightSquareColor", "lightSquareColor", XrmoptionSepArg, NULL },
1413 { "-darkSquareColor", "darkSquareColor", XrmoptionSepArg, NULL },
1414 { "-highlightSquareColor", "highlightSquareColor", XrmoptionSepArg, NULL },
1415 { "-premoveHighlightColor", "premoveHighlightColor", XrmoptionSepArg,NULL},
1416 { "-movesPerSession", "movesPerSession", XrmoptionSepArg, NULL },
1417 { "-mps", "movesPerSession", XrmoptionSepArg, NULL },
1418 { "-timeIncrement", "timeIncrement", XrmoptionSepArg, NULL },
1419 { "-inc", "timeIncrement", XrmoptionSepArg, NULL },
1420 { "-initString", "initString", XrmoptionSepArg, NULL },
1421 { "-firstInitString", "initString", XrmoptionSepArg, NULL },
1422 { "-secondInitString", "secondInitString", XrmoptionSepArg, NULL },
1423 { "-firstComputerString", "firstComputerString", XrmoptionSepArg, NULL },
1424 { "-secondComputerString", "secondComputerString", XrmoptionSepArg, NULL },
1425 { "-firstChessProgram", "firstChessProgram", XrmoptionSepArg, NULL },
1426 { "-fcp", "firstChessProgram", XrmoptionSepArg, NULL },
1427 { "-secondChessProgram", "secondChessProgram", XrmoptionSepArg, NULL },
1428 { "-scp", "secondChessProgram", XrmoptionSepArg, NULL },
1429 { "-firstPlaysBlack", "firstPlaysBlack", XrmoptionSepArg, NULL },
1430 { "-fb", "firstPlaysBlack", XrmoptionNoArg, "True" },
1431 { "-xfb", "firstPlaysBlack", XrmoptionNoArg, "False" },
1432 { "-noChessProgram", "noChessProgram", XrmoptionSepArg, NULL },
1433 { "-ncp", "noChessProgram", XrmoptionNoArg, "True" },
1434 { "-xncp", "noChessProgram", XrmoptionNoArg, "False" },
1435 { "-firstHost", "firstHost", XrmoptionSepArg, NULL },
1436 { "-fh", "firstHost", XrmoptionSepArg, NULL },
1437 { "-secondHost", "secondHost", XrmoptionSepArg, NULL },
1438 { "-sh", "secondHost", XrmoptionSepArg, NULL },
1439 { "-firstDirectory", "firstDirectory", XrmoptionSepArg, NULL },
1440 { "-fd", "firstDirectory", XrmoptionSepArg, NULL },
1441 { "-secondDirectory", "secondDirectory", XrmoptionSepArg, NULL },
1442 { "-sd", "secondDirectory", XrmoptionSepArg, NULL },
1443 { "-bitmapDirectory", "bitmapDirectory", XrmoptionSepArg, NULL },
1444 { "-bm", "bitmapDirectory", XrmoptionSepArg, NULL },
1445 { "-remoteShell", "remoteShell", XrmoptionSepArg, NULL },
1446 { "-rsh", "remoteShell", XrmoptionSepArg, NULL },
1447 { "-remoteUser", "remoteUser", XrmoptionSepArg, NULL },
1448 { "-ruser", "remoteUser", XrmoptionSepArg, NULL },
1449 { "-timeDelay", "timeDelay", XrmoptionSepArg, NULL },
1450 { "-td", "timeDelay", XrmoptionSepArg, NULL },
1451 { "-timeControl", "timeControl", XrmoptionSepArg, NULL },
1452 { "-tc", "timeControl", XrmoptionSepArg, NULL },
1453 { "-internetChessServerMode", "internetChessServerMode",
1454 XrmoptionSepArg, NULL },
1455 { "-ics", "internetChessServerMode", XrmoptionNoArg, "True" },
1456 { "-xics", "internetChessServerMode", XrmoptionNoArg, "False" },
1457 { "-internetChessServerHost", "internetChessServerHost",
1458 XrmoptionSepArg, NULL },
1459 { "-icshost", "internetChessServerHost", XrmoptionSepArg, NULL },
1460 { "-internetChessServerPort", "internetChessServerPort",
1461 XrmoptionSepArg, NULL },
1462 { "-icsport", "internetChessServerPort", XrmoptionSepArg, NULL },
1463 { "-internetChessServerCommPort", "internetChessServerCommPort",
1464 XrmoptionSepArg, NULL },
1465 { "-icscomm", "internetChessServerCommPort", XrmoptionSepArg, NULL },
1466 { "-internetChessServerLogonScript", "internetChessServerLogonScript",
1467 XrmoptionSepArg, NULL },
1468 { "-icslogon", "internetChessServerLogonScript", XrmoptionSepArg, NULL },
1469 { "-internetChessServerHelper", "internetChessServerHelper",
1470 XrmoptionSepArg, NULL },
1471 { "-icshelper", "internetChessServerHelper", XrmoptionSepArg, NULL },
1472 { "-internetChessServerInputBox", "internetChessServerInputBox",
1473 XrmoptionSepArg, NULL },
1474 { "-icsinput", "internetChessServerInputBox", XrmoptionNoArg, "True" },
1475 { "-xicsinput", "internetChessServerInputBox", XrmoptionNoArg, "False" },
1476 { "-icsAlarm", "icsAlarm", XrmoptionSepArg, NULL },
1477 { "-alarm", "icsAlarm", XrmoptionNoArg, "True" },
1478 { "-xalarm", "icsAlarm", XrmoptionNoArg, "False" },
1479 { "-icsAlarmTime", "icsAlarmTime", XrmoptionSepArg, NULL },
1480 { "-useTelnet", "useTelnet", XrmoptionSepArg, NULL },
1481 { "-telnet", "useTelnet", XrmoptionNoArg, "True" },
1482 { "-xtelnet", "useTelnet", XrmoptionNoArg, "False" },
1483 { "-telnetProgram", "telnetProgram", XrmoptionSepArg, NULL },
1484 { "-gateway", "gateway", XrmoptionSepArg, NULL },
1485 { "-loadGameFile", "loadGameFile", XrmoptionSepArg, NULL },
1486 { "-lgf", "loadGameFile", XrmoptionSepArg, NULL },
1487 { "-loadGameIndex", "loadGameIndex", XrmoptionSepArg, NULL },
1488 { "-lgi", "loadGameIndex", XrmoptionSepArg, NULL },
1489 { "-saveGameFile", "saveGameFile", XrmoptionSepArg, NULL },
1490 { "-sgf", "saveGameFile", XrmoptionSepArg, NULL },
1491 { "-autoSaveGames", "autoSaveGames", XrmoptionSepArg, NULL },
1492 { "-autosave", "autoSaveGames", XrmoptionNoArg, "True" },
1493 { "-xautosave", "autoSaveGames", XrmoptionNoArg, "False" },
1494 { "-autoRaiseBoard", "autoRaiseBoard", XrmoptionSepArg, NULL },
1495 { "-autoraise", "autoRaiseBoard", XrmoptionNoArg, "True" },
1496 { "-xautoraise", "autoRaiseBoard", XrmoptionNoArg, "False" },
1497 { "-blindfold", "blindfold", XrmoptionSepArg, NULL },
1498 { "-blind", "blindfold", XrmoptionNoArg, "True" },
1499 { "-xblind", "blindfold", XrmoptionNoArg, "False" },
1500 { "-loadPositionFile", "loadPositionFile", XrmoptionSepArg, NULL },
1501 { "-lpf", "loadPositionFile", XrmoptionSepArg, NULL },
1502 { "-loadPositionIndex", "loadPositionIndex", XrmoptionSepArg, NULL },
1503 { "-lpi", "loadPositionIndex", XrmoptionSepArg, NULL },
1504 { "-savePositionFile", "savePositionFile", XrmoptionSepArg, NULL },
1505 { "-spf", "savePositionFile", XrmoptionSepArg, NULL },
1506 { "-matchMode", "matchMode", XrmoptionSepArg, NULL },
1507 { "-mm", "matchMode", XrmoptionNoArg, "True" },
1508 { "-xmm", "matchMode", XrmoptionNoArg, "False" },
1509 { "-matchGames", "matchGames", XrmoptionSepArg, NULL },
1510 { "-mg", "matchGames", XrmoptionSepArg, NULL },
1511 { "-monoMode", "monoMode", XrmoptionSepArg, NULL },
1512 { "-mono", "monoMode", XrmoptionNoArg, "True" },
1513 { "-xmono", "monoMode", XrmoptionNoArg, "False" },
1514 { "-debugMode", "debugMode", XrmoptionSepArg, NULL },
1515 { "-debug", "debugMode", XrmoptionNoArg, "True" },
1516 { "-xdebug", "debugMode", XrmoptionNoArg, "False" },
1517 { "-clockMode", "clockMode", XrmoptionSepArg, NULL },
1518 { "-clock", "clockMode", XrmoptionNoArg, "True" },
1519 { "-xclock", "clockMode", XrmoptionNoArg, "False" },
1520 { "-boardSize", "boardSize", XrmoptionSepArg, NULL },
1521 { "-size", "boardSize", XrmoptionSepArg, NULL },
1522 { "-searchTime", "searchTime", XrmoptionSepArg, NULL },
1523 { "-st", "searchTime", XrmoptionSepArg, NULL },
1524 { "-searchDepth", "searchDepth", XrmoptionSepArg, NULL },
1525 { "-depth", "searchDepth", XrmoptionSepArg, NULL },
1526 { "-showCoords", "showCoords", XrmoptionSepArg, NULL },
1527 { "-coords", "showCoords", XrmoptionNoArg, "True" },
1528 { "-xcoords", "showCoords", XrmoptionNoArg, "False" },
1530 { "-showJail", "showJail", XrmoptionSepArg, NULL },
1531 { "-jail", "showJail", XrmoptionNoArg, "1" },
1532 { "-sidejail", "showJail", XrmoptionNoArg, "2" },
1533 { "-xjail", "showJail", XrmoptionNoArg, "0" },
1535 { "-showThinking", "showThinking", XrmoptionSepArg, NULL },
1536 { "-thinking", "showThinking", XrmoptionNoArg, "True" },
1537 { "-xthinking", "showThinking", XrmoptionNoArg, "False" },
1538 { "-ponderNextMove", "ponderNextMove", XrmoptionSepArg, NULL },
1539 { "-ponder", "ponderNextMove", XrmoptionNoArg, "True" },
1540 { "-xponder", "ponderNextMove", XrmoptionNoArg, "False" },
1541 { "-periodicUpdates", "periodicUpdates", XrmoptionSepArg, NULL },
1542 { "-periodic", "periodicUpdates", XrmoptionNoArg, "True" },
1543 { "-xperiodic", "periodicUpdates", XrmoptionNoArg, "False" },
1544 { "-clockFont", "clockFont", XrmoptionSepArg, NULL },
1545 { "-coordFont", "coordFont", XrmoptionSepArg, NULL },
1546 { "-font", "font", XrmoptionSepArg, NULL },
1547 { "-ringBellAfterMoves", "ringBellAfterMoves", XrmoptionSepArg, NULL },
1548 { "-bell", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1549 { "-xbell", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1550 { "-movesound", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1551 { "-xmovesound", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1552 { "-autoCallFlag", "autoCallFlag", XrmoptionSepArg, NULL },
1553 { "-autoflag", "autoCallFlag", XrmoptionNoArg, "True" },
1554 { "-xautoflag", "autoCallFlag", XrmoptionNoArg, "False" },
1555 { "-autoFlipView", "autoFlipView", XrmoptionSepArg, NULL },
1556 { "-autoflip", "autoFlipView", XrmoptionNoArg, "True" },
1557 { "-xautoflip", "autoFlipView", XrmoptionNoArg, "False" },
1558 { "-autoObserve", "autoObserve", XrmoptionSepArg, NULL },
1559 { "-autobs", "autoObserve", XrmoptionNoArg, "True" },
1560 { "-xautobs", "autoObserve", XrmoptionNoArg, "False" },
1561 { "-autoComment", "autoComment", XrmoptionSepArg, NULL },
1562 { "-autocomm", "autoComment", XrmoptionNoArg, "True" },
1563 { "-xautocomm", "autoComment", XrmoptionNoArg, "False" },
1564 { "-getMoveList", "getMoveList", XrmoptionSepArg, NULL },
1565 { "-moves", "getMoveList", XrmoptionNoArg, "True" },
1566 { "-xmoves", "getMoveList", XrmoptionNoArg, "False" },
1568 { "-highlightDragging", "highlightDragging", XrmoptionSepArg, NULL },
1569 { "-highdrag", "highlightDragging", XrmoptionNoArg, "True" },
1570 { "-xhighdrag", "highlightDragging", XrmoptionNoArg, "False" },
1572 { "-highlightLastMove", "highlightLastMove", XrmoptionSepArg, NULL },
1573 { "-highlight", "highlightLastMove", XrmoptionNoArg, "True" },
1574 { "-xhighlight", "highlightLastMove", XrmoptionNoArg, "False" },
1575 { "-premove", "premove", XrmoptionSepArg, NULL },
1576 { "-pre", "premove", XrmoptionNoArg, "True" },
1577 { "-xpre", "premove", XrmoptionNoArg, "False" },
1578 { "-testLegality", "testLegality", XrmoptionSepArg, NULL },
1579 { "-legal", "testLegality", XrmoptionNoArg, "True" },
1580 { "-xlegal", "testLegality", XrmoptionNoArg, "False" },
1581 { "-flipView", "flipView", XrmoptionSepArg, NULL },
1582 { "-flip", "flipView", XrmoptionNoArg, "True" },
1583 { "-xflip", "flipView", XrmoptionNoArg, "False" },
1584 { "-cmail", "cmailGameName", XrmoptionSepArg, NULL },
1585 { "-alwaysPromoteToQueen", "alwaysPromoteToQueen",
1586 XrmoptionSepArg, NULL },
1587 { "-queen", "alwaysPromoteToQueen", XrmoptionNoArg, "True" },
1588 { "-xqueen", "alwaysPromoteToQueen", XrmoptionNoArg, "False" },
1589 { "-oldSaveStyle", "oldSaveStyle", XrmoptionSepArg, NULL },
1590 { "-oldsave", "oldSaveStyle", XrmoptionNoArg, "True" },
1591 { "-xoldsave", "oldSaveStyle", XrmoptionNoArg, "False" },
1592 { "-quietPlay", "quietPlay", XrmoptionSepArg, NULL },
1593 { "-quiet", "quietPlay", XrmoptionNoArg, "True" },
1594 { "-xquiet", "quietPlay", XrmoptionNoArg, "False" },
1595 { "-titleInWindow", "titleInWindow", XrmoptionSepArg, NULL },
1596 { "-title", "titleInWindow", XrmoptionNoArg, "True" },
1597 { "-xtitle", "titleInWindow", XrmoptionNoArg, "False" },
1599 { "-zippyTalk", "zippyTalk", XrmoptionSepArg, NULL },
1600 { "-zt", "zippyTalk", XrmoptionNoArg, "True" },
1601 { "-xzt", "zippyTalk", XrmoptionNoArg, "False" },
1602 { "-zippyPlay", "zippyPlay", XrmoptionSepArg, NULL },
1603 { "-zp", "zippyPlay", XrmoptionNoArg, "True" },
1604 { "-xzp", "zippyPlay", XrmoptionNoArg, "False" },
1605 { "-zippyLines", "zippyLines", XrmoptionSepArg, NULL },
1606 { "-zippyPinhead", "zippyPinhead", XrmoptionSepArg, NULL },
1607 { "-zippyPassword", "zippyPassword", XrmoptionSepArg, NULL },
1608 { "-zippyPassword2", "zippyPassword2", XrmoptionSepArg, NULL },
1609 { "-zippyWrongPassword", "zippyWrongPassword", XrmoptionSepArg, NULL },
1610 { "-zippyAcceptOnly", "zippyAcceptOnly", XrmoptionSepArg, NULL },
1611 { "-zippyUseI", "zippyUseI", XrmoptionSepArg, NULL },
1612 { "-zui", "zippyUseI", XrmoptionNoArg, "True" },
1613 { "-xzui", "zippyUseI", XrmoptionNoArg, "False" },
1614 { "-zippyBughouse", "zippyBughouse", XrmoptionSepArg, NULL },
1615 { "-zippyNoplayCrafty", "zippyNoplayCrafty", XrmoptionSepArg, NULL },
1616 { "-znc", "zippyNoplayCrafty", XrmoptionNoArg, "True" },
1617 { "-xznc", "zippyNoplayCrafty", XrmoptionNoArg, "False" },
1618 { "-zippyGameEnd", "zippyGameEnd", XrmoptionSepArg, NULL },
1619 { "-zippyGameStart", "zippyGameStart", XrmoptionSepArg, NULL },
1620 { "-zippyAdjourn", "zippyAdjourn", XrmoptionSepArg, NULL },
1621 { "-zadj", "zippyAdjourn", XrmoptionNoArg, "True" },
1622 { "-xzadj", "zippyAdjourn", XrmoptionNoArg, "False" },
1623 { "-zippyAbort", "zippyAbort", XrmoptionSepArg, NULL },
1624 { "-zab", "zippyAbort", XrmoptionNoArg, "True" },
1625 { "-xzab", "zippyAbort", XrmoptionNoArg, "False" },
1626 { "-zippyVariants", "zippyVariants", XrmoptionSepArg, NULL },
1627 { "-zippyMaxGames", "zippyMaxGames", XrmoptionSepArg, NULL },
1628 { "-zippyReplayTimeout", "zippyReplayTimeout", XrmoptionSepArg, NULL },
1629 { "-zippyShortGame", "zippyShortGame", XrmoptionSepArg, NULL },
1631 { "-flashCount", "flashCount", XrmoptionSepArg, NULL },
1632 { "-flash", "flashCount", XrmoptionNoArg, "3" },
1633 { "-xflash", "flashCount", XrmoptionNoArg, "0" },
1634 { "-flashRate", "flashRate", XrmoptionSepArg, NULL },
1635 { "-pixmapDirectory", "pixmapDirectory", XrmoptionSepArg, NULL },
1636 { "-msLoginDelay", "msLoginDelay", XrmoptionSepArg, NULL },
1637 { "-pixmap", "pixmapDirectory", XrmoptionSepArg, NULL },
1638 { "-colorizeMessages", "colorizeMessages", XrmoptionSepArg, NULL },
1639 { "-colorize", "colorizeMessages", XrmoptionNoArg, "True" },
1640 { "-xcolorize", "colorizeMessages", XrmoptionNoArg, "False" },
1641 { "-colorShout", "colorShout", XrmoptionSepArg, NULL },
1642 { "-colorSShout", "colorSShout", XrmoptionSepArg, NULL },
1643 { "-colorCShout", "colorSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1644 { "-colorChannel1", "colorChannel1", XrmoptionSepArg, NULL },
1645 { "-colorChannel", "colorChannel", XrmoptionSepArg, NULL },
1646 { "-colorKibitz", "colorKibitz", XrmoptionSepArg, NULL },
1647 { "-colorTell", "colorTell", XrmoptionSepArg, NULL },
1648 { "-colorChallenge", "colorChallenge", XrmoptionSepArg, NULL },
1649 { "-colorRequest", "colorRequest", XrmoptionSepArg, NULL },
1650 { "-colorSeek", "colorSeek", XrmoptionSepArg, NULL },
1651 { "-colorNormal", "colorNormal", XrmoptionSepArg, NULL },
1652 { "-soundProgram", "soundProgram", XrmoptionSepArg, NULL },
1653 { "-soundShout", "soundShout", XrmoptionSepArg, NULL },
1654 { "-soundSShout", "soundSShout", XrmoptionSepArg, NULL },
1655 { "-soundCShout", "soundSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1656 { "-soundChannel1", "soundChannel1", XrmoptionSepArg, NULL },
1657 { "-soundChannel", "soundChannel", XrmoptionSepArg, NULL },
1658 { "-soundKibitz", "soundKibitz", XrmoptionSepArg, NULL },
1659 { "-soundTell", "soundTell", XrmoptionSepArg, NULL },
1660 { "-soundChallenge", "soundChallenge", XrmoptionSepArg, NULL },
1661 { "-soundRequest", "soundRequest", XrmoptionSepArg, NULL },
1662 { "-soundSeek", "soundSeek", XrmoptionSepArg, NULL },
1663 { "-soundMove", "soundMove", XrmoptionSepArg, NULL },
1664 { "-soundIcsWin", "soundIcsWin", XrmoptionSepArg, NULL },
1665 { "-soundIcsLoss", "soundIcsLoss", XrmoptionSepArg, NULL },
1666 { "-soundIcsDraw", "soundIcsDraw", XrmoptionSepArg, NULL },
1667 { "-soundIcsUnfinished", "soundIcsUnfinished", XrmoptionSepArg, NULL },
1668 { "-soundIcsAlarm", "soundIcsAlarm", XrmoptionSepArg, NULL },
1669 { "-reuseFirst", "reuseFirst", XrmoptionSepArg, NULL },
1670 { "-reuseChessPrograms", "reuseFirst", XrmoptionSepArg, NULL }, /*compat*/
1671 { "-reuse", "reuseFirst", XrmoptionNoArg, "True" },
1672 { "-xreuse", "reuseFirst", XrmoptionNoArg, "False" },
1673 { "-reuseSecond", "reuseSecond", XrmoptionSepArg, NULL },
1674 { "-reuse2", "reuseSecond", XrmoptionNoArg, "True" },
1675 { "-xreuse2", "reuseSecond", XrmoptionNoArg, "False" },
1676 { "-animateMoving", "animateMoving", XrmoptionSepArg, NULL },
1677 { "-animate", "animateMoving", XrmoptionNoArg, "True" },
1678 { "-xanimate", "animateMoving", XrmoptionNoArg, "False" },
1679 { "-animateDragging", "animateDragging", XrmoptionSepArg, NULL },
1680 { "-drag", "animateDragging", XrmoptionNoArg, "True" },
1681 { "-xdrag", "animateDragging", XrmoptionNoArg, "False" },
1682 { "-animateSpeed", "animateSpeed", XrmoptionSepArg, NULL },
1683 { "-popupExitMessage", "popupExitMessage", XrmoptionSepArg, NULL },
1684 { "-exit", "popupExitMessage", XrmoptionNoArg, "True" },
1685 { "-xexit", "popupExitMessage", XrmoptionNoArg, "False" },
1686 { "-popupMoveErrors", "popupMoveErrors", XrmoptionSepArg, NULL },
1687 { "-popup", "popupMoveErrors", XrmoptionNoArg, "True" },
1688 { "-xpopup", "popupMoveErrors", XrmoptionNoArg, "False" },
1689 { "-fontSizeTolerance", "fontSizeTolerance", XrmoptionSepArg, NULL },
1690 { "-initialMode", "initialMode", XrmoptionSepArg, NULL },
1691 { "-mode", "initialMode", XrmoptionSepArg, NULL },
1692 { "-variant", "variant", XrmoptionSepArg, NULL },
1693 { "-firstProtocolVersion", "firstProtocolVersion", XrmoptionSepArg, NULL },
1694 { "-secondProtocolVersion","secondProtocolVersion",XrmoptionSepArg, NULL },
1695 { "-showButtonBar", "showButtonBar", XrmoptionSepArg, NULL },
1696 { "-buttons", "showButtonBar", XrmoptionNoArg, "True" },
1697 { "-xbuttons", "showButtonBar", XrmoptionNoArg, "False" },
1698 { "-lowTimeWarningColor", "lowTimeWarningColor", XrmoptionSepArg, NULL },
1699 { "-lowTimeWarning", "lowTimeWarning", XrmoptionSepArg, NULL },
1700 /* [AS,HR] New features */
1701 { "-firstScoreAbs", "firstScoreAbs", XrmoptionSepArg, NULL },
1702 { "-secondScoreAbs", "secondScoreAbs", XrmoptionSepArg, NULL },
1703 { "-pgnExtendedInfo", "pgnExtendedInfo", XrmoptionSepArg, NULL },
1704 { "-hideThinkingFromHuman", "hideThinkingFromHuman", XrmoptionSepArg, NULL },
1705 { "-adjudicateLossThreshold", "adjudicateLossThreshold", XrmoptionSepArg, NULL },
1706 { "-adjudicateDrawMoves", "adjudicateDrawMoves", XrmoptionSepArg, NULL },
1707 { "-pgnEventHeader", "pgnEventHeader", XrmoptionSepArg, NULL },
1708 { "-firstIsUCI", "firstIsUCI", XrmoptionSepArg, NULL },
1709 { "-secondIsUCI", "secondIsUCI", XrmoptionSepArg, NULL },
1710 { "-fUCI", "firstIsUCI", XrmoptionNoArg, "True" },
1711 { "-sUCI", "secondIsUCI", XrmoptionNoArg, "True" },
1712 { "-firstHasOwnBookUCI", "firstHasOwnBookUCI", XrmoptionSepArg, NULL },
1713 { "-secondHasOwnBookUCI", "secondHasOwnBookUCI", XrmoptionSepArg, NULL },
1714 { "-fNoOwnBookUCI", "firstHasOwnBookUCI", XrmoptionNoArg, "False" },
1715 { "-sNoOwnBookUCI", "secondHasOwnBookUCI", XrmoptionNoArg, "False" },
1716 { "-firstXBook", "firstHasOwnBookUCI", XrmoptionNoArg, "False" },
1717 { "-secondXBook", "secondHasOwnBookUCI", XrmoptionNoArg, "False" },
1718 { "-polyglotDir", "polyglotDir", XrmoptionSepArg, NULL },
1719 { "-usePolyglotBook", "usePolyglotBook", XrmoptionSepArg, NULL },
1720 { "-polyglotBook", "polyglotBook", XrmoptionSepArg, NULL },
1721 { "-defaultHashSize", "defaultHashSize", XrmoptionSepArg, NULL },
1722 { "-defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XrmoptionSepArg, NULL },
1723 { "-defaultPathEGTB", "defaultPathEGTB", XrmoptionSepArg, NULL },
1724 { "-defaultFrcPosition", "defaultFrcPosition", XrmoptionSepArg, NULL },
1725 { "-gameListTags", "gameListTags", XrmoptionSepArg, NULL },
1726 // [HGM] I am sure AS added many more options, but we have to fish them out, from the list in winboard.c
1728 /* [HGM,HR] User-selectable board size */
1729 { "-boardWidth", "boardWidth", XrmoptionSepArg, NULL },
1730 { "-boardHeight", "boardHeight", XrmoptionSepArg, NULL },
1731 { "-matchPause", "matchPause", XrmoptionSepArg, NULL },
1733 /* [HGM] new arguments of 4.3.xx. All except first three are back-end options, which should work immediately */
1734 { "-holdingsSize", "holdingsSize", XrmoptionSepArg, NULL }, // requires extensive front-end changes to work
1735 { "-flipBlack", "flipBlack", XrmoptionSepArg, NULL }, // requires front-end changes to work
1736 { "-allWhite", "allWhite", XrmoptionSepArg, NULL }, // requires front-end changes to work
1737 { "-pieceToCharTable", "pieceToCharTable", XrmoptionSepArg, NULL },
1738 { "-alphaRank", "alphaRank", XrmoptionSepArg, NULL },
1739 { "-testClaims", "testClaims", XrmoptionSepArg, NULL },
1740 { "-checkMates", "checkMates", XrmoptionSepArg, NULL },
1741 { "-materialDraws", "materialDraws", XrmoptionSepArg, NULL },
1742 { "-trivialDraws", "trivialDraws", XrmoptionSepArg, NULL },
1743 { "-ruleMoves", "ruleMoves", XrmoptionSepArg, NULL },
1744 { "-repeatsToDraw", "repeatsToDraw", XrmoptionSepArg, NULL },
1745 { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL },
1746 { "-userName", "userName", XrmoptionSepArg, NULL },
1747 { "-autoKibitz", "autoKibitz", XrmoptionNoArg, "True" },
1748 { "-firstTimeOdds", "firstTimeOdds", XrmoptionSepArg, NULL },
1749 { "-secondTimeOdds", "secondTimeOdds", XrmoptionSepArg, NULL },
1750 { "-timeOddsMode", "timeOddsMode", XrmoptionSepArg, NULL },
1751 { "-firstAccumulateTC", "firstAccumulateTC", XrmoptionSepArg, NULL },
1752 { "-secondAccumulateTC", "secondAccumulateTC", XrmoptionSepArg, NULL },
1753 { "-firstNPS", "firstNPS", XrmoptionSepArg, NULL },
1754 { "-secondNPS", "secondNPS", XrmoptionSepArg, NULL },
1755 { "-serverMoves", "serverMoves", XrmoptionSepArg, NULL },
1756 { "-serverPause", "serverPause", XrmoptionSepArg, NULL },
1757 { "-suppressLoadMoves", "suppressLoadMoves", XrmoptionSepArg, NULL },
1758 { "-egtFormats", "egtFormats", XrmoptionSepArg, NULL },
1759 { "-userName", "userName", XrmoptionSepArg, NULL },
1760 { "-smpCores", "smpCores", XrmoptionSepArg, NULL },
1761 { "-sameColorGames", "sameColorGames", XrmoptionSepArg, NULL },
1762 { "-rewindIndex", "rewindIndex", XrmoptionSepArg, NULL },
1763 { "-niceEngines", "niceEngines", XrmoptionSepArg, NULL },
1764 { "-delayBeforeQuit", "delayBeforeQuit", XrmoptionSepArg, NULL },
1765 { "-delayAfterQuit", "delayAfterQuit", XrmoptionSepArg, NULL },
1766 { "-nameOfDebugFile", "nameOfDebugFile", XrmoptionSepArg, NULL },
1767 { "-debugFile", "nameOfDebugFile", XrmoptionSepArg, NULL },
1768 { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL },
1769 { "-noGUI", "noGUI", XrmoptionNoArg, "True" },
1770 { "-firstOptions", "firstOptions", XrmoptionSepArg, NULL },
1771 { "-secondOptions", "secondOptions", XrmoptionSepArg, NULL },
1772 { "-firstNeedsNoncompliantFEN", "firstNeedsNoncompliantFEN", XrmoptionSepArg, NULL },
1773 { "-secondNeedsNoncompliantFEN", "secondNeedsNoncompliantFEN", XrmoptionSepArg, NULL },
1774 { "-keepAlive", "keepAlive", XrmoptionSepArg, NULL },
1778 XtActionsRec boardActions[] = {
1779 { "DrawPosition", DrawPositionProc },
1780 { "HandleUserMove", HandleUserMove },
1781 { "AnimateUserMove", AnimateUserMove },
1782 { "FileNameAction", FileNameAction },
1783 { "AskQuestionProc", AskQuestionProc },
1784 { "AskQuestionReplyAction", AskQuestionReplyAction },
1785 { "PieceMenuPopup", PieceMenuPopup },
1786 { "WhiteClock", WhiteClock },
1787 { "BlackClock", BlackClock },
1788 { "Iconify", Iconify },
1789 { "ResetProc", ResetProc },
1790 { "LoadGameProc", LoadGameProc },
1791 { "LoadNextGameProc", LoadNextGameProc },
1792 { "LoadPrevGameProc", LoadPrevGameProc },
1793 { "LoadSelectedProc", LoadSelectedProc },
1794 { "ReloadGameProc", ReloadGameProc },
1795 { "LoadPositionProc", LoadPositionProc },
1796 { "LoadNextPositionProc", LoadNextPositionProc },
1797 { "LoadPrevPositionProc", LoadPrevPositionProc },
1798 { "ReloadPositionProc", ReloadPositionProc },
1799 { "CopyPositionProc", CopyPositionProc },
1800 { "PastePositionProc", PastePositionProc },
1801 { "CopyGameProc", CopyGameProc },
1802 { "PasteGameProc", PasteGameProc },
1803 { "SaveGameProc", SaveGameProc },
1804 { "SavePositionProc", SavePositionProc },
1805 { "MailMoveProc", MailMoveProc },
1806 { "ReloadCmailMsgProc", ReloadCmailMsgProc },
1807 { "QuitProc", QuitProc },
1808 { "MachineWhiteProc", MachineWhiteProc },
1809 { "MachineBlackProc", MachineBlackProc },
1810 { "AnalysisModeProc", AnalyzeModeProc },
1811 { "AnalyzeFileProc", AnalyzeFileProc },
1812 { "TwoMachinesProc", TwoMachinesProc },
1813 { "IcsClientProc", IcsClientProc },
1814 { "EditGameProc", EditGameProc },
1815 { "EditPositionProc", EditPositionProc },
1816 { "TrainingProc", EditPositionProc },
1817 { "EngineOutputProc", EngineOutputProc}, // [HGM] Winboard_x engine-output window
1818 { "ShowGameListProc", ShowGameListProc },
1819 { "ShowMoveListProc", HistoryShowProc},
1820 { "EditTagsProc", EditCommentProc },
1821 { "EditCommentProc", EditCommentProc },
1822 { "IcsAlarmProc", IcsAlarmProc },
1823 { "IcsInputBoxProc", IcsInputBoxProc },
1824 { "PauseProc", PauseProc },
1825 { "AcceptProc", AcceptProc },
1826 { "DeclineProc", DeclineProc },
1827 { "RematchProc", RematchProc },
1828 { "CallFlagProc", CallFlagProc },
1829 { "DrawProc", DrawProc },
1830 { "AdjournProc", AdjournProc },
1831 { "AbortProc", AbortProc },
1832 { "ResignProc", ResignProc },
1833 { "AdjuWhiteProc", AdjuWhiteProc },
1834 { "AdjuBlackProc", AdjuBlackProc },
1835 { "AdjuDrawProc", AdjuDrawProc },
1836 { "EnterKeyProc", EnterKeyProc },
1837 { "StopObservingProc", StopObservingProc },
1838 { "StopExaminingProc", StopExaminingProc },
1839 { "BackwardProc", BackwardProc },
1840 { "ForwardProc", ForwardProc },
1841 { "ToStartProc", ToStartProc },
1842 { "ToEndProc", ToEndProc },
1843 { "RevertProc", RevertProc },
1844 { "TruncateGameProc", TruncateGameProc },
1845 { "MoveNowProc", MoveNowProc },
1846 { "RetractMoveProc", RetractMoveProc },
1847 { "AlwaysQueenProc", AlwaysQueenProc },
1848 { "AnimateDraggingProc", AnimateDraggingProc },
1849 { "AnimateMovingProc", AnimateMovingProc },
1850 { "AutoflagProc", AutoflagProc },
1851 { "AutoflipProc", AutoflipProc },
1852 { "AutobsProc", AutobsProc },
1853 { "AutoraiseProc", AutoraiseProc },
1854 { "AutosaveProc", AutosaveProc },
1855 { "BlindfoldProc", BlindfoldProc },
1856 { "FlashMovesProc", FlashMovesProc },
1857 { "FlipViewProc", FlipViewProc },
1858 { "GetMoveListProc", GetMoveListProc },
1860 { "HighlightDraggingProc", HighlightDraggingProc },
1862 { "HighlightLastMoveProc", HighlightLastMoveProc },
1863 { "IcsAlarmProc", IcsAlarmProc },
1864 { "MoveSoundProc", MoveSoundProc },
1865 { "OldSaveStyleProc", OldSaveStyleProc },
1866 { "PeriodicUpdatesProc", PeriodicUpdatesProc },
1867 { "PonderNextMoveProc", PonderNextMoveProc },
1868 { "PopupExitMessageProc", PopupExitMessageProc },
1869 { "PopupMoveErrorsProc", PopupMoveErrorsProc },
1870 { "PremoveProc", PremoveProc },
1871 { "QuietPlayProc", QuietPlayProc },
1872 { "ShowCoordsProc", ShowCoordsProc },
1873 { "ShowThinkingProc", ShowThinkingProc },
1874 { "HideThinkingProc", HideThinkingProc },
1875 { "TestLegalityProc", TestLegalityProc },
1876 { "InfoProc", InfoProc },
1877 { "ManProc", ManProc },
1878 { "HintProc", HintProc },
1879 { "BookProc", BookProc },
1880 { "AboutGameProc", AboutGameProc },
1881 { "AboutProc", AboutProc },
1882 { "DebugProc", DebugProc },
1883 { "NothingProc", NothingProc },
1884 { "CommentPopDown", (XtActionProc) CommentPopDown },
1885 { "EditCommentPopDown", (XtActionProc) EditCommentPopDown },
1886 { "TagsPopDown", (XtActionProc) TagsPopDown },
1887 { "ErrorPopDown", (XtActionProc) ErrorPopDown },
1888 { "ICSInputBoxPopDown", (XtActionProc) ICSInputBoxPopDown },
1889 { "AnalysisPopDown", (XtActionProc) AnalysisPopDown },
1890 { "FileNamePopDown", (XtActionProc) FileNamePopDown },
1891 { "AskQuestionPopDown", (XtActionProc) AskQuestionPopDown },
1892 { "GameListPopDown", (XtActionProc) GameListPopDown },
1893 { "PromotionPopDown", (XtActionProc) PromotionPopDown },
1894 { "HistoryPopDown", (XtActionProc) HistoryPopDown },
1895 { "EngineOutputPopDown", (XtActionProc) EngineOutputPopDown },
1896 { "ShufflePopDown", (XtActionProc) ShufflePopDown },
1897 { "EnginePopDown", (XtActionProc) EnginePopDown },
1898 { "UciPopDown", (XtActionProc) UciPopDown },
1899 { "TimeControlPopDown", (XtActionProc) TimeControlPopDown },
1900 { "NewVariantPopDown", (XtActionProc) NewVariantPopDown },
1901 { "SettingsPopDown", (XtActionProc) SettingsPopDown },
1904 char globalTranslations[] =
1905 ":<Key>R: ResignProc() \n \
1906 :<Key>r: ResetProc() \n \
1907 :<Key>g: LoadGameProc() \n \
1908 :<Key>N: LoadNextGameProc() \n \
1909 :<Key>P: LoadPrevGameProc() \n \
1910 :<Key>Q: QuitProc() \n \
1911 :<Key>F: ToEndProc() \n \
1912 :<Key>f: ForwardProc() \n \
1913 :<Key>B: ToStartProc() \n \
1914 :<Key>b: BackwardProc() \n \
1915 :<Key>p: PauseProc() \n \
1916 :<Key>d: DrawProc() \n \
1917 :<Key>t: CallFlagProc() \n \
1918 :<Key>i: Iconify() \n \
1919 :<Key>c: Iconify() \n \
1920 :<Key>v: FlipViewProc() \n \
1921 <KeyDown>Control_L: BackwardProc() \n \
1922 <KeyUp>Control_L: ForwardProc() \n \
1923 <KeyDown>Control_R: BackwardProc() \n \
1924 <KeyUp>Control_R: ForwardProc() \n \
1925 Shift<Key>1: AskQuestionProc(\"Direct command\",\
1926 \"Send to chess program:\",,1) \n \
1927 Shift<Key>2: AskQuestionProc(\"Direct command\",\
1928 \"Send to second chess program:\",,2) \n";
1930 char boardTranslations[] =
1931 "<Btn1Down>: HandleUserMove() \n \
1932 <Btn1Up>: HandleUserMove() \n \
1933 <Btn1Motion>: AnimateUserMove() \n \
1934 Shift<Btn2Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD)\
1935 PieceMenuPopup(menuB) \n \
1936 Any<Btn2Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD) \
1937 PieceMenuPopup(menuW) \n \
1938 Shift<Btn3Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD)\
1939 PieceMenuPopup(menuW) \n \
1940 Any<Btn3Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD) \
1941 PieceMenuPopup(menuB) \n";
1943 char whiteTranslations[] = "<BtnDown>: WhiteClock()\n";
1944 char blackTranslations[] = "<BtnDown>: BlackClock()\n";
1946 char ICSInputTranslations[] =
1947 "<Key>Return: EnterKeyProc() \n";
1949 String xboardResources[] = {
1950 "*fileName*value.translations: #override\\n <Key>Return: FileNameAction()",
1951 "*question*value.translations: #override\\n <Key>Return: AskQuestionReplyAction()",
1952 "*errorpopup*translations: #override\\n <Key>Return: ErrorPopDown()",
1957 /* Max possible square size */
1958 #define MAXSQSIZE 256
1960 static int xpm_avail[MAXSQSIZE];
1962 #ifdef HAVE_DIR_STRUCT
1964 /* Extract piece size from filename */
1966 xpm_getsize(name, len, ext)
1977 if ((p=strchr(name, '.')) == NULL ||
1978 StrCaseCmp(p+1, ext) != 0)
1984 while (*p && isdigit(*p))
1991 /* Setup xpm_avail */
1993 xpm_getavail(dirname, ext)
2001 for (i=0; i<MAXSQSIZE; ++i)
2004 if (appData.debugMode)
2005 fprintf(stderr, "XPM dir:%s:ext:%s:\n", dirname, ext);
2007 dir = opendir(dirname);
2010 fprintf(stderr, _("%s: Can't access XPM directory %s\n"),
2011 programName, dirname);
2015 while ((ent=readdir(dir)) != NULL) {
2016 i = xpm_getsize(ent->d_name, NAMLEN(ent), ext);
2017 if (i > 0 && i < MAXSQSIZE)
2027 xpm_print_avail(fp, ext)
2033 fprintf(fp, _("Available `%s' sizes:\n"), ext);
2034 for (i=1; i<MAXSQSIZE; ++i) {
2040 /* Return XPM piecesize closest to size */
2042 xpm_closest_to(dirname, size, ext)
2048 int sm_diff = MAXSQSIZE;
2052 xpm_getavail(dirname, ext);
2054 if (appData.debugMode)
2055 xpm_print_avail(stderr, ext);
2057 for (i=1; i<MAXSQSIZE; ++i) {
2060 diff = (diff<0) ? -diff : diff;
2061 if (diff < sm_diff) {
2069 fprintf(stderr, _("Error: No `%s' files!\n"), ext);
2075 #else /* !HAVE_DIR_STRUCT */
2076 /* If we are on a system without a DIR struct, we can't
2077 read the directory, so we can't collect a list of
2078 filenames, etc., so we can't do any size-fitting. */
2080 xpm_closest_to(dirname, size, ext)
2085 fprintf(stderr, _("\
2086 Warning: No DIR structure found on this system --\n\
2087 Unable to autosize for XPM/XIM pieces.\n\
2088 Please report this error to frankm@hiwaay.net.\n\
2089 Include system type & operating system in message.\n"));
2092 #endif /* HAVE_DIR_STRUCT */
2094 static char *cnames[9] = { "black", "red", "green", "yellow", "blue",
2095 "magenta", "cyan", "white" };
2099 TextColors textColors[(int)NColorClasses];
2101 /* String is: "fg, bg, attr". Which is 0, 1, 2 */
2103 parse_color(str, which)
2107 char *p, buf[100], *d;
2110 if (strlen(str) > 99) /* watch bounds on buf */
2115 for (i=0; i<which; ++i) {
2122 /* Could be looking at something like:
2124 .. in which case we want to stop on a comma also */
2125 while (*p && *p != ',' && !isalpha(*p) && !isdigit(*p))
2129 return -1; /* Use default for empty field */
2132 if (which == 2 || isdigit(*p))
2135 while (*p && isalpha(*p))
2140 for (i=0; i<8; ++i) {
2141 if (!StrCaseCmp(buf, cnames[i]))
2142 return which? (i+40) : (i+30);
2144 if (!StrCaseCmp(buf, "default")) return -1;
2146 fprintf(stderr, _("%s: unrecognized color %s\n"), programName, buf);
2151 parse_cpair(cc, str)
2155 if ((textColors[(int)cc].fg=parse_color(str, 0)) == -2) {
2156 fprintf(stderr, _("%s: can't parse foreground color in `%s'\n"),
2161 /* bg and attr are optional */
2162 textColors[(int)cc].bg = parse_color(str, 1);
2163 if ((textColors[(int)cc].attr = parse_color(str, 2)) < 0) {
2164 textColors[(int)cc].attr = 0;
2170 /* Arrange to catch delete-window events */
2171 Atom wm_delete_window;
2173 CatchDeleteWindow(Widget w, String procname)
2176 XSetWMProtocols(xDisplay, XtWindow(w), &wm_delete_window, 1);
2177 snprintf(buf, sizeof(buf), "<Message>WM_PROTOCOLS: %s() \n", procname);
2178 XtAugmentTranslations(w, XtParseTranslationTable(buf));
2185 XtSetArg(args[0], XtNiconic, False);
2186 XtSetValues(shellWidget, args, 1);
2188 XtPopup(shellWidget, XtGrabNone); /* Raise if lowered */
2192 // eventually, all layout determining code should go into a subroutine, but until then IDSIZE remains undefined
2194 #define BoardSize int
2195 void InitDrawingSizes(BoardSize boardSize, int flags)
2196 { // [HGM] resize is functional now, but for board format changes only (nr of ranks, files)
2197 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
2199 XtGeometryResult gres;
2202 if(!formWidget) return;
2205 * Enable shell resizing.
2207 shellArgs[0].value = (XtArgVal) &w;
2208 shellArgs[1].value = (XtArgVal) &h;
2209 XtGetValues(shellWidget, shellArgs, 2);
2211 shellArgs[4].value = 2*w; shellArgs[2].value = 10;
2212 shellArgs[5].value = 2*h; shellArgs[3].value = 10;
2213 XtSetValues(shellWidget, &shellArgs[2], 4);
2215 XtSetArg(args[0], XtNdefaultDistance, &sep);
2216 XtGetValues(formWidget, args, 1);
2218 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2219 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2222 XtSetArg(args[0], XtNwidth, boardWidth);
2223 XtSetArg(args[1], XtNheight, boardHeight);
2224 XtSetValues(boardWidget, args, 2);
2226 timerWidth = (boardWidth - sep) / 2;
2227 XtSetArg(args[0], XtNwidth, timerWidth);
2228 XtSetValues(whiteTimerWidget, args, 1);
2229 XtSetValues(blackTimerWidget, args, 1);
2231 XawFormDoLayout(formWidget, False);
2233 if (appData.titleInWindow) {
2235 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2236 XtSetArg(args[i], XtNheight, &h); i++;
2237 XtGetValues(titleWidget, args, i);
2239 w = boardWidth - 2*bor;
2241 XtSetArg(args[0], XtNwidth, &w);
2242 XtGetValues(menuBarWidget, args, 1);
2243 w = boardWidth - w - sep - 2*bor - 2; // WIDTH_FUDGE
2246 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
2247 if (gres != XtGeometryYes && appData.debugMode) {
2249 _("%s: titleWidget geometry error %d %d %d %d %d\n"),
2250 programName, gres, w, h, wr, hr);
2254 XawFormDoLayout(formWidget, True);
2257 * Inhibit shell resizing.
2259 shellArgs[0].value = w = (XtArgVal) boardWidth + marginW;
2260 shellArgs[1].value = h = (XtArgVal) boardHeight + marginH;
2261 shellArgs[4].value = shellArgs[2].value = w;
2262 shellArgs[5].value = shellArgs[3].value = h;
2263 XtSetValues(shellWidget, &shellArgs[0], 6);
2265 // [HGM] pieces: tailor piece bitmaps to needs of specific variant
2268 for(i=0; i<4; i++) {
2270 for(p=0; p<=(int)WhiteKing; p++)
2271 xpmPieceBitmap[i][p] = xpmPieceBitmap2[i][p]; // defaults
2272 if(gameInfo.variant == VariantShogi) {
2273 xpmPieceBitmap[i][(int)WhiteCannon] = xpmPieceBitmap2[i][(int)WhiteKing+1];
2274 xpmPieceBitmap[i][(int)WhiteNightrider] = xpmPieceBitmap2[i][(int)WhiteKing+2];
2275 xpmPieceBitmap[i][(int)WhiteSilver] = xpmPieceBitmap2[i][(int)WhiteKing+3];
2276 xpmPieceBitmap[i][(int)WhiteGrasshopper] = xpmPieceBitmap2[i][(int)WhiteKing+4];
2277 xpmPieceBitmap[i][(int)WhiteQueen] = xpmPieceBitmap2[i][(int)WhiteLance];
2280 if(gameInfo.variant == VariantGothic) {
2281 xpmPieceBitmap[i][(int)WhiteMarshall] = xpmPieceBitmap2[i][(int)WhiteSilver];
2285 // [HGM] why are thee ximMasks used at all? the ximPieceBitmaps seem to be never used!
2286 for(p=0; p<=(int)WhiteKing; p++)
2287 ximMaskPm[p] = ximMaskPm2[p]; // defaults
2288 if(gameInfo.variant == VariantShogi) {
2289 ximMaskPm[(int)WhiteCannon] = ximMaskPm2[(int)WhiteKing+1];
2290 ximMaskPm[(int)WhiteNightrider] = ximMaskPm2[(int)WhiteKing+2];
2291 ximMaskPm[(int)WhiteSilver] = ximMaskPm2[(int)WhiteKing+3];
2292 ximMaskPm[(int)WhiteGrasshopper] = ximMaskPm2[(int)WhiteKing+4];
2293 ximMaskPm[(int)WhiteQueen] = ximMaskPm2[(int)WhiteLance];
2296 if(gameInfo.variant == VariantGothic) {
2297 ximMaskPm[(int)WhiteMarshall] = ximMaskPm2[(int)WhiteSilver];
2303 for(i=0; i<2; i++) {
2305 for(p=0; p<=(int)WhiteKing; p++)
2306 pieceBitmap[i][p] = pieceBitmap2[i][p]; // defaults
2307 if(gameInfo.variant == VariantShogi) {
2308 pieceBitmap[i][(int)WhiteCannon] = pieceBitmap2[i][(int)WhiteKing+1];
2309 pieceBitmap[i][(int)WhiteNightrider] = pieceBitmap2[i][(int)WhiteKing+2];
2310 pieceBitmap[i][(int)WhiteSilver] = pieceBitmap2[i][(int)WhiteKing+3];
2311 pieceBitmap[i][(int)WhiteGrasshopper] = pieceBitmap2[i][(int)WhiteKing+4];
2312 pieceBitmap[i][(int)WhiteQueen] = pieceBitmap2[i][(int)WhiteLance];
2315 if(gameInfo.variant == VariantGothic) {
2316 pieceBitmap[i][(int)WhiteMarshall] = pieceBitmap2[i][(int)WhiteSilver];
2327 void EscapeExpand(char *p, char *q)
2328 { // [HGM] initstring: routine to shape up string arguments
2329 while(*p++ = *q++) if(p[-1] == '\\')
2331 case 'n': p[-1] = '\n'; break;
2332 case 'r': p[-1] = '\r'; break;
2333 case 't': p[-1] = '\t'; break;
2334 case '\\': p[-1] = '\\'; break;
2335 case 0: *p = 0; return;
2336 default: p[-1] = q[-1]; break;
2345 int i, j, clockFontPxlSize, coordFontPxlSize, fontPxlSize;
2346 XSetWindowAttributes window_attributes;
2348 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
2349 XrmValue vFrom, vTo;
2350 XtGeometryResult gres;
2353 int forceMono = False;
2356 // [HGM] before anything else, expand any indirection files amongst options
2357 char *argvCopy[1000]; // 1000 seems enough
2358 char newArgs[10000]; // holds actual characters
2361 srandom(time(0)); // [HGM] book: make random truly random
2364 for(i=0; i<argc; i++) {
2365 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2366 //fprintf(stderr, "arg %s\n", argv[i]);
2367 if(argv[i][0] != '@') argvCopy[j++] = argv[i]; else {
2369 FILE *f = fopen(argv[i]+1, "rb");
2370 if(f == NULL) { fprintf(stderr, _("ignore %s\n"), argv[i]); continue; } // do not expand non-existing
2371 argvCopy[j++] = newArgs + k; // get ready for first argument from file
2372 while((c = fgetc(f)) != EOF) { // each line of file inserts 1 argument in the list
2374 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2375 newArgs[k++] = 0; // terminate current arg
2376 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2377 argvCopy[j++] = newArgs + k; // get ready for next
2379 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2392 if(appData.debugMode,1) { // OK, appData is not initialized here yet...
2393 for(i=0; i<argc; i++) fprintf(stderr, "argv[%2d] = '%s'\n", i, argv[i]);
2398 setbuf(stdout, NULL);
2399 setbuf(stderr, NULL);
2402 programName = strrchr(argv[0], '/');
2403 if (programName == NULL)
2404 programName = argv[0];
2409 XtSetLanguageProc(NULL, NULL, NULL);
2410 bindtextdomain(PACKAGE, LOCALEDIR);
2411 textdomain(PACKAGE);
2415 XtAppInitialize(&appContext, "XBoard", shellOptions,
2416 XtNumber(shellOptions),
2417 &argc, argv, xboardResources, NULL, 0);
2419 fprintf(stderr, _("%s: unrecognized argument %s\n"),
2420 programName, argv[1]);
2421 fprintf(stderr, "Recognized options:\n");
2422 for(i = 0; i < XtNumber(shellOptions); i++) {
2423 j = fprintf(stderr, " %s%s", shellOptions[i].option,
2424 (shellOptions[i].argKind == XrmoptionSepArg
2426 if (i++ < XtNumber(shellOptions)) {
2427 fprintf(stderr, "%*c%s%s\n", 40 - j, ' ',
2428 shellOptions[i].option,
2429 (shellOptions[i].argKind == XrmoptionSepArg
2432 fprintf(stderr, "\n");
2439 if (p == NULL) p = "/tmp";
2440 i = strlen(p) + strlen("/.xboardXXXXXx.pgn") + 1;
2441 gameCopyFilename = (char*) malloc(i);
2442 gamePasteFilename = (char*) malloc(i);
2443 snprintf(gameCopyFilename,i, "%s/.xboard%05uc.pgn", p, getpid());
2444 snprintf(gamePasteFilename,i, "%s/.xboard%05up.pgn", p, getpid());
2446 XtGetApplicationResources(shellWidget, (XtPointer) &appData,
2447 clientResources, XtNumber(clientResources),
2450 { // [HGM] initstring: kludge to fix bad bug. expand '\n' characters in init string and computer string.
2451 static char buf[MSG_SIZ];
2452 EscapeExpand(buf, appData.initString);
2453 appData.initString = strdup(buf);
2454 EscapeExpand(buf, appData.secondInitString);
2455 appData.secondInitString = strdup(buf);
2456 EscapeExpand(buf, appData.firstComputerString);
2457 appData.firstComputerString = strdup(buf);
2458 EscapeExpand(buf, appData.secondComputerString);
2459 appData.secondComputerString = strdup(buf);
2462 if ((chessDir = (char *) getenv("CHESSDIR")) == NULL) {
2465 if (chdir(chessDir) != 0) {
2466 fprintf(stderr, _("%s: can't cd to CHESSDIR: "), programName);
2472 if (appData.debugMode && appData.nameOfDebugFile && strcmp(appData.nameOfDebugFile, "stderr")) {
2473 /* [DM] debug info to file [HGM] make the filename a command-line option, and allow it to remain stderr */
2474 if ((debugFP = fopen(appData.nameOfDebugFile, "w")) == NULL) {
2475 printf(_("Failed to open file '%s'\n"), appData.nameOfDebugFile);
2478 setbuf(debugFP, NULL);
2481 /* [HGM,HR] make sure board size is acceptable */
2482 if(appData.NrFiles > BOARD_SIZE ||
2483 appData.NrRanks > BOARD_SIZE )
2484 DisplayFatalError(_("Recompile with BOARD_SIZE > 12, to support this size"), 0, 2);
2487 /* This feature does not work; animation needs a rewrite */
2488 appData.highlightDragging = FALSE;
2492 xDisplay = XtDisplay(shellWidget);
2493 xScreen = DefaultScreen(xDisplay);
2494 wm_delete_window = XInternAtom(xDisplay, "WM_DELETE_WINDOW", True);
2496 gameInfo.variant = StringToVariant(appData.variant);
2497 InitPosition(FALSE);
2500 * Determine boardSize
2502 gameInfo.boardWidth = gameInfo.boardHeight = 8; // [HGM] boardsize: make sure we start as 8x8
2505 // [HGM] as long as we have not created the possibility to change size while running, start with requested size
2506 gameInfo.boardWidth = appData.NrFiles > 0 ? appData.NrFiles : 8;
2507 gameInfo.boardHeight = appData.NrRanks > 0 ? appData.NrRanks : 8;
2508 gameInfo.holdingsWidth = appData.holdingsSize > 0 ? 2 : 0;
2513 InitDrawingSizes(-1, 0); // [HGM] initsize: make this into a subroutine
2515 if (isdigit(appData.boardSize[0])) {
2516 i = sscanf(appData.boardSize, "%d,%d,%d,%d,%d,%d,%d", &squareSize,
2517 &lineGap, &clockFontPxlSize, &coordFontPxlSize,
2518 &fontPxlSize, &smallLayout, &tinyLayout);
2520 fprintf(stderr, _("%s: bad boardSize syntax %s\n"),
2521 programName, appData.boardSize);
2525 /* Find some defaults; use the nearest known size */
2526 SizeDefaults *szd, *nearest;
2527 int distance = 99999;
2528 nearest = szd = sizeDefaults;
2529 while (szd->name != NULL) {
2530 if (abs(szd->squareSize - squareSize) < distance) {
2532 distance = abs(szd->squareSize - squareSize);
2533 if (distance == 0) break;
2537 if (i < 2) lineGap = nearest->lineGap;
2538 if (i < 3) clockFontPxlSize = nearest->clockFontPxlSize;
2539 if (i < 4) coordFontPxlSize = nearest->coordFontPxlSize;
2540 if (i < 5) fontPxlSize = nearest->fontPxlSize;
2541 if (i < 6) smallLayout = nearest->smallLayout;
2542 if (i < 7) tinyLayout = nearest->tinyLayout;
2545 SizeDefaults *szd = sizeDefaults;
2546 if (*appData.boardSize == NULLCHAR) {
2547 while (DisplayWidth(xDisplay, xScreen) < szd->minScreenSize ||
2548 DisplayHeight(xDisplay, xScreen) < szd->minScreenSize) {
2551 if (szd->name == NULL) szd--;
2553 while (szd->name != NULL &&
2554 StrCaseCmp(szd->name, appData.boardSize) != 0) szd++;
2555 if (szd->name == NULL) {
2556 fprintf(stderr, _("%s: unrecognized boardSize name %s\n"),
2557 programName, appData.boardSize);
2561 squareSize = szd->squareSize;
2562 lineGap = szd->lineGap;
2563 clockFontPxlSize = szd->clockFontPxlSize;
2564 coordFontPxlSize = szd->coordFontPxlSize;
2565 fontPxlSize = szd->fontPxlSize;
2566 smallLayout = szd->smallLayout;
2567 tinyLayout = szd->tinyLayout;
2570 /* Now, using squareSize as a hint, find a good XPM/XIM set size */
2571 if (strlen(appData.pixmapDirectory) > 0) {
2572 p = ExpandPathName(appData.pixmapDirectory);
2574 fprintf(stderr, _("Error expanding path name \"%s\"\n"),
2575 appData.pixmapDirectory);
2578 if (appData.debugMode) {
2579 fprintf(stderr, _("\
2580 XBoard square size (hint): %d\n\
2581 %s fulldir:%s:\n"), squareSize, IMAGE_EXT, p);
2583 squareSize = xpm_closest_to(p, squareSize, IMAGE_EXT);
2584 if (appData.debugMode) {
2585 fprintf(stderr, _("Closest %s size: %d\n"), IMAGE_EXT, squareSize);
2589 /* [HR] height treated separately (hacked) */
2590 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2591 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2592 if (appData.showJail == 1) {
2593 /* Jail on top and bottom */
2594 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2595 XtSetArg(boardArgs[2], XtNheight,
2596 boardHeight + 2*(lineGap + squareSize));
2597 } else if (appData.showJail == 2) {
2599 XtSetArg(boardArgs[1], XtNwidth,
2600 boardWidth + 2*(lineGap + squareSize));
2601 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2604 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2605 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2609 * Determine what fonts to use.
2611 appData.clockFont = FindFont(appData.clockFont, clockFontPxlSize);
2612 clockFontID = XLoadFont(xDisplay, appData.clockFont);
2613 clockFontStruct = XQueryFont(xDisplay, clockFontID);
2614 appData.coordFont = FindFont(appData.coordFont, coordFontPxlSize);
2615 coordFontID = XLoadFont(xDisplay, appData.coordFont);
2616 coordFontStruct = XQueryFont(xDisplay, coordFontID);
2617 appData.font = FindFont(appData.font, fontPxlSize);
2618 countFontID = XLoadFont(xDisplay, appData.coordFont); // [HGM] holdings
2619 countFontStruct = XQueryFont(xDisplay, countFontID);
2620 // appData.font = FindFont(appData.font, fontPxlSize);
2622 xdb = XtDatabase(xDisplay);
2623 XrmPutStringResource(&xdb, "*font", appData.font);
2626 * Detect if there are not enough colors available and adapt.
2628 if (DefaultDepth(xDisplay, xScreen) <= 2) {
2629 appData.monoMode = True;
2632 if (!appData.monoMode) {
2633 vFrom.addr = (caddr_t) appData.lightSquareColor;
2634 vFrom.size = strlen(appData.lightSquareColor);
2635 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2636 if (vTo.addr == NULL) {
2637 appData.monoMode = True;
2640 lightSquareColor = *(Pixel *) vTo.addr;
2643 if (!appData.monoMode) {
2644 vFrom.addr = (caddr_t) appData.darkSquareColor;
2645 vFrom.size = strlen(appData.darkSquareColor);
2646 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2647 if (vTo.addr == NULL) {
2648 appData.monoMode = True;
2651 darkSquareColor = *(Pixel *) vTo.addr;
2654 if (!appData.monoMode) {
2655 vFrom.addr = (caddr_t) appData.whitePieceColor;
2656 vFrom.size = strlen(appData.whitePieceColor);
2657 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2658 if (vTo.addr == NULL) {
2659 appData.monoMode = True;
2662 whitePieceColor = *(Pixel *) vTo.addr;
2665 if (!appData.monoMode) {
2666 vFrom.addr = (caddr_t) appData.blackPieceColor;
2667 vFrom.size = strlen(appData.blackPieceColor);
2668 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2669 if (vTo.addr == NULL) {
2670 appData.monoMode = True;
2673 blackPieceColor = *(Pixel *) vTo.addr;
2677 if (!appData.monoMode) {
2678 vFrom.addr = (caddr_t) appData.highlightSquareColor;
2679 vFrom.size = strlen(appData.highlightSquareColor);
2680 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2681 if (vTo.addr == NULL) {
2682 appData.monoMode = True;
2685 highlightSquareColor = *(Pixel *) vTo.addr;
2689 if (!appData.monoMode) {
2690 vFrom.addr = (caddr_t) appData.premoveHighlightColor;
2691 vFrom.size = strlen(appData.premoveHighlightColor);
2692 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2693 if (vTo.addr == NULL) {
2694 appData.monoMode = True;
2697 premoveHighlightColor = *(Pixel *) vTo.addr;
2702 fprintf(stderr, _("%s: too few colors available; trying monochrome mode\n"),
2705 if (appData.bitmapDirectory == NULL ||
2706 appData.bitmapDirectory[0] == NULLCHAR)
2707 appData.bitmapDirectory = DEF_BITMAP_DIR;
2710 if (appData.lowTimeWarning && !appData.monoMode) {
2711 vFrom.addr = (caddr_t) appData.lowTimeWarningColor;
2712 vFrom.size = strlen(appData.lowTimeWarningColor);
2713 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2714 if (vTo.addr == NULL)
2715 appData.monoMode = True;
2717 lowTimeWarningColor = *(Pixel *) vTo.addr;
2720 if (appData.monoMode && appData.debugMode) {
2721 fprintf(stderr, _("white pixel = 0x%lx, black pixel = 0x%lx\n"),
2722 (unsigned long) XWhitePixel(xDisplay, xScreen),
2723 (unsigned long) XBlackPixel(xDisplay, xScreen));
2726 if (parse_cpair(ColorShout, appData.colorShout) < 0 ||
2727 parse_cpair(ColorSShout, appData.colorSShout) < 0 ||
2728 parse_cpair(ColorChannel1, appData.colorChannel1) < 0 ||
2729 parse_cpair(ColorChannel, appData.colorChannel) < 0 ||
2730 parse_cpair(ColorKibitz, appData.colorKibitz) < 0 ||
2731 parse_cpair(ColorTell, appData.colorTell) < 0 ||
2732 parse_cpair(ColorChallenge, appData.colorChallenge) < 0 ||
2733 parse_cpair(ColorRequest, appData.colorRequest) < 0 ||
2734 parse_cpair(ColorSeek, appData.colorSeek) < 0 ||
2735 parse_cpair(ColorNormal, appData.colorNormal) < 0)
2737 if (appData.colorize) {
2739 _("%s: can't parse color names; disabling colorization\n"),
2742 appData.colorize = FALSE;
2744 textColors[ColorNone].fg = textColors[ColorNone].bg = -1;
2745 textColors[ColorNone].attr = 0;
2747 XtAppAddActions(appContext, boardActions, XtNumber(boardActions));
2753 layoutName = "tinyLayout";
2754 } else if (smallLayout) {
2755 layoutName = "smallLayout";
2757 layoutName = "normalLayout";
2759 /* Outer layoutWidget is there only to provide a name for use in
2760 resources that depend on the layout style */
2762 XtCreateManagedWidget(layoutName, formWidgetClass, shellWidget,
2763 layoutArgs, XtNumber(layoutArgs));
2765 XtCreateManagedWidget("form", formWidgetClass, layoutWidget,
2766 formArgs, XtNumber(formArgs));
2767 XtSetArg(args[0], XtNdefaultDistance, &sep);
2768 XtGetValues(formWidget, args, 1);
2771 widgetList[j++] = menuBarWidget = CreateMenuBar(menuBar);
2772 XtSetArg(args[0], XtNtop, XtChainTop);
2773 XtSetArg(args[1], XtNbottom, XtChainTop);
2774 XtSetValues(menuBarWidget, args, 2);
2776 widgetList[j++] = whiteTimerWidget =
2777 XtCreateWidget("whiteTime", labelWidgetClass,
2778 formWidget, timerArgs, XtNumber(timerArgs));
2779 XtSetArg(args[0], XtNfont, clockFontStruct);
2780 XtSetArg(args[1], XtNtop, XtChainTop);
2781 XtSetArg(args[2], XtNbottom, XtChainTop);
2782 XtSetValues(whiteTimerWidget, args, 3);
2784 widgetList[j++] = blackTimerWidget =
2785 XtCreateWidget("blackTime", labelWidgetClass,
2786 formWidget, timerArgs, XtNumber(timerArgs));
2787 XtSetArg(args[0], XtNfont, clockFontStruct);
2788 XtSetArg(args[1], XtNtop, XtChainTop);
2789 XtSetArg(args[2], XtNbottom, XtChainTop);
2790 XtSetValues(blackTimerWidget, args, 3);
2792 if (appData.titleInWindow) {
2793 widgetList[j++] = titleWidget =
2794 XtCreateWidget("title", labelWidgetClass, formWidget,
2795 titleArgs, XtNumber(titleArgs));
2796 XtSetArg(args[0], XtNtop, XtChainTop);
2797 XtSetArg(args[1], XtNbottom, XtChainTop);
2798 XtSetValues(titleWidget, args, 2);
2801 if (appData.showButtonBar) {
2802 widgetList[j++] = buttonBarWidget = CreateButtonBar(buttonBar);
2803 XtSetArg(args[0], XtNleft, XtChainRight); // [HGM] glue to right window edge
2804 XtSetArg(args[1], XtNright, XtChainRight); // for good run-time sizing
2805 XtSetArg(args[2], XtNtop, XtChainTop);
2806 XtSetArg(args[3], XtNbottom, XtChainTop);
2807 XtSetValues(buttonBarWidget, args, 4);
2810 widgetList[j++] = messageWidget =
2811 XtCreateWidget("message", labelWidgetClass, formWidget,
2812 messageArgs, XtNumber(messageArgs));
2813 XtSetArg(args[0], XtNtop, XtChainTop);
2814 XtSetArg(args[1], XtNbottom, XtChainTop);
2815 XtSetValues(messageWidget, args, 2);
2817 widgetList[j++] = boardWidget =
2818 XtCreateWidget("board", widgetClass, formWidget, boardArgs,
2819 XtNumber(boardArgs));
2821 XtManageChildren(widgetList, j);
2823 timerWidth = (boardWidth - sep) / 2;
2824 XtSetArg(args[0], XtNwidth, timerWidth);
2825 XtSetValues(whiteTimerWidget, args, 1);
2826 XtSetValues(blackTimerWidget, args, 1);
2828 XtSetArg(args[0], XtNbackground, &timerBackgroundPixel);
2829 XtSetArg(args[1], XtNforeground, &timerForegroundPixel);
2830 XtGetValues(whiteTimerWidget, args, 2);
2832 if (appData.showButtonBar) {
2833 XtSetArg(args[0], XtNbackground, &buttonBackgroundPixel);
2834 XtSetArg(args[1], XtNforeground, &buttonForegroundPixel);
2835 XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
2839 * formWidget uses these constraints but they are stored
2843 XtSetArg(args[i], XtNfromHoriz, 0); i++;
2844 XtSetValues(menuBarWidget, args, i);
2845 if (appData.titleInWindow) {
2848 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2849 XtSetValues(whiteTimerWidget, args, i);
2851 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2852 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2853 XtSetValues(blackTimerWidget, args, i);
2855 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2856 XtSetArg(args[i], XtNjustify, XtJustifyLeft); i++;
2857 XtSetValues(titleWidget, args, i);
2859 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2860 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2861 XtSetValues(messageWidget, args, i);
2862 if (appData.showButtonBar) {
2864 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2865 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2866 XtSetValues(buttonBarWidget, args, i);
2870 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2871 XtSetValues(whiteTimerWidget, args, i);
2873 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2874 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2875 XtSetValues(blackTimerWidget, args, i);
2877 XtSetArg(args[i], XtNfromHoriz, menuBarWidget); i++;
2878 XtSetValues(titleWidget, args, i);
2880 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2881 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2882 XtSetValues(messageWidget, args, i);
2883 if (appData.showButtonBar) {
2885 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2886 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2887 XtSetValues(buttonBarWidget, args, i);
2892 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2893 XtSetValues(whiteTimerWidget, args, i);
2895 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2896 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2897 XtSetValues(blackTimerWidget, args, i);
2899 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2900 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2901 XtSetValues(messageWidget, args, i);
2902 if (appData.showButtonBar) {
2904 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2905 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2906 XtSetValues(buttonBarWidget, args, i);
2910 XtSetArg(args[0], XtNfromVert, messageWidget);
2911 XtSetArg(args[1], XtNtop, XtChainTop);
2912 XtSetArg(args[2], XtNbottom, XtChainBottom);
2913 XtSetArg(args[3], XtNleft, XtChainLeft);
2914 XtSetArg(args[4], XtNright, XtChainRight);
2915 XtSetValues(boardWidget, args, 5);
2917 XtRealizeWidget(shellWidget);
2920 * Correct the width of the message and title widgets.
2921 * It is not known why some systems need the extra fudge term.
2922 * The value "2" is probably larger than needed.
2924 XawFormDoLayout(formWidget, False);
2926 #define WIDTH_FUDGE 2
2928 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2929 XtSetArg(args[i], XtNheight, &h); i++;
2930 XtGetValues(messageWidget, args, i);
2931 if (appData.showButtonBar) {
2933 XtSetArg(args[i], XtNwidth, &w); i++;
2934 XtGetValues(buttonBarWidget, args, i);
2935 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2937 w = boardWidth - 2*bor + 1; /*!! +1 compensates for kludge below */
2940 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2941 if (gres != XtGeometryYes && appData.debugMode) {
2942 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2943 programName, gres, w, h, wr, hr);
2946 /* !! Horrible hack to work around bug in XFree86 4.0.1 (X11R6.4.3) */
2947 /* The size used for the child widget in layout lags one resize behind
2948 its true size, so we resize a second time, 1 pixel smaller. Yeech! */
2950 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2951 if (gres != XtGeometryYes && appData.debugMode) {
2952 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2953 programName, gres, w, h, wr, hr);
2956 XtSetArg(args[0], XtNleft, XtChainLeft); // [HGM] glue ends for good run-time sizing
2957 XtSetArg(args[1], XtNright, XtChainRight);
2958 XtSetValues(messageWidget, args, 2);
2960 if (appData.titleInWindow) {
2962 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2963 XtSetArg(args[i], XtNheight, &h); i++;
2964 XtGetValues(titleWidget, args, i);
2966 w = boardWidth - 2*bor;
2968 XtSetArg(args[0], XtNwidth, &w);
2969 XtGetValues(menuBarWidget, args, 1);
2970 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2973 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
2974 if (gres != XtGeometryYes && appData.debugMode) {
2976 _("%s: titleWidget geometry error %d %d %d %d %d\n"),
2977 programName, gres, w, h, wr, hr);
2980 XawFormDoLayout(formWidget, True);
2982 xBoardWindow = XtWindow(boardWidget);
2984 // [HGM] it seems the layout code ends here, but perhaps the color stuff is size independent and would
2985 // not need to go into InitDrawingSizes().
2989 * Create X checkmark bitmap and initialize option menu checks.
2991 ReadBitmap(&xMarkPixmap, "checkmark.bm",
2992 checkmark_bits, checkmark_width, checkmark_height);
2993 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
2994 if (appData.alwaysPromoteToQueen) {
2995 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
2998 if (appData.animateDragging) {
2999 XtSetValues(XtNameToWidget(menuBarWidget,
3000 "menuOptions.Animate Dragging"),
3003 if (appData.animate) {
3004 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
3007 if (appData.autoComment) {
3008 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
3011 if (appData.autoCallFlag) {
3012 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
3015 if (appData.autoFlipView) {
3016 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Auto Flip View"),
3019 if (appData.autoObserve) {
3020 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
3023 if (appData.autoRaiseBoard) {
3024 XtSetValues(XtNameToWidget(menuBarWidget,
3025 "menuOptions.Auto Raise Board"), args, 1);
3027 if (appData.autoSaveGames) {
3028 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
3031 if (appData.saveGameFile[0] != NULLCHAR) {
3032 /* Can't turn this off from menu */
3033 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
3035 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
3039 if (appData.blindfold) {
3040 XtSetValues(XtNameToWidget(menuBarWidget,
3041 "menuOptions.Blindfold"), args, 1);
3043 if (appData.flashCount > 0) {
3044 XtSetValues(XtNameToWidget(menuBarWidget,
3045 "menuOptions.Flash Moves"),
3048 if (appData.getMoveList) {
3049 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
3053 if (appData.highlightDragging) {
3054 XtSetValues(XtNameToWidget(menuBarWidget,
3055 "menuOptions.Highlight Dragging"),
3059 if (appData.highlightLastMove) {
3060 XtSetValues(XtNameToWidget(menuBarWidget,
3061 "menuOptions.Highlight Last Move"),
3064 if (appData.icsAlarm) {
3065 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.ICS Alarm"),
3068 if (appData.ringBellAfterMoves) {
3069 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
3072 if (appData.oldSaveStyle) {
3073 XtSetValues(XtNameToWidget(menuBarWidget,
3074 "menuOptions.Old Save Style"), args, 1);
3076 if (appData.periodicUpdates) {
3077 XtSetValues(XtNameToWidget(menuBarWidget,
3078 "menuOptions.Periodic Updates"), args, 1);
3080 if (appData.ponderNextMove) {
3081 XtSetValues(XtNameToWidget(menuBarWidget,
3082 "menuOptions.Ponder Next Move"), args, 1);
3084 if (appData.popupExitMessage) {
3085 XtSetValues(XtNameToWidget(menuBarWidget,
3086 "menuOptions.Popup Exit Message"), args, 1);
3088 if (appData.popupMoveErrors) {
3089 XtSetValues(XtNameToWidget(menuBarWidget,
3090 "menuOptions.Popup Move Errors"), args, 1);
3092 if (appData.premove) {
3093 XtSetValues(XtNameToWidget(menuBarWidget,
3094 "menuOptions.Premove"), args, 1);
3096 if (appData.quietPlay) {
3097 XtSetValues(XtNameToWidget(menuBarWidget,
3098 "menuOptions.Quiet Play"), args, 1);
3100 if (appData.showCoords) {
3101 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
3104 if (appData.hideThinkingFromHuman) {
3105 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
3108 if (appData.testLegality) {
3109 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Test Legality"),
3116 ReadBitmap(&wIconPixmap, "icon_white.bm",
3117 icon_white_bits, icon_white_width, icon_white_height);
3118 ReadBitmap(&bIconPixmap, "icon_black.bm",
3119 icon_black_bits, icon_black_width, icon_black_height);
3120 iconPixmap = wIconPixmap;
3122 XtSetArg(args[i], XtNiconPixmap, iconPixmap); i++;
3123 XtSetValues(shellWidget, args, i);
3126 * Create a cursor for the board widget.
3128 window_attributes.cursor = XCreateFontCursor(xDisplay, XC_hand2);
3129 XChangeWindowAttributes(xDisplay, xBoardWindow,
3130 CWCursor, &window_attributes);
3133 * Inhibit shell resizing.
3135 shellArgs[0].value = (XtArgVal) &w;
3136 shellArgs[1].value = (XtArgVal) &h;
3137 XtGetValues(shellWidget, shellArgs, 2);
3138 shellArgs[4].value = shellArgs[2].value = w;
3139 shellArgs[5].value = shellArgs[3].value = h;
3140 XtSetValues(shellWidget, &shellArgs[2], 4);
3141 marginW = w - boardWidth; // [HGM] needed to set new shellWidget size when we resize board
3142 marginH = h - boardHeight;
3144 CatchDeleteWindow(shellWidget, "QuitProc");
3149 if (appData.bitmapDirectory[0] != NULLCHAR) {
3156 /* Create regular pieces */
3157 if (!useImages) CreatePieces();
3162 if (appData.animate || appData.animateDragging)
3165 XtAugmentTranslations(formWidget,
3166 XtParseTranslationTable(globalTranslations));
3167 XtAugmentTranslations(boardWidget,
3168 XtParseTranslationTable(boardTranslations));
3169 XtAugmentTranslations(whiteTimerWidget,
3170 XtParseTranslationTable(whiteTranslations));
3171 XtAugmentTranslations(blackTimerWidget,
3172 XtParseTranslationTable(blackTranslations));
3174 /* Why is the following needed on some versions of X instead
3175 * of a translation? */
3176 XtAddEventHandler(boardWidget, ExposureMask, False,
3177 (XtEventHandler) EventProc, NULL);
3182 if (errorExitStatus == -1) {
3183 if (appData.icsActive) {
3184 /* We now wait until we see "login:" from the ICS before
3185 sending the logon script (problems with timestamp otherwise) */
3186 /*ICSInitScript();*/
3187 if (appData.icsInputBox) ICSInputBoxPopUp();
3190 signal(SIGINT, IntSigHandler);
3191 signal(SIGTERM, IntSigHandler);
3192 if (*appData.cmailGameName != NULLCHAR) {
3193 signal(SIGUSR1, CmailSigHandler);
3196 gameInfo.boardWidth = 0; // [HGM] pieces: kludge to ensure InitPosition() calls InitDrawingSizes()
3199 XtAppMainLoop(appContext);
3200 if (appData.debugMode) fclose(debugFP); // [DM] debug
3207 if (appData.icsActive && oldICSInteractionTitle != NULL) {
3208 DisplayIcsInteractionTitle(oldICSInteractionTitle);
3210 unlink(gameCopyFilename);
3211 unlink(gamePasteFilename);
3222 CmailSigHandler(sig)
3228 signal(SIGUSR1, SIG_IGN); /* suspend handler */
3230 /* Activate call-back function CmailSigHandlerCallBack() */
3231 OutputToProcess(cmailPR, (char *)(&dummy), sizeof(int), &error);
3233 signal(SIGUSR1, CmailSigHandler); /* re-activate handler */
3237 CmailSigHandlerCallBack(isr, closure, message, count, error)
3245 ReloadCmailMsgEvent(TRUE); /* Reload cmail msg */
3247 /**** end signal code ****/
3257 f = fopen(appData.icsLogon, "r");
3263 strcat(buf, appData.icsLogon);
3264 f = fopen(buf, "r");
3268 ProcessICSInitScript(f);
3275 EditCommentPopDown();
3286 SetMenuEnables(enab)
3290 if (!menuBarWidget) return;
3291 while (enab->name != NULL) {
3292 w = XtNameToWidget(menuBarWidget, enab->name);
3294 DisplayError(enab->name, 0);
3296 XtSetSensitive(w, enab->value);
3302 Enables icsEnables[] = {
3303 { "menuFile.Mail Move", False },
3304 { "menuFile.Reload CMail Message", False },
3305 { "menuMode.Machine Black", False },
3306 { "menuMode.Machine White", False },
3307 { "menuMode.Analysis Mode", False },
3308 { "menuMode.Analyze File", False },
3309 { "menuMode.Two Machines", False },
3311 { "menuHelp.Hint", False },
3312 { "menuHelp.Book", False },
3313 { "menuStep.Move Now", False },
3314 { "menuOptions.Periodic Updates", False },
3315 { "menuOptions.Hide Thinking", False },
3316 { "menuOptions.Ponder Next Move", False },
3321 Enables ncpEnables[] = {
3322 { "menuFile.Mail Move", False },
3323 { "menuFile.Reload CMail Message", False },
3324 { "menuMode.Machine White", False },
3325 { "menuMode.Machine Black", False },
3326 { "menuMode.Analysis Mode", False },
3327 { "menuMode.Analyze File", False },
3328 { "menuMode.Two Machines", False },
3329 { "menuMode.ICS Client", False },
3330 { "menuMode.ICS Input Box", False },
3331 { "Action", False },
3332 { "menuStep.Revert", False },
3333 { "menuStep.Move Now", False },
3334 { "menuStep.Retract Move", False },
3335 { "menuOptions.Auto Comment", False },
3336 { "menuOptions.Auto Flag", False },
3337 { "menuOptions.Auto Flip View", False },
3338 { "menuOptions.Auto Observe", False },
3339 { "menuOptions.Auto Raise Board", False },
3340 { "menuOptions.Get Move List", False },
3341 { "menuOptions.ICS Alarm", False },
3342 { "menuOptions.Move Sound", False },
3343 { "menuOptions.Quiet Play", False },
3344 { "menuOptions.Hide Thinking", False },
3345 { "menuOptions.Periodic Updates", False },
3346 { "menuOptions.Ponder Next Move", False },
3347 { "menuHelp.Hint", False },
3348 { "menuHelp.Book", False },
3352 Enables gnuEnables[] = {
3353 { "menuMode.ICS Client", False },
3354 { "menuMode.ICS Input Box", False },
3355 { "menuAction.Accept", False },
3356 { "menuAction.Decline", False },
3357 { "menuAction.Rematch", False },
3358 { "menuAction.Adjourn", False },
3359 { "menuAction.Stop Examining", False },
3360 { "menuAction.Stop Observing", False },
3361 { "menuStep.Revert", False },
3362 { "menuOptions.Auto Comment", False },
3363 { "menuOptions.Auto Observe", False },
3364 { "menuOptions.Auto Raise Board", False },
3365 { "menuOptions.Get Move List", False },
3366 { "menuOptions.Premove", False },
3367 { "menuOptions.Quiet Play", False },
3369 /* The next two options rely on SetCmailMode being called *after* */
3370 /* SetGNUMode so that when GNU is being used to give hints these */
3371 /* menu options are still available */
3373 { "menuFile.Mail Move", False },
3374 { "menuFile.Reload CMail Message", False },
3378 Enables cmailEnables[] = {
3380 { "menuAction.Call Flag", False },
3381 { "menuAction.Draw", True },
3382 { "menuAction.Adjourn", False },
3383 { "menuAction.Abort", False },
3384 { "menuAction.Stop Observing", False },
3385 { "menuAction.Stop Examining", False },
3386 { "menuFile.Mail Move", True },
3387 { "menuFile.Reload CMail Message", True },
3391 Enables trainingOnEnables[] = {
3392 { "menuMode.Edit Comment", False },
3393 { "menuMode.Pause", False },
3394 { "menuStep.Forward", False },
3395 { "menuStep.Backward", False },
3396 { "menuStep.Forward to End", False },
3397 { "menuStep.Back to Start", False },
3398 { "menuStep.Move Now", False },
3399 { "menuStep.Truncate Game", False },
3403 Enables trainingOffEnables[] = {
3404 { "menuMode.Edit Comment", True },
3405 { "menuMode.Pause", True },
3406 { "menuStep.Forward", True },
3407 { "menuStep.Backward", True },
3408 { "menuStep.Forward to End", True },
3409 { "menuStep.Back to Start", True },
3410 { "menuStep.Move Now", True },
3411 { "menuStep.Truncate Game", True },
3415 Enables machineThinkingEnables[] = {
3416 { "menuFile.Load Game", False },
3417 { "menuFile.Load Next Game", False },
3418 { "menuFile.Load Previous Game", False },
3419 { "menuFile.Reload Same Game", False },
3420 { "menuFile.Paste Game", False },
3421 { "menuFile.Load Position", False },
3422 { "menuFile.Load Next Position", False },
3423 { "menuFile.Load Previous Position", False },
3424 { "menuFile.Reload Same Position", False },
3425 { "menuFile.Paste Position", False },
3426 { "menuMode.Machine White", False },
3427 { "menuMode.Machine Black", False },
3428 { "menuMode.Two Machines", False },
3429 { "menuStep.Retract Move", False },
3433 Enables userThinkingEnables[] = {
3434 { "menuFile.Load Game", True },
3435 { "menuFile.Load Next Game", True },
3436 { "menuFile.Load Previous Game", True },
3437 { "menuFile.Reload Same Game", True },
3438 { "menuFile.Paste Game", True },
3439 { "menuFile.Load Position", True },
3440 { "menuFile.Load Next Position", True },
3441 { "menuFile.Load Previous Position", True },
3442 { "menuFile.Reload Same Position", True },
3443 { "menuFile.Paste Position", True },
3444 { "menuMode.Machine White", True },
3445 { "menuMode.Machine Black", True },
3446 { "menuMode.Two Machines", True },
3447 { "menuStep.Retract Move", True },
3453 SetMenuEnables(icsEnables);
3456 if (appData.zippyPlay && !appData.noChessProgram) /* [DM] icsEngineAnalyze */
3457 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Analysis Mode"), True);
3464 SetMenuEnables(ncpEnables);
3470 SetMenuEnables(gnuEnables);
3476 SetMenuEnables(cmailEnables);
3482 SetMenuEnables(trainingOnEnables);
3483 if (appData.showButtonBar) {
3484 XtSetSensitive(buttonBarWidget, False);
3490 SetTrainingModeOff()
3492 SetMenuEnables(trainingOffEnables);
3493 if (appData.showButtonBar) {
3494 XtSetSensitive(buttonBarWidget, True);
3499 SetUserThinkingEnables()
3501 if (appData.noChessProgram) return;
3502 SetMenuEnables(userThinkingEnables);
3506 SetMachineThinkingEnables()
3508 if (appData.noChessProgram) return;
3509 SetMenuEnables(machineThinkingEnables);
3511 case MachinePlaysBlack:
3512 case MachinePlaysWhite:
3513 case TwoMachinesPlay:
3514 XtSetSensitive(XtNameToWidget(menuBarWidget,
3515 ModeToWidgetName(gameMode)), True);
3522 #define Abs(n) ((n)<0 ? -(n) : (n))
3525 * Find a font that matches "pattern" that is as close as
3526 * possible to the targetPxlSize. Prefer fonts that are k
3527 * pixels smaller to fonts that are k pixels larger. The
3528 * pattern must be in the X Consortium standard format,
3529 * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".
3530 * The return value should be freed with XtFree when no
3533 char *FindFont(pattern, targetPxlSize)
3537 char **fonts, *p, *best, *scalable, *scalableTail;
3538 int i, j, nfonts, minerr, err, pxlSize;
3541 char **missing_list;
3543 char *def_string, *base_fnt_lst, strInt[3];
3545 XFontStruct **fnt_list;
3547 base_fnt_lst = calloc(1, strlen(pattern) + 3);
3548 sprintf(strInt, "%d", targetPxlSize);
3549 p = strstr(pattern, "--");
3550 strncpy(base_fnt_lst, pattern, p - pattern + 2);
3551 strcat(base_fnt_lst, strInt);
3552 strcat(base_fnt_lst, strchr(p + 2, '-'));
3554 if ((fntSet = XCreateFontSet(xDisplay,
3558 &def_string)) == NULL) {
3560 fprintf(stderr, _("Unable to create font set.\n"));
3564 nfonts = XFontsOfFontSet(fntSet, &fnt_list, &fonts);
3566 fonts = XListFonts(xDisplay, pattern, 999999, &nfonts);
3568 fprintf(stderr, _("%s: no fonts match pattern %s\n"),
3569 programName, pattern);
3577 for (i=0; i<nfonts; i++) {
3580 if (*p != '-') continue;
3582 if (*p == NULLCHAR) break;
3583 if (*p++ == '-') j++;
3585 if (j < 7) continue;
3588 scalable = fonts[i];
3591 err = pxlSize - targetPxlSize;
3592 if (Abs(err) < Abs(minerr) ||
3593 (minerr > 0 && err < 0 && -err == minerr)) {
3599 if (scalable && Abs(minerr) > appData.fontSizeTolerance) {
3600 /* If the error is too big and there is a scalable font,
3601 use the scalable font. */
3602 int headlen = scalableTail - scalable;
3603 p = (char *) XtMalloc(strlen(scalable) + 10);
3604 while (isdigit(*scalableTail)) scalableTail++;
3605 sprintf(p, "%.*s%d%s", headlen, scalable, targetPxlSize, scalableTail);
3607 p = (char *) XtMalloc(strlen(best) + 1);
3610 if (appData.debugMode) {
3611 fprintf(debugFP, _("resolved %s at pixel size %d\n to %s\n"),
3612 pattern, targetPxlSize, p);
3615 if (missing_count > 0)
3616 XFreeStringList(missing_list);
3617 XFreeFontSet(xDisplay, fntSet);
3619 XFreeFontNames(fonts);
3626 XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
3627 | GCBackground | GCFunction | GCPlaneMask;
3628 XGCValues gc_values;
3631 gc_values.plane_mask = AllPlanes;
3632 gc_values.line_width = lineGap;
3633 gc_values.line_style = LineSolid;
3634 gc_values.function = GXcopy;
3636 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3637 gc_values.background = XBlackPixel(xDisplay, xScreen);
3638 lineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3640 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3641 gc_values.background = XWhitePixel(xDisplay, xScreen);
3642 coordGC = XtGetGC(shellWidget, value_mask, &gc_values);
3643 XSetFont(xDisplay, coordGC, coordFontID);
3645 // [HGM] make font for holdings counts (white on black0
3646 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3647 gc_values.background = XBlackPixel(xDisplay, xScreen);
3648 countGC = XtGetGC(shellWidget, value_mask, &gc_values);
3649 XSetFont(xDisplay, countGC, countFontID);
3651 if (appData.monoMode) {
3652 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3653 gc_values.background = XWhitePixel(xDisplay, xScreen);
3654 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3656 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3657 gc_values.background = XBlackPixel(xDisplay, xScreen);
3658 lightSquareGC = wbPieceGC
3659 = XtGetGC(shellWidget, value_mask, &gc_values);
3661 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3662 gc_values.background = XWhitePixel(xDisplay, xScreen);
3663 darkSquareGC = bwPieceGC
3664 = XtGetGC(shellWidget, value_mask, &gc_values);
3666 if (DefaultDepth(xDisplay, xScreen) == 1) {
3667 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
3668 gc_values.function = GXcopyInverted;
3669 copyInvertedGC = XtGetGC(shellWidget, value_mask, &gc_values);
3670 gc_values.function = GXcopy;
3671 if (XBlackPixel(xDisplay, xScreen) == 1) {
3672 bwPieceGC = darkSquareGC;
3673 wbPieceGC = copyInvertedGC;
3675 bwPieceGC = copyInvertedGC;
3676 wbPieceGC = lightSquareGC;
3680 gc_values.foreground = highlightSquareColor;
3681 gc_values.background = highlightSquareColor;
3682 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3684 gc_values.foreground = premoveHighlightColor;
3685 gc_values.background = premoveHighlightColor;
3686 prelineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3688 gc_values.foreground = lightSquareColor;
3689 gc_values.background = darkSquareColor;
3690 lightSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3692 gc_values.foreground = darkSquareColor;
3693 gc_values.background = lightSquareColor;
3694 darkSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3696 gc_values.foreground = jailSquareColor;
3697 gc_values.background = jailSquareColor;
3698 jailSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3700 gc_values.foreground = whitePieceColor;
3701 gc_values.background = darkSquareColor;
3702 wdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3704 gc_values.foreground = whitePieceColor;
3705 gc_values.background = lightSquareColor;
3706 wlPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3708 gc_values.foreground = whitePieceColor;
3709 gc_values.background = jailSquareColor;
3710 wjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3712 gc_values.foreground = blackPieceColor;
3713 gc_values.background = darkSquareColor;
3714 bdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3716 gc_values.foreground = blackPieceColor;
3717 gc_values.background = lightSquareColor;
3718 blPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3720 gc_values.foreground = blackPieceColor;
3721 gc_values.background = jailSquareColor;
3722 bjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3726 void loadXIM(xim, xmask, filename, dest, mask)
3739 fp = fopen(filename, "rb");
3741 fprintf(stderr, _("%s: error loading XIM!\n"), programName);
3748 for (y=0; y<h; ++y) {
3749 for (x=0; x<h; ++x) {
3754 XPutPixel(xim, x, y, blackPieceColor);
3756 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3759 XPutPixel(xim, x, y, darkSquareColor);
3761 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3764 XPutPixel(xim, x, y, whitePieceColor);
3766 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3769 XPutPixel(xim, x, y, lightSquareColor);
3771 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3777 /* create Pixmap of piece */
3778 *dest = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3780 XPutImage(xDisplay, *dest, lightSquareGC, xim,
3783 /* create Pixmap of clipmask
3784 Note: We assume the white/black pieces have the same
3785 outline, so we make only 6 masks. This is okay
3786 since the XPM clipmask routines do the same. */
3788 temp = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3790 XPutImage(xDisplay, temp, lightSquareGC, xmask,
3793 /* now create the 1-bit version */
3794 *mask = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3797 values.foreground = 1;
3798 values.background = 0;
3800 /* Don't use XtGetGC, not read only */
3801 maskGC = XCreateGC(xDisplay, *mask,
3802 GCForeground | GCBackground, &values);
3803 XCopyPlane(xDisplay, temp, *mask, maskGC,
3804 0, 0, squareSize, squareSize, 0, 0, 1);
3805 XFreePixmap(xDisplay, temp);
3810 char pieceBitmapNames[] = "pnbrqfeacwmohijgdvlsukpnsl";
3812 void CreateXIMPieces()
3817 static char *ximkind[] = { "ll", "ld", "dl", "dd" };
3822 /* The XSynchronize calls were copied from CreatePieces.
3823 Not sure if needed, but can't hurt */
3824 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3827 /* temp needed by loadXIM() */
3828 ximtemp = XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3829 0, 0, ss, ss, AllPlanes, XYPixmap);
3831 if (strlen(appData.pixmapDirectory) == 0) {
3835 if (appData.monoMode) {
3836 DisplayFatalError(_("XIM pieces cannot be used in monochrome mode"),
3840 fprintf(stderr, _("\nLoading XIMs...\n"));
3842 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3843 fprintf(stderr, "%d", piece+1);
3844 for (kind=0; kind<4; kind++) {
3845 fprintf(stderr, ".");
3846 snprintf(buf, sizeof(buf), "%s/%s%c%s%u.xim",
3847 ExpandPathName(appData.pixmapDirectory),
3848 piece <= (int) WhiteKing ? "" : "w",
3849 pieceBitmapNames[piece],
3851 ximPieceBitmap[kind][piece] =
3852 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3853 0, 0, ss, ss, AllPlanes, XYPixmap);
3854 if (appData.debugMode)
3855 fprintf(stderr, _("(File:%s:) "), buf);
3856 loadXIM(ximPieceBitmap[kind][piece],
3858 &(xpmPieceBitmap2[kind][piece]),
3859 &(ximMaskPm2[piece]));
3860 if(piece <= (int)WhiteKing)
3861 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3863 fprintf(stderr," ");
3865 /* Load light and dark squares */
3866 /* If the LSQ and DSQ pieces don't exist, we will
3867 draw them with solid squares. */
3868 snprintf(buf,sizeof(buf), "%s/lsq%u.xim", ExpandPathName(appData.pixmapDirectory), ss);
3869 if (access(buf, 0) != 0) {
3873 fprintf(stderr, _("light square "));
3875 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3876 0, 0, ss, ss, AllPlanes, XYPixmap);
3877 if (appData.debugMode)
3878 fprintf(stderr, _("(File:%s:) "), buf);
3880 loadXIM(ximLightSquare, NULL, buf, &xpmLightSquare, NULL);
3881 fprintf(stderr, _("dark square "));
3882 snprintf(buf,sizeof(buf), "%s/dsq%u.xim",
3883 ExpandPathName(appData.pixmapDirectory), ss);
3884 if (appData.debugMode)
3885 fprintf(stderr, _("(File:%s:) "), buf);
3887 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3888 0, 0, ss, ss, AllPlanes, XYPixmap);
3889 loadXIM(ximDarkSquare, NULL, buf, &xpmDarkSquare, NULL);
3890 xpmJailSquare = xpmLightSquare;
3892 fprintf(stderr, _("Done.\n"));
3894 XSynchronize(xDisplay, False); /* Work-around for xlib/xt buffering bug */
3898 void CreateXPMPieces()
3902 u_int ss = squareSize;
3904 static char *xpmkind[] = { "ll", "ld", "dl", "dd" };
3905 XpmColorSymbol symbols[4];
3908 /* Apparently some versions of Xpm don't define XpmFormat at all --tpm */
3909 if (appData.debugMode) {
3910 fprintf(stderr, "XPM Library Version: %d.%d%c\n",
3911 XpmFormat, XpmVersion, (char)('a' + XpmRevision - 1));
3915 /* The XSynchronize calls were copied from CreatePieces.
3916 Not sure if needed, but can't hurt */
3917 XSynchronize(xDisplay, True); /* Work-around for xlib/xt buffering bug */
3919 /* Setup translations so piece colors match square colors */
3920 symbols[0].name = "light_piece";
3921 symbols[0].value = appData.whitePieceColor;
3922 symbols[1].name = "dark_piece";
3923 symbols[1].value = appData.blackPieceColor;
3924 symbols[2].name = "light_square";
3925 symbols[2].value = appData.lightSquareColor;
3926 symbols[3].name = "dark_square";
3927 symbols[3].value = appData.darkSquareColor;
3929 attr.valuemask = XpmColorSymbols;
3930 attr.colorsymbols = symbols;
3931 attr.numsymbols = 4;
3933 if (appData.monoMode) {
3934 DisplayFatalError(_("XPM pieces cannot be used in monochrome mode"),
3938 if (strlen(appData.pixmapDirectory) == 0) {
3939 XpmPieces* pieces = builtInXpms;
3942 while (pieces->size != squareSize && pieces->size) pieces++;
3943 if (!pieces->size) {
3944 fprintf(stderr, _("No builtin XPM pieces of size %d\n"), squareSize);
3947 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3948 for (kind=0; kind<4; kind++) {
3950 if ((r=XpmCreatePixmapFromData(xDisplay, xBoardWindow,
3951 pieces->xpm[piece][kind],
3952 &(xpmPieceBitmap2[kind][piece]),
3953 NULL, &attr)) != 0) {
3954 fprintf(stderr, _("Error %d loading XPM image \"%s\"\n"),
3958 if(piece <= (int) WhiteKing)
3959 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3963 xpmJailSquare = xpmLightSquare;
3967 fprintf(stderr, _("\nLoading XPMs...\n"));
3970 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3971 fprintf(stderr, "%d ", piece+1);
3972 for (kind=0; kind<4; kind++) {
3973 snprintf(buf, sizeof(buf), "%s/%s%c%s%u.xpm",
3974 ExpandPathName(appData.pixmapDirectory),
3975 piece > (int) WhiteKing ? "w" : "",
3976 pieceBitmapNames[piece],
3978 if (appData.debugMode) {
3979 fprintf(stderr, _("(File:%s:) "), buf);
3981 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3982 &(xpmPieceBitmap2[kind][piece]),
3983 NULL, &attr)) != 0) {
3984 if(piece != (int)WhiteKing && piece > (int)WhiteQueen) {
3985 // [HGM] missing: read of unorthodox piece failed; substitute King.
3986 snprintf(buf, sizeof(buf), "%s/k%s%u.xpm",
3987 ExpandPathName(appData.pixmapDirectory),
3989 if (appData.debugMode) {
3990 fprintf(stderr, _("(Replace by File:%s:) "), buf);
3992 r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3993 &(xpmPieceBitmap2[kind][piece]),
3997 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"),
4002 if(piece <= (int) WhiteKing)
4003 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
4006 /* Load light and dark squares */
4007 /* If the LSQ and DSQ pieces don't exist, we will
4008 draw them with solid squares. */
4009 fprintf(stderr, _("light square "));
4010 snprintf(buf, sizeof(buf), "%s/lsq%u.xpm", ExpandPathName(appData.pixmapDirectory), ss);
4011 if (access(buf, 0) != 0) {
4015 if (appData.debugMode)
4016 fprintf(stderr, _("(File:%s:) "), buf);
4018 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
4019 &xpmLightSquare, NULL, &attr)) != 0) {
4020 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
4023 fprintf(stderr, _("dark square "));
4024 snprintf(buf, sizeof(buf), "%s/dsq%u.xpm",
4025 ExpandPathName(appData.pixmapDirectory), ss);
4026 if (appData.debugMode) {
4027 fprintf(stderr, _("(File:%s:) "), buf);
4029 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
4030 &xpmDarkSquare, NULL, &attr)) != 0) {
4031 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
4035 xpmJailSquare = xpmLightSquare;
4036 fprintf(stderr, _("Done.\n"));
4038 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
4041 #endif /* HAVE_LIBXPM */
4044 /* No built-in bitmaps */
4049 u_int ss = squareSize;
4051 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
4054 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
4055 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
4056 sprintf(buf, "%s%c%u%c.bm", piece > (int)WhiteKing ? "w" : "",
4057 pieceBitmapNames[piece],
4058 ss, kind == SOLID ? 's' : 'o');
4059 ReadBitmap(&pieceBitmap2[kind][piece], buf, NULL, ss, ss);
4060 if(piece <= (int)WhiteKing)
4061 pieceBitmap[kind][piece] = pieceBitmap2[kind][piece];
4065 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
4069 /* With built-in bitmaps */
4072 BuiltInBits* bib = builtInBits;
4075 u_int ss = squareSize;
4077 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
4080 while (bib->squareSize != ss && bib->squareSize != 0) bib++;
4082 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
4083 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
4084 sprintf(buf, "%s%c%u%c.bm", piece > (int)WhiteKing ? "w" : "",
4085 pieceBitmapNames[piece],
4086 ss, kind == SOLID ? 's' : 'o');
4087 ReadBitmap(&pieceBitmap2[kind][piece], buf,
4088 bib->bits[kind][piece], ss, ss);
4089 if(piece <= (int)WhiteKing)
4090 pieceBitmap[kind][piece] = pieceBitmap2[kind][piece];
4094 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
4099 void ReadBitmap(pm, name, bits, wreq, hreq)
4102 unsigned char bits[];
4108 char msg[MSG_SIZ], fullname[MSG_SIZ];
4110 if (*appData.bitmapDirectory != NULLCHAR) {
4111 strcpy(fullname, appData.bitmapDirectory);
4112 strcat(fullname, "/");
4113 strcat(fullname, name);
4114 errcode = XReadBitmapFile(xDisplay, xBoardWindow, fullname,
4115 &w, &h, pm, &x_hot, &y_hot);
4116 fprintf(stderr, "load %s\n", name);
4117 if (errcode != BitmapSuccess) {
4119 case BitmapOpenFailed:
4120 snprintf(msg, sizeof(msg), _("Can't open bitmap file %s"), fullname);
4122 case BitmapFileInvalid:
4123 snprintf(msg, sizeof(msg), _("Invalid bitmap in file %s"), fullname);
4125 case BitmapNoMemory:
4126 snprintf(msg, sizeof(msg), _("Ran out of memory reading bitmap file %s"),
4130 snprintf(msg, sizeof(msg), _("Unknown XReadBitmapFile error %d on file %s"),
4134 fprintf(stderr, _("%s: %s...using built-in\n"),
4136 } else if (w != wreq || h != hreq) {
4138 _("%s: Bitmap %s is %dx%d, not %dx%d...using built-in\n"),
4139 programName, fullname, w, h, wreq, hreq);
4146 fprintf(stderr, _("%s: No built-in bitmap for %s; giving up\n"),
4150 ; // [HGM] bitmaps: make it non-fatal if we have no bitmap;
4152 *pm = XCreateBitmapFromData(xDisplay, xBoardWindow, (char *) bits,
4161 if (lineGap == 0) return;
4163 /* [HR] Split this into 2 loops for non-square boards. */
4165 for (i = 0; i < BOARD_HEIGHT + 1; i++) {
4166 gridSegments[i].x1 = 0;
4167 gridSegments[i].x2 =
4168 lineGap + BOARD_WIDTH * (squareSize + lineGap);
4169 gridSegments[i].y1 = gridSegments[i].y2
4170 = lineGap / 2 + (i * (squareSize + lineGap));
4173 for (j = 0; j < BOARD_WIDTH + 1; j++) {
4174 gridSegments[j + i].y1 = 0;
4175 gridSegments[j + i].y2 =
4176 lineGap + BOARD_HEIGHT * (squareSize + lineGap);
4177 gridSegments[j + i].x1 = gridSegments[j + i].x2
4178 = lineGap / 2 + (j * (squareSize + lineGap));
4182 static void MenuBarSelect(w, addr, index)
4187 XtActionProc proc = (XtActionProc) addr;
4189 (proc)(NULL, NULL, NULL, NULL);
4192 void CreateMenuBarPopup(parent, name, mb)
4202 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
4205 XtSetArg(args[j], XtNleftMargin, 20); j++;
4206 XtSetArg(args[j], XtNrightMargin, 20); j++;
4208 while (mi->string != NULL) {
4209 if (strcmp(mi->string, "----") == 0) {
4210 entry = XtCreateManagedWidget(mi->string, smeLineObjectClass,
4213 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string)));
4214 entry = XtCreateManagedWidget(mi->string, smeBSBObjectClass,
4216 XtAddCallback(entry, XtNcallback,
4217 (XtCallbackProc) MenuBarSelect,
4218 (caddr_t) mi->proc);
4224 Widget CreateMenuBar(mb)
4228 Widget anchor, menuBar;
4230 char menuName[MSG_SIZ];
4233 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
4234 XtSetArg(args[j], XtNvSpace, 0); j++;
4235 XtSetArg(args[j], XtNborderWidth, 0); j++;
4236 menuBar = XtCreateWidget("menuBar", boxWidgetClass,
4237 formWidget, args, j);
4239 while (mb->name != NULL) {
4240 strcpy(menuName, "menu");
4241 strcat(menuName, mb->name);
4243 XtSetArg(args[j], XtNmenuName, XtNewString(menuName)); j++;
4246 shortName[0] = _(mb->name)[0];
4247 shortName[1] = NULLCHAR;
4248 XtSetArg(args[j], XtNlabel, XtNewString(shortName)); j++;
4251 XtSetArg(args[j], XtNlabel, XtNewString(_(mb->name))); j++;
4254 XtSetArg(args[j], XtNborderWidth, 0); j++;
4255 anchor = XtCreateManagedWidget(mb->name, menuButtonWidgetClass,
4257 CreateMenuBarPopup(menuBar, menuName, mb);
4263 Widget CreateButtonBar(mi)
4267 Widget button, buttonBar;
4271 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
4273 XtSetArg(args[j], XtNhSpace, 0); j++;
4275 XtSetArg(args[j], XtNborderWidth, 0); j++;
4276 XtSetArg(args[j], XtNvSpace, 0); j++;
4277 buttonBar = XtCreateWidget("buttonBar", boxWidgetClass,
4278 formWidget, args, j);
4280 while (mi->string != NULL) {
4283 XtSetArg(args[j], XtNinternalWidth, 2); j++;
4284 XtSetArg(args[j], XtNborderWidth, 0); j++;
4286 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string))); j++;
4287 button = XtCreateManagedWidget(mi->string, commandWidgetClass,
4288 buttonBar, args, j);
4289 XtAddCallback(button, XtNcallback,
4290 (XtCallbackProc) MenuBarSelect,
4291 (caddr_t) mi->proc);
4298 CreatePieceMenu(name, color)
4305 ChessSquare selection;
4307 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
4308 boardWidget, args, 0);
4310 for (i = 0; i < PIECE_MENU_SIZE; i++) {
4311 String item = pieceMenuStrings[color][i];
4313 if (strcmp(item, "----") == 0) {
4314 entry = XtCreateManagedWidget(item, smeLineObjectClass,
4317 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
4318 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
4320 selection = pieceMenuTranslation[color][i];
4321 XtAddCallback(entry, XtNcallback,
4322 (XtCallbackProc) PieceMenuSelect,
4323 (caddr_t) selection);
4324 if (selection == WhitePawn || selection == BlackPawn) {
4325 XtSetArg(args[0], XtNpopupOnEntry, entry);
4326 XtSetValues(menu, args, 1);
4339 ChessSquare selection;
4341 whitePieceMenu = CreatePieceMenu("menuW", 0);
4342 blackPieceMenu = CreatePieceMenu("menuB", 1);
4344 XtRegisterGrabAction(PieceMenuPopup, True,
4345 (unsigned)(ButtonPressMask|ButtonReleaseMask),
4346 GrabModeAsync, GrabModeAsync);
4348 XtSetArg(args[0], XtNlabel, _("Drop"));
4349 dropMenu = XtCreatePopupShell("menuD", simpleMenuWidgetClass,
4350 boardWidget, args, 1);
4351 for (i = 0; i < DROP_MENU_SIZE; i++) {
4352 String item = dropMenuStrings[i];
4354 if (strcmp(item, "----") == 0) {
4355 entry = XtCreateManagedWidget(item, smeLineObjectClass,
4358 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
4359 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
4361 selection = dropMenuTranslation[i];
4362 XtAddCallback(entry, XtNcallback,
4363 (XtCallbackProc) DropMenuSelect,
4364 (caddr_t) selection);
4369 void SetupDropMenu()
4377 for (i=0; i<sizeof(dmEnables)/sizeof(DropMenuEnables); i++) {
4378 entry = XtNameToWidget(dropMenu, dmEnables[i].widget);
4379 p = strchr(gameMode == IcsPlayingWhite ? white_holding : black_holding,
4380 dmEnables[i].piece);
4381 XtSetSensitive(entry, p != NULL || !appData.testLegality
4382 /*!!temp:*/ || (gameInfo.variant == VariantCrazyhouse
4383 && !appData.icsActive));
4385 while (p && *p++ == dmEnables[i].piece) count++;
4386 snprintf(label, sizeof(label), "%s %d", dmEnables[i].widget, count);
4388 XtSetArg(args[j], XtNlabel, label); j++;
4389 XtSetValues(entry, args, j);
4393 void PieceMenuPopup(w, event, params, num_params)
4397 Cardinal *num_params;
4400 if (event->type != ButtonPress) return;
4401 if (errorUp) ErrorPopDown();
4405 whichMenu = params[0];
4407 case IcsPlayingWhite:
4408 case IcsPlayingBlack:
4410 case MachinePlaysWhite:
4411 case MachinePlaysBlack:
4412 if (appData.testLegality &&
4413 gameInfo.variant != VariantBughouse &&
4414 gameInfo.variant != VariantCrazyhouse) return;
4416 whichMenu = "menuD";
4422 if (((pmFromX = EventToSquare(event->xbutton.x, BOARD_WIDTH)) < 0) ||
4423 ((pmFromY = EventToSquare(event->xbutton.y, BOARD_HEIGHT)) < 0)) {
4424 pmFromX = pmFromY = -1;
4428 pmFromX = BOARD_WIDTH - 1 - pmFromX;
4430 pmFromY = BOARD_HEIGHT - 1 - pmFromY;
4432 XtPopupSpringLoaded(XtNameToWidget(boardWidget, whichMenu));
4435 static void PieceMenuSelect(w, piece, junk)
4440 if (pmFromX < 0 || pmFromY < 0) return;
4441 EditPositionMenuEvent(piece, pmFromX, pmFromY);
4444 static void DropMenuSelect(w, piece, junk)
4449 if (pmFromX < 0 || pmFromY < 0) return;
4450 DropMenuEvent(piece, pmFromX, pmFromY);
4453 void WhiteClock(w, event, prms, nprms)
4459 if (gameMode == EditPosition || gameMode == IcsExamining) {
4460 SetWhiteToPlayEvent();
4461 } else if (gameMode == IcsPlayingBlack || gameMode == MachinePlaysWhite) {
4466 void BlackClock(w, event, prms, nprms)
4472 if (gameMode == EditPosition || gameMode == IcsExamining) {
4473 SetBlackToPlayEvent();
4474 } else if (gameMode == IcsPlayingWhite || gameMode == MachinePlaysBlack) {
4481 * If the user selects on a border boundary, return -1; if off the board,
4482 * return -2. Otherwise map the event coordinate to the square.
4484 int EventToSquare(x, limit)
4492 if ((x % (squareSize + lineGap)) >= squareSize)
4494 x /= (squareSize + lineGap);
4500 static void do_flash_delay(msec)
4506 static void drawHighlight(file, rank, gc)
4512 if (lineGap == 0 || appData.blindfold) return;
4515 x = lineGap/2 + ((BOARD_WIDTH-1)-file) *
4516 (squareSize + lineGap);
4517 y = lineGap/2 + rank * (squareSize + lineGap);
4519 x = lineGap/2 + file * (squareSize + lineGap);
4520 y = lineGap/2 + ((BOARD_HEIGHT-1)-rank) *
4521 (squareSize + lineGap);
4524 XDrawRectangle(xDisplay, xBoardWindow, gc, x, y,
4525 squareSize+lineGap, squareSize+lineGap);
4528 int hi1X = -1, hi1Y = -1, hi2X = -1, hi2Y = -1;
4529 int pm1X = -1, pm1Y = -1, pm2X = -1, pm2Y = -1;
4532 SetHighlights(fromX, fromY, toX, toY)
4533 int fromX, fromY, toX, toY;
4535 if (hi1X != fromX || hi1Y != fromY) {
4536 if (hi1X >= 0 && hi1Y >= 0) {
4537 drawHighlight(hi1X, hi1Y, lineGC);
4539 if (fromX >= 0 && fromY >= 0) {
4540 drawHighlight(fromX, fromY, highlineGC);
4543 if (hi2X != toX || hi2Y != toY) {
4544 if (hi2X >= 0 && hi2Y >= 0) {
4545 drawHighlight(hi2X, hi2Y, lineGC);
4547 if (toX >= 0 && toY >= 0) {
4548 drawHighlight(toX, toY, highlineGC);
4560 SetHighlights(-1, -1, -1, -1);
4565 SetPremoveHighlights(fromX, fromY, toX, toY)
4566 int fromX, fromY, toX, toY;
4568 if (pm1X != fromX || pm1Y != fromY) {
4569 if (pm1X >= 0 && pm1Y >= 0) {
4570 drawHighlight(pm1X, pm1Y, lineGC);
4572 if (fromX >= 0 && fromY >= 0) {
4573 drawHighlight(fromX, fromY, prelineGC);
4576 if (pm2X != toX || pm2Y != toY) {
4577 if (pm2X >= 0 && pm2Y >= 0) {
4578 drawHighlight(pm2X, pm2Y, lineGC);
4580 if (toX >= 0 && toY >= 0) {
4581 drawHighlight(toX, toY, prelineGC);
4591 ClearPremoveHighlights()
4593 SetPremoveHighlights(-1, -1, -1, -1);
4596 static void BlankSquare(x, y, color, piece, dest)
4601 if (useImages && useImageSqs) {
4605 pm = xpmLightSquare;
4610 case 2: /* neutral */
4615 XCopyArea(xDisplay, pm, dest, wlPieceGC, 0, 0,
4616 squareSize, squareSize, x, y);
4626 case 2: /* neutral */
4631 XFillRectangle(xDisplay, dest, gc, x, y, squareSize, squareSize);
4636 I split out the routines to draw a piece so that I could
4637 make a generic flash routine.
4639 static void monoDrawPiece_1bit(piece, square_color, x, y, dest)
4641 int square_color, x, y;
4644 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
4645 switch (square_color) {
4647 case 2: /* neutral */
4649 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
4650 ? *pieceToOutline(piece)
4651 : *pieceToSolid(piece),
4652 dest, bwPieceGC, 0, 0,
4653 squareSize, squareSize, x, y);
4656 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
4657 ? *pieceToSolid(piece)
4658 : *pieceToOutline(piece),
4659 dest, wbPieceGC, 0, 0,
4660 squareSize, squareSize, x, y);
4665 static void monoDrawPiece(piece, square_color, x, y, dest)
4667 int square_color, x, y;
4670 switch (square_color) {
4672 case 2: /* neutral */
4674 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
4675 ? *pieceToOutline(piece)
4676 : *pieceToSolid(piece),
4677 dest, bwPieceGC, 0, 0,
4678 squareSize, squareSize, x, y, 1);
4681 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
4682 ? *pieceToSolid(piece)
4683 : *pieceToOutline(piece),
4684 dest, wbPieceGC, 0, 0,
4685 squareSize, squareSize, x, y, 1);
4690 static void colorDrawPiece(piece, square_color, x, y, dest)
4692 int square_color, x, y;
4695 if(pieceToSolid(piece) == NULL) return; // [HGM] bitmaps: make it non-fatal if we have no bitmap;
4696 switch (square_color) {
4698 XCopyPlane(xDisplay, *pieceToSolid(piece),
4699 dest, (int) piece < (int) BlackPawn
4700 ? wlPieceGC : blPieceGC, 0, 0,
4701 squareSize, squareSize, x, y, 1);
4704 XCopyPlane(xDisplay, *pieceToSolid(piece),
4705 dest, (int) piece < (int) BlackPawn
4706 ? wdPieceGC : bdPieceGC, 0, 0,
4707 squareSize, squareSize, x, y, 1);
4709 case 2: /* neutral */
4711 XCopyPlane(xDisplay, *pieceToSolid(piece),
4712 dest, (int) piece < (int) BlackPawn
4713 ? wjPieceGC : bjPieceGC, 0, 0,
4714 squareSize, squareSize, x, y, 1);
4719 static void colorDrawPieceImage(piece, square_color, x, y, dest)
4721 int square_color, x, y;
4726 switch (square_color) {
4728 case 2: /* neutral */
4730 if ((int)piece < (int) BlackPawn) {
4738 if ((int)piece < (int) BlackPawn) {
4746 XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
4747 dest, wlPieceGC, 0, 0,
4748 squareSize, squareSize, x, y);
4751 typedef void (*DrawFunc)();
4753 DrawFunc ChooseDrawFunc()
4755 if (appData.monoMode) {
4756 if (DefaultDepth(xDisplay, xScreen) == 1) {
4757 return monoDrawPiece_1bit;
4759 return monoDrawPiece;
4763 return colorDrawPieceImage;
4765 return colorDrawPiece;
4769 /* [HR] determine square color depending on chess variant. */
4770 static int SquareColor(row, column)
4775 if (gameInfo.variant == VariantXiangqi) {
4776 if (column >= 3 && column <= 5 && row >= 0 && row <= 2) {
4778 } else if (column >= 3 && column <= 5 && row >= 7 && row <= 9) {
4780 } else if (row <= 4) {
4786 square_color = ((column + row) % 2) == 1;
4789 /* [hgm] holdings: next line makes all holdings squares light */
4790 if(column < BOARD_LEFT || column >= BOARD_RGHT) square_color = 1;
4792 return square_color;
4795 void DrawSquare(row, column, piece, do_flash)
4796 int row, column, do_flash;
4799 int square_color, x, y, direction, font_ascent, font_descent;
4802 XCharStruct overall;
4806 /* Calculate delay in milliseconds (2-delays per complete flash) */
4807 flash_delay = 500 / appData.flashRate;
4810 x = lineGap + ((BOARD_WIDTH-1)-column) *
4811 (squareSize + lineGap);
4812 y = lineGap + row * (squareSize + lineGap);
4814 x = lineGap + column * (squareSize + lineGap);
4815 y = lineGap + ((BOARD_HEIGHT-1)-row) *
4816 (squareSize + lineGap);
4819 square_color = SquareColor(row, column);
4821 if ( // [HGM] holdings: blank out area between board and holdings
4822 column == BOARD_LEFT-1 || column == BOARD_RGHT
4823 || (column == BOARD_LEFT-2 && row < BOARD_HEIGHT-gameInfo.holdingsSize)
4824 || (column == BOARD_RGHT+1 && row >= gameInfo.holdingsSize) ) {
4825 BlankSquare(x, y, 2, EmptySquare, xBoardWindow);
4827 // [HGM] print piece counts next to holdings
4828 string[1] = NULLCHAR;
4829 if (column == (flipView ? BOARD_LEFT-1 : BOARD_RGHT) && piece > 1 ) {
4830 string[0] = '0' + piece;
4831 XTextExtents(countFontStruct, string, 1, &direction,
4832 &font_ascent, &font_descent, &overall);
4833 if (appData.monoMode) {
4834 XDrawImageString(xDisplay, xBoardWindow, countGC,
4835 x + squareSize - overall.width - 2,
4836 y + font_ascent + 1, string, 1);
4838 XDrawString(xDisplay, xBoardWindow, countGC,
4839 x + squareSize - overall.width - 2,
4840 y + font_ascent + 1, string, 1);
4843 if (column == (flipView ? BOARD_RGHT : BOARD_LEFT-1) && piece > 1) {
4844 string[0] = '0' + piece;
4845 XTextExtents(countFontStruct, string, 1, &direction,
4846 &font_ascent, &font_descent, &overall);
4847 if (appData.monoMode) {
4848 XDrawImageString(xDisplay, xBoardWindow, countGC,
4849 x + 2, y + font_ascent + 1, string, 1);
4851 XDrawString(xDisplay, xBoardWindow, countGC,
4852 x + 2, y + font_ascent + 1, string, 1);
4856 if (piece == EmptySquare || appData.blindfold) {
4857 BlankSquare(x, y, square_color, piece, xBoardWindow);
4859 drawfunc = ChooseDrawFunc();
4860 if (do_flash && appData.flashCount > 0) {
4861 for (i=0; i<appData.flashCount; ++i) {
4863 drawfunc(piece, square_color, x, y, xBoardWindow);
4864 XSync(xDisplay, False);
4865 do_flash_delay(flash_delay);
4867 BlankSquare(x, y, square_color, piece, xBoardWindow);
4868 XSync(xDisplay, False);
4869 do_flash_delay(flash_delay);
4872 drawfunc(piece, square_color, x, y, xBoardWindow);
4876 string[1] = NULLCHAR;
4877 if (appData.showCoords && row == (flipView ? BOARD_HEIGHT-1 : 0)
4878 && column >= BOARD_LEFT && column < BOARD_RGHT) {
4879 string[0] = 'a' + column - BOARD_LEFT;
4880 XTextExtents(coordFontStruct, string, 1, &direction,
4881 &font_ascent, &font_descent, &overall);
4882 if (appData.monoMode) {
4883 XDrawImageString(xDisplay, xBoardWindow, coordGC,
4884 x + squareSize - overall.width - 2,
4885 y + squareSize - font_descent - 1, string, 1);
4887 XDrawString(xDisplay, xBoardWindow, coordGC,
4888 x + squareSize - overall.width - 2,
4889 y + squareSize - font_descent - 1, string, 1);
4892 if (appData.showCoords && column == (flipView ? BOARD_RGHT-1 : BOARD_LEFT)) {
4893 string[0] = ONE + row;
4894 XTextExtents(coordFontStruct, string, 1, &direction,
4895 &font_ascent, &font_descent, &overall);
4896 if (appData.monoMode) {
4897 XDrawImageString(xDisplay, xBoardWindow, coordGC,
4898 x + 2, y + font_ascent + 1, string, 1);
4900 XDrawString(xDisplay, xBoardWindow, coordGC,
4901 x + 2, y + font_ascent + 1, string, 1);
4907 /* Why is this needed on some versions of X? */
4908 void EventProc(widget, unused, event)
4913 if (!XtIsRealized(widget))
4916 switch (event->type) {
4918 if (event->xexpose.count > 0) return; /* no clipping is done */
4919 XDrawPosition(widget, True, NULL);
4927 void DrawPosition(fullRedraw, board)
4928 /*Boolean*/int fullRedraw;
4931 XDrawPosition(boardWidget, fullRedraw, board);
4934 /* Returns 1 if there are "too many" differences between b1 and b2
4935 (i.e. more than 1 move was made) */
4936 static int too_many_diffs(b1, b2)
4942 for (i=0; i<BOARD_HEIGHT; ++i) {
4943 for (j=0; j<BOARD_WIDTH; ++j) {
4944 if (b1[i][j] != b2[i][j]) {
4945 if (++c > 4) /* Castling causes 4 diffs */
4954 /* Matrix describing castling maneuvers */
4955 /* Row, ColRookFrom, ColKingFrom, ColRookTo, ColKingTo */
4956 static int castling_matrix[4][5] = {
4957 { 0, 0, 4, 3, 2 }, /* 0-0-0, white */
4958 { 0, 7, 4, 5, 6 }, /* 0-0, white */
4959 { 7, 0, 4, 3, 2 }, /* 0-0-0, black */
4960 { 7, 7, 4, 5, 6 } /* 0-0, black */
4963 /* Checks whether castling occurred. If it did, *rrow and *rcol
4964 are set to the destination (row,col) of the rook that moved.
4966 Returns 1 if castling occurred, 0 if not.
4968 Note: Only handles a max of 1 castling move, so be sure
4969 to call too_many_diffs() first.
4971 static int check_castle_draw(newb, oldb, rrow, rcol)
4978 /* For each type of castling... */
4979 for (i=0; i<4; ++i) {
4980 r = castling_matrix[i];
4982 /* Check the 4 squares involved in the castling move */
4984 for (j=1; j<=4; ++j) {
4985 if (newb[r[0]][r[j]] == oldb[r[0]][r[j]]) {
4992 /* All 4 changed, so it must be a castling move */
5001 static int damage[BOARD_SIZE][BOARD_SIZE];
5004 * event handler for redrawing the board
5006 void XDrawPosition(w, repaint, board)
5008 /*Boolean*/int repaint;
5012 static int lastFlipView = 0;
5013 static int lastBoardValid = 0;
5014 static Board lastBoard;
5018 if (board == NULL) {
5019 if (!lastBoardValid) return;
5022 if (!lastBoardValid || lastFlipView != flipView) {
5023 XtSetArg(args[0], XtNleftBitmap, (flipView ? xMarkPixmap : None));
5024 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flip View"),
5029 * It would be simpler to clear the window with XClearWindow()
5030 * but this causes a very distracting flicker.
5033 if (!repaint && lastBoardValid && lastFlipView == flipView) {
5035 /* If too much changes (begin observing new game, etc.), don't
5037 do_flash = too_many_diffs(board, lastBoard) ? 0 : 1;
5039 /* Special check for castling so we don't flash both the king
5040 and the rook (just flash the king). */
5042 if (check_castle_draw(board, lastBoard, &rrow, &rcol)) {
5043 /* Draw rook with NO flashing. King will be drawn flashing later */
5044 DrawSquare(rrow, rcol, board[rrow][rcol], 0);
5045 lastBoard[rrow][rcol] = board[rrow][rcol];
5049 /* First pass -- Draw (newly) empty squares and repair damage.
5050 This prevents you from having a piece show up twice while it
5051 is flashing on its new square */
5052 for (i = 0; i < BOARD_HEIGHT; i++)
5053 for (j = 0; j < BOARD_WIDTH; j++)
5054 if ((board[i][j] != lastBoard[i][j] && board[i][j] == EmptySquare)
5056 DrawSquare(i, j, board[i][j], 0);
5057 damage[i][j] = False;
5060 /* Second pass -- Draw piece(s) in new position and flash them */
5061 for (i = 0; i < BOARD_HEIGHT; i++)
5062 for (j = 0; j < BOARD_WIDTH; j++)
5063 if (board[i][j] != lastBoard[i][j]) {
5064 DrawSquare(i, j, board[i][j], do_flash);
5068 XDrawSegments(xDisplay, xBoardWindow, lineGC,
5069 gridSegments, BOARD_HEIGHT + BOARD_WIDTH + 2);
5071 for (i = 0; i < BOARD_HEIGHT; i++)
5072 for (j = 0; j < BOARD_WIDTH; j++) {
5073 DrawSquare(i, j, board[i][j], 0);
5074 damage[i][j] = False;
5078 CopyBoard(lastBoard, board);
5080 lastFlipView = flipView;
5082 /* Draw highlights */
5083 if (pm1X >= 0 && pm1Y >= 0) {
5084 drawHighlight(pm1X, pm1Y, prelineGC);
5086 if (pm2X >= 0 && pm2Y >= 0) {
5087 drawHighlight(pm2X, pm2Y, prelineGC);
5089 if (hi1X >= 0 && hi1Y >= 0) {
5090 drawHighlight(hi1X, hi1Y, highlineGC);
5092 if (hi2X >= 0 && hi2Y >= 0) {
5093 drawHighlight(hi2X, hi2Y, highlineGC);
5096 /* If piece being dragged around board, must redraw that too */
5099 XSync(xDisplay, False);
5104 * event handler for redrawing the board
5106 void DrawPositionProc(w, event, prms, nprms)
5112 XDrawPosition(w, True, NULL);
5117 * event handler for parsing user moves
5119 // [HGM] This routine will need quite some reworking. Although the backend still supports the old
5120 // way of doing things, by calling UserMoveEvent() to test the legality of the move and then perform
5121 // it at the end, and doing all kind of preliminary tests here (e.g. to weed out self-captures), it
5122 // should be made to use the new way, of calling UserMoveTest early to determine the legality of the
5123 // move, (which will weed out the illegal selfcaptures and moves into the holdings, and flag promotions),
5124 // and at the end FinishMove() to perform the move after optional promotion popups.
5125 // For now I patched it to allow self-capture with King, and suppress clicks between board and holdings.
5126 void HandleUserMove(w, event, prms, nprms)
5133 Boolean saveAnimate;
5134 static int second = 0;
5136 if (w != boardWidget || errorExitStatus != -1) return;
5138 if (event->type == ButtonPress) ErrorPopDown();
5141 if (event->type == ButtonPress) {
5142 XtPopdown(promotionShell);
5143 XtDestroyWidget(promotionShell);
5144 promotionUp = False;
5152 x = EventToSquare(event->xbutton.x, BOARD_WIDTH);
5153 y = EventToSquare(event->xbutton.y, BOARD_HEIGHT);
5154 if (!flipView && y >= 0) {
5155 y = BOARD_HEIGHT - 1 - y;
5157 if (flipView && x >= 0) {
5158 x = BOARD_WIDTH - 1 - x;
5161 /* [HGM] holdings: next 5 lines: ignore all clicks between board and holdings */
5162 if(event->type == ButtonPress
5163 && ( x == BOARD_LEFT-1 || x == BOARD_RGHT
5164 || x == BOARD_LEFT-2 && y < BOARD_HEIGHT-gameInfo.holdingsSize
5165 || x == BOARD_RGHT+1 && y >= gameInfo.holdingsSize) )
5169 if (event->type == ButtonPress) {
5171 if (OKToStartUserMove(x, y)) {
5175 DragPieceBegin(event->xbutton.x, event->xbutton.y);
5176 if (appData.highlightDragging) {
5177 SetHighlights(x, y, -1, -1);
5185 if (event->type == ButtonPress && gameMode != EditPosition &&
5191 /* Check if clicking again on the same color piece */
5192 fromP = boards[currentMove][fromY][fromX];
5193 toP = boards[currentMove][y][x];
5194 frc = gameInfo.variant == VariantFischeRandom || gameInfo.variant == VariantCapaRandom;
5195 if ((WhitePawn <= fromP && fromP <= WhiteKing && // [HGM] this test should go, as UserMoveTest now does it.
5196 WhitePawn <= toP && toP <= WhiteKing &&
5197 !(fromP == WhiteKing && toP == WhiteRook && frc)) ||
5198 (BlackPawn <= fromP && fromP <= BlackKing &&
5199 BlackPawn <= toP && toP <= BlackKing &&
5200 !(fromP == BlackKing && toP == BlackRook && frc))) {
5201 /* Clicked again on same color piece -- changed his mind */
5202 second = (x == fromX && y == fromY);
5203 if (appData.highlightDragging) {
5204 SetHighlights(x, y, -1, -1);
5208 if (OKToStartUserMove(x, y)) {
5211 DragPieceBegin(event->xbutton.x, event->xbutton.y);
5217 if (event->type == ButtonRelease && x == fromX && y == fromY) {
5218 DragPieceEnd(event->xbutton.x, event->xbutton.y);
5219 if (appData.animateDragging) {
5220 /* Undo animation damage if any */
5221 DrawPosition(FALSE, NULL);
5224 /* Second up/down in same square; just abort move */
5229 ClearPremoveHighlights();
5231 /* First upclick in same square; start click-click mode */
5232 SetHighlights(x, y, -1, -1);
5237 /* Completed move */
5240 saveAnimate = appData.animate;
5241 if (event->type == ButtonPress) {
5242 /* Finish clickclick move */
5243 if (appData.animate || appData.highlightLastMove) {
5244 SetHighlights(fromX, fromY, toX, toY);
5249 /* Finish drag move */
5250 if (appData.highlightLastMove) {
5251 SetHighlights(fromX, fromY, toX, toY);
5255 DragPieceEnd(event->xbutton.x, event->xbutton.y);
5256 /* Don't animate move and drag both */
5257 appData.animate = FALSE;
5259 if (IsPromotion(fromX, fromY, toX, toY)) {
5260 if (appData.alwaysPromoteToQueen) {
5261 UserMoveEvent(fromX, fromY, toX, toY, 'q');
5262 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
5263 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
5266 SetHighlights(fromX, fromY, toX, toY);
5270 UserMoveEvent(fromX, fromY, toX, toY, NULLCHAR);
5271 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
5272 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
5275 appData.animate = saveAnimate;
5276 if (appData.animate || appData.animateDragging) {
5277 /* Undo animation damage if needed */
5278 DrawPosition(FALSE, NULL);
5282 void AnimateUserMove (Widget w, XEvent * event,
5283 String * params, Cardinal * nParams)
5285 DragPieceMove(event->xmotion.x, event->xmotion.y);
5288 Widget CommentCreate(name, text, mutable, callback, lines)
5290 int /*Boolean*/ mutable;
5291 XtCallbackProc callback;
5295 Widget shell, layout, form, edit, b_ok, b_cancel, b_clear, b_close, b_edit;
5300 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5301 XtGetValues(boardWidget, args, j);
5304 XtSetArg(args[j], XtNresizable, True); j++;
5307 XtCreatePopupShell(name, topLevelShellWidgetClass,
5308 shellWidget, args, j);
5311 XtCreatePopupShell(name, transientShellWidgetClass,
5312 shellWidget, args, j);
5315 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
5316 layoutArgs, XtNumber(layoutArgs));
5318 XtCreateManagedWidget("form", formWidgetClass, layout,
5319 formArgs, XtNumber(formArgs));
5323 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
5324 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
5326 XtSetArg(args[j], XtNstring, text); j++;
5327 XtSetArg(args[j], XtNtop, XtChainTop); j++;
5328 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5329 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5330 XtSetArg(args[j], XtNright, XtChainRight); j++;
5331 XtSetArg(args[j], XtNresizable, True); j++;
5332 XtSetArg(args[j], XtNwidth, bw_width); j++; /*force wider than buttons*/
5334 XtSetArg(args[j], XtNscrollVertical, XawtextScrollWhenNeeded); j++;
5336 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
5337 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
5339 XtSetArg(args[j], XtNautoFill, True); j++;
5340 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
5342 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
5346 XtSetArg(args[j], XtNfromVert, edit); j++;
5347 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5348 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5349 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5350 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5352 XtCreateManagedWidget(_("ok"), commandWidgetClass, form, args, j);
5353 XtAddCallback(b_ok, XtNcallback, callback, (XtPointer) 0);
5356 XtSetArg(args[j], XtNfromVert, edit); j++;
5357 XtSetArg(args[j], XtNfromHoriz, b_ok); j++;
5358 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5359 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5360 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5361 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5363 XtCreateManagedWidget(_("cancel"), commandWidgetClass, form, args, j);
5364 XtAddCallback(b_cancel, XtNcallback, callback, (XtPointer) 0);
5367 XtSetArg(args[j], XtNfromVert, edit); j++;
5368 XtSetArg(args[j], XtNfromHoriz, b_cancel); j++;
5369 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5370 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5371 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5372 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5374 XtCreateManagedWidget(_("clear"), commandWidgetClass, form, args, j);
5375 XtAddCallback(b_clear, XtNcallback, callback, (XtPointer) 0);
5378 XtSetArg(args[j], XtNfromVert, edit); j++;
5379 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5380 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5381 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5382 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5384 XtCreateManagedWidget(_("close"), commandWidgetClass, form, args, j);
5385 XtAddCallback(b_close, XtNcallback, callback, (XtPointer) 0);
5388 XtSetArg(args[j], XtNfromVert, edit); j++;
5389 XtSetArg(args[j], XtNfromHoriz, b_close); j++;
5390 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5391 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5392 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5393 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5395 XtCreateManagedWidget(_("edit"), commandWidgetClass, form, args, j);
5396 XtAddCallback(b_edit, XtNcallback, callback, (XtPointer) 0);
5399 XtRealizeWidget(shell);
5401 if (commentX == -1) {
5404 Dimension pw_height;
5405 Dimension ew_height;
5408 XtSetArg(args[j], XtNheight, &ew_height); j++;
5409 XtGetValues(edit, args, j);
5412 XtSetArg(args[j], XtNheight, &pw_height); j++;
5413 XtGetValues(shell, args, j);
5414 commentH = pw_height + (lines - 1) * ew_height;
5415 commentW = bw_width - 16;
5417 XSync(xDisplay, False);
5419 /* This code seems to tickle an X bug if it is executed too soon
5420 after xboard starts up. The coordinates get transformed as if
5421 the main window was positioned at (0, 0).
5423 XtTranslateCoords(shellWidget,
5424 (bw_width - commentW) / 2, 0 - commentH / 2,
5425 &commentX, &commentY);
5427 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
5428 RootWindowOfScreen(XtScreen(shellWidget)),
5429 (bw_width - commentW) / 2, 0 - commentH / 2,
5434 if (commentY < 0) commentY = 0; /*avoid positioning top offscreen*/
5437 XtSetArg(args[j], XtNheight, commentH); j++;
5438 XtSetArg(args[j], XtNwidth, commentW); j++;
5439 XtSetArg(args[j], XtNx, commentX); j++;
5440 XtSetArg(args[j], XtNy, commentY); j++;
5441 XtSetValues(shell, args, j);
5442 XtSetKeyboardFocus(shell, edit);
5447 /* Used for analysis window and ICS input window */
5448 Widget MiscCreate(name, text, mutable, callback, lines)
5450 int /*Boolean*/ mutable;
5451 XtCallbackProc callback;
5455 Widget shell, layout, form, edit;
5457 Dimension bw_width, pw_height, ew_height, w, h;
5463 XtSetArg(args[j], XtNresizable, True); j++;
5466 XtCreatePopupShell(name, topLevelShellWidgetClass,
5467 shellWidget, args, j);
5470 XtCreatePopupShell(name, transientShellWidgetClass,
5471 shellWidget, args, j);
5474 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
5475 layoutArgs, XtNumber(layoutArgs));
5477 XtCreateManagedWidget("form", formWidgetClass, layout,
5478 formArgs, XtNumber(formArgs));
5482 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
5483 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
5485 XtSetArg(args[j], XtNstring, text); j++;
5486 XtSetArg(args[j], XtNtop, XtChainTop); j++;
5487 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5488 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5489 XtSetArg(args[j], XtNright, XtChainRight); j++;
5490 XtSetArg(args[j], XtNresizable, True); j++;
5492 XtSetArg(args[j], XtNscrollVertical, XawtextScrollWhenNeeded); j++;
5494 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
5495 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
5497 XtSetArg(args[j], XtNautoFill, True); j++;
5498 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
5500 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
5502 XtRealizeWidget(shell);
5505 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5506 XtGetValues(boardWidget, args, j);
5509 XtSetArg(args[j], XtNheight, &ew_height); j++;
5510 XtGetValues(edit, args, j);
5513 XtSetArg(args[j], XtNheight, &pw_height); j++;
5514 XtGetValues(shell, args, j);
5515 h = pw_height + (lines - 1) * ew_height;
5518 XSync(xDisplay, False);
5520 /* This code seems to tickle an X bug if it is executed too soon
5521 after xboard starts up. The coordinates get transformed as if
5522 the main window was positioned at (0, 0).
5524 XtTranslateCoords(shellWidget, (bw_width - w) / 2, 0 - h / 2, &x, &y);
5526 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
5527 RootWindowOfScreen(XtScreen(shellWidget)),
5528 (bw_width - w) / 2, 0 - h / 2, &xx, &yy, &junk);
5532 if (y < 0) y = 0; /*avoid positioning top offscreen*/
5535 XtSetArg(args[j], XtNheight, h); j++;
5536 XtSetArg(args[j], XtNwidth, w); j++;
5537 XtSetArg(args[j], XtNx, x); j++;
5538 XtSetArg(args[j], XtNy, y); j++;
5539 XtSetValues(shell, args, j);
5545 static int savedIndex; /* gross that this is global */
5547 void EditCommentPopUp(index, title, text)
5556 if (text == NULL) text = "";
5558 if (editShell == NULL) {
5560 CommentCreate(title, text, True, EditCommentCallback, 4);
5561 XtRealizeWidget(editShell);
5562 CatchDeleteWindow(editShell, "EditCommentPopDown");
5564 edit = XtNameToWidget(editShell, "*form.text");
5566 XtSetArg(args[j], XtNstring, text); j++;
5567 XtSetValues(edit, args, j);
5569 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5570 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5571 XtSetValues(editShell, args, j);
5574 XtPopup(editShell, XtGrabNone);
5578 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
5579 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
5583 void EditCommentCallback(w, client_data, call_data)
5585 XtPointer client_data, call_data;
5593 XtSetArg(args[j], XtNlabel, &name); j++;
5594 XtGetValues(w, args, j);
5596 if (strcmp(name, _("ok")) == 0) {
5597 edit = XtNameToWidget(editShell, "*form.text");
5599 XtSetArg(args[j], XtNstring, &val); j++;
5600 XtGetValues(edit, args, j);
5601 ReplaceComment(savedIndex, val);
5602 EditCommentPopDown();
5603 } else if (strcmp(name, _("cancel")) == 0) {
5604 EditCommentPopDown();
5605 } else if (strcmp(name, _("clear")) == 0) {
5606 edit = XtNameToWidget(editShell, "*form.text");
5607 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
5608 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
5612 void EditCommentPopDown()
5617 if (!editUp) return;
5619 XtSetArg(args[j], XtNx, &commentX); j++;
5620 XtSetArg(args[j], XtNy, &commentY); j++;
5621 XtSetArg(args[j], XtNheight, &commentH); j++;
5622 XtSetArg(args[j], XtNwidth, &commentW); j++;
5623 XtGetValues(editShell, args, j);
5624 XtPopdown(editShell);
5627 XtSetArg(args[j], XtNleftBitmap, None); j++;
5628 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
5632 void ICSInputBoxPopUp()
5637 char *title = _("ICS Input");
5640 if (ICSInputShell == NULL) {
5641 ICSInputShell = MiscCreate(title, "", True, NULL, 1);
5642 tr = XtParseTranslationTable(ICSInputTranslations);
5643 edit = XtNameToWidget(ICSInputShell, "*form.text");
5644 XtOverrideTranslations(edit, tr);
5645 XtRealizeWidget(ICSInputShell);
5646 CatchDeleteWindow(ICSInputShell, "ICSInputBoxPopDown");
5649 edit = XtNameToWidget(ICSInputShell, "*form.text");
5651 XtSetArg(args[j], XtNstring, ""); j++;
5652 XtSetValues(edit, args, j);
5654 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5655 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5656 XtSetValues(ICSInputShell, args, j);
5659 XtPopup(ICSInputShell, XtGrabNone);
5660 XtSetKeyboardFocus(ICSInputShell, edit);
5662 ICSInputBoxUp = True;
5664 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
5665 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
5669 void ICSInputSendText()
5676 edit = XtNameToWidget(ICSInputShell, "*form.text");
5678 XtSetArg(args[j], XtNstring, &val); j++;
5679 XtGetValues(edit, args, j);
5680 SendMultiLineToICS(val);
5681 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
5682 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
5685 void ICSInputBoxPopDown()
5690 if (!ICSInputBoxUp) return;
5692 XtPopdown(ICSInputShell);
5693 ICSInputBoxUp = False;
5695 XtSetArg(args[j], XtNleftBitmap, None); j++;
5696 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
5700 void CommentPopUp(title, text)
5707 if (commentShell == NULL) {
5709 CommentCreate(title, text, False, CommentCallback, 4);
5710 XtRealizeWidget(commentShell);
5711 CatchDeleteWindow(commentShell, "CommentPopDown");
5713 edit = XtNameToWidget(commentShell, "*form.text");
5715 XtSetArg(args[j], XtNstring, text); j++;
5716 XtSetValues(edit, args, j);
5718 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5719 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5720 XtSetValues(commentShell, args, j);
5723 XtPopup(commentShell, XtGrabNone);
5724 XSync(xDisplay, False);
5729 void AnalysisPopUp(title, text)
5736 if (analysisShell == NULL) {
5737 analysisShell = MiscCreate(title, text, False, NULL, 4);
5738 XtRealizeWidget(analysisShell);
5739 CatchDeleteWindow(analysisShell, "AnalysisPopDown");
5742 edit = XtNameToWidget(analysisShell, "*form.text");
5744 XtSetArg(args[j], XtNstring, text); j++;
5745 XtSetValues(edit, args, j);
5747 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5748 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5749 XtSetValues(analysisShell, args, j);
5753 XtPopup(analysisShell, XtGrabNone);
5755 XSync(xDisplay, False);
5760 void CommentCallback(w, client_data, call_data)
5762 XtPointer client_data, call_data;
5769 XtSetArg(args[j], XtNlabel, &name); j++;
5770 XtGetValues(w, args, j);
5772 if (strcmp(name, _("close")) == 0) {
5774 } else if (strcmp(name, _("edit")) == 0) {
5781 void CommentPopDown()
5786 if (!commentUp) return;
5788 XtSetArg(args[j], XtNx, &commentX); j++;
5789 XtSetArg(args[j], XtNy, &commentY); j++;
5790 XtSetArg(args[j], XtNwidth, &commentW); j++;
5791 XtSetArg(args[j], XtNheight, &commentH); j++;
5792 XtGetValues(commentShell, args, j);
5793 XtPopdown(commentShell);
5794 XSync(xDisplay, False);
5798 void AnalysisPopDown()
5800 if (!analysisUp) return;
5801 XtPopdown(analysisShell);
5802 XSync(xDisplay, False);
5804 if (appData.icsEngineAnalyze) ExitAnalyzeMode(); /* [DM] icsEngineAnalyze */
5808 void FileNamePopUp(label, def, proc, openMode)
5815 Widget popup, layout, dialog, edit;
5821 fileProc = proc; /* I can't see a way not */
5822 fileOpenMode = openMode; /* to use globals here */
5825 XtSetArg(args[i], XtNresizable, True); i++;
5826 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
5827 XtSetArg(args[i], XtNtitle, XtNewString(_("File name prompt"))); i++;
5828 fileNameShell = popup =
5829 XtCreatePopupShell("File name prompt", transientShellWidgetClass,
5830 shellWidget, args, i);
5833 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
5834 layoutArgs, XtNumber(layoutArgs));
5837 XtSetArg(args[i], XtNlabel, label); i++;
5838 XtSetArg(args[i], XtNvalue, def); i++;
5839 XtSetArg(args[i], XtNborderWidth, 0); i++;
5840 dialog = XtCreateManagedWidget("fileName", dialogWidgetClass,
5843 XawDialogAddButton(dialog, _("ok"), FileNameCallback, (XtPointer) dialog);
5844 XawDialogAddButton(dialog, _("cancel"), FileNameCallback,
5845 (XtPointer) dialog);
5847 XtRealizeWidget(popup);
5848 CatchDeleteWindow(popup, "FileNamePopDown");
5850 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
5851 &x, &y, &win_x, &win_y, &mask);
5853 XtSetArg(args[0], XtNx, x - 10);
5854 XtSetArg(args[1], XtNy, y - 30);
5855 XtSetValues(popup, args, 2);
5857 XtPopup(popup, XtGrabExclusive);
5860 edit = XtNameToWidget(dialog, "*value");
5861 XtSetKeyboardFocus(popup, edit);
5864 void FileNamePopDown()
5866 if (!filenameUp) return;
5867 XtPopdown(fileNameShell);
5868 XtDestroyWidget(fileNameShell);
5873 void FileNameCallback(w, client_data, call_data)
5875 XtPointer client_data, call_data;
5880 XtSetArg(args[0], XtNlabel, &name);
5881 XtGetValues(w, args, 1);
5883 if (strcmp(name, _("cancel")) == 0) {
5888 FileNameAction(w, NULL, NULL, NULL);
5891 void FileNameAction(w, event, prms, nprms)
5903 name = XawDialogGetValueString(w = XtParent(w));
5905 if ((name != NULL) && (*name != NULLCHAR)) {
5907 XtPopdown(w = XtParent(XtParent(w)));
5911 p = strrchr(buf, ' ');
5918 fullname = ExpandPathName(buf);
5920 ErrorPopUp(_("Error"), _("Can't open file"), FALSE);
5923 f = fopen(fullname, fileOpenMode);
5925 DisplayError(_("Failed to open file"), errno);
5927 (void) (*fileProc)(f, index, buf);
5934 XtPopdown(w = XtParent(XtParent(w)));
5940 void PromotionPopUp()
5943 Widget dialog, layout;
5945 Dimension bw_width, pw_width;
5949 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5950 XtGetValues(boardWidget, args, j);
5953 XtSetArg(args[j], XtNresizable, True); j++;
5954 XtSetArg(args[j], XtNtitle, XtNewString(_("Promotion"))); j++;
5956 XtCreatePopupShell("Promotion", transientShellWidgetClass,
5957 shellWidget, args, j);
5959 XtCreateManagedWidget(layoutName, formWidgetClass, promotionShell,
5960 layoutArgs, XtNumber(layoutArgs));
5963 XtSetArg(args[j], XtNlabel, _("Promote to what?")); j++;
5964 XtSetArg(args[j], XtNborderWidth, 0); j++;
5965 dialog = XtCreateManagedWidget("promotion", dialogWidgetClass,
5968 if(gameInfo.variant != VariantShogi) {
5969 XawDialogAddButton(dialog, _("Queen"), PromotionCallback,
5970 (XtPointer) dialog);
5971 XawDialogAddButton(dialog, _("Rook"), PromotionCallback,
5972 (XtPointer) dialog);
5973 XawDialogAddButton(dialog, _("Bishop"), PromotionCallback,
5974 (XtPointer) dialog);
5975 XawDialogAddButton(dialog, _("Knight"), PromotionCallback,
5976 (XtPointer) dialog);
5977 if (!appData.testLegality || gameInfo.variant == VariantSuicide ||
5978 gameInfo.variant == VariantGiveaway) {
5979 XawDialogAddButton(dialog, _("King"), PromotionCallback,
5980 (XtPointer) dialog);
5982 if(gameInfo.variant == VariantCapablanca ||
5983 gameInfo.variant == VariantGothic ||
5984 gameInfo.variant == VariantCapaRandom) {
5985 XawDialogAddButton(dialog, _("Archbishop"), PromotionCallback,
5986 (XtPointer) dialog);
5987 XawDialogAddButton(dialog, _("Chancellor"), PromotionCallback,
5988 (XtPointer) dialog);
5990 } else // [HGM] shogi
5992 XawDialogAddButton(dialog, _("Promote"), PromotionCallback,
5993 (XtPointer) dialog);
5994 XawDialogAddButton(dialog, _("Defer"), PromotionCallback,
5995 (XtPointer) dialog);
5997 XawDialogAddButton(dialog, _("cancel"), PromotionCallback,
5998 (XtPointer) dialog);
6000 XtRealizeWidget(promotionShell);
6001 CatchDeleteWindow(promotionShell, "PromotionPopDown");
6004 XtSetArg(args[j], XtNwidth, &pw_width); j++;
6005 XtGetValues(promotionShell, args, j);
6007 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
6008 lineGap + squareSize/3 +
6009 ((toY == BOARD_HEIGHT-1) ^ (flipView) ?
6010 0 : 6*(squareSize + lineGap)), &x, &y);
6013 XtSetArg(args[j], XtNx, x); j++;
6014 XtSetArg(args[j], XtNy, y); j++;
6015 XtSetValues(promotionShell, args, j);
6017 XtPopup(promotionShell, XtGrabNone);
6022 void PromotionPopDown()
6024 if (!promotionUp) return;
6025 XtPopdown(promotionShell);
6026 XtDestroyWidget(promotionShell);
6027 promotionUp = False;
6030 void PromotionCallback(w, client_data, call_data)
6032 XtPointer client_data, call_data;
6038 XtSetArg(args[0], XtNlabel, &name);
6039 XtGetValues(w, args, 1);
6043 if (fromX == -1) return;
6045 if (strcmp(name, _("cancel")) == 0) {
6049 } else if (strcmp(name, _("Knight")) == 0) {
6051 } else if (strcmp(name, _("Promote")) == 0) {
6053 } else if (strcmp(name, _("Defer")) == 0) {
6056 promoChar = ToLower(name[0]);
6059 UserMoveEvent(fromX, fromY, toX, toY, promoChar);
6061 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
6062 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
6067 void ErrorCallback(w, client_data, call_data)
6069 XtPointer client_data, call_data;
6072 XtPopdown(w = XtParent(XtParent(XtParent(w))));
6074 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
6080 if (!errorUp) return;
6082 XtPopdown(errorShell);
6083 XtDestroyWidget(errorShell);
6084 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
6087 void ErrorPopUp(title, label, modal)
6088 char *title, *label;
6092 Widget dialog, layout;
6096 Dimension bw_width, pw_width;
6097 Dimension pw_height;
6101 XtSetArg(args[i], XtNresizable, True); i++;
6102 XtSetArg(args[i], XtNtitle, title); i++;
6104 XtCreatePopupShell("errorpopup", transientShellWidgetClass,
6105 shellWidget, args, i);
6107 XtCreateManagedWidget(layoutName, formWidgetClass, errorShell,
6108 layoutArgs, XtNumber(layoutArgs));
6111 XtSetArg(args[i], XtNlabel, label); i++;
6112 XtSetArg(args[i], XtNborderWidth, 0); i++;
6113 dialog = XtCreateManagedWidget("dialog", dialogWidgetClass,
6116 XawDialogAddButton(dialog, _("ok"), ErrorCallback, (XtPointer) dialog);
6118 XtRealizeWidget(errorShell);
6119 CatchDeleteWindow(errorShell, "ErrorPopDown");
6122 XtSetArg(args[i], XtNwidth, &bw_width); i++;
6123 XtGetValues(boardWidget, args, i);
6125 XtSetArg(args[i], XtNwidth, &pw_width); i++;
6126 XtSetArg(args[i], XtNheight, &pw_height); i++;
6127 XtGetValues(errorShell, args, i);
6130 /* This code seems to tickle an X bug if it is executed too soon
6131 after xboard starts up. The coordinates get transformed as if
6132 the main window was positioned at (0, 0).
6134 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
6135 0 - pw_height + squareSize / 3, &x, &y);
6137 XTranslateCoordinates(xDisplay, XtWindow(boardWidget),
6138 RootWindowOfScreen(XtScreen(boardWidget)),
6139 (bw_width - pw_width) / 2,
6140 0 - pw_height + squareSize / 3, &xx, &yy, &junk);
6144 if (y < 0) y = 0; /*avoid positioning top offscreen*/
6147 XtSetArg(args[i], XtNx, x); i++;
6148 XtSetArg(args[i], XtNy, y); i++;
6149 XtSetValues(errorShell, args, i);
6152 XtPopup(errorShell, modal ? XtGrabExclusive : XtGrabNone);
6155 /* Disable all user input other than deleting the window */
6156 static int frozen = 0;
6160 /* Grab by a widget that doesn't accept input */
6161 XtAddGrab(messageWidget, TRUE, FALSE);
6165 /* Undo a FreezeUI */
6168 if (!frozen) return;
6169 XtRemoveGrab(messageWidget);
6173 char *ModeToWidgetName(mode)
6177 case BeginningOfGame:
6178 if (appData.icsActive)
6179 return "menuMode.ICS Client";
6180 else if (appData.noChessProgram ||
6181 *appData.cmailGameName != NULLCHAR)
6182 return "menuMode.Edit Game";
6184 return "menuMode.Machine Black";
6185 case MachinePlaysBlack:
6186 return "menuMode.Machine Black";
6187 case MachinePlaysWhite:
6188 return "menuMode.Machine White";
6190 return "menuMode.Analysis Mode";
6192 return "menuMode.Analyze File";
6193 case TwoMachinesPlay:
6194 return "menuMode.Two Machines";
6196 return "menuMode.Edit Game";
6197 case PlayFromGameFile:
6198 return "menuFile.Load Game";
6200 return "menuMode.Edit Position";
6202 return "menuMode.Training";
6203 case IcsPlayingWhite:
6204 case IcsPlayingBlack:
6208 return "menuMode.ICS Client";
6215 void ModeHighlight()
6218 static int oldPausing = FALSE;
6219 static GameMode oldmode = (GameMode) -1;
6222 if (!boardWidget || !XtIsRealized(boardWidget)) return;
6224 if (pausing != oldPausing) {
6225 oldPausing = pausing;
6227 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6229 XtSetArg(args[0], XtNleftBitmap, None);
6231 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Pause"),
6234 if (appData.showButtonBar) {
6237 XtSetArg(args[0], XtNbackground, buttonForegroundPixel);
6238 XtSetArg(args[1], XtNforeground, buttonBackgroundPixel);
6240 XtSetArg(args[0], XtNbackground, buttonBackgroundPixel);
6241 XtSetArg(args[1], XtNforeground, buttonForegroundPixel);
6244 /* Always toggle, don't set. Previous code messes up when
6245 invoked while the button is pressed, as releasing it
6246 toggles the state again. */
6249 XtSetArg(args[0], XtNbackground, &oldbg);
6250 XtSetArg(args[1], XtNforeground, &oldfg);
6251 XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON),
6253 XtSetArg(args[0], XtNbackground, oldfg);
6254 XtSetArg(args[1], XtNforeground, oldbg);
6257 XtSetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
6261 wname = ModeToWidgetName(oldmode);
6262 if (wname != NULL) {
6263 XtSetArg(args[0], XtNleftBitmap, None);
6264 XtSetValues(XtNameToWidget(menuBarWidget, wname), args, 1);
6266 wname = ModeToWidgetName(gameMode);
6267 if (wname != NULL) {
6268 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6269 XtSetValues(XtNameToWidget(menuBarWidget, wname), args, 1);
6273 /* Maybe all the enables should be handled here, not just this one */
6274 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Training"),
6275 gameMode == Training || gameMode == PlayFromGameFile);
6280 * Button/menu procedures
6282 void ResetProc(w, event, prms, nprms)
6292 int LoadGamePopUp(f, gameNumber, title)
6297 cmailMsgLoaded = FALSE;
6298 if (gameNumber == 0) {
6299 int error = GameListBuild(f);
6301 DisplayError(_("Cannot build game list"), error);
6302 } else if (!ListEmpty(&gameList) &&
6303 ((ListGame *) gameList.tailPred)->number > 1) {
6304 GameListPopUp(f, title);
6310 return LoadGame(f, gameNumber, title, FALSE);
6313 void LoadGameProc(w, event, prms, nprms)
6319 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
6322 FileNamePopUp(_("Load game file name?"), "", LoadGamePopUp, "rb");
6325 void LoadNextGameProc(w, event, prms, nprms)
6334 void LoadPrevGameProc(w, event, prms, nprms)
6343 void ReloadGameProc(w, event, prms, nprms)
6352 void LoadNextPositionProc(w, event, prms, nprms)
6361 void LoadPrevPositionProc(w, event, prms, nprms)
6370 void ReloadPositionProc(w, event, prms, nprms)
6379 void LoadPositionProc(w, event, prms, nprms)
6385 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
6388 FileNamePopUp(_("Load position file name?"), "", LoadPosition, "rb");
6391 void SaveGameProc(w, event, prms, nprms)
6397 FileNamePopUp(_("Save game file name?"),
6398 DefaultFileName(appData.oldSaveStyle ? "game" : "pgn"),
6402 void SavePositionProc(w, event, prms, nprms)
6408 FileNamePopUp(_("Save position file name?"),
6409 DefaultFileName(appData.oldSaveStyle ? "pos" : "fen"),
6413 void ReloadCmailMsgProc(w, event, prms, nprms)
6419 ReloadCmailMsgEvent(FALSE);
6422 void MailMoveProc(w, event, prms, nprms)
6431 /* this variable is shared between CopyPositionProc and SendPositionSelection */
6432 static char *selected_fen_position=NULL;
6435 SendPositionSelection(Widget w, Atom *selection, Atom *target,
6436 Atom *type_return, XtPointer *value_return,
6437 unsigned long *length_return, int *format_return)
6439 char *selection_tmp;
6441 if (!selected_fen_position) return False; /* should never happen */
6442 if (*target == XA_STRING){
6443 /* note: since no XtSelectionDoneProc was registered, Xt will
6444 * automatically call XtFree on the value returned. So have to
6445 * make a copy of it allocated with XtMalloc */
6446 selection_tmp= XtMalloc(strlen(selected_fen_position)+16);
6447 strcpy(selection_tmp, selected_fen_position);
6449 *value_return=selection_tmp;
6450 *length_return=strlen(selection_tmp);
6451 *type_return=XA_STRING;
6452 *format_return = 8; /* bits per byte */
6459 /* note: when called from menu all parameters are NULL, so no clue what the
6460 * Widget which was clicked on was, or what the click event was
6462 void CopyPositionProc(w, event, prms, nprms)
6470 if (selected_fen_position) free(selected_fen_position);
6471 selected_fen_position = (char *)PositionToFEN(currentMove, NULL);
6472 if (!selected_fen_position) return;
6473 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
6475 SendPositionSelection,
6476 NULL/* lose_ownership_proc */ ,
6477 NULL/* transfer_done_proc */);
6479 free(selected_fen_position);
6480 selected_fen_position=NULL;
6484 /* function called when the data to Paste is ready */
6486 PastePositionCB(Widget w, XtPointer client_data, Atom *selection,
6487 Atom *type, XtPointer value, unsigned long *len, int *format)
6490 if (value==NULL || *len==0) return; /* nothing had been selected to copy */
6491 fenstr[*len]='\0'; /* normally this string is terminated, but be safe */
6492 EditPositionPasteFEN(fenstr);
6496 /* called when Paste Position button is pressed,
6497 * all parameters will be NULL */
6498 void PastePositionProc(w, event, prms, nprms)
6504 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
6505 /* (XtSelectionCallbackProc) */ PastePositionCB,
6506 NULL, /* client_data passed to PastePositionCB */
6508 /* better to use the time field from the event that triggered the
6509 * call to this function, but that isn't trivial to get
6517 SendGameSelection(Widget w, Atom *selection, Atom *target,
6518 Atom *type_return, XtPointer *value_return,
6519 unsigned long *length_return, int *format_return)
6521 char *selection_tmp;
6523 if (*target == XA_STRING){
6524 FILE* f = fopen(gameCopyFilename, "r");
6527 if (f == NULL) return False;
6531 selection_tmp = XtMalloc(len + 1);
6532 count = fread(selection_tmp, 1, len, f);
6534 XtFree(selection_tmp);
6537 selection_tmp[len] = NULLCHAR;
6538 *value_return = selection_tmp;
6539 *length_return = len;
6540 *type_return = XA_STRING;
6541 *format_return = 8; /* bits per byte */
6548 /* note: when called from menu all parameters are NULL, so no clue what the
6549 * Widget which was clicked on was, or what the click event was
6551 void CopyGameProc(w, event, prms, nprms)
6559 ret = SaveGameToFile(gameCopyFilename, FALSE);
6562 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
6565 NULL/* lose_ownership_proc */ ,
6566 NULL/* transfer_done_proc */);
6569 /* function called when the data to Paste is ready */
6571 PasteGameCB(Widget w, XtPointer client_data, Atom *selection,
6572 Atom *type, XtPointer value, unsigned long *len, int *format)
6575 if (value == NULL || *len == 0) {
6576 return; /* nothing had been selected to copy */
6578 f = fopen(gamePasteFilename, "w");
6580 DisplayError(_("Can't open temp file"), errno);
6583 fwrite(value, 1, *len, f);
6586 LoadGameFromFile(gamePasteFilename, 0, gamePasteFilename, TRUE);
6589 /* called when Paste Game button is pressed,
6590 * all parameters will be NULL */
6591 void PasteGameProc(w, event, prms, nprms)
6597 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
6598 /* (XtSelectionCallbackProc) */ PasteGameCB,
6599 NULL, /* client_data passed to PasteGameCB */
6601 /* better to use the time field from the event that triggered the
6602 * call to this function, but that isn't trivial to get
6612 SaveGameProc(NULL, NULL, NULL, NULL);
6616 void QuitProc(w, event, prms, nprms)
6625 void PauseProc(w, event, prms, nprms)
6635 void MachineBlackProc(w, event, prms, nprms)
6641 MachineBlackEvent();
6644 void MachineWhiteProc(w, event, prms, nprms)
6650 MachineWhiteEvent();
6653 void AnalyzeModeProc(w, event, prms, nprms)
6661 if (!first.analysisSupport) {
6662 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
6663 DisplayError(buf, 0);
6666 /* [DM] icsEngineAnalyze [HGM] This is horrible code; reverse the gameMode and isEngineAnalyze tests! */
6667 if (appData.icsActive) {
6668 if (gameMode != IcsObserving) {
6669 sprintf(buf,_("You are not observing a game"));
6670 DisplayError(buf, 0);
6672 if (appData.icsEngineAnalyze) {
6673 if (appData.debugMode)
6674 fprintf(debugFP, _("Found unexpected active ICS engine analyze \n"));
6680 /* if enable, use want disable icsEngineAnalyze */
6681 if (appData.icsEngineAnalyze) {
6686 appData.icsEngineAnalyze = TRUE;
6687 if (appData.debugMode)
6688 fprintf(debugFP, _("ICS engine analyze starting... \n"));
6690 if (!appData.showThinking)
6691 ShowThinkingProc(w,event,prms,nprms);
6696 void AnalyzeFileProc(w, event, prms, nprms)
6702 if (!first.analysisSupport) {
6704 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
6705 DisplayError(buf, 0);
6710 if (!appData.showThinking)
6711 ShowThinkingProc(w,event,prms,nprms);
6714 FileNamePopUp(_("File to analyze"), "", LoadGamePopUp, "rb");
6715 AnalysisPeriodicEvent(1);
6718 void TwoMachinesProc(w, event, prms, nprms)
6727 void IcsClientProc(w, event, prms, nprms)
6736 void EditGameProc(w, event, prms, nprms)
6745 void EditPositionProc(w, event, prms, nprms)
6751 EditPositionEvent();
6754 void TrainingProc(w, event, prms, nprms)
6763 void EditCommentProc(w, event, prms, nprms)
6770 EditCommentPopDown();
6776 void IcsInputBoxProc(w, event, prms, nprms)
6782 if (ICSInputBoxUp) {
6783 ICSInputBoxPopDown();
6789 void AcceptProc(w, event, prms, nprms)
6798 void DeclineProc(w, event, prms, nprms)
6807 void RematchProc(w, event, prms, nprms)
6816 void CallFlagProc(w, event, prms, nprms)
6825 void DrawProc(w, event, prms, nprms)
6834 void AbortProc(w, event, prms, nprms)
6843 void AdjournProc(w, event, prms, nprms)
6852 void ResignProc(w, event, prms, nprms)
6861 void AdjuWhiteProc(w, event, prms, nprms)
6867 UserAdjudicationEvent(+1);
6870 void AdjuBlackProc(w, event, prms, nprms)
6876 UserAdjudicationEvent(-1);
6879 void AdjuDrawProc(w, event, prms, nprms)
6885 UserAdjudicationEvent(0);
6888 void EnterKeyProc(w, event, prms, nprms)
6894 if (ICSInputBoxUp == True)
6898 void StopObservingProc(w, event, prms, nprms)
6904 StopObservingEvent();
6907 void StopExaminingProc(w, event, prms, nprms)
6913 StopExaminingEvent();
6917 void ForwardProc(w, event, prms, nprms)
6927 void BackwardProc(w, event, prms, nprms)
6936 void ToStartProc(w, event, prms, nprms)
6945 void ToEndProc(w, event, prms, nprms)
6954 void RevertProc(w, event, prms, nprms)
6963 void TruncateGameProc(w, event, prms, nprms)
6969 TruncateGameEvent();
6971 void RetractMoveProc(w, event, prms, nprms)
6980 void MoveNowProc(w, event, prms, nprms)
6990 void AlwaysQueenProc(w, event, prms, nprms)
6998 appData.alwaysPromoteToQueen = !appData.alwaysPromoteToQueen;
7000 if (appData.alwaysPromoteToQueen) {
7001 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7003 XtSetArg(args[0], XtNleftBitmap, None);
7005 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
7009 void AnimateDraggingProc(w, event, prms, nprms)
7017 appData.animateDragging = !appData.animateDragging;
7019 if (appData.animateDragging) {
7020 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7023 XtSetArg(args[0], XtNleftBitmap, None);
7025 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Dragging"),
7029 void AnimateMovingProc(w, event, prms, nprms)
7037 appData.animate = !appData.animate;
7039 if (appData.animate) {
7040 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7043 XtSetArg(args[0], XtNleftBitmap, None);
7045 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
7049 void AutocommProc(w, event, prms, nprms)
7057 appData.autoComment = !appData.autoComment;
7059 if (appData.autoComment) {
7060 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7062 XtSetArg(args[0], XtNleftBitmap, None);
7064 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
7069 void AutoflagProc(w, event, prms, nprms)
7077 appData.autoCallFlag = !appData.autoCallFlag;
7079 if (appData.autoCallFlag) {
7080 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7082 XtSetArg(args[0], XtNleftBitmap, None);
7084 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
7088 void AutoflipProc(w, event, prms, nprms)
7096 appData.autoFlipView = !appData.autoFlipView;
7098 if (appData.autoFlipView) {
7099 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7101 XtSetArg(args[0], XtNleftBitmap, None);
7103 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flip View"),
7107 void AutobsProc(w, event, prms, nprms)
7115 appData.autoObserve = !appData.autoObserve;
7117 if (appData.autoObserve) {
7118 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7120 XtSetArg(args[0], XtNleftBitmap, None);
7122 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
7126 void AutoraiseProc(w, event, prms, nprms)
7134 appData.autoRaiseBoard = !appData.autoRaiseBoard;
7136 if (appData.autoRaiseBoard) {
7137 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7139 XtSetArg(args[0], XtNleftBitmap, None);
7141 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Raise Board"),
7145 void AutosaveProc(w, event, prms, nprms)
7153 appData.autoSaveGames = !appData.autoSaveGames;
7155 if (appData.autoSaveGames) {
7156 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7158 XtSetArg(args[0], XtNleftBitmap, None);
7160 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
7164 void BlindfoldProc(w, event, prms, nprms)
7172 appData.blindfold = !appData.blindfold;
7174 if (appData.blindfold) {
7175 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7177 XtSetArg(args[0], XtNleftBitmap, None);
7179 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Blindfold"),
7182 DrawPosition(True, NULL);
7185 void TestLegalityProc(w, event, prms, nprms)
7193 appData.testLegality = !appData.testLegality;
7195 if (appData.testLegality) {
7196 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7198 XtSetArg(args[0], XtNleftBitmap, None);
7200 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Test Legality"),
7205 void FlashMovesProc(w, event, prms, nprms)
7213 if (appData.flashCount == 0) {
7214 appData.flashCount = 3;
7216 appData.flashCount = -appData.flashCount;
7219 if (appData.flashCount > 0) {
7220 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7222 XtSetArg(args[0], XtNleftBitmap, None);
7224 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flash Moves"),
7228 void FlipViewProc(w, event, prms, nprms)
7234 flipView = !flipView;
7235 DrawPosition(True, NULL);
7238 void GetMoveListProc(w, event, prms, nprms)
7246 appData.getMoveList = !appData.getMoveList;
7248 if (appData.getMoveList) {
7249 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7252 XtSetArg(args[0], XtNleftBitmap, None);
7254 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
7259 void HighlightDraggingProc(w, event, prms, nprms)
7267 appData.highlightDragging = !appData.highlightDragging;
7269 if (appData.highlightDragging) {
7270 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7272 XtSetArg(args[0], XtNleftBitmap, None);
7274 XtSetValues(XtNameToWidget(menuBarWidget,
7275 "menuOptions.Highlight Dragging"), args, 1);
7279 void HighlightLastMoveProc(w, event, prms, nprms)
7287 appData.highlightLastMove = !appData.highlightLastMove;
7289 if (appData.highlightLastMove) {
7290 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7292 XtSetArg(args[0], XtNleftBitmap, None);
7294 XtSetValues(XtNameToWidget(menuBarWidget,
7295 "menuOptions.Highlight Last Move"), args, 1);
7298 void IcsAlarmProc(w, event, prms, nprms)
7306 appData.icsAlarm = !appData.icsAlarm;
7308 if (appData.icsAlarm) {
7309 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7311 XtSetArg(args[0], XtNleftBitmap, None);
7313 XtSetValues(XtNameToWidget(menuBarWidget,
7314 "menuOptions.ICS Alarm"), args, 1);
7317 void MoveSoundProc(w, event, prms, nprms)
7325 appData.ringBellAfterMoves = !appData.ringBellAfterMoves;
7327 if (appData.ringBellAfterMoves) {
7328 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7330 XtSetArg(args[0], XtNleftBitmap, None);
7332 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
7337 void OldSaveStyleProc(w, event, prms, nprms)
7345 appData.oldSaveStyle = !appData.oldSaveStyle;
7347 if (appData.oldSaveStyle) {
7348 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7350 XtSetArg(args[0], XtNleftBitmap, None);
7352 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Old Save Style"),
7356 void PeriodicUpdatesProc(w, event, prms, nprms)
7364 PeriodicUpdatesEvent(!appData.periodicUpdates);
7366 if (appData.periodicUpdates) {
7367 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7369 XtSetArg(args[0], XtNleftBitmap, None);
7371 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Periodic Updates"),
7375 void PonderNextMoveProc(w, event, prms, nprms)
7383 PonderNextMoveEvent(!appData.ponderNextMove);
7385 if (appData.ponderNextMove) {
7386 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7388 XtSetArg(args[0], XtNleftBitmap, None);
7390 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Ponder Next Move"),
7394 void PopupExitMessageProc(w, event, prms, nprms)
7402 appData.popupExitMessage = !appData.popupExitMessage;
7404 if (appData.popupExitMessage) {
7405 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7407 XtSetArg(args[0], XtNleftBitmap, None);
7409 XtSetValues(XtNameToWidget(menuBarWidget,
7410 "menuOptions.Popup Exit Message"), args, 1);
7413 void PopupMoveErrorsProc(w, event, prms, nprms)
7421 appData.popupMoveErrors = !appData.popupMoveErrors;
7423 if (appData.popupMoveErrors) {
7424 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7426 XtSetArg(args[0], XtNleftBitmap, None);
7428 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Popup Move Errors"),
7432 void PremoveProc(w, event, prms, nprms)
7440 appData.premove = !appData.premove;
7442 if (appData.premove) {
7443 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7445 XtSetArg(args[0], XtNleftBitmap, None);
7447 XtSetValues(XtNameToWidget(menuBarWidget,
7448 "menuOptions.Premove"), args, 1);
7451 void QuietPlayProc(w, event, prms, nprms)
7459 appData.quietPlay = !appData.quietPlay;
7461 if (appData.quietPlay) {
7462 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7464 XtSetArg(args[0], XtNleftBitmap, None);
7466 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Quiet Play"),
7470 void ShowCoordsProc(w, event, prms, nprms)
7478 appData.showCoords = !appData.showCoords;
7480 if (appData.showCoords) {
7481 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7483 XtSetArg(args[0], XtNleftBitmap, None);
7485 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
7488 DrawPosition(True, NULL);
7491 void ShowThinkingProc(w, event, prms, nprms)
7499 appData.showThinking = !appData.showThinking; // [HGM] thinking: tken out of ShowThinkingEvent
7500 ShowThinkingEvent();
7502 // [HGM] thinking: currently no suc menu item; replaced by Hide Thinking (From Human)
7503 if (appData.showThinking) {
7504 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7506 XtSetArg(args[0], XtNleftBitmap, None);
7508 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Thinking"),
7513 void HideThinkingProc(w, event, prms, nprms)
7521 appData.hideThinkingFromHuman = !appData.hideThinkingFromHuman; // [HGM] thinking: tken out of ShowThinkingEvent
7522 ShowThinkingEvent();
7524 if (appData.hideThinkingFromHuman) {
7525 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7527 XtSetArg(args[0], XtNleftBitmap, None);
7529 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
7533 void InfoProc(w, event, prms, nprms)
7540 snprintf(buf, sizeof(buf), "xterm -e info --directory %s --directory . -f %s &",
7545 void ManProc(w, event, prms, nprms)
7553 if (nprms && *nprms > 0)
7557 snprintf(buf, sizeof(buf), "xterm -e man %s &", name);
7561 void HintProc(w, event, prms, nprms)
7570 void BookProc(w, event, prms, nprms)
7579 void AboutProc(w, event, prms, nprms)
7587 char *zippy = " (with Zippy code)";
7591 snprintf(buf, sizeof(buf), "%s%s\n\n%s\n%s\n%s\n\n%s%s\n%s",
7592 programVersion, zippy,
7593 "Copyright 1991 Digital Equipment Corporation",
7594 "Enhancements Copyright 1992-2009 Free Software Foundation",
7595 "Enhancements Copyright 2005 Alessandro Scotti",
7596 PACKAGE, " is free software and carries NO WARRANTY;",
7597 "see the file COPYING for more information.");
7598 ErrorPopUp(_("About XBoard"), buf, FALSE);
7601 void DebugProc(w, event, prms, nprms)
7607 appData.debugMode = !appData.debugMode;
7610 void AboutGameProc(w, event, prms, nprms)
7619 void NothingProc(w, event, prms, nprms)
7628 void Iconify(w, event, prms, nprms)
7637 XtSetArg(args[0], XtNiconic, True);
7638 XtSetValues(shellWidget, args, 1);
7641 void DisplayMessage(message, extMessage)
7642 char *message, *extMessage;
7644 /* display a message in the message widget */
7653 snprintf(buf, sizeof(buf), "%s %s", message, extMessage);
7658 message = extMessage;
7662 /* need to test if messageWidget already exists, since this function
7663 can also be called during the startup, if for example a Xresource
7664 is not set up correctly */
7667 XtSetArg(arg, XtNlabel, message);
7668 XtSetValues(messageWidget, &arg, 1);
7674 void DisplayTitle(text)
7679 char title[MSG_SIZ];
7682 if (text == NULL) text = "";
7684 if (appData.titleInWindow) {
7686 XtSetArg(args[i], XtNlabel, text); i++;
7687 XtSetValues(titleWidget, args, i);
7690 if (*text != NULLCHAR) {
7692 strcpy(title, text);
7693 } else if (appData.icsActive) {
7694 snprintf(icon, sizeof(icon), "%s", appData.icsHost);
7695 snprintf(title, sizeof(title), "%s: %s", programName, appData.icsHost);
7696 } else if (appData.cmailGameName[0] != NULLCHAR) {
7697 snprintf(icon, sizeof(icon), "%s", "CMail");
7698 snprintf(title,sizeof(title), "%s: %s", programName, "CMail");
7700 // [HGM] license: This stuff should really be done in back-end, but WinBoard already had a pop-up for it
7701 } else if (gameInfo.variant == VariantGothic) {
7702 strcpy(icon, programName);
7703 strcpy(title, GOTHIC);
7706 } else if (gameInfo.variant == VariantFalcon) {
7707 strcpy(icon, programName);
7708 strcpy(title, FALCON);
7710 } else if (appData.noChessProgram) {
7711 strcpy(icon, programName);
7712 strcpy(title, programName);
7714 strcpy(icon, first.tidy);
7715 snprintf(title,sizeof(title), "%s: %s", programName, first.tidy);
7718 XtSetArg(args[i], XtNiconName, (XtArgVal) icon); i++;
7719 XtSetArg(args[i], XtNtitle, (XtArgVal) title); i++;
7720 XtSetValues(shellWidget, args, i);
7724 void DisplayError(message, error)
7731 if (appData.debugMode || appData.matchMode) {
7732 fprintf(stderr, "%s: %s\n", programName, message);
7735 if (appData.debugMode || appData.matchMode) {
7736 fprintf(stderr, "%s: %s: %s\n",
7737 programName, message, strerror(error));
7739 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
7742 ErrorPopUp(_("Error"), message, FALSE);
7746 void DisplayMoveError(message)
7751 DrawPosition(FALSE, NULL);
7752 if (appData.debugMode || appData.matchMode) {
7753 fprintf(stderr, "%s: %s\n", programName, message);
7755 if (appData.popupMoveErrors) {
7756 ErrorPopUp(_("Error"), message, FALSE);
7758 DisplayMessage(message, "");
7763 void DisplayFatalError(message, error, status)
7769 errorExitStatus = status;
7771 fprintf(stderr, "%s: %s\n", programName, message);
7773 fprintf(stderr, "%s: %s: %s\n",
7774 programName, message, strerror(error));
7775 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
7778 if (appData.popupExitMessage && boardWidget && XtIsRealized(boardWidget)) {
7779 ErrorPopUp(status ? _("Fatal Error") : _("Exiting"), message, TRUE);
7785 void DisplayInformation(message)
7789 ErrorPopUp(_("Information"), message, TRUE);
7792 void DisplayNote(message)
7796 ErrorPopUp(_("Note"), message, FALSE);
7800 NullXErrorCheck(dpy, error_event)
7802 XErrorEvent *error_event;
7807 void DisplayIcsInteractionTitle(message)
7810 if (oldICSInteractionTitle == NULL) {
7811 /* Magic to find the old window title, adapted from vim */
7812 char *wina = getenv("WINDOWID");
7814 Window win = (Window) atoi(wina);
7815 Window root, parent, *children;
7816 unsigned int nchildren;
7817 int (*oldHandler)() = XSetErrorHandler(NullXErrorCheck);
7819 if (XFetchName(xDisplay, win, &oldICSInteractionTitle)) break;
7820 if (!XQueryTree(xDisplay, win, &root, &parent,
7821 &children, &nchildren)) break;
7822 if (children) XFree((void *)children);
7823 if (parent == root || parent == 0) break;
7826 XSetErrorHandler(oldHandler);
7828 if (oldICSInteractionTitle == NULL) {
7829 oldICSInteractionTitle = "xterm";
7832 printf("\033]0;%s\007", message);
7836 char pendingReplyPrefix[MSG_SIZ];
7837 ProcRef pendingReplyPR;
7839 void AskQuestionProc(w, event, prms, nprms)
7846 fprintf(stderr, _("AskQuestionProc needed 4 parameters, got %d\n"),
7850 AskQuestionEvent(prms[0], prms[1], prms[2], prms[3]);
7853 void AskQuestionPopDown()
7855 if (!askQuestionUp) return;
7856 XtPopdown(askQuestionShell);
7857 XtDestroyWidget(askQuestionShell);
7858 askQuestionUp = False;
7861 void AskQuestionReplyAction(w, event, prms, nprms)
7871 reply = XawDialogGetValueString(w = XtParent(w));
7872 strcpy(buf, pendingReplyPrefix);
7873 if (*buf) strcat(buf, " ");
7876 OutputToProcess(pendingReplyPR, buf, strlen(buf), &err);
7877 AskQuestionPopDown();
7879 if (err) DisplayFatalError(_("Error writing to chess program"), err, 0);
7882 void AskQuestionCallback(w, client_data, call_data)
7884 XtPointer client_data, call_data;
7889 XtSetArg(args[0], XtNlabel, &name);
7890 XtGetValues(w, args, 1);
7892 if (strcmp(name, _("cancel")) == 0) {
7893 AskQuestionPopDown();
7895 AskQuestionReplyAction(w, NULL, NULL, NULL);
7899 void AskQuestion(title, question, replyPrefix, pr)
7900 char *title, *question, *replyPrefix;
7904 Widget popup, layout, dialog, edit;
7910 strcpy(pendingReplyPrefix, replyPrefix);
7911 pendingReplyPR = pr;
7914 XtSetArg(args[i], XtNresizable, True); i++;
7915 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
7916 askQuestionShell = popup =
7917 XtCreatePopupShell(title, transientShellWidgetClass,
7918 shellWidget, args, i);
7921 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
7922 layoutArgs, XtNumber(layoutArgs));
7925 XtSetArg(args[i], XtNlabel, question); i++;
7926 XtSetArg(args[i], XtNvalue, ""); i++;
7927 XtSetArg(args[i], XtNborderWidth, 0); i++;
7928 dialog = XtCreateManagedWidget("question", dialogWidgetClass,
7931 XawDialogAddButton(dialog, _("enter"), AskQuestionCallback,
7932 (XtPointer) dialog);
7933 XawDialogAddButton(dialog, _("cancel"), AskQuestionCallback,
7934 (XtPointer) dialog);
7936 XtRealizeWidget(popup);
7937 CatchDeleteWindow(popup, "AskQuestionPopDown");
7939 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
7940 &x, &y, &win_x, &win_y, &mask);
7942 XtSetArg(args[0], XtNx, x - 10);
7943 XtSetArg(args[1], XtNy, y - 30);
7944 XtSetValues(popup, args, 2);
7946 XtPopup(popup, XtGrabExclusive);
7947 askQuestionUp = True;
7949 edit = XtNameToWidget(dialog, "*value");
7950 XtSetKeyboardFocus(popup, edit);
7958 if (*name == NULLCHAR) {
7960 } else if (strcmp(name, "$") == 0) {
7961 putc(BELLCHAR, stderr);
7964 snprintf(buf, sizeof(buf), "%s '%s' &", appData.soundProgram, name);
7972 PlaySound(appData.soundMove);
7978 PlaySound(appData.soundIcsWin);
7984 PlaySound(appData.soundIcsLoss);
7990 PlaySound(appData.soundIcsDraw);
7994 PlayIcsUnfinishedSound()
7996 PlaySound(appData.soundIcsUnfinished);
8002 PlaySound(appData.soundIcsAlarm);
8008 system("stty echo");
8014 system("stty -echo");
8018 Colorize(cc, continuation)
8023 int count, outCount, error;
8025 if (textColors[(int)cc].bg > 0) {
8026 if (textColors[(int)cc].fg > 0) {
8027 sprintf(buf, "\033[0;%d;%d;%dm", textColors[(int)cc].attr,
8028 textColors[(int)cc].fg, textColors[(int)cc].bg);
8030 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
8031 textColors[(int)cc].bg);
8034 if (textColors[(int)cc].fg > 0) {
8035 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
8036 textColors[(int)cc].fg);
8038 sprintf(buf, "\033[0;%dm", textColors[(int)cc].attr);
8041 count = strlen(buf);
8042 outCount = OutputToProcess(NoProc, buf, count, &error);
8043 if (outCount < count) {
8044 DisplayFatalError(_("Error writing to display"), error, 1);
8047 if (continuation) return;
8050 PlaySound(appData.soundShout);
8053 PlaySound(appData.soundSShout);
8056 PlaySound(appData.soundChannel1);
8059 PlaySound(appData.soundChannel);
8062 PlaySound(appData.soundKibitz);
8065 PlaySound(appData.soundTell);
8067 case ColorChallenge:
8068 PlaySound(appData.soundChallenge);
8071 PlaySound(appData.soundRequest);
8074 PlaySound(appData.soundSeek);
8085 return getpwuid(getuid())->pw_name;
8088 static char *ExpandPathName(path)
8091 static char static_buf[2000];
8092 char *d, *s, buf[2000];
8098 while (*s && isspace(*s))
8107 if (*(s+1) == '/') {
8108 strcpy(d, getpwuid(getuid())->pw_dir);
8113 *strchr(buf, '/') = 0;
8114 pwd = getpwnam(buf);
8117 fprintf(stderr, _("ERROR: Unknown user %s (in path %s)\n"),
8121 strcpy(d, pwd->pw_dir);
8122 strcat(d, strchr(s+1, '/'));
8133 static char host_name[MSG_SIZ];
8135 #if HAVE_GETHOSTNAME
8136 gethostname(host_name, MSG_SIZ);
8138 #else /* not HAVE_GETHOSTNAME */
8139 # if HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H
8140 sysinfo(SI_HOSTNAME, host_name, MSG_SIZ);
8142 # else /* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
8144 # endif/* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
8145 #endif /* not HAVE_GETHOSTNAME */
8148 XtIntervalId delayedEventTimerXID = 0;
8149 DelayedEventCallback delayedEventCallback = 0;
8154 delayedEventTimerXID = 0;
8155 delayedEventCallback();
8159 ScheduleDelayedEvent(cb, millisec)
8160 DelayedEventCallback cb; long millisec;
8162 if(delayedEventTimerXID && delayedEventCallback == cb)
8163 // [HGM] alive: replace, rather than add or flush identical event
8164 XtRemoveTimeOut(delayedEventTimerXID);
8165 delayedEventCallback = cb;
8166 delayedEventTimerXID =
8167 XtAppAddTimeOut(appContext, millisec,
8168 (XtTimerCallbackProc) FireDelayedEvent, (XtPointer) 0);
8171 DelayedEventCallback
8174 if (delayedEventTimerXID) {
8175 return delayedEventCallback;
8182 CancelDelayedEvent()
8184 if (delayedEventTimerXID) {
8185 XtRemoveTimeOut(delayedEventTimerXID);
8186 delayedEventTimerXID = 0;
8190 XtIntervalId loadGameTimerXID = 0;
8192 int LoadGameTimerRunning()
8194 return loadGameTimerXID != 0;
8197 int StopLoadGameTimer()
8199 if (loadGameTimerXID != 0) {
8200 XtRemoveTimeOut(loadGameTimerXID);
8201 loadGameTimerXID = 0;
8209 LoadGameTimerCallback(arg, id)
8213 loadGameTimerXID = 0;
8218 StartLoadGameTimer(millisec)
8222 XtAppAddTimeOut(appContext, millisec,
8223 (XtTimerCallbackProc) LoadGameTimerCallback,
8227 XtIntervalId analysisClockXID = 0;
8230 AnalysisClockCallback(arg, id)
8234 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile
8235 || appData.icsEngineAnalyze) { // [DM]
8236 AnalysisPeriodicEvent(0);
8237 StartAnalysisClock();
8242 StartAnalysisClock()
8245 XtAppAddTimeOut(appContext, 2000,
8246 (XtTimerCallbackProc) AnalysisClockCallback,
8250 XtIntervalId clockTimerXID = 0;
8252 int ClockTimerRunning()
8254 return clockTimerXID != 0;
8257 int StopClockTimer()
8259 if (clockTimerXID != 0) {
8260 XtRemoveTimeOut(clockTimerXID);
8269 ClockTimerCallback(arg, id)
8278 StartClockTimer(millisec)
8282 XtAppAddTimeOut(appContext, millisec,
8283 (XtTimerCallbackProc) ClockTimerCallback,
8288 DisplayTimerLabel(w, color, timer, highlight)
8297 /* check for low time warning */
8298 Pixel foregroundOrWarningColor = timerForegroundPixel;
8301 appData.lowTimeWarning &&
8302 (timer / 1000) < appData.icsAlarmTime)
8303 foregroundOrWarningColor = lowTimeWarningColor;
8305 if (appData.clockMode) {
8306 sprintf(buf, "%s: %s", color, TimeString(timer));
8307 XtSetArg(args[0], XtNlabel, buf);
8309 sprintf(buf, "%s ", color);
8310 XtSetArg(args[0], XtNlabel, buf);
8315 XtSetArg(args[1], XtNbackground, foregroundOrWarningColor);
8316 XtSetArg(args[2], XtNforeground, timerBackgroundPixel);
8318 XtSetArg(args[1], XtNbackground, timerBackgroundPixel);
8319 XtSetArg(args[2], XtNforeground, foregroundOrWarningColor);
8322 XtSetValues(w, args, 3);
8326 DisplayWhiteClock(timeRemaining, highlight)
8332 if(appData.noGUI) return;
8333 DisplayTimerLabel(whiteTimerWidget, _("White"), timeRemaining, highlight);
8334 if (highlight && iconPixmap == bIconPixmap) {
8335 iconPixmap = wIconPixmap;
8336 XtSetArg(args[0], XtNiconPixmap, iconPixmap);
8337 XtSetValues(shellWidget, args, 1);
8342 DisplayBlackClock(timeRemaining, highlight)
8348 if(appData.noGUI) return;
8349 DisplayTimerLabel(blackTimerWidget, _("Black"), timeRemaining, highlight);
8350 if (highlight && iconPixmap == wIconPixmap) {
8351 iconPixmap = bIconPixmap;
8352 XtSetArg(args[0], XtNiconPixmap, iconPixmap);
8353 XtSetValues(shellWidget, args, 1);
8371 int StartChildProcess(cmdLine, dir, pr)
8378 int to_prog[2], from_prog[2];
8382 if (appData.debugMode) {
8383 fprintf(stderr, "StartChildProcess (dir=\"%s\") %s\n",dir, cmdLine);
8386 /* We do NOT feed the cmdLine to the shell; we just
8387 parse it into blank-separated arguments in the
8388 most simple-minded way possible.
8391 strcpy(buf, cmdLine);
8396 if (p == NULL) break;
8401 SetUpChildIO(to_prog, from_prog);
8403 if ((pid = fork()) == 0) {
8405 // [HGM] PSWBTM: made order resistant against case where fd of created pipe was 0 or 1
8406 close(to_prog[1]); // first close the unused pipe ends
8407 close(from_prog[0]);
8408 dup2(to_prog[0], 0); // to_prog was created first, nd is the only one to use 0 or 1
8409 dup2(from_prog[1], 1);
8410 if(to_prog[0] >= 2) close(to_prog[0]); // if 0 or 1, the dup2 already cosed the original
8411 close(from_prog[1]); // and closing again loses one of the pipes!
8412 if(fileno(stderr) >= 2) // better safe than sorry...
8413 dup2(1, fileno(stderr)); /* force stderr to the pipe */
8415 if (dir[0] != NULLCHAR && chdir(dir) != 0) {
8420 nice(appData.niceEngines); // [HGM] nice: adjust priority of engine proc
8422 execvp(argv[0], argv);
8424 /* If we get here, exec failed */
8429 /* Parent process */
8431 close(from_prog[1]);
8433 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8436 cp->fdFrom = from_prog[0];
8437 cp->fdTo = to_prog[1];
8442 // [HGM] kill: implement the 'hard killing' of AS's Winboard_x
8443 static RETSIGTYPE AlarmCallBack(int n)
8449 DestroyChildProcess(pr, signalType)
8453 ChildProc *cp = (ChildProc *) pr;
8455 if (cp->kind != CPReal) return;
8457 if (signalType == 10) { // [HGM] kill: if it does not terminate in 3 sec, kill
8458 signal(SIGALRM, AlarmCallBack);
8460 if(wait((int *) 0) == -1) { // process does not terminate on its own accord
8461 kill(cp->pid, SIGKILL); // kill it forcefully
8462 wait((int *) 0); // and wait again
8466 kill(cp->pid, signalType == 9 ? SIGKILL : SIGTERM); // [HGM] kill: use hard kill if so requested
8468 /* Process is exiting either because of the kill or because of
8469 a quit command sent by the backend; either way, wait for it to die.
8478 InterruptChildProcess(pr)
8481 ChildProc *cp = (ChildProc *) pr;
8483 if (cp->kind != CPReal) return;
8484 (void) kill(cp->pid, SIGINT); /* stop it thinking */
8487 int OpenTelnet(host, port, pr)
8492 char cmdLine[MSG_SIZ];
8494 if (port[0] == NULLCHAR) {
8495 snprintf(cmdLine, sizeof(cmdLine), "%s %s", appData.telnetProgram, host);
8497 snprintf(cmdLine, sizeof(cmdLine), "%s %s %s", appData.telnetProgram, host, port);
8499 return StartChildProcess(cmdLine, "", pr);
8502 int OpenTCP(host, port, pr)
8508 DisplayFatalError(_("Socket support is not configured in"), 0, 2);
8509 #else /* !OMIT_SOCKETS */
8511 struct sockaddr_in sa;
8513 unsigned short uport;
8516 if ((s = socket(AF_INET, SOCK_STREAM, 6)) < 0) {
8520 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
8521 sa.sin_family = AF_INET;
8522 sa.sin_addr.s_addr = INADDR_ANY;
8523 uport = (unsigned short) 0;
8524 sa.sin_port = htons(uport);
8525 if (bind(s, (struct sockaddr *) &sa, sizeof(struct sockaddr_in)) < 0) {
8529 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
8530 if (!(hp = gethostbyname(host))) {
8532 if (sscanf(host, "%d.%d.%d.%d", &b0, &b1, &b2, &b3) == 4) {
8533 hp = (struct hostent *) calloc(1, sizeof(struct hostent));
8534 hp->h_addrtype = AF_INET;
8536 hp->h_addr_list = (char **) calloc(2, sizeof(char *));
8537 hp->h_addr_list[0] = (char *) malloc(4);
8538 hp->h_addr_list[0][0] = b0;
8539 hp->h_addr_list[0][1] = b1;
8540 hp->h_addr_list[0][2] = b2;
8541 hp->h_addr_list[0][3] = b3;
8546 sa.sin_family = hp->h_addrtype;
8547 uport = (unsigned short) atoi(port);
8548 sa.sin_port = htons(uport);
8549 memcpy((char *) &sa.sin_addr, hp->h_addr, hp->h_length);
8551 if (connect(s, (struct sockaddr *) &sa,
8552 sizeof(struct sockaddr_in)) < 0) {
8556 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8563 #endif /* !OMIT_SOCKETS */
8568 int OpenCommPort(name, pr)
8575 fd = open(name, 2, 0);
8576 if (fd < 0) return errno;
8578 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8588 int OpenLoopback(pr)
8594 SetUpChildIO(to, from);
8596 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8599 cp->fdFrom = to[0]; /* note not from[0]; we are doing a loopback */
8606 int OpenRcmd(host, user, cmd, pr)
8607 char *host, *user, *cmd;
8610 DisplayFatalError(_("internal rcmd not implemented for Unix"), 0, 1);
8614 #define INPUT_SOURCE_BUF_SIZE 8192
8623 char buf[INPUT_SOURCE_BUF_SIZE];
8628 DoInputCallback(closure, source, xid)
8633 InputSource *is = (InputSource *) closure;
8638 if (is->lineByLine) {
8639 count = read(is->fd, is->unused,
8640 INPUT_SOURCE_BUF_SIZE - (is->unused - is->buf));
8642 (is->func)(is, is->closure, is->buf, count, count ? errno : 0);
8645 is->unused += count;
8647 while (p < is->unused) {
8648 q = memchr(p, '\n', is->unused - p);
8649 if (q == NULL) break;
8651 (is->func)(is, is->closure, p, q - p, 0);
8655 while (p < is->unused) {
8660 count = read(is->fd, is->buf, INPUT_SOURCE_BUF_SIZE);
8665 (is->func)(is, is->closure, is->buf, count, error);
8669 InputSourceRef AddInputSource(pr, lineByLine, func, closure)
8676 ChildProc *cp = (ChildProc *) pr;
8678 is = (InputSource *) calloc(1, sizeof(InputSource));
8679 is->lineByLine = lineByLine;
8683 is->fd = fileno(stdin);
8685 is->kind = cp->kind;
8686 is->fd = cp->fdFrom;
8689 is->unused = is->buf;
8692 is->xid = XtAppAddInput(appContext, is->fd,
8693 (XtPointer) (XtInputReadMask),
8694 (XtInputCallbackProc) DoInputCallback,
8696 is->closure = closure;
8697 return (InputSourceRef) is;
8701 RemoveInputSource(isr)
8704 InputSource *is = (InputSource *) isr;
8706 if (is->xid == 0) return;
8707 XtRemoveInput(is->xid);
8711 int OutputToProcess(pr, message, count, outError)
8717 ChildProc *cp = (ChildProc *) pr;
8721 outCount = fwrite(message, 1, count, stdout);
8723 outCount = write(cp->fdTo, message, count);
8733 /* Output message to process, with "ms" milliseconds of delay
8734 between each character. This is needed when sending the logon
8735 script to ICC, which for some reason doesn't like the
8736 instantaneous send. */
8737 int OutputToProcessDelayed(pr, message, count, outError, msdelay)
8744 ChildProc *cp = (ChildProc *) pr;
8749 r = write(cp->fdTo, message++, 1);
8762 /**** Animation code by Hugh Fisher, DCS, ANU.
8764 Known problem: if a window overlapping the board is
8765 moved away while a piece is being animated underneath,
8766 the newly exposed area won't be updated properly.
8767 I can live with this.
8769 Known problem: if you look carefully at the animation
8770 of pieces in mono mode, they are being drawn as solid
8771 shapes without interior detail while moving. Fixing
8772 this would be a major complication for minimal return.
8775 /* Masks for XPM pieces. Black and white pieces can have
8776 different shapes, but in the interest of retaining my
8777 sanity pieces must have the same outline on both light
8778 and dark squares, and all pieces must use the same
8779 background square colors/images. */
8781 static int xpmDone = 0;
8784 CreateAnimMasks (pieceDepth)
8791 unsigned long plane;
8794 /* Need a bitmap just to get a GC with right depth */
8795 buf = XCreatePixmap(xDisplay, xBoardWindow,
8797 values.foreground = 1;
8798 values.background = 0;
8799 /* Don't use XtGetGC, not read only */
8800 maskGC = XCreateGC(xDisplay, buf,
8801 GCForeground | GCBackground, &values);
8802 XFreePixmap(xDisplay, buf);
8804 buf = XCreatePixmap(xDisplay, xBoardWindow,
8805 squareSize, squareSize, pieceDepth);
8806 values.foreground = XBlackPixel(xDisplay, xScreen);
8807 values.background = XWhitePixel(xDisplay, xScreen);
8808 bufGC = XCreateGC(xDisplay, buf,
8809 GCForeground | GCBackground, &values);
8811 for (piece = WhitePawn; piece <= BlackKing; piece++) {
8812 /* Begin with empty mask */
8813 if(!xpmDone) // [HGM] pieces: keep using existing
8814 xpmMask[piece] = XCreatePixmap(xDisplay, xBoardWindow,
8815 squareSize, squareSize, 1);
8816 XSetFunction(xDisplay, maskGC, GXclear);
8817 XFillRectangle(xDisplay, xpmMask[piece], maskGC,
8818 0, 0, squareSize, squareSize);
8820 /* Take a copy of the piece */
8825 XSetFunction(xDisplay, bufGC, GXcopy);
8826 XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % (int)BlackPawn],
8828 0, 0, squareSize, squareSize, 0, 0);
8830 /* XOR the background (light) over the piece */
8831 XSetFunction(xDisplay, bufGC, GXxor);
8833 XCopyArea(xDisplay, xpmLightSquare, buf, bufGC,
8834 0, 0, squareSize, squareSize, 0, 0);
8836 XSetForeground(xDisplay, bufGC, lightSquareColor);
8837 XFillRectangle(xDisplay, buf, bufGC, 0, 0, squareSize, squareSize);
8840 /* We now have an inverted piece image with the background
8841 erased. Construct mask by just selecting all the non-zero
8842 pixels - no need to reconstruct the original image. */
8843 XSetFunction(xDisplay, maskGC, GXor);
8845 /* Might be quicker to download an XImage and create bitmap
8846 data from it rather than this N copies per piece, but it
8847 only takes a fraction of a second and there is a much
8848 longer delay for loading the pieces. */
8849 for (n = 0; n < pieceDepth; n ++) {
8850 XCopyPlane(xDisplay, buf, xpmMask[piece], maskGC,
8851 0, 0, squareSize, squareSize,
8857 XFreePixmap(xDisplay, buf);
8858 XFreeGC(xDisplay, bufGC);
8859 XFreeGC(xDisplay, maskGC);
8863 InitAnimState (anim, info)
8865 XWindowAttributes * info;
8870 /* Each buffer is square size, same depth as window */
8871 anim->saveBuf = XCreatePixmap(xDisplay, xBoardWindow,
8872 squareSize, squareSize, info->depth);
8873 anim->newBuf = XCreatePixmap(xDisplay, xBoardWindow,
8874 squareSize, squareSize, info->depth);
8876 /* Create a plain GC for blitting */
8877 mask = GCForeground | GCBackground | GCFunction |
8878 GCPlaneMask | GCGraphicsExposures;
8879 values.foreground = XBlackPixel(xDisplay, xScreen);
8880 values.background = XWhitePixel(xDisplay, xScreen);
8881 values.function = GXcopy;
8882 values.plane_mask = AllPlanes;
8883 values.graphics_exposures = False;
8884 anim->blitGC = XCreateGC(xDisplay, xBoardWindow, mask, &values);
8886 /* Piece will be copied from an existing context at
8887 the start of each new animation/drag. */
8888 anim->pieceGC = XCreateGC(xDisplay, xBoardWindow, 0, &values);
8890 /* Outline will be a read-only copy of an existing */
8891 anim->outlineGC = None;
8897 static VariantClass old = (VariantClass) -1; // [HGM] pieces: redo every time variant changes
8898 XWindowAttributes info;
8900 if (xpmDone && gameInfo.variant == old) return;
8901 if(xpmDone) old = gameInfo.variant; // first time pieces might not be created yet
8902 XGetWindowAttributes(xDisplay, xBoardWindow, &info);
8904 InitAnimState(&game, &info);
8905 InitAnimState(&player, &info);
8907 /* For XPM pieces, we need bitmaps to use as masks. */
8909 CreateAnimMasks(info.depth);
8915 static Boolean frameWaiting;
8917 static RETSIGTYPE FrameAlarm (sig)
8920 frameWaiting = False;
8921 /* In case System-V style signals. Needed?? */
8922 signal(SIGALRM, FrameAlarm);
8929 struct itimerval delay;
8931 XSync(xDisplay, False);
8934 frameWaiting = True;
8935 signal(SIGALRM, FrameAlarm);
8936 delay.it_interval.tv_sec =
8937 delay.it_value.tv_sec = time / 1000;
8938 delay.it_interval.tv_usec =
8939 delay.it_value.tv_usec = (time % 1000) * 1000;
8940 setitimer(ITIMER_REAL, &delay, NULL);
8942 /* Ugh -- busy-wait! --tpm */
8943 while (frameWaiting);
8945 while (frameWaiting) pause();
8947 delay.it_interval.tv_sec = delay.it_value.tv_sec = 0;
8948 delay.it_interval.tv_usec = delay.it_value.tv_usec = 0;
8949 setitimer(ITIMER_REAL, &delay, NULL);
8959 XSync(xDisplay, False);
8961 usleep(time * 1000);
8966 /* Convert board position to corner of screen rect and color */
8969 ScreenSquare(column, row, pt, color)
8970 int column; int row; XPoint * pt; int * color;
8973 pt->x = lineGap + ((BOARD_WIDTH-1)-column) * (squareSize + lineGap);
8974 pt->y = lineGap + row * (squareSize + lineGap);
8976 pt->x = lineGap + column * (squareSize + lineGap);
8977 pt->y = lineGap + ((BOARD_HEIGHT-1)-row) * (squareSize + lineGap);
8979 *color = SquareColor(row, column);
8982 /* Convert window coords to square */
8985 BoardSquare(x, y, column, row)
8986 int x; int y; int * column; int * row;
8988 *column = EventToSquare(x, BOARD_WIDTH);
8989 if (flipView && *column >= 0)
8990 *column = BOARD_WIDTH - 1 - *column;
8991 *row = EventToSquare(y, BOARD_HEIGHT);
8992 if (!flipView && *row >= 0)
8993 *row = BOARD_HEIGHT - 1 - *row;
8998 #undef Max /* just in case */
9000 #define Max(a, b) ((a) > (b) ? (a) : (b))
9001 #define Min(a, b) ((a) < (b) ? (a) : (b))
9004 SetRect(rect, x, y, width, height)
9005 XRectangle * rect; int x; int y; int width; int height;
9009 rect->width = width;
9010 rect->height = height;
9013 /* Test if two frames overlap. If they do, return
9014 intersection rect within old and location of
9015 that rect within new. */
9018 Intersect(old, new, size, area, pt)
9019 XPoint * old; XPoint * new;
9020 int size; XRectangle * area; XPoint * pt;
9022 if (old->x > new->x + size || new->x > old->x + size ||
9023 old->y > new->y + size || new->y > old->y + size) {
9026 SetRect(area, Max(new->x - old->x, 0), Max(new->y - old->y, 0),
9027 size - abs(old->x - new->x), size - abs(old->y - new->y));
9028 pt->x = Max(old->x - new->x, 0);
9029 pt->y = Max(old->y - new->y, 0);
9034 /* For two overlapping frames, return the rect(s)
9035 in the old that do not intersect with the new. */
9038 CalcUpdateRects(old, new, size, update, nUpdates)
9039 XPoint * old; XPoint * new; int size;
9040 XRectangle update[]; int * nUpdates;
9044 /* If old = new (shouldn't happen) then nothing to draw */
9045 if (old->x == new->x && old->y == new->y) {
9049 /* Work out what bits overlap. Since we know the rects
9050 are the same size we don't need a full intersect calc. */
9052 /* Top or bottom edge? */
9053 if (new->y > old->y) {
9054 SetRect(&(update[count]), old->x, old->y, size, new->y - old->y);
9056 } else if (old->y > new->y) {
9057 SetRect(&(update[count]), old->x, old->y + size - (old->y - new->y),
9058 size, old->y - new->y);
9061 /* Left or right edge - don't overlap any update calculated above. */
9062 if (new->x > old->x) {
9063 SetRect(&(update[count]), old->x, Max(new->y, old->y),
9064 new->x - old->x, size - abs(new->y - old->y));
9066 } else if (old->x > new->x) {
9067 SetRect(&(update[count]), new->x + size, Max(new->y, old->y),
9068 old->x - new->x, size - abs(new->y - old->y));
9075 /* Generate a series of frame coords from start->mid->finish.
9076 The movement rate doubles until the half way point is
9077 reached, then halves back down to the final destination,
9078 which gives a nice slow in/out effect. The algorithmn
9079 may seem to generate too many intermediates for short
9080 moves, but remember that the purpose is to attract the
9081 viewers attention to the piece about to be moved and
9082 then to where it ends up. Too few frames would be less
9086 Tween(start, mid, finish, factor, frames, nFrames)
9087 XPoint * start; XPoint * mid;
9088 XPoint * finish; int factor;
9089 XPoint frames[]; int * nFrames;
9091 int fraction, n, count;
9095 /* Slow in, stepping 1/16th, then 1/8th, ... */
9097 for (n = 0; n < factor; n++)
9099 for (n = 0; n < factor; n++) {
9100 frames[count].x = start->x + (mid->x - start->x) / fraction;
9101 frames[count].y = start->y + (mid->y - start->y) / fraction;
9103 fraction = fraction / 2;
9107 frames[count] = *mid;
9110 /* Slow out, stepping 1/2, then 1/4, ... */
9112 for (n = 0; n < factor; n++) {
9113 frames[count].x = finish->x - (finish->x - mid->x) / fraction;
9114 frames[count].y = finish->y - (finish->y - mid->y) / fraction;
9116 fraction = fraction * 2;
9121 /* Draw a piece on the screen without disturbing what's there */
9124 SelectGCMask(piece, clip, outline, mask)
9125 ChessSquare piece; GC * clip; GC * outline; Pixmap * mask;
9129 /* Bitmap for piece being moved. */
9130 if (appData.monoMode) {
9131 *mask = *pieceToSolid(piece);
9132 } else if (useImages) {
9134 *mask = xpmMask[piece];
9136 *mask = ximMaskPm[piece];
9139 *mask = *pieceToSolid(piece);
9142 /* GC for piece being moved. Square color doesn't matter, but
9143 since it gets modified we make a copy of the original. */
9145 if (appData.monoMode)
9150 if (appData.monoMode)
9155 XCopyGC(xDisplay, source, 0xFFFFFFFF, *clip);
9157 /* Outline only used in mono mode and is not modified */
9159 *outline = bwPieceGC;
9161 *outline = wbPieceGC;
9165 OverlayPiece(piece, clip, outline, dest)
9166 ChessSquare piece; GC clip; GC outline; Drawable dest;
9171 /* Draw solid rectangle which will be clipped to shape of piece */
9172 XFillRectangle(xDisplay, dest, clip,
9173 0, 0, squareSize, squareSize);
9174 if (appData.monoMode)
9175 /* Also draw outline in contrasting color for black
9176 on black / white on white cases */
9177 XCopyPlane(xDisplay, *pieceToOutline(piece), dest, outline,
9178 0, 0, squareSize, squareSize, 0, 0, 1);
9180 /* Copy the piece */
9185 XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
9187 0, 0, squareSize, squareSize,
9192 /* Animate the movement of a single piece */
9195 BeginAnimation(anim, piece, startColor, start)
9203 /* The old buffer is initialised with the start square (empty) */
9204 BlankSquare(0, 0, startColor, EmptySquare, anim->saveBuf);
9205 anim->prevFrame = *start;
9207 /* The piece will be drawn using its own bitmap as a matte */
9208 SelectGCMask(piece, &anim->pieceGC, &anim->outlineGC, &mask);
9209 XSetClipMask(xDisplay, anim->pieceGC, mask);
9213 AnimationFrame(anim, frame, piece)
9218 XRectangle updates[4];
9223 /* Save what we are about to draw into the new buffer */
9224 XCopyArea(xDisplay, xBoardWindow, anim->newBuf, anim->blitGC,
9225 frame->x, frame->y, squareSize, squareSize,
9228 /* Erase bits of the previous frame */
9229 if (Intersect(&anim->prevFrame, frame, squareSize, &overlap, &pt)) {
9230 /* Where the new frame overlapped the previous,
9231 the contents in newBuf are wrong. */
9232 XCopyArea(xDisplay, anim->saveBuf, anim->newBuf, anim->blitGC,
9233 overlap.x, overlap.y,
9234 overlap.width, overlap.height,
9236 /* Repaint the areas in the old that don't overlap new */
9237 CalcUpdateRects(&anim->prevFrame, frame, squareSize, updates, &count);
9238 for (i = 0; i < count; i++)
9239 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9240 updates[i].x - anim->prevFrame.x,
9241 updates[i].y - anim->prevFrame.y,
9242 updates[i].width, updates[i].height,
9243 updates[i].x, updates[i].y);
9245 /* Easy when no overlap */
9246 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9247 0, 0, squareSize, squareSize,
9248 anim->prevFrame.x, anim->prevFrame.y);
9251 /* Save this frame for next time round */
9252 XCopyArea(xDisplay, anim->newBuf, anim->saveBuf, anim->blitGC,
9253 0, 0, squareSize, squareSize,
9255 anim->prevFrame = *frame;
9257 /* Draw piece over original screen contents, not current,
9258 and copy entire rect. Wipes out overlapping piece images. */
9259 OverlayPiece(piece, anim->pieceGC, anim->outlineGC, anim->newBuf);
9260 XCopyArea(xDisplay, anim->newBuf, xBoardWindow, anim->blitGC,
9261 0, 0, squareSize, squareSize,
9262 frame->x, frame->y);
9266 EndAnimation (anim, finish)
9270 XRectangle updates[4];
9275 /* The main code will redraw the final square, so we
9276 only need to erase the bits that don't overlap. */
9277 if (Intersect(&anim->prevFrame, finish, squareSize, &overlap, &pt)) {
9278 CalcUpdateRects(&anim->prevFrame, finish, squareSize, updates, &count);
9279 for (i = 0; i < count; i++)
9280 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9281 updates[i].x - anim->prevFrame.x,
9282 updates[i].y - anim->prevFrame.y,
9283 updates[i].width, updates[i].height,
9284 updates[i].x, updates[i].y);
9286 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9287 0, 0, squareSize, squareSize,
9288 anim->prevFrame.x, anim->prevFrame.y);
9293 FrameSequence(anim, piece, startColor, start, finish, frames, nFrames)
9295 ChessSquare piece; int startColor;
9296 XPoint * start; XPoint * finish;
9297 XPoint frames[]; int nFrames;
9301 BeginAnimation(anim, piece, startColor, start);
9302 for (n = 0; n < nFrames; n++) {
9303 AnimationFrame(anim, &(frames[n]), piece);
9304 FrameDelay(appData.animSpeed);
9306 EndAnimation(anim, finish);
9309 /* Main control logic for deciding what to animate and how */
9312 AnimateMove(board, fromX, fromY, toX, toY)
9321 XPoint start, finish, mid;
9322 XPoint frames[kFactor * 2 + 1];
9323 int nFrames, startColor, endColor;
9325 /* Are we animating? */
9326 if (!appData.animate || appData.blindfold)
9329 if(board[toY][toX] == WhiteRook && board[fromY][fromX] == WhiteKing ||
9330 board[toY][toX] == BlackRook && board[fromY][fromX] == BlackKing)
9331 return; // [HGM] FRC: no animtion of FRC castlings, as to-square is not true to-square
9333 if (fromY < 0 || fromX < 0 || toX < 0 || toY < 0) return;
9334 piece = board[fromY][fromX];
9335 if (piece >= EmptySquare) return;
9340 hop = (piece == WhiteKnight || piece == BlackKnight);
9343 if (appData.debugMode) {
9344 fprintf(debugFP, hop ? _("AnimateMove: piece %d hops from %d,%d to %d,%d \n") :
9345 _("AnimateMove: piece %d slides from %d,%d to %d,%d \n"),
9346 piece, fromX, fromY, toX, toY); }
9348 ScreenSquare(fromX, fromY, &start, &startColor);
9349 ScreenSquare(toX, toY, &finish, &endColor);
9352 /* Knight: make diagonal movement then straight */
9353 if (abs(toY - fromY) < abs(toX - fromX)) {
9354 mid.x = start.x + (finish.x - start.x) / 2;
9358 mid.y = start.y + (finish.y - start.y) / 2;
9361 mid.x = start.x + (finish.x - start.x) / 2;
9362 mid.y = start.y + (finish.y - start.y) / 2;
9365 /* Don't use as many frames for very short moves */
9366 if (abs(toY - fromY) + abs(toX - fromX) <= 2)
9367 Tween(&start, &mid, &finish, kFactor - 1, frames, &nFrames);
9369 Tween(&start, &mid, &finish, kFactor, frames, &nFrames);
9370 FrameSequence(&game, piece, startColor, &start, &finish, frames, nFrames);
9372 /* Be sure end square is redrawn */
9373 damage[toY][toX] = True;
9377 DragPieceBegin(x, y)
9380 int boardX, boardY, color;
9383 /* Are we animating? */
9384 if (!appData.animateDragging || appData.blindfold)
9387 /* Figure out which square we start in and the
9388 mouse position relative to top left corner. */
9389 BoardSquare(x, y, &boardX, &boardY);
9390 player.startBoardX = boardX;
9391 player.startBoardY = boardY;
9392 ScreenSquare(boardX, boardY, &corner, &color);
9393 player.startSquare = corner;
9394 player.startColor = color;
9396 /* Start from exactly where the piece is. This can be confusing
9397 if you start dragging far from the center of the square; most
9398 or all of the piece can be over a different square from the one
9399 the mouse pointer is in. */
9400 player.mouseDelta.x = x - corner.x;
9401 player.mouseDelta.y = y - corner.y;
9403 /* As soon as we start dragging, the piece will jump slightly to
9404 be centered over the mouse pointer. */
9405 player.mouseDelta.x = squareSize/2;
9406 player.mouseDelta.y = squareSize/2;
9408 /* Initialise animation */
9409 player.dragPiece = PieceForSquare(boardX, boardY);
9411 if (player.dragPiece >= 0 && player.dragPiece < EmptySquare) {
9412 player.dragActive = True;
9413 BeginAnimation(&player, player.dragPiece, color, &corner);
9414 /* Mark this square as needing to be redrawn. Note that
9415 we don't remove the piece though, since logically (ie
9416 as seen by opponent) the move hasn't been made yet. */
9417 if(boardX == BOARD_RGHT+1 && PieceForSquare(boardX-1, boardY) > 1 ||
9418 boardX == BOARD_LEFT-2 && PieceForSquare(boardX+1, boardY) > 1)
9419 XCopyArea(xDisplay, xBoardWindow, player.saveBuf, player.blitGC,
9420 corner.x, corner.y, squareSize, squareSize,
9421 0, 0); // [HGM] zh: unstack in stead of grab
9422 damage[boardY][boardX] = True;
9424 player.dragActive = False;
9434 /* Are we animating? */
9435 if (!appData.animateDragging || appData.blindfold)
9439 if (! player.dragActive)
9441 /* Move piece, maintaining same relative position
9442 of mouse within square */
9443 corner.x = x - player.mouseDelta.x;
9444 corner.y = y - player.mouseDelta.y;
9445 AnimationFrame(&player, &corner, player.dragPiece);
9447 if (appData.highlightDragging) {
9449 BoardSquare(x, y, &boardX, &boardY);
9450 SetHighlights(fromX, fromY, boardX, boardY);
9459 int boardX, boardY, color;
9462 /* Are we animating? */
9463 if (!appData.animateDragging || appData.blindfold)
9467 if (! player.dragActive)
9469 /* Last frame in sequence is square piece is
9470 placed on, which may not match mouse exactly. */
9471 BoardSquare(x, y, &boardX, &boardY);
9472 ScreenSquare(boardX, boardY, &corner, &color);
9473 EndAnimation(&player, &corner);
9475 /* Be sure end square is redrawn */
9476 damage[boardY][boardX] = True;
9478 /* This prevents weird things happening with fast successive
9479 clicks which on my Sun at least can cause motion events
9480 without corresponding press/release. */
9481 player.dragActive = False;
9484 /* Handle expose event while piece being dragged */
9489 if (!player.dragActive || appData.blindfold)
9492 /* What we're doing: logically, the move hasn't been made yet,
9493 so the piece is still in it's original square. But visually
9494 it's being dragged around the board. So we erase the square
9495 that the piece is on and draw it at the last known drag point. */
9496 BlankSquare(player.startSquare.x, player.startSquare.y,
9497 player.startColor, EmptySquare, xBoardWindow);
9498 AnimationFrame(&player, &player.prevFrame, player.dragPiece);
9499 damage[player.startBoardY][player.startBoardX] = TRUE;
9503 SetProgramStats( FrontEndProgramStats * stats )
9506 // [HGM] done, but perhaps backend should call this directly?
9507 EngineOutputUpdate( stats );