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;
7649 snprintf(buf, sizeof(buf), "%s %s", message, extMessage);
7652 message = extMessage;
7655 XtSetArg(arg, XtNlabel, message);
7656 XtSetValues(messageWidget, &arg, 1);
7659 void DisplayTitle(text)
7664 char title[MSG_SIZ];
7667 if (text == NULL) text = "";
7669 if (appData.titleInWindow) {
7671 XtSetArg(args[i], XtNlabel, text); i++;
7672 XtSetValues(titleWidget, args, i);
7675 if (*text != NULLCHAR) {
7677 strcpy(title, text);
7678 } else if (appData.icsActive) {
7679 snprintf(icon, sizeof(icon), "%s", appData.icsHost);
7680 snprintf(title, sizeof(title), "%s: %s", programName, appData.icsHost);
7681 } else if (appData.cmailGameName[0] != NULLCHAR) {
7682 snprintf(icon, sizeof(icon), "%s", "CMail");
7683 snprintf(title,sizeof(title), "%s: %s", programName, "CMail");
7685 // [HGM] license: This stuff should really be done in back-end, but WinBoard already had a pop-up for it
7686 } else if (gameInfo.variant == VariantGothic) {
7687 strcpy(icon, programName);
7688 strcpy(title, GOTHIC);
7691 } else if (gameInfo.variant == VariantFalcon) {
7692 strcpy(icon, programName);
7693 strcpy(title, FALCON);
7695 } else if (appData.noChessProgram) {
7696 strcpy(icon, programName);
7697 strcpy(title, programName);
7699 strcpy(icon, first.tidy);
7700 snprintf(title,sizeof(title), "%s: %s", programName, first.tidy);
7703 XtSetArg(args[i], XtNiconName, (XtArgVal) icon); i++;
7704 XtSetArg(args[i], XtNtitle, (XtArgVal) title); i++;
7705 XtSetValues(shellWidget, args, i);
7709 void DisplayError(message, error)
7716 if (appData.debugMode || appData.matchMode) {
7717 fprintf(stderr, "%s: %s\n", programName, message);
7720 if (appData.debugMode || appData.matchMode) {
7721 fprintf(stderr, "%s: %s: %s\n",
7722 programName, message, strerror(error));
7724 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
7727 ErrorPopUp(_("Error"), message, FALSE);
7731 void DisplayMoveError(message)
7736 DrawPosition(FALSE, NULL);
7737 if (appData.debugMode || appData.matchMode) {
7738 fprintf(stderr, "%s: %s\n", programName, message);
7740 if (appData.popupMoveErrors) {
7741 ErrorPopUp(_("Error"), message, FALSE);
7743 DisplayMessage(message, "");
7748 void DisplayFatalError(message, error, status)
7754 errorExitStatus = status;
7756 fprintf(stderr, "%s: %s\n", programName, message);
7758 fprintf(stderr, "%s: %s: %s\n",
7759 programName, message, strerror(error));
7760 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
7763 if (appData.popupExitMessage && boardWidget && XtIsRealized(boardWidget)) {
7764 ErrorPopUp(status ? _("Fatal Error") : _("Exiting"), message, TRUE);
7770 void DisplayInformation(message)
7774 ErrorPopUp(_("Information"), message, TRUE);
7777 void DisplayNote(message)
7781 ErrorPopUp(_("Note"), message, FALSE);
7785 NullXErrorCheck(dpy, error_event)
7787 XErrorEvent *error_event;
7792 void DisplayIcsInteractionTitle(message)
7795 if (oldICSInteractionTitle == NULL) {
7796 /* Magic to find the old window title, adapted from vim */
7797 char *wina = getenv("WINDOWID");
7799 Window win = (Window) atoi(wina);
7800 Window root, parent, *children;
7801 unsigned int nchildren;
7802 int (*oldHandler)() = XSetErrorHandler(NullXErrorCheck);
7804 if (XFetchName(xDisplay, win, &oldICSInteractionTitle)) break;
7805 if (!XQueryTree(xDisplay, win, &root, &parent,
7806 &children, &nchildren)) break;
7807 if (children) XFree((void *)children);
7808 if (parent == root || parent == 0) break;
7811 XSetErrorHandler(oldHandler);
7813 if (oldICSInteractionTitle == NULL) {
7814 oldICSInteractionTitle = "xterm";
7817 printf("\033]0;%s\007", message);
7821 char pendingReplyPrefix[MSG_SIZ];
7822 ProcRef pendingReplyPR;
7824 void AskQuestionProc(w, event, prms, nprms)
7831 fprintf(stderr, _("AskQuestionProc needed 4 parameters, got %d\n"),
7835 AskQuestionEvent(prms[0], prms[1], prms[2], prms[3]);
7838 void AskQuestionPopDown()
7840 if (!askQuestionUp) return;
7841 XtPopdown(askQuestionShell);
7842 XtDestroyWidget(askQuestionShell);
7843 askQuestionUp = False;
7846 void AskQuestionReplyAction(w, event, prms, nprms)
7856 reply = XawDialogGetValueString(w = XtParent(w));
7857 strcpy(buf, pendingReplyPrefix);
7858 if (*buf) strcat(buf, " ");
7861 OutputToProcess(pendingReplyPR, buf, strlen(buf), &err);
7862 AskQuestionPopDown();
7864 if (err) DisplayFatalError(_("Error writing to chess program"), err, 0);
7867 void AskQuestionCallback(w, client_data, call_data)
7869 XtPointer client_data, call_data;
7874 XtSetArg(args[0], XtNlabel, &name);
7875 XtGetValues(w, args, 1);
7877 if (strcmp(name, _("cancel")) == 0) {
7878 AskQuestionPopDown();
7880 AskQuestionReplyAction(w, NULL, NULL, NULL);
7884 void AskQuestion(title, question, replyPrefix, pr)
7885 char *title, *question, *replyPrefix;
7889 Widget popup, layout, dialog, edit;
7895 strcpy(pendingReplyPrefix, replyPrefix);
7896 pendingReplyPR = pr;
7899 XtSetArg(args[i], XtNresizable, True); i++;
7900 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
7901 askQuestionShell = popup =
7902 XtCreatePopupShell(title, transientShellWidgetClass,
7903 shellWidget, args, i);
7906 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
7907 layoutArgs, XtNumber(layoutArgs));
7910 XtSetArg(args[i], XtNlabel, question); i++;
7911 XtSetArg(args[i], XtNvalue, ""); i++;
7912 XtSetArg(args[i], XtNborderWidth, 0); i++;
7913 dialog = XtCreateManagedWidget("question", dialogWidgetClass,
7916 XawDialogAddButton(dialog, _("enter"), AskQuestionCallback,
7917 (XtPointer) dialog);
7918 XawDialogAddButton(dialog, _("cancel"), AskQuestionCallback,
7919 (XtPointer) dialog);
7921 XtRealizeWidget(popup);
7922 CatchDeleteWindow(popup, "AskQuestionPopDown");
7924 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
7925 &x, &y, &win_x, &win_y, &mask);
7927 XtSetArg(args[0], XtNx, x - 10);
7928 XtSetArg(args[1], XtNy, y - 30);
7929 XtSetValues(popup, args, 2);
7931 XtPopup(popup, XtGrabExclusive);
7932 askQuestionUp = True;
7934 edit = XtNameToWidget(dialog, "*value");
7935 XtSetKeyboardFocus(popup, edit);
7943 if (*name == NULLCHAR) {
7945 } else if (strcmp(name, "$") == 0) {
7946 putc(BELLCHAR, stderr);
7949 snprintf(buf, sizeof(buf), "%s '%s' &", appData.soundProgram, name);
7957 PlaySound(appData.soundMove);
7963 PlaySound(appData.soundIcsWin);
7969 PlaySound(appData.soundIcsLoss);
7975 PlaySound(appData.soundIcsDraw);
7979 PlayIcsUnfinishedSound()
7981 PlaySound(appData.soundIcsUnfinished);
7987 PlaySound(appData.soundIcsAlarm);
7993 system("stty echo");
7999 system("stty -echo");
8003 Colorize(cc, continuation)
8008 int count, outCount, error;
8010 if (textColors[(int)cc].bg > 0) {
8011 if (textColors[(int)cc].fg > 0) {
8012 sprintf(buf, "\033[0;%d;%d;%dm", textColors[(int)cc].attr,
8013 textColors[(int)cc].fg, textColors[(int)cc].bg);
8015 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
8016 textColors[(int)cc].bg);
8019 if (textColors[(int)cc].fg > 0) {
8020 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
8021 textColors[(int)cc].fg);
8023 sprintf(buf, "\033[0;%dm", textColors[(int)cc].attr);
8026 count = strlen(buf);
8027 outCount = OutputToProcess(NoProc, buf, count, &error);
8028 if (outCount < count) {
8029 DisplayFatalError(_("Error writing to display"), error, 1);
8032 if (continuation) return;
8035 PlaySound(appData.soundShout);
8038 PlaySound(appData.soundSShout);
8041 PlaySound(appData.soundChannel1);
8044 PlaySound(appData.soundChannel);
8047 PlaySound(appData.soundKibitz);
8050 PlaySound(appData.soundTell);
8052 case ColorChallenge:
8053 PlaySound(appData.soundChallenge);
8056 PlaySound(appData.soundRequest);
8059 PlaySound(appData.soundSeek);
8070 return getpwuid(getuid())->pw_name;
8073 static char *ExpandPathName(path)
8076 static char static_buf[2000];
8077 char *d, *s, buf[2000];
8083 while (*s && isspace(*s))
8092 if (*(s+1) == '/') {
8093 strcpy(d, getpwuid(getuid())->pw_dir);
8098 *strchr(buf, '/') = 0;
8099 pwd = getpwnam(buf);
8102 fprintf(stderr, _("ERROR: Unknown user %s (in path %s)\n"),
8106 strcpy(d, pwd->pw_dir);
8107 strcat(d, strchr(s+1, '/'));
8118 static char host_name[MSG_SIZ];
8120 #if HAVE_GETHOSTNAME
8121 gethostname(host_name, MSG_SIZ);
8123 #else /* not HAVE_GETHOSTNAME */
8124 # if HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H
8125 sysinfo(SI_HOSTNAME, host_name, MSG_SIZ);
8127 # else /* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
8129 # endif/* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
8130 #endif /* not HAVE_GETHOSTNAME */
8133 XtIntervalId delayedEventTimerXID = 0;
8134 DelayedEventCallback delayedEventCallback = 0;
8139 delayedEventTimerXID = 0;
8140 delayedEventCallback();
8144 ScheduleDelayedEvent(cb, millisec)
8145 DelayedEventCallback cb; long millisec;
8147 if(delayedEventTimerXID && delayedEventCallback == cb)
8148 // [HGM] alive: replace, rather than add or flush identical event
8149 XtRemoveTimeOut(delayedEventTimerXID);
8150 delayedEventCallback = cb;
8151 delayedEventTimerXID =
8152 XtAppAddTimeOut(appContext, millisec,
8153 (XtTimerCallbackProc) FireDelayedEvent, (XtPointer) 0);
8156 DelayedEventCallback
8159 if (delayedEventTimerXID) {
8160 return delayedEventCallback;
8167 CancelDelayedEvent()
8169 if (delayedEventTimerXID) {
8170 XtRemoveTimeOut(delayedEventTimerXID);
8171 delayedEventTimerXID = 0;
8175 XtIntervalId loadGameTimerXID = 0;
8177 int LoadGameTimerRunning()
8179 return loadGameTimerXID != 0;
8182 int StopLoadGameTimer()
8184 if (loadGameTimerXID != 0) {
8185 XtRemoveTimeOut(loadGameTimerXID);
8186 loadGameTimerXID = 0;
8194 LoadGameTimerCallback(arg, id)
8198 loadGameTimerXID = 0;
8203 StartLoadGameTimer(millisec)
8207 XtAppAddTimeOut(appContext, millisec,
8208 (XtTimerCallbackProc) LoadGameTimerCallback,
8212 XtIntervalId analysisClockXID = 0;
8215 AnalysisClockCallback(arg, id)
8219 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile
8220 || appData.icsEngineAnalyze) { // [DM]
8221 AnalysisPeriodicEvent(0);
8222 StartAnalysisClock();
8227 StartAnalysisClock()
8230 XtAppAddTimeOut(appContext, 2000,
8231 (XtTimerCallbackProc) AnalysisClockCallback,
8235 XtIntervalId clockTimerXID = 0;
8237 int ClockTimerRunning()
8239 return clockTimerXID != 0;
8242 int StopClockTimer()
8244 if (clockTimerXID != 0) {
8245 XtRemoveTimeOut(clockTimerXID);
8254 ClockTimerCallback(arg, id)
8263 StartClockTimer(millisec)
8267 XtAppAddTimeOut(appContext, millisec,
8268 (XtTimerCallbackProc) ClockTimerCallback,
8273 DisplayTimerLabel(w, color, timer, highlight)
8282 /* check for low time warning */
8283 Pixel foregroundOrWarningColor = timerForegroundPixel;
8286 appData.lowTimeWarning &&
8287 (timer / 1000) < appData.icsAlarmTime)
8288 foregroundOrWarningColor = lowTimeWarningColor;
8290 if (appData.clockMode) {
8291 sprintf(buf, "%s: %s", color, TimeString(timer));
8292 XtSetArg(args[0], XtNlabel, buf);
8294 sprintf(buf, "%s ", color);
8295 XtSetArg(args[0], XtNlabel, buf);
8300 XtSetArg(args[1], XtNbackground, foregroundOrWarningColor);
8301 XtSetArg(args[2], XtNforeground, timerBackgroundPixel);
8303 XtSetArg(args[1], XtNbackground, timerBackgroundPixel);
8304 XtSetArg(args[2], XtNforeground, foregroundOrWarningColor);
8307 XtSetValues(w, args, 3);
8311 DisplayWhiteClock(timeRemaining, highlight)
8317 if(appData.noGUI) return;
8318 DisplayTimerLabel(whiteTimerWidget, _("White"), timeRemaining, highlight);
8319 if (highlight && iconPixmap == bIconPixmap) {
8320 iconPixmap = wIconPixmap;
8321 XtSetArg(args[0], XtNiconPixmap, iconPixmap);
8322 XtSetValues(shellWidget, args, 1);
8327 DisplayBlackClock(timeRemaining, highlight)
8333 if(appData.noGUI) return;
8334 DisplayTimerLabel(blackTimerWidget, _("Black"), timeRemaining, highlight);
8335 if (highlight && iconPixmap == wIconPixmap) {
8336 iconPixmap = bIconPixmap;
8337 XtSetArg(args[0], XtNiconPixmap, iconPixmap);
8338 XtSetValues(shellWidget, args, 1);
8356 int StartChildProcess(cmdLine, dir, pr)
8363 int to_prog[2], from_prog[2];
8367 if (appData.debugMode) {
8368 fprintf(stderr, "StartChildProcess (dir=\"%s\") %s\n",dir, cmdLine);
8371 /* We do NOT feed the cmdLine to the shell; we just
8372 parse it into blank-separated arguments in the
8373 most simple-minded way possible.
8376 strcpy(buf, cmdLine);
8381 if (p == NULL) break;
8386 SetUpChildIO(to_prog, from_prog);
8388 if ((pid = fork()) == 0) {
8390 // [HGM] PSWBTM: made order resistant against case where fd of created pipe was 0 or 1
8391 close(to_prog[1]); // first close the unused pipe ends
8392 close(from_prog[0]);
8393 dup2(to_prog[0], 0); // to_prog was created first, nd is the only one to use 0 or 1
8394 dup2(from_prog[1], 1);
8395 if(to_prog[0] >= 2) close(to_prog[0]); // if 0 or 1, the dup2 already cosed the original
8396 close(from_prog[1]); // and closing again loses one of the pipes!
8397 if(fileno(stderr) >= 2) // better safe than sorry...
8398 dup2(1, fileno(stderr)); /* force stderr to the pipe */
8400 if (dir[0] != NULLCHAR && chdir(dir) != 0) {
8405 nice(appData.niceEngines); // [HGM] nice: adjust priority of engine proc
8407 execvp(argv[0], argv);
8409 /* If we get here, exec failed */
8414 /* Parent process */
8416 close(from_prog[1]);
8418 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8421 cp->fdFrom = from_prog[0];
8422 cp->fdTo = to_prog[1];
8427 // [HGM] kill: implement the 'hard killing' of AS's Winboard_x
8428 static RETSIGTYPE AlarmCallBack(int n)
8434 DestroyChildProcess(pr, signalType)
8438 ChildProc *cp = (ChildProc *) pr;
8440 if (cp->kind != CPReal) return;
8442 if (signalType == 10) { // [HGM] kill: if it does not terminate in 3 sec, kill
8443 signal(SIGALRM, AlarmCallBack);
8445 if(wait((int *) 0) == -1) { // process does not terminate on its own accord
8446 kill(cp->pid, SIGKILL); // kill it forcefully
8447 wait((int *) 0); // and wait again
8451 kill(cp->pid, signalType == 9 ? SIGKILL : SIGTERM); // [HGM] kill: use hard kill if so requested
8453 /* Process is exiting either because of the kill or because of
8454 a quit command sent by the backend; either way, wait for it to die.
8463 InterruptChildProcess(pr)
8466 ChildProc *cp = (ChildProc *) pr;
8468 if (cp->kind != CPReal) return;
8469 (void) kill(cp->pid, SIGINT); /* stop it thinking */
8472 int OpenTelnet(host, port, pr)
8477 char cmdLine[MSG_SIZ];
8479 if (port[0] == NULLCHAR) {
8480 snprintf(cmdLine, sizeof(cmdLine), "%s %s", appData.telnetProgram, host);
8482 snprintf(cmdLine, sizeof(cmdLine), "%s %s %s", appData.telnetProgram, host, port);
8484 return StartChildProcess(cmdLine, "", pr);
8487 int OpenTCP(host, port, pr)
8493 DisplayFatalError(_("Socket support is not configured in"), 0, 2);
8494 #else /* !OMIT_SOCKETS */
8496 struct sockaddr_in sa;
8498 unsigned short uport;
8501 if ((s = socket(AF_INET, SOCK_STREAM, 6)) < 0) {
8505 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
8506 sa.sin_family = AF_INET;
8507 sa.sin_addr.s_addr = INADDR_ANY;
8508 uport = (unsigned short) 0;
8509 sa.sin_port = htons(uport);
8510 if (bind(s, (struct sockaddr *) &sa, sizeof(struct sockaddr_in)) < 0) {
8514 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
8515 if (!(hp = gethostbyname(host))) {
8517 if (sscanf(host, "%d.%d.%d.%d", &b0, &b1, &b2, &b3) == 4) {
8518 hp = (struct hostent *) calloc(1, sizeof(struct hostent));
8519 hp->h_addrtype = AF_INET;
8521 hp->h_addr_list = (char **) calloc(2, sizeof(char *));
8522 hp->h_addr_list[0] = (char *) malloc(4);
8523 hp->h_addr_list[0][0] = b0;
8524 hp->h_addr_list[0][1] = b1;
8525 hp->h_addr_list[0][2] = b2;
8526 hp->h_addr_list[0][3] = b3;
8531 sa.sin_family = hp->h_addrtype;
8532 uport = (unsigned short) atoi(port);
8533 sa.sin_port = htons(uport);
8534 memcpy((char *) &sa.sin_addr, hp->h_addr, hp->h_length);
8536 if (connect(s, (struct sockaddr *) &sa,
8537 sizeof(struct sockaddr_in)) < 0) {
8541 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8548 #endif /* !OMIT_SOCKETS */
8553 int OpenCommPort(name, pr)
8560 fd = open(name, 2, 0);
8561 if (fd < 0) return errno;
8563 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8573 int OpenLoopback(pr)
8579 SetUpChildIO(to, from);
8581 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8584 cp->fdFrom = to[0]; /* note not from[0]; we are doing a loopback */
8591 int OpenRcmd(host, user, cmd, pr)
8592 char *host, *user, *cmd;
8595 DisplayFatalError(_("internal rcmd not implemented for Unix"), 0, 1);
8599 #define INPUT_SOURCE_BUF_SIZE 8192
8608 char buf[INPUT_SOURCE_BUF_SIZE];
8613 DoInputCallback(closure, source, xid)
8618 InputSource *is = (InputSource *) closure;
8623 if (is->lineByLine) {
8624 count = read(is->fd, is->unused,
8625 INPUT_SOURCE_BUF_SIZE - (is->unused - is->buf));
8627 (is->func)(is, is->closure, is->buf, count, count ? errno : 0);
8630 is->unused += count;
8632 while (p < is->unused) {
8633 q = memchr(p, '\n', is->unused - p);
8634 if (q == NULL) break;
8636 (is->func)(is, is->closure, p, q - p, 0);
8640 while (p < is->unused) {
8645 count = read(is->fd, is->buf, INPUT_SOURCE_BUF_SIZE);
8650 (is->func)(is, is->closure, is->buf, count, error);
8654 InputSourceRef AddInputSource(pr, lineByLine, func, closure)
8661 ChildProc *cp = (ChildProc *) pr;
8663 is = (InputSource *) calloc(1, sizeof(InputSource));
8664 is->lineByLine = lineByLine;
8668 is->fd = fileno(stdin);
8670 is->kind = cp->kind;
8671 is->fd = cp->fdFrom;
8674 is->unused = is->buf;
8677 is->xid = XtAppAddInput(appContext, is->fd,
8678 (XtPointer) (XtInputReadMask),
8679 (XtInputCallbackProc) DoInputCallback,
8681 is->closure = closure;
8682 return (InputSourceRef) is;
8686 RemoveInputSource(isr)
8689 InputSource *is = (InputSource *) isr;
8691 if (is->xid == 0) return;
8692 XtRemoveInput(is->xid);
8696 int OutputToProcess(pr, message, count, outError)
8702 ChildProc *cp = (ChildProc *) pr;
8706 outCount = fwrite(message, 1, count, stdout);
8708 outCount = write(cp->fdTo, message, count);
8718 /* Output message to process, with "ms" milliseconds of delay
8719 between each character. This is needed when sending the logon
8720 script to ICC, which for some reason doesn't like the
8721 instantaneous send. */
8722 int OutputToProcessDelayed(pr, message, count, outError, msdelay)
8729 ChildProc *cp = (ChildProc *) pr;
8734 r = write(cp->fdTo, message++, 1);
8747 /**** Animation code by Hugh Fisher, DCS, ANU.
8749 Known problem: if a window overlapping the board is
8750 moved away while a piece is being animated underneath,
8751 the newly exposed area won't be updated properly.
8752 I can live with this.
8754 Known problem: if you look carefully at the animation
8755 of pieces in mono mode, they are being drawn as solid
8756 shapes without interior detail while moving. Fixing
8757 this would be a major complication for minimal return.
8760 /* Masks for XPM pieces. Black and white pieces can have
8761 different shapes, but in the interest of retaining my
8762 sanity pieces must have the same outline on both light
8763 and dark squares, and all pieces must use the same
8764 background square colors/images. */
8766 static int xpmDone = 0;
8769 CreateAnimMasks (pieceDepth)
8776 unsigned long plane;
8779 /* Need a bitmap just to get a GC with right depth */
8780 buf = XCreatePixmap(xDisplay, xBoardWindow,
8782 values.foreground = 1;
8783 values.background = 0;
8784 /* Don't use XtGetGC, not read only */
8785 maskGC = XCreateGC(xDisplay, buf,
8786 GCForeground | GCBackground, &values);
8787 XFreePixmap(xDisplay, buf);
8789 buf = XCreatePixmap(xDisplay, xBoardWindow,
8790 squareSize, squareSize, pieceDepth);
8791 values.foreground = XBlackPixel(xDisplay, xScreen);
8792 values.background = XWhitePixel(xDisplay, xScreen);
8793 bufGC = XCreateGC(xDisplay, buf,
8794 GCForeground | GCBackground, &values);
8796 for (piece = WhitePawn; piece <= BlackKing; piece++) {
8797 /* Begin with empty mask */
8798 if(!xpmDone) // [HGM] pieces: keep using existing
8799 xpmMask[piece] = XCreatePixmap(xDisplay, xBoardWindow,
8800 squareSize, squareSize, 1);
8801 XSetFunction(xDisplay, maskGC, GXclear);
8802 XFillRectangle(xDisplay, xpmMask[piece], maskGC,
8803 0, 0, squareSize, squareSize);
8805 /* Take a copy of the piece */
8810 XSetFunction(xDisplay, bufGC, GXcopy);
8811 XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % (int)BlackPawn],
8813 0, 0, squareSize, squareSize, 0, 0);
8815 /* XOR the background (light) over the piece */
8816 XSetFunction(xDisplay, bufGC, GXxor);
8818 XCopyArea(xDisplay, xpmLightSquare, buf, bufGC,
8819 0, 0, squareSize, squareSize, 0, 0);
8821 XSetForeground(xDisplay, bufGC, lightSquareColor);
8822 XFillRectangle(xDisplay, buf, bufGC, 0, 0, squareSize, squareSize);
8825 /* We now have an inverted piece image with the background
8826 erased. Construct mask by just selecting all the non-zero
8827 pixels - no need to reconstruct the original image. */
8828 XSetFunction(xDisplay, maskGC, GXor);
8830 /* Might be quicker to download an XImage and create bitmap
8831 data from it rather than this N copies per piece, but it
8832 only takes a fraction of a second and there is a much
8833 longer delay for loading the pieces. */
8834 for (n = 0; n < pieceDepth; n ++) {
8835 XCopyPlane(xDisplay, buf, xpmMask[piece], maskGC,
8836 0, 0, squareSize, squareSize,
8842 XFreePixmap(xDisplay, buf);
8843 XFreeGC(xDisplay, bufGC);
8844 XFreeGC(xDisplay, maskGC);
8848 InitAnimState (anim, info)
8850 XWindowAttributes * info;
8855 /* Each buffer is square size, same depth as window */
8856 anim->saveBuf = XCreatePixmap(xDisplay, xBoardWindow,
8857 squareSize, squareSize, info->depth);
8858 anim->newBuf = XCreatePixmap(xDisplay, xBoardWindow,
8859 squareSize, squareSize, info->depth);
8861 /* Create a plain GC for blitting */
8862 mask = GCForeground | GCBackground | GCFunction |
8863 GCPlaneMask | GCGraphicsExposures;
8864 values.foreground = XBlackPixel(xDisplay, xScreen);
8865 values.background = XWhitePixel(xDisplay, xScreen);
8866 values.function = GXcopy;
8867 values.plane_mask = AllPlanes;
8868 values.graphics_exposures = False;
8869 anim->blitGC = XCreateGC(xDisplay, xBoardWindow, mask, &values);
8871 /* Piece will be copied from an existing context at
8872 the start of each new animation/drag. */
8873 anim->pieceGC = XCreateGC(xDisplay, xBoardWindow, 0, &values);
8875 /* Outline will be a read-only copy of an existing */
8876 anim->outlineGC = None;
8882 static VariantClass old = (VariantClass) -1; // [HGM] pieces: redo every time variant changes
8883 XWindowAttributes info;
8885 if (xpmDone && gameInfo.variant == old) return;
8886 if(xpmDone) old = gameInfo.variant; // first time pieces might not be created yet
8887 XGetWindowAttributes(xDisplay, xBoardWindow, &info);
8889 InitAnimState(&game, &info);
8890 InitAnimState(&player, &info);
8892 /* For XPM pieces, we need bitmaps to use as masks. */
8894 CreateAnimMasks(info.depth);
8900 static Boolean frameWaiting;
8902 static RETSIGTYPE FrameAlarm (sig)
8905 frameWaiting = False;
8906 /* In case System-V style signals. Needed?? */
8907 signal(SIGALRM, FrameAlarm);
8914 struct itimerval delay;
8916 XSync(xDisplay, False);
8919 frameWaiting = True;
8920 signal(SIGALRM, FrameAlarm);
8921 delay.it_interval.tv_sec =
8922 delay.it_value.tv_sec = time / 1000;
8923 delay.it_interval.tv_usec =
8924 delay.it_value.tv_usec = (time % 1000) * 1000;
8925 setitimer(ITIMER_REAL, &delay, NULL);
8927 /* Ugh -- busy-wait! --tpm */
8928 while (frameWaiting);
8930 while (frameWaiting) pause();
8932 delay.it_interval.tv_sec = delay.it_value.tv_sec = 0;
8933 delay.it_interval.tv_usec = delay.it_value.tv_usec = 0;
8934 setitimer(ITIMER_REAL, &delay, NULL);
8944 XSync(xDisplay, False);
8946 usleep(time * 1000);
8951 /* Convert board position to corner of screen rect and color */
8954 ScreenSquare(column, row, pt, color)
8955 int column; int row; XPoint * pt; int * color;
8958 pt->x = lineGap + ((BOARD_WIDTH-1)-column) * (squareSize + lineGap);
8959 pt->y = lineGap + row * (squareSize + lineGap);
8961 pt->x = lineGap + column * (squareSize + lineGap);
8962 pt->y = lineGap + ((BOARD_HEIGHT-1)-row) * (squareSize + lineGap);
8964 *color = SquareColor(row, column);
8967 /* Convert window coords to square */
8970 BoardSquare(x, y, column, row)
8971 int x; int y; int * column; int * row;
8973 *column = EventToSquare(x, BOARD_WIDTH);
8974 if (flipView && *column >= 0)
8975 *column = BOARD_WIDTH - 1 - *column;
8976 *row = EventToSquare(y, BOARD_HEIGHT);
8977 if (!flipView && *row >= 0)
8978 *row = BOARD_HEIGHT - 1 - *row;
8983 #undef Max /* just in case */
8985 #define Max(a, b) ((a) > (b) ? (a) : (b))
8986 #define Min(a, b) ((a) < (b) ? (a) : (b))
8989 SetRect(rect, x, y, width, height)
8990 XRectangle * rect; int x; int y; int width; int height;
8994 rect->width = width;
8995 rect->height = height;
8998 /* Test if two frames overlap. If they do, return
8999 intersection rect within old and location of
9000 that rect within new. */
9003 Intersect(old, new, size, area, pt)
9004 XPoint * old; XPoint * new;
9005 int size; XRectangle * area; XPoint * pt;
9007 if (old->x > new->x + size || new->x > old->x + size ||
9008 old->y > new->y + size || new->y > old->y + size) {
9011 SetRect(area, Max(new->x - old->x, 0), Max(new->y - old->y, 0),
9012 size - abs(old->x - new->x), size - abs(old->y - new->y));
9013 pt->x = Max(old->x - new->x, 0);
9014 pt->y = Max(old->y - new->y, 0);
9019 /* For two overlapping frames, return the rect(s)
9020 in the old that do not intersect with the new. */
9023 CalcUpdateRects(old, new, size, update, nUpdates)
9024 XPoint * old; XPoint * new; int size;
9025 XRectangle update[]; int * nUpdates;
9029 /* If old = new (shouldn't happen) then nothing to draw */
9030 if (old->x == new->x && old->y == new->y) {
9034 /* Work out what bits overlap. Since we know the rects
9035 are the same size we don't need a full intersect calc. */
9037 /* Top or bottom edge? */
9038 if (new->y > old->y) {
9039 SetRect(&(update[count]), old->x, old->y, size, new->y - old->y);
9041 } else if (old->y > new->y) {
9042 SetRect(&(update[count]), old->x, old->y + size - (old->y - new->y),
9043 size, old->y - new->y);
9046 /* Left or right edge - don't overlap any update calculated above. */
9047 if (new->x > old->x) {
9048 SetRect(&(update[count]), old->x, Max(new->y, old->y),
9049 new->x - old->x, size - abs(new->y - old->y));
9051 } else if (old->x > new->x) {
9052 SetRect(&(update[count]), new->x + size, Max(new->y, old->y),
9053 old->x - new->x, size - abs(new->y - old->y));
9060 /* Generate a series of frame coords from start->mid->finish.
9061 The movement rate doubles until the half way point is
9062 reached, then halves back down to the final destination,
9063 which gives a nice slow in/out effect. The algorithmn
9064 may seem to generate too many intermediates for short
9065 moves, but remember that the purpose is to attract the
9066 viewers attention to the piece about to be moved and
9067 then to where it ends up. Too few frames would be less
9071 Tween(start, mid, finish, factor, frames, nFrames)
9072 XPoint * start; XPoint * mid;
9073 XPoint * finish; int factor;
9074 XPoint frames[]; int * nFrames;
9076 int fraction, n, count;
9080 /* Slow in, stepping 1/16th, then 1/8th, ... */
9082 for (n = 0; n < factor; n++)
9084 for (n = 0; n < factor; n++) {
9085 frames[count].x = start->x + (mid->x - start->x) / fraction;
9086 frames[count].y = start->y + (mid->y - start->y) / fraction;
9088 fraction = fraction / 2;
9092 frames[count] = *mid;
9095 /* Slow out, stepping 1/2, then 1/4, ... */
9097 for (n = 0; n < factor; n++) {
9098 frames[count].x = finish->x - (finish->x - mid->x) / fraction;
9099 frames[count].y = finish->y - (finish->y - mid->y) / fraction;
9101 fraction = fraction * 2;
9106 /* Draw a piece on the screen without disturbing what's there */
9109 SelectGCMask(piece, clip, outline, mask)
9110 ChessSquare piece; GC * clip; GC * outline; Pixmap * mask;
9114 /* Bitmap for piece being moved. */
9115 if (appData.monoMode) {
9116 *mask = *pieceToSolid(piece);
9117 } else if (useImages) {
9119 *mask = xpmMask[piece];
9121 *mask = ximMaskPm[piece];
9124 *mask = *pieceToSolid(piece);
9127 /* GC for piece being moved. Square color doesn't matter, but
9128 since it gets modified we make a copy of the original. */
9130 if (appData.monoMode)
9135 if (appData.monoMode)
9140 XCopyGC(xDisplay, source, 0xFFFFFFFF, *clip);
9142 /* Outline only used in mono mode and is not modified */
9144 *outline = bwPieceGC;
9146 *outline = wbPieceGC;
9150 OverlayPiece(piece, clip, outline, dest)
9151 ChessSquare piece; GC clip; GC outline; Drawable dest;
9156 /* Draw solid rectangle which will be clipped to shape of piece */
9157 XFillRectangle(xDisplay, dest, clip,
9158 0, 0, squareSize, squareSize);
9159 if (appData.monoMode)
9160 /* Also draw outline in contrasting color for black
9161 on black / white on white cases */
9162 XCopyPlane(xDisplay, *pieceToOutline(piece), dest, outline,
9163 0, 0, squareSize, squareSize, 0, 0, 1);
9165 /* Copy the piece */
9170 XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
9172 0, 0, squareSize, squareSize,
9177 /* Animate the movement of a single piece */
9180 BeginAnimation(anim, piece, startColor, start)
9188 /* The old buffer is initialised with the start square (empty) */
9189 BlankSquare(0, 0, startColor, EmptySquare, anim->saveBuf);
9190 anim->prevFrame = *start;
9192 /* The piece will be drawn using its own bitmap as a matte */
9193 SelectGCMask(piece, &anim->pieceGC, &anim->outlineGC, &mask);
9194 XSetClipMask(xDisplay, anim->pieceGC, mask);
9198 AnimationFrame(anim, frame, piece)
9203 XRectangle updates[4];
9208 /* Save what we are about to draw into the new buffer */
9209 XCopyArea(xDisplay, xBoardWindow, anim->newBuf, anim->blitGC,
9210 frame->x, frame->y, squareSize, squareSize,
9213 /* Erase bits of the previous frame */
9214 if (Intersect(&anim->prevFrame, frame, squareSize, &overlap, &pt)) {
9215 /* Where the new frame overlapped the previous,
9216 the contents in newBuf are wrong. */
9217 XCopyArea(xDisplay, anim->saveBuf, anim->newBuf, anim->blitGC,
9218 overlap.x, overlap.y,
9219 overlap.width, overlap.height,
9221 /* Repaint the areas in the old that don't overlap new */
9222 CalcUpdateRects(&anim->prevFrame, frame, squareSize, updates, &count);
9223 for (i = 0; i < count; i++)
9224 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9225 updates[i].x - anim->prevFrame.x,
9226 updates[i].y - anim->prevFrame.y,
9227 updates[i].width, updates[i].height,
9228 updates[i].x, updates[i].y);
9230 /* Easy when no overlap */
9231 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9232 0, 0, squareSize, squareSize,
9233 anim->prevFrame.x, anim->prevFrame.y);
9236 /* Save this frame for next time round */
9237 XCopyArea(xDisplay, anim->newBuf, anim->saveBuf, anim->blitGC,
9238 0, 0, squareSize, squareSize,
9240 anim->prevFrame = *frame;
9242 /* Draw piece over original screen contents, not current,
9243 and copy entire rect. Wipes out overlapping piece images. */
9244 OverlayPiece(piece, anim->pieceGC, anim->outlineGC, anim->newBuf);
9245 XCopyArea(xDisplay, anim->newBuf, xBoardWindow, anim->blitGC,
9246 0, 0, squareSize, squareSize,
9247 frame->x, frame->y);
9251 EndAnimation (anim, finish)
9255 XRectangle updates[4];
9260 /* The main code will redraw the final square, so we
9261 only need to erase the bits that don't overlap. */
9262 if (Intersect(&anim->prevFrame, finish, squareSize, &overlap, &pt)) {
9263 CalcUpdateRects(&anim->prevFrame, finish, squareSize, updates, &count);
9264 for (i = 0; i < count; i++)
9265 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9266 updates[i].x - anim->prevFrame.x,
9267 updates[i].y - anim->prevFrame.y,
9268 updates[i].width, updates[i].height,
9269 updates[i].x, updates[i].y);
9271 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9272 0, 0, squareSize, squareSize,
9273 anim->prevFrame.x, anim->prevFrame.y);
9278 FrameSequence(anim, piece, startColor, start, finish, frames, nFrames)
9280 ChessSquare piece; int startColor;
9281 XPoint * start; XPoint * finish;
9282 XPoint frames[]; int nFrames;
9286 BeginAnimation(anim, piece, startColor, start);
9287 for (n = 0; n < nFrames; n++) {
9288 AnimationFrame(anim, &(frames[n]), piece);
9289 FrameDelay(appData.animSpeed);
9291 EndAnimation(anim, finish);
9294 /* Main control logic for deciding what to animate and how */
9297 AnimateMove(board, fromX, fromY, toX, toY)
9306 XPoint start, finish, mid;
9307 XPoint frames[kFactor * 2 + 1];
9308 int nFrames, startColor, endColor;
9310 /* Are we animating? */
9311 if (!appData.animate || appData.blindfold)
9314 if(board[toY][toX] == WhiteRook && board[fromY][fromX] == WhiteKing ||
9315 board[toY][toX] == BlackRook && board[fromY][fromX] == BlackKing)
9316 return; // [HGM] FRC: no animtion of FRC castlings, as to-square is not true to-square
9318 if (fromY < 0 || fromX < 0 || toX < 0 || toY < 0) return;
9319 piece = board[fromY][fromX];
9320 if (piece >= EmptySquare) return;
9325 hop = (piece == WhiteKnight || piece == BlackKnight);
9328 if (appData.debugMode) {
9329 fprintf(debugFP, hop ? _("AnimateMove: piece %d hops from %d,%d to %d,%d \n") :
9330 _("AnimateMove: piece %d slides from %d,%d to %d,%d \n"),
9331 piece, fromX, fromY, toX, toY); }
9333 ScreenSquare(fromX, fromY, &start, &startColor);
9334 ScreenSquare(toX, toY, &finish, &endColor);
9337 /* Knight: make diagonal movement then straight */
9338 if (abs(toY - fromY) < abs(toX - fromX)) {
9339 mid.x = start.x + (finish.x - start.x) / 2;
9343 mid.y = start.y + (finish.y - start.y) / 2;
9346 mid.x = start.x + (finish.x - start.x) / 2;
9347 mid.y = start.y + (finish.y - start.y) / 2;
9350 /* Don't use as many frames for very short moves */
9351 if (abs(toY - fromY) + abs(toX - fromX) <= 2)
9352 Tween(&start, &mid, &finish, kFactor - 1, frames, &nFrames);
9354 Tween(&start, &mid, &finish, kFactor, frames, &nFrames);
9355 FrameSequence(&game, piece, startColor, &start, &finish, frames, nFrames);
9357 /* Be sure end square is redrawn */
9358 damage[toY][toX] = True;
9362 DragPieceBegin(x, y)
9365 int boardX, boardY, color;
9368 /* Are we animating? */
9369 if (!appData.animateDragging || appData.blindfold)
9372 /* Figure out which square we start in and the
9373 mouse position relative to top left corner. */
9374 BoardSquare(x, y, &boardX, &boardY);
9375 player.startBoardX = boardX;
9376 player.startBoardY = boardY;
9377 ScreenSquare(boardX, boardY, &corner, &color);
9378 player.startSquare = corner;
9379 player.startColor = color;
9381 /* Start from exactly where the piece is. This can be confusing
9382 if you start dragging far from the center of the square; most
9383 or all of the piece can be over a different square from the one
9384 the mouse pointer is in. */
9385 player.mouseDelta.x = x - corner.x;
9386 player.mouseDelta.y = y - corner.y;
9388 /* As soon as we start dragging, the piece will jump slightly to
9389 be centered over the mouse pointer. */
9390 player.mouseDelta.x = squareSize/2;
9391 player.mouseDelta.y = squareSize/2;
9393 /* Initialise animation */
9394 player.dragPiece = PieceForSquare(boardX, boardY);
9396 if (player.dragPiece >= 0 && player.dragPiece < EmptySquare) {
9397 player.dragActive = True;
9398 BeginAnimation(&player, player.dragPiece, color, &corner);
9399 /* Mark this square as needing to be redrawn. Note that
9400 we don't remove the piece though, since logically (ie
9401 as seen by opponent) the move hasn't been made yet. */
9402 if(boardX == BOARD_RGHT+1 && PieceForSquare(boardX-1, boardY) > 1 ||
9403 boardX == BOARD_LEFT-2 && PieceForSquare(boardX+1, boardY) > 1)
9404 XCopyArea(xDisplay, xBoardWindow, player.saveBuf, player.blitGC,
9405 corner.x, corner.y, squareSize, squareSize,
9406 0, 0); // [HGM] zh: unstack in stead of grab
9407 damage[boardY][boardX] = True;
9409 player.dragActive = False;
9419 /* Are we animating? */
9420 if (!appData.animateDragging || appData.blindfold)
9424 if (! player.dragActive)
9426 /* Move piece, maintaining same relative position
9427 of mouse within square */
9428 corner.x = x - player.mouseDelta.x;
9429 corner.y = y - player.mouseDelta.y;
9430 AnimationFrame(&player, &corner, player.dragPiece);
9432 if (appData.highlightDragging) {
9434 BoardSquare(x, y, &boardX, &boardY);
9435 SetHighlights(fromX, fromY, boardX, boardY);
9444 int boardX, boardY, color;
9447 /* Are we animating? */
9448 if (!appData.animateDragging || appData.blindfold)
9452 if (! player.dragActive)
9454 /* Last frame in sequence is square piece is
9455 placed on, which may not match mouse exactly. */
9456 BoardSquare(x, y, &boardX, &boardY);
9457 ScreenSquare(boardX, boardY, &corner, &color);
9458 EndAnimation(&player, &corner);
9460 /* Be sure end square is redrawn */
9461 damage[boardY][boardX] = True;
9463 /* This prevents weird things happening with fast successive
9464 clicks which on my Sun at least can cause motion events
9465 without corresponding press/release. */
9466 player.dragActive = False;
9469 /* Handle expose event while piece being dragged */
9474 if (!player.dragActive || appData.blindfold)
9477 /* What we're doing: logically, the move hasn't been made yet,
9478 so the piece is still in it's original square. But visually
9479 it's being dragged around the board. So we erase the square
9480 that the piece is on and draw it at the last known drag point. */
9481 BlankSquare(player.startSquare.x, player.startSquare.y,
9482 player.startColor, EmptySquare, xBoardWindow);
9483 AnimationFrame(&player, &player.prevFrame, player.dragPiece);
9484 damage[player.startBoardY][player.startBoardX] = TRUE;
9488 SetProgramStats( FrontEndProgramStats * stats )
9491 // [HGM] done, but perhaps backend should call this directly?
9492 EngineOutputUpdate( stats );