2 * xboard.c -- X front end for XBoard
4 * Copyright 1991 by Digital Equipment Corporation, Maynard,
7 * Enhancements Copyright 1992-2001, 2002, 2003, 2004, 2005, 2006,
8 * 2007, 2008, 2009 Free Software Foundation, Inc.
10 * The following terms apply to Digital Equipment Corporation's copyright
12 * ------------------------------------------------------------------------
15 * Permission to use, copy, modify, and distribute this software and its
16 * documentation for any purpose and without fee is hereby granted,
17 * provided that the above copyright notice appear in all copies and that
18 * both that copyright notice and this permission notice appear in
19 * supporting documentation, and that the name of Digital not be
20 * used in advertising or publicity pertaining to distribution of the
21 * software without specific, written prior permission.
23 * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
24 * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
25 * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
26 * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
27 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
28 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
30 * ------------------------------------------------------------------------
32 * The following terms apply to the enhanced version of XBoard
33 * distributed by the Free Software Foundation:
34 * ------------------------------------------------------------------------
36 * GNU XBoard is free software: you can redistribute it and/or modify
37 * it under the terms of the GNU General Public License as published by
38 * the Free Software Foundation, either version 3 of the License, or (at
39 * your option) any later version.
41 * GNU XBoard is distributed in the hope that it will be useful, but
42 * WITHOUT ANY WARRANTY; without even the implied warranty of
43 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
44 * General Public License for more details.
46 * You should have received a copy of the GNU General Public License
47 * along with this program. If not, see http://www.gnu.org/licenses/. *
49 *------------------------------------------------------------------------
50 ** See the file ChangeLog for a revision history. */
58 #include <sys/types.h>
63 # if HAVE_SYS_SOCKET_H
64 # include <sys/socket.h>
65 # include <netinet/in.h>
67 # else /* not HAVE_SYS_SOCKET_H */
68 # if HAVE_LAN_SOCKET_H
69 # include <lan/socket.h>
71 # include <lan/netdb.h>
72 # else /* not HAVE_LAN_SOCKET_H */
73 # define OMIT_SOCKETS 1
74 # endif /* not HAVE_LAN_SOCKET_H */
75 # endif /* not HAVE_SYS_SOCKET_H */
76 #endif /* !OMIT_SOCKETS */
81 #else /* not STDC_HEADERS */
82 extern char *getenv();
85 # else /* not HAVE_STRING_H */
87 # endif /* not HAVE_STRING_H */
88 #endif /* not STDC_HEADERS */
91 # include <sys/fcntl.h>
92 #else /* not HAVE_SYS_FCNTL_H */
95 # endif /* HAVE_FCNTL_H */
96 #endif /* not HAVE_SYS_FCNTL_H */
98 #if HAVE_SYS_SYSTEMINFO_H
99 # include <sys/systeminfo.h>
100 #endif /* HAVE_SYS_SYSTEMINFO_H */
102 #if TIME_WITH_SYS_TIME
103 # include <sys/time.h>
107 # include <sys/time.h>
118 # include <sys/wait.h>
123 # define NAMLEN(dirent) strlen((dirent)->d_name)
124 # define HAVE_DIR_STRUCT
126 # define dirent direct
127 # define NAMLEN(dirent) (dirent)->d_namlen
129 # include <sys/ndir.h>
130 # define HAVE_DIR_STRUCT
133 # include <sys/dir.h>
134 # define HAVE_DIR_STRUCT
138 # define HAVE_DIR_STRUCT
142 #include <X11/Intrinsic.h>
143 #include <X11/StringDefs.h>
144 #include <X11/Shell.h>
145 #include <X11/cursorfont.h>
146 #include <X11/Xatom.h>
148 #include <X11/Xaw3d/Dialog.h>
149 #include <X11/Xaw3d/Form.h>
150 #include <X11/Xaw3d/List.h>
151 #include <X11/Xaw3d/Label.h>
152 #include <X11/Xaw3d/SimpleMenu.h>
153 #include <X11/Xaw3d/SmeBSB.h>
154 #include <X11/Xaw3d/SmeLine.h>
155 #include <X11/Xaw3d/Box.h>
156 #include <X11/Xaw3d/MenuButton.h>
157 #include <X11/Xaw3d/Text.h>
158 #include <X11/Xaw3d/AsciiText.h>
160 #include <X11/Xaw/Dialog.h>
161 #include <X11/Xaw/Form.h>
162 #include <X11/Xaw/List.h>
163 #include <X11/Xaw/Label.h>
164 #include <X11/Xaw/SimpleMenu.h>
165 #include <X11/Xaw/SmeBSB.h>
166 #include <X11/Xaw/SmeLine.h>
167 #include <X11/Xaw/Box.h>
168 #include <X11/Xaw/MenuButton.h>
169 #include <X11/Xaw/Text.h>
170 #include <X11/Xaw/AsciiText.h>
173 // [HGM] bitmaps: put before incuding the bitmaps / pixmaps, to know how many piece types there are.
178 #include "pixmaps/pixmaps.h"
179 #define IMAGE_EXT "xpm"
181 #define IMAGE_EXT "xim"
182 #include "bitmaps/bitmaps.h"
185 #include "bitmaps/icon_white.bm"
186 #include "bitmaps/icon_black.bm"
187 #include "bitmaps/checkmark.bm"
189 #include "frontend.h"
194 #include "xgamelist.h"
195 #include "xhistory.h"
196 #include "xedittags.h"
199 // must be moved to xengineoutput.h
201 void EngineOutputProc P((Widget w, XEvent *event,
202 String *prms, Cardinal *nprms));
204 void EngineOutputPopDown();
211 #define usleep(t) _sleep2(((t)+500)/1000)
215 # define _(s) gettext (s)
216 # define N_(s) gettext_noop (s)
232 int main P((int argc, char **argv));
233 RETSIGTYPE CmailSigHandler P((int sig));
234 RETSIGTYPE IntSigHandler P((int sig));
235 void CreateGCs P((void));
236 void CreateXIMPieces P((void));
237 void CreateXPMPieces P((void));
238 void CreatePieces P((void));
239 void CreatePieceMenus P((void));
240 Widget CreateMenuBar P((Menu *mb));
241 Widget CreateButtonBar P ((MenuItem *mi));
242 char *FindFont P((char *pattern, int targetPxlSize));
243 void PieceMenuPopup P((Widget w, XEvent *event,
244 String *params, Cardinal *num_params));
245 static void PieceMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
246 static void DropMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
247 void ReadBitmap P((Pixmap *pm, String name, unsigned char bits[],
248 u_int wreq, u_int hreq));
249 void CreateGrid P((void));
250 int EventToSquare P((int x, int limit));
251 void DrawSquare P((int row, int column, ChessSquare piece, int do_flash));
252 void EventProc P((Widget widget, caddr_t unused, XEvent *event));
253 void HandleUserMove P((Widget w, XEvent *event,
254 String *prms, Cardinal *nprms));
255 void AnimateUserMove P((Widget w, XEvent * event,
256 String * params, Cardinal * nParams));
257 void WhiteClock P((Widget w, XEvent *event,
258 String *prms, Cardinal *nprms));
259 void BlackClock P((Widget w, XEvent *event,
260 String *prms, Cardinal *nprms));
261 void DrawPositionProc P((Widget w, XEvent *event,
262 String *prms, Cardinal *nprms));
263 void XDrawPosition P((Widget w, /*Boolean*/int repaint,
265 void CommentPopUp P((char *title, char *label));
266 void CommentPopDown P((void));
267 void CommentCallback P((Widget w, XtPointer client_data,
268 XtPointer call_data));
269 void ICSInputBoxPopUp P((void));
270 void ICSInputBoxPopDown P((void));
271 void FileNamePopUp P((char *label, char *def,
272 FileProc proc, char *openMode));
273 void FileNamePopDown P((void));
274 void FileNameCallback P((Widget w, XtPointer client_data,
275 XtPointer call_data));
276 void FileNameAction P((Widget w, XEvent *event,
277 String *prms, Cardinal *nprms));
278 void AskQuestionReplyAction P((Widget w, XEvent *event,
279 String *prms, Cardinal *nprms));
280 void AskQuestionProc P((Widget w, XEvent *event,
281 String *prms, Cardinal *nprms));
282 void AskQuestionPopDown P((void));
283 void PromotionPopUp P((void));
284 void PromotionPopDown P((void));
285 void PromotionCallback P((Widget w, XtPointer client_data,
286 XtPointer call_data));
287 void EditCommentPopDown P((void));
288 void EditCommentCallback P((Widget w, XtPointer client_data,
289 XtPointer call_data));
290 void SelectCommand P((Widget w, XtPointer client_data, XtPointer call_data));
291 void ResetProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
292 void LoadGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
293 void LoadNextGameProc P((Widget w, XEvent *event, String *prms,
295 void LoadPrevGameProc P((Widget w, XEvent *event, String *prms,
297 void ReloadGameProc P((Widget w, XEvent *event, String *prms,
299 void LoadPositionProc P((Widget w, XEvent *event,
300 String *prms, Cardinal *nprms));
301 void LoadNextPositionProc P((Widget w, XEvent *event, String *prms,
303 void LoadPrevPositionProc P((Widget w, XEvent *event, String *prms,
305 void ReloadPositionProc P((Widget w, XEvent *event, String *prms,
307 void CopyPositionProc P((Widget w, XEvent *event, String *prms,
309 void PastePositionProc P((Widget w, XEvent *event, String *prms,
311 void CopyGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
312 void PasteGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
313 void SaveGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
314 void SavePositionProc P((Widget w, XEvent *event,
315 String *prms, Cardinal *nprms));
316 void MailMoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
317 void ReloadCmailMsgProc P((Widget w, XEvent *event, String *prms,
319 void QuitProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
320 void PauseProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
321 void MachineBlackProc P((Widget w, XEvent *event, String *prms,
323 void MachineWhiteProc P((Widget w, XEvent *event,
324 String *prms, Cardinal *nprms));
325 void AnalyzeModeProc P((Widget w, XEvent *event,
326 String *prms, Cardinal *nprms));
327 void AnalyzeFileProc P((Widget w, XEvent *event,
328 String *prms, Cardinal *nprms));
329 void TwoMachinesProc P((Widget w, XEvent *event, String *prms,
331 void IcsClientProc P((Widget w, XEvent *event, String *prms,
333 void EditGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
334 void EditPositionProc P((Widget w, XEvent *event,
335 String *prms, Cardinal *nprms));
336 void TrainingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
337 void EditCommentProc P((Widget w, XEvent *event,
338 String *prms, Cardinal *nprms));
339 void IcsInputBoxProc P((Widget w, XEvent *event,
340 String *prms, Cardinal *nprms));
341 void AcceptProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
342 void DeclineProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
343 void RematchProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
344 void CallFlagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
345 void DrawProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
346 void AbortProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
347 void AdjournProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
348 void ResignProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
349 void AdjuWhiteProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
350 void AdjuBlackProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
351 void AdjuDrawProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
352 void EnterKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
353 void StopObservingProc P((Widget w, XEvent *event, String *prms,
355 void StopExaminingProc P((Widget w, XEvent *event, String *prms,
357 void BackwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
358 void ForwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
359 void ToStartProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
360 void ToEndProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
361 void RevertProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
362 void TruncateGameProc P((Widget w, XEvent *event, String *prms,
364 void RetractMoveProc P((Widget w, XEvent *event, String *prms,
366 void MoveNowProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
367 void AlwaysQueenProc P((Widget w, XEvent *event, String *prms,
369 void AnimateDraggingProc P((Widget w, XEvent *event, String *prms,
371 void AnimateMovingProc P((Widget w, XEvent *event, String *prms,
373 void AutocommProc P((Widget w, XEvent *event, String *prms,
375 void AutoflagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
376 void AutoflipProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
377 void AutobsProc P((Widget w, XEvent *event, String *prms,
379 void AutoraiseProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
380 void AutosaveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
381 void BlindfoldProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
382 void FlashMovesProc P((Widget w, XEvent *event, String *prms,
384 void FlipViewProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
385 void GetMoveListProc P((Widget w, XEvent *event, String *prms,
387 void HighlightDraggingProc P((Widget w, XEvent *event, String *prms,
389 void HighlightLastMoveProc P((Widget w, XEvent *event, String *prms,
391 void MoveSoundProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
392 void IcsAlarmProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
393 void OldSaveStyleProc P((Widget w, XEvent *event, String *prms,
395 void PeriodicUpdatesProc P((Widget w, XEvent *event, String *prms,
397 void PonderNextMoveProc P((Widget w, XEvent *event, String *prms,
399 void PopupMoveErrorsProc P((Widget w, XEvent *event, String *prms,
401 void PopupExitMessageProc P((Widget w, XEvent *event, String *prms,
403 void PremoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
404 void QuietPlayProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
405 void ShowCoordsProc P((Widget w, XEvent *event, String *prms,
407 void ShowThinkingProc P((Widget w, XEvent *event, String *prms,
409 void HideThinkingProc P((Widget w, XEvent *event, String *prms,
411 void TestLegalityProc P((Widget w, XEvent *event, String *prms,
413 void InfoProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
414 void ManProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
415 void HintProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
416 void BookProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
417 void AboutGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
418 void AboutProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
419 void DebugProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
420 void NothingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
421 void Iconify P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
422 void DisplayMove P((int moveNumber));
423 void DisplayTitle P((char *title));
424 void ICSInitScript P((void));
425 int LoadGamePopUp P((FILE *f, int gameNumber, char *title));
426 void ErrorPopUp P((char *title, char *text, int modal));
427 void ErrorPopDown P((void));
428 static char *ExpandPathName P((char *path));
429 static void CreateAnimVars P((void));
430 static void DragPieceBegin P((int x, int y));
431 static void DragPieceMove P((int x, int y));
432 static void DragPieceEnd P((int x, int y));
433 static void DrawDragPiece P((void));
434 char *ModeToWidgetName P((GameMode mode));
435 void EngineOutputUpdate( FrontEndProgramStats * stats );
436 void ShuffleMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
437 void EngineMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
438 void UciMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
439 void TimeControlProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
440 void NewVariantProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
441 void FirstSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
442 void SecondSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
443 void ShufflePopDown P(());
444 void EnginePopDown P(());
445 void UciPopDown P(());
446 void TimeControlPopDown P(());
447 void NewVariantPopDown P(());
448 void SettingsPopDown P(());
450 * XBoard depends on Xt R4 or higher
452 int xtVersion = XtSpecificationRelease;
457 Pixel lightSquareColor, darkSquareColor, whitePieceColor, blackPieceColor,
458 jailSquareColor, highlightSquareColor, premoveHighlightColor;
459 Pixel lowTimeWarningColor;
460 GC lightSquareGC, darkSquareGC, jailSquareGC, lineGC, wdPieceGC, wlPieceGC,
461 bdPieceGC, blPieceGC, wbPieceGC, bwPieceGC, coordGC, highlineGC,
462 wjPieceGC, bjPieceGC, prelineGC, countGC;
463 Pixmap iconPixmap, wIconPixmap, bIconPixmap, xMarkPixmap;
464 Widget shellWidget, layoutWidget, formWidget, boardWidget, messageWidget,
465 whiteTimerWidget, blackTimerWidget, titleWidget, widgetList[16],
466 commentShell, promotionShell, whitePieceMenu, blackPieceMenu, dropMenu,
467 menuBarWidget, buttonBarWidget, editShell, errorShell, analysisShell,
468 ICSInputShell, fileNameShell, askQuestionShell;
469 XSegment gridSegments[(BOARD_SIZE + 1) * 2];
470 XSegment jailGridSegments[(BOARD_SIZE + 3) * 2];
471 Font clockFontID, coordFontID, countFontID;
472 XFontStruct *clockFontStruct, *coordFontStruct, *countFontStruct;
473 XtAppContext appContext;
475 char *oldICSInteractionTitle;
479 char installDir[] = "."; // [HGM] UCI: needed for UCI; probably needs run-time initializtion
481 Position commentX = -1, commentY = -1;
482 Dimension commentW, commentH;
484 int squareSize, smallLayout = 0, tinyLayout = 0,
485 marginW, marginH, // [HGM] for run-time resizing
486 fromX = -1, fromY = -1, toX, toY, commentUp = False, analysisUp = False,
487 ICSInputBoxUp = False, askQuestionUp = False,
488 filenameUp = False, promotionUp = False, pmFromX = -1, pmFromY = -1,
489 editUp = False, errorUp = False, errorExitStatus = -1, lineGap;
490 Pixel timerForegroundPixel, timerBackgroundPixel;
491 Pixel buttonForegroundPixel, buttonBackgroundPixel;
492 char *chessDir, *programName, *programVersion,
493 *gameCopyFilename, *gamePasteFilename;
497 Pixmap pieceBitmap[2][(int)BlackPawn];
498 Pixmap pieceBitmap2[2][(int)BlackPawn+4]; /* [HGM] pieces */
499 Pixmap xpmPieceBitmap[4][(int)BlackPawn]; /* LL, LD, DL, DD actually used*/
500 Pixmap xpmPieceBitmap2[4][(int)BlackPawn+4]; /* LL, LD, DL, DD set to select from */
501 Pixmap xpmLightSquare, xpmDarkSquare, xpmJailSquare;
502 int useImages, useImageSqs;
503 XImage *ximPieceBitmap[4][(int)BlackPawn+4]; /* LL, LD, DL, DD */
504 Pixmap ximMaskPm[(int)BlackPawn]; /* clipmasks, used for XIM pieces */
505 Pixmap ximMaskPm2[(int)BlackPawn+4]; /* clipmasks, used for XIM pieces */
506 XImage *ximLightSquare, *ximDarkSquare;
509 #define pieceToSolid(piece) &pieceBitmap[SOLID][(piece) % (int)BlackPawn]
510 #define pieceToOutline(piece) &pieceBitmap[OUTLINE][(piece) % (int)BlackPawn]
512 #define White(piece) ((int)(piece) < (int)BlackPawn)
514 /* Variables for doing smooth animation. This whole thing
515 would be much easier if the board was double-buffered,
516 but that would require a fairly major rewrite. */
521 GC blitGC, pieceGC, outlineGC;
522 XPoint startSquare, prevFrame, mouseDelta;
526 int startBoardX, startBoardY;
529 /* There can be two pieces being animated at once: a player
530 can begin dragging a piece before the remote opponent has moved. */
532 static AnimState game, player;
534 /* Bitmaps for use as masks when drawing XPM pieces.
535 Need one for each black and white piece. */
536 static Pixmap xpmMask[BlackKing + 1];
538 /* This magic number is the number of intermediate frames used
539 in each half of the animation. For short moves it's reduced
540 by 1. The total number of frames will be factor * 2 + 1. */
543 SizeDefaults sizeDefaults[] = SIZE_DEFAULTS;
545 MenuItem fileMenu[] = {
546 {N_("New Game"), ResetProc},
547 {N_("New Shuffle Game ..."), ShuffleMenuProc},
548 {N_("New Variant ..."), NewVariantProc}, // [HGM] variant: not functional yet
549 {"----", NothingProc},
550 {N_("Load Game"), LoadGameProc},
551 {N_("Load Next Game"), LoadNextGameProc},
552 {N_("Load Previous Game"), LoadPrevGameProc},
553 {N_("Reload Same Game"), ReloadGameProc},
554 {N_("Save Game"), SaveGameProc},
555 {"----", NothingProc},
556 {N_("Copy Game"), CopyGameProc},
557 {N_("Paste Game"), PasteGameProc},
558 {"----", NothingProc},
559 {N_("Load Position"), LoadPositionProc},
560 {N_("Load Next Position"), LoadNextPositionProc},
561 {N_("Load Previous Position"), LoadPrevPositionProc},
562 {N_("Reload Same Position"), ReloadPositionProc},
563 {N_("Save Position"), SavePositionProc},
564 {"----", NothingProc},
565 {N_("Copy Position"), CopyPositionProc},
566 {N_("Paste Position"), PastePositionProc},
567 {"----", NothingProc},
568 {N_("Mail Move"), MailMoveProc},
569 {N_("Reload CMail Message"), ReloadCmailMsgProc},
570 {"----", NothingProc},
571 {N_("Exit"), QuitProc},
575 MenuItem modeMenu[] = {
576 {N_("Machine White"), MachineWhiteProc},
577 {N_("Machine Black"), MachineBlackProc},
578 {N_("Two Machines"), TwoMachinesProc},
579 {N_("Analysis Mode"), AnalyzeModeProc},
580 {N_("Analyze File"), AnalyzeFileProc },
581 {N_("ICS Client"), IcsClientProc},
582 {N_("Edit Game"), EditGameProc},
583 {N_("Edit Position"), EditPositionProc},
584 {N_("Training"), TrainingProc},
585 {"----", NothingProc},
586 {N_("Show Engine Output"), EngineOutputProc},
587 {N_("Show Evaluation Graph"), NothingProc}, // [HGM] evalgr: not functional yet
588 {N_("Show Game List"), ShowGameListProc},
589 {"Show Move History", HistoryShowProc}, // [HGM] hist: activate 4.2.7 code
590 {"----", NothingProc},
591 {N_("Edit Tags"), EditTagsProc},
592 {N_("Edit Comment"), EditCommentProc},
593 {N_("ICS Input Box"), IcsInputBoxProc},
594 {N_("Pause"), PauseProc},
598 MenuItem actionMenu[] = {
599 {N_("Accept"), AcceptProc},
600 {N_("Decline"), DeclineProc},
601 {N_("Rematch"), RematchProc},
602 {"----", NothingProc},
603 {N_("Call Flag"), CallFlagProc},
604 {N_("Draw"), DrawProc},
605 {N_("Adjourn"), AdjournProc},
606 {N_("Abort"), AbortProc},
607 {N_("Resign"), ResignProc},
608 {"----", NothingProc},
609 {N_("Stop Observing"), StopObservingProc},
610 {N_("Stop Examining"), StopExaminingProc},
611 {"----", NothingProc},
612 {N_("Adjudicate to White"), AdjuWhiteProc},
613 {N_("Adjudicate to Black"), AdjuBlackProc},
614 {N_("Adjudicate Draw"), AdjuDrawProc},
618 MenuItem stepMenu[] = {
619 {N_("Backward"), BackwardProc},
620 {N_("Forward"), ForwardProc},
621 {N_("Back to Start"), ToStartProc},
622 {N_("Forward to End"), ToEndProc},
623 {N_("Revert"), RevertProc},
624 {N_("Truncate Game"), TruncateGameProc},
625 {"----", NothingProc},
626 {N_("Move Now"), MoveNowProc},
627 {N_("Retract Move"), RetractMoveProc},
631 MenuItem optionsMenu[] = {
632 {N_("Flip View"), FlipViewProc},
633 {"----", NothingProc},
634 {N_("Adjudications ..."), EngineMenuProc},
635 {N_("General Settings ..."), UciMenuProc},
636 {N_("Engine #1 Settings ..."), FirstSettingsProc},
637 {N_("Engine #2 Settings ..."), SecondSettingsProc},
638 {N_("Time Control ..."), TimeControlProc},
639 {"----", NothingProc},
640 {N_("Always Queen"), AlwaysQueenProc},
641 {N_("Animate Dragging"), AnimateDraggingProc},
642 {N_("Animate Moving"), AnimateMovingProc},
643 {N_("Auto Comment"), AutocommProc},
644 {N_("Auto Flag"), AutoflagProc},
645 {N_("Auto Flip View"), AutoflipProc},
646 {N_("Auto Observe"), AutobsProc},
647 {N_("Auto Raise Board"), AutoraiseProc},
648 {N_("Auto Save"), AutosaveProc},
649 {N_("Blindfold"), BlindfoldProc},
650 {N_("Flash Moves"), FlashMovesProc},
651 {N_("Get Move List"), GetMoveListProc},
653 {N_("Highlight Dragging"), HighlightDraggingProc},
655 {N_("Highlight Last Move"), HighlightLastMoveProc},
656 {N_("Move Sound"), MoveSoundProc},
657 {N_("ICS Alarm"), IcsAlarmProc},
658 {N_("Old Save Style"), OldSaveStyleProc},
659 {N_("Periodic Updates"), PeriodicUpdatesProc},
660 {N_("Ponder Next Move"), PonderNextMoveProc},
661 {N_("Popup Exit Message"), PopupExitMessageProc},
662 {N_("Popup Move Errors"), PopupMoveErrorsProc},
663 {N_("Premove"), PremoveProc},
664 {N_("Quiet Play"), QuietPlayProc},
665 {N_("Show Coords"), ShowCoordsProc},
666 {N_("Hide Thinking"), HideThinkingProc},
667 {N_("Test Legality"), TestLegalityProc},
671 MenuItem helpMenu[] = {
672 {N_("Info XBoard"), InfoProc},
673 {N_("Man XBoard"), ManProc},
674 {"----", NothingProc},
675 {N_("Hint"), HintProc},
676 {N_("Book"), BookProc},
677 {"----", NothingProc},
678 {N_("About XBoard"), AboutProc},
683 {N_("File"), fileMenu},
684 {N_("Mode"), modeMenu},
685 {N_("Action"), actionMenu},
686 {N_("Step"), stepMenu},
687 {N_("Options"), optionsMenu},
688 {N_("Help"), helpMenu},
692 #define PAUSE_BUTTON N_("P")
693 MenuItem buttonBar[] = {
696 {PAUSE_BUTTON, PauseProc},
702 #define PIECE_MENU_SIZE 18
703 String pieceMenuStrings[2][PIECE_MENU_SIZE] = {
704 { N_("White"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
705 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
706 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
707 N_("Empty square"), N_("Clear board") },
708 { N_("Black"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
709 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
710 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
711 N_("Empty square"), N_("Clear board") }
713 /* must be in same order as PieceMenuStrings! */
714 ChessSquare pieceMenuTranslation[2][PIECE_MENU_SIZE] = {
715 { WhitePlay, (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
716 WhiteRook, WhiteQueen, WhiteKing, (ChessSquare) 0, WhiteAlfil,
717 WhiteCannon, WhiteAngel, WhiteMarshall, (ChessSquare) 0,
718 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
719 { BlackPlay, (ChessSquare) 0, BlackPawn, BlackKnight, BlackBishop,
720 BlackRook, BlackQueen, BlackKing, (ChessSquare) 0, BlackAlfil,
721 BlackCannon, BlackAngel, BlackMarshall, (ChessSquare) 0,
722 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
725 #define DROP_MENU_SIZE 6
726 String dropMenuStrings[DROP_MENU_SIZE] = {
727 "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"), N_("Queen")
729 /* must be in same order as PieceMenuStrings! */
730 ChessSquare dropMenuTranslation[DROP_MENU_SIZE] = {
731 (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
732 WhiteRook, WhiteQueen
740 DropMenuEnables dmEnables[] = {
758 { XtNborderWidth, 0 },
759 { XtNdefaultDistance, 0 },
763 { XtNborderWidth, 0 },
764 { XtNresizable, (XtArgVal) True },
768 { XtNborderWidth, 0 },
774 { XtNjustify, (XtArgVal) XtJustifyRight },
775 { XtNlabel, (XtArgVal) "..." },
776 { XtNresizable, (XtArgVal) True },
777 { XtNresize, (XtArgVal) False }
780 Arg messageArgs[] = {
781 { XtNjustify, (XtArgVal) XtJustifyLeft },
782 { XtNlabel, (XtArgVal) "..." },
783 { XtNresizable, (XtArgVal) True },
784 { XtNresize, (XtArgVal) False }
788 { XtNborderWidth, 0 },
789 { XtNjustify, (XtArgVal) XtJustifyLeft }
792 XtResource clientResources[] = {
793 { "whitePieceColor", "whitePieceColor", XtRString, sizeof(String),
794 XtOffset(AppDataPtr, whitePieceColor), XtRString,
796 { "blackPieceColor", "blackPieceColor", XtRString, sizeof(String),
797 XtOffset(AppDataPtr, blackPieceColor), XtRString,
799 { "lightSquareColor", "lightSquareColor", XtRString,
800 sizeof(String), XtOffset(AppDataPtr, lightSquareColor),
801 XtRString, LIGHT_SQUARE_COLOR },
802 { "darkSquareColor", "darkSquareColor", XtRString, sizeof(String),
803 XtOffset(AppDataPtr, darkSquareColor), XtRString,
805 { "highlightSquareColor", "highlightSquareColor", XtRString,
806 sizeof(String), XtOffset(AppDataPtr, highlightSquareColor),
807 XtRString, HIGHLIGHT_SQUARE_COLOR },
808 { "premoveHighlightColor", "premoveHighlightColor", XtRString,
809 sizeof(String), XtOffset(AppDataPtr, premoveHighlightColor),
810 XtRString, PREMOVE_HIGHLIGHT_COLOR },
811 { "movesPerSession", "movesPerSession", XtRInt, sizeof(int),
812 XtOffset(AppDataPtr, movesPerSession), XtRImmediate,
813 (XtPointer) MOVES_PER_SESSION },
814 { "timeIncrement", "timeIncrement", XtRInt, sizeof(int),
815 XtOffset(AppDataPtr, timeIncrement), XtRImmediate,
816 (XtPointer) TIME_INCREMENT },
817 { "initString", "initString", XtRString, sizeof(String),
818 XtOffset(AppDataPtr, initString), XtRString, INIT_STRING },
819 { "secondInitString", "secondInitString", XtRString, sizeof(String),
820 XtOffset(AppDataPtr, secondInitString), XtRString, INIT_STRING },
821 { "firstComputerString", "firstComputerString", XtRString,
822 sizeof(String), XtOffset(AppDataPtr, firstComputerString), XtRString,
824 { "secondComputerString", "secondComputerString", XtRString,
825 sizeof(String), XtOffset(AppDataPtr, secondComputerString), XtRString,
827 { "firstChessProgram", "firstChessProgram", XtRString,
828 sizeof(String), XtOffset(AppDataPtr, firstChessProgram),
829 XtRString, FIRST_CHESS_PROGRAM },
830 { "secondChessProgram", "secondChessProgram", XtRString,
831 sizeof(String), XtOffset(AppDataPtr, secondChessProgram),
832 XtRString, SECOND_CHESS_PROGRAM },
833 { "firstPlaysBlack", "firstPlaysBlack", XtRBoolean,
834 sizeof(Boolean), XtOffset(AppDataPtr, firstPlaysBlack),
835 XtRImmediate, (XtPointer) False },
836 { "noChessProgram", "noChessProgram", XtRBoolean,
837 sizeof(Boolean), XtOffset(AppDataPtr, noChessProgram),
838 XtRImmediate, (XtPointer) False },
839 { "firstHost", "firstHost", XtRString, sizeof(String),
840 XtOffset(AppDataPtr, firstHost), XtRString, FIRST_HOST },
841 { "secondHost", "secondHost", XtRString, sizeof(String),
842 XtOffset(AppDataPtr, secondHost), XtRString, SECOND_HOST },
843 { "firstDirectory", "firstDirectory", XtRString, sizeof(String),
844 XtOffset(AppDataPtr, firstDirectory), XtRString, "." },
845 { "secondDirectory", "secondDirectory", XtRString, sizeof(String),
846 XtOffset(AppDataPtr, secondDirectory), XtRString, "." },
847 { "bitmapDirectory", "bitmapDirectory", XtRString,
848 sizeof(String), XtOffset(AppDataPtr, bitmapDirectory),
850 { "remoteShell", "remoteShell", XtRString, sizeof(String),
851 XtOffset(AppDataPtr, remoteShell), XtRString, REMOTE_SHELL },
852 { "remoteUser", "remoteUser", XtRString, sizeof(String),
853 XtOffset(AppDataPtr, remoteUser), XtRString, "" },
854 { "timeDelay", "timeDelay", XtRFloat, sizeof(float),
855 XtOffset(AppDataPtr, timeDelay), XtRString,
856 (XtPointer) TIME_DELAY_QUOTE },
857 { "timeControl", "timeControl", XtRString, sizeof(String),
858 XtOffset(AppDataPtr, timeControl), XtRString,
859 (XtPointer) TIME_CONTROL },
860 { "internetChessServerMode", "internetChessServerMode",
861 XtRBoolean, sizeof(Boolean),
862 XtOffset(AppDataPtr, icsActive), XtRImmediate,
864 { "internetChessServerHost", "internetChessServerHost",
865 XtRString, sizeof(String),
866 XtOffset(AppDataPtr, icsHost),
867 XtRString, (XtPointer) ICS_HOST },
868 { "internetChessServerPort", "internetChessServerPort",
869 XtRString, sizeof(String),
870 XtOffset(AppDataPtr, icsPort), XtRString,
871 (XtPointer) ICS_PORT },
872 { "internetChessServerCommPort", "internetChessServerCommPort",
873 XtRString, sizeof(String),
874 XtOffset(AppDataPtr, icsCommPort), XtRString,
876 { "internetChessServerLogonScript", "internetChessServerLogonScript",
877 XtRString, sizeof(String),
878 XtOffset(AppDataPtr, icsLogon), XtRString,
880 { "internetChessServerHelper", "internetChessServerHelper",
881 XtRString, sizeof(String),
882 XtOffset(AppDataPtr, icsHelper), XtRString, "" },
883 { "internetChessServerInputBox", "internetChessServerInputBox",
884 XtRBoolean, sizeof(Boolean),
885 XtOffset(AppDataPtr, icsInputBox), XtRImmediate,
887 { "icsAlarm", "icsAlarm",
888 XtRBoolean, sizeof(Boolean),
889 XtOffset(AppDataPtr, icsAlarm), XtRImmediate,
891 { "icsAlarmTime", "icsAlarmTime",
893 XtOffset(AppDataPtr, icsAlarmTime), XtRImmediate,
895 { "useTelnet", "useTelnet", XtRBoolean, sizeof(Boolean),
896 XtOffset(AppDataPtr, useTelnet), XtRImmediate,
898 { "telnetProgram", "telnetProgram", XtRString, sizeof(String),
899 XtOffset(AppDataPtr, telnetProgram), XtRString, TELNET_PROGRAM },
900 { "gateway", "gateway", XtRString, sizeof(String),
901 XtOffset(AppDataPtr, gateway), XtRString, "" },
902 { "loadGameFile", "loadGameFile", XtRString, sizeof(String),
903 XtOffset(AppDataPtr, loadGameFile), XtRString, "" },
904 { "loadGameIndex", "loadGameIndex",
906 XtOffset(AppDataPtr, loadGameIndex), XtRImmediate,
908 { "saveGameFile", "saveGameFile", XtRString, sizeof(String),
909 XtOffset(AppDataPtr, saveGameFile), XtRString, "" },
910 { "autoRaiseBoard", "autoRaiseBoard", XtRBoolean,
911 sizeof(Boolean), XtOffset(AppDataPtr, autoRaiseBoard),
912 XtRImmediate, (XtPointer) True },
913 { "autoSaveGames", "autoSaveGames", XtRBoolean,
914 sizeof(Boolean), XtOffset(AppDataPtr, autoSaveGames),
915 XtRImmediate, (XtPointer) False },
916 { "blindfold", "blindfold", XtRBoolean,
917 sizeof(Boolean), XtOffset(AppDataPtr, blindfold),
918 XtRImmediate, (XtPointer) False },
919 { "loadPositionFile", "loadPositionFile", XtRString,
920 sizeof(String), XtOffset(AppDataPtr, loadPositionFile),
922 { "loadPositionIndex", "loadPositionIndex",
924 XtOffset(AppDataPtr, loadPositionIndex), XtRImmediate,
926 { "savePositionFile", "savePositionFile", XtRString,
927 sizeof(String), XtOffset(AppDataPtr, savePositionFile),
929 { "matchMode", "matchMode", XtRBoolean, sizeof(Boolean),
930 XtOffset(AppDataPtr, matchMode), XtRImmediate, (XtPointer) False },
931 { "matchGames", "matchGames", XtRInt, sizeof(int),
932 XtOffset(AppDataPtr, matchGames), XtRImmediate,
934 { "monoMode", "monoMode", XtRBoolean, sizeof(Boolean),
935 XtOffset(AppDataPtr, monoMode), XtRImmediate,
937 { "debugMode", "debugMode", XtRBoolean, sizeof(Boolean),
938 XtOffset(AppDataPtr, debugMode), XtRImmediate,
940 { "clockMode", "clockMode", XtRBoolean, sizeof(Boolean),
941 XtOffset(AppDataPtr, clockMode), XtRImmediate,
943 { "boardSize", "boardSize", XtRString, sizeof(String),
944 XtOffset(AppDataPtr, boardSize), XtRString, "" },
945 { "searchTime", "searchTime", XtRString, sizeof(String),
946 XtOffset(AppDataPtr, searchTime), XtRString,
948 { "searchDepth", "searchDepth", XtRInt, sizeof(int),
949 XtOffset(AppDataPtr, searchDepth), XtRImmediate,
951 { "showCoords", "showCoords", XtRBoolean, sizeof(Boolean),
952 XtOffset(AppDataPtr, showCoords), XtRImmediate,
954 { "showJail", "showJail", XtRInt, sizeof(int),
955 XtOffset(AppDataPtr, showJail), XtRImmediate,
957 { "showThinking", "showThinking", XtRBoolean, sizeof(Boolean),
958 XtOffset(AppDataPtr, showThinking), XtRImmediate,
960 { "ponderNextMove", "ponderNextMove", XtRBoolean, sizeof(Boolean),
961 XtOffset(AppDataPtr, ponderNextMove), XtRImmediate,
963 { "periodicUpdates", "periodicUpdates", XtRBoolean, sizeof(Boolean),
964 XtOffset(AppDataPtr, periodicUpdates), XtRImmediate,
966 { "clockFont", "clockFont", XtRString, sizeof(String),
967 XtOffset(AppDataPtr, clockFont), XtRString, CLOCK_FONT },
968 { "coordFont", "coordFont", XtRString, sizeof(String),
969 XtOffset(AppDataPtr, coordFont), XtRString, COORD_FONT },
970 { "font", "font", XtRString, sizeof(String),
971 XtOffset(AppDataPtr, font), XtRString, DEFAULT_FONT },
972 { "ringBellAfterMoves", "ringBellAfterMoves",
973 XtRBoolean, sizeof(Boolean),
974 XtOffset(AppDataPtr, ringBellAfterMoves),
975 XtRImmediate, (XtPointer) False },
976 { "autoCallFlag", "autoCallFlag", XtRBoolean,
977 sizeof(Boolean), XtOffset(AppDataPtr, autoCallFlag),
978 XtRImmediate, (XtPointer) False },
979 { "autoFlipView", "autoFlipView", XtRBoolean,
980 sizeof(Boolean), XtOffset(AppDataPtr, autoFlipView),
981 XtRImmediate, (XtPointer) True },
982 { "autoObserve", "autoObserve", XtRBoolean,
983 sizeof(Boolean), XtOffset(AppDataPtr, autoObserve),
984 XtRImmediate, (XtPointer) False },
985 { "autoComment", "autoComment", XtRBoolean,
986 sizeof(Boolean), XtOffset(AppDataPtr, autoComment),
987 XtRImmediate, (XtPointer) False },
988 { "getMoveList", "getMoveList", XtRBoolean,
989 sizeof(Boolean), XtOffset(AppDataPtr, getMoveList),
990 XtRImmediate, (XtPointer) True },
992 { "highlightDragging", "highlightDragging", XtRBoolean,
993 sizeof(Boolean), XtOffset(AppDataPtr, highlightDragging),
994 XtRImmediate, (XtPointer) False },
996 { "highlightLastMove", "highlightLastMove", XtRBoolean,
997 sizeof(Boolean), XtOffset(AppDataPtr, highlightLastMove),
998 XtRImmediate, (XtPointer) False },
999 { "premove", "premove", XtRBoolean,
1000 sizeof(Boolean), XtOffset(AppDataPtr, premove),
1001 XtRImmediate, (XtPointer) True },
1002 { "testLegality", "testLegality", XtRBoolean,
1003 sizeof(Boolean), XtOffset(AppDataPtr, testLegality),
1004 XtRImmediate, (XtPointer) True },
1005 { "flipView", "flipView", XtRBoolean,
1006 sizeof(Boolean), XtOffset(AppDataPtr, flipView),
1007 XtRImmediate, (XtPointer) False },
1008 { "cmail", "cmailGameName", XtRString, sizeof(String),
1009 XtOffset(AppDataPtr, cmailGameName), XtRString, "" },
1010 { "alwaysPromoteToQueen", "alwaysPromoteToQueen", XtRBoolean,
1011 sizeof(Boolean), XtOffset(AppDataPtr, alwaysPromoteToQueen),
1012 XtRImmediate, (XtPointer) False },
1013 { "oldSaveStyle", "oldSaveStyle", XtRBoolean,
1014 sizeof(Boolean), XtOffset(AppDataPtr, oldSaveStyle),
1015 XtRImmediate, (XtPointer) False },
1016 { "quietPlay", "quietPlay", XtRBoolean,
1017 sizeof(Boolean), XtOffset(AppDataPtr, quietPlay),
1018 XtRImmediate, (XtPointer) False },
1019 { "titleInWindow", "titleInWindow", XtRBoolean,
1020 sizeof(Boolean), XtOffset(AppDataPtr, titleInWindow),
1021 XtRImmediate, (XtPointer) False },
1022 { "localLineEditing", "localLineEditing", XtRBoolean,
1023 sizeof(Boolean), XtOffset(AppDataPtr, localLineEditing),
1024 XtRImmediate, (XtPointer) True }, /* not implemented, must be True */
1026 { "zippyTalk", "zippyTalk", XtRBoolean,
1027 sizeof(Boolean), XtOffset(AppDataPtr, zippyTalk),
1028 XtRImmediate, (XtPointer) ZIPPY_TALK },
1029 { "zippyPlay", "zippyPlay", XtRBoolean,
1030 sizeof(Boolean), XtOffset(AppDataPtr, zippyPlay),
1031 XtRImmediate, (XtPointer) ZIPPY_PLAY },
1032 { "zippyLines", "zippyLines", XtRString, sizeof(String),
1033 XtOffset(AppDataPtr, zippyLines), XtRString, ZIPPY_LINES },
1034 { "zippyPinhead", "zippyPinhead", XtRString, sizeof(String),
1035 XtOffset(AppDataPtr, zippyPinhead), XtRString, ZIPPY_PINHEAD },
1036 { "zippyPassword", "zippyPassword", XtRString, sizeof(String),
1037 XtOffset(AppDataPtr, zippyPassword), XtRString, ZIPPY_PASSWORD },
1038 { "zippyPassword2", "zippyPassword2", XtRString, sizeof(String),
1039 XtOffset(AppDataPtr, zippyPassword2), XtRString, ZIPPY_PASSWORD2 },
1040 { "zippyWrongPassword", "zippyWrongPassword", XtRString, sizeof(String),
1041 XtOffset(AppDataPtr, zippyWrongPassword), XtRString,
1042 ZIPPY_WRONG_PASSWORD },
1043 { "zippyAcceptOnly", "zippyAcceptOnly", XtRString, sizeof(String),
1044 XtOffset(AppDataPtr, zippyAcceptOnly), XtRString, ZIPPY_ACCEPT_ONLY },
1045 { "zippyUseI", "zippyUseI", XtRBoolean,
1046 sizeof(Boolean), XtOffset(AppDataPtr, zippyUseI),
1047 XtRImmediate, (XtPointer) ZIPPY_USE_I },
1048 { "zippyBughouse", "zippyBughouse", XtRInt,
1049 sizeof(int), XtOffset(AppDataPtr, zippyBughouse),
1050 XtRImmediate, (XtPointer) ZIPPY_BUGHOUSE },
1051 { "zippyNoplayCrafty", "zippyNoplayCrafty", XtRBoolean,
1052 sizeof(Boolean), XtOffset(AppDataPtr, zippyNoplayCrafty),
1053 XtRImmediate, (XtPointer) ZIPPY_NOPLAY_CRAFTY },
1054 { "zippyGameEnd", "zippyGameEnd", XtRString, sizeof(String),
1055 XtOffset(AppDataPtr, zippyGameEnd), XtRString, ZIPPY_GAME_END },
1056 { "zippyGameStart", "zippyGameStart", XtRString, sizeof(String),
1057 XtOffset(AppDataPtr, zippyGameStart), XtRString, ZIPPY_GAME_START },
1058 { "zippyAdjourn", "zippyAdjourn", XtRBoolean,
1059 sizeof(Boolean), XtOffset(AppDataPtr, zippyAdjourn),
1060 XtRImmediate, (XtPointer) ZIPPY_ADJOURN },
1061 { "zippyAbort", "zippyAbort", XtRBoolean,
1062 sizeof(Boolean), XtOffset(AppDataPtr, zippyAbort),
1063 XtRImmediate, (XtPointer) ZIPPY_ABORT },
1064 { "zippyVariants", "zippyVariants", XtRString, sizeof(String),
1065 XtOffset(AppDataPtr, zippyVariants), XtRString, ZIPPY_VARIANTS },
1066 { "zippyMaxGames", "zippyMaxGames", XtRInt, sizeof(int),
1067 XtOffset(AppDataPtr, zippyMaxGames), XtRImmediate,
1068 (XtPointer) ZIPPY_MAX_GAMES },
1069 { "zippyReplayTimeout", "zippyReplayTimeout", XtRInt, sizeof(int),
1070 XtOffset(AppDataPtr, zippyReplayTimeout), XtRImmediate,
1071 (XtPointer) ZIPPY_REPLAY_TIMEOUT },
1072 { "zippyShortGame", "zippyShortGame", XtRInt, sizeof(int),
1073 XtOffset(AppDataPtr, zippyShortGame), XtRImmediate,
1076 { "flashCount", "flashCount", XtRInt, sizeof(int),
1077 XtOffset(AppDataPtr, flashCount), XtRImmediate,
1078 (XtPointer) FLASH_COUNT },
1079 { "flashRate", "flashRate", XtRInt, sizeof(int),
1080 XtOffset(AppDataPtr, flashRate), XtRImmediate,
1081 (XtPointer) FLASH_RATE },
1082 { "pixmapDirectory", "pixmapDirectory", XtRString,
1083 sizeof(String), XtOffset(AppDataPtr, pixmapDirectory),
1085 { "msLoginDelay", "msLoginDelay", XtRInt, sizeof(int),
1086 XtOffset(AppDataPtr, msLoginDelay), XtRImmediate,
1087 (XtPointer) MS_LOGIN_DELAY },
1088 { "colorizeMessages", "colorizeMessages", XtRBoolean,
1089 sizeof(Boolean), XtOffset(AppDataPtr, colorize),
1090 XtRImmediate, (XtPointer) False },
1091 { "colorShout", "colorShout", XtRString,
1092 sizeof(String), XtOffset(AppDataPtr, colorShout),
1093 XtRString, COLOR_SHOUT },
1094 { "colorSShout", "colorSShout", XtRString,
1095 sizeof(String), XtOffset(AppDataPtr, colorSShout),
1096 XtRString, COLOR_SSHOUT },
1097 { "colorChannel1", "colorChannel1", XtRString,
1098 sizeof(String), XtOffset(AppDataPtr, colorChannel1),
1099 XtRString, COLOR_CHANNEL1 },
1100 { "colorChannel", "colorChannel", XtRString,
1101 sizeof(String), XtOffset(AppDataPtr, colorChannel),
1102 XtRString, COLOR_CHANNEL },
1103 { "colorKibitz", "colorKibitz", XtRString,
1104 sizeof(String), XtOffset(AppDataPtr, colorKibitz),
1105 XtRString, COLOR_KIBITZ },
1106 { "colorTell", "colorTell", XtRString,
1107 sizeof(String), XtOffset(AppDataPtr, colorTell),
1108 XtRString, COLOR_TELL },
1109 { "colorChallenge", "colorChallenge", XtRString,
1110 sizeof(String), XtOffset(AppDataPtr, colorChallenge),
1111 XtRString, COLOR_CHALLENGE },
1112 { "colorRequest", "colorRequest", XtRString,
1113 sizeof(String), XtOffset(AppDataPtr, colorRequest),
1114 XtRString, COLOR_REQUEST },
1115 { "colorSeek", "colorSeek", XtRString,
1116 sizeof(String), XtOffset(AppDataPtr, colorSeek),
1117 XtRString, COLOR_SEEK },
1118 { "colorNormal", "colorNormal", XtRString,
1119 sizeof(String), XtOffset(AppDataPtr, colorNormal),
1120 XtRString, COLOR_NORMAL },
1121 { "soundProgram", "soundProgram", XtRString,
1122 sizeof(String), XtOffset(AppDataPtr, soundProgram),
1123 XtRString, "play" },
1124 { "soundShout", "soundShout", XtRString,
1125 sizeof(String), XtOffset(AppDataPtr, soundShout),
1127 { "soundSShout", "soundSShout", XtRString,
1128 sizeof(String), XtOffset(AppDataPtr, soundSShout),
1130 { "soundChannel1", "soundChannel1", XtRString,
1131 sizeof(String), XtOffset(AppDataPtr, soundChannel1),
1133 { "soundChannel", "soundChannel", XtRString,
1134 sizeof(String), XtOffset(AppDataPtr, soundChannel),
1136 { "soundKibitz", "soundKibitz", XtRString,
1137 sizeof(String), XtOffset(AppDataPtr, soundKibitz),
1139 { "soundTell", "soundTell", XtRString,
1140 sizeof(String), XtOffset(AppDataPtr, soundTell),
1142 { "soundChallenge", "soundChallenge", XtRString,
1143 sizeof(String), XtOffset(AppDataPtr, soundChallenge),
1145 { "soundRequest", "soundRequest", XtRString,
1146 sizeof(String), XtOffset(AppDataPtr, soundRequest),
1148 { "soundSeek", "soundSeek", XtRString,
1149 sizeof(String), XtOffset(AppDataPtr, soundSeek),
1151 { "soundMove", "soundMove", XtRString,
1152 sizeof(String), XtOffset(AppDataPtr, soundMove),
1154 { "soundIcsWin", "soundIcsWin", XtRString,
1155 sizeof(String), XtOffset(AppDataPtr, soundIcsWin),
1157 { "soundIcsLoss", "soundIcsLoss", XtRString,
1158 sizeof(String), XtOffset(AppDataPtr, soundIcsLoss),
1160 { "soundIcsDraw", "soundIcsDraw", XtRString,
1161 sizeof(String), XtOffset(AppDataPtr, soundIcsDraw),
1163 { "soundIcsUnfinished", "soundIcsUnfinished", XtRString,
1164 sizeof(String), XtOffset(AppDataPtr, soundIcsUnfinished),
1166 { "soundIcsAlarm", "soundIcsAlarm", XtRString,
1167 sizeof(String), XtOffset(AppDataPtr, soundIcsAlarm),
1169 { "reuseFirst", "reuseFirst", XtRBoolean,
1170 sizeof(Boolean), XtOffset(AppDataPtr, reuseFirst),
1171 XtRImmediate, (XtPointer) True },
1172 { "reuseSecond", "reuseSecond", XtRBoolean,
1173 sizeof(Boolean), XtOffset(AppDataPtr, reuseSecond),
1174 XtRImmediate, (XtPointer) True },
1175 { "animateDragging", "animateDragging", XtRBoolean,
1176 sizeof(Boolean), XtOffset(AppDataPtr, animateDragging),
1177 XtRImmediate, (XtPointer) True },
1178 { "animateMoving", "animateMoving", XtRBoolean,
1179 sizeof(Boolean), XtOffset(AppDataPtr, animate),
1180 XtRImmediate, (XtPointer) True },
1181 { "animateSpeed", "animateSpeed", XtRInt,
1182 sizeof(int), XtOffset(AppDataPtr, animSpeed),
1183 XtRImmediate, (XtPointer)10 },
1184 { "popupExitMessage", "popupExitMessage", XtRBoolean,
1185 sizeof(Boolean), XtOffset(AppDataPtr, popupExitMessage),
1186 XtRImmediate, (XtPointer) True },
1187 { "popupMoveErrors", "popupMoveErrors", XtRBoolean,
1188 sizeof(Boolean), XtOffset(AppDataPtr, popupMoveErrors),
1189 XtRImmediate, (XtPointer) False },
1190 { "fontSizeTolerance", "fontSizeTolerance", XtRInt,
1191 sizeof(int), XtOffset(AppDataPtr, fontSizeTolerance),
1192 XtRImmediate, (XtPointer)4 },
1193 { "initialMode", "initialMode", XtRString,
1194 sizeof(String), XtOffset(AppDataPtr, initialMode),
1195 XtRImmediate, (XtPointer) "" },
1196 { "variant", "variant", XtRString,
1197 sizeof(String), XtOffset(AppDataPtr, variant),
1198 XtRImmediate, (XtPointer) "normal" },
1199 { "firstProtocolVersion", "firstProtocolVersion", XtRInt,
1200 sizeof(int), XtOffset(AppDataPtr, firstProtocolVersion),
1201 XtRImmediate, (XtPointer)PROTOVER },
1202 { "secondProtocolVersion", "secondProtocolVersion", XtRInt,
1203 sizeof(int), XtOffset(AppDataPtr, secondProtocolVersion),
1204 XtRImmediate, (XtPointer)PROTOVER },
1205 { "showButtonBar", "showButtonBar", XtRBoolean,
1206 sizeof(Boolean), XtOffset(AppDataPtr, showButtonBar),
1207 XtRImmediate, (XtPointer) True },
1208 { "lowTimeWarningColor", "lowTimeWarningColor", XtRString,
1209 sizeof(String), XtOffset(AppDataPtr, lowTimeWarningColor),
1210 XtRString, COLOR_LOWTIMEWARNING },
1211 { "lowTimeWarning", "lowTimeWarning", XtRBoolean,
1212 sizeof(Boolean), XtOffset(AppDataPtr, lowTimeWarning),
1213 XtRImmediate, (XtPointer) False },
1214 {"icsEngineAnalyze", "icsEngineAnalyze", XtRBoolean, /* [DM] icsEngineAnalyze */
1215 sizeof(Boolean), XtOffset(AppDataPtr, icsEngineAnalyze),
1216 XtRImmediate, (XtPointer) False },
1217 { "firstScoreAbs", "firstScoreAbs", XtRBoolean,
1218 sizeof(Boolean), XtOffset(AppDataPtr, firstScoreIsAbsolute),
1219 XtRImmediate, (XtPointer) False },
1220 { "secondScoreAbs", "secondScoreAbs", XtRBoolean,
1221 sizeof(Boolean), XtOffset(AppDataPtr, secondScoreIsAbsolute),
1222 XtRImmediate, (XtPointer) False },
1223 { "pgnExtendedInfo", "pgnExtendedInfo", XtRBoolean,
1224 sizeof(Boolean), XtOffset(AppDataPtr, saveExtendedInfoInPGN),
1225 XtRImmediate, (XtPointer) False },
1226 { "hideThinkingFromHuman", "hideThinkingFromHuman", XtRBoolean,
1227 sizeof(Boolean), XtOffset(AppDataPtr, hideThinkingFromHuman),
1228 XtRImmediate, (XtPointer) True },
1229 { "adjudicateLossThreshold", "adjudicateLossThreshold", XtRInt,
1230 sizeof(int), XtOffset(AppDataPtr, adjudicateLossThreshold),
1231 XtRImmediate, (XtPointer) 0},
1232 { "adjudicateDrawMoves", "adjudicateDrawMoves", XtRInt,
1233 sizeof(int), XtOffset(AppDataPtr, adjudicateDrawMoves),
1234 XtRImmediate, (XtPointer) 0},
1235 { "pgnEventHeader", "pgnEventHeader", XtRString,
1236 sizeof(String), XtOffset(AppDataPtr, pgnEventHeader),
1237 XtRImmediate, (XtPointer) "Computer Chess Game" },
1238 { "defaultFrcPosition", "defaultFrcPositon", XtRInt,
1239 sizeof(int), XtOffset(AppDataPtr, defaultFrcPosition),
1240 XtRImmediate, (XtPointer) -1},
1241 { "gameListTags", "gameListTags", XtRString,
1242 sizeof(String), XtOffset(AppDataPtr, gameListTags),
1243 XtRImmediate, (XtPointer) GLT_DEFAULT_TAGS },
1245 // [HGM] 4.3.xx options
1246 { "boardWidth", "boardWidth", XtRInt,
1247 sizeof(int), XtOffset(AppDataPtr, NrFiles),
1248 XtRImmediate, (XtPointer) -1},
1249 { "boardHeight", "boardHeight", XtRInt,
1250 sizeof(int), XtOffset(AppDataPtr, NrRanks),
1251 XtRImmediate, (XtPointer) -1},
1252 { "matchPause", "matchPause", XtRInt,
1253 sizeof(int), XtOffset(AppDataPtr, matchPause),
1254 XtRImmediate, (XtPointer) 10000},
1255 { "holdingsSize", "holdingsSize", XtRInt,
1256 sizeof(int), XtOffset(AppDataPtr, holdingsSize),
1257 XtRImmediate, (XtPointer) -1},
1258 { "flipBlack", "flipBlack", XtRBoolean,
1259 sizeof(Boolean), XtOffset(AppDataPtr, upsideDown),
1260 XtRImmediate, (XtPointer) False},
1261 { "allWhite", "allWhite", XtRBoolean,
1262 sizeof(Boolean), XtOffset(AppDataPtr, allWhite),
1263 XtRImmediate, (XtPointer) False},
1264 { "pieceToCharTable", "pieceToCharTable", XtRString,
1265 sizeof(String), XtOffset(AppDataPtr, pieceToCharTable),
1266 XtRImmediate, (XtPointer) 0},
1267 { "alphaRank", "alphaRank", XtRBoolean,
1268 sizeof(Boolean), XtOffset(AppDataPtr, alphaRank),
1269 XtRImmediate, (XtPointer) False},
1270 { "testClaims", "testClaims", XtRBoolean,
1271 sizeof(Boolean), XtOffset(AppDataPtr, testClaims),
1272 XtRImmediate, (XtPointer) True},
1273 { "checkMates", "checkMates", XtRBoolean,
1274 sizeof(Boolean), XtOffset(AppDataPtr, checkMates),
1275 XtRImmediate, (XtPointer) True},
1276 { "materialDraws", "materialDraws", XtRBoolean,
1277 sizeof(Boolean), XtOffset(AppDataPtr, materialDraws),
1278 XtRImmediate, (XtPointer) True},
1279 { "trivialDraws", "trivialDraws", XtRBoolean,
1280 sizeof(Boolean), XtOffset(AppDataPtr, trivialDraws),
1281 XtRImmediate, (XtPointer) False},
1282 { "ruleMoves", "ruleMoves", XtRInt,
1283 sizeof(int), XtOffset(AppDataPtr, ruleMoves),
1284 XtRImmediate, (XtPointer) 51},
1285 { "repeatsToDraw", "repeatsToDraw", XtRInt,
1286 sizeof(int), XtOffset(AppDataPtr, drawRepeats),
1287 XtRImmediate, (XtPointer) 6},
1288 { "engineDebugOutput", "engineDebugOutput", XtRInt,
1289 sizeof(int), XtOffset(AppDataPtr, engineComments),
1290 XtRImmediate, (XtPointer) 1},
1291 { "userName", "userName", XtRString,
1292 sizeof(int), XtOffset(AppDataPtr, userName),
1293 XtRImmediate, (XtPointer) 0},
1294 { "autoKibitz", "autoKibitz", XtRBoolean,
1295 sizeof(Boolean), XtOffset(AppDataPtr, autoKibitz),
1296 XtRImmediate, (XtPointer) False},
1297 { "firstTimeOdds", "firstTimeOdds", XtRInt,
1298 sizeof(int), XtOffset(AppDataPtr, firstTimeOdds),
1299 XtRImmediate, (XtPointer) 1},
1300 { "secondTimeOdds", "secondTimeOdds", XtRInt,
1301 sizeof(int), XtOffset(AppDataPtr, secondTimeOdds),
1302 XtRImmediate, (XtPointer) 1},
1303 { "timeOddsMode", "timeOddsMode", XtRInt,
1304 sizeof(int), XtOffset(AppDataPtr, timeOddsMode),
1305 XtRImmediate, (XtPointer) 0},
1306 { "firstAccumulateTC", "firstAccumulateTC", XtRInt,
1307 sizeof(int), XtOffset(AppDataPtr, firstAccumulateTC),
1308 XtRImmediate, (XtPointer) 1},
1309 { "secondAccumulateTC", "secondAccumulateTC", XtRInt,
1310 sizeof(int), XtOffset(AppDataPtr, secondAccumulateTC),
1311 XtRImmediate, (XtPointer) 1},
1312 { "firstNPS", "firstNPS", XtRInt,
1313 sizeof(int), XtOffset(AppDataPtr, firstNPS),
1314 XtRImmediate, (XtPointer) -1},
1315 { "secondNPS", "secondNPS", XtRInt,
1316 sizeof(int), XtOffset(AppDataPtr, secondNPS),
1317 XtRImmediate, (XtPointer) -1},
1318 { "serverMoves", "serverMoves", XtRString,
1319 sizeof(String), XtOffset(AppDataPtr, serverMovesName),
1320 XtRImmediate, (XtPointer) 0},
1321 { "serverPause", "serverPause", XtRInt,
1322 sizeof(int), XtOffset(AppDataPtr, serverPause),
1323 XtRImmediate, (XtPointer) 0},
1324 { "suppressLoadMoves", "suppressLoadMoves", XtRBoolean,
1325 sizeof(Boolean), XtOffset(AppDataPtr, suppressLoadMoves),
1326 XtRImmediate, (XtPointer) False},
1327 { "userName", "userName", XtRString,
1328 sizeof(String), XtOffset(AppDataPtr, userName),
1329 XtRImmediate, (XtPointer) 0},
1330 { "egtFormats", "egtFormats", XtRString,
1331 sizeof(String), XtOffset(AppDataPtr, egtFormats),
1332 XtRImmediate, (XtPointer) 0},
1333 { "rewindIndex", "rewindIndex", XtRInt,
1334 sizeof(int), XtOffset(AppDataPtr, rewindIndex),
1335 XtRImmediate, (XtPointer) 0},
1336 { "sameColorGames", "sameColorGames", XtRInt,
1337 sizeof(int), XtOffset(AppDataPtr, sameColorGames),
1338 XtRImmediate, (XtPointer) 0},
1339 { "smpCores", "smpCores", XtRInt,
1340 sizeof(int), XtOffset(AppDataPtr, smpCores),
1341 XtRImmediate, (XtPointer) 1},
1342 { "niceEngines", "niceEngines", XtRInt,
1343 sizeof(int), XtOffset(AppDataPtr, niceEngines),
1344 XtRImmediate, (XtPointer) 0},
1345 { "nameOfDebugFile", "nameOfDebugFile", XtRString,
1346 sizeof(String), XtOffset(AppDataPtr, nameOfDebugFile),
1347 XtRImmediate, (XtPointer) "xboard.debug"},
1348 { "engineDebugOutput", "engineDebugOutput", XtRInt,
1349 sizeof(int), XtOffset(AppDataPtr, engineComments),
1350 XtRImmediate, (XtPointer) 0},
1351 { "noGUI", "noGUI", XtRBoolean,
1352 sizeof(Boolean), XtOffset(AppDataPtr, noGUI),
1353 XtRImmediate, (XtPointer) 0},
1354 { "firstOptions", "firstOptions", XtRString,
1355 sizeof(String), XtOffset(AppDataPtr, firstOptions),
1356 XtRImmediate, (XtPointer) "" },
1357 { "secondOptions", "secondOptions", XtRString,
1358 sizeof(String), XtOffset(AppDataPtr, secondOptions),
1359 XtRImmediate, (XtPointer) "" },
1360 { "firstNeedsNoncompliantFEN", "firstNeedsNoncompliantFEN", XtRString,
1361 sizeof(String), XtOffset(AppDataPtr, fenOverride1),
1362 XtRImmediate, (XtPointer) 0 },
1363 { "secondNeedsNoncompliantFEN", "secondNeedsNoncompliantFEN", XtRString,
1364 sizeof(String), XtOffset(AppDataPtr, fenOverride2),
1365 XtRImmediate, (XtPointer) 0 },
1367 // [HGM] Winboard_x UCI options
1368 { "firstIsUCI", "firstIsUCI", XtRBoolean,
1369 sizeof(Boolean), XtOffset(AppDataPtr, firstIsUCI),
1370 XtRImmediate, (XtPointer) False},
1371 { "secondIsUCI", "secondIsUCI", XtRBoolean,
1372 sizeof(Boolean), XtOffset(AppDataPtr, secondIsUCI),
1373 XtRImmediate, (XtPointer) False},
1374 { "firstHasOwnBookUCI", "firstHasOwnBookUCI", XtRBoolean,
1375 sizeof(Boolean), XtOffset(AppDataPtr, firstHasOwnBookUCI),
1376 XtRImmediate, (XtPointer) True},
1377 { "secondHasOwnBookUCI", "secondHasOwnBookUCI", XtRBoolean,
1378 sizeof(Boolean), XtOffset(AppDataPtr, secondHasOwnBookUCI),
1379 XtRImmediate, (XtPointer) True},
1380 { "usePolyglotBook", "usePolyglotBook", XtRBoolean,
1381 sizeof(Boolean), XtOffset(AppDataPtr, usePolyglotBook),
1382 XtRImmediate, (XtPointer) False},
1383 { "defaultHashSize", "defaultHashSize", XtRInt,
1384 sizeof(int), XtOffset(AppDataPtr, defaultHashSize),
1385 XtRImmediate, (XtPointer) 64},
1386 { "defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XtRInt,
1387 sizeof(int), XtOffset(AppDataPtr, defaultCacheSizeEGTB),
1388 XtRImmediate, (XtPointer) 4},
1389 { "polyglotDir", "polyglotDir", XtRString,
1390 sizeof(String), XtOffset(AppDataPtr, polyglotDir),
1391 XtRImmediate, (XtPointer) "." },
1392 { "polyglotBook", "polyglotBook", XtRString,
1393 sizeof(String), XtOffset(AppDataPtr, polyglotBook),
1394 XtRImmediate, (XtPointer) "" },
1395 { "defaultPathEGTB", "defaultPathEGTB", XtRString,
1396 sizeof(String), XtOffset(AppDataPtr, defaultPathEGTB),
1397 XtRImmediate, (XtPointer) "/usr/local/share/egtb"},
1398 { "delayBeforeQuit", "delayBeforeQuit", XtRInt,
1399 sizeof(int), XtOffset(AppDataPtr, delayBeforeQuit),
1400 XtRImmediate, (XtPointer) 0},
1401 { "delayAfterQuit", "delayAfterQuit", XtRInt,
1402 sizeof(int), XtOffset(AppDataPtr, delayAfterQuit),
1403 XtRImmediate, (XtPointer) 0},
1406 XrmOptionDescRec shellOptions[] = {
1407 { "-whitePieceColor", "whitePieceColor", XrmoptionSepArg, NULL },
1408 { "-blackPieceColor", "blackPieceColor", XrmoptionSepArg, NULL },
1409 { "-lightSquareColor", "lightSquareColor", XrmoptionSepArg, NULL },
1410 { "-darkSquareColor", "darkSquareColor", XrmoptionSepArg, NULL },
1411 { "-highlightSquareColor", "highlightSquareColor", XrmoptionSepArg, NULL },
1412 { "-premoveHighlightColor", "premoveHighlightColor", XrmoptionSepArg,NULL},
1413 { "-movesPerSession", "movesPerSession", XrmoptionSepArg, NULL },
1414 { "-mps", "movesPerSession", XrmoptionSepArg, NULL },
1415 { "-timeIncrement", "timeIncrement", XrmoptionSepArg, NULL },
1416 { "-inc", "timeIncrement", XrmoptionSepArg, NULL },
1417 { "-initString", "initString", XrmoptionSepArg, NULL },
1418 { "-firstInitString", "initString", XrmoptionSepArg, NULL },
1419 { "-secondInitString", "secondInitString", XrmoptionSepArg, NULL },
1420 { "-firstComputerString", "firstComputerString", XrmoptionSepArg, NULL },
1421 { "-secondComputerString", "secondComputerString", XrmoptionSepArg, NULL },
1422 { "-firstChessProgram", "firstChessProgram", XrmoptionSepArg, NULL },
1423 { "-fcp", "firstChessProgram", XrmoptionSepArg, NULL },
1424 { "-secondChessProgram", "secondChessProgram", XrmoptionSepArg, NULL },
1425 { "-scp", "secondChessProgram", XrmoptionSepArg, NULL },
1426 { "-firstPlaysBlack", "firstPlaysBlack", XrmoptionSepArg, NULL },
1427 { "-fb", "firstPlaysBlack", XrmoptionNoArg, "True" },
1428 { "-xfb", "firstPlaysBlack", XrmoptionNoArg, "False" },
1429 { "-noChessProgram", "noChessProgram", XrmoptionSepArg, NULL },
1430 { "-ncp", "noChessProgram", XrmoptionNoArg, "True" },
1431 { "-xncp", "noChessProgram", XrmoptionNoArg, "False" },
1432 { "-firstHost", "firstHost", XrmoptionSepArg, NULL },
1433 { "-fh", "firstHost", XrmoptionSepArg, NULL },
1434 { "-secondHost", "secondHost", XrmoptionSepArg, NULL },
1435 { "-sh", "secondHost", XrmoptionSepArg, NULL },
1436 { "-firstDirectory", "firstDirectory", XrmoptionSepArg, NULL },
1437 { "-fd", "firstDirectory", XrmoptionSepArg, NULL },
1438 { "-secondDirectory", "secondDirectory", XrmoptionSepArg, NULL },
1439 { "-sd", "secondDirectory", XrmoptionSepArg, NULL },
1440 { "-bitmapDirectory", "bitmapDirectory", XrmoptionSepArg, NULL },
1441 { "-bm", "bitmapDirectory", XrmoptionSepArg, NULL },
1442 { "-remoteShell", "remoteShell", XrmoptionSepArg, NULL },
1443 { "-rsh", "remoteShell", XrmoptionSepArg, NULL },
1444 { "-remoteUser", "remoteUser", XrmoptionSepArg, NULL },
1445 { "-ruser", "remoteUser", XrmoptionSepArg, NULL },
1446 { "-timeDelay", "timeDelay", XrmoptionSepArg, NULL },
1447 { "-td", "timeDelay", XrmoptionSepArg, NULL },
1448 { "-timeControl", "timeControl", XrmoptionSepArg, NULL },
1449 { "-tc", "timeControl", XrmoptionSepArg, NULL },
1450 { "-internetChessServerMode", "internetChessServerMode",
1451 XrmoptionSepArg, NULL },
1452 { "-ics", "internetChessServerMode", XrmoptionNoArg, "True" },
1453 { "-xics", "internetChessServerMode", XrmoptionNoArg, "False" },
1454 { "-internetChessServerHost", "internetChessServerHost",
1455 XrmoptionSepArg, NULL },
1456 { "-icshost", "internetChessServerHost", XrmoptionSepArg, NULL },
1457 { "-internetChessServerPort", "internetChessServerPort",
1458 XrmoptionSepArg, NULL },
1459 { "-icsport", "internetChessServerPort", XrmoptionSepArg, NULL },
1460 { "-internetChessServerCommPort", "internetChessServerCommPort",
1461 XrmoptionSepArg, NULL },
1462 { "-icscomm", "internetChessServerCommPort", XrmoptionSepArg, NULL },
1463 { "-internetChessServerLogonScript", "internetChessServerLogonScript",
1464 XrmoptionSepArg, NULL },
1465 { "-icslogon", "internetChessServerLogonScript", XrmoptionSepArg, NULL },
1466 { "-internetChessServerHelper", "internetChessServerHelper",
1467 XrmoptionSepArg, NULL },
1468 { "-icshelper", "internetChessServerHelper", XrmoptionSepArg, NULL },
1469 { "-internetChessServerInputBox", "internetChessServerInputBox",
1470 XrmoptionSepArg, NULL },
1471 { "-icsinput", "internetChessServerInputBox", XrmoptionNoArg, "True" },
1472 { "-xicsinput", "internetChessServerInputBox", XrmoptionNoArg, "False" },
1473 { "-icsAlarm", "icsAlarm", XrmoptionSepArg, NULL },
1474 { "-alarm", "icsAlarm", XrmoptionNoArg, "True" },
1475 { "-xalarm", "icsAlarm", XrmoptionNoArg, "False" },
1476 { "-icsAlarmTime", "icsAlarmTime", XrmoptionSepArg, NULL },
1477 { "-useTelnet", "useTelnet", XrmoptionSepArg, NULL },
1478 { "-telnet", "useTelnet", XrmoptionNoArg, "True" },
1479 { "-xtelnet", "useTelnet", XrmoptionNoArg, "False" },
1480 { "-telnetProgram", "telnetProgram", XrmoptionSepArg, NULL },
1481 { "-gateway", "gateway", XrmoptionSepArg, NULL },
1482 { "-loadGameFile", "loadGameFile", XrmoptionSepArg, NULL },
1483 { "-lgf", "loadGameFile", XrmoptionSepArg, NULL },
1484 { "-loadGameIndex", "loadGameIndex", XrmoptionSepArg, NULL },
1485 { "-lgi", "loadGameIndex", XrmoptionSepArg, NULL },
1486 { "-saveGameFile", "saveGameFile", XrmoptionSepArg, NULL },
1487 { "-sgf", "saveGameFile", XrmoptionSepArg, NULL },
1488 { "-autoSaveGames", "autoSaveGames", XrmoptionSepArg, NULL },
1489 { "-autosave", "autoSaveGames", XrmoptionNoArg, "True" },
1490 { "-xautosave", "autoSaveGames", XrmoptionNoArg, "False" },
1491 { "-autoRaiseBoard", "autoRaiseBoard", XrmoptionSepArg, NULL },
1492 { "-autoraise", "autoRaiseBoard", XrmoptionNoArg, "True" },
1493 { "-xautoraise", "autoRaiseBoard", XrmoptionNoArg, "False" },
1494 { "-blindfold", "blindfold", XrmoptionSepArg, NULL },
1495 { "-blind", "blindfold", XrmoptionNoArg, "True" },
1496 { "-xblind", "blindfold", XrmoptionNoArg, "False" },
1497 { "-loadPositionFile", "loadPositionFile", XrmoptionSepArg, NULL },
1498 { "-lpf", "loadPositionFile", XrmoptionSepArg, NULL },
1499 { "-loadPositionIndex", "loadPositionIndex", XrmoptionSepArg, NULL },
1500 { "-lpi", "loadPositionIndex", XrmoptionSepArg, NULL },
1501 { "-savePositionFile", "savePositionFile", XrmoptionSepArg, NULL },
1502 { "-spf", "savePositionFile", XrmoptionSepArg, NULL },
1503 { "-matchMode", "matchMode", XrmoptionSepArg, NULL },
1504 { "-mm", "matchMode", XrmoptionNoArg, "True" },
1505 { "-xmm", "matchMode", XrmoptionNoArg, "False" },
1506 { "-matchGames", "matchGames", XrmoptionSepArg, NULL },
1507 { "-mg", "matchGames", XrmoptionSepArg, NULL },
1508 { "-monoMode", "monoMode", XrmoptionSepArg, NULL },
1509 { "-mono", "monoMode", XrmoptionNoArg, "True" },
1510 { "-xmono", "monoMode", XrmoptionNoArg, "False" },
1511 { "-debugMode", "debugMode", XrmoptionSepArg, NULL },
1512 { "-debug", "debugMode", XrmoptionNoArg, "True" },
1513 { "-xdebug", "debugMode", XrmoptionNoArg, "False" },
1514 { "-clockMode", "clockMode", XrmoptionSepArg, NULL },
1515 { "-clock", "clockMode", XrmoptionNoArg, "True" },
1516 { "-xclock", "clockMode", XrmoptionNoArg, "False" },
1517 { "-boardSize", "boardSize", XrmoptionSepArg, NULL },
1518 { "-size", "boardSize", XrmoptionSepArg, NULL },
1519 { "-searchTime", "searchTime", XrmoptionSepArg, NULL },
1520 { "-st", "searchTime", XrmoptionSepArg, NULL },
1521 { "-searchDepth", "searchDepth", XrmoptionSepArg, NULL },
1522 { "-depth", "searchDepth", XrmoptionSepArg, NULL },
1523 { "-showCoords", "showCoords", XrmoptionSepArg, NULL },
1524 { "-coords", "showCoords", XrmoptionNoArg, "True" },
1525 { "-xcoords", "showCoords", XrmoptionNoArg, "False" },
1527 { "-showJail", "showJail", XrmoptionSepArg, NULL },
1528 { "-jail", "showJail", XrmoptionNoArg, "1" },
1529 { "-sidejail", "showJail", XrmoptionNoArg, "2" },
1530 { "-xjail", "showJail", XrmoptionNoArg, "0" },
1532 { "-showThinking", "showThinking", XrmoptionSepArg, NULL },
1533 { "-thinking", "showThinking", XrmoptionNoArg, "True" },
1534 { "-xthinking", "showThinking", XrmoptionNoArg, "False" },
1535 { "-ponderNextMove", "ponderNextMove", XrmoptionSepArg, NULL },
1536 { "-ponder", "ponderNextMove", XrmoptionNoArg, "True" },
1537 { "-xponder", "ponderNextMove", XrmoptionNoArg, "False" },
1538 { "-periodicUpdates", "periodicUpdates", XrmoptionSepArg, NULL },
1539 { "-periodic", "periodicUpdates", XrmoptionNoArg, "True" },
1540 { "-xperiodic", "periodicUpdates", XrmoptionNoArg, "False" },
1541 { "-clockFont", "clockFont", XrmoptionSepArg, NULL },
1542 { "-coordFont", "coordFont", XrmoptionSepArg, NULL },
1543 { "-font", "font", XrmoptionSepArg, NULL },
1544 { "-ringBellAfterMoves", "ringBellAfterMoves", XrmoptionSepArg, NULL },
1545 { "-bell", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1546 { "-xbell", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1547 { "-movesound", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1548 { "-xmovesound", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1549 { "-autoCallFlag", "autoCallFlag", XrmoptionSepArg, NULL },
1550 { "-autoflag", "autoCallFlag", XrmoptionNoArg, "True" },
1551 { "-xautoflag", "autoCallFlag", XrmoptionNoArg, "False" },
1552 { "-autoFlipView", "autoFlipView", XrmoptionSepArg, NULL },
1553 { "-autoflip", "autoFlipView", XrmoptionNoArg, "True" },
1554 { "-xautoflip", "autoFlipView", XrmoptionNoArg, "False" },
1555 { "-autoObserve", "autoObserve", XrmoptionSepArg, NULL },
1556 { "-autobs", "autoObserve", XrmoptionNoArg, "True" },
1557 { "-xautobs", "autoObserve", XrmoptionNoArg, "False" },
1558 { "-autoComment", "autoComment", XrmoptionSepArg, NULL },
1559 { "-autocomm", "autoComment", XrmoptionNoArg, "True" },
1560 { "-xautocomm", "autoComment", XrmoptionNoArg, "False" },
1561 { "-getMoveList", "getMoveList", XrmoptionSepArg, NULL },
1562 { "-moves", "getMoveList", XrmoptionNoArg, "True" },
1563 { "-xmoves", "getMoveList", XrmoptionNoArg, "False" },
1565 { "-highlightDragging", "highlightDragging", XrmoptionSepArg, NULL },
1566 { "-highdrag", "highlightDragging", XrmoptionNoArg, "True" },
1567 { "-xhighdrag", "highlightDragging", XrmoptionNoArg, "False" },
1569 { "-highlightLastMove", "highlightLastMove", XrmoptionSepArg, NULL },
1570 { "-highlight", "highlightLastMove", XrmoptionNoArg, "True" },
1571 { "-xhighlight", "highlightLastMove", XrmoptionNoArg, "False" },
1572 { "-premove", "premove", XrmoptionSepArg, NULL },
1573 { "-pre", "premove", XrmoptionNoArg, "True" },
1574 { "-xpre", "premove", XrmoptionNoArg, "False" },
1575 { "-testLegality", "testLegality", XrmoptionSepArg, NULL },
1576 { "-legal", "testLegality", XrmoptionNoArg, "True" },
1577 { "-xlegal", "testLegality", XrmoptionNoArg, "False" },
1578 { "-flipView", "flipView", XrmoptionSepArg, NULL },
1579 { "-flip", "flipView", XrmoptionNoArg, "True" },
1580 { "-xflip", "flipView", XrmoptionNoArg, "False" },
1581 { "-cmail", "cmailGameName", XrmoptionSepArg, NULL },
1582 { "-alwaysPromoteToQueen", "alwaysPromoteToQueen",
1583 XrmoptionSepArg, NULL },
1584 { "-queen", "alwaysPromoteToQueen", XrmoptionNoArg, "True" },
1585 { "-xqueen", "alwaysPromoteToQueen", XrmoptionNoArg, "False" },
1586 { "-oldSaveStyle", "oldSaveStyle", XrmoptionSepArg, NULL },
1587 { "-oldsave", "oldSaveStyle", XrmoptionNoArg, "True" },
1588 { "-xoldsave", "oldSaveStyle", XrmoptionNoArg, "False" },
1589 { "-quietPlay", "quietPlay", XrmoptionSepArg, NULL },
1590 { "-quiet", "quietPlay", XrmoptionNoArg, "True" },
1591 { "-xquiet", "quietPlay", XrmoptionNoArg, "False" },
1592 { "-titleInWindow", "titleInWindow", XrmoptionSepArg, NULL },
1593 { "-title", "titleInWindow", XrmoptionNoArg, "True" },
1594 { "-xtitle", "titleInWindow", XrmoptionNoArg, "False" },
1596 { "-zippyTalk", "zippyTalk", XrmoptionSepArg, NULL },
1597 { "-zt", "zippyTalk", XrmoptionNoArg, "True" },
1598 { "-xzt", "zippyTalk", XrmoptionNoArg, "False" },
1599 { "-zippyPlay", "zippyPlay", XrmoptionSepArg, NULL },
1600 { "-zp", "zippyPlay", XrmoptionNoArg, "True" },
1601 { "-xzp", "zippyPlay", XrmoptionNoArg, "False" },
1602 { "-zippyLines", "zippyLines", XrmoptionSepArg, NULL },
1603 { "-zippyPinhead", "zippyPinhead", XrmoptionSepArg, NULL },
1604 { "-zippyPassword", "zippyPassword", XrmoptionSepArg, NULL },
1605 { "-zippyPassword2", "zippyPassword2", XrmoptionSepArg, NULL },
1606 { "-zippyWrongPassword", "zippyWrongPassword", XrmoptionSepArg, NULL },
1607 { "-zippyAcceptOnly", "zippyAcceptOnly", XrmoptionSepArg, NULL },
1608 { "-zippyUseI", "zippyUseI", XrmoptionSepArg, NULL },
1609 { "-zui", "zippyUseI", XrmoptionNoArg, "True" },
1610 { "-xzui", "zippyUseI", XrmoptionNoArg, "False" },
1611 { "-zippyBughouse", "zippyBughouse", XrmoptionSepArg, NULL },
1612 { "-zippyNoplayCrafty", "zippyNoplayCrafty", XrmoptionSepArg, NULL },
1613 { "-znc", "zippyNoplayCrafty", XrmoptionNoArg, "True" },
1614 { "-xznc", "zippyNoplayCrafty", XrmoptionNoArg, "False" },
1615 { "-zippyGameEnd", "zippyGameEnd", XrmoptionSepArg, NULL },
1616 { "-zippyGameStart", "zippyGameStart", XrmoptionSepArg, NULL },
1617 { "-zippyAdjourn", "zippyAdjourn", XrmoptionSepArg, NULL },
1618 { "-zadj", "zippyAdjourn", XrmoptionNoArg, "True" },
1619 { "-xzadj", "zippyAdjourn", XrmoptionNoArg, "False" },
1620 { "-zippyAbort", "zippyAbort", XrmoptionSepArg, NULL },
1621 { "-zab", "zippyAbort", XrmoptionNoArg, "True" },
1622 { "-xzab", "zippyAbort", XrmoptionNoArg, "False" },
1623 { "-zippyVariants", "zippyVariants", XrmoptionSepArg, NULL },
1624 { "-zippyMaxGames", "zippyMaxGames", XrmoptionSepArg, NULL },
1625 { "-zippyReplayTimeout", "zippyReplayTimeout", XrmoptionSepArg, NULL },
1626 { "-zippyShortGame", "zippyShortGame", XrmoptionSepArg, NULL },
1628 { "-flashCount", "flashCount", XrmoptionSepArg, NULL },
1629 { "-flash", "flashCount", XrmoptionNoArg, "3" },
1630 { "-xflash", "flashCount", XrmoptionNoArg, "0" },
1631 { "-flashRate", "flashRate", XrmoptionSepArg, NULL },
1632 { "-pixmapDirectory", "pixmapDirectory", XrmoptionSepArg, NULL },
1633 { "-msLoginDelay", "msLoginDelay", XrmoptionSepArg, NULL },
1634 { "-pixmap", "pixmapDirectory", XrmoptionSepArg, NULL },
1635 { "-colorizeMessages", "colorizeMessages", XrmoptionSepArg, NULL },
1636 { "-colorize", "colorizeMessages", XrmoptionNoArg, "True" },
1637 { "-xcolorize", "colorizeMessages", XrmoptionNoArg, "False" },
1638 { "-colorShout", "colorShout", XrmoptionSepArg, NULL },
1639 { "-colorSShout", "colorSShout", XrmoptionSepArg, NULL },
1640 { "-colorCShout", "colorSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1641 { "-colorChannel1", "colorChannel1", XrmoptionSepArg, NULL },
1642 { "-colorChannel", "colorChannel", XrmoptionSepArg, NULL },
1643 { "-colorKibitz", "colorKibitz", XrmoptionSepArg, NULL },
1644 { "-colorTell", "colorTell", XrmoptionSepArg, NULL },
1645 { "-colorChallenge", "colorChallenge", XrmoptionSepArg, NULL },
1646 { "-colorRequest", "colorRequest", XrmoptionSepArg, NULL },
1647 { "-colorSeek", "colorSeek", XrmoptionSepArg, NULL },
1648 { "-colorNormal", "colorNormal", XrmoptionSepArg, NULL },
1649 { "-soundProgram", "soundProgram", XrmoptionSepArg, NULL },
1650 { "-soundShout", "soundShout", XrmoptionSepArg, NULL },
1651 { "-soundSShout", "soundSShout", XrmoptionSepArg, NULL },
1652 { "-soundCShout", "soundSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1653 { "-soundChannel1", "soundChannel1", XrmoptionSepArg, NULL },
1654 { "-soundChannel", "soundChannel", XrmoptionSepArg, NULL },
1655 { "-soundKibitz", "soundKibitz", XrmoptionSepArg, NULL },
1656 { "-soundTell", "soundTell", XrmoptionSepArg, NULL },
1657 { "-soundChallenge", "soundChallenge", XrmoptionSepArg, NULL },
1658 { "-soundRequest", "soundRequest", XrmoptionSepArg, NULL },
1659 { "-soundSeek", "soundSeek", XrmoptionSepArg, NULL },
1660 { "-soundMove", "soundMove", XrmoptionSepArg, NULL },
1661 { "-soundIcsWin", "soundIcsWin", XrmoptionSepArg, NULL },
1662 { "-soundIcsLoss", "soundIcsLoss", XrmoptionSepArg, NULL },
1663 { "-soundIcsDraw", "soundIcsDraw", XrmoptionSepArg, NULL },
1664 { "-soundIcsUnfinished", "soundIcsUnfinished", XrmoptionSepArg, NULL },
1665 { "-soundIcsAlarm", "soundIcsAlarm", XrmoptionSepArg, NULL },
1666 { "-reuseFirst", "reuseFirst", XrmoptionSepArg, NULL },
1667 { "-reuseChessPrograms", "reuseFirst", XrmoptionSepArg, NULL }, /*compat*/
1668 { "-reuse", "reuseFirst", XrmoptionNoArg, "True" },
1669 { "-xreuse", "reuseFirst", XrmoptionNoArg, "False" },
1670 { "-reuseSecond", "reuseSecond", XrmoptionSepArg, NULL },
1671 { "-reuse2", "reuseSecond", XrmoptionNoArg, "True" },
1672 { "-xreuse2", "reuseSecond", XrmoptionNoArg, "False" },
1673 { "-animateMoving", "animateMoving", XrmoptionSepArg, NULL },
1674 { "-animate", "animateMoving", XrmoptionNoArg, "True" },
1675 { "-xanimate", "animateMoving", XrmoptionNoArg, "False" },
1676 { "-animateDragging", "animateDragging", XrmoptionSepArg, NULL },
1677 { "-drag", "animateDragging", XrmoptionNoArg, "True" },
1678 { "-xdrag", "animateDragging", XrmoptionNoArg, "False" },
1679 { "-animateSpeed", "animateSpeed", XrmoptionSepArg, NULL },
1680 { "-popupExitMessage", "popupExitMessage", XrmoptionSepArg, NULL },
1681 { "-exit", "popupExitMessage", XrmoptionNoArg, "True" },
1682 { "-xexit", "popupExitMessage", XrmoptionNoArg, "False" },
1683 { "-popupMoveErrors", "popupMoveErrors", XrmoptionSepArg, NULL },
1684 { "-popup", "popupMoveErrors", XrmoptionNoArg, "True" },
1685 { "-xpopup", "popupMoveErrors", XrmoptionNoArg, "False" },
1686 { "-fontSizeTolerance", "fontSizeTolerance", XrmoptionSepArg, NULL },
1687 { "-initialMode", "initialMode", XrmoptionSepArg, NULL },
1688 { "-mode", "initialMode", XrmoptionSepArg, NULL },
1689 { "-variant", "variant", XrmoptionSepArg, NULL },
1690 { "-firstProtocolVersion", "firstProtocolVersion", XrmoptionSepArg, NULL },
1691 { "-secondProtocolVersion","secondProtocolVersion",XrmoptionSepArg, NULL },
1692 { "-showButtonBar", "showButtonBar", XrmoptionSepArg, NULL },
1693 { "-buttons", "showButtonBar", XrmoptionNoArg, "True" },
1694 { "-xbuttons", "showButtonBar", XrmoptionNoArg, "False" },
1695 { "-lowTimeWarningColor", "lowTimeWarningColor", XrmoptionSepArg, NULL },
1696 { "-lowTimeWarning", "lowTimeWarning", XrmoptionSepArg, NULL },
1697 /* [AS,HR] New features */
1698 { "-firstScoreAbs", "firstScoreAbs", XrmoptionSepArg, NULL },
1699 { "-secondScoreAbs", "secondScoreAbs", XrmoptionSepArg, NULL },
1700 { "-pgnExtendedInfo", "pgnExtendedInfo", XrmoptionSepArg, NULL },
1701 { "-hideThinkingFromHuman", "hideThinkingFromHuman", XrmoptionSepArg, NULL },
1702 { "-adjudicateLossThreshold", "adjudicateLossThreshold", XrmoptionSepArg, NULL },
1703 { "-adjudicateDrawMoves", "adjudicateDrawMoves", XrmoptionSepArg, NULL },
1704 { "-pgnEventHeader", "pgnEventHeader", XrmoptionSepArg, NULL },
1705 { "-firstIsUCI", "firstIsUCI", XrmoptionSepArg, NULL },
1706 { "-secondIsUCI", "secondIsUCI", XrmoptionSepArg, NULL },
1707 { "-fUCI", "firstIsUCI", XrmoptionNoArg, "True" },
1708 { "-sUCI", "secondIsUCI", XrmoptionNoArg, "True" },
1709 { "-firstHasOwnBookUCI", "firstHasOwnBookUCI", XrmoptionSepArg, NULL },
1710 { "-secondHasOwnBookUCI", "secondHasOwnBookUCI", XrmoptionSepArg, NULL },
1711 { "-fNoOwnBookUCI", "firstHasOwnBookUCI", XrmoptionNoArg, "False" },
1712 { "-sNoOwnBookUCI", "secondHasOwnBookUCI", XrmoptionNoArg, "False" },
1713 { "-firstXBook", "firstHasOwnBookUCI", XrmoptionNoArg, "False" },
1714 { "-secondXBook", "secondHasOwnBookUCI", XrmoptionNoArg, "False" },
1715 { "-polyglotDir", "polyglotDir", XrmoptionSepArg, NULL },
1716 { "-usePolyglotBook", "usePolyglotBook", XrmoptionSepArg, NULL },
1717 { "-polyglotBook", "polyglotBook", XrmoptionSepArg, NULL },
1718 { "-defaultHashSize", "defaultHashSize", XrmoptionSepArg, NULL },
1719 { "-defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XrmoptionSepArg, NULL },
1720 { "-defaultPathEGTB", "defaultPathEGTB", XrmoptionSepArg, NULL },
1721 { "-defaultFrcPosition", "defaultFrcPosition", XrmoptionSepArg, NULL },
1722 { "-gameListTags", "gameListTags", XrmoptionSepArg, NULL },
1723 // [HGM] I am sure AS added many more options, but we have to fish them out, from the list in winboard.c
1725 /* [HGM,HR] User-selectable board size */
1726 { "-boardWidth", "boardWidth", XrmoptionSepArg, NULL },
1727 { "-boardHeight", "boardHeight", XrmoptionSepArg, NULL },
1728 { "-matchPause", "matchPause", XrmoptionSepArg, NULL },
1730 /* [HGM] new arguments of 4.3.xx. All except first three are back-end options, which should work immediately */
1731 { "-holdingsSize", "holdingsSize", XrmoptionSepArg, NULL }, // requires extensive front-end changes to work
1732 { "-flipBlack", "flipBlack", XrmoptionSepArg, NULL }, // requires front-end changes to work
1733 { "-allWhite", "allWhite", XrmoptionSepArg, NULL }, // requires front-end changes to work
1734 { "-pieceToCharTable", "pieceToCharTable", XrmoptionSepArg, NULL },
1735 { "-alphaRank", "alphaRank", XrmoptionSepArg, NULL },
1736 { "-testClaims", "testClaims", XrmoptionSepArg, NULL },
1737 { "-checkMates", "checkMates", XrmoptionSepArg, NULL },
1738 { "-materialDraws", "materialDraws", XrmoptionSepArg, NULL },
1739 { "-trivialDraws", "trivialDraws", XrmoptionSepArg, NULL },
1740 { "-ruleMoves", "ruleMoves", XrmoptionSepArg, NULL },
1741 { "-repeatsToDraw", "repeatsToDraw", XrmoptionSepArg, NULL },
1742 { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL },
1743 { "-userName", "userName", XrmoptionSepArg, NULL },
1744 { "-autoKibitz", "autoKibitz", XrmoptionNoArg, "True" },
1745 { "-firstTimeOdds", "firstTimeOdds", XrmoptionSepArg, NULL },
1746 { "-secondTimeOdds", "secondTimeOdds", XrmoptionSepArg, NULL },
1747 { "-timeOddsMode", "timeOddsMode", XrmoptionSepArg, NULL },
1748 { "-firstAccumulateTC", "firstAccumulateTC", XrmoptionSepArg, NULL },
1749 { "-secondAccumulateTC", "secondAccumulateTC", XrmoptionSepArg, NULL },
1750 { "-firstNPS", "firstNPS", XrmoptionSepArg, NULL },
1751 { "-secondNPS", "secondNPS", XrmoptionSepArg, NULL },
1752 { "-serverMoves", "serverMoves", XrmoptionSepArg, NULL },
1753 { "-serverPause", "serverPause", XrmoptionSepArg, NULL },
1754 { "-suppressLoadMoves", "suppressLoadMoves", XrmoptionSepArg, NULL },
1755 { "-egtFormats", "egtFormats", XrmoptionSepArg, NULL },
1756 { "-userName", "userName", XrmoptionSepArg, NULL },
1757 { "-smpCores", "smpCores", XrmoptionSepArg, NULL },
1758 { "-sameColorGames", "sameColorGames", XrmoptionSepArg, NULL },
1759 { "-rewindIndex", "rewindIndex", XrmoptionSepArg, NULL },
1760 { "-niceEngines", "niceEngines", XrmoptionSepArg, NULL },
1761 { "-delayBeforeQuit", "delayBeforeQuit", XrmoptionSepArg, NULL },
1762 { "-delayAfterQuit", "delayAfterQuit", XrmoptionSepArg, NULL },
1763 { "-nameOfDebugFile", "nameOfDebugFile", XrmoptionSepArg, NULL },
1764 { "-debugFile", "nameOfDebugFile", XrmoptionSepArg, NULL },
1765 { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL },
1766 { "-noGUI", "noGUI", XrmoptionNoArg, "True" },
1767 { "-firstOptions", "firstOptions", XrmoptionSepArg, NULL },
1768 { "-secondOptions", "secondOptions", XrmoptionSepArg, NULL },
1769 { "-firstNeedsNoncompliantFEN", "firstNeedsNoncompliantFEN", XrmoptionSepArg, NULL },
1770 { "-secondNeedsNoncompliantFEN", "secondNeedsNoncompliantFEN", XrmoptionSepArg, NULL },
1774 XtActionsRec boardActions[] = {
1775 { "DrawPosition", DrawPositionProc },
1776 { "HandleUserMove", HandleUserMove },
1777 { "AnimateUserMove", AnimateUserMove },
1778 { "FileNameAction", FileNameAction },
1779 { "AskQuestionProc", AskQuestionProc },
1780 { "AskQuestionReplyAction", AskQuestionReplyAction },
1781 { "PieceMenuPopup", PieceMenuPopup },
1782 { "WhiteClock", WhiteClock },
1783 { "BlackClock", BlackClock },
1784 { "Iconify", Iconify },
1785 { "ResetProc", ResetProc },
1786 { "LoadGameProc", LoadGameProc },
1787 { "LoadNextGameProc", LoadNextGameProc },
1788 { "LoadPrevGameProc", LoadPrevGameProc },
1789 { "LoadSelectedProc", LoadSelectedProc },
1790 { "ReloadGameProc", ReloadGameProc },
1791 { "LoadPositionProc", LoadPositionProc },
1792 { "LoadNextPositionProc", LoadNextPositionProc },
1793 { "LoadPrevPositionProc", LoadPrevPositionProc },
1794 { "ReloadPositionProc", ReloadPositionProc },
1795 { "CopyPositionProc", CopyPositionProc },
1796 { "PastePositionProc", PastePositionProc },
1797 { "CopyGameProc", CopyGameProc },
1798 { "PasteGameProc", PasteGameProc },
1799 { "SaveGameProc", SaveGameProc },
1800 { "SavePositionProc", SavePositionProc },
1801 { "MailMoveProc", MailMoveProc },
1802 { "ReloadCmailMsgProc", ReloadCmailMsgProc },
1803 { "QuitProc", QuitProc },
1804 { "MachineWhiteProc", MachineWhiteProc },
1805 { "MachineBlackProc", MachineBlackProc },
1806 { "AnalysisModeProc", AnalyzeModeProc },
1807 { "AnalyzeFileProc", AnalyzeFileProc },
1808 { "TwoMachinesProc", TwoMachinesProc },
1809 { "IcsClientProc", IcsClientProc },
1810 { "EditGameProc", EditGameProc },
1811 { "EditPositionProc", EditPositionProc },
1812 { "TrainingProc", EditPositionProc },
1813 { "EngineOutputProc", EngineOutputProc}, // [HGM] Winboard_x engine-output window
1814 { "ShowGameListProc", ShowGameListProc },
1815 { "ShowMoveListProc", HistoryShowProc},
1816 { "EditTagsProc", EditCommentProc },
1817 { "EditCommentProc", EditCommentProc },
1818 { "IcsAlarmProc", IcsAlarmProc },
1819 { "IcsInputBoxProc", IcsInputBoxProc },
1820 { "PauseProc", PauseProc },
1821 { "AcceptProc", AcceptProc },
1822 { "DeclineProc", DeclineProc },
1823 { "RematchProc", RematchProc },
1824 { "CallFlagProc", CallFlagProc },
1825 { "DrawProc", DrawProc },
1826 { "AdjournProc", AdjournProc },
1827 { "AbortProc", AbortProc },
1828 { "ResignProc", ResignProc },
1829 { "AdjuWhiteProc", AdjuWhiteProc },
1830 { "AdjuBlackProc", AdjuBlackProc },
1831 { "AdjuDrawProc", AdjuDrawProc },
1832 { "EnterKeyProc", EnterKeyProc },
1833 { "StopObservingProc", StopObservingProc },
1834 { "StopExaminingProc", StopExaminingProc },
1835 { "BackwardProc", BackwardProc },
1836 { "ForwardProc", ForwardProc },
1837 { "ToStartProc", ToStartProc },
1838 { "ToEndProc", ToEndProc },
1839 { "RevertProc", RevertProc },
1840 { "TruncateGameProc", TruncateGameProc },
1841 { "MoveNowProc", MoveNowProc },
1842 { "RetractMoveProc", RetractMoveProc },
1843 { "AlwaysQueenProc", AlwaysQueenProc },
1844 { "AnimateDraggingProc", AnimateDraggingProc },
1845 { "AnimateMovingProc", AnimateMovingProc },
1846 { "AutoflagProc", AutoflagProc },
1847 { "AutoflipProc", AutoflipProc },
1848 { "AutobsProc", AutobsProc },
1849 { "AutoraiseProc", AutoraiseProc },
1850 { "AutosaveProc", AutosaveProc },
1851 { "BlindfoldProc", BlindfoldProc },
1852 { "FlashMovesProc", FlashMovesProc },
1853 { "FlipViewProc", FlipViewProc },
1854 { "GetMoveListProc", GetMoveListProc },
1856 { "HighlightDraggingProc", HighlightDraggingProc },
1858 { "HighlightLastMoveProc", HighlightLastMoveProc },
1859 { "IcsAlarmProc", IcsAlarmProc },
1860 { "MoveSoundProc", MoveSoundProc },
1861 { "OldSaveStyleProc", OldSaveStyleProc },
1862 { "PeriodicUpdatesProc", PeriodicUpdatesProc },
1863 { "PonderNextMoveProc", PonderNextMoveProc },
1864 { "PopupExitMessageProc", PopupExitMessageProc },
1865 { "PopupMoveErrorsProc", PopupMoveErrorsProc },
1866 { "PremoveProc", PremoveProc },
1867 { "QuietPlayProc", QuietPlayProc },
1868 { "ShowCoordsProc", ShowCoordsProc },
1869 { "ShowThinkingProc", ShowThinkingProc },
1870 { "HideThinkingProc", HideThinkingProc },
1871 { "TestLegalityProc", TestLegalityProc },
1872 { "InfoProc", InfoProc },
1873 { "ManProc", ManProc },
1874 { "HintProc", HintProc },
1875 { "BookProc", BookProc },
1876 { "AboutGameProc", AboutGameProc },
1877 { "AboutProc", AboutProc },
1878 { "DebugProc", DebugProc },
1879 { "NothingProc", NothingProc },
1880 { "CommentPopDown", (XtActionProc) CommentPopDown },
1881 { "EditCommentPopDown", (XtActionProc) EditCommentPopDown },
1882 { "TagsPopDown", (XtActionProc) TagsPopDown },
1883 { "ErrorPopDown", (XtActionProc) ErrorPopDown },
1884 { "ICSInputBoxPopDown", (XtActionProc) ICSInputBoxPopDown },
1885 { "AnalysisPopDown", (XtActionProc) AnalysisPopDown },
1886 { "FileNamePopDown", (XtActionProc) FileNamePopDown },
1887 { "AskQuestionPopDown", (XtActionProc) AskQuestionPopDown },
1888 { "GameListPopDown", (XtActionProc) GameListPopDown },
1889 { "PromotionPopDown", (XtActionProc) PromotionPopDown },
1890 { "HistoryPopDown", (XtActionProc) HistoryPopDown },
1891 { "EngineOutputPopDown", (XtActionProc) EngineOutputPopDown },
1892 { "ShufflePopDown", (XtActionProc) ShufflePopDown },
1893 { "EnginePopDown", (XtActionProc) EnginePopDown },
1894 { "UciPopDown", (XtActionProc) UciPopDown },
1895 { "TimeControlPopDown", (XtActionProc) TimeControlPopDown },
1896 { "NewVariantPopDown", (XtActionProc) NewVariantPopDown },
1897 { "SettingsPopDown", (XtActionProc) SettingsPopDown },
1900 char globalTranslations[] =
1901 ":<Key>R: ResignProc() \n \
1902 :<Key>r: ResetProc() \n \
1903 :<Key>g: LoadGameProc() \n \
1904 :<Key>N: LoadNextGameProc() \n \
1905 :<Key>P: LoadPrevGameProc() \n \
1906 :<Key>Q: QuitProc() \n \
1907 :<Key>F: ToEndProc() \n \
1908 :<Key>f: ForwardProc() \n \
1909 :<Key>B: ToStartProc() \n \
1910 :<Key>b: BackwardProc() \n \
1911 :<Key>p: PauseProc() \n \
1912 :<Key>d: DrawProc() \n \
1913 :<Key>t: CallFlagProc() \n \
1914 :<Key>i: Iconify() \n \
1915 :<Key>c: Iconify() \n \
1916 :<Key>v: FlipViewProc() \n \
1917 <KeyDown>Control_L: BackwardProc() \n \
1918 <KeyUp>Control_L: ForwardProc() \n \
1919 <KeyDown>Control_R: BackwardProc() \n \
1920 <KeyUp>Control_R: ForwardProc() \n \
1921 Shift<Key>1: AskQuestionProc(\"Direct command\",\
1922 \"Send to chess program:\",,1) \n \
1923 Shift<Key>2: AskQuestionProc(\"Direct command\",\
1924 \"Send to second chess program:\",,2) \n";
1926 char boardTranslations[] =
1927 "<Btn1Down>: HandleUserMove() \n \
1928 <Btn1Up>: HandleUserMove() \n \
1929 <Btn1Motion>: AnimateUserMove() \n \
1930 Shift<Btn2Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD)\
1931 PieceMenuPopup(menuB) \n \
1932 Any<Btn2Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD) \
1933 PieceMenuPopup(menuW) \n \
1934 Shift<Btn3Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD)\
1935 PieceMenuPopup(menuW) \n \
1936 Any<Btn3Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD) \
1937 PieceMenuPopup(menuB) \n";
1939 char whiteTranslations[] = "<BtnDown>: WhiteClock()\n";
1940 char blackTranslations[] = "<BtnDown>: BlackClock()\n";
1942 char ICSInputTranslations[] =
1943 "<Key>Return: EnterKeyProc() \n";
1945 String xboardResources[] = {
1946 "*fileName*value.translations: #override\\n <Key>Return: FileNameAction()",
1947 "*question*value.translations: #override\\n <Key>Return: AskQuestionReplyAction()",
1948 "*errorpopup*translations: #override\\n <Key>Return: ErrorPopDown()",
1953 /* Max possible square size */
1954 #define MAXSQSIZE 256
1956 static int xpm_avail[MAXSQSIZE];
1958 #ifdef HAVE_DIR_STRUCT
1960 /* Extract piece size from filename */
1962 xpm_getsize(name, len, ext)
1973 if ((p=strchr(name, '.')) == NULL ||
1974 StrCaseCmp(p+1, ext) != 0)
1980 while (*p && isdigit(*p))
1987 /* Setup xpm_avail */
1989 xpm_getavail(dirname, ext)
1997 for (i=0; i<MAXSQSIZE; ++i)
2000 if (appData.debugMode)
2001 fprintf(stderr, "XPM dir:%s:ext:%s:\n", dirname, ext);
2003 dir = opendir(dirname);
2006 fprintf(stderr, _("%s: Can't access XPM directory %s\n"),
2007 programName, dirname);
2011 while ((ent=readdir(dir)) != NULL) {
2012 i = xpm_getsize(ent->d_name, NAMLEN(ent), ext);
2013 if (i > 0 && i < MAXSQSIZE)
2023 xpm_print_avail(fp, ext)
2029 fprintf(fp, _("Available `%s' sizes:\n"), ext);
2030 for (i=1; i<MAXSQSIZE; ++i) {
2036 /* Return XPM piecesize closest to size */
2038 xpm_closest_to(dirname, size, ext)
2044 int sm_diff = MAXSQSIZE;
2048 xpm_getavail(dirname, ext);
2050 if (appData.debugMode)
2051 xpm_print_avail(stderr, ext);
2053 for (i=1; i<MAXSQSIZE; ++i) {
2056 diff = (diff<0) ? -diff : diff;
2057 if (diff < sm_diff) {
2065 fprintf(stderr, _("Error: No `%s' files!\n"), ext);
2071 #else /* !HAVE_DIR_STRUCT */
2072 /* If we are on a system without a DIR struct, we can't
2073 read the directory, so we can't collect a list of
2074 filenames, etc., so we can't do any size-fitting. */
2076 xpm_closest_to(dirname, size, ext)
2081 fprintf(stderr, _("\
2082 Warning: No DIR structure found on this system --\n\
2083 Unable to autosize for XPM/XIM pieces.\n\
2084 Please report this error to frankm@hiwaay.net.\n\
2085 Include system type & operating system in message.\n"));
2088 #endif /* HAVE_DIR_STRUCT */
2090 static char *cnames[9] = { "black", "red", "green", "yellow", "blue",
2091 "magenta", "cyan", "white" };
2095 TextColors textColors[(int)NColorClasses];
2097 /* String is: "fg, bg, attr". Which is 0, 1, 2 */
2099 parse_color(str, which)
2103 char *p, buf[100], *d;
2106 if (strlen(str) > 99) /* watch bounds on buf */
2111 for (i=0; i<which; ++i) {
2118 /* Could be looking at something like:
2120 .. in which case we want to stop on a comma also */
2121 while (*p && *p != ',' && !isalpha(*p) && !isdigit(*p))
2125 return -1; /* Use default for empty field */
2128 if (which == 2 || isdigit(*p))
2131 while (*p && isalpha(*p))
2136 for (i=0; i<8; ++i) {
2137 if (!StrCaseCmp(buf, cnames[i]))
2138 return which? (i+40) : (i+30);
2140 if (!StrCaseCmp(buf, "default")) return -1;
2142 fprintf(stderr, _("%s: unrecognized color %s\n"), programName, buf);
2147 parse_cpair(cc, str)
2151 if ((textColors[(int)cc].fg=parse_color(str, 0)) == -2) {
2152 fprintf(stderr, _("%s: can't parse foreground color in `%s'\n"),
2157 /* bg and attr are optional */
2158 textColors[(int)cc].bg = parse_color(str, 1);
2159 if ((textColors[(int)cc].attr = parse_color(str, 2)) < 0) {
2160 textColors[(int)cc].attr = 0;
2166 /* Arrange to catch delete-window events */
2167 Atom wm_delete_window;
2169 CatchDeleteWindow(Widget w, String procname)
2172 XSetWMProtocols(xDisplay, XtWindow(w), &wm_delete_window, 1);
2173 snprintf(buf, sizeof(buf), "<Message>WM_PROTOCOLS: %s() \n", procname);
2174 XtAugmentTranslations(w, XtParseTranslationTable(buf));
2181 XtSetArg(args[0], XtNiconic, False);
2182 XtSetValues(shellWidget, args, 1);
2184 XtPopup(shellWidget, XtGrabNone); /* Raise if lowered */
2188 // eventually, all layout determining code should go into a subroutine, but until then IDSIZE remains undefined
2190 #define BoardSize int
2191 void InitDrawingSizes(BoardSize boardSize, int flags)
2192 { // [HGM] resize is functional now, but for board format changes only (nr of ranks, files)
2193 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
2195 XtGeometryResult gres;
2198 if(!formWidget) return;
2201 * Enable shell resizing.
2203 shellArgs[0].value = (XtArgVal) &w;
2204 shellArgs[1].value = (XtArgVal) &h;
2205 XtGetValues(shellWidget, shellArgs, 2);
2207 shellArgs[4].value = 2*w; shellArgs[2].value = 10;
2208 shellArgs[5].value = 2*h; shellArgs[3].value = 10;
2209 XtSetValues(shellWidget, &shellArgs[2], 4);
2211 XtSetArg(args[0], XtNdefaultDistance, &sep);
2212 XtGetValues(formWidget, args, 1);
2214 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2215 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2218 XtSetArg(args[0], XtNwidth, boardWidth);
2219 XtSetArg(args[1], XtNheight, boardHeight);
2220 XtSetValues(boardWidget, args, 2);
2222 timerWidth = (boardWidth - sep) / 2;
2223 XtSetArg(args[0], XtNwidth, timerWidth);
2224 XtSetValues(whiteTimerWidget, args, 1);
2225 XtSetValues(blackTimerWidget, args, 1);
2227 XawFormDoLayout(formWidget, False);
2229 if (appData.titleInWindow) {
2231 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2232 XtSetArg(args[i], XtNheight, &h); i++;
2233 XtGetValues(titleWidget, args, i);
2235 w = boardWidth - 2*bor;
2237 XtSetArg(args[0], XtNwidth, &w);
2238 XtGetValues(menuBarWidget, args, 1);
2239 w = boardWidth - w - sep - 2*bor - 2; // WIDTH_FUDGE
2242 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
2243 if (gres != XtGeometryYes && appData.debugMode) {
2245 _("%s: titleWidget geometry error %d %d %d %d %d\n"),
2246 programName, gres, w, h, wr, hr);
2250 XawFormDoLayout(formWidget, True);
2253 * Inhibit shell resizing.
2255 shellArgs[0].value = w = (XtArgVal) boardWidth + marginW;
2256 shellArgs[1].value = h = (XtArgVal) boardHeight + marginH;
2257 shellArgs[4].value = shellArgs[2].value = w;
2258 shellArgs[5].value = shellArgs[3].value = h;
2259 XtSetValues(shellWidget, &shellArgs[0], 6);
2261 // [HGM] pieces: tailor piece bitmaps to needs of specific variant
2264 for(i=0; i<4; i++) {
2266 for(p=0; p<=(int)WhiteKing; p++)
2267 xpmPieceBitmap[i][p] = xpmPieceBitmap2[i][p]; // defaults
2268 if(gameInfo.variant == VariantShogi) {
2269 xpmPieceBitmap[i][(int)WhiteCannon] = xpmPieceBitmap2[i][(int)WhiteKing+1];
2270 xpmPieceBitmap[i][(int)WhiteNightrider] = xpmPieceBitmap2[i][(int)WhiteKing+2];
2271 xpmPieceBitmap[i][(int)WhiteSilver] = xpmPieceBitmap2[i][(int)WhiteKing+3];
2272 xpmPieceBitmap[i][(int)WhiteGrasshopper] = xpmPieceBitmap2[i][(int)WhiteKing+4];
2273 xpmPieceBitmap[i][(int)WhiteQueen] = xpmPieceBitmap2[i][(int)WhiteLance];
2276 if(gameInfo.variant == VariantGothic) {
2277 xpmPieceBitmap[i][(int)WhiteMarshall] = xpmPieceBitmap2[i][(int)WhiteSilver];
2281 // [HGM] why are thee ximMasks used at all? the ximPieceBitmaps seem to be never used!
2282 for(p=0; p<=(int)WhiteKing; p++)
2283 ximMaskPm[p] = ximMaskPm2[p]; // defaults
2284 if(gameInfo.variant == VariantShogi) {
2285 ximMaskPm[(int)WhiteCannon] = ximMaskPm2[(int)WhiteKing+1];
2286 ximMaskPm[(int)WhiteNightrider] = ximMaskPm2[(int)WhiteKing+2];
2287 ximMaskPm[(int)WhiteSilver] = ximMaskPm2[(int)WhiteKing+3];
2288 ximMaskPm[(int)WhiteGrasshopper] = ximMaskPm2[(int)WhiteKing+4];
2289 ximMaskPm[(int)WhiteQueen] = ximMaskPm2[(int)WhiteLance];
2292 if(gameInfo.variant == VariantGothic) {
2293 ximMaskPm[(int)WhiteMarshall] = ximMaskPm2[i][(int)WhiteSilver];
2299 for(i=0; i<2; i++) {
2301 for(p=0; p<=(int)WhiteKing; p++)
2302 pieceBitmap[i][p] = pieceBitmap2[i][p]; // defaults
2303 if(gameInfo.variant == VariantShogi) {
2304 pieceBitmap[i][(int)WhiteCannon] = pieceBitmap2[i][(int)WhiteKing+1];
2305 pieceBitmap[i][(int)WhiteNightrider] = pieceBitmap2[i][(int)WhiteKing+2];
2306 pieceBitmap[i][(int)WhiteSilver] = pieceBitmap2[i][(int)WhiteKing+3];
2307 pieceBitmap[i][(int)WhiteGrasshopper] = pieceBitmap2[i][(int)WhiteKing+4];
2308 pieceBitmap[i][(int)WhiteQueen] = pieceBitmap2[i][(int)WhiteLance];
2311 if(gameInfo.variant == VariantGothic) {
2312 pieceBitmap[i][(int)WhiteMarshall] = pieceBitmap2[i][(int)WhiteSilver];
2328 int i, j, clockFontPxlSize, coordFontPxlSize, fontPxlSize;
2329 XSetWindowAttributes window_attributes;
2331 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
2332 XrmValue vFrom, vTo;
2333 XtGeometryResult gres;
2336 int forceMono = False;
2339 // [HGM] before anything else, expand any indirection files amongst options
2340 char *argvCopy[1000]; // 1000 seems enough
2341 char newArgs[10000]; // holds actual characters
2344 srandom(time(0)); // [HGM] book: make random truly random
2347 for(i=0; i<argc; i++) {
2348 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2349 //fprintf(stderr, "arg %s\n", argv[i]);
2350 if(argv[i][0] != '@') argvCopy[j++] = argv[i]; else {
2352 FILE *f = fopen(argv[i]+1, "rb");
2353 if(f == NULL) { fprintf(stderr, _("ignore %s\n"), argv[i]); continue; } // do not expand non-existing
2354 argvCopy[j++] = newArgs + k; // get ready for first argument from file
2355 while((c = fgetc(f)) != EOF) { // each line of file inserts 1 argument in the list
2357 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2358 newArgs[k++] = 0; // terminate current arg
2359 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2360 argvCopy[j++] = newArgs + k; // get ready for next
2362 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2375 if(appData.debugMode,1) { // OK, appData is not initialized here yet...
2376 for(i=0; i<argc; i++) fprintf(stderr, "argv[%2d] = '%s'\n", i, argv[i]);
2382 setbuf(stdout, NULL);
2383 setbuf(stderr, NULL);
2386 programName = strrchr(argv[0], '/');
2387 if (programName == NULL)
2388 programName = argv[0];
2393 XtSetLanguageProc(NULL, NULL, NULL);
2394 bindtextdomain(PACKAGE, LOCALEDIR);
2395 textdomain(PACKAGE);
2399 XtAppInitialize(&appContext, "XBoard", shellOptions,
2400 XtNumber(shellOptions),
2401 &argc, argv, xboardResources, NULL, 0);
2403 fprintf(stderr, _("%s: unrecognized argument %s\n"),
2404 programName, argv[1]);
2405 fprintf(stderr, "Recognized options:\n");
2406 for(i = 0; i < XtNumber(shellOptions); i++) {
2407 j = fprintf(stderr, " %s%s", shellOptions[i].option,
2408 (shellOptions[i].argKind == XrmoptionSepArg
2410 if (i++ < XtNumber(shellOptions)) {
2411 fprintf(stderr, "%*c%s%s\n", 40 - j, ' ',
2412 shellOptions[i].option,
2413 (shellOptions[i].argKind == XrmoptionSepArg
2416 fprintf(stderr, "\n");
2422 if ((chessDir = (char *) getenv("CHESSDIR")) == NULL) {
2425 if (chdir(chessDir) != 0) {
2426 fprintf(stderr, _("%s: can't cd to CHESSDIR: "), programName);
2433 if (p == NULL) p = "/tmp";
2434 i = strlen(p) + strlen("/.xboardXXXXXx.pgn") + 1;
2435 gameCopyFilename = (char*) malloc(i);
2436 gamePasteFilename = (char*) malloc(i);
2437 snprintf(gameCopyFilename,i, "%s/.xboard%05uc.pgn", p, getpid());
2438 snprintf(gamePasteFilename,i, "%s/.xboard%05up.pgn", p, getpid());
2440 XtGetApplicationResources(shellWidget, (XtPointer) &appData,
2441 clientResources, XtNumber(clientResources),
2444 if (appData.debugMode && appData.nameOfDebugFile && strcmp(appData.nameOfDebugFile, "stderr")) {
2445 /* [DM] debug info to file [HGM] make the filename a command-line option, and allow it to remain stderr */
2446 if ((debugFP = fopen(appData.nameOfDebugFile, "w")) == NULL) {
2447 printf(_("Failed to open file '%s'\n"), appData.nameOfDebugFile);
2450 setbuf(debugFP, NULL);
2453 /* [HGM,HR] make sure board size is acceptable */
2454 if(appData.NrFiles > BOARD_SIZE ||
2455 appData.NrRanks > BOARD_SIZE )
2456 DisplayFatalError(_("Recompile with BOARD_SIZE > 12, to support this size"), 0, 2);
2459 /* This feature does not work; animation needs a rewrite */
2460 appData.highlightDragging = FALSE;
2464 xDisplay = XtDisplay(shellWidget);
2465 xScreen = DefaultScreen(xDisplay);
2466 wm_delete_window = XInternAtom(xDisplay, "WM_DELETE_WINDOW", True);
2468 gameInfo.variant = StringToVariant(appData.variant);
2469 InitPosition(FALSE);
2472 * Determine boardSize
2474 gameInfo.boardWidth = gameInfo.boardHeight = 8; // [HGM] boardsize: make sure we start as 8x8
2477 // [HGM] as long as we have not created the possibility to change size while running, start with requested size
2478 gameInfo.boardWidth = appData.NrFiles > 0 ? appData.NrFiles : 8;
2479 gameInfo.boardHeight = appData.NrRanks > 0 ? appData.NrRanks : 8;
2480 gameInfo.holdingsWidth = appData.holdingsSize > 0 ? 2 : 0;
2485 InitDrawingSizes(-1, 0); // [HGM] initsize: make this into a subroutine
2487 if (isdigit(appData.boardSize[0])) {
2488 i = sscanf(appData.boardSize, "%d,%d,%d,%d,%d,%d,%d", &squareSize,
2489 &lineGap, &clockFontPxlSize, &coordFontPxlSize,
2490 &fontPxlSize, &smallLayout, &tinyLayout);
2492 fprintf(stderr, _("%s: bad boardSize syntax %s\n"),
2493 programName, appData.boardSize);
2497 /* Find some defaults; use the nearest known size */
2498 SizeDefaults *szd, *nearest;
2499 int distance = 99999;
2500 nearest = szd = sizeDefaults;
2501 while (szd->name != NULL) {
2502 if (abs(szd->squareSize - squareSize) < distance) {
2504 distance = abs(szd->squareSize - squareSize);
2505 if (distance == 0) break;
2509 if (i < 2) lineGap = nearest->lineGap;
2510 if (i < 3) clockFontPxlSize = nearest->clockFontPxlSize;
2511 if (i < 4) coordFontPxlSize = nearest->coordFontPxlSize;
2512 if (i < 5) fontPxlSize = nearest->fontPxlSize;
2513 if (i < 6) smallLayout = nearest->smallLayout;
2514 if (i < 7) tinyLayout = nearest->tinyLayout;
2517 SizeDefaults *szd = sizeDefaults;
2518 if (*appData.boardSize == NULLCHAR) {
2519 while (DisplayWidth(xDisplay, xScreen) < szd->minScreenSize ||
2520 DisplayHeight(xDisplay, xScreen) < szd->minScreenSize) {
2523 if (szd->name == NULL) szd--;
2525 while (szd->name != NULL &&
2526 StrCaseCmp(szd->name, appData.boardSize) != 0) szd++;
2527 if (szd->name == NULL) {
2528 fprintf(stderr, _("%s: unrecognized boardSize name %s\n"),
2529 programName, appData.boardSize);
2533 squareSize = szd->squareSize;
2534 lineGap = szd->lineGap;
2535 clockFontPxlSize = szd->clockFontPxlSize;
2536 coordFontPxlSize = szd->coordFontPxlSize;
2537 fontPxlSize = szd->fontPxlSize;
2538 smallLayout = szd->smallLayout;
2539 tinyLayout = szd->tinyLayout;
2542 /* Now, using squareSize as a hint, find a good XPM/XIM set size */
2543 if (strlen(appData.pixmapDirectory) > 0) {
2544 p = ExpandPathName(appData.pixmapDirectory);
2546 fprintf(stderr, _("Error expanding path name \"%s\"\n"),
2547 appData.pixmapDirectory);
2550 if (appData.debugMode) {
2551 fprintf(stderr, _("\
2552 XBoard square size (hint): %d\n\
2553 %s fulldir:%s:\n"), squareSize, IMAGE_EXT, p);
2555 squareSize = xpm_closest_to(p, squareSize, IMAGE_EXT);
2556 if (appData.debugMode) {
2557 fprintf(stderr, _("Closest %s size: %d\n"), IMAGE_EXT, squareSize);
2561 /* [HR] height treated separately (hacked) */
2562 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2563 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2564 if (appData.showJail == 1) {
2565 /* Jail on top and bottom */
2566 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2567 XtSetArg(boardArgs[2], XtNheight,
2568 boardHeight + 2*(lineGap + squareSize));
2569 } else if (appData.showJail == 2) {
2571 XtSetArg(boardArgs[1], XtNwidth,
2572 boardWidth + 2*(lineGap + squareSize));
2573 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2576 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2577 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2581 * Determine what fonts to use.
2583 appData.clockFont = FindFont(appData.clockFont, clockFontPxlSize);
2584 clockFontID = XLoadFont(xDisplay, appData.clockFont);
2585 clockFontStruct = XQueryFont(xDisplay, clockFontID);
2586 appData.coordFont = FindFont(appData.coordFont, coordFontPxlSize);
2587 coordFontID = XLoadFont(xDisplay, appData.coordFont);
2588 coordFontStruct = XQueryFont(xDisplay, coordFontID);
2589 appData.font = FindFont(appData.font, fontPxlSize);
2590 countFontID = XLoadFont(xDisplay, appData.coordFont); // [HGM] holdings
2591 countFontStruct = XQueryFont(xDisplay, countFontID);
2592 // appData.font = FindFont(appData.font, fontPxlSize);
2594 xdb = XtDatabase(xDisplay);
2595 XrmPutStringResource(&xdb, "*font", appData.font);
2598 * Detect if there are not enough colors available and adapt.
2600 if (DefaultDepth(xDisplay, xScreen) <= 2) {
2601 appData.monoMode = True;
2604 if (!appData.monoMode) {
2605 vFrom.addr = (caddr_t) appData.lightSquareColor;
2606 vFrom.size = strlen(appData.lightSquareColor);
2607 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2608 if (vTo.addr == NULL) {
2609 appData.monoMode = True;
2612 lightSquareColor = *(Pixel *) vTo.addr;
2615 if (!appData.monoMode) {
2616 vFrom.addr = (caddr_t) appData.darkSquareColor;
2617 vFrom.size = strlen(appData.darkSquareColor);
2618 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2619 if (vTo.addr == NULL) {
2620 appData.monoMode = True;
2623 darkSquareColor = *(Pixel *) vTo.addr;
2626 if (!appData.monoMode) {
2627 vFrom.addr = (caddr_t) appData.whitePieceColor;
2628 vFrom.size = strlen(appData.whitePieceColor);
2629 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2630 if (vTo.addr == NULL) {
2631 appData.monoMode = True;
2634 whitePieceColor = *(Pixel *) vTo.addr;
2637 if (!appData.monoMode) {
2638 vFrom.addr = (caddr_t) appData.blackPieceColor;
2639 vFrom.size = strlen(appData.blackPieceColor);
2640 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2641 if (vTo.addr == NULL) {
2642 appData.monoMode = True;
2645 blackPieceColor = *(Pixel *) vTo.addr;
2649 if (!appData.monoMode) {
2650 vFrom.addr = (caddr_t) appData.highlightSquareColor;
2651 vFrom.size = strlen(appData.highlightSquareColor);
2652 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2653 if (vTo.addr == NULL) {
2654 appData.monoMode = True;
2657 highlightSquareColor = *(Pixel *) vTo.addr;
2661 if (!appData.monoMode) {
2662 vFrom.addr = (caddr_t) appData.premoveHighlightColor;
2663 vFrom.size = strlen(appData.premoveHighlightColor);
2664 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2665 if (vTo.addr == NULL) {
2666 appData.monoMode = True;
2669 premoveHighlightColor = *(Pixel *) vTo.addr;
2674 fprintf(stderr, _("%s: too few colors available; trying monochrome mode\n"),
2677 if (appData.bitmapDirectory == NULL ||
2678 appData.bitmapDirectory[0] == NULLCHAR)
2679 appData.bitmapDirectory = DEF_BITMAP_DIR;
2682 if (appData.lowTimeWarning && !appData.monoMode) {
2683 vFrom.addr = (caddr_t) appData.lowTimeWarningColor;
2684 vFrom.size = strlen(appData.lowTimeWarningColor);
2685 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2686 if (vTo.addr == NULL)
2687 appData.monoMode = True;
2689 lowTimeWarningColor = *(Pixel *) vTo.addr;
2692 if (appData.monoMode && appData.debugMode) {
2693 fprintf(stderr, _("white pixel = 0x%lx, black pixel = 0x%lx\n"),
2694 (unsigned long) XWhitePixel(xDisplay, xScreen),
2695 (unsigned long) XBlackPixel(xDisplay, xScreen));
2698 if (parse_cpair(ColorShout, appData.colorShout) < 0 ||
2699 parse_cpair(ColorSShout, appData.colorSShout) < 0 ||
2700 parse_cpair(ColorChannel1, appData.colorChannel1) < 0 ||
2701 parse_cpair(ColorChannel, appData.colorChannel) < 0 ||
2702 parse_cpair(ColorKibitz, appData.colorKibitz) < 0 ||
2703 parse_cpair(ColorTell, appData.colorTell) < 0 ||
2704 parse_cpair(ColorChallenge, appData.colorChallenge) < 0 ||
2705 parse_cpair(ColorRequest, appData.colorRequest) < 0 ||
2706 parse_cpair(ColorSeek, appData.colorSeek) < 0 ||
2707 parse_cpair(ColorNormal, appData.colorNormal) < 0)
2709 if (appData.colorize) {
2711 _("%s: can't parse color names; disabling colorization\n"),
2714 appData.colorize = FALSE;
2716 textColors[ColorNone].fg = textColors[ColorNone].bg = -1;
2717 textColors[ColorNone].attr = 0;
2719 XtAppAddActions(appContext, boardActions, XtNumber(boardActions));
2725 layoutName = "tinyLayout";
2726 } else if (smallLayout) {
2727 layoutName = "smallLayout";
2729 layoutName = "normalLayout";
2731 /* Outer layoutWidget is there only to provide a name for use in
2732 resources that depend on the layout style */
2734 XtCreateManagedWidget(layoutName, formWidgetClass, shellWidget,
2735 layoutArgs, XtNumber(layoutArgs));
2737 XtCreateManagedWidget("form", formWidgetClass, layoutWidget,
2738 formArgs, XtNumber(formArgs));
2739 XtSetArg(args[0], XtNdefaultDistance, &sep);
2740 XtGetValues(formWidget, args, 1);
2743 widgetList[j++] = menuBarWidget = CreateMenuBar(menuBar);
2744 XtSetArg(args[0], XtNtop, XtChainTop);
2745 XtSetArg(args[1], XtNbottom, XtChainTop);
2746 XtSetValues(menuBarWidget, args, 2);
2748 widgetList[j++] = whiteTimerWidget =
2749 XtCreateWidget("whiteTime", labelWidgetClass,
2750 formWidget, timerArgs, XtNumber(timerArgs));
2751 XtSetArg(args[0], XtNfont, clockFontStruct);
2752 XtSetArg(args[1], XtNtop, XtChainTop);
2753 XtSetArg(args[2], XtNbottom, XtChainTop);
2754 XtSetValues(whiteTimerWidget, args, 3);
2756 widgetList[j++] = blackTimerWidget =
2757 XtCreateWidget("blackTime", labelWidgetClass,
2758 formWidget, timerArgs, XtNumber(timerArgs));
2759 XtSetArg(args[0], XtNfont, clockFontStruct);
2760 XtSetArg(args[1], XtNtop, XtChainTop);
2761 XtSetArg(args[2], XtNbottom, XtChainTop);
2762 XtSetValues(blackTimerWidget, args, 3);
2764 if (appData.titleInWindow) {
2765 widgetList[j++] = titleWidget =
2766 XtCreateWidget("title", labelWidgetClass, formWidget,
2767 titleArgs, XtNumber(titleArgs));
2768 XtSetArg(args[0], XtNtop, XtChainTop);
2769 XtSetArg(args[1], XtNbottom, XtChainTop);
2770 XtSetValues(titleWidget, args, 2);
2773 if (appData.showButtonBar) {
2774 widgetList[j++] = buttonBarWidget = CreateButtonBar(buttonBar);
2775 XtSetArg(args[0], XtNleft, XtChainRight); // [HGM] glue to right window edge
2776 XtSetArg(args[1], XtNright, XtChainRight); // for good run-time sizing
2777 XtSetArg(args[2], XtNtop, XtChainTop);
2778 XtSetArg(args[3], XtNbottom, XtChainTop);
2779 XtSetValues(buttonBarWidget, args, 4);
2782 widgetList[j++] = messageWidget =
2783 XtCreateWidget("message", labelWidgetClass, formWidget,
2784 messageArgs, XtNumber(messageArgs));
2785 XtSetArg(args[0], XtNtop, XtChainTop);
2786 XtSetArg(args[1], XtNbottom, XtChainTop);
2787 XtSetValues(messageWidget, args, 2);
2789 widgetList[j++] = boardWidget =
2790 XtCreateWidget("board", widgetClass, formWidget, boardArgs,
2791 XtNumber(boardArgs));
2793 XtManageChildren(widgetList, j);
2795 timerWidth = (boardWidth - sep) / 2;
2796 XtSetArg(args[0], XtNwidth, timerWidth);
2797 XtSetValues(whiteTimerWidget, args, 1);
2798 XtSetValues(blackTimerWidget, args, 1);
2800 XtSetArg(args[0], XtNbackground, &timerBackgroundPixel);
2801 XtSetArg(args[1], XtNforeground, &timerForegroundPixel);
2802 XtGetValues(whiteTimerWidget, args, 2);
2804 if (appData.showButtonBar) {
2805 XtSetArg(args[0], XtNbackground, &buttonBackgroundPixel);
2806 XtSetArg(args[1], XtNforeground, &buttonForegroundPixel);
2807 XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
2811 * formWidget uses these constraints but they are stored
2815 XtSetArg(args[i], XtNfromHoriz, 0); i++;
2816 XtSetValues(menuBarWidget, args, i);
2817 if (appData.titleInWindow) {
2820 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2821 XtSetValues(whiteTimerWidget, args, i);
2823 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2824 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2825 XtSetValues(blackTimerWidget, args, i);
2827 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2828 XtSetArg(args[i], XtNjustify, XtJustifyLeft); i++;
2829 XtSetValues(titleWidget, args, i);
2831 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2832 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2833 XtSetValues(messageWidget, args, i);
2834 if (appData.showButtonBar) {
2836 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2837 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2838 XtSetValues(buttonBarWidget, args, i);
2842 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2843 XtSetValues(whiteTimerWidget, args, i);
2845 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2846 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2847 XtSetValues(blackTimerWidget, args, i);
2849 XtSetArg(args[i], XtNfromHoriz, menuBarWidget); i++;
2850 XtSetValues(titleWidget, args, i);
2852 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2853 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2854 XtSetValues(messageWidget, args, i);
2855 if (appData.showButtonBar) {
2857 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2858 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2859 XtSetValues(buttonBarWidget, args, i);
2864 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2865 XtSetValues(whiteTimerWidget, args, i);
2867 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2868 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2869 XtSetValues(blackTimerWidget, args, i);
2871 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2872 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2873 XtSetValues(messageWidget, args, i);
2874 if (appData.showButtonBar) {
2876 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2877 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2878 XtSetValues(buttonBarWidget, args, i);
2882 XtSetArg(args[0], XtNfromVert, messageWidget);
2883 XtSetArg(args[1], XtNtop, XtChainTop);
2884 XtSetArg(args[2], XtNbottom, XtChainBottom);
2885 XtSetArg(args[3], XtNleft, XtChainLeft);
2886 XtSetArg(args[4], XtNright, XtChainRight);
2887 XtSetValues(boardWidget, args, 5);
2889 XtRealizeWidget(shellWidget);
2892 * Correct the width of the message and title widgets.
2893 * It is not known why some systems need the extra fudge term.
2894 * The value "2" is probably larger than needed.
2896 XawFormDoLayout(formWidget, False);
2898 #define WIDTH_FUDGE 2
2900 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2901 XtSetArg(args[i], XtNheight, &h); i++;
2902 XtGetValues(messageWidget, args, i);
2903 if (appData.showButtonBar) {
2905 XtSetArg(args[i], XtNwidth, &w); i++;
2906 XtGetValues(buttonBarWidget, args, i);
2907 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2909 w = boardWidth - 2*bor + 1; /*!! +1 compensates for kludge below */
2912 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2913 if (gres != XtGeometryYes && appData.debugMode) {
2914 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2915 programName, gres, w, h, wr, hr);
2918 /* !! Horrible hack to work around bug in XFree86 4.0.1 (X11R6.4.3) */
2919 /* The size used for the child widget in layout lags one resize behind
2920 its true size, so we resize a second time, 1 pixel smaller. Yeech! */
2922 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2923 if (gres != XtGeometryYes && appData.debugMode) {
2924 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2925 programName, gres, w, h, wr, hr);
2928 XtSetArg(args[0], XtNleft, XtChainLeft); // [HGM] glue ends for good run-time sizing
2929 XtSetArg(args[1], XtNright, XtChainRight);
2930 XtSetValues(messageWidget, args, 2);
2932 if (appData.titleInWindow) {
2934 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2935 XtSetArg(args[i], XtNheight, &h); i++;
2936 XtGetValues(titleWidget, args, i);
2938 w = boardWidth - 2*bor;
2940 XtSetArg(args[0], XtNwidth, &w);
2941 XtGetValues(menuBarWidget, args, 1);
2942 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2945 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
2946 if (gres != XtGeometryYes && appData.debugMode) {
2948 _("%s: titleWidget geometry error %d %d %d %d %d\n"),
2949 programName, gres, w, h, wr, hr);
2952 XawFormDoLayout(formWidget, True);
2954 xBoardWindow = XtWindow(boardWidget);
2956 // [HGM] it seems the layout code ends here, but perhaps the color stuff is size independent and would
2957 // not need to go into InitDrawingSizes().
2961 * Create X checkmark bitmap and initialize option menu checks.
2963 ReadBitmap(&xMarkPixmap, "checkmark.bm",
2964 checkmark_bits, checkmark_width, checkmark_height);
2965 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
2966 if (appData.alwaysPromoteToQueen) {
2967 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
2970 if (appData.animateDragging) {
2971 XtSetValues(XtNameToWidget(menuBarWidget,
2972 "menuOptions.Animate Dragging"),
2975 if (appData.animate) {
2976 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
2979 if (appData.autoComment) {
2980 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
2983 if (appData.autoCallFlag) {
2984 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
2987 if (appData.autoFlipView) {
2988 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Auto Flip View"),
2991 if (appData.autoObserve) {
2992 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
2995 if (appData.autoRaiseBoard) {
2996 XtSetValues(XtNameToWidget(menuBarWidget,
2997 "menuOptions.Auto Raise Board"), args, 1);
2999 if (appData.autoSaveGames) {
3000 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
3003 if (appData.saveGameFile[0] != NULLCHAR) {
3004 /* Can't turn this off from menu */
3005 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
3007 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
3011 if (appData.blindfold) {
3012 XtSetValues(XtNameToWidget(menuBarWidget,
3013 "menuOptions.Blindfold"), args, 1);
3015 if (appData.flashCount > 0) {
3016 XtSetValues(XtNameToWidget(menuBarWidget,
3017 "menuOptions.Flash Moves"),
3020 if (appData.getMoveList) {
3021 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
3025 if (appData.highlightDragging) {
3026 XtSetValues(XtNameToWidget(menuBarWidget,
3027 "menuOptions.Highlight Dragging"),
3031 if (appData.highlightLastMove) {
3032 XtSetValues(XtNameToWidget(menuBarWidget,
3033 "menuOptions.Highlight Last Move"),
3036 if (appData.icsAlarm) {
3037 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.ICS Alarm"),
3040 if (appData.ringBellAfterMoves) {
3041 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
3044 if (appData.oldSaveStyle) {
3045 XtSetValues(XtNameToWidget(menuBarWidget,
3046 "menuOptions.Old Save Style"), args, 1);
3048 if (appData.periodicUpdates) {
3049 XtSetValues(XtNameToWidget(menuBarWidget,
3050 "menuOptions.Periodic Updates"), args, 1);
3052 if (appData.ponderNextMove) {
3053 XtSetValues(XtNameToWidget(menuBarWidget,
3054 "menuOptions.Ponder Next Move"), args, 1);
3056 if (appData.popupExitMessage) {
3057 XtSetValues(XtNameToWidget(menuBarWidget,
3058 "menuOptions.Popup Exit Message"), args, 1);
3060 if (appData.popupMoveErrors) {
3061 XtSetValues(XtNameToWidget(menuBarWidget,
3062 "menuOptions.Popup Move Errors"), args, 1);
3064 if (appData.premove) {
3065 XtSetValues(XtNameToWidget(menuBarWidget,
3066 "menuOptions.Premove"), args, 1);
3068 if (appData.quietPlay) {
3069 XtSetValues(XtNameToWidget(menuBarWidget,
3070 "menuOptions.Quiet Play"), args, 1);
3072 if (appData.showCoords) {
3073 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
3076 if (appData.hideThinkingFromHuman) {
3077 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
3080 if (appData.testLegality) {
3081 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Test Legality"),
3088 ReadBitmap(&wIconPixmap, "icon_white.bm",
3089 icon_white_bits, icon_white_width, icon_white_height);
3090 ReadBitmap(&bIconPixmap, "icon_black.bm",
3091 icon_black_bits, icon_black_width, icon_black_height);
3092 iconPixmap = wIconPixmap;
3094 XtSetArg(args[i], XtNiconPixmap, iconPixmap); i++;
3095 XtSetValues(shellWidget, args, i);
3098 * Create a cursor for the board widget.
3100 window_attributes.cursor = XCreateFontCursor(xDisplay, XC_hand2);
3101 XChangeWindowAttributes(xDisplay, xBoardWindow,
3102 CWCursor, &window_attributes);
3105 * Inhibit shell resizing.
3107 shellArgs[0].value = (XtArgVal) &w;
3108 shellArgs[1].value = (XtArgVal) &h;
3109 XtGetValues(shellWidget, shellArgs, 2);
3110 shellArgs[4].value = shellArgs[2].value = w;
3111 shellArgs[5].value = shellArgs[3].value = h;
3112 XtSetValues(shellWidget, &shellArgs[2], 4);
3113 marginW = w - boardWidth; // [HGM] needed to set new shellWidget size when we resize board
3114 marginH = h - boardHeight;
3116 CatchDeleteWindow(shellWidget, "QuitProc");
3121 if (appData.bitmapDirectory[0] != NULLCHAR) {
3128 /* Create regular pieces */
3129 if (!useImages) CreatePieces();
3134 if (appData.animate || appData.animateDragging)
3137 XtAugmentTranslations(formWidget,
3138 XtParseTranslationTable(globalTranslations));
3139 XtAugmentTranslations(boardWidget,
3140 XtParseTranslationTable(boardTranslations));
3141 XtAugmentTranslations(whiteTimerWidget,
3142 XtParseTranslationTable(whiteTranslations));
3143 XtAugmentTranslations(blackTimerWidget,
3144 XtParseTranslationTable(blackTranslations));
3146 /* Why is the following needed on some versions of X instead
3147 * of a translation? */
3148 XtAddEventHandler(boardWidget, ExposureMask, False,
3149 (XtEventHandler) EventProc, NULL);
3154 if (errorExitStatus == -1) {
3155 if (appData.icsActive) {
3156 /* We now wait until we see "login:" from the ICS before
3157 sending the logon script (problems with timestamp otherwise) */
3158 /*ICSInitScript();*/
3159 if (appData.icsInputBox) ICSInputBoxPopUp();
3162 signal(SIGINT, IntSigHandler);
3163 signal(SIGTERM, IntSigHandler);
3164 if (*appData.cmailGameName != NULLCHAR) {
3165 signal(SIGUSR1, CmailSigHandler);
3168 gameInfo.boardWidth = 0; // [HGM] pieces: kludge to ensure InitPosition() calls InitDrawingSizes()
3171 XtAppMainLoop(appContext);
3172 if (appData.debugMode) fclose(debugFP); // [DM] debug
3179 if (appData.icsActive && oldICSInteractionTitle != NULL) {
3180 DisplayIcsInteractionTitle(oldICSInteractionTitle);
3182 unlink(gameCopyFilename);
3183 unlink(gamePasteFilename);
3194 CmailSigHandler(sig)
3200 signal(SIGUSR1, SIG_IGN); /* suspend handler */
3202 /* Activate call-back function CmailSigHandlerCallBack() */
3203 OutputToProcess(cmailPR, (char *)(&dummy), sizeof(int), &error);
3205 signal(SIGUSR1, CmailSigHandler); /* re-activate handler */
3209 CmailSigHandlerCallBack(isr, closure, message, count, error)
3217 ReloadCmailMsgEvent(TRUE); /* Reload cmail msg */
3219 /**** end signal code ****/
3229 f = fopen(appData.icsLogon, "r");
3235 strcat(buf, appData.icsLogon);
3236 f = fopen(buf, "r");
3240 ProcessICSInitScript(f);
3247 EditCommentPopDown();
3258 SetMenuEnables(enab)
3262 if (!menuBarWidget) return;
3263 while (enab->name != NULL) {
3264 w = XtNameToWidget(menuBarWidget, enab->name);
3266 DisplayError(enab->name, 0);
3268 XtSetSensitive(w, enab->value);
3274 Enables icsEnables[] = {
3275 { "menuFile.Mail Move", False },
3276 { "menuFile.Reload CMail Message", False },
3277 { "menuMode.Machine Black", False },
3278 { "menuMode.Machine White", False },
3279 { "menuMode.Analysis Mode", False },
3280 { "menuMode.Analyze File", False },
3281 { "menuMode.Two Machines", False },
3283 { "menuHelp.Hint", False },
3284 { "menuHelp.Book", False },
3285 { "menuStep.Move Now", False },
3286 { "menuOptions.Periodic Updates", False },
3287 { "menuOptions.Hide Thinking", False },
3288 { "menuOptions.Ponder Next Move", False },
3293 Enables ncpEnables[] = {
3294 { "menuFile.Mail Move", False },
3295 { "menuFile.Reload CMail Message", False },
3296 { "menuMode.Machine White", False },
3297 { "menuMode.Machine Black", False },
3298 { "menuMode.Analysis Mode", False },
3299 { "menuMode.Analyze File", False },
3300 { "menuMode.Two Machines", False },
3301 { "menuMode.ICS Client", False },
3302 { "menuMode.ICS Input Box", False },
3303 { "Action", False },
3304 { "menuStep.Revert", False },
3305 { "menuStep.Move Now", False },
3306 { "menuStep.Retract Move", False },
3307 { "menuOptions.Auto Comment", False },
3308 { "menuOptions.Auto Flag", False },
3309 { "menuOptions.Auto Flip View", False },
3310 { "menuOptions.Auto Observe", False },
3311 { "menuOptions.Auto Raise Board", False },
3312 { "menuOptions.Get Move List", False },
3313 { "menuOptions.ICS Alarm", False },
3314 { "menuOptions.Move Sound", False },
3315 { "menuOptions.Quiet Play", False },
3316 { "menuOptions.Hide Thinking", False },
3317 { "menuOptions.Periodic Updates", False },
3318 { "menuOptions.Ponder Next Move", False },
3319 { "menuHelp.Hint", False },
3320 { "menuHelp.Book", False },
3324 Enables gnuEnables[] = {
3325 { "menuMode.ICS Client", False },
3326 { "menuMode.ICS Input Box", False },
3327 { "menuAction.Accept", False },
3328 { "menuAction.Decline", False },
3329 { "menuAction.Rematch", False },
3330 { "menuAction.Adjourn", False },
3331 { "menuAction.Stop Examining", False },
3332 { "menuAction.Stop Observing", False },
3333 { "menuStep.Revert", False },
3334 { "menuOptions.Auto Comment", False },
3335 { "menuOptions.Auto Observe", False },
3336 { "menuOptions.Auto Raise Board", False },
3337 { "menuOptions.Get Move List", False },
3338 { "menuOptions.Premove", False },
3339 { "menuOptions.Quiet Play", False },
3341 /* The next two options rely on SetCmailMode being called *after* */
3342 /* SetGNUMode so that when GNU is being used to give hints these */
3343 /* menu options are still available */
3345 { "menuFile.Mail Move", False },
3346 { "menuFile.Reload CMail Message", False },
3350 Enables cmailEnables[] = {
3352 { "menuAction.Call Flag", False },
3353 { "menuAction.Draw", True },
3354 { "menuAction.Adjourn", False },
3355 { "menuAction.Abort", False },
3356 { "menuAction.Stop Observing", False },
3357 { "menuAction.Stop Examining", False },
3358 { "menuFile.Mail Move", True },
3359 { "menuFile.Reload CMail Message", True },
3363 Enables trainingOnEnables[] = {
3364 { "menuMode.Edit Comment", False },
3365 { "menuMode.Pause", False },
3366 { "menuStep.Forward", False },
3367 { "menuStep.Backward", False },
3368 { "menuStep.Forward to End", False },
3369 { "menuStep.Back to Start", False },
3370 { "menuStep.Move Now", False },
3371 { "menuStep.Truncate Game", False },
3375 Enables trainingOffEnables[] = {
3376 { "menuMode.Edit Comment", True },
3377 { "menuMode.Pause", True },
3378 { "menuStep.Forward", True },
3379 { "menuStep.Backward", True },
3380 { "menuStep.Forward to End", True },
3381 { "menuStep.Back to Start", True },
3382 { "menuStep.Move Now", True },
3383 { "menuStep.Truncate Game", True },
3387 Enables machineThinkingEnables[] = {
3388 { "menuFile.Load Game", False },
3389 { "menuFile.Load Next Game", False },
3390 { "menuFile.Load Previous Game", False },
3391 { "menuFile.Reload Same Game", False },
3392 { "menuFile.Paste Game", False },
3393 { "menuFile.Load Position", False },
3394 { "menuFile.Load Next Position", False },
3395 { "menuFile.Load Previous Position", False },
3396 { "menuFile.Reload Same Position", False },
3397 { "menuFile.Paste Position", False },
3398 { "menuMode.Machine White", False },
3399 { "menuMode.Machine Black", False },
3400 { "menuMode.Two Machines", False },
3401 { "menuStep.Retract Move", False },
3405 Enables userThinkingEnables[] = {
3406 { "menuFile.Load Game", True },
3407 { "menuFile.Load Next Game", True },
3408 { "menuFile.Load Previous Game", True },
3409 { "menuFile.Reload Same Game", True },
3410 { "menuFile.Paste Game", True },
3411 { "menuFile.Load Position", True },
3412 { "menuFile.Load Next Position", True },
3413 { "menuFile.Load Previous Position", True },
3414 { "menuFile.Reload Same Position", True },
3415 { "menuFile.Paste Position", True },
3416 { "menuMode.Machine White", True },
3417 { "menuMode.Machine Black", True },
3418 { "menuMode.Two Machines", True },
3419 { "menuStep.Retract Move", True },
3425 SetMenuEnables(icsEnables);
3428 if (appData.zippyPlay && !appData.noChessProgram) /* [DM] icsEngineAnalyze */
3429 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Analysis Mode"), True);
3436 SetMenuEnables(ncpEnables);
3442 SetMenuEnables(gnuEnables);
3448 SetMenuEnables(cmailEnables);
3454 SetMenuEnables(trainingOnEnables);
3455 if (appData.showButtonBar) {
3456 XtSetSensitive(buttonBarWidget, False);
3462 SetTrainingModeOff()
3464 SetMenuEnables(trainingOffEnables);
3465 if (appData.showButtonBar) {
3466 XtSetSensitive(buttonBarWidget, True);
3471 SetUserThinkingEnables()
3473 if (appData.noChessProgram) return;
3474 SetMenuEnables(userThinkingEnables);
3478 SetMachineThinkingEnables()
3480 if (appData.noChessProgram) return;
3481 SetMenuEnables(machineThinkingEnables);
3483 case MachinePlaysBlack:
3484 case MachinePlaysWhite:
3485 case TwoMachinesPlay:
3486 XtSetSensitive(XtNameToWidget(menuBarWidget,
3487 ModeToWidgetName(gameMode)), True);
3494 #define Abs(n) ((n)<0 ? -(n) : (n))
3497 * Find a font that matches "pattern" that is as close as
3498 * possible to the targetPxlSize. Prefer fonts that are k
3499 * pixels smaller to fonts that are k pixels larger. The
3500 * pattern must be in the X Consortium standard format,
3501 * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".
3502 * The return value should be freed with XtFree when no
3505 char *FindFont(pattern, targetPxlSize)
3509 char **fonts, *p, *best, *scalable, *scalableTail;
3510 int i, j, nfonts, minerr, err, pxlSize;
3513 char **missing_list;
3515 char *def_string, *base_fnt_lst, strInt[3];
3517 XFontStruct **fnt_list;
3519 base_fnt_lst = calloc(1, strlen(pattern) + 3);
3520 sprintf(strInt, "%d", targetPxlSize);
3521 p = strstr(pattern, "--");
3522 strncpy(base_fnt_lst, pattern, p - pattern + 2);
3523 strcat(base_fnt_lst, strInt);
3524 strcat(base_fnt_lst, strchr(p + 2, '-'));
3526 if ((fntSet = XCreateFontSet(xDisplay,
3530 &def_string)) == NULL) {
3532 fprintf(stderr, _("Unable to create font set.\n"));
3536 nfonts = XFontsOfFontSet(fntSet, &fnt_list, &fonts);
3538 fonts = XListFonts(xDisplay, pattern, 999999, &nfonts);
3540 fprintf(stderr, _("%s: no fonts match pattern %s\n"),
3541 programName, pattern);
3549 for (i=0; i<nfonts; i++) {
3552 if (*p != '-') continue;
3554 if (*p == NULLCHAR) break;
3555 if (*p++ == '-') j++;
3557 if (j < 7) continue;
3560 scalable = fonts[i];
3563 err = pxlSize - targetPxlSize;
3564 if (Abs(err) < Abs(minerr) ||
3565 (minerr > 0 && err < 0 && -err == minerr)) {
3571 if (scalable && Abs(minerr) > appData.fontSizeTolerance) {
3572 /* If the error is too big and there is a scalable font,
3573 use the scalable font. */
3574 int headlen = scalableTail - scalable;
3575 p = (char *) XtMalloc(strlen(scalable) + 10);
3576 while (isdigit(*scalableTail)) scalableTail++;
3577 sprintf(p, "%.*s%d%s", headlen, scalable, targetPxlSize, scalableTail);
3579 p = (char *) XtMalloc(strlen(best) + 1);
3582 if (appData.debugMode) {
3583 fprintf(debugFP, _("resolved %s at pixel size %d\n to %s\n"),
3584 pattern, targetPxlSize, p);
3587 if (missing_count > 0)
3588 XFreeStringList(missing_list);
3589 XFreeFontSet(xDisplay, fntSet);
3591 XFreeFontNames(fonts);
3598 XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
3599 | GCBackground | GCFunction | GCPlaneMask;
3600 XGCValues gc_values;
3603 gc_values.plane_mask = AllPlanes;
3604 gc_values.line_width = lineGap;
3605 gc_values.line_style = LineSolid;
3606 gc_values.function = GXcopy;
3608 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3609 gc_values.background = XBlackPixel(xDisplay, xScreen);
3610 lineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3612 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3613 gc_values.background = XWhitePixel(xDisplay, xScreen);
3614 coordGC = XtGetGC(shellWidget, value_mask, &gc_values);
3615 XSetFont(xDisplay, coordGC, coordFontID);
3617 // [HGM] make font for holdings counts (white on black0
3618 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3619 gc_values.background = XBlackPixel(xDisplay, xScreen);
3620 countGC = XtGetGC(shellWidget, value_mask, &gc_values);
3621 XSetFont(xDisplay, countGC, countFontID);
3623 if (appData.monoMode) {
3624 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3625 gc_values.background = XWhitePixel(xDisplay, xScreen);
3626 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3628 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3629 gc_values.background = XBlackPixel(xDisplay, xScreen);
3630 lightSquareGC = wbPieceGC
3631 = XtGetGC(shellWidget, value_mask, &gc_values);
3633 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3634 gc_values.background = XWhitePixel(xDisplay, xScreen);
3635 darkSquareGC = bwPieceGC
3636 = XtGetGC(shellWidget, value_mask, &gc_values);
3638 if (DefaultDepth(xDisplay, xScreen) == 1) {
3639 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
3640 gc_values.function = GXcopyInverted;
3641 copyInvertedGC = XtGetGC(shellWidget, value_mask, &gc_values);
3642 gc_values.function = GXcopy;
3643 if (XBlackPixel(xDisplay, xScreen) == 1) {
3644 bwPieceGC = darkSquareGC;
3645 wbPieceGC = copyInvertedGC;
3647 bwPieceGC = copyInvertedGC;
3648 wbPieceGC = lightSquareGC;
3652 gc_values.foreground = highlightSquareColor;
3653 gc_values.background = highlightSquareColor;
3654 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3656 gc_values.foreground = premoveHighlightColor;
3657 gc_values.background = premoveHighlightColor;
3658 prelineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3660 gc_values.foreground = lightSquareColor;
3661 gc_values.background = darkSquareColor;
3662 lightSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3664 gc_values.foreground = darkSquareColor;
3665 gc_values.background = lightSquareColor;
3666 darkSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3668 gc_values.foreground = jailSquareColor;
3669 gc_values.background = jailSquareColor;
3670 jailSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3672 gc_values.foreground = whitePieceColor;
3673 gc_values.background = darkSquareColor;
3674 wdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3676 gc_values.foreground = whitePieceColor;
3677 gc_values.background = lightSquareColor;
3678 wlPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3680 gc_values.foreground = whitePieceColor;
3681 gc_values.background = jailSquareColor;
3682 wjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3684 gc_values.foreground = blackPieceColor;
3685 gc_values.background = darkSquareColor;
3686 bdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3688 gc_values.foreground = blackPieceColor;
3689 gc_values.background = lightSquareColor;
3690 blPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3692 gc_values.foreground = blackPieceColor;
3693 gc_values.background = jailSquareColor;
3694 bjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3698 void loadXIM(xim, xmask, filename, dest, mask)
3711 fp = fopen(filename, "rb");
3713 fprintf(stderr, _("%s: error loading XIM!\n"), programName);
3720 for (y=0; y<h; ++y) {
3721 for (x=0; x<h; ++x) {
3726 XPutPixel(xim, x, y, blackPieceColor);
3728 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3731 XPutPixel(xim, x, y, darkSquareColor);
3733 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3736 XPutPixel(xim, x, y, whitePieceColor);
3738 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3741 XPutPixel(xim, x, y, lightSquareColor);
3743 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3749 /* create Pixmap of piece */
3750 *dest = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3752 XPutImage(xDisplay, *dest, lightSquareGC, xim,
3755 /* create Pixmap of clipmask
3756 Note: We assume the white/black pieces have the same
3757 outline, so we make only 6 masks. This is okay
3758 since the XPM clipmask routines do the same. */
3760 temp = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3762 XPutImage(xDisplay, temp, lightSquareGC, xmask,
3765 /* now create the 1-bit version */
3766 *mask = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3769 values.foreground = 1;
3770 values.background = 0;
3772 /* Don't use XtGetGC, not read only */
3773 maskGC = XCreateGC(xDisplay, *mask,
3774 GCForeground | GCBackground, &values);
3775 XCopyPlane(xDisplay, temp, *mask, maskGC,
3776 0, 0, squareSize, squareSize, 0, 0, 1);
3777 XFreePixmap(xDisplay, temp);
3782 char pieceBitmapNames[] = "pnbrqfeacwmohijgdvlsukpnsl";
3784 void CreateXIMPieces()
3789 static char *ximkind[] = { "ll", "ld", "dl", "dd" };
3794 /* The XSynchronize calls were copied from CreatePieces.
3795 Not sure if needed, but can't hurt */
3796 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3799 /* temp needed by loadXIM() */
3800 ximtemp = XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3801 0, 0, ss, ss, AllPlanes, XYPixmap);
3803 if (strlen(appData.pixmapDirectory) == 0) {
3807 if (appData.monoMode) {
3808 DisplayFatalError(_("XIM pieces cannot be used in monochrome mode"),
3812 fprintf(stderr, _("\nLoading XIMs...\n"));
3814 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3815 fprintf(stderr, "%d", piece+1);
3816 for (kind=0; kind<4; kind++) {
3817 fprintf(stderr, ".");
3818 snprintf(buf, sizeof(buf), "%s/%s%c%s%u.xim",
3819 ExpandPathName(appData.pixmapDirectory),
3820 piece <= (int) WhiteKing ? "" : "w",
3821 pieceBitmapNames[piece],
3823 ximPieceBitmap[kind][piece] =
3824 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3825 0, 0, ss, ss, AllPlanes, XYPixmap);
3826 if (appData.debugMode)
3827 fprintf(stderr, _("(File:%s:) "), buf);
3828 loadXIM(ximPieceBitmap[kind][piece],
3830 &(xpmPieceBitmap2[kind][piece]),
3831 &(ximMaskPm2[piece]));
3832 if(piece <= (int)WhiteKing)
3833 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3835 fprintf(stderr," ");
3837 /* Load light and dark squares */
3838 /* If the LSQ and DSQ pieces don't exist, we will
3839 draw them with solid squares. */
3840 snprintf(buf,sizeof(buf), "%s/lsq%u.xim", ExpandPathName(appData.pixmapDirectory), ss);
3841 if (access(buf, 0) != 0) {
3845 fprintf(stderr, _("light square "));
3847 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3848 0, 0, ss, ss, AllPlanes, XYPixmap);
3849 if (appData.debugMode)
3850 fprintf(stderr, _("(File:%s:) "), buf);
3852 loadXIM(ximLightSquare, NULL, buf, &xpmLightSquare, NULL);
3853 fprintf(stderr, _("dark square "));
3854 snprintf(buf,sizeof(buf), "%s/dsq%u.xim",
3855 ExpandPathName(appData.pixmapDirectory), ss);
3856 if (appData.debugMode)
3857 fprintf(stderr, _("(File:%s:) "), buf);
3859 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3860 0, 0, ss, ss, AllPlanes, XYPixmap);
3861 loadXIM(ximDarkSquare, NULL, buf, &xpmDarkSquare, NULL);
3862 xpmJailSquare = xpmLightSquare;
3864 fprintf(stderr, _("Done.\n"));
3866 XSynchronize(xDisplay, False); /* Work-around for xlib/xt buffering bug */
3870 void CreateXPMPieces()
3874 u_int ss = squareSize;
3876 static char *xpmkind[] = { "ll", "ld", "dl", "dd" };
3877 XpmColorSymbol symbols[4];
3880 /* Apparently some versions of Xpm don't define XpmFormat at all --tpm */
3881 if (appData.debugMode) {
3882 fprintf(stderr, "XPM Library Version: %d.%d%c\n",
3883 XpmFormat, XpmVersion, (char)('a' + XpmRevision - 1));
3887 /* The XSynchronize calls were copied from CreatePieces.
3888 Not sure if needed, but can't hurt */
3889 XSynchronize(xDisplay, True); /* Work-around for xlib/xt buffering bug */
3891 /* Setup translations so piece colors match square colors */
3892 symbols[0].name = "light_piece";
3893 symbols[0].value = appData.whitePieceColor;
3894 symbols[1].name = "dark_piece";
3895 symbols[1].value = appData.blackPieceColor;
3896 symbols[2].name = "light_square";
3897 symbols[2].value = appData.lightSquareColor;
3898 symbols[3].name = "dark_square";
3899 symbols[3].value = appData.darkSquareColor;
3901 attr.valuemask = XpmColorSymbols;
3902 attr.colorsymbols = symbols;
3903 attr.numsymbols = 4;
3905 if (appData.monoMode) {
3906 DisplayFatalError(_("XPM pieces cannot be used in monochrome mode"),
3910 if (strlen(appData.pixmapDirectory) == 0) {
3911 XpmPieces* pieces = builtInXpms;
3914 while (pieces->size != squareSize && pieces->size) pieces++;
3915 if (!pieces->size) {
3916 fprintf(stderr, _("No builtin XPM pieces of size %d\n"), squareSize);
3919 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3920 for (kind=0; kind<4; kind++) {
3922 if ((r=XpmCreatePixmapFromData(xDisplay, xBoardWindow,
3923 pieces->xpm[piece][kind],
3924 &(xpmPieceBitmap2[kind][piece]),
3925 NULL, &attr)) != 0) {
3926 fprintf(stderr, _("Error %d loading XPM image \"%s\"\n"),
3930 if(piece <= (int) WhiteKing)
3931 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3935 xpmJailSquare = xpmLightSquare;
3939 fprintf(stderr, _("\nLoading XPMs...\n"));
3942 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3943 fprintf(stderr, "%d ", piece+1);
3944 for (kind=0; kind<4; kind++) {
3945 snprintf(buf, sizeof(buf), "%s/%s%c%s%u.xpm",
3946 ExpandPathName(appData.pixmapDirectory),
3947 piece > (int) WhiteKing ? "w" : "",
3948 pieceBitmapNames[piece],
3950 if (appData.debugMode) {
3951 fprintf(stderr, _("(File:%s:) "), buf);
3953 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3954 &(xpmPieceBitmap2[kind][piece]),
3955 NULL, &attr)) != 0) {
3956 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"),
3960 if(piece <= (int) WhiteKing)
3961 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3964 /* Load light and dark squares */
3965 /* If the LSQ and DSQ pieces don't exist, we will
3966 draw them with solid squares. */
3967 fprintf(stderr, _("light square "));
3968 snprintf(buf, sizeof(buf), "%s/lsq%u.xpm", ExpandPathName(appData.pixmapDirectory), ss);
3969 if (access(buf, 0) != 0) {
3973 if (appData.debugMode)
3974 fprintf(stderr, _("(File:%s:) "), buf);
3976 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3977 &xpmLightSquare, NULL, &attr)) != 0) {
3978 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
3981 fprintf(stderr, _("dark square "));
3982 snprintf(buf, sizeof(buf), "%s/dsq%u.xpm",
3983 ExpandPathName(appData.pixmapDirectory), ss);
3984 if (appData.debugMode) {
3985 fprintf(stderr, _("(File:%s:) "), buf);
3987 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3988 &xpmDarkSquare, NULL, &attr)) != 0) {
3989 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
3993 xpmJailSquare = xpmLightSquare;
3994 fprintf(stderr, _("Done.\n"));
3996 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3999 #endif /* HAVE_LIBXPM */
4002 /* No built-in bitmaps */
4007 u_int ss = squareSize;
4009 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
4012 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
4013 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
4014 sprintf(buf, "%s%c%u%c.bm", piece > (int)WhiteKing ? "w" : "",
4015 pieceBitmapNames[piece],
4016 ss, kind == SOLID ? 's' : 'o');
4017 ReadBitmap(&pieceBitmap2[kind][piece], buf, NULL, ss, ss);
4018 if(piece <= (int)WhiteKing)
4019 pieceBitmap[kind][piece] = pieceBitmap2[kind][piece];
4023 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
4027 /* With built-in bitmaps */
4030 BuiltInBits* bib = builtInBits;
4033 u_int ss = squareSize;
4035 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
4038 while (bib->squareSize != ss && bib->squareSize != 0) bib++;
4040 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
4041 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
4042 sprintf(buf, "%s%c%u%c.bm", piece > (int)WhiteKing ? "w" : "",
4043 pieceBitmapNames[piece],
4044 ss, kind == SOLID ? 's' : 'o');
4045 ReadBitmap(&pieceBitmap2[kind][piece], buf,
4046 bib->bits[kind][piece], ss, ss);
4047 if(piece <= (int)WhiteKing)
4048 pieceBitmap[kind][piece] = pieceBitmap2[kind][piece];
4052 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
4057 void ReadBitmap(pm, name, bits, wreq, hreq)
4060 unsigned char bits[];
4066 char msg[MSG_SIZ], fullname[MSG_SIZ];
4068 if (*appData.bitmapDirectory != NULLCHAR) {
4069 strcpy(fullname, appData.bitmapDirectory);
4070 strcat(fullname, "/");
4071 strcat(fullname, name);
4072 errcode = XReadBitmapFile(xDisplay, xBoardWindow, fullname,
4073 &w, &h, pm, &x_hot, &y_hot);
4074 fprintf(stderr, "load %s\n", name);
4075 if (errcode != BitmapSuccess) {
4077 case BitmapOpenFailed:
4078 snprintf(msg, sizeof(msg), _("Can't open bitmap file %s"), fullname);
4080 case BitmapFileInvalid:
4081 snprintf(msg, sizeof(msg), _("Invalid bitmap in file %s"), fullname);
4083 case BitmapNoMemory:
4084 snprintf(msg, sizeof(msg), _("Ran out of memory reading bitmap file %s"),
4088 snprintf(msg, sizeof(msg), _("Unknown XReadBitmapFile error %d on file %s"),
4092 fprintf(stderr, _("%s: %s...using built-in\n"),
4094 } else if (w != wreq || h != hreq) {
4096 _("%s: Bitmap %s is %dx%d, not %dx%d...using built-in\n"),
4097 programName, fullname, w, h, wreq, hreq);
4104 fprintf(stderr, _("%s: No built-in bitmap for %s; giving up\n"),
4108 ; // [HGM] bitmaps: make it non-fatal if we have no bitmap;
4110 *pm = XCreateBitmapFromData(xDisplay, xBoardWindow, (char *) bits,
4119 if (lineGap == 0) return;
4121 /* [HR] Split this into 2 loops for non-square boards. */
4123 for (i = 0; i < BOARD_HEIGHT + 1; i++) {
4124 gridSegments[i].x1 = 0;
4125 gridSegments[i].x2 =
4126 lineGap + BOARD_WIDTH * (squareSize + lineGap);
4127 gridSegments[i].y1 = gridSegments[i].y2
4128 = lineGap / 2 + (i * (squareSize + lineGap));
4131 for (j = 0; j < BOARD_WIDTH + 1; j++) {
4132 gridSegments[j + i].y1 = 0;
4133 gridSegments[j + i].y2 =
4134 lineGap + BOARD_HEIGHT * (squareSize + lineGap);
4135 gridSegments[j + i].x1 = gridSegments[j + i].x2
4136 = lineGap / 2 + (j * (squareSize + lineGap));
4140 static void MenuBarSelect(w, addr, index)
4145 XtActionProc proc = (XtActionProc) addr;
4147 (proc)(NULL, NULL, NULL, NULL);
4150 void CreateMenuBarPopup(parent, name, mb)
4160 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
4163 XtSetArg(args[j], XtNleftMargin, 20); j++;
4164 XtSetArg(args[j], XtNrightMargin, 20); j++;
4166 while (mi->string != NULL) {
4167 if (strcmp(mi->string, "----") == 0) {
4168 entry = XtCreateManagedWidget(mi->string, smeLineObjectClass,
4171 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string)));
4172 entry = XtCreateManagedWidget(mi->string, smeBSBObjectClass,
4174 XtAddCallback(entry, XtNcallback,
4175 (XtCallbackProc) MenuBarSelect,
4176 (caddr_t) mi->proc);
4182 Widget CreateMenuBar(mb)
4186 Widget anchor, menuBar;
4188 char menuName[MSG_SIZ];
4191 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
4192 XtSetArg(args[j], XtNvSpace, 0); j++;
4193 XtSetArg(args[j], XtNborderWidth, 0); j++;
4194 menuBar = XtCreateWidget("menuBar", boxWidgetClass,
4195 formWidget, args, j);
4197 while (mb->name != NULL) {
4198 strcpy(menuName, "menu");
4199 strcat(menuName, mb->name);
4201 XtSetArg(args[j], XtNmenuName, XtNewString(menuName)); j++;
4204 shortName[0] = _(mb->name)[0];
4205 shortName[1] = NULLCHAR;
4206 XtSetArg(args[j], XtNlabel, XtNewString(shortName)); j++;
4209 XtSetArg(args[j], XtNlabel, XtNewString(_(mb->name))); j++;
4212 XtSetArg(args[j], XtNborderWidth, 0); j++;
4213 anchor = XtCreateManagedWidget(mb->name, menuButtonWidgetClass,
4215 CreateMenuBarPopup(menuBar, menuName, mb);
4221 Widget CreateButtonBar(mi)
4225 Widget button, buttonBar;
4229 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
4231 XtSetArg(args[j], XtNhSpace, 0); j++;
4233 XtSetArg(args[j], XtNborderWidth, 0); j++;
4234 XtSetArg(args[j], XtNvSpace, 0); j++;
4235 buttonBar = XtCreateWidget("buttonBar", boxWidgetClass,
4236 formWidget, args, j);
4238 while (mi->string != NULL) {
4241 XtSetArg(args[j], XtNinternalWidth, 2); j++;
4242 XtSetArg(args[j], XtNborderWidth, 0); j++;
4244 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string))); j++;
4245 button = XtCreateManagedWidget(mi->string, commandWidgetClass,
4246 buttonBar, args, j);
4247 XtAddCallback(button, XtNcallback,
4248 (XtCallbackProc) MenuBarSelect,
4249 (caddr_t) mi->proc);
4256 CreatePieceMenu(name, color)
4263 ChessSquare selection;
4265 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
4266 boardWidget, args, 0);
4268 for (i = 0; i < PIECE_MENU_SIZE; i++) {
4269 String item = pieceMenuStrings[color][i];
4271 if (strcmp(item, "----") == 0) {
4272 entry = XtCreateManagedWidget(item, smeLineObjectClass,
4275 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
4276 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
4278 selection = pieceMenuTranslation[color][i];
4279 XtAddCallback(entry, XtNcallback,
4280 (XtCallbackProc) PieceMenuSelect,
4281 (caddr_t) selection);
4282 if (selection == WhitePawn || selection == BlackPawn) {
4283 XtSetArg(args[0], XtNpopupOnEntry, entry);
4284 XtSetValues(menu, args, 1);
4297 ChessSquare selection;
4299 whitePieceMenu = CreatePieceMenu("menuW", 0);
4300 blackPieceMenu = CreatePieceMenu("menuB", 1);
4302 XtRegisterGrabAction(PieceMenuPopup, True,
4303 (unsigned)(ButtonPressMask|ButtonReleaseMask),
4304 GrabModeAsync, GrabModeAsync);
4306 XtSetArg(args[0], XtNlabel, _("Drop"));
4307 dropMenu = XtCreatePopupShell("menuD", simpleMenuWidgetClass,
4308 boardWidget, args, 1);
4309 for (i = 0; i < DROP_MENU_SIZE; i++) {
4310 String item = dropMenuStrings[i];
4312 if (strcmp(item, "----") == 0) {
4313 entry = XtCreateManagedWidget(item, smeLineObjectClass,
4316 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
4317 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
4319 selection = dropMenuTranslation[i];
4320 XtAddCallback(entry, XtNcallback,
4321 (XtCallbackProc) DropMenuSelect,
4322 (caddr_t) selection);
4327 void SetupDropMenu()
4335 for (i=0; i<sizeof(dmEnables)/sizeof(DropMenuEnables); i++) {
4336 entry = XtNameToWidget(dropMenu, dmEnables[i].widget);
4337 p = strchr(gameMode == IcsPlayingWhite ? white_holding : black_holding,
4338 dmEnables[i].piece);
4339 XtSetSensitive(entry, p != NULL || !appData.testLegality
4340 /*!!temp:*/ || (gameInfo.variant == VariantCrazyhouse
4341 && !appData.icsActive));
4343 while (p && *p++ == dmEnables[i].piece) count++;
4344 snprintf(label, sizeof(label), "%s %d", dmEnables[i].widget, count);
4346 XtSetArg(args[j], XtNlabel, label); j++;
4347 XtSetValues(entry, args, j);
4351 void PieceMenuPopup(w, event, params, num_params)
4355 Cardinal *num_params;
4358 if (event->type != ButtonPress) return;
4359 if (errorUp) ErrorPopDown();
4363 whichMenu = params[0];
4365 case IcsPlayingWhite:
4366 case IcsPlayingBlack:
4368 case MachinePlaysWhite:
4369 case MachinePlaysBlack:
4370 if (appData.testLegality &&
4371 gameInfo.variant != VariantBughouse &&
4372 gameInfo.variant != VariantCrazyhouse) return;
4374 whichMenu = "menuD";
4380 if (((pmFromX = EventToSquare(event->xbutton.x, BOARD_WIDTH)) < 0) ||
4381 ((pmFromY = EventToSquare(event->xbutton.y, BOARD_HEIGHT)) < 0)) {
4382 pmFromX = pmFromY = -1;
4386 pmFromX = BOARD_WIDTH - 1 - pmFromX;
4388 pmFromY = BOARD_HEIGHT - 1 - pmFromY;
4390 XtPopupSpringLoaded(XtNameToWidget(boardWidget, whichMenu));
4393 static void PieceMenuSelect(w, piece, junk)
4398 if (pmFromX < 0 || pmFromY < 0) return;
4399 EditPositionMenuEvent(piece, pmFromX, pmFromY);
4402 static void DropMenuSelect(w, piece, junk)
4407 if (pmFromX < 0 || pmFromY < 0) return;
4408 DropMenuEvent(piece, pmFromX, pmFromY);
4411 void WhiteClock(w, event, prms, nprms)
4417 if (gameMode == EditPosition || gameMode == IcsExamining) {
4418 SetWhiteToPlayEvent();
4419 } else if (gameMode == IcsPlayingBlack || gameMode == MachinePlaysWhite) {
4424 void BlackClock(w, event, prms, nprms)
4430 if (gameMode == EditPosition || gameMode == IcsExamining) {
4431 SetBlackToPlayEvent();
4432 } else if (gameMode == IcsPlayingWhite || gameMode == MachinePlaysBlack) {
4439 * If the user selects on a border boundary, return -1; if off the board,
4440 * return -2. Otherwise map the event coordinate to the square.
4442 int EventToSquare(x, limit)
4450 if ((x % (squareSize + lineGap)) >= squareSize)
4452 x /= (squareSize + lineGap);
4458 static void do_flash_delay(msec)
4464 static void drawHighlight(file, rank, gc)
4470 if (lineGap == 0 || appData.blindfold) return;
4473 x = lineGap/2 + ((BOARD_WIDTH-1)-file) *
4474 (squareSize + lineGap);
4475 y = lineGap/2 + rank * (squareSize + lineGap);
4477 x = lineGap/2 + file * (squareSize + lineGap);
4478 y = lineGap/2 + ((BOARD_HEIGHT-1)-rank) *
4479 (squareSize + lineGap);
4482 XDrawRectangle(xDisplay, xBoardWindow, gc, x, y,
4483 squareSize+lineGap, squareSize+lineGap);
4486 int hi1X = -1, hi1Y = -1, hi2X = -1, hi2Y = -1;
4487 int pm1X = -1, pm1Y = -1, pm2X = -1, pm2Y = -1;
4490 SetHighlights(fromX, fromY, toX, toY)
4491 int fromX, fromY, toX, toY;
4493 if (hi1X != fromX || hi1Y != fromY) {
4494 if (hi1X >= 0 && hi1Y >= 0) {
4495 drawHighlight(hi1X, hi1Y, lineGC);
4497 if (fromX >= 0 && fromY >= 0) {
4498 drawHighlight(fromX, fromY, highlineGC);
4501 if (hi2X != toX || hi2Y != toY) {
4502 if (hi2X >= 0 && hi2Y >= 0) {
4503 drawHighlight(hi2X, hi2Y, lineGC);
4505 if (toX >= 0 && toY >= 0) {
4506 drawHighlight(toX, toY, highlineGC);
4518 SetHighlights(-1, -1, -1, -1);
4523 SetPremoveHighlights(fromX, fromY, toX, toY)
4524 int fromX, fromY, toX, toY;
4526 if (pm1X != fromX || pm1Y != fromY) {
4527 if (pm1X >= 0 && pm1Y >= 0) {
4528 drawHighlight(pm1X, pm1Y, lineGC);
4530 if (fromX >= 0 && fromY >= 0) {
4531 drawHighlight(fromX, fromY, prelineGC);
4534 if (pm2X != toX || pm2Y != toY) {
4535 if (pm2X >= 0 && pm2Y >= 0) {
4536 drawHighlight(pm2X, pm2Y, lineGC);
4538 if (toX >= 0 && toY >= 0) {
4539 drawHighlight(toX, toY, prelineGC);
4549 ClearPremoveHighlights()
4551 SetPremoveHighlights(-1, -1, -1, -1);
4554 static void BlankSquare(x, y, color, piece, dest)
4559 if (useImages && useImageSqs) {
4563 pm = xpmLightSquare;
4568 case 2: /* neutral */
4573 XCopyArea(xDisplay, pm, dest, wlPieceGC, 0, 0,
4574 squareSize, squareSize, x, y);
4584 case 2: /* neutral */
4589 XFillRectangle(xDisplay, dest, gc, x, y, squareSize, squareSize);
4594 I split out the routines to draw a piece so that I could
4595 make a generic flash routine.
4597 static void monoDrawPiece_1bit(piece, square_color, x, y, dest)
4599 int square_color, x, y;
4602 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
4603 switch (square_color) {
4605 case 2: /* neutral */
4607 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
4608 ? *pieceToOutline(piece)
4609 : *pieceToSolid(piece),
4610 dest, bwPieceGC, 0, 0,
4611 squareSize, squareSize, x, y);
4614 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
4615 ? *pieceToSolid(piece)
4616 : *pieceToOutline(piece),
4617 dest, wbPieceGC, 0, 0,
4618 squareSize, squareSize, x, y);
4623 static void monoDrawPiece(piece, square_color, x, y, dest)
4625 int square_color, x, y;
4628 switch (square_color) {
4630 case 2: /* neutral */
4632 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
4633 ? *pieceToOutline(piece)
4634 : *pieceToSolid(piece),
4635 dest, bwPieceGC, 0, 0,
4636 squareSize, squareSize, x, y, 1);
4639 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
4640 ? *pieceToSolid(piece)
4641 : *pieceToOutline(piece),
4642 dest, wbPieceGC, 0, 0,
4643 squareSize, squareSize, x, y, 1);
4648 static void colorDrawPiece(piece, square_color, x, y, dest)
4650 int square_color, x, y;
4653 if(pieceToSolid(piece) == NULL) return; // [HGM] bitmaps: make it non-fatal if we have no bitmap;
4654 switch (square_color) {
4656 XCopyPlane(xDisplay, *pieceToSolid(piece),
4657 dest, (int) piece < (int) BlackPawn
4658 ? wlPieceGC : blPieceGC, 0, 0,
4659 squareSize, squareSize, x, y, 1);
4662 XCopyPlane(xDisplay, *pieceToSolid(piece),
4663 dest, (int) piece < (int) BlackPawn
4664 ? wdPieceGC : bdPieceGC, 0, 0,
4665 squareSize, squareSize, x, y, 1);
4667 case 2: /* neutral */
4669 XCopyPlane(xDisplay, *pieceToSolid(piece),
4670 dest, (int) piece < (int) BlackPawn
4671 ? wjPieceGC : bjPieceGC, 0, 0,
4672 squareSize, squareSize, x, y, 1);
4677 static void colorDrawPieceImage(piece, square_color, x, y, dest)
4679 int square_color, x, y;
4684 switch (square_color) {
4686 case 2: /* neutral */
4688 if ((int)piece < (int) BlackPawn) {
4696 if ((int)piece < (int) BlackPawn) {
4704 XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
4705 dest, wlPieceGC, 0, 0,
4706 squareSize, squareSize, x, y);
4709 typedef void (*DrawFunc)();
4711 DrawFunc ChooseDrawFunc()
4713 if (appData.monoMode) {
4714 if (DefaultDepth(xDisplay, xScreen) == 1) {
4715 return monoDrawPiece_1bit;
4717 return monoDrawPiece;
4721 return colorDrawPieceImage;
4723 return colorDrawPiece;
4727 /* [HR] determine square color depending on chess variant. */
4728 static int SquareColor(row, column)
4733 if (gameInfo.variant == VariantXiangqi) {
4734 if (column >= 3 && column <= 5 && row >= 0 && row <= 2) {
4736 } else if (column >= 3 && column <= 5 && row >= 7 && row <= 9) {
4738 } else if (row <= 4) {
4744 square_color = ((column + row) % 2) == 1;
4747 /* [hgm] holdings: next line makes all holdings squares light */
4748 if(column < BOARD_LEFT || column >= BOARD_RGHT) square_color = 1;
4750 return square_color;
4753 void DrawSquare(row, column, piece, do_flash)
4754 int row, column, do_flash;
4757 int square_color, x, y, direction, font_ascent, font_descent;
4760 XCharStruct overall;
4764 /* Calculate delay in milliseconds (2-delays per complete flash) */
4765 flash_delay = 500 / appData.flashRate;
4768 x = lineGap + ((BOARD_WIDTH-1)-column) *
4769 (squareSize + lineGap);
4770 y = lineGap + row * (squareSize + lineGap);
4772 x = lineGap + column * (squareSize + lineGap);
4773 y = lineGap + ((BOARD_HEIGHT-1)-row) *
4774 (squareSize + lineGap);
4777 square_color = SquareColor(row, column);
4779 if ( // [HGM] holdings: blank out area between board and holdings
4780 column == BOARD_LEFT-1 || column == BOARD_RGHT
4781 || (column == BOARD_LEFT-2 && row < BOARD_HEIGHT-gameInfo.holdingsSize)
4782 || (column == BOARD_RGHT+1 && row >= gameInfo.holdingsSize) ) {
4783 BlankSquare(x, y, 2, EmptySquare, xBoardWindow);
4785 // [HGM] print piece counts next to holdings
4786 string[1] = NULLCHAR;
4787 if (column == (flipView ? BOARD_LEFT-1 : BOARD_RGHT) && piece > 1 ) {
4788 string[0] = '0' + piece;
4789 XTextExtents(countFontStruct, string, 1, &direction,
4790 &font_ascent, &font_descent, &overall);
4791 if (appData.monoMode) {
4792 XDrawImageString(xDisplay, xBoardWindow, countGC,
4793 x + squareSize - overall.width - 2,
4794 y + font_ascent + 1, string, 1);
4796 XDrawString(xDisplay, xBoardWindow, countGC,
4797 x + squareSize - overall.width - 2,
4798 y + font_ascent + 1, string, 1);
4801 if (column == (flipView ? BOARD_RGHT : BOARD_LEFT-1) && piece > 1) {
4802 string[0] = '0' + piece;
4803 XTextExtents(countFontStruct, string, 1, &direction,
4804 &font_ascent, &font_descent, &overall);
4805 if (appData.monoMode) {
4806 XDrawImageString(xDisplay, xBoardWindow, countGC,
4807 x + 2, y + font_ascent + 1, string, 1);
4809 XDrawString(xDisplay, xBoardWindow, countGC,
4810 x + 2, y + font_ascent + 1, string, 1);
4814 if (piece == EmptySquare || appData.blindfold) {
4815 BlankSquare(x, y, square_color, piece, xBoardWindow);
4817 drawfunc = ChooseDrawFunc();
4818 if (do_flash && appData.flashCount > 0) {
4819 for (i=0; i<appData.flashCount; ++i) {
4821 drawfunc(piece, square_color, x, y, xBoardWindow);
4822 XSync(xDisplay, False);
4823 do_flash_delay(flash_delay);
4825 BlankSquare(x, y, square_color, piece, xBoardWindow);
4826 XSync(xDisplay, False);
4827 do_flash_delay(flash_delay);
4830 drawfunc(piece, square_color, x, y, xBoardWindow);
4834 string[1] = NULLCHAR;
4835 if (appData.showCoords && row == (flipView ? BOARD_HEIGHT-1 : 0)
4836 && column >= BOARD_LEFT && column < BOARD_RGHT) {
4837 string[0] = 'a' + column - BOARD_LEFT;
4838 XTextExtents(coordFontStruct, string, 1, &direction,
4839 &font_ascent, &font_descent, &overall);
4840 if (appData.monoMode) {
4841 XDrawImageString(xDisplay, xBoardWindow, coordGC,
4842 x + squareSize - overall.width - 2,
4843 y + squareSize - font_descent - 1, string, 1);
4845 XDrawString(xDisplay, xBoardWindow, coordGC,
4846 x + squareSize - overall.width - 2,
4847 y + squareSize - font_descent - 1, string, 1);
4850 if (appData.showCoords && column == (flipView ? BOARD_RGHT-1 : BOARD_LEFT)) {
4851 string[0] = ONE + row;
4852 XTextExtents(coordFontStruct, string, 1, &direction,
4853 &font_ascent, &font_descent, &overall);
4854 if (appData.monoMode) {
4855 XDrawImageString(xDisplay, xBoardWindow, coordGC,
4856 x + 2, y + font_ascent + 1, string, 1);
4858 XDrawString(xDisplay, xBoardWindow, coordGC,
4859 x + 2, y + font_ascent + 1, string, 1);
4865 /* Why is this needed on some versions of X? */
4866 void EventProc(widget, unused, event)
4871 if (!XtIsRealized(widget))
4874 switch (event->type) {
4876 if (event->xexpose.count > 0) return; /* no clipping is done */
4877 XDrawPosition(widget, True, NULL);
4885 void DrawPosition(fullRedraw, board)
4886 /*Boolean*/int fullRedraw;
4889 XDrawPosition(boardWidget, fullRedraw, board);
4892 /* Returns 1 if there are "too many" differences between b1 and b2
4893 (i.e. more than 1 move was made) */
4894 static int too_many_diffs(b1, b2)
4900 for (i=0; i<BOARD_HEIGHT; ++i) {
4901 for (j=0; j<BOARD_WIDTH; ++j) {
4902 if (b1[i][j] != b2[i][j]) {
4903 if (++c > 4) /* Castling causes 4 diffs */
4912 /* Matrix describing castling maneuvers */
4913 /* Row, ColRookFrom, ColKingFrom, ColRookTo, ColKingTo */
4914 static int castling_matrix[4][5] = {
4915 { 0, 0, 4, 3, 2 }, /* 0-0-0, white */
4916 { 0, 7, 4, 5, 6 }, /* 0-0, white */
4917 { 7, 0, 4, 3, 2 }, /* 0-0-0, black */
4918 { 7, 7, 4, 5, 6 } /* 0-0, black */
4921 /* Checks whether castling occurred. If it did, *rrow and *rcol
4922 are set to the destination (row,col) of the rook that moved.
4924 Returns 1 if castling occurred, 0 if not.
4926 Note: Only handles a max of 1 castling move, so be sure
4927 to call too_many_diffs() first.
4929 static int check_castle_draw(newb, oldb, rrow, rcol)
4936 /* For each type of castling... */
4937 for (i=0; i<4; ++i) {
4938 r = castling_matrix[i];
4940 /* Check the 4 squares involved in the castling move */
4942 for (j=1; j<=4; ++j) {
4943 if (newb[r[0]][r[j]] == oldb[r[0]][r[j]]) {
4950 /* All 4 changed, so it must be a castling move */
4959 static int damage[BOARD_SIZE][BOARD_SIZE];
4962 * event handler for redrawing the board
4964 void XDrawPosition(w, repaint, board)
4966 /*Boolean*/int repaint;
4970 static int lastFlipView = 0;
4971 static int lastBoardValid = 0;
4972 static Board lastBoard;
4976 if (board == NULL) {
4977 if (!lastBoardValid) return;
4980 if (!lastBoardValid || lastFlipView != flipView) {
4981 XtSetArg(args[0], XtNleftBitmap, (flipView ? xMarkPixmap : None));
4982 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flip View"),
4987 * It would be simpler to clear the window with XClearWindow()
4988 * but this causes a very distracting flicker.
4991 if (!repaint && lastBoardValid && lastFlipView == flipView) {
4993 /* If too much changes (begin observing new game, etc.), don't
4995 do_flash = too_many_diffs(board, lastBoard) ? 0 : 1;
4997 /* Special check for castling so we don't flash both the king
4998 and the rook (just flash the king). */
5000 if (check_castle_draw(board, lastBoard, &rrow, &rcol)) {
5001 /* Draw rook with NO flashing. King will be drawn flashing later */
5002 DrawSquare(rrow, rcol, board[rrow][rcol], 0);
5003 lastBoard[rrow][rcol] = board[rrow][rcol];
5007 /* First pass -- Draw (newly) empty squares and repair damage.
5008 This prevents you from having a piece show up twice while it
5009 is flashing on its new square */
5010 for (i = 0; i < BOARD_HEIGHT; i++)
5011 for (j = 0; j < BOARD_WIDTH; j++)
5012 if ((board[i][j] != lastBoard[i][j] && board[i][j] == EmptySquare)
5014 DrawSquare(i, j, board[i][j], 0);
5015 damage[i][j] = False;
5018 /* Second pass -- Draw piece(s) in new position and flash them */
5019 for (i = 0; i < BOARD_HEIGHT; i++)
5020 for (j = 0; j < BOARD_WIDTH; j++)
5021 if (board[i][j] != lastBoard[i][j]) {
5022 DrawSquare(i, j, board[i][j], do_flash);
5026 XDrawSegments(xDisplay, xBoardWindow, lineGC,
5027 gridSegments, BOARD_HEIGHT + BOARD_WIDTH + 2);
5029 for (i = 0; i < BOARD_HEIGHT; i++)
5030 for (j = 0; j < BOARD_WIDTH; j++) {
5031 DrawSquare(i, j, board[i][j], 0);
5032 damage[i][j] = False;
5036 CopyBoard(lastBoard, board);
5038 lastFlipView = flipView;
5040 /* Draw highlights */
5041 if (pm1X >= 0 && pm1Y >= 0) {
5042 drawHighlight(pm1X, pm1Y, prelineGC);
5044 if (pm2X >= 0 && pm2Y >= 0) {
5045 drawHighlight(pm2X, pm2Y, prelineGC);
5047 if (hi1X >= 0 && hi1Y >= 0) {
5048 drawHighlight(hi1X, hi1Y, highlineGC);
5050 if (hi2X >= 0 && hi2Y >= 0) {
5051 drawHighlight(hi2X, hi2Y, highlineGC);
5054 /* If piece being dragged around board, must redraw that too */
5057 XSync(xDisplay, False);
5062 * event handler for redrawing the board
5064 void DrawPositionProc(w, event, prms, nprms)
5070 XDrawPosition(w, True, NULL);
5075 * event handler for parsing user moves
5077 // [HGM] This routine will need quite some reworking. Although the backend still supports the old
5078 // way of doing things, by calling UserMoveEvent() to test the legality of the move and then perform
5079 // it at the end, and doing all kind of preliminary tests here (e.g. to weed out self-captures), it
5080 // should be made to use the new way, of calling UserMoveTest early to determine the legality of the
5081 // move, (which will weed out the illegal selfcaptures and moves into the holdings, and flag promotions),
5082 // and at the end FinishMove() to perform the move after optional promotion popups.
5083 // For now I patched it to allow self-capture with King, and suppress clicks between board and holdings.
5084 void HandleUserMove(w, event, prms, nprms)
5091 Boolean saveAnimate;
5092 static int second = 0;
5094 if (w != boardWidget || errorExitStatus != -1) return;
5096 if (event->type == ButtonPress) ErrorPopDown();
5099 if (event->type == ButtonPress) {
5100 XtPopdown(promotionShell);
5101 XtDestroyWidget(promotionShell);
5102 promotionUp = False;
5110 x = EventToSquare(event->xbutton.x, BOARD_WIDTH);
5111 y = EventToSquare(event->xbutton.y, BOARD_HEIGHT);
5112 if (!flipView && y >= 0) {
5113 y = BOARD_HEIGHT - 1 - y;
5115 if (flipView && x >= 0) {
5116 x = BOARD_WIDTH - 1 - x;
5119 /* [HGM] holdings: next 5 lines: ignore all clicks between board and holdings */
5120 if(event->type == ButtonPress
5121 && ( x == BOARD_LEFT-1 || x == BOARD_RGHT
5122 || x == BOARD_LEFT-2 && y < BOARD_HEIGHT-gameInfo.holdingsSize
5123 || x == BOARD_RGHT+1 && y >= gameInfo.holdingsSize) )
5127 if (event->type == ButtonPress) {
5129 if (OKToStartUserMove(x, y)) {
5133 DragPieceBegin(event->xbutton.x, event->xbutton.y);
5134 if (appData.highlightDragging) {
5135 SetHighlights(x, y, -1, -1);
5143 if (event->type == ButtonPress && gameMode != EditPosition &&
5148 /* Check if clicking again on the same color piece */
5149 fromP = boards[currentMove][fromY][fromX];
5150 toP = boards[currentMove][y][x];
5151 if ((WhitePawn <= fromP && fromP < WhiteKing && // [HGM] this test should go, as UserMoveTest now does it.
5152 WhitePawn <= toP && toP <= WhiteKing) || // For now I made it less critical by exempting King
5153 (BlackPawn <= fromP && fromP < BlackKing && // moves, to not interfere with FRC castlings.
5154 BlackPawn <= toP && toP <= BlackKing)) {
5155 /* Clicked again on same color piece -- changed his mind */
5156 second = (x == fromX && y == fromY);
5157 if (appData.highlightDragging) {
5158 SetHighlights(x, y, -1, -1);
5162 if (OKToStartUserMove(x, y)) {
5165 DragPieceBegin(event->xbutton.x, event->xbutton.y);
5171 if (event->type == ButtonRelease && x == fromX && y == fromY) {
5172 DragPieceEnd(event->xbutton.x, event->xbutton.y);
5173 if (appData.animateDragging) {
5174 /* Undo animation damage if any */
5175 DrawPosition(FALSE, NULL);
5178 /* Second up/down in same square; just abort move */
5183 ClearPremoveHighlights();
5185 /* First upclick in same square; start click-click mode */
5186 SetHighlights(x, y, -1, -1);
5191 /* Completed move */
5194 saveAnimate = appData.animate;
5195 if (event->type == ButtonPress) {
5196 /* Finish clickclick move */
5197 if (appData.animate || appData.highlightLastMove) {
5198 SetHighlights(fromX, fromY, toX, toY);
5203 /* Finish drag move */
5204 if (appData.highlightLastMove) {
5205 SetHighlights(fromX, fromY, toX, toY);
5209 DragPieceEnd(event->xbutton.x, event->xbutton.y);
5210 /* Don't animate move and drag both */
5211 appData.animate = FALSE;
5213 if (IsPromotion(fromX, fromY, toX, toY)) {
5214 if (appData.alwaysPromoteToQueen) {
5215 UserMoveEvent(fromX, fromY, toX, toY, 'q');
5216 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
5217 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
5220 SetHighlights(fromX, fromY, toX, toY);
5224 UserMoveEvent(fromX, fromY, toX, toY, NULLCHAR);
5225 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
5226 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
5229 appData.animate = saveAnimate;
5230 if (appData.animate || appData.animateDragging) {
5231 /* Undo animation damage if needed */
5232 DrawPosition(FALSE, NULL);
5236 void AnimateUserMove (Widget w, XEvent * event,
5237 String * params, Cardinal * nParams)
5239 DragPieceMove(event->xmotion.x, event->xmotion.y);
5242 Widget CommentCreate(name, text, mutable, callback, lines)
5244 int /*Boolean*/ mutable;
5245 XtCallbackProc callback;
5249 Widget shell, layout, form, edit, b_ok, b_cancel, b_clear, b_close, b_edit;
5254 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5255 XtGetValues(boardWidget, args, j);
5258 XtSetArg(args[j], XtNresizable, True); j++;
5261 XtCreatePopupShell(name, topLevelShellWidgetClass,
5262 shellWidget, args, j);
5265 XtCreatePopupShell(name, transientShellWidgetClass,
5266 shellWidget, args, j);
5269 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
5270 layoutArgs, XtNumber(layoutArgs));
5272 XtCreateManagedWidget("form", formWidgetClass, layout,
5273 formArgs, XtNumber(formArgs));
5277 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
5278 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
5280 XtSetArg(args[j], XtNstring, text); j++;
5281 XtSetArg(args[j], XtNtop, XtChainTop); j++;
5282 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5283 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5284 XtSetArg(args[j], XtNright, XtChainRight); j++;
5285 XtSetArg(args[j], XtNresizable, True); j++;
5286 XtSetArg(args[j], XtNwidth, bw_width); j++; /*force wider than buttons*/
5288 XtSetArg(args[j], XtNscrollVertical, XawtextScrollWhenNeeded); j++;
5290 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
5291 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
5293 XtSetArg(args[j], XtNautoFill, True); j++;
5294 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
5296 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
5300 XtSetArg(args[j], XtNfromVert, edit); j++;
5301 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5302 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5303 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5304 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5306 XtCreateManagedWidget(_("ok"), commandWidgetClass, form, args, j);
5307 XtAddCallback(b_ok, XtNcallback, callback, (XtPointer) 0);
5310 XtSetArg(args[j], XtNfromVert, edit); j++;
5311 XtSetArg(args[j], XtNfromHoriz, b_ok); j++;
5312 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5313 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5314 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5315 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5317 XtCreateManagedWidget(_("cancel"), commandWidgetClass, form, args, j);
5318 XtAddCallback(b_cancel, XtNcallback, callback, (XtPointer) 0);
5321 XtSetArg(args[j], XtNfromVert, edit); j++;
5322 XtSetArg(args[j], XtNfromHoriz, b_cancel); j++;
5323 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5324 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5325 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5326 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5328 XtCreateManagedWidget(_("clear"), commandWidgetClass, form, args, j);
5329 XtAddCallback(b_clear, XtNcallback, callback, (XtPointer) 0);
5332 XtSetArg(args[j], XtNfromVert, edit); j++;
5333 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5334 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5335 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5336 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5338 XtCreateManagedWidget(_("close"), commandWidgetClass, form, args, j);
5339 XtAddCallback(b_close, XtNcallback, callback, (XtPointer) 0);
5342 XtSetArg(args[j], XtNfromVert, edit); j++;
5343 XtSetArg(args[j], XtNfromHoriz, b_close); j++;
5344 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5345 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5346 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5347 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5349 XtCreateManagedWidget(_("edit"), commandWidgetClass, form, args, j);
5350 XtAddCallback(b_edit, XtNcallback, callback, (XtPointer) 0);
5353 XtRealizeWidget(shell);
5355 if (commentX == -1) {
5358 Dimension pw_height;
5359 Dimension ew_height;
5362 XtSetArg(args[j], XtNheight, &ew_height); j++;
5363 XtGetValues(edit, args, j);
5366 XtSetArg(args[j], XtNheight, &pw_height); j++;
5367 XtGetValues(shell, args, j);
5368 commentH = pw_height + (lines - 1) * ew_height;
5369 commentW = bw_width - 16;
5371 XSync(xDisplay, False);
5373 /* This code seems to tickle an X bug if it is executed too soon
5374 after xboard starts up. The coordinates get transformed as if
5375 the main window was positioned at (0, 0).
5377 XtTranslateCoords(shellWidget,
5378 (bw_width - commentW) / 2, 0 - commentH / 2,
5379 &commentX, &commentY);
5381 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
5382 RootWindowOfScreen(XtScreen(shellWidget)),
5383 (bw_width - commentW) / 2, 0 - commentH / 2,
5388 if (commentY < 0) commentY = 0; /*avoid positioning top offscreen*/
5391 XtSetArg(args[j], XtNheight, commentH); j++;
5392 XtSetArg(args[j], XtNwidth, commentW); j++;
5393 XtSetArg(args[j], XtNx, commentX); j++;
5394 XtSetArg(args[j], XtNy, commentY); j++;
5395 XtSetValues(shell, args, j);
5396 XtSetKeyboardFocus(shell, edit);
5401 /* Used for analysis window and ICS input window */
5402 Widget MiscCreate(name, text, mutable, callback, lines)
5404 int /*Boolean*/ mutable;
5405 XtCallbackProc callback;
5409 Widget shell, layout, form, edit;
5411 Dimension bw_width, pw_height, ew_height, w, h;
5417 XtSetArg(args[j], XtNresizable, True); j++;
5420 XtCreatePopupShell(name, topLevelShellWidgetClass,
5421 shellWidget, args, j);
5424 XtCreatePopupShell(name, transientShellWidgetClass,
5425 shellWidget, args, j);
5428 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
5429 layoutArgs, XtNumber(layoutArgs));
5431 XtCreateManagedWidget("form", formWidgetClass, layout,
5432 formArgs, XtNumber(formArgs));
5436 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
5437 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
5439 XtSetArg(args[j], XtNstring, text); j++;
5440 XtSetArg(args[j], XtNtop, XtChainTop); j++;
5441 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5442 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5443 XtSetArg(args[j], XtNright, XtChainRight); j++;
5444 XtSetArg(args[j], XtNresizable, True); j++;
5446 XtSetArg(args[j], XtNscrollVertical, XawtextScrollWhenNeeded); j++;
5448 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
5449 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
5451 XtSetArg(args[j], XtNautoFill, True); j++;
5452 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
5454 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
5456 XtRealizeWidget(shell);
5459 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5460 XtGetValues(boardWidget, args, j);
5463 XtSetArg(args[j], XtNheight, &ew_height); j++;
5464 XtGetValues(edit, args, j);
5467 XtSetArg(args[j], XtNheight, &pw_height); j++;
5468 XtGetValues(shell, args, j);
5469 h = pw_height + (lines - 1) * ew_height;
5472 XSync(xDisplay, False);
5474 /* This code seems to tickle an X bug if it is executed too soon
5475 after xboard starts up. The coordinates get transformed as if
5476 the main window was positioned at (0, 0).
5478 XtTranslateCoords(shellWidget, (bw_width - w) / 2, 0 - h / 2, &x, &y);
5480 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
5481 RootWindowOfScreen(XtScreen(shellWidget)),
5482 (bw_width - w) / 2, 0 - h / 2, &xx, &yy, &junk);
5486 if (y < 0) y = 0; /*avoid positioning top offscreen*/
5489 XtSetArg(args[j], XtNheight, h); j++;
5490 XtSetArg(args[j], XtNwidth, w); j++;
5491 XtSetArg(args[j], XtNx, x); j++;
5492 XtSetArg(args[j], XtNy, y); j++;
5493 XtSetValues(shell, args, j);
5499 static int savedIndex; /* gross that this is global */
5501 void EditCommentPopUp(index, title, text)
5510 if (text == NULL) text = "";
5512 if (editShell == NULL) {
5514 CommentCreate(title, text, True, EditCommentCallback, 4);
5515 XtRealizeWidget(editShell);
5516 CatchDeleteWindow(editShell, "EditCommentPopDown");
5518 edit = XtNameToWidget(editShell, "*form.text");
5520 XtSetArg(args[j], XtNstring, text); j++;
5521 XtSetValues(edit, args, j);
5523 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5524 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5525 XtSetValues(editShell, args, j);
5528 XtPopup(editShell, XtGrabNone);
5532 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
5533 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
5537 void EditCommentCallback(w, client_data, call_data)
5539 XtPointer client_data, call_data;
5547 XtSetArg(args[j], XtNlabel, &name); j++;
5548 XtGetValues(w, args, j);
5550 if (strcmp(name, _("ok")) == 0) {
5551 edit = XtNameToWidget(editShell, "*form.text");
5553 XtSetArg(args[j], XtNstring, &val); j++;
5554 XtGetValues(edit, args, j);
5555 ReplaceComment(savedIndex, val);
5556 EditCommentPopDown();
5557 } else if (strcmp(name, _("cancel")) == 0) {
5558 EditCommentPopDown();
5559 } else if (strcmp(name, _("clear")) == 0) {
5560 edit = XtNameToWidget(editShell, "*form.text");
5561 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
5562 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
5566 void EditCommentPopDown()
5571 if (!editUp) return;
5573 XtSetArg(args[j], XtNx, &commentX); j++;
5574 XtSetArg(args[j], XtNy, &commentY); j++;
5575 XtSetArg(args[j], XtNheight, &commentH); j++;
5576 XtSetArg(args[j], XtNwidth, &commentW); j++;
5577 XtGetValues(editShell, args, j);
5578 XtPopdown(editShell);
5581 XtSetArg(args[j], XtNleftBitmap, None); j++;
5582 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
5586 void ICSInputBoxPopUp()
5591 char *title = _("ICS Input");
5594 if (ICSInputShell == NULL) {
5595 ICSInputShell = MiscCreate(title, "", True, NULL, 1);
5596 tr = XtParseTranslationTable(ICSInputTranslations);
5597 edit = XtNameToWidget(ICSInputShell, "*form.text");
5598 XtOverrideTranslations(edit, tr);
5599 XtRealizeWidget(ICSInputShell);
5600 CatchDeleteWindow(ICSInputShell, "ICSInputBoxPopDown");
5603 edit = XtNameToWidget(ICSInputShell, "*form.text");
5605 XtSetArg(args[j], XtNstring, ""); j++;
5606 XtSetValues(edit, args, j);
5608 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5609 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5610 XtSetValues(ICSInputShell, args, j);
5613 XtPopup(ICSInputShell, XtGrabNone);
5614 XtSetKeyboardFocus(ICSInputShell, edit);
5616 ICSInputBoxUp = True;
5618 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
5619 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
5623 void ICSInputSendText()
5630 edit = XtNameToWidget(ICSInputShell, "*form.text");
5632 XtSetArg(args[j], XtNstring, &val); j++;
5633 XtGetValues(edit, args, j);
5634 SendMultiLineToICS(val);
5635 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
5636 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
5639 void ICSInputBoxPopDown()
5644 if (!ICSInputBoxUp) return;
5646 XtPopdown(ICSInputShell);
5647 ICSInputBoxUp = False;
5649 XtSetArg(args[j], XtNleftBitmap, None); j++;
5650 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
5654 void CommentPopUp(title, text)
5661 if (commentShell == NULL) {
5663 CommentCreate(title, text, False, CommentCallback, 4);
5664 XtRealizeWidget(commentShell);
5665 CatchDeleteWindow(commentShell, "CommentPopDown");
5667 edit = XtNameToWidget(commentShell, "*form.text");
5669 XtSetArg(args[j], XtNstring, text); j++;
5670 XtSetValues(edit, args, j);
5672 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5673 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5674 XtSetValues(commentShell, args, j);
5677 XtPopup(commentShell, XtGrabNone);
5678 XSync(xDisplay, False);
5683 void AnalysisPopUp(title, text)
5690 if (analysisShell == NULL) {
5691 analysisShell = MiscCreate(title, text, False, NULL, 4);
5692 XtRealizeWidget(analysisShell);
5693 CatchDeleteWindow(analysisShell, "AnalysisPopDown");
5696 edit = XtNameToWidget(analysisShell, "*form.text");
5698 XtSetArg(args[j], XtNstring, text); j++;
5699 XtSetValues(edit, args, j);
5701 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5702 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5703 XtSetValues(analysisShell, args, j);
5707 XtPopup(analysisShell, XtGrabNone);
5709 XSync(xDisplay, False);
5714 void CommentCallback(w, client_data, call_data)
5716 XtPointer client_data, call_data;
5723 XtSetArg(args[j], XtNlabel, &name); j++;
5724 XtGetValues(w, args, j);
5726 if (strcmp(name, _("close")) == 0) {
5728 } else if (strcmp(name, _("edit")) == 0) {
5735 void CommentPopDown()
5740 if (!commentUp) return;
5742 XtSetArg(args[j], XtNx, &commentX); j++;
5743 XtSetArg(args[j], XtNy, &commentY); j++;
5744 XtSetArg(args[j], XtNwidth, &commentW); j++;
5745 XtSetArg(args[j], XtNheight, &commentH); j++;
5746 XtGetValues(commentShell, args, j);
5747 XtPopdown(commentShell);
5748 XSync(xDisplay, False);
5752 void AnalysisPopDown()
5754 if (!analysisUp) return;
5755 XtPopdown(analysisShell);
5756 XSync(xDisplay, False);
5758 if (appData.icsEngineAnalyze) ExitAnalyzeMode(); /* [DM] icsEngineAnalyze */
5762 void FileNamePopUp(label, def, proc, openMode)
5769 Widget popup, layout, dialog, edit;
5775 fileProc = proc; /* I can't see a way not */
5776 fileOpenMode = openMode; /* to use globals here */
5779 XtSetArg(args[i], XtNresizable, True); i++;
5780 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
5781 XtSetArg(args[i], XtNtitle, XtNewString(_("File name prompt"))); i++;
5782 fileNameShell = popup =
5783 XtCreatePopupShell("File name prompt", transientShellWidgetClass,
5784 shellWidget, args, i);
5787 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
5788 layoutArgs, XtNumber(layoutArgs));
5791 XtSetArg(args[i], XtNlabel, label); i++;
5792 XtSetArg(args[i], XtNvalue, def); i++;
5793 XtSetArg(args[i], XtNborderWidth, 0); i++;
5794 dialog = XtCreateManagedWidget("fileName", dialogWidgetClass,
5797 XawDialogAddButton(dialog, _("ok"), FileNameCallback, (XtPointer) dialog);
5798 XawDialogAddButton(dialog, _("cancel"), FileNameCallback,
5799 (XtPointer) dialog);
5801 XtRealizeWidget(popup);
5802 CatchDeleteWindow(popup, "FileNamePopDown");
5804 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
5805 &x, &y, &win_x, &win_y, &mask);
5807 XtSetArg(args[0], XtNx, x - 10);
5808 XtSetArg(args[1], XtNy, y - 30);
5809 XtSetValues(popup, args, 2);
5811 XtPopup(popup, XtGrabExclusive);
5814 edit = XtNameToWidget(dialog, "*value");
5815 XtSetKeyboardFocus(popup, edit);
5818 void FileNamePopDown()
5820 if (!filenameUp) return;
5821 XtPopdown(fileNameShell);
5822 XtDestroyWidget(fileNameShell);
5827 void FileNameCallback(w, client_data, call_data)
5829 XtPointer client_data, call_data;
5834 XtSetArg(args[0], XtNlabel, &name);
5835 XtGetValues(w, args, 1);
5837 if (strcmp(name, _("cancel")) == 0) {
5842 FileNameAction(w, NULL, NULL, NULL);
5845 void FileNameAction(w, event, prms, nprms)
5857 name = XawDialogGetValueString(w = XtParent(w));
5859 if ((name != NULL) && (*name != NULLCHAR)) {
5861 XtPopdown(w = XtParent(XtParent(w)));
5865 p = strrchr(buf, ' ');
5872 fullname = ExpandPathName(buf);
5874 ErrorPopUp(_("Error"), _("Can't open file"), FALSE);
5877 f = fopen(fullname, fileOpenMode);
5879 DisplayError(_("Failed to open file"), errno);
5881 (void) (*fileProc)(f, index, buf);
5888 XtPopdown(w = XtParent(XtParent(w)));
5894 void PromotionPopUp()
5897 Widget dialog, layout;
5899 Dimension bw_width, pw_width;
5903 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5904 XtGetValues(boardWidget, args, j);
5907 XtSetArg(args[j], XtNresizable, True); j++;
5908 XtSetArg(args[j], XtNtitle, XtNewString(_("Promotion"))); j++;
5910 XtCreatePopupShell("Promotion", transientShellWidgetClass,
5911 shellWidget, args, j);
5913 XtCreateManagedWidget(layoutName, formWidgetClass, promotionShell,
5914 layoutArgs, XtNumber(layoutArgs));
5917 XtSetArg(args[j], XtNlabel, _("Promote to what?")); j++;
5918 XtSetArg(args[j], XtNborderWidth, 0); j++;
5919 dialog = XtCreateManagedWidget("promotion", dialogWidgetClass,
5922 if(gameInfo.variant != VariantShogi) {
5923 XawDialogAddButton(dialog, _("Queen"), PromotionCallback,
5924 (XtPointer) dialog);
5925 XawDialogAddButton(dialog, _("Rook"), PromotionCallback,
5926 (XtPointer) dialog);
5927 XawDialogAddButton(dialog, _("Bishop"), PromotionCallback,
5928 (XtPointer) dialog);
5929 XawDialogAddButton(dialog, _("Knight"), PromotionCallback,
5930 (XtPointer) dialog);
5931 if (!appData.testLegality || gameInfo.variant == VariantSuicide ||
5932 gameInfo.variant == VariantGiveaway) {
5933 XawDialogAddButton(dialog, _("King"), PromotionCallback,
5934 (XtPointer) dialog);
5936 if(gameInfo.variant == VariantCapablanca ||
5937 gameInfo.variant == VariantGothic ||
5938 gameInfo.variant == VariantCapaRandom) {
5939 XawDialogAddButton(dialog, _("Archbishop"), PromotionCallback,
5940 (XtPointer) dialog);
5941 XawDialogAddButton(dialog, _("Chancellor"), PromotionCallback,
5942 (XtPointer) dialog);
5944 } else // [HGM] shogi
5946 XawDialogAddButton(dialog, _("Promote"), PromotionCallback,
5947 (XtPointer) dialog);
5948 XawDialogAddButton(dialog, _("Defer"), PromotionCallback,
5949 (XtPointer) dialog);
5951 XawDialogAddButton(dialog, _("cancel"), PromotionCallback,
5952 (XtPointer) dialog);
5954 XtRealizeWidget(promotionShell);
5955 CatchDeleteWindow(promotionShell, "PromotionPopDown");
5958 XtSetArg(args[j], XtNwidth, &pw_width); j++;
5959 XtGetValues(promotionShell, args, j);
5961 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
5962 lineGap + squareSize/3 +
5963 ((toY == BOARD_HEIGHT-1) ^ (flipView) ?
5964 0 : 6*(squareSize + lineGap)), &x, &y);
5967 XtSetArg(args[j], XtNx, x); j++;
5968 XtSetArg(args[j], XtNy, y); j++;
5969 XtSetValues(promotionShell, args, j);
5971 XtPopup(promotionShell, XtGrabNone);
5976 void PromotionPopDown()
5978 if (!promotionUp) return;
5979 XtPopdown(promotionShell);
5980 XtDestroyWidget(promotionShell);
5981 promotionUp = False;
5984 void PromotionCallback(w, client_data, call_data)
5986 XtPointer client_data, call_data;
5992 XtSetArg(args[0], XtNlabel, &name);
5993 XtGetValues(w, args, 1);
5997 if (fromX == -1) return;
5999 if (strcmp(name, _("cancel")) == 0) {
6003 } else if (strcmp(name, _("Knight")) == 0) {
6005 } else if (strcmp(name, _("Promote")) == 0) {
6007 } else if (strcmp(name, _("Defer")) == 0) {
6010 promoChar = ToLower(name[0]);
6013 UserMoveEvent(fromX, fromY, toX, toY, promoChar);
6015 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
6016 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
6021 void ErrorCallback(w, client_data, call_data)
6023 XtPointer client_data, call_data;
6026 XtPopdown(w = XtParent(XtParent(XtParent(w))));
6028 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
6034 if (!errorUp) return;
6036 XtPopdown(errorShell);
6037 XtDestroyWidget(errorShell);
6038 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
6041 void ErrorPopUp(title, label, modal)
6042 char *title, *label;
6046 Widget dialog, layout;
6050 Dimension bw_width, pw_width;
6051 Dimension pw_height;
6055 XtSetArg(args[i], XtNresizable, True); i++;
6056 XtSetArg(args[i], XtNtitle, title); i++;
6058 XtCreatePopupShell("errorpopup", transientShellWidgetClass,
6059 shellWidget, args, i);
6061 XtCreateManagedWidget(layoutName, formWidgetClass, errorShell,
6062 layoutArgs, XtNumber(layoutArgs));
6065 XtSetArg(args[i], XtNlabel, label); i++;
6066 XtSetArg(args[i], XtNborderWidth, 0); i++;
6067 dialog = XtCreateManagedWidget("dialog", dialogWidgetClass,
6070 XawDialogAddButton(dialog, _("ok"), ErrorCallback, (XtPointer) dialog);
6072 XtRealizeWidget(errorShell);
6073 CatchDeleteWindow(errorShell, "ErrorPopDown");
6076 XtSetArg(args[i], XtNwidth, &bw_width); i++;
6077 XtGetValues(boardWidget, args, i);
6079 XtSetArg(args[i], XtNwidth, &pw_width); i++;
6080 XtSetArg(args[i], XtNheight, &pw_height); i++;
6081 XtGetValues(errorShell, args, i);
6084 /* This code seems to tickle an X bug if it is executed too soon
6085 after xboard starts up. The coordinates get transformed as if
6086 the main window was positioned at (0, 0).
6088 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
6089 0 - pw_height + squareSize / 3, &x, &y);
6091 XTranslateCoordinates(xDisplay, XtWindow(boardWidget),
6092 RootWindowOfScreen(XtScreen(boardWidget)),
6093 (bw_width - pw_width) / 2,
6094 0 - pw_height + squareSize / 3, &xx, &yy, &junk);
6098 if (y < 0) y = 0; /*avoid positioning top offscreen*/
6101 XtSetArg(args[i], XtNx, x); i++;
6102 XtSetArg(args[i], XtNy, y); i++;
6103 XtSetValues(errorShell, args, i);
6106 XtPopup(errorShell, modal ? XtGrabExclusive : XtGrabNone);
6109 /* Disable all user input other than deleting the window */
6110 static int frozen = 0;
6114 /* Grab by a widget that doesn't accept input */
6115 XtAddGrab(messageWidget, TRUE, FALSE);
6119 /* Undo a FreezeUI */
6122 if (!frozen) return;
6123 XtRemoveGrab(messageWidget);
6127 char *ModeToWidgetName(mode)
6131 case BeginningOfGame:
6132 if (appData.icsActive)
6133 return "menuMode.ICS Client";
6134 else if (appData.noChessProgram ||
6135 *appData.cmailGameName != NULLCHAR)
6136 return "menuMode.Edit Game";
6138 return "menuMode.Machine Black";
6139 case MachinePlaysBlack:
6140 return "menuMode.Machine Black";
6141 case MachinePlaysWhite:
6142 return "menuMode.Machine White";
6144 return "menuMode.Analysis Mode";
6146 return "menuMode.Analyze File";
6147 case TwoMachinesPlay:
6148 return "menuMode.Two Machines";
6150 return "menuMode.Edit Game";
6151 case PlayFromGameFile:
6152 return "menuFile.Load Game";
6154 return "menuMode.Edit Position";
6156 return "menuMode.Training";
6157 case IcsPlayingWhite:
6158 case IcsPlayingBlack:
6162 return "menuMode.ICS Client";
6169 void ModeHighlight()
6172 static int oldPausing = FALSE;
6173 static GameMode oldmode = (GameMode) -1;
6176 if (!boardWidget || !XtIsRealized(boardWidget)) return;
6178 if (pausing != oldPausing) {
6179 oldPausing = pausing;
6181 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6183 XtSetArg(args[0], XtNleftBitmap, None);
6185 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Pause"),
6188 if (appData.showButtonBar) {
6191 XtSetArg(args[0], XtNbackground, buttonForegroundPixel);
6192 XtSetArg(args[1], XtNforeground, buttonBackgroundPixel);
6194 XtSetArg(args[0], XtNbackground, buttonBackgroundPixel);
6195 XtSetArg(args[1], XtNforeground, buttonForegroundPixel);
6198 /* Always toggle, don't set. Previous code messes up when
6199 invoked while the button is pressed, as releasing it
6200 toggles the state again. */
6203 XtSetArg(args[0], XtNbackground, &oldbg);
6204 XtSetArg(args[1], XtNforeground, &oldfg);
6205 XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON),
6207 XtSetArg(args[0], XtNbackground, oldfg);
6208 XtSetArg(args[1], XtNforeground, oldbg);
6211 XtSetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
6215 wname = ModeToWidgetName(oldmode);
6216 if (wname != NULL) {
6217 XtSetArg(args[0], XtNleftBitmap, None);
6218 XtSetValues(XtNameToWidget(menuBarWidget, wname), args, 1);
6220 wname = ModeToWidgetName(gameMode);
6221 if (wname != NULL) {
6222 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6223 XtSetValues(XtNameToWidget(menuBarWidget, wname), args, 1);
6227 /* Maybe all the enables should be handled here, not just this one */
6228 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Training"),
6229 gameMode == Training || gameMode == PlayFromGameFile);
6234 * Button/menu procedures
6236 void ResetProc(w, event, prms, nprms)
6246 int LoadGamePopUp(f, gameNumber, title)
6251 cmailMsgLoaded = FALSE;
6252 if (gameNumber == 0) {
6253 int error = GameListBuild(f);
6255 DisplayError(_("Cannot build game list"), error);
6256 } else if (!ListEmpty(&gameList) &&
6257 ((ListGame *) gameList.tailPred)->number > 1) {
6258 GameListPopUp(f, title);
6264 return LoadGame(f, gameNumber, title, FALSE);
6267 void LoadGameProc(w, event, prms, nprms)
6273 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
6276 FileNamePopUp(_("Load game file name?"), "", LoadGamePopUp, "rb");
6279 void LoadNextGameProc(w, event, prms, nprms)
6288 void LoadPrevGameProc(w, event, prms, nprms)
6297 void ReloadGameProc(w, event, prms, nprms)
6306 void LoadNextPositionProc(w, event, prms, nprms)
6315 void LoadPrevPositionProc(w, event, prms, nprms)
6324 void ReloadPositionProc(w, event, prms, nprms)
6333 void LoadPositionProc(w, event, prms, nprms)
6339 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
6342 FileNamePopUp(_("Load position file name?"), "", LoadPosition, "rb");
6345 void SaveGameProc(w, event, prms, nprms)
6351 FileNamePopUp(_("Save game file name?"),
6352 DefaultFileName(appData.oldSaveStyle ? "game" : "pgn"),
6356 void SavePositionProc(w, event, prms, nprms)
6362 FileNamePopUp(_("Save position file name?"),
6363 DefaultFileName(appData.oldSaveStyle ? "pos" : "fen"),
6367 void ReloadCmailMsgProc(w, event, prms, nprms)
6373 ReloadCmailMsgEvent(FALSE);
6376 void MailMoveProc(w, event, prms, nprms)
6385 /* this variable is shared between CopyPositionProc and SendPositionSelection */
6386 static char *selected_fen_position=NULL;
6389 SendPositionSelection(Widget w, Atom *selection, Atom *target,
6390 Atom *type_return, XtPointer *value_return,
6391 unsigned long *length_return, int *format_return)
6393 char *selection_tmp;
6395 if (!selected_fen_position) return False; /* should never happen */
6396 if (*target == XA_STRING){
6397 /* note: since no XtSelectionDoneProc was registered, Xt will
6398 * automatically call XtFree on the value returned. So have to
6399 * make a copy of it allocated with XtMalloc */
6400 selection_tmp= XtMalloc(strlen(selected_fen_position)+16);
6401 strcpy(selection_tmp, selected_fen_position);
6403 *value_return=selection_tmp;
6404 *length_return=strlen(selection_tmp);
6405 *type_return=XA_STRING;
6406 *format_return = 8; /* bits per byte */
6413 /* note: when called from menu all parameters are NULL, so no clue what the
6414 * Widget which was clicked on was, or what the click event was
6416 void CopyPositionProc(w, event, prms, nprms)
6424 if (selected_fen_position) free(selected_fen_position);
6425 selected_fen_position = (char *)PositionToFEN(currentMove, NULL);
6426 if (!selected_fen_position) return;
6427 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
6429 SendPositionSelection,
6430 NULL/* lose_ownership_proc */ ,
6431 NULL/* transfer_done_proc */);
6433 free(selected_fen_position);
6434 selected_fen_position=NULL;
6438 /* function called when the data to Paste is ready */
6440 PastePositionCB(Widget w, XtPointer client_data, Atom *selection,
6441 Atom *type, XtPointer value, unsigned long *len, int *format)
6444 if (value==NULL || *len==0) return; /* nothing had been selected to copy */
6445 fenstr[*len]='\0'; /* normally this string is terminated, but be safe */
6446 EditPositionPasteFEN(fenstr);
6450 /* called when Paste Position button is pressed,
6451 * all parameters will be NULL */
6452 void PastePositionProc(w, event, prms, nprms)
6458 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
6459 /* (XtSelectionCallbackProc) */ PastePositionCB,
6460 NULL, /* client_data passed to PastePositionCB */
6462 /* better to use the time field from the event that triggered the
6463 * call to this function, but that isn't trivial to get
6471 SendGameSelection(Widget w, Atom *selection, Atom *target,
6472 Atom *type_return, XtPointer *value_return,
6473 unsigned long *length_return, int *format_return)
6475 char *selection_tmp;
6477 if (*target == XA_STRING){
6478 FILE* f = fopen(gameCopyFilename, "r");
6481 if (f == NULL) return False;
6485 selection_tmp = XtMalloc(len + 1);
6486 count = fread(selection_tmp, 1, len, f);
6488 XtFree(selection_tmp);
6491 selection_tmp[len] = NULLCHAR;
6492 *value_return = selection_tmp;
6493 *length_return = len;
6494 *type_return = XA_STRING;
6495 *format_return = 8; /* bits per byte */
6502 /* note: when called from menu all parameters are NULL, so no clue what the
6503 * Widget which was clicked on was, or what the click event was
6505 void CopyGameProc(w, event, prms, nprms)
6513 ret = SaveGameToFile(gameCopyFilename, FALSE);
6516 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
6519 NULL/* lose_ownership_proc */ ,
6520 NULL/* transfer_done_proc */);
6523 /* function called when the data to Paste is ready */
6525 PasteGameCB(Widget w, XtPointer client_data, Atom *selection,
6526 Atom *type, XtPointer value, unsigned long *len, int *format)
6529 if (value == NULL || *len == 0) {
6530 return; /* nothing had been selected to copy */
6532 f = fopen(gamePasteFilename, "w");
6534 DisplayError(_("Can't open temp file"), errno);
6537 fwrite(value, 1, *len, f);
6540 LoadGameFromFile(gamePasteFilename, 0, gamePasteFilename, TRUE);
6543 /* called when Paste Game button is pressed,
6544 * all parameters will be NULL */
6545 void PasteGameProc(w, event, prms, nprms)
6551 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
6552 /* (XtSelectionCallbackProc) */ PasteGameCB,
6553 NULL, /* client_data passed to PasteGameCB */
6555 /* better to use the time field from the event that triggered the
6556 * call to this function, but that isn't trivial to get
6566 SaveGameProc(NULL, NULL, NULL, NULL);
6570 void QuitProc(w, event, prms, nprms)
6579 void PauseProc(w, event, prms, nprms)
6589 void MachineBlackProc(w, event, prms, nprms)
6595 MachineBlackEvent();
6598 void MachineWhiteProc(w, event, prms, nprms)
6604 MachineWhiteEvent();
6607 void AnalyzeModeProc(w, event, prms, nprms)
6615 if (!first.analysisSupport) {
6616 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
6617 DisplayError(buf, 0);
6620 /* [DM] icsEngineAnalyze [HGM] This is horrible code; reverse the gameMode and isEngineAnalyze tests! */
6621 if (appData.icsActive) {
6622 if (gameMode != IcsObserving) {
6623 sprintf(buf,_("You are not observing a game"));
6624 DisplayError(buf, 0);
6626 if (appData.icsEngineAnalyze) {
6627 if (appData.debugMode)
6628 fprintf(debugFP, _("Found unexpected active ICS engine analyze \n"));
6634 /* if enable, use want disable icsEngineAnalyze */
6635 if (appData.icsEngineAnalyze) {
6640 appData.icsEngineAnalyze = TRUE;
6641 if (appData.debugMode)
6642 fprintf(debugFP, _("ICS engine analyze starting... \n"));
6644 if (!appData.showThinking)
6645 ShowThinkingProc(w,event,prms,nprms);
6650 void AnalyzeFileProc(w, event, prms, nprms)
6656 if (!first.analysisSupport) {
6658 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
6659 DisplayError(buf, 0);
6664 if (!appData.showThinking)
6665 ShowThinkingProc(w,event,prms,nprms);
6668 FileNamePopUp(_("File to analyze"), "", LoadGamePopUp, "rb");
6669 AnalysisPeriodicEvent(1);
6672 void TwoMachinesProc(w, event, prms, nprms)
6681 void IcsClientProc(w, event, prms, nprms)
6690 void EditGameProc(w, event, prms, nprms)
6699 void EditPositionProc(w, event, prms, nprms)
6705 EditPositionEvent();
6708 void TrainingProc(w, event, prms, nprms)
6717 void EditCommentProc(w, event, prms, nprms)
6724 EditCommentPopDown();
6730 void IcsInputBoxProc(w, event, prms, nprms)
6736 if (ICSInputBoxUp) {
6737 ICSInputBoxPopDown();
6743 void AcceptProc(w, event, prms, nprms)
6752 void DeclineProc(w, event, prms, nprms)
6761 void RematchProc(w, event, prms, nprms)
6770 void CallFlagProc(w, event, prms, nprms)
6779 void DrawProc(w, event, prms, nprms)
6788 void AbortProc(w, event, prms, nprms)
6797 void AdjournProc(w, event, prms, nprms)
6806 void ResignProc(w, event, prms, nprms)
6815 void AdjuWhiteProc(w, event, prms, nprms)
6821 UserAdjudicationEvent(+1);
6824 void AdjuBlackProc(w, event, prms, nprms)
6830 UserAdjudicationEvent(-1);
6833 void AdjuDrawProc(w, event, prms, nprms)
6839 UserAdjudicationEvent(0);
6842 void EnterKeyProc(w, event, prms, nprms)
6848 if (ICSInputBoxUp == True)
6852 void StopObservingProc(w, event, prms, nprms)
6858 StopObservingEvent();
6861 void StopExaminingProc(w, event, prms, nprms)
6867 StopExaminingEvent();
6871 void ForwardProc(w, event, prms, nprms)
6881 void BackwardProc(w, event, prms, nprms)
6890 void ToStartProc(w, event, prms, nprms)
6899 void ToEndProc(w, event, prms, nprms)
6908 void RevertProc(w, event, prms, nprms)
6917 void TruncateGameProc(w, event, prms, nprms)
6923 TruncateGameEvent();
6925 void RetractMoveProc(w, event, prms, nprms)
6934 void MoveNowProc(w, event, prms, nprms)
6944 void AlwaysQueenProc(w, event, prms, nprms)
6952 appData.alwaysPromoteToQueen = !appData.alwaysPromoteToQueen;
6954 if (appData.alwaysPromoteToQueen) {
6955 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6957 XtSetArg(args[0], XtNleftBitmap, None);
6959 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
6963 void AnimateDraggingProc(w, event, prms, nprms)
6971 appData.animateDragging = !appData.animateDragging;
6973 if (appData.animateDragging) {
6974 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6977 XtSetArg(args[0], XtNleftBitmap, None);
6979 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Dragging"),
6983 void AnimateMovingProc(w, event, prms, nprms)
6991 appData.animate = !appData.animate;
6993 if (appData.animate) {
6994 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6997 XtSetArg(args[0], XtNleftBitmap, None);
6999 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
7003 void AutocommProc(w, event, prms, nprms)
7011 appData.autoComment = !appData.autoComment;
7013 if (appData.autoComment) {
7014 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7016 XtSetArg(args[0], XtNleftBitmap, None);
7018 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
7023 void AutoflagProc(w, event, prms, nprms)
7031 appData.autoCallFlag = !appData.autoCallFlag;
7033 if (appData.autoCallFlag) {
7034 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7036 XtSetArg(args[0], XtNleftBitmap, None);
7038 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
7042 void AutoflipProc(w, event, prms, nprms)
7050 appData.autoFlipView = !appData.autoFlipView;
7052 if (appData.autoFlipView) {
7053 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7055 XtSetArg(args[0], XtNleftBitmap, None);
7057 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flip View"),
7061 void AutobsProc(w, event, prms, nprms)
7069 appData.autoObserve = !appData.autoObserve;
7071 if (appData.autoObserve) {
7072 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7074 XtSetArg(args[0], XtNleftBitmap, None);
7076 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
7080 void AutoraiseProc(w, event, prms, nprms)
7088 appData.autoRaiseBoard = !appData.autoRaiseBoard;
7090 if (appData.autoRaiseBoard) {
7091 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7093 XtSetArg(args[0], XtNleftBitmap, None);
7095 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Raise Board"),
7099 void AutosaveProc(w, event, prms, nprms)
7107 appData.autoSaveGames = !appData.autoSaveGames;
7109 if (appData.autoSaveGames) {
7110 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7112 XtSetArg(args[0], XtNleftBitmap, None);
7114 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
7118 void BlindfoldProc(w, event, prms, nprms)
7126 appData.blindfold = !appData.blindfold;
7128 if (appData.blindfold) {
7129 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7131 XtSetArg(args[0], XtNleftBitmap, None);
7133 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Blindfold"),
7136 DrawPosition(True, NULL);
7139 void TestLegalityProc(w, event, prms, nprms)
7147 appData.testLegality = !appData.testLegality;
7149 if (appData.testLegality) {
7150 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7152 XtSetArg(args[0], XtNleftBitmap, None);
7154 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Test Legality"),
7159 void FlashMovesProc(w, event, prms, nprms)
7167 if (appData.flashCount == 0) {
7168 appData.flashCount = 3;
7170 appData.flashCount = -appData.flashCount;
7173 if (appData.flashCount > 0) {
7174 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7176 XtSetArg(args[0], XtNleftBitmap, None);
7178 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flash Moves"),
7182 void FlipViewProc(w, event, prms, nprms)
7188 flipView = !flipView;
7189 DrawPosition(True, NULL);
7192 void GetMoveListProc(w, event, prms, nprms)
7200 appData.getMoveList = !appData.getMoveList;
7202 if (appData.getMoveList) {
7203 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7206 XtSetArg(args[0], XtNleftBitmap, None);
7208 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
7213 void HighlightDraggingProc(w, event, prms, nprms)
7221 appData.highlightDragging = !appData.highlightDragging;
7223 if (appData.highlightDragging) {
7224 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7226 XtSetArg(args[0], XtNleftBitmap, None);
7228 XtSetValues(XtNameToWidget(menuBarWidget,
7229 "menuOptions.Highlight Dragging"), args, 1);
7233 void HighlightLastMoveProc(w, event, prms, nprms)
7241 appData.highlightLastMove = !appData.highlightLastMove;
7243 if (appData.highlightLastMove) {
7244 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7246 XtSetArg(args[0], XtNleftBitmap, None);
7248 XtSetValues(XtNameToWidget(menuBarWidget,
7249 "menuOptions.Highlight Last Move"), args, 1);
7252 void IcsAlarmProc(w, event, prms, nprms)
7260 appData.icsAlarm = !appData.icsAlarm;
7262 if (appData.icsAlarm) {
7263 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7265 XtSetArg(args[0], XtNleftBitmap, None);
7267 XtSetValues(XtNameToWidget(menuBarWidget,
7268 "menuOptions.ICS Alarm"), args, 1);
7271 void MoveSoundProc(w, event, prms, nprms)
7279 appData.ringBellAfterMoves = !appData.ringBellAfterMoves;
7281 if (appData.ringBellAfterMoves) {
7282 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7284 XtSetArg(args[0], XtNleftBitmap, None);
7286 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
7291 void OldSaveStyleProc(w, event, prms, nprms)
7299 appData.oldSaveStyle = !appData.oldSaveStyle;
7301 if (appData.oldSaveStyle) {
7302 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7304 XtSetArg(args[0], XtNleftBitmap, None);
7306 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Old Save Style"),
7310 void PeriodicUpdatesProc(w, event, prms, nprms)
7318 PeriodicUpdatesEvent(!appData.periodicUpdates);
7320 if (appData.periodicUpdates) {
7321 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7323 XtSetArg(args[0], XtNleftBitmap, None);
7325 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Periodic Updates"),
7329 void PonderNextMoveProc(w, event, prms, nprms)
7337 PonderNextMoveEvent(!appData.ponderNextMove);
7339 if (appData.ponderNextMove) {
7340 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7342 XtSetArg(args[0], XtNleftBitmap, None);
7344 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Ponder Next Move"),
7348 void PopupExitMessageProc(w, event, prms, nprms)
7356 appData.popupExitMessage = !appData.popupExitMessage;
7358 if (appData.popupExitMessage) {
7359 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7361 XtSetArg(args[0], XtNleftBitmap, None);
7363 XtSetValues(XtNameToWidget(menuBarWidget,
7364 "menuOptions.Popup Exit Message"), args, 1);
7367 void PopupMoveErrorsProc(w, event, prms, nprms)
7375 appData.popupMoveErrors = !appData.popupMoveErrors;
7377 if (appData.popupMoveErrors) {
7378 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7380 XtSetArg(args[0], XtNleftBitmap, None);
7382 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Popup Move Errors"),
7386 void PremoveProc(w, event, prms, nprms)
7394 appData.premove = !appData.premove;
7396 if (appData.premove) {
7397 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7399 XtSetArg(args[0], XtNleftBitmap, None);
7401 XtSetValues(XtNameToWidget(menuBarWidget,
7402 "menuOptions.Premove"), args, 1);
7405 void QuietPlayProc(w, event, prms, nprms)
7413 appData.quietPlay = !appData.quietPlay;
7415 if (appData.quietPlay) {
7416 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7418 XtSetArg(args[0], XtNleftBitmap, None);
7420 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Quiet Play"),
7424 void ShowCoordsProc(w, event, prms, nprms)
7432 appData.showCoords = !appData.showCoords;
7434 if (appData.showCoords) {
7435 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7437 XtSetArg(args[0], XtNleftBitmap, None);
7439 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
7442 DrawPosition(True, NULL);
7445 void ShowThinkingProc(w, event, prms, nprms)
7453 appData.showThinking = !appData.showThinking; // [HGM] thinking: tken out of ShowThinkingEvent
7454 ShowThinkingEvent();
7456 // [HGM] thinking: currently no suc menu item; replaced by Hide Thinking (From Human)
7457 if (appData.showThinking) {
7458 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7460 XtSetArg(args[0], XtNleftBitmap, None);
7462 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Thinking"),
7467 void HideThinkingProc(w, event, prms, nprms)
7475 appData.hideThinkingFromHuman = !appData.hideThinkingFromHuman; // [HGM] thinking: tken out of ShowThinkingEvent
7476 ShowThinkingEvent();
7478 if (appData.hideThinkingFromHuman) {
7479 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7481 XtSetArg(args[0], XtNleftBitmap, None);
7483 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
7487 void InfoProc(w, event, prms, nprms)
7494 snprintf(buf, sizeof(buf), "xterm -e info --directory %s --directory . -f %s &",
7499 void ManProc(w, event, prms, nprms)
7507 if (nprms && *nprms > 0)
7511 snprintf(buf, sizeof(buf), "xterm -e man %s &", name);
7515 void HintProc(w, event, prms, nprms)
7524 void BookProc(w, event, prms, nprms)
7533 void AboutProc(w, event, prms, nprms)
7541 char *zippy = " (with Zippy code)";
7545 snprintf(buf, sizeof(buf), "%s%s\n\n%s\n%s\n%s\n\n%s%s\n%s",
7546 programVersion, zippy,
7547 "Copyright 1991 Digital Equipment Corporation",
7548 "Enhancements Copyright 1992-2009 Free Software Foundation",
7549 "Enhancements Copyright 2005 Alessandro Scotti",
7550 PACKAGE, " is free software and carries NO WARRANTY;",
7551 "see the file COPYING for more information.");
7552 ErrorPopUp(_("About XBoard"), buf, FALSE);
7555 void DebugProc(w, event, prms, nprms)
7561 appData.debugMode = !appData.debugMode;
7564 void AboutGameProc(w, event, prms, nprms)
7573 void NothingProc(w, event, prms, nprms)
7582 void Iconify(w, event, prms, nprms)
7591 XtSetArg(args[0], XtNiconic, True);
7592 XtSetValues(shellWidget, args, 1);
7595 void DisplayMessage(message, extMessage)
7596 char *message, *extMessage;
7603 snprintf(buf, sizeof(buf), "%s %s", message, extMessage);
7606 message = extMessage;
7609 XtSetArg(arg, XtNlabel, message);
7610 XtSetValues(messageWidget, &arg, 1);
7613 void DisplayTitle(text)
7618 char title[MSG_SIZ];
7621 if (text == NULL) text = "";
7623 if (appData.titleInWindow) {
7625 XtSetArg(args[i], XtNlabel, text); i++;
7626 XtSetValues(titleWidget, args, i);
7629 if (*text != NULLCHAR) {
7631 strcpy(title, text);
7632 } else if (appData.icsActive) {
7633 snprintf(icon, sizeof(icon), "%s", appData.icsHost);
7634 snprintf(title, sizeof(title), "%s: %s", programName, appData.icsHost);
7635 } else if (appData.cmailGameName[0] != NULLCHAR) {
7636 snprintf(icon, sizeof(icon), "%s", "CMail");
7637 snprintf(title,sizeof(title), "%s: %s", programName, "CMail");
7639 // [HGM] license: This stuff should really be done in back-end, but WinBoard already had a pop-up for it
7640 } else if (gameInfo.variant == VariantGothic) {
7641 strcpy(icon, programName);
7642 strcpy(title, GOTHIC);
7645 } else if (gameInfo.variant == VariantFalcon) {
7646 strcpy(icon, programName);
7647 strcpy(title, FALCON);
7649 } else if (appData.noChessProgram) {
7650 strcpy(icon, programName);
7651 strcpy(title, programName);
7653 strcpy(icon, first.tidy);
7654 snprintf(title,sizeof(title), "%s: %s", programName, first.tidy);
7657 XtSetArg(args[i], XtNiconName, (XtArgVal) icon); i++;
7658 XtSetArg(args[i], XtNtitle, (XtArgVal) title); i++;
7659 XtSetValues(shellWidget, args, i);
7663 void DisplayError(message, error)
7670 if (appData.debugMode || appData.matchMode) {
7671 fprintf(stderr, "%s: %s\n", programName, message);
7674 if (appData.debugMode || appData.matchMode) {
7675 fprintf(stderr, "%s: %s: %s\n",
7676 programName, message, strerror(error));
7678 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
7681 ErrorPopUp(_("Error"), message, FALSE);
7685 void DisplayMoveError(message)
7690 DrawPosition(FALSE, NULL);
7691 if (appData.debugMode || appData.matchMode) {
7692 fprintf(stderr, "%s: %s\n", programName, message);
7694 if (appData.popupMoveErrors) {
7695 ErrorPopUp(_("Error"), message, FALSE);
7697 DisplayMessage(message, "");
7702 void DisplayFatalError(message, error, status)
7708 errorExitStatus = status;
7710 fprintf(stderr, "%s: %s\n", programName, message);
7712 fprintf(stderr, "%s: %s: %s\n",
7713 programName, message, strerror(error));
7714 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
7717 if (appData.popupExitMessage && boardWidget && XtIsRealized(boardWidget)) {
7718 ErrorPopUp(status ? _("Fatal Error") : _("Exiting"), message, TRUE);
7724 void DisplayInformation(message)
7728 ErrorPopUp(_("Information"), message, TRUE);
7731 void DisplayNote(message)
7735 ErrorPopUp(_("Note"), message, FALSE);
7739 NullXErrorCheck(dpy, error_event)
7741 XErrorEvent *error_event;
7746 void DisplayIcsInteractionTitle(message)
7749 if (oldICSInteractionTitle == NULL) {
7750 /* Magic to find the old window title, adapted from vim */
7751 char *wina = getenv("WINDOWID");
7753 Window win = (Window) atoi(wina);
7754 Window root, parent, *children;
7755 unsigned int nchildren;
7756 int (*oldHandler)() = XSetErrorHandler(NullXErrorCheck);
7758 if (XFetchName(xDisplay, win, &oldICSInteractionTitle)) break;
7759 if (!XQueryTree(xDisplay, win, &root, &parent,
7760 &children, &nchildren)) break;
7761 if (children) XFree((void *)children);
7762 if (parent == root || parent == 0) break;
7765 XSetErrorHandler(oldHandler);
7767 if (oldICSInteractionTitle == NULL) {
7768 oldICSInteractionTitle = "xterm";
7771 printf("\033]0;%s\007", message);
7775 char pendingReplyPrefix[MSG_SIZ];
7776 ProcRef pendingReplyPR;
7778 void AskQuestionProc(w, event, prms, nprms)
7785 fprintf(stderr, _("AskQuestionProc needed 4 parameters, got %d\n"),
7789 AskQuestionEvent(prms[0], prms[1], prms[2], prms[3]);
7792 void AskQuestionPopDown()
7794 if (!askQuestionUp) return;
7795 XtPopdown(askQuestionShell);
7796 XtDestroyWidget(askQuestionShell);
7797 askQuestionUp = False;
7800 void AskQuestionReplyAction(w, event, prms, nprms)
7810 reply = XawDialogGetValueString(w = XtParent(w));
7811 strcpy(buf, pendingReplyPrefix);
7812 if (*buf) strcat(buf, " ");
7815 OutputToProcess(pendingReplyPR, buf, strlen(buf), &err);
7816 AskQuestionPopDown();
7818 if (err) DisplayFatalError(_("Error writing to chess program"), err, 0);
7821 void AskQuestionCallback(w, client_data, call_data)
7823 XtPointer client_data, call_data;
7828 XtSetArg(args[0], XtNlabel, &name);
7829 XtGetValues(w, args, 1);
7831 if (strcmp(name, _("cancel")) == 0) {
7832 AskQuestionPopDown();
7834 AskQuestionReplyAction(w, NULL, NULL, NULL);
7838 void AskQuestion(title, question, replyPrefix, pr)
7839 char *title, *question, *replyPrefix;
7843 Widget popup, layout, dialog, edit;
7849 strcpy(pendingReplyPrefix, replyPrefix);
7850 pendingReplyPR = pr;
7853 XtSetArg(args[i], XtNresizable, True); i++;
7854 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
7855 askQuestionShell = popup =
7856 XtCreatePopupShell(title, transientShellWidgetClass,
7857 shellWidget, args, i);
7860 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
7861 layoutArgs, XtNumber(layoutArgs));
7864 XtSetArg(args[i], XtNlabel, question); i++;
7865 XtSetArg(args[i], XtNvalue, ""); i++;
7866 XtSetArg(args[i], XtNborderWidth, 0); i++;
7867 dialog = XtCreateManagedWidget("question", dialogWidgetClass,
7870 XawDialogAddButton(dialog, _("enter"), AskQuestionCallback,
7871 (XtPointer) dialog);
7872 XawDialogAddButton(dialog, _("cancel"), AskQuestionCallback,
7873 (XtPointer) dialog);
7875 XtRealizeWidget(popup);
7876 CatchDeleteWindow(popup, "AskQuestionPopDown");
7878 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
7879 &x, &y, &win_x, &win_y, &mask);
7881 XtSetArg(args[0], XtNx, x - 10);
7882 XtSetArg(args[1], XtNy, y - 30);
7883 XtSetValues(popup, args, 2);
7885 XtPopup(popup, XtGrabExclusive);
7886 askQuestionUp = True;
7888 edit = XtNameToWidget(dialog, "*value");
7889 XtSetKeyboardFocus(popup, edit);
7897 if (*name == NULLCHAR) {
7899 } else if (strcmp(name, "$") == 0) {
7900 putc(BELLCHAR, stderr);
7903 snprintf(buf, sizeof(buf), "%s '%s' &", appData.soundProgram, name);
7911 PlaySound(appData.soundMove);
7917 PlaySound(appData.soundIcsWin);
7923 PlaySound(appData.soundIcsLoss);
7929 PlaySound(appData.soundIcsDraw);
7933 PlayIcsUnfinishedSound()
7935 PlaySound(appData.soundIcsUnfinished);
7941 PlaySound(appData.soundIcsAlarm);
7947 system("stty echo");
7953 system("stty -echo");
7957 Colorize(cc, continuation)
7962 int count, outCount, error;
7964 if (textColors[(int)cc].bg > 0) {
7965 if (textColors[(int)cc].fg > 0) {
7966 sprintf(buf, "\033[0;%d;%d;%dm", textColors[(int)cc].attr,
7967 textColors[(int)cc].fg, textColors[(int)cc].bg);
7969 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
7970 textColors[(int)cc].bg);
7973 if (textColors[(int)cc].fg > 0) {
7974 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
7975 textColors[(int)cc].fg);
7977 sprintf(buf, "\033[0;%dm", textColors[(int)cc].attr);
7980 count = strlen(buf);
7981 outCount = OutputToProcess(NoProc, buf, count, &error);
7982 if (outCount < count) {
7983 DisplayFatalError(_("Error writing to display"), error, 1);
7986 if (continuation) return;
7989 PlaySound(appData.soundShout);
7992 PlaySound(appData.soundSShout);
7995 PlaySound(appData.soundChannel1);
7998 PlaySound(appData.soundChannel);
8001 PlaySound(appData.soundKibitz);
8004 PlaySound(appData.soundTell);
8006 case ColorChallenge:
8007 PlaySound(appData.soundChallenge);
8010 PlaySound(appData.soundRequest);
8013 PlaySound(appData.soundSeek);
8024 return getpwuid(getuid())->pw_name;
8027 static char *ExpandPathName(path)
8030 static char static_buf[2000];
8031 char *d, *s, buf[2000];
8037 while (*s && isspace(*s))
8046 if (*(s+1) == '/') {
8047 strcpy(d, getpwuid(getuid())->pw_dir);
8052 *strchr(buf, '/') = 0;
8053 pwd = getpwnam(buf);
8056 fprintf(stderr, _("ERROR: Unknown user %s (in path %s)\n"),
8060 strcpy(d, pwd->pw_dir);
8061 strcat(d, strchr(s+1, '/'));
8072 static char host_name[MSG_SIZ];
8074 #if HAVE_GETHOSTNAME
8075 gethostname(host_name, MSG_SIZ);
8077 #else /* not HAVE_GETHOSTNAME */
8078 # if HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H
8079 sysinfo(SI_HOSTNAME, host_name, MSG_SIZ);
8081 # else /* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
8083 # endif/* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
8084 #endif /* not HAVE_GETHOSTNAME */
8087 XtIntervalId delayedEventTimerXID = 0;
8088 DelayedEventCallback delayedEventCallback = 0;
8093 delayedEventTimerXID = 0;
8094 delayedEventCallback();
8098 ScheduleDelayedEvent(cb, millisec)
8099 DelayedEventCallback cb; long millisec;
8101 delayedEventCallback = cb;
8102 delayedEventTimerXID =
8103 XtAppAddTimeOut(appContext, millisec,
8104 (XtTimerCallbackProc) FireDelayedEvent, (XtPointer) 0);
8107 DelayedEventCallback
8110 if (delayedEventTimerXID) {
8111 return delayedEventCallback;
8118 CancelDelayedEvent()
8120 if (delayedEventTimerXID) {
8121 XtRemoveTimeOut(delayedEventTimerXID);
8122 delayedEventTimerXID = 0;
8126 XtIntervalId loadGameTimerXID = 0;
8128 int LoadGameTimerRunning()
8130 return loadGameTimerXID != 0;
8133 int StopLoadGameTimer()
8135 if (loadGameTimerXID != 0) {
8136 XtRemoveTimeOut(loadGameTimerXID);
8137 loadGameTimerXID = 0;
8145 LoadGameTimerCallback(arg, id)
8149 loadGameTimerXID = 0;
8154 StartLoadGameTimer(millisec)
8158 XtAppAddTimeOut(appContext, millisec,
8159 (XtTimerCallbackProc) LoadGameTimerCallback,
8163 XtIntervalId analysisClockXID = 0;
8166 AnalysisClockCallback(arg, id)
8170 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile
8171 || appData.icsEngineAnalyze) { // [DM]
8172 AnalysisPeriodicEvent(0);
8173 StartAnalysisClock();
8178 StartAnalysisClock()
8181 XtAppAddTimeOut(appContext, 2000,
8182 (XtTimerCallbackProc) AnalysisClockCallback,
8186 XtIntervalId clockTimerXID = 0;
8188 int ClockTimerRunning()
8190 return clockTimerXID != 0;
8193 int StopClockTimer()
8195 if (clockTimerXID != 0) {
8196 XtRemoveTimeOut(clockTimerXID);
8205 ClockTimerCallback(arg, id)
8214 StartClockTimer(millisec)
8218 XtAppAddTimeOut(appContext, millisec,
8219 (XtTimerCallbackProc) ClockTimerCallback,
8224 DisplayTimerLabel(w, color, timer, highlight)
8233 /* check for low time warning */
8234 Pixel foregroundOrWarningColor = timerForegroundPixel;
8237 appData.lowTimeWarning &&
8238 (timer / 1000) < appData.icsAlarmTime)
8239 foregroundOrWarningColor = lowTimeWarningColor;
8241 if (appData.clockMode) {
8242 sprintf(buf, "%s: %s", color, TimeString(timer));
8243 XtSetArg(args[0], XtNlabel, buf);
8245 sprintf(buf, "%s ", color);
8246 XtSetArg(args[0], XtNlabel, buf);
8251 XtSetArg(args[1], XtNbackground, foregroundOrWarningColor);
8252 XtSetArg(args[2], XtNforeground, timerBackgroundPixel);
8254 XtSetArg(args[1], XtNbackground, timerBackgroundPixel);
8255 XtSetArg(args[2], XtNforeground, foregroundOrWarningColor);
8258 XtSetValues(w, args, 3);
8262 DisplayWhiteClock(timeRemaining, highlight)
8268 if(appData.noGUI) return;
8269 DisplayTimerLabel(whiteTimerWidget, _("White"), timeRemaining, highlight);
8270 if (highlight && iconPixmap == bIconPixmap) {
8271 iconPixmap = wIconPixmap;
8272 XtSetArg(args[0], XtNiconPixmap, iconPixmap);
8273 XtSetValues(shellWidget, args, 1);
8278 DisplayBlackClock(timeRemaining, highlight)
8284 if(appData.noGUI) return;
8285 DisplayTimerLabel(blackTimerWidget, _("Black"), timeRemaining, highlight);
8286 if (highlight && iconPixmap == wIconPixmap) {
8287 iconPixmap = bIconPixmap;
8288 XtSetArg(args[0], XtNiconPixmap, iconPixmap);
8289 XtSetValues(shellWidget, args, 1);
8307 int StartChildProcess(cmdLine, dir, pr)
8314 int to_prog[2], from_prog[2];
8318 if (appData.debugMode) {
8319 fprintf(stderr, "StartChildProcess (dir=\"%s\") %s\n",dir, cmdLine);
8322 /* We do NOT feed the cmdLine to the shell; we just
8323 parse it into blank-separated arguments in the
8324 most simple-minded way possible.
8327 strcpy(buf, cmdLine);
8332 if (p == NULL) break;
8337 SetUpChildIO(to_prog, from_prog);
8339 if ((pid = fork()) == 0) {
8341 // [HGM] PSWBTM: made order resistant against case where fd of created pipe was 0 or 1
8342 close(to_prog[1]); // first close the unused pipe ends
8343 close(from_prog[0]);
8344 dup2(to_prog[0], 0); // to_prog was created first, nd is the only one to use 0 or 1
8345 dup2(from_prog[1], 1);
8346 if(to_prog[0] >= 2) close(to_prog[0]); // if 0 or 1, the dup2 already cosed the original
8347 close(from_prog[1]); // and closing again loses one of the pipes!
8348 if(fileno(stderr) >= 2) // better safe than sorry...
8349 dup2(1, fileno(stderr)); /* force stderr to the pipe */
8351 if (dir[0] != NULLCHAR && chdir(dir) != 0) {
8356 nice(appData.niceEngines); // [HGM] nice: adjust priority of engine proc
8358 execvp(argv[0], argv);
8360 /* If we get here, exec failed */
8365 /* Parent process */
8367 close(from_prog[1]);
8369 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8372 cp->fdFrom = from_prog[0];
8373 cp->fdTo = to_prog[1];
8378 // [HGM] kill: implement the 'hard killing' of AS's Winboard_x
8379 static RETSIGTYPE AlarmCallBack(int n)
8385 DestroyChildProcess(pr, signalType)
8389 ChildProc *cp = (ChildProc *) pr;
8391 if (cp->kind != CPReal) return;
8393 if (signalType == 10) { // [HGM] kill: if it does not terminate in 3 sec, kill
8394 signal(SIGALRM, AlarmCallBack);
8396 if(wait((int *) 0) == -1) { // process does not terminate on its own accord
8397 kill(cp->pid, SIGKILL); // kill it forcefully
8398 wait((int *) 0); // and wait again
8402 kill(cp->pid, signalType == 9 ? SIGKILL : SIGTERM); // [HGM] kill: use hard kill if so requested
8404 /* Process is exiting either because of the kill or because of
8405 a quit command sent by the backend; either way, wait for it to die.
8414 InterruptChildProcess(pr)
8417 ChildProc *cp = (ChildProc *) pr;
8419 if (cp->kind != CPReal) return;
8420 (void) kill(cp->pid, SIGINT); /* stop it thinking */
8423 int OpenTelnet(host, port, pr)
8428 char cmdLine[MSG_SIZ];
8430 if (port[0] == NULLCHAR) {
8431 snprintf(cmdLine, sizeof(cmdLine), "%s %s", appData.telnetProgram, host);
8433 snprintf(cmdLine, sizeof(cmdLine), "%s %s %s", appData.telnetProgram, host, port);
8435 return StartChildProcess(cmdLine, "", pr);
8438 int OpenTCP(host, port, pr)
8444 DisplayFatalError(_("Socket support is not configured in"), 0, 2);
8445 #else /* !OMIT_SOCKETS */
8447 struct sockaddr_in sa;
8449 unsigned short uport;
8452 if ((s = socket(AF_INET, SOCK_STREAM, 6)) < 0) {
8456 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
8457 sa.sin_family = AF_INET;
8458 sa.sin_addr.s_addr = INADDR_ANY;
8459 uport = (unsigned short) 0;
8460 sa.sin_port = htons(uport);
8461 if (bind(s, (struct sockaddr *) &sa, sizeof(struct sockaddr_in)) < 0) {
8465 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
8466 if (!(hp = gethostbyname(host))) {
8468 if (sscanf(host, "%d.%d.%d.%d", &b0, &b1, &b2, &b3) == 4) {
8469 hp = (struct hostent *) calloc(1, sizeof(struct hostent));
8470 hp->h_addrtype = AF_INET;
8472 hp->h_addr_list = (char **) calloc(2, sizeof(char *));
8473 hp->h_addr_list[0] = (char *) malloc(4);
8474 hp->h_addr_list[0][0] = b0;
8475 hp->h_addr_list[0][1] = b1;
8476 hp->h_addr_list[0][2] = b2;
8477 hp->h_addr_list[0][3] = b3;
8482 sa.sin_family = hp->h_addrtype;
8483 uport = (unsigned short) atoi(port);
8484 sa.sin_port = htons(uport);
8485 memcpy((char *) &sa.sin_addr, hp->h_addr, hp->h_length);
8487 if (connect(s, (struct sockaddr *) &sa,
8488 sizeof(struct sockaddr_in)) < 0) {
8492 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8499 #endif /* !OMIT_SOCKETS */
8504 int OpenCommPort(name, pr)
8511 fd = open(name, 2, 0);
8512 if (fd < 0) return errno;
8514 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8524 int OpenLoopback(pr)
8530 SetUpChildIO(to, from);
8532 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8535 cp->fdFrom = to[0]; /* note not from[0]; we are doing a loopback */
8542 int OpenRcmd(host, user, cmd, pr)
8543 char *host, *user, *cmd;
8546 DisplayFatalError(_("internal rcmd not implemented for Unix"), 0, 1);
8550 #define INPUT_SOURCE_BUF_SIZE 8192
8559 char buf[INPUT_SOURCE_BUF_SIZE];
8564 DoInputCallback(closure, source, xid)
8569 InputSource *is = (InputSource *) closure;
8574 if (is->lineByLine) {
8575 count = read(is->fd, is->unused,
8576 INPUT_SOURCE_BUF_SIZE - (is->unused - is->buf));
8578 (is->func)(is, is->closure, is->buf, count, count ? errno : 0);
8581 is->unused += count;
8583 while (p < is->unused) {
8584 q = memchr(p, '\n', is->unused - p);
8585 if (q == NULL) break;
8587 (is->func)(is, is->closure, p, q - p, 0);
8591 while (p < is->unused) {
8596 count = read(is->fd, is->buf, INPUT_SOURCE_BUF_SIZE);
8601 (is->func)(is, is->closure, is->buf, count, error);
8605 InputSourceRef AddInputSource(pr, lineByLine, func, closure)
8612 ChildProc *cp = (ChildProc *) pr;
8614 is = (InputSource *) calloc(1, sizeof(InputSource));
8615 is->lineByLine = lineByLine;
8619 is->fd = fileno(stdin);
8621 is->kind = cp->kind;
8622 is->fd = cp->fdFrom;
8625 is->unused = is->buf;
8628 is->xid = XtAppAddInput(appContext, is->fd,
8629 (XtPointer) (XtInputReadMask),
8630 (XtInputCallbackProc) DoInputCallback,
8632 is->closure = closure;
8633 return (InputSourceRef) is;
8637 RemoveInputSource(isr)
8640 InputSource *is = (InputSource *) isr;
8642 if (is->xid == 0) return;
8643 XtRemoveInput(is->xid);
8647 int OutputToProcess(pr, message, count, outError)
8653 ChildProc *cp = (ChildProc *) pr;
8657 outCount = fwrite(message, 1, count, stdout);
8659 outCount = write(cp->fdTo, message, count);
8669 /* Output message to process, with "ms" milliseconds of delay
8670 between each character. This is needed when sending the logon
8671 script to ICC, which for some reason doesn't like the
8672 instantaneous send. */
8673 int OutputToProcessDelayed(pr, message, count, outError, msdelay)
8680 ChildProc *cp = (ChildProc *) pr;
8685 r = write(cp->fdTo, message++, 1);
8698 /**** Animation code by Hugh Fisher, DCS, ANU.
8700 Known problem: if a window overlapping the board is
8701 moved away while a piece is being animated underneath,
8702 the newly exposed area won't be updated properly.
8703 I can live with this.
8705 Known problem: if you look carefully at the animation
8706 of pieces in mono mode, they are being drawn as solid
8707 shapes without interior detail while moving. Fixing
8708 this would be a major complication for minimal return.
8711 /* Masks for XPM pieces. Black and white pieces can have
8712 different shapes, but in the interest of retaining my
8713 sanity pieces must have the same outline on both light
8714 and dark squares, and all pieces must use the same
8715 background square colors/images. */
8717 static int xpmDone = 0;
8720 CreateAnimMasks (pieceDepth)
8727 unsigned long plane;
8730 /* Need a bitmap just to get a GC with right depth */
8731 buf = XCreatePixmap(xDisplay, xBoardWindow,
8733 values.foreground = 1;
8734 values.background = 0;
8735 /* Don't use XtGetGC, not read only */
8736 maskGC = XCreateGC(xDisplay, buf,
8737 GCForeground | GCBackground, &values);
8738 XFreePixmap(xDisplay, buf);
8740 buf = XCreatePixmap(xDisplay, xBoardWindow,
8741 squareSize, squareSize, pieceDepth);
8742 values.foreground = XBlackPixel(xDisplay, xScreen);
8743 values.background = XWhitePixel(xDisplay, xScreen);
8744 bufGC = XCreateGC(xDisplay, buf,
8745 GCForeground | GCBackground, &values);
8747 for (piece = WhitePawn; piece <= BlackKing; piece++) {
8748 /* Begin with empty mask */
8749 if(!xpmDone) // [HGM] pieces: keep using existing
8750 xpmMask[piece] = XCreatePixmap(xDisplay, xBoardWindow,
8751 squareSize, squareSize, 1);
8752 XSetFunction(xDisplay, maskGC, GXclear);
8753 XFillRectangle(xDisplay, xpmMask[piece], maskGC,
8754 0, 0, squareSize, squareSize);
8756 /* Take a copy of the piece */
8761 XSetFunction(xDisplay, bufGC, GXcopy);
8762 XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % (int)BlackPawn],
8764 0, 0, squareSize, squareSize, 0, 0);
8766 /* XOR the background (light) over the piece */
8767 XSetFunction(xDisplay, bufGC, GXxor);
8769 XCopyArea(xDisplay, xpmLightSquare, buf, bufGC,
8770 0, 0, squareSize, squareSize, 0, 0);
8772 XSetForeground(xDisplay, bufGC, lightSquareColor);
8773 XFillRectangle(xDisplay, buf, bufGC, 0, 0, squareSize, squareSize);
8776 /* We now have an inverted piece image with the background
8777 erased. Construct mask by just selecting all the non-zero
8778 pixels - no need to reconstruct the original image. */
8779 XSetFunction(xDisplay, maskGC, GXor);
8781 /* Might be quicker to download an XImage and create bitmap
8782 data from it rather than this N copies per piece, but it
8783 only takes a fraction of a second and there is a much
8784 longer delay for loading the pieces. */
8785 for (n = 0; n < pieceDepth; n ++) {
8786 XCopyPlane(xDisplay, buf, xpmMask[piece], maskGC,
8787 0, 0, squareSize, squareSize,
8793 XFreePixmap(xDisplay, buf);
8794 XFreeGC(xDisplay, bufGC);
8795 XFreeGC(xDisplay, maskGC);
8799 InitAnimState (anim, info)
8801 XWindowAttributes * info;
8806 /* Each buffer is square size, same depth as window */
8807 anim->saveBuf = XCreatePixmap(xDisplay, xBoardWindow,
8808 squareSize, squareSize, info->depth);
8809 anim->newBuf = XCreatePixmap(xDisplay, xBoardWindow,
8810 squareSize, squareSize, info->depth);
8812 /* Create a plain GC for blitting */
8813 mask = GCForeground | GCBackground | GCFunction |
8814 GCPlaneMask | GCGraphicsExposures;
8815 values.foreground = XBlackPixel(xDisplay, xScreen);
8816 values.background = XWhitePixel(xDisplay, xScreen);
8817 values.function = GXcopy;
8818 values.plane_mask = AllPlanes;
8819 values.graphics_exposures = False;
8820 anim->blitGC = XCreateGC(xDisplay, xBoardWindow, mask, &values);
8822 /* Piece will be copied from an existing context at
8823 the start of each new animation/drag. */
8824 anim->pieceGC = XCreateGC(xDisplay, xBoardWindow, 0, &values);
8826 /* Outline will be a read-only copy of an existing */
8827 anim->outlineGC = None;
8833 static VariantClass old = (VariantClass) -1; // [HGM] pieces: redo every time variant changes
8834 XWindowAttributes info;
8836 if (xpmDone && gameInfo.variant == old) return;
8837 if(xpmDone) old = gameInfo.variant; // first time pieces might not be created yet
8838 XGetWindowAttributes(xDisplay, xBoardWindow, &info);
8840 InitAnimState(&game, &info);
8841 InitAnimState(&player, &info);
8843 /* For XPM pieces, we need bitmaps to use as masks. */
8845 CreateAnimMasks(info.depth);
8851 static Boolean frameWaiting;
8853 static RETSIGTYPE FrameAlarm (sig)
8856 frameWaiting = False;
8857 /* In case System-V style signals. Needed?? */
8858 signal(SIGALRM, FrameAlarm);
8865 struct itimerval delay;
8867 XSync(xDisplay, False);
8870 frameWaiting = True;
8871 signal(SIGALRM, FrameAlarm);
8872 delay.it_interval.tv_sec =
8873 delay.it_value.tv_sec = time / 1000;
8874 delay.it_interval.tv_usec =
8875 delay.it_value.tv_usec = (time % 1000) * 1000;
8876 setitimer(ITIMER_REAL, &delay, NULL);
8878 /* Ugh -- busy-wait! --tpm */
8879 while (frameWaiting);
8881 while (frameWaiting) pause();
8883 delay.it_interval.tv_sec = delay.it_value.tv_sec = 0;
8884 delay.it_interval.tv_usec = delay.it_value.tv_usec = 0;
8885 setitimer(ITIMER_REAL, &delay, NULL);
8895 XSync(xDisplay, False);
8897 usleep(time * 1000);
8902 /* Convert board position to corner of screen rect and color */
8905 ScreenSquare(column, row, pt, color)
8906 int column; int row; XPoint * pt; int * color;
8909 pt->x = lineGap + ((BOARD_WIDTH-1)-column) * (squareSize + lineGap);
8910 pt->y = lineGap + row * (squareSize + lineGap);
8912 pt->x = lineGap + column * (squareSize + lineGap);
8913 pt->y = lineGap + ((BOARD_HEIGHT-1)-row) * (squareSize + lineGap);
8915 *color = SquareColor(row, column);
8918 /* Convert window coords to square */
8921 BoardSquare(x, y, column, row)
8922 int x; int y; int * column; int * row;
8924 *column = EventToSquare(x, BOARD_WIDTH);
8925 if (flipView && *column >= 0)
8926 *column = BOARD_WIDTH - 1 - *column;
8927 *row = EventToSquare(y, BOARD_HEIGHT);
8928 if (!flipView && *row >= 0)
8929 *row = BOARD_HEIGHT - 1 - *row;
8934 #undef Max /* just in case */
8936 #define Max(a, b) ((a) > (b) ? (a) : (b))
8937 #define Min(a, b) ((a) < (b) ? (a) : (b))
8940 SetRect(rect, x, y, width, height)
8941 XRectangle * rect; int x; int y; int width; int height;
8945 rect->width = width;
8946 rect->height = height;
8949 /* Test if two frames overlap. If they do, return
8950 intersection rect within old and location of
8951 that rect within new. */
8954 Intersect(old, new, size, area, pt)
8955 XPoint * old; XPoint * new;
8956 int size; XRectangle * area; XPoint * pt;
8958 if (old->x > new->x + size || new->x > old->x + size ||
8959 old->y > new->y + size || new->y > old->y + size) {
8962 SetRect(area, Max(new->x - old->x, 0), Max(new->y - old->y, 0),
8963 size - abs(old->x - new->x), size - abs(old->y - new->y));
8964 pt->x = Max(old->x - new->x, 0);
8965 pt->y = Max(old->y - new->y, 0);
8970 /* For two overlapping frames, return the rect(s)
8971 in the old that do not intersect with the new. */
8974 CalcUpdateRects(old, new, size, update, nUpdates)
8975 XPoint * old; XPoint * new; int size;
8976 XRectangle update[]; int * nUpdates;
8980 /* If old = new (shouldn't happen) then nothing to draw */
8981 if (old->x == new->x && old->y == new->y) {
8985 /* Work out what bits overlap. Since we know the rects
8986 are the same size we don't need a full intersect calc. */
8988 /* Top or bottom edge? */
8989 if (new->y > old->y) {
8990 SetRect(&(update[count]), old->x, old->y, size, new->y - old->y);
8992 } else if (old->y > new->y) {
8993 SetRect(&(update[count]), old->x, old->y + size - (old->y - new->y),
8994 size, old->y - new->y);
8997 /* Left or right edge - don't overlap any update calculated above. */
8998 if (new->x > old->x) {
8999 SetRect(&(update[count]), old->x, Max(new->y, old->y),
9000 new->x - old->x, size - abs(new->y - old->y));
9002 } else if (old->x > new->x) {
9003 SetRect(&(update[count]), new->x + size, Max(new->y, old->y),
9004 old->x - new->x, size - abs(new->y - old->y));
9011 /* Generate a series of frame coords from start->mid->finish.
9012 The movement rate doubles until the half way point is
9013 reached, then halves back down to the final destination,
9014 which gives a nice slow in/out effect. The algorithmn
9015 may seem to generate too many intermediates for short
9016 moves, but remember that the purpose is to attract the
9017 viewers attention to the piece about to be moved and
9018 then to where it ends up. Too few frames would be less
9022 Tween(start, mid, finish, factor, frames, nFrames)
9023 XPoint * start; XPoint * mid;
9024 XPoint * finish; int factor;
9025 XPoint frames[]; int * nFrames;
9027 int fraction, n, count;
9031 /* Slow in, stepping 1/16th, then 1/8th, ... */
9033 for (n = 0; n < factor; n++)
9035 for (n = 0; n < factor; n++) {
9036 frames[count].x = start->x + (mid->x - start->x) / fraction;
9037 frames[count].y = start->y + (mid->y - start->y) / fraction;
9039 fraction = fraction / 2;
9043 frames[count] = *mid;
9046 /* Slow out, stepping 1/2, then 1/4, ... */
9048 for (n = 0; n < factor; n++) {
9049 frames[count].x = finish->x - (finish->x - mid->x) / fraction;
9050 frames[count].y = finish->y - (finish->y - mid->y) / fraction;
9052 fraction = fraction * 2;
9057 /* Draw a piece on the screen without disturbing what's there */
9060 SelectGCMask(piece, clip, outline, mask)
9061 ChessSquare piece; GC * clip; GC * outline; Pixmap * mask;
9065 /* Bitmap for piece being moved. */
9066 if (appData.monoMode) {
9067 *mask = *pieceToSolid(piece);
9068 } else if (useImages) {
9070 *mask = xpmMask[piece];
9072 *mask = ximMaskPm[piece];
9075 *mask = *pieceToSolid(piece);
9078 /* GC for piece being moved. Square color doesn't matter, but
9079 since it gets modified we make a copy of the original. */
9081 if (appData.monoMode)
9086 if (appData.monoMode)
9091 XCopyGC(xDisplay, source, 0xFFFFFFFF, *clip);
9093 /* Outline only used in mono mode and is not modified */
9095 *outline = bwPieceGC;
9097 *outline = wbPieceGC;
9101 OverlayPiece(piece, clip, outline, dest)
9102 ChessSquare piece; GC clip; GC outline; Drawable dest;
9107 /* Draw solid rectangle which will be clipped to shape of piece */
9108 XFillRectangle(xDisplay, dest, clip,
9109 0, 0, squareSize, squareSize);
9110 if (appData.monoMode)
9111 /* Also draw outline in contrasting color for black
9112 on black / white on white cases */
9113 XCopyPlane(xDisplay, *pieceToOutline(piece), dest, outline,
9114 0, 0, squareSize, squareSize, 0, 0, 1);
9116 /* Copy the piece */
9121 XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
9123 0, 0, squareSize, squareSize,
9128 /* Animate the movement of a single piece */
9131 BeginAnimation(anim, piece, startColor, start)
9139 /* The old buffer is initialised with the start square (empty) */
9140 BlankSquare(0, 0, startColor, EmptySquare, anim->saveBuf);
9141 anim->prevFrame = *start;
9143 /* The piece will be drawn using its own bitmap as a matte */
9144 SelectGCMask(piece, &anim->pieceGC, &anim->outlineGC, &mask);
9145 XSetClipMask(xDisplay, anim->pieceGC, mask);
9149 AnimationFrame(anim, frame, piece)
9154 XRectangle updates[4];
9159 /* Save what we are about to draw into the new buffer */
9160 XCopyArea(xDisplay, xBoardWindow, anim->newBuf, anim->blitGC,
9161 frame->x, frame->y, squareSize, squareSize,
9164 /* Erase bits of the previous frame */
9165 if (Intersect(&anim->prevFrame, frame, squareSize, &overlap, &pt)) {
9166 /* Where the new frame overlapped the previous,
9167 the contents in newBuf are wrong. */
9168 XCopyArea(xDisplay, anim->saveBuf, anim->newBuf, anim->blitGC,
9169 overlap.x, overlap.y,
9170 overlap.width, overlap.height,
9172 /* Repaint the areas in the old that don't overlap new */
9173 CalcUpdateRects(&anim->prevFrame, frame, squareSize, updates, &count);
9174 for (i = 0; i < count; i++)
9175 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9176 updates[i].x - anim->prevFrame.x,
9177 updates[i].y - anim->prevFrame.y,
9178 updates[i].width, updates[i].height,
9179 updates[i].x, updates[i].y);
9181 /* Easy when no overlap */
9182 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9183 0, 0, squareSize, squareSize,
9184 anim->prevFrame.x, anim->prevFrame.y);
9187 /* Save this frame for next time round */
9188 XCopyArea(xDisplay, anim->newBuf, anim->saveBuf, anim->blitGC,
9189 0, 0, squareSize, squareSize,
9191 anim->prevFrame = *frame;
9193 /* Draw piece over original screen contents, not current,
9194 and copy entire rect. Wipes out overlapping piece images. */
9195 OverlayPiece(piece, anim->pieceGC, anim->outlineGC, anim->newBuf);
9196 XCopyArea(xDisplay, anim->newBuf, xBoardWindow, anim->blitGC,
9197 0, 0, squareSize, squareSize,
9198 frame->x, frame->y);
9202 EndAnimation (anim, finish)
9206 XRectangle updates[4];
9211 /* The main code will redraw the final square, so we
9212 only need to erase the bits that don't overlap. */
9213 if (Intersect(&anim->prevFrame, finish, squareSize, &overlap, &pt)) {
9214 CalcUpdateRects(&anim->prevFrame, finish, squareSize, updates, &count);
9215 for (i = 0; i < count; i++)
9216 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9217 updates[i].x - anim->prevFrame.x,
9218 updates[i].y - anim->prevFrame.y,
9219 updates[i].width, updates[i].height,
9220 updates[i].x, updates[i].y);
9222 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9223 0, 0, squareSize, squareSize,
9224 anim->prevFrame.x, anim->prevFrame.y);
9229 FrameSequence(anim, piece, startColor, start, finish, frames, nFrames)
9231 ChessSquare piece; int startColor;
9232 XPoint * start; XPoint * finish;
9233 XPoint frames[]; int nFrames;
9237 BeginAnimation(anim, piece, startColor, start);
9238 for (n = 0; n < nFrames; n++) {
9239 AnimationFrame(anim, &(frames[n]), piece);
9240 FrameDelay(appData.animSpeed);
9242 EndAnimation(anim, finish);
9245 /* Main control logic for deciding what to animate and how */
9248 AnimateMove(board, fromX, fromY, toX, toY)
9257 XPoint start, finish, mid;
9258 XPoint frames[kFactor * 2 + 1];
9259 int nFrames, startColor, endColor;
9261 /* Are we animating? */
9262 if (!appData.animate || appData.blindfold)
9265 if(board[toY][toX] == WhiteRook && board[fromY][fromX] == WhiteKing ||
9266 board[toY][toX] == BlackRook && board[fromY][fromX] == BlackKing)
9267 return; // [HGM] FRC: no animtion of FRC castlings, as to-square is not true to-square
9269 if (fromY < 0 || fromX < 0 || toX < 0 || toY < 0) return;
9270 piece = board[fromY][fromX];
9271 if (piece >= EmptySquare) return;
9276 hop = (piece == WhiteKnight || piece == BlackKnight);
9279 if (appData.debugMode) {
9280 fprintf(debugFP, hop ? _("AnimateMove: piece %d hops from %d,%d to %d,%d \n") :
9281 _("AnimateMove: piece %d slides from %d,%d to %d,%d \n"),
9282 piece, fromX, fromY, toX, toY); }
9284 ScreenSquare(fromX, fromY, &start, &startColor);
9285 ScreenSquare(toX, toY, &finish, &endColor);
9288 /* Knight: make diagonal movement then straight */
9289 if (abs(toY - fromY) < abs(toX - fromX)) {
9290 mid.x = start.x + (finish.x - start.x) / 2;
9294 mid.y = start.y + (finish.y - start.y) / 2;
9297 mid.x = start.x + (finish.x - start.x) / 2;
9298 mid.y = start.y + (finish.y - start.y) / 2;
9301 /* Don't use as many frames for very short moves */
9302 if (abs(toY - fromY) + abs(toX - fromX) <= 2)
9303 Tween(&start, &mid, &finish, kFactor - 1, frames, &nFrames);
9305 Tween(&start, &mid, &finish, kFactor, frames, &nFrames);
9306 FrameSequence(&game, piece, startColor, &start, &finish, frames, nFrames);
9308 /* Be sure end square is redrawn */
9309 damage[toY][toX] = True;
9313 DragPieceBegin(x, y)
9316 int boardX, boardY, color;
9319 /* Are we animating? */
9320 if (!appData.animateDragging || appData.blindfold)
9323 /* Figure out which square we start in and the
9324 mouse position relative to top left corner. */
9325 BoardSquare(x, y, &boardX, &boardY);
9326 player.startBoardX = boardX;
9327 player.startBoardY = boardY;
9328 ScreenSquare(boardX, boardY, &corner, &color);
9329 player.startSquare = corner;
9330 player.startColor = color;
9332 /* Start from exactly where the piece is. This can be confusing
9333 if you start dragging far from the center of the square; most
9334 or all of the piece can be over a different square from the one
9335 the mouse pointer is in. */
9336 player.mouseDelta.x = x - corner.x;
9337 player.mouseDelta.y = y - corner.y;
9339 /* As soon as we start dragging, the piece will jump slightly to
9340 be centered over the mouse pointer. */
9341 player.mouseDelta.x = squareSize/2;
9342 player.mouseDelta.y = squareSize/2;
9344 /* Initialise animation */
9345 player.dragPiece = PieceForSquare(boardX, boardY);
9347 if (player.dragPiece >= 0 && player.dragPiece < EmptySquare) {
9348 player.dragActive = True;
9349 BeginAnimation(&player, player.dragPiece, color, &corner);
9350 /* Mark this square as needing to be redrawn. Note that
9351 we don't remove the piece though, since logically (ie
9352 as seen by opponent) the move hasn't been made yet. */
9353 if(boardX == BOARD_RGHT+1 && PieceForSquare(boardX-1, boardY) > 1 ||
9354 boardX == BOARD_LEFT-2 && PieceForSquare(boardX+1, boardY) > 1)
9355 XCopyArea(xDisplay, xBoardWindow, player.saveBuf, player.blitGC,
9356 corner.x, corner.y, squareSize, squareSize,
9357 0, 0); // [HGM] zh: unstack in stead of grab
9358 damage[boardY][boardX] = True;
9360 player.dragActive = False;
9370 /* Are we animating? */
9371 if (!appData.animateDragging || appData.blindfold)
9375 if (! player.dragActive)
9377 /* Move piece, maintaining same relative position
9378 of mouse within square */
9379 corner.x = x - player.mouseDelta.x;
9380 corner.y = y - player.mouseDelta.y;
9381 AnimationFrame(&player, &corner, player.dragPiece);
9383 if (appData.highlightDragging) {
9385 BoardSquare(x, y, &boardX, &boardY);
9386 SetHighlights(fromX, fromY, boardX, boardY);
9395 int boardX, boardY, color;
9398 /* Are we animating? */
9399 if (!appData.animateDragging || appData.blindfold)
9403 if (! player.dragActive)
9405 /* Last frame in sequence is square piece is
9406 placed on, which may not match mouse exactly. */
9407 BoardSquare(x, y, &boardX, &boardY);
9408 ScreenSquare(boardX, boardY, &corner, &color);
9409 EndAnimation(&player, &corner);
9411 /* Be sure end square is redrawn */
9412 damage[boardY][boardX] = True;
9414 /* This prevents weird things happening with fast successive
9415 clicks which on my Sun at least can cause motion events
9416 without corresponding press/release. */
9417 player.dragActive = False;
9420 /* Handle expose event while piece being dragged */
9425 if (!player.dragActive || appData.blindfold)
9428 /* What we're doing: logically, the move hasn't been made yet,
9429 so the piece is still in it's original square. But visually
9430 it's being dragged around the board. So we erase the square
9431 that the piece is on and draw it at the last known drag point. */
9432 BlankSquare(player.startSquare.x, player.startSquare.y,
9433 player.startColor, EmptySquare, xBoardWindow);
9434 AnimationFrame(&player, &player.prevFrame, player.dragPiece);
9435 damage[player.startBoardY][player.startBoardX] = TRUE;
9439 SetProgramStats( FrontEndProgramStats * stats )
9442 // [HGM] done, but perhaps backend should call this directly?
9443 EngineOutputUpdate( stats );