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 &&
5149 /* Check if clicking again on the same color piece */
5150 fromP = boards[currentMove][fromY][fromX];
5151 toP = boards[currentMove][y][x];
5152 frc = gameInfo.variant == VariantFischeRandom || gameInfo.variant == VariantCapaRandom;
5153 if ((WhitePawn <= fromP && fromP <= WhiteKing && // [HGM] this test should go, as UserMoveTest now does it.
5154 WhitePawn <= toP && toP <= WhiteKing &&
5155 !(fromP == WhiteKing && toP == WhiteRook && frc)) ||
5156 (BlackPawn <= fromP && fromP <= BlackKing &&
5157 BlackPawn <= toP && toP <= BlackKing &&
5158 !(fromP == BlackKing && toP == BlackRook && frc))) {
5159 /* Clicked again on same color piece -- changed his mind */
5160 second = (x == fromX && y == fromY);
5161 if (appData.highlightDragging) {
5162 SetHighlights(x, y, -1, -1);
5166 if (OKToStartUserMove(x, y)) {
5169 DragPieceBegin(event->xbutton.x, event->xbutton.y);
5175 if (event->type == ButtonRelease && x == fromX && y == fromY) {
5176 DragPieceEnd(event->xbutton.x, event->xbutton.y);
5177 if (appData.animateDragging) {
5178 /* Undo animation damage if any */
5179 DrawPosition(FALSE, NULL);
5182 /* Second up/down in same square; just abort move */
5187 ClearPremoveHighlights();
5189 /* First upclick in same square; start click-click mode */
5190 SetHighlights(x, y, -1, -1);
5195 /* Completed move */
5198 saveAnimate = appData.animate;
5199 if (event->type == ButtonPress) {
5200 /* Finish clickclick move */
5201 if (appData.animate || appData.highlightLastMove) {
5202 SetHighlights(fromX, fromY, toX, toY);
5207 /* Finish drag move */
5208 if (appData.highlightLastMove) {
5209 SetHighlights(fromX, fromY, toX, toY);
5213 DragPieceEnd(event->xbutton.x, event->xbutton.y);
5214 /* Don't animate move and drag both */
5215 appData.animate = FALSE;
5217 if (IsPromotion(fromX, fromY, toX, toY)) {
5218 if (appData.alwaysPromoteToQueen) {
5219 UserMoveEvent(fromX, fromY, toX, toY, 'q');
5220 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
5221 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
5224 SetHighlights(fromX, fromY, toX, toY);
5228 UserMoveEvent(fromX, fromY, toX, toY, NULLCHAR);
5229 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
5230 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
5233 appData.animate = saveAnimate;
5234 if (appData.animate || appData.animateDragging) {
5235 /* Undo animation damage if needed */
5236 DrawPosition(FALSE, NULL);
5240 void AnimateUserMove (Widget w, XEvent * event,
5241 String * params, Cardinal * nParams)
5243 DragPieceMove(event->xmotion.x, event->xmotion.y);
5246 Widget CommentCreate(name, text, mutable, callback, lines)
5248 int /*Boolean*/ mutable;
5249 XtCallbackProc callback;
5253 Widget shell, layout, form, edit, b_ok, b_cancel, b_clear, b_close, b_edit;
5258 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5259 XtGetValues(boardWidget, args, j);
5262 XtSetArg(args[j], XtNresizable, True); j++;
5265 XtCreatePopupShell(name, topLevelShellWidgetClass,
5266 shellWidget, args, j);
5269 XtCreatePopupShell(name, transientShellWidgetClass,
5270 shellWidget, args, j);
5273 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
5274 layoutArgs, XtNumber(layoutArgs));
5276 XtCreateManagedWidget("form", formWidgetClass, layout,
5277 formArgs, XtNumber(formArgs));
5281 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
5282 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
5284 XtSetArg(args[j], XtNstring, text); j++;
5285 XtSetArg(args[j], XtNtop, XtChainTop); j++;
5286 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5287 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5288 XtSetArg(args[j], XtNright, XtChainRight); j++;
5289 XtSetArg(args[j], XtNresizable, True); j++;
5290 XtSetArg(args[j], XtNwidth, bw_width); j++; /*force wider than buttons*/
5292 XtSetArg(args[j], XtNscrollVertical, XawtextScrollWhenNeeded); j++;
5294 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
5295 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
5297 XtSetArg(args[j], XtNautoFill, True); j++;
5298 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
5300 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
5304 XtSetArg(args[j], XtNfromVert, edit); j++;
5305 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5306 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5307 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5308 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5310 XtCreateManagedWidget(_("ok"), commandWidgetClass, form, args, j);
5311 XtAddCallback(b_ok, XtNcallback, callback, (XtPointer) 0);
5314 XtSetArg(args[j], XtNfromVert, edit); j++;
5315 XtSetArg(args[j], XtNfromHoriz, b_ok); j++;
5316 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5317 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5318 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5319 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5321 XtCreateManagedWidget(_("cancel"), commandWidgetClass, form, args, j);
5322 XtAddCallback(b_cancel, XtNcallback, callback, (XtPointer) 0);
5325 XtSetArg(args[j], XtNfromVert, edit); j++;
5326 XtSetArg(args[j], XtNfromHoriz, b_cancel); j++;
5327 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5328 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5329 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5330 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5332 XtCreateManagedWidget(_("clear"), commandWidgetClass, form, args, j);
5333 XtAddCallback(b_clear, XtNcallback, callback, (XtPointer) 0);
5336 XtSetArg(args[j], XtNfromVert, edit); j++;
5337 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5338 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5339 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5340 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5342 XtCreateManagedWidget(_("close"), commandWidgetClass, form, args, j);
5343 XtAddCallback(b_close, XtNcallback, callback, (XtPointer) 0);
5346 XtSetArg(args[j], XtNfromVert, edit); j++;
5347 XtSetArg(args[j], XtNfromHoriz, b_close); j++;
5348 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5349 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5350 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5351 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5353 XtCreateManagedWidget(_("edit"), commandWidgetClass, form, args, j);
5354 XtAddCallback(b_edit, XtNcallback, callback, (XtPointer) 0);
5357 XtRealizeWidget(shell);
5359 if (commentX == -1) {
5362 Dimension pw_height;
5363 Dimension ew_height;
5366 XtSetArg(args[j], XtNheight, &ew_height); j++;
5367 XtGetValues(edit, args, j);
5370 XtSetArg(args[j], XtNheight, &pw_height); j++;
5371 XtGetValues(shell, args, j);
5372 commentH = pw_height + (lines - 1) * ew_height;
5373 commentW = bw_width - 16;
5375 XSync(xDisplay, False);
5377 /* This code seems to tickle an X bug if it is executed too soon
5378 after xboard starts up. The coordinates get transformed as if
5379 the main window was positioned at (0, 0).
5381 XtTranslateCoords(shellWidget,
5382 (bw_width - commentW) / 2, 0 - commentH / 2,
5383 &commentX, &commentY);
5385 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
5386 RootWindowOfScreen(XtScreen(shellWidget)),
5387 (bw_width - commentW) / 2, 0 - commentH / 2,
5392 if (commentY < 0) commentY = 0; /*avoid positioning top offscreen*/
5395 XtSetArg(args[j], XtNheight, commentH); j++;
5396 XtSetArg(args[j], XtNwidth, commentW); j++;
5397 XtSetArg(args[j], XtNx, commentX); j++;
5398 XtSetArg(args[j], XtNy, commentY); j++;
5399 XtSetValues(shell, args, j);
5400 XtSetKeyboardFocus(shell, edit);
5405 /* Used for analysis window and ICS input window */
5406 Widget MiscCreate(name, text, mutable, callback, lines)
5408 int /*Boolean*/ mutable;
5409 XtCallbackProc callback;
5413 Widget shell, layout, form, edit;
5415 Dimension bw_width, pw_height, ew_height, w, h;
5421 XtSetArg(args[j], XtNresizable, True); j++;
5424 XtCreatePopupShell(name, topLevelShellWidgetClass,
5425 shellWidget, args, j);
5428 XtCreatePopupShell(name, transientShellWidgetClass,
5429 shellWidget, args, j);
5432 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
5433 layoutArgs, XtNumber(layoutArgs));
5435 XtCreateManagedWidget("form", formWidgetClass, layout,
5436 formArgs, XtNumber(formArgs));
5440 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
5441 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
5443 XtSetArg(args[j], XtNstring, text); j++;
5444 XtSetArg(args[j], XtNtop, XtChainTop); j++;
5445 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5446 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5447 XtSetArg(args[j], XtNright, XtChainRight); j++;
5448 XtSetArg(args[j], XtNresizable, True); j++;
5450 XtSetArg(args[j], XtNscrollVertical, XawtextScrollWhenNeeded); j++;
5452 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
5453 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
5455 XtSetArg(args[j], XtNautoFill, True); j++;
5456 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
5458 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
5460 XtRealizeWidget(shell);
5463 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5464 XtGetValues(boardWidget, args, j);
5467 XtSetArg(args[j], XtNheight, &ew_height); j++;
5468 XtGetValues(edit, args, j);
5471 XtSetArg(args[j], XtNheight, &pw_height); j++;
5472 XtGetValues(shell, args, j);
5473 h = pw_height + (lines - 1) * ew_height;
5476 XSync(xDisplay, False);
5478 /* This code seems to tickle an X bug if it is executed too soon
5479 after xboard starts up. The coordinates get transformed as if
5480 the main window was positioned at (0, 0).
5482 XtTranslateCoords(shellWidget, (bw_width - w) / 2, 0 - h / 2, &x, &y);
5484 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
5485 RootWindowOfScreen(XtScreen(shellWidget)),
5486 (bw_width - w) / 2, 0 - h / 2, &xx, &yy, &junk);
5490 if (y < 0) y = 0; /*avoid positioning top offscreen*/
5493 XtSetArg(args[j], XtNheight, h); j++;
5494 XtSetArg(args[j], XtNwidth, w); j++;
5495 XtSetArg(args[j], XtNx, x); j++;
5496 XtSetArg(args[j], XtNy, y); j++;
5497 XtSetValues(shell, args, j);
5503 static int savedIndex; /* gross that this is global */
5505 void EditCommentPopUp(index, title, text)
5514 if (text == NULL) text = "";
5516 if (editShell == NULL) {
5518 CommentCreate(title, text, True, EditCommentCallback, 4);
5519 XtRealizeWidget(editShell);
5520 CatchDeleteWindow(editShell, "EditCommentPopDown");
5522 edit = XtNameToWidget(editShell, "*form.text");
5524 XtSetArg(args[j], XtNstring, text); j++;
5525 XtSetValues(edit, args, j);
5527 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5528 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5529 XtSetValues(editShell, args, j);
5532 XtPopup(editShell, XtGrabNone);
5536 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
5537 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
5541 void EditCommentCallback(w, client_data, call_data)
5543 XtPointer client_data, call_data;
5551 XtSetArg(args[j], XtNlabel, &name); j++;
5552 XtGetValues(w, args, j);
5554 if (strcmp(name, _("ok")) == 0) {
5555 edit = XtNameToWidget(editShell, "*form.text");
5557 XtSetArg(args[j], XtNstring, &val); j++;
5558 XtGetValues(edit, args, j);
5559 ReplaceComment(savedIndex, val);
5560 EditCommentPopDown();
5561 } else if (strcmp(name, _("cancel")) == 0) {
5562 EditCommentPopDown();
5563 } else if (strcmp(name, _("clear")) == 0) {
5564 edit = XtNameToWidget(editShell, "*form.text");
5565 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
5566 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
5570 void EditCommentPopDown()
5575 if (!editUp) return;
5577 XtSetArg(args[j], XtNx, &commentX); j++;
5578 XtSetArg(args[j], XtNy, &commentY); j++;
5579 XtSetArg(args[j], XtNheight, &commentH); j++;
5580 XtSetArg(args[j], XtNwidth, &commentW); j++;
5581 XtGetValues(editShell, args, j);
5582 XtPopdown(editShell);
5585 XtSetArg(args[j], XtNleftBitmap, None); j++;
5586 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
5590 void ICSInputBoxPopUp()
5595 char *title = _("ICS Input");
5598 if (ICSInputShell == NULL) {
5599 ICSInputShell = MiscCreate(title, "", True, NULL, 1);
5600 tr = XtParseTranslationTable(ICSInputTranslations);
5601 edit = XtNameToWidget(ICSInputShell, "*form.text");
5602 XtOverrideTranslations(edit, tr);
5603 XtRealizeWidget(ICSInputShell);
5604 CatchDeleteWindow(ICSInputShell, "ICSInputBoxPopDown");
5607 edit = XtNameToWidget(ICSInputShell, "*form.text");
5609 XtSetArg(args[j], XtNstring, ""); j++;
5610 XtSetValues(edit, args, j);
5612 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5613 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5614 XtSetValues(ICSInputShell, args, j);
5617 XtPopup(ICSInputShell, XtGrabNone);
5618 XtSetKeyboardFocus(ICSInputShell, edit);
5620 ICSInputBoxUp = True;
5622 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
5623 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
5627 void ICSInputSendText()
5634 edit = XtNameToWidget(ICSInputShell, "*form.text");
5636 XtSetArg(args[j], XtNstring, &val); j++;
5637 XtGetValues(edit, args, j);
5638 SendMultiLineToICS(val);
5639 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
5640 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
5643 void ICSInputBoxPopDown()
5648 if (!ICSInputBoxUp) return;
5650 XtPopdown(ICSInputShell);
5651 ICSInputBoxUp = False;
5653 XtSetArg(args[j], XtNleftBitmap, None); j++;
5654 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
5658 void CommentPopUp(title, text)
5665 if (commentShell == NULL) {
5667 CommentCreate(title, text, False, CommentCallback, 4);
5668 XtRealizeWidget(commentShell);
5669 CatchDeleteWindow(commentShell, "CommentPopDown");
5671 edit = XtNameToWidget(commentShell, "*form.text");
5673 XtSetArg(args[j], XtNstring, text); j++;
5674 XtSetValues(edit, args, j);
5676 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5677 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5678 XtSetValues(commentShell, args, j);
5681 XtPopup(commentShell, XtGrabNone);
5682 XSync(xDisplay, False);
5687 void AnalysisPopUp(title, text)
5694 if (analysisShell == NULL) {
5695 analysisShell = MiscCreate(title, text, False, NULL, 4);
5696 XtRealizeWidget(analysisShell);
5697 CatchDeleteWindow(analysisShell, "AnalysisPopDown");
5700 edit = XtNameToWidget(analysisShell, "*form.text");
5702 XtSetArg(args[j], XtNstring, text); j++;
5703 XtSetValues(edit, args, j);
5705 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5706 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5707 XtSetValues(analysisShell, args, j);
5711 XtPopup(analysisShell, XtGrabNone);
5713 XSync(xDisplay, False);
5718 void CommentCallback(w, client_data, call_data)
5720 XtPointer client_data, call_data;
5727 XtSetArg(args[j], XtNlabel, &name); j++;
5728 XtGetValues(w, args, j);
5730 if (strcmp(name, _("close")) == 0) {
5732 } else if (strcmp(name, _("edit")) == 0) {
5739 void CommentPopDown()
5744 if (!commentUp) return;
5746 XtSetArg(args[j], XtNx, &commentX); j++;
5747 XtSetArg(args[j], XtNy, &commentY); j++;
5748 XtSetArg(args[j], XtNwidth, &commentW); j++;
5749 XtSetArg(args[j], XtNheight, &commentH); j++;
5750 XtGetValues(commentShell, args, j);
5751 XtPopdown(commentShell);
5752 XSync(xDisplay, False);
5756 void AnalysisPopDown()
5758 if (!analysisUp) return;
5759 XtPopdown(analysisShell);
5760 XSync(xDisplay, False);
5762 if (appData.icsEngineAnalyze) ExitAnalyzeMode(); /* [DM] icsEngineAnalyze */
5766 void FileNamePopUp(label, def, proc, openMode)
5773 Widget popup, layout, dialog, edit;
5779 fileProc = proc; /* I can't see a way not */
5780 fileOpenMode = openMode; /* to use globals here */
5783 XtSetArg(args[i], XtNresizable, True); i++;
5784 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
5785 XtSetArg(args[i], XtNtitle, XtNewString(_("File name prompt"))); i++;
5786 fileNameShell = popup =
5787 XtCreatePopupShell("File name prompt", transientShellWidgetClass,
5788 shellWidget, args, i);
5791 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
5792 layoutArgs, XtNumber(layoutArgs));
5795 XtSetArg(args[i], XtNlabel, label); i++;
5796 XtSetArg(args[i], XtNvalue, def); i++;
5797 XtSetArg(args[i], XtNborderWidth, 0); i++;
5798 dialog = XtCreateManagedWidget("fileName", dialogWidgetClass,
5801 XawDialogAddButton(dialog, _("ok"), FileNameCallback, (XtPointer) dialog);
5802 XawDialogAddButton(dialog, _("cancel"), FileNameCallback,
5803 (XtPointer) dialog);
5805 XtRealizeWidget(popup);
5806 CatchDeleteWindow(popup, "FileNamePopDown");
5808 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
5809 &x, &y, &win_x, &win_y, &mask);
5811 XtSetArg(args[0], XtNx, x - 10);
5812 XtSetArg(args[1], XtNy, y - 30);
5813 XtSetValues(popup, args, 2);
5815 XtPopup(popup, XtGrabExclusive);
5818 edit = XtNameToWidget(dialog, "*value");
5819 XtSetKeyboardFocus(popup, edit);
5822 void FileNamePopDown()
5824 if (!filenameUp) return;
5825 XtPopdown(fileNameShell);
5826 XtDestroyWidget(fileNameShell);
5831 void FileNameCallback(w, client_data, call_data)
5833 XtPointer client_data, call_data;
5838 XtSetArg(args[0], XtNlabel, &name);
5839 XtGetValues(w, args, 1);
5841 if (strcmp(name, _("cancel")) == 0) {
5846 FileNameAction(w, NULL, NULL, NULL);
5849 void FileNameAction(w, event, prms, nprms)
5861 name = XawDialogGetValueString(w = XtParent(w));
5863 if ((name != NULL) && (*name != NULLCHAR)) {
5865 XtPopdown(w = XtParent(XtParent(w)));
5869 p = strrchr(buf, ' ');
5876 fullname = ExpandPathName(buf);
5878 ErrorPopUp(_("Error"), _("Can't open file"), FALSE);
5881 f = fopen(fullname, fileOpenMode);
5883 DisplayError(_("Failed to open file"), errno);
5885 (void) (*fileProc)(f, index, buf);
5892 XtPopdown(w = XtParent(XtParent(w)));
5898 void PromotionPopUp()
5901 Widget dialog, layout;
5903 Dimension bw_width, pw_width;
5907 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5908 XtGetValues(boardWidget, args, j);
5911 XtSetArg(args[j], XtNresizable, True); j++;
5912 XtSetArg(args[j], XtNtitle, XtNewString(_("Promotion"))); j++;
5914 XtCreatePopupShell("Promotion", transientShellWidgetClass,
5915 shellWidget, args, j);
5917 XtCreateManagedWidget(layoutName, formWidgetClass, promotionShell,
5918 layoutArgs, XtNumber(layoutArgs));
5921 XtSetArg(args[j], XtNlabel, _("Promote to what?")); j++;
5922 XtSetArg(args[j], XtNborderWidth, 0); j++;
5923 dialog = XtCreateManagedWidget("promotion", dialogWidgetClass,
5926 if(gameInfo.variant != VariantShogi) {
5927 XawDialogAddButton(dialog, _("Queen"), PromotionCallback,
5928 (XtPointer) dialog);
5929 XawDialogAddButton(dialog, _("Rook"), PromotionCallback,
5930 (XtPointer) dialog);
5931 XawDialogAddButton(dialog, _("Bishop"), PromotionCallback,
5932 (XtPointer) dialog);
5933 XawDialogAddButton(dialog, _("Knight"), PromotionCallback,
5934 (XtPointer) dialog);
5935 if (!appData.testLegality || gameInfo.variant == VariantSuicide ||
5936 gameInfo.variant == VariantGiveaway) {
5937 XawDialogAddButton(dialog, _("King"), PromotionCallback,
5938 (XtPointer) dialog);
5940 if(gameInfo.variant == VariantCapablanca ||
5941 gameInfo.variant == VariantGothic ||
5942 gameInfo.variant == VariantCapaRandom) {
5943 XawDialogAddButton(dialog, _("Archbishop"), PromotionCallback,
5944 (XtPointer) dialog);
5945 XawDialogAddButton(dialog, _("Chancellor"), PromotionCallback,
5946 (XtPointer) dialog);
5948 } else // [HGM] shogi
5950 XawDialogAddButton(dialog, _("Promote"), PromotionCallback,
5951 (XtPointer) dialog);
5952 XawDialogAddButton(dialog, _("Defer"), PromotionCallback,
5953 (XtPointer) dialog);
5955 XawDialogAddButton(dialog, _("cancel"), PromotionCallback,
5956 (XtPointer) dialog);
5958 XtRealizeWidget(promotionShell);
5959 CatchDeleteWindow(promotionShell, "PromotionPopDown");
5962 XtSetArg(args[j], XtNwidth, &pw_width); j++;
5963 XtGetValues(promotionShell, args, j);
5965 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
5966 lineGap + squareSize/3 +
5967 ((toY == BOARD_HEIGHT-1) ^ (flipView) ?
5968 0 : 6*(squareSize + lineGap)), &x, &y);
5971 XtSetArg(args[j], XtNx, x); j++;
5972 XtSetArg(args[j], XtNy, y); j++;
5973 XtSetValues(promotionShell, args, j);
5975 XtPopup(promotionShell, XtGrabNone);
5980 void PromotionPopDown()
5982 if (!promotionUp) return;
5983 XtPopdown(promotionShell);
5984 XtDestroyWidget(promotionShell);
5985 promotionUp = False;
5988 void PromotionCallback(w, client_data, call_data)
5990 XtPointer client_data, call_data;
5996 XtSetArg(args[0], XtNlabel, &name);
5997 XtGetValues(w, args, 1);
6001 if (fromX == -1) return;
6003 if (strcmp(name, _("cancel")) == 0) {
6007 } else if (strcmp(name, _("Knight")) == 0) {
6009 } else if (strcmp(name, _("Promote")) == 0) {
6011 } else if (strcmp(name, _("Defer")) == 0) {
6014 promoChar = ToLower(name[0]);
6017 UserMoveEvent(fromX, fromY, toX, toY, promoChar);
6019 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
6020 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
6025 void ErrorCallback(w, client_data, call_data)
6027 XtPointer client_data, call_data;
6030 XtPopdown(w = XtParent(XtParent(XtParent(w))));
6032 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
6038 if (!errorUp) return;
6040 XtPopdown(errorShell);
6041 XtDestroyWidget(errorShell);
6042 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
6045 void ErrorPopUp(title, label, modal)
6046 char *title, *label;
6050 Widget dialog, layout;
6054 Dimension bw_width, pw_width;
6055 Dimension pw_height;
6059 XtSetArg(args[i], XtNresizable, True); i++;
6060 XtSetArg(args[i], XtNtitle, title); i++;
6062 XtCreatePopupShell("errorpopup", transientShellWidgetClass,
6063 shellWidget, args, i);
6065 XtCreateManagedWidget(layoutName, formWidgetClass, errorShell,
6066 layoutArgs, XtNumber(layoutArgs));
6069 XtSetArg(args[i], XtNlabel, label); i++;
6070 XtSetArg(args[i], XtNborderWidth, 0); i++;
6071 dialog = XtCreateManagedWidget("dialog", dialogWidgetClass,
6074 XawDialogAddButton(dialog, _("ok"), ErrorCallback, (XtPointer) dialog);
6076 XtRealizeWidget(errorShell);
6077 CatchDeleteWindow(errorShell, "ErrorPopDown");
6080 XtSetArg(args[i], XtNwidth, &bw_width); i++;
6081 XtGetValues(boardWidget, args, i);
6083 XtSetArg(args[i], XtNwidth, &pw_width); i++;
6084 XtSetArg(args[i], XtNheight, &pw_height); i++;
6085 XtGetValues(errorShell, args, i);
6088 /* This code seems to tickle an X bug if it is executed too soon
6089 after xboard starts up. The coordinates get transformed as if
6090 the main window was positioned at (0, 0).
6092 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
6093 0 - pw_height + squareSize / 3, &x, &y);
6095 XTranslateCoordinates(xDisplay, XtWindow(boardWidget),
6096 RootWindowOfScreen(XtScreen(boardWidget)),
6097 (bw_width - pw_width) / 2,
6098 0 - pw_height + squareSize / 3, &xx, &yy, &junk);
6102 if (y < 0) y = 0; /*avoid positioning top offscreen*/
6105 XtSetArg(args[i], XtNx, x); i++;
6106 XtSetArg(args[i], XtNy, y); i++;
6107 XtSetValues(errorShell, args, i);
6110 XtPopup(errorShell, modal ? XtGrabExclusive : XtGrabNone);
6113 /* Disable all user input other than deleting the window */
6114 static int frozen = 0;
6118 /* Grab by a widget that doesn't accept input */
6119 XtAddGrab(messageWidget, TRUE, FALSE);
6123 /* Undo a FreezeUI */
6126 if (!frozen) return;
6127 XtRemoveGrab(messageWidget);
6131 char *ModeToWidgetName(mode)
6135 case BeginningOfGame:
6136 if (appData.icsActive)
6137 return "menuMode.ICS Client";
6138 else if (appData.noChessProgram ||
6139 *appData.cmailGameName != NULLCHAR)
6140 return "menuMode.Edit Game";
6142 return "menuMode.Machine Black";
6143 case MachinePlaysBlack:
6144 return "menuMode.Machine Black";
6145 case MachinePlaysWhite:
6146 return "menuMode.Machine White";
6148 return "menuMode.Analysis Mode";
6150 return "menuMode.Analyze File";
6151 case TwoMachinesPlay:
6152 return "menuMode.Two Machines";
6154 return "menuMode.Edit Game";
6155 case PlayFromGameFile:
6156 return "menuFile.Load Game";
6158 return "menuMode.Edit Position";
6160 return "menuMode.Training";
6161 case IcsPlayingWhite:
6162 case IcsPlayingBlack:
6166 return "menuMode.ICS Client";
6173 void ModeHighlight()
6176 static int oldPausing = FALSE;
6177 static GameMode oldmode = (GameMode) -1;
6180 if (!boardWidget || !XtIsRealized(boardWidget)) return;
6182 if (pausing != oldPausing) {
6183 oldPausing = pausing;
6185 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6187 XtSetArg(args[0], XtNleftBitmap, None);
6189 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Pause"),
6192 if (appData.showButtonBar) {
6195 XtSetArg(args[0], XtNbackground, buttonForegroundPixel);
6196 XtSetArg(args[1], XtNforeground, buttonBackgroundPixel);
6198 XtSetArg(args[0], XtNbackground, buttonBackgroundPixel);
6199 XtSetArg(args[1], XtNforeground, buttonForegroundPixel);
6202 /* Always toggle, don't set. Previous code messes up when
6203 invoked while the button is pressed, as releasing it
6204 toggles the state again. */
6207 XtSetArg(args[0], XtNbackground, &oldbg);
6208 XtSetArg(args[1], XtNforeground, &oldfg);
6209 XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON),
6211 XtSetArg(args[0], XtNbackground, oldfg);
6212 XtSetArg(args[1], XtNforeground, oldbg);
6215 XtSetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
6219 wname = ModeToWidgetName(oldmode);
6220 if (wname != NULL) {
6221 XtSetArg(args[0], XtNleftBitmap, None);
6222 XtSetValues(XtNameToWidget(menuBarWidget, wname), args, 1);
6224 wname = ModeToWidgetName(gameMode);
6225 if (wname != NULL) {
6226 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6227 XtSetValues(XtNameToWidget(menuBarWidget, wname), args, 1);
6231 /* Maybe all the enables should be handled here, not just this one */
6232 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Training"),
6233 gameMode == Training || gameMode == PlayFromGameFile);
6238 * Button/menu procedures
6240 void ResetProc(w, event, prms, nprms)
6250 int LoadGamePopUp(f, gameNumber, title)
6255 cmailMsgLoaded = FALSE;
6256 if (gameNumber == 0) {
6257 int error = GameListBuild(f);
6259 DisplayError(_("Cannot build game list"), error);
6260 } else if (!ListEmpty(&gameList) &&
6261 ((ListGame *) gameList.tailPred)->number > 1) {
6262 GameListPopUp(f, title);
6268 return LoadGame(f, gameNumber, title, FALSE);
6271 void LoadGameProc(w, event, prms, nprms)
6277 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
6280 FileNamePopUp(_("Load game file name?"), "", LoadGamePopUp, "rb");
6283 void LoadNextGameProc(w, event, prms, nprms)
6292 void LoadPrevGameProc(w, event, prms, nprms)
6301 void ReloadGameProc(w, event, prms, nprms)
6310 void LoadNextPositionProc(w, event, prms, nprms)
6319 void LoadPrevPositionProc(w, event, prms, nprms)
6328 void ReloadPositionProc(w, event, prms, nprms)
6337 void LoadPositionProc(w, event, prms, nprms)
6343 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
6346 FileNamePopUp(_("Load position file name?"), "", LoadPosition, "rb");
6349 void SaveGameProc(w, event, prms, nprms)
6355 FileNamePopUp(_("Save game file name?"),
6356 DefaultFileName(appData.oldSaveStyle ? "game" : "pgn"),
6360 void SavePositionProc(w, event, prms, nprms)
6366 FileNamePopUp(_("Save position file name?"),
6367 DefaultFileName(appData.oldSaveStyle ? "pos" : "fen"),
6371 void ReloadCmailMsgProc(w, event, prms, nprms)
6377 ReloadCmailMsgEvent(FALSE);
6380 void MailMoveProc(w, event, prms, nprms)
6389 /* this variable is shared between CopyPositionProc and SendPositionSelection */
6390 static char *selected_fen_position=NULL;
6393 SendPositionSelection(Widget w, Atom *selection, Atom *target,
6394 Atom *type_return, XtPointer *value_return,
6395 unsigned long *length_return, int *format_return)
6397 char *selection_tmp;
6399 if (!selected_fen_position) return False; /* should never happen */
6400 if (*target == XA_STRING){
6401 /* note: since no XtSelectionDoneProc was registered, Xt will
6402 * automatically call XtFree on the value returned. So have to
6403 * make a copy of it allocated with XtMalloc */
6404 selection_tmp= XtMalloc(strlen(selected_fen_position)+16);
6405 strcpy(selection_tmp, selected_fen_position);
6407 *value_return=selection_tmp;
6408 *length_return=strlen(selection_tmp);
6409 *type_return=XA_STRING;
6410 *format_return = 8; /* bits per byte */
6417 /* note: when called from menu all parameters are NULL, so no clue what the
6418 * Widget which was clicked on was, or what the click event was
6420 void CopyPositionProc(w, event, prms, nprms)
6428 if (selected_fen_position) free(selected_fen_position);
6429 selected_fen_position = (char *)PositionToFEN(currentMove, NULL);
6430 if (!selected_fen_position) return;
6431 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
6433 SendPositionSelection,
6434 NULL/* lose_ownership_proc */ ,
6435 NULL/* transfer_done_proc */);
6437 free(selected_fen_position);
6438 selected_fen_position=NULL;
6442 /* function called when the data to Paste is ready */
6444 PastePositionCB(Widget w, XtPointer client_data, Atom *selection,
6445 Atom *type, XtPointer value, unsigned long *len, int *format)
6448 if (value==NULL || *len==0) return; /* nothing had been selected to copy */
6449 fenstr[*len]='\0'; /* normally this string is terminated, but be safe */
6450 EditPositionPasteFEN(fenstr);
6454 /* called when Paste Position button is pressed,
6455 * all parameters will be NULL */
6456 void PastePositionProc(w, event, prms, nprms)
6462 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
6463 /* (XtSelectionCallbackProc) */ PastePositionCB,
6464 NULL, /* client_data passed to PastePositionCB */
6466 /* better to use the time field from the event that triggered the
6467 * call to this function, but that isn't trivial to get
6475 SendGameSelection(Widget w, Atom *selection, Atom *target,
6476 Atom *type_return, XtPointer *value_return,
6477 unsigned long *length_return, int *format_return)
6479 char *selection_tmp;
6481 if (*target == XA_STRING){
6482 FILE* f = fopen(gameCopyFilename, "r");
6485 if (f == NULL) return False;
6489 selection_tmp = XtMalloc(len + 1);
6490 count = fread(selection_tmp, 1, len, f);
6492 XtFree(selection_tmp);
6495 selection_tmp[len] = NULLCHAR;
6496 *value_return = selection_tmp;
6497 *length_return = len;
6498 *type_return = XA_STRING;
6499 *format_return = 8; /* bits per byte */
6506 /* note: when called from menu all parameters are NULL, so no clue what the
6507 * Widget which was clicked on was, or what the click event was
6509 void CopyGameProc(w, event, prms, nprms)
6517 ret = SaveGameToFile(gameCopyFilename, FALSE);
6520 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
6523 NULL/* lose_ownership_proc */ ,
6524 NULL/* transfer_done_proc */);
6527 /* function called when the data to Paste is ready */
6529 PasteGameCB(Widget w, XtPointer client_data, Atom *selection,
6530 Atom *type, XtPointer value, unsigned long *len, int *format)
6533 if (value == NULL || *len == 0) {
6534 return; /* nothing had been selected to copy */
6536 f = fopen(gamePasteFilename, "w");
6538 DisplayError(_("Can't open temp file"), errno);
6541 fwrite(value, 1, *len, f);
6544 LoadGameFromFile(gamePasteFilename, 0, gamePasteFilename, TRUE);
6547 /* called when Paste Game button is pressed,
6548 * all parameters will be NULL */
6549 void PasteGameProc(w, event, prms, nprms)
6555 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
6556 /* (XtSelectionCallbackProc) */ PasteGameCB,
6557 NULL, /* client_data passed to PasteGameCB */
6559 /* better to use the time field from the event that triggered the
6560 * call to this function, but that isn't trivial to get
6570 SaveGameProc(NULL, NULL, NULL, NULL);
6574 void QuitProc(w, event, prms, nprms)
6583 void PauseProc(w, event, prms, nprms)
6593 void MachineBlackProc(w, event, prms, nprms)
6599 MachineBlackEvent();
6602 void MachineWhiteProc(w, event, prms, nprms)
6608 MachineWhiteEvent();
6611 void AnalyzeModeProc(w, event, prms, nprms)
6619 if (!first.analysisSupport) {
6620 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
6621 DisplayError(buf, 0);
6624 /* [DM] icsEngineAnalyze [HGM] This is horrible code; reverse the gameMode and isEngineAnalyze tests! */
6625 if (appData.icsActive) {
6626 if (gameMode != IcsObserving) {
6627 sprintf(buf,_("You are not observing a game"));
6628 DisplayError(buf, 0);
6630 if (appData.icsEngineAnalyze) {
6631 if (appData.debugMode)
6632 fprintf(debugFP, _("Found unexpected active ICS engine analyze \n"));
6638 /* if enable, use want disable icsEngineAnalyze */
6639 if (appData.icsEngineAnalyze) {
6644 appData.icsEngineAnalyze = TRUE;
6645 if (appData.debugMode)
6646 fprintf(debugFP, _("ICS engine analyze starting... \n"));
6648 if (!appData.showThinking)
6649 ShowThinkingProc(w,event,prms,nprms);
6654 void AnalyzeFileProc(w, event, prms, nprms)
6660 if (!first.analysisSupport) {
6662 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
6663 DisplayError(buf, 0);
6668 if (!appData.showThinking)
6669 ShowThinkingProc(w,event,prms,nprms);
6672 FileNamePopUp(_("File to analyze"), "", LoadGamePopUp, "rb");
6673 AnalysisPeriodicEvent(1);
6676 void TwoMachinesProc(w, event, prms, nprms)
6685 void IcsClientProc(w, event, prms, nprms)
6694 void EditGameProc(w, event, prms, nprms)
6703 void EditPositionProc(w, event, prms, nprms)
6709 EditPositionEvent();
6712 void TrainingProc(w, event, prms, nprms)
6721 void EditCommentProc(w, event, prms, nprms)
6728 EditCommentPopDown();
6734 void IcsInputBoxProc(w, event, prms, nprms)
6740 if (ICSInputBoxUp) {
6741 ICSInputBoxPopDown();
6747 void AcceptProc(w, event, prms, nprms)
6756 void DeclineProc(w, event, prms, nprms)
6765 void RematchProc(w, event, prms, nprms)
6774 void CallFlagProc(w, event, prms, nprms)
6783 void DrawProc(w, event, prms, nprms)
6792 void AbortProc(w, event, prms, nprms)
6801 void AdjournProc(w, event, prms, nprms)
6810 void ResignProc(w, event, prms, nprms)
6819 void AdjuWhiteProc(w, event, prms, nprms)
6825 UserAdjudicationEvent(+1);
6828 void AdjuBlackProc(w, event, prms, nprms)
6834 UserAdjudicationEvent(-1);
6837 void AdjuDrawProc(w, event, prms, nprms)
6843 UserAdjudicationEvent(0);
6846 void EnterKeyProc(w, event, prms, nprms)
6852 if (ICSInputBoxUp == True)
6856 void StopObservingProc(w, event, prms, nprms)
6862 StopObservingEvent();
6865 void StopExaminingProc(w, event, prms, nprms)
6871 StopExaminingEvent();
6875 void ForwardProc(w, event, prms, nprms)
6885 void BackwardProc(w, event, prms, nprms)
6894 void ToStartProc(w, event, prms, nprms)
6903 void ToEndProc(w, event, prms, nprms)
6912 void RevertProc(w, event, prms, nprms)
6921 void TruncateGameProc(w, event, prms, nprms)
6927 TruncateGameEvent();
6929 void RetractMoveProc(w, event, prms, nprms)
6938 void MoveNowProc(w, event, prms, nprms)
6948 void AlwaysQueenProc(w, event, prms, nprms)
6956 appData.alwaysPromoteToQueen = !appData.alwaysPromoteToQueen;
6958 if (appData.alwaysPromoteToQueen) {
6959 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6961 XtSetArg(args[0], XtNleftBitmap, None);
6963 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
6967 void AnimateDraggingProc(w, event, prms, nprms)
6975 appData.animateDragging = !appData.animateDragging;
6977 if (appData.animateDragging) {
6978 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6981 XtSetArg(args[0], XtNleftBitmap, None);
6983 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Dragging"),
6987 void AnimateMovingProc(w, event, prms, nprms)
6995 appData.animate = !appData.animate;
6997 if (appData.animate) {
6998 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7001 XtSetArg(args[0], XtNleftBitmap, None);
7003 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
7007 void AutocommProc(w, event, prms, nprms)
7015 appData.autoComment = !appData.autoComment;
7017 if (appData.autoComment) {
7018 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7020 XtSetArg(args[0], XtNleftBitmap, None);
7022 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
7027 void AutoflagProc(w, event, prms, nprms)
7035 appData.autoCallFlag = !appData.autoCallFlag;
7037 if (appData.autoCallFlag) {
7038 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7040 XtSetArg(args[0], XtNleftBitmap, None);
7042 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
7046 void AutoflipProc(w, event, prms, nprms)
7054 appData.autoFlipView = !appData.autoFlipView;
7056 if (appData.autoFlipView) {
7057 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7059 XtSetArg(args[0], XtNleftBitmap, None);
7061 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flip View"),
7065 void AutobsProc(w, event, prms, nprms)
7073 appData.autoObserve = !appData.autoObserve;
7075 if (appData.autoObserve) {
7076 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7078 XtSetArg(args[0], XtNleftBitmap, None);
7080 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
7084 void AutoraiseProc(w, event, prms, nprms)
7092 appData.autoRaiseBoard = !appData.autoRaiseBoard;
7094 if (appData.autoRaiseBoard) {
7095 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7097 XtSetArg(args[0], XtNleftBitmap, None);
7099 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Raise Board"),
7103 void AutosaveProc(w, event, prms, nprms)
7111 appData.autoSaveGames = !appData.autoSaveGames;
7113 if (appData.autoSaveGames) {
7114 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7116 XtSetArg(args[0], XtNleftBitmap, None);
7118 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
7122 void BlindfoldProc(w, event, prms, nprms)
7130 appData.blindfold = !appData.blindfold;
7132 if (appData.blindfold) {
7133 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7135 XtSetArg(args[0], XtNleftBitmap, None);
7137 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Blindfold"),
7140 DrawPosition(True, NULL);
7143 void TestLegalityProc(w, event, prms, nprms)
7151 appData.testLegality = !appData.testLegality;
7153 if (appData.testLegality) {
7154 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7156 XtSetArg(args[0], XtNleftBitmap, None);
7158 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Test Legality"),
7163 void FlashMovesProc(w, event, prms, nprms)
7171 if (appData.flashCount == 0) {
7172 appData.flashCount = 3;
7174 appData.flashCount = -appData.flashCount;
7177 if (appData.flashCount > 0) {
7178 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7180 XtSetArg(args[0], XtNleftBitmap, None);
7182 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flash Moves"),
7186 void FlipViewProc(w, event, prms, nprms)
7192 flipView = !flipView;
7193 DrawPosition(True, NULL);
7196 void GetMoveListProc(w, event, prms, nprms)
7204 appData.getMoveList = !appData.getMoveList;
7206 if (appData.getMoveList) {
7207 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7210 XtSetArg(args[0], XtNleftBitmap, None);
7212 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
7217 void HighlightDraggingProc(w, event, prms, nprms)
7225 appData.highlightDragging = !appData.highlightDragging;
7227 if (appData.highlightDragging) {
7228 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7230 XtSetArg(args[0], XtNleftBitmap, None);
7232 XtSetValues(XtNameToWidget(menuBarWidget,
7233 "menuOptions.Highlight Dragging"), args, 1);
7237 void HighlightLastMoveProc(w, event, prms, nprms)
7245 appData.highlightLastMove = !appData.highlightLastMove;
7247 if (appData.highlightLastMove) {
7248 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7250 XtSetArg(args[0], XtNleftBitmap, None);
7252 XtSetValues(XtNameToWidget(menuBarWidget,
7253 "menuOptions.Highlight Last Move"), args, 1);
7256 void IcsAlarmProc(w, event, prms, nprms)
7264 appData.icsAlarm = !appData.icsAlarm;
7266 if (appData.icsAlarm) {
7267 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7269 XtSetArg(args[0], XtNleftBitmap, None);
7271 XtSetValues(XtNameToWidget(menuBarWidget,
7272 "menuOptions.ICS Alarm"), args, 1);
7275 void MoveSoundProc(w, event, prms, nprms)
7283 appData.ringBellAfterMoves = !appData.ringBellAfterMoves;
7285 if (appData.ringBellAfterMoves) {
7286 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7288 XtSetArg(args[0], XtNleftBitmap, None);
7290 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
7295 void OldSaveStyleProc(w, event, prms, nprms)
7303 appData.oldSaveStyle = !appData.oldSaveStyle;
7305 if (appData.oldSaveStyle) {
7306 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7308 XtSetArg(args[0], XtNleftBitmap, None);
7310 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Old Save Style"),
7314 void PeriodicUpdatesProc(w, event, prms, nprms)
7322 PeriodicUpdatesEvent(!appData.periodicUpdates);
7324 if (appData.periodicUpdates) {
7325 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7327 XtSetArg(args[0], XtNleftBitmap, None);
7329 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Periodic Updates"),
7333 void PonderNextMoveProc(w, event, prms, nprms)
7341 PonderNextMoveEvent(!appData.ponderNextMove);
7343 if (appData.ponderNextMove) {
7344 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7346 XtSetArg(args[0], XtNleftBitmap, None);
7348 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Ponder Next Move"),
7352 void PopupExitMessageProc(w, event, prms, nprms)
7360 appData.popupExitMessage = !appData.popupExitMessage;
7362 if (appData.popupExitMessage) {
7363 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7365 XtSetArg(args[0], XtNleftBitmap, None);
7367 XtSetValues(XtNameToWidget(menuBarWidget,
7368 "menuOptions.Popup Exit Message"), args, 1);
7371 void PopupMoveErrorsProc(w, event, prms, nprms)
7379 appData.popupMoveErrors = !appData.popupMoveErrors;
7381 if (appData.popupMoveErrors) {
7382 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7384 XtSetArg(args[0], XtNleftBitmap, None);
7386 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Popup Move Errors"),
7390 void PremoveProc(w, event, prms, nprms)
7398 appData.premove = !appData.premove;
7400 if (appData.premove) {
7401 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7403 XtSetArg(args[0], XtNleftBitmap, None);
7405 XtSetValues(XtNameToWidget(menuBarWidget,
7406 "menuOptions.Premove"), args, 1);
7409 void QuietPlayProc(w, event, prms, nprms)
7417 appData.quietPlay = !appData.quietPlay;
7419 if (appData.quietPlay) {
7420 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7422 XtSetArg(args[0], XtNleftBitmap, None);
7424 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Quiet Play"),
7428 void ShowCoordsProc(w, event, prms, nprms)
7436 appData.showCoords = !appData.showCoords;
7438 if (appData.showCoords) {
7439 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7441 XtSetArg(args[0], XtNleftBitmap, None);
7443 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
7446 DrawPosition(True, NULL);
7449 void ShowThinkingProc(w, event, prms, nprms)
7457 appData.showThinking = !appData.showThinking; // [HGM] thinking: tken out of ShowThinkingEvent
7458 ShowThinkingEvent();
7460 // [HGM] thinking: currently no suc menu item; replaced by Hide Thinking (From Human)
7461 if (appData.showThinking) {
7462 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7464 XtSetArg(args[0], XtNleftBitmap, None);
7466 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Thinking"),
7471 void HideThinkingProc(w, event, prms, nprms)
7479 appData.hideThinkingFromHuman = !appData.hideThinkingFromHuman; // [HGM] thinking: tken out of ShowThinkingEvent
7480 ShowThinkingEvent();
7482 if (appData.hideThinkingFromHuman) {
7483 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7485 XtSetArg(args[0], XtNleftBitmap, None);
7487 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
7491 void InfoProc(w, event, prms, nprms)
7498 snprintf(buf, sizeof(buf), "xterm -e info --directory %s --directory . -f %s &",
7503 void ManProc(w, event, prms, nprms)
7511 if (nprms && *nprms > 0)
7515 snprintf(buf, sizeof(buf), "xterm -e man %s &", name);
7519 void HintProc(w, event, prms, nprms)
7528 void BookProc(w, event, prms, nprms)
7537 void AboutProc(w, event, prms, nprms)
7545 char *zippy = " (with Zippy code)";
7549 snprintf(buf, sizeof(buf), "%s%s\n\n%s\n%s\n%s\n\n%s%s\n%s",
7550 programVersion, zippy,
7551 "Copyright 1991 Digital Equipment Corporation",
7552 "Enhancements Copyright 1992-2009 Free Software Foundation",
7553 "Enhancements Copyright 2005 Alessandro Scotti",
7554 PACKAGE, " is free software and carries NO WARRANTY;",
7555 "see the file COPYING for more information.");
7556 ErrorPopUp(_("About XBoard"), buf, FALSE);
7559 void DebugProc(w, event, prms, nprms)
7565 appData.debugMode = !appData.debugMode;
7568 void AboutGameProc(w, event, prms, nprms)
7577 void NothingProc(w, event, prms, nprms)
7586 void Iconify(w, event, prms, nprms)
7595 XtSetArg(args[0], XtNiconic, True);
7596 XtSetValues(shellWidget, args, 1);
7599 void DisplayMessage(message, extMessage)
7600 char *message, *extMessage;
7607 snprintf(buf, sizeof(buf), "%s %s", message, extMessage);
7610 message = extMessage;
7613 XtSetArg(arg, XtNlabel, message);
7614 XtSetValues(messageWidget, &arg, 1);
7617 void DisplayTitle(text)
7622 char title[MSG_SIZ];
7625 if (text == NULL) text = "";
7627 if (appData.titleInWindow) {
7629 XtSetArg(args[i], XtNlabel, text); i++;
7630 XtSetValues(titleWidget, args, i);
7633 if (*text != NULLCHAR) {
7635 strcpy(title, text);
7636 } else if (appData.icsActive) {
7637 snprintf(icon, sizeof(icon), "%s", appData.icsHost);
7638 snprintf(title, sizeof(title), "%s: %s", programName, appData.icsHost);
7639 } else if (appData.cmailGameName[0] != NULLCHAR) {
7640 snprintf(icon, sizeof(icon), "%s", "CMail");
7641 snprintf(title,sizeof(title), "%s: %s", programName, "CMail");
7643 // [HGM] license: This stuff should really be done in back-end, but WinBoard already had a pop-up for it
7644 } else if (gameInfo.variant == VariantGothic) {
7645 strcpy(icon, programName);
7646 strcpy(title, GOTHIC);
7649 } else if (gameInfo.variant == VariantFalcon) {
7650 strcpy(icon, programName);
7651 strcpy(title, FALCON);
7653 } else if (appData.noChessProgram) {
7654 strcpy(icon, programName);
7655 strcpy(title, programName);
7657 strcpy(icon, first.tidy);
7658 snprintf(title,sizeof(title), "%s: %s", programName, first.tidy);
7661 XtSetArg(args[i], XtNiconName, (XtArgVal) icon); i++;
7662 XtSetArg(args[i], XtNtitle, (XtArgVal) title); i++;
7663 XtSetValues(shellWidget, args, i);
7667 void DisplayError(message, error)
7674 if (appData.debugMode || appData.matchMode) {
7675 fprintf(stderr, "%s: %s\n", programName, message);
7678 if (appData.debugMode || appData.matchMode) {
7679 fprintf(stderr, "%s: %s: %s\n",
7680 programName, message, strerror(error));
7682 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
7685 ErrorPopUp(_("Error"), message, FALSE);
7689 void DisplayMoveError(message)
7694 DrawPosition(FALSE, NULL);
7695 if (appData.debugMode || appData.matchMode) {
7696 fprintf(stderr, "%s: %s\n", programName, message);
7698 if (appData.popupMoveErrors) {
7699 ErrorPopUp(_("Error"), message, FALSE);
7701 DisplayMessage(message, "");
7706 void DisplayFatalError(message, error, status)
7712 errorExitStatus = status;
7714 fprintf(stderr, "%s: %s\n", programName, message);
7716 fprintf(stderr, "%s: %s: %s\n",
7717 programName, message, strerror(error));
7718 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
7721 if (appData.popupExitMessage && boardWidget && XtIsRealized(boardWidget)) {
7722 ErrorPopUp(status ? _("Fatal Error") : _("Exiting"), message, TRUE);
7728 void DisplayInformation(message)
7732 ErrorPopUp(_("Information"), message, TRUE);
7735 void DisplayNote(message)
7739 ErrorPopUp(_("Note"), message, FALSE);
7743 NullXErrorCheck(dpy, error_event)
7745 XErrorEvent *error_event;
7750 void DisplayIcsInteractionTitle(message)
7753 if (oldICSInteractionTitle == NULL) {
7754 /* Magic to find the old window title, adapted from vim */
7755 char *wina = getenv("WINDOWID");
7757 Window win = (Window) atoi(wina);
7758 Window root, parent, *children;
7759 unsigned int nchildren;
7760 int (*oldHandler)() = XSetErrorHandler(NullXErrorCheck);
7762 if (XFetchName(xDisplay, win, &oldICSInteractionTitle)) break;
7763 if (!XQueryTree(xDisplay, win, &root, &parent,
7764 &children, &nchildren)) break;
7765 if (children) XFree((void *)children);
7766 if (parent == root || parent == 0) break;
7769 XSetErrorHandler(oldHandler);
7771 if (oldICSInteractionTitle == NULL) {
7772 oldICSInteractionTitle = "xterm";
7775 printf("\033]0;%s\007", message);
7779 char pendingReplyPrefix[MSG_SIZ];
7780 ProcRef pendingReplyPR;
7782 void AskQuestionProc(w, event, prms, nprms)
7789 fprintf(stderr, _("AskQuestionProc needed 4 parameters, got %d\n"),
7793 AskQuestionEvent(prms[0], prms[1], prms[2], prms[3]);
7796 void AskQuestionPopDown()
7798 if (!askQuestionUp) return;
7799 XtPopdown(askQuestionShell);
7800 XtDestroyWidget(askQuestionShell);
7801 askQuestionUp = False;
7804 void AskQuestionReplyAction(w, event, prms, nprms)
7814 reply = XawDialogGetValueString(w = XtParent(w));
7815 strcpy(buf, pendingReplyPrefix);
7816 if (*buf) strcat(buf, " ");
7819 OutputToProcess(pendingReplyPR, buf, strlen(buf), &err);
7820 AskQuestionPopDown();
7822 if (err) DisplayFatalError(_("Error writing to chess program"), err, 0);
7825 void AskQuestionCallback(w, client_data, call_data)
7827 XtPointer client_data, call_data;
7832 XtSetArg(args[0], XtNlabel, &name);
7833 XtGetValues(w, args, 1);
7835 if (strcmp(name, _("cancel")) == 0) {
7836 AskQuestionPopDown();
7838 AskQuestionReplyAction(w, NULL, NULL, NULL);
7842 void AskQuestion(title, question, replyPrefix, pr)
7843 char *title, *question, *replyPrefix;
7847 Widget popup, layout, dialog, edit;
7853 strcpy(pendingReplyPrefix, replyPrefix);
7854 pendingReplyPR = pr;
7857 XtSetArg(args[i], XtNresizable, True); i++;
7858 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
7859 askQuestionShell = popup =
7860 XtCreatePopupShell(title, transientShellWidgetClass,
7861 shellWidget, args, i);
7864 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
7865 layoutArgs, XtNumber(layoutArgs));
7868 XtSetArg(args[i], XtNlabel, question); i++;
7869 XtSetArg(args[i], XtNvalue, ""); i++;
7870 XtSetArg(args[i], XtNborderWidth, 0); i++;
7871 dialog = XtCreateManagedWidget("question", dialogWidgetClass,
7874 XawDialogAddButton(dialog, _("enter"), AskQuestionCallback,
7875 (XtPointer) dialog);
7876 XawDialogAddButton(dialog, _("cancel"), AskQuestionCallback,
7877 (XtPointer) dialog);
7879 XtRealizeWidget(popup);
7880 CatchDeleteWindow(popup, "AskQuestionPopDown");
7882 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
7883 &x, &y, &win_x, &win_y, &mask);
7885 XtSetArg(args[0], XtNx, x - 10);
7886 XtSetArg(args[1], XtNy, y - 30);
7887 XtSetValues(popup, args, 2);
7889 XtPopup(popup, XtGrabExclusive);
7890 askQuestionUp = True;
7892 edit = XtNameToWidget(dialog, "*value");
7893 XtSetKeyboardFocus(popup, edit);
7901 if (*name == NULLCHAR) {
7903 } else if (strcmp(name, "$") == 0) {
7904 putc(BELLCHAR, stderr);
7907 snprintf(buf, sizeof(buf), "%s '%s' &", appData.soundProgram, name);
7915 PlaySound(appData.soundMove);
7921 PlaySound(appData.soundIcsWin);
7927 PlaySound(appData.soundIcsLoss);
7933 PlaySound(appData.soundIcsDraw);
7937 PlayIcsUnfinishedSound()
7939 PlaySound(appData.soundIcsUnfinished);
7945 PlaySound(appData.soundIcsAlarm);
7951 system("stty echo");
7957 system("stty -echo");
7961 Colorize(cc, continuation)
7966 int count, outCount, error;
7968 if (textColors[(int)cc].bg > 0) {
7969 if (textColors[(int)cc].fg > 0) {
7970 sprintf(buf, "\033[0;%d;%d;%dm", textColors[(int)cc].attr,
7971 textColors[(int)cc].fg, textColors[(int)cc].bg);
7973 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
7974 textColors[(int)cc].bg);
7977 if (textColors[(int)cc].fg > 0) {
7978 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
7979 textColors[(int)cc].fg);
7981 sprintf(buf, "\033[0;%dm", textColors[(int)cc].attr);
7984 count = strlen(buf);
7985 outCount = OutputToProcess(NoProc, buf, count, &error);
7986 if (outCount < count) {
7987 DisplayFatalError(_("Error writing to display"), error, 1);
7990 if (continuation) return;
7993 PlaySound(appData.soundShout);
7996 PlaySound(appData.soundSShout);
7999 PlaySound(appData.soundChannel1);
8002 PlaySound(appData.soundChannel);
8005 PlaySound(appData.soundKibitz);
8008 PlaySound(appData.soundTell);
8010 case ColorChallenge:
8011 PlaySound(appData.soundChallenge);
8014 PlaySound(appData.soundRequest);
8017 PlaySound(appData.soundSeek);
8028 return getpwuid(getuid())->pw_name;
8031 static char *ExpandPathName(path)
8034 static char static_buf[2000];
8035 char *d, *s, buf[2000];
8041 while (*s && isspace(*s))
8050 if (*(s+1) == '/') {
8051 strcpy(d, getpwuid(getuid())->pw_dir);
8056 *strchr(buf, '/') = 0;
8057 pwd = getpwnam(buf);
8060 fprintf(stderr, _("ERROR: Unknown user %s (in path %s)\n"),
8064 strcpy(d, pwd->pw_dir);
8065 strcat(d, strchr(s+1, '/'));
8076 static char host_name[MSG_SIZ];
8078 #if HAVE_GETHOSTNAME
8079 gethostname(host_name, MSG_SIZ);
8081 #else /* not HAVE_GETHOSTNAME */
8082 # if HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H
8083 sysinfo(SI_HOSTNAME, host_name, MSG_SIZ);
8085 # else /* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
8087 # endif/* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
8088 #endif /* not HAVE_GETHOSTNAME */
8091 XtIntervalId delayedEventTimerXID = 0;
8092 DelayedEventCallback delayedEventCallback = 0;
8097 delayedEventTimerXID = 0;
8098 delayedEventCallback();
8102 ScheduleDelayedEvent(cb, millisec)
8103 DelayedEventCallback cb; long millisec;
8105 delayedEventCallback = cb;
8106 delayedEventTimerXID =
8107 XtAppAddTimeOut(appContext, millisec,
8108 (XtTimerCallbackProc) FireDelayedEvent, (XtPointer) 0);
8111 DelayedEventCallback
8114 if (delayedEventTimerXID) {
8115 return delayedEventCallback;
8122 CancelDelayedEvent()
8124 if (delayedEventTimerXID) {
8125 XtRemoveTimeOut(delayedEventTimerXID);
8126 delayedEventTimerXID = 0;
8130 XtIntervalId loadGameTimerXID = 0;
8132 int LoadGameTimerRunning()
8134 return loadGameTimerXID != 0;
8137 int StopLoadGameTimer()
8139 if (loadGameTimerXID != 0) {
8140 XtRemoveTimeOut(loadGameTimerXID);
8141 loadGameTimerXID = 0;
8149 LoadGameTimerCallback(arg, id)
8153 loadGameTimerXID = 0;
8158 StartLoadGameTimer(millisec)
8162 XtAppAddTimeOut(appContext, millisec,
8163 (XtTimerCallbackProc) LoadGameTimerCallback,
8167 XtIntervalId analysisClockXID = 0;
8170 AnalysisClockCallback(arg, id)
8174 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile
8175 || appData.icsEngineAnalyze) { // [DM]
8176 AnalysisPeriodicEvent(0);
8177 StartAnalysisClock();
8182 StartAnalysisClock()
8185 XtAppAddTimeOut(appContext, 2000,
8186 (XtTimerCallbackProc) AnalysisClockCallback,
8190 XtIntervalId clockTimerXID = 0;
8192 int ClockTimerRunning()
8194 return clockTimerXID != 0;
8197 int StopClockTimer()
8199 if (clockTimerXID != 0) {
8200 XtRemoveTimeOut(clockTimerXID);
8209 ClockTimerCallback(arg, id)
8218 StartClockTimer(millisec)
8222 XtAppAddTimeOut(appContext, millisec,
8223 (XtTimerCallbackProc) ClockTimerCallback,
8228 DisplayTimerLabel(w, color, timer, highlight)
8237 /* check for low time warning */
8238 Pixel foregroundOrWarningColor = timerForegroundPixel;
8241 appData.lowTimeWarning &&
8242 (timer / 1000) < appData.icsAlarmTime)
8243 foregroundOrWarningColor = lowTimeWarningColor;
8245 if (appData.clockMode) {
8246 sprintf(buf, "%s: %s", color, TimeString(timer));
8247 XtSetArg(args[0], XtNlabel, buf);
8249 sprintf(buf, "%s ", color);
8250 XtSetArg(args[0], XtNlabel, buf);
8255 XtSetArg(args[1], XtNbackground, foregroundOrWarningColor);
8256 XtSetArg(args[2], XtNforeground, timerBackgroundPixel);
8258 XtSetArg(args[1], XtNbackground, timerBackgroundPixel);
8259 XtSetArg(args[2], XtNforeground, foregroundOrWarningColor);
8262 XtSetValues(w, args, 3);
8266 DisplayWhiteClock(timeRemaining, highlight)
8272 if(appData.noGUI) return;
8273 DisplayTimerLabel(whiteTimerWidget, _("White"), timeRemaining, highlight);
8274 if (highlight && iconPixmap == bIconPixmap) {
8275 iconPixmap = wIconPixmap;
8276 XtSetArg(args[0], XtNiconPixmap, iconPixmap);
8277 XtSetValues(shellWidget, args, 1);
8282 DisplayBlackClock(timeRemaining, highlight)
8288 if(appData.noGUI) return;
8289 DisplayTimerLabel(blackTimerWidget, _("Black"), timeRemaining, highlight);
8290 if (highlight && iconPixmap == wIconPixmap) {
8291 iconPixmap = bIconPixmap;
8292 XtSetArg(args[0], XtNiconPixmap, iconPixmap);
8293 XtSetValues(shellWidget, args, 1);
8311 int StartChildProcess(cmdLine, dir, pr)
8318 int to_prog[2], from_prog[2];
8322 if (appData.debugMode) {
8323 fprintf(stderr, "StartChildProcess (dir=\"%s\") %s\n",dir, cmdLine);
8326 /* We do NOT feed the cmdLine to the shell; we just
8327 parse it into blank-separated arguments in the
8328 most simple-minded way possible.
8331 strcpy(buf, cmdLine);
8336 if (p == NULL) break;
8341 SetUpChildIO(to_prog, from_prog);
8343 if ((pid = fork()) == 0) {
8345 // [HGM] PSWBTM: made order resistant against case where fd of created pipe was 0 or 1
8346 close(to_prog[1]); // first close the unused pipe ends
8347 close(from_prog[0]);
8348 dup2(to_prog[0], 0); // to_prog was created first, nd is the only one to use 0 or 1
8349 dup2(from_prog[1], 1);
8350 if(to_prog[0] >= 2) close(to_prog[0]); // if 0 or 1, the dup2 already cosed the original
8351 close(from_prog[1]); // and closing again loses one of the pipes!
8352 if(fileno(stderr) >= 2) // better safe than sorry...
8353 dup2(1, fileno(stderr)); /* force stderr to the pipe */
8355 if (dir[0] != NULLCHAR && chdir(dir) != 0) {
8360 nice(appData.niceEngines); // [HGM] nice: adjust priority of engine proc
8362 execvp(argv[0], argv);
8364 /* If we get here, exec failed */
8369 /* Parent process */
8371 close(from_prog[1]);
8373 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8376 cp->fdFrom = from_prog[0];
8377 cp->fdTo = to_prog[1];
8382 // [HGM] kill: implement the 'hard killing' of AS's Winboard_x
8383 static RETSIGTYPE AlarmCallBack(int n)
8389 DestroyChildProcess(pr, signalType)
8393 ChildProc *cp = (ChildProc *) pr;
8395 if (cp->kind != CPReal) return;
8397 if (signalType == 10) { // [HGM] kill: if it does not terminate in 3 sec, kill
8398 signal(SIGALRM, AlarmCallBack);
8400 if(wait((int *) 0) == -1) { // process does not terminate on its own accord
8401 kill(cp->pid, SIGKILL); // kill it forcefully
8402 wait((int *) 0); // and wait again
8406 kill(cp->pid, signalType == 9 ? SIGKILL : SIGTERM); // [HGM] kill: use hard kill if so requested
8408 /* Process is exiting either because of the kill or because of
8409 a quit command sent by the backend; either way, wait for it to die.
8418 InterruptChildProcess(pr)
8421 ChildProc *cp = (ChildProc *) pr;
8423 if (cp->kind != CPReal) return;
8424 (void) kill(cp->pid, SIGINT); /* stop it thinking */
8427 int OpenTelnet(host, port, pr)
8432 char cmdLine[MSG_SIZ];
8434 if (port[0] == NULLCHAR) {
8435 snprintf(cmdLine, sizeof(cmdLine), "%s %s", appData.telnetProgram, host);
8437 snprintf(cmdLine, sizeof(cmdLine), "%s %s %s", appData.telnetProgram, host, port);
8439 return StartChildProcess(cmdLine, "", pr);
8442 int OpenTCP(host, port, pr)
8448 DisplayFatalError(_("Socket support is not configured in"), 0, 2);
8449 #else /* !OMIT_SOCKETS */
8451 struct sockaddr_in sa;
8453 unsigned short uport;
8456 if ((s = socket(AF_INET, SOCK_STREAM, 6)) < 0) {
8460 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
8461 sa.sin_family = AF_INET;
8462 sa.sin_addr.s_addr = INADDR_ANY;
8463 uport = (unsigned short) 0;
8464 sa.sin_port = htons(uport);
8465 if (bind(s, (struct sockaddr *) &sa, sizeof(struct sockaddr_in)) < 0) {
8469 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
8470 if (!(hp = gethostbyname(host))) {
8472 if (sscanf(host, "%d.%d.%d.%d", &b0, &b1, &b2, &b3) == 4) {
8473 hp = (struct hostent *) calloc(1, sizeof(struct hostent));
8474 hp->h_addrtype = AF_INET;
8476 hp->h_addr_list = (char **) calloc(2, sizeof(char *));
8477 hp->h_addr_list[0] = (char *) malloc(4);
8478 hp->h_addr_list[0][0] = b0;
8479 hp->h_addr_list[0][1] = b1;
8480 hp->h_addr_list[0][2] = b2;
8481 hp->h_addr_list[0][3] = b3;
8486 sa.sin_family = hp->h_addrtype;
8487 uport = (unsigned short) atoi(port);
8488 sa.sin_port = htons(uport);
8489 memcpy((char *) &sa.sin_addr, hp->h_addr, hp->h_length);
8491 if (connect(s, (struct sockaddr *) &sa,
8492 sizeof(struct sockaddr_in)) < 0) {
8496 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8503 #endif /* !OMIT_SOCKETS */
8508 int OpenCommPort(name, pr)
8515 fd = open(name, 2, 0);
8516 if (fd < 0) return errno;
8518 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8528 int OpenLoopback(pr)
8534 SetUpChildIO(to, from);
8536 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8539 cp->fdFrom = to[0]; /* note not from[0]; we are doing a loopback */
8546 int OpenRcmd(host, user, cmd, pr)
8547 char *host, *user, *cmd;
8550 DisplayFatalError(_("internal rcmd not implemented for Unix"), 0, 1);
8554 #define INPUT_SOURCE_BUF_SIZE 8192
8563 char buf[INPUT_SOURCE_BUF_SIZE];
8568 DoInputCallback(closure, source, xid)
8573 InputSource *is = (InputSource *) closure;
8578 if (is->lineByLine) {
8579 count = read(is->fd, is->unused,
8580 INPUT_SOURCE_BUF_SIZE - (is->unused - is->buf));
8582 (is->func)(is, is->closure, is->buf, count, count ? errno : 0);
8585 is->unused += count;
8587 while (p < is->unused) {
8588 q = memchr(p, '\n', is->unused - p);
8589 if (q == NULL) break;
8591 (is->func)(is, is->closure, p, q - p, 0);
8595 while (p < is->unused) {
8600 count = read(is->fd, is->buf, INPUT_SOURCE_BUF_SIZE);
8605 (is->func)(is, is->closure, is->buf, count, error);
8609 InputSourceRef AddInputSource(pr, lineByLine, func, closure)
8616 ChildProc *cp = (ChildProc *) pr;
8618 is = (InputSource *) calloc(1, sizeof(InputSource));
8619 is->lineByLine = lineByLine;
8623 is->fd = fileno(stdin);
8625 is->kind = cp->kind;
8626 is->fd = cp->fdFrom;
8629 is->unused = is->buf;
8632 is->xid = XtAppAddInput(appContext, is->fd,
8633 (XtPointer) (XtInputReadMask),
8634 (XtInputCallbackProc) DoInputCallback,
8636 is->closure = closure;
8637 return (InputSourceRef) is;
8641 RemoveInputSource(isr)
8644 InputSource *is = (InputSource *) isr;
8646 if (is->xid == 0) return;
8647 XtRemoveInput(is->xid);
8651 int OutputToProcess(pr, message, count, outError)
8657 ChildProc *cp = (ChildProc *) pr;
8661 outCount = fwrite(message, 1, count, stdout);
8663 outCount = write(cp->fdTo, message, count);
8673 /* Output message to process, with "ms" milliseconds of delay
8674 between each character. This is needed when sending the logon
8675 script to ICC, which for some reason doesn't like the
8676 instantaneous send. */
8677 int OutputToProcessDelayed(pr, message, count, outError, msdelay)
8684 ChildProc *cp = (ChildProc *) pr;
8689 r = write(cp->fdTo, message++, 1);
8702 /**** Animation code by Hugh Fisher, DCS, ANU.
8704 Known problem: if a window overlapping the board is
8705 moved away while a piece is being animated underneath,
8706 the newly exposed area won't be updated properly.
8707 I can live with this.
8709 Known problem: if you look carefully at the animation
8710 of pieces in mono mode, they are being drawn as solid
8711 shapes without interior detail while moving. Fixing
8712 this would be a major complication for minimal return.
8715 /* Masks for XPM pieces. Black and white pieces can have
8716 different shapes, but in the interest of retaining my
8717 sanity pieces must have the same outline on both light
8718 and dark squares, and all pieces must use the same
8719 background square colors/images. */
8721 static int xpmDone = 0;
8724 CreateAnimMasks (pieceDepth)
8731 unsigned long plane;
8734 /* Need a bitmap just to get a GC with right depth */
8735 buf = XCreatePixmap(xDisplay, xBoardWindow,
8737 values.foreground = 1;
8738 values.background = 0;
8739 /* Don't use XtGetGC, not read only */
8740 maskGC = XCreateGC(xDisplay, buf,
8741 GCForeground | GCBackground, &values);
8742 XFreePixmap(xDisplay, buf);
8744 buf = XCreatePixmap(xDisplay, xBoardWindow,
8745 squareSize, squareSize, pieceDepth);
8746 values.foreground = XBlackPixel(xDisplay, xScreen);
8747 values.background = XWhitePixel(xDisplay, xScreen);
8748 bufGC = XCreateGC(xDisplay, buf,
8749 GCForeground | GCBackground, &values);
8751 for (piece = WhitePawn; piece <= BlackKing; piece++) {
8752 /* Begin with empty mask */
8753 if(!xpmDone) // [HGM] pieces: keep using existing
8754 xpmMask[piece] = XCreatePixmap(xDisplay, xBoardWindow,
8755 squareSize, squareSize, 1);
8756 XSetFunction(xDisplay, maskGC, GXclear);
8757 XFillRectangle(xDisplay, xpmMask[piece], maskGC,
8758 0, 0, squareSize, squareSize);
8760 /* Take a copy of the piece */
8765 XSetFunction(xDisplay, bufGC, GXcopy);
8766 XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % (int)BlackPawn],
8768 0, 0, squareSize, squareSize, 0, 0);
8770 /* XOR the background (light) over the piece */
8771 XSetFunction(xDisplay, bufGC, GXxor);
8773 XCopyArea(xDisplay, xpmLightSquare, buf, bufGC,
8774 0, 0, squareSize, squareSize, 0, 0);
8776 XSetForeground(xDisplay, bufGC, lightSquareColor);
8777 XFillRectangle(xDisplay, buf, bufGC, 0, 0, squareSize, squareSize);
8780 /* We now have an inverted piece image with the background
8781 erased. Construct mask by just selecting all the non-zero
8782 pixels - no need to reconstruct the original image. */
8783 XSetFunction(xDisplay, maskGC, GXor);
8785 /* Might be quicker to download an XImage and create bitmap
8786 data from it rather than this N copies per piece, but it
8787 only takes a fraction of a second and there is a much
8788 longer delay for loading the pieces. */
8789 for (n = 0; n < pieceDepth; n ++) {
8790 XCopyPlane(xDisplay, buf, xpmMask[piece], maskGC,
8791 0, 0, squareSize, squareSize,
8797 XFreePixmap(xDisplay, buf);
8798 XFreeGC(xDisplay, bufGC);
8799 XFreeGC(xDisplay, maskGC);
8803 InitAnimState (anim, info)
8805 XWindowAttributes * info;
8810 /* Each buffer is square size, same depth as window */
8811 anim->saveBuf = XCreatePixmap(xDisplay, xBoardWindow,
8812 squareSize, squareSize, info->depth);
8813 anim->newBuf = XCreatePixmap(xDisplay, xBoardWindow,
8814 squareSize, squareSize, info->depth);
8816 /* Create a plain GC for blitting */
8817 mask = GCForeground | GCBackground | GCFunction |
8818 GCPlaneMask | GCGraphicsExposures;
8819 values.foreground = XBlackPixel(xDisplay, xScreen);
8820 values.background = XWhitePixel(xDisplay, xScreen);
8821 values.function = GXcopy;
8822 values.plane_mask = AllPlanes;
8823 values.graphics_exposures = False;
8824 anim->blitGC = XCreateGC(xDisplay, xBoardWindow, mask, &values);
8826 /* Piece will be copied from an existing context at
8827 the start of each new animation/drag. */
8828 anim->pieceGC = XCreateGC(xDisplay, xBoardWindow, 0, &values);
8830 /* Outline will be a read-only copy of an existing */
8831 anim->outlineGC = None;
8837 static VariantClass old = (VariantClass) -1; // [HGM] pieces: redo every time variant changes
8838 XWindowAttributes info;
8840 if (xpmDone && gameInfo.variant == old) return;
8841 if(xpmDone) old = gameInfo.variant; // first time pieces might not be created yet
8842 XGetWindowAttributes(xDisplay, xBoardWindow, &info);
8844 InitAnimState(&game, &info);
8845 InitAnimState(&player, &info);
8847 /* For XPM pieces, we need bitmaps to use as masks. */
8849 CreateAnimMasks(info.depth);
8855 static Boolean frameWaiting;
8857 static RETSIGTYPE FrameAlarm (sig)
8860 frameWaiting = False;
8861 /* In case System-V style signals. Needed?? */
8862 signal(SIGALRM, FrameAlarm);
8869 struct itimerval delay;
8871 XSync(xDisplay, False);
8874 frameWaiting = True;
8875 signal(SIGALRM, FrameAlarm);
8876 delay.it_interval.tv_sec =
8877 delay.it_value.tv_sec = time / 1000;
8878 delay.it_interval.tv_usec =
8879 delay.it_value.tv_usec = (time % 1000) * 1000;
8880 setitimer(ITIMER_REAL, &delay, NULL);
8882 /* Ugh -- busy-wait! --tpm */
8883 while (frameWaiting);
8885 while (frameWaiting) pause();
8887 delay.it_interval.tv_sec = delay.it_value.tv_sec = 0;
8888 delay.it_interval.tv_usec = delay.it_value.tv_usec = 0;
8889 setitimer(ITIMER_REAL, &delay, NULL);
8899 XSync(xDisplay, False);
8901 usleep(time * 1000);
8906 /* Convert board position to corner of screen rect and color */
8909 ScreenSquare(column, row, pt, color)
8910 int column; int row; XPoint * pt; int * color;
8913 pt->x = lineGap + ((BOARD_WIDTH-1)-column) * (squareSize + lineGap);
8914 pt->y = lineGap + row * (squareSize + lineGap);
8916 pt->x = lineGap + column * (squareSize + lineGap);
8917 pt->y = lineGap + ((BOARD_HEIGHT-1)-row) * (squareSize + lineGap);
8919 *color = SquareColor(row, column);
8922 /* Convert window coords to square */
8925 BoardSquare(x, y, column, row)
8926 int x; int y; int * column; int * row;
8928 *column = EventToSquare(x, BOARD_WIDTH);
8929 if (flipView && *column >= 0)
8930 *column = BOARD_WIDTH - 1 - *column;
8931 *row = EventToSquare(y, BOARD_HEIGHT);
8932 if (!flipView && *row >= 0)
8933 *row = BOARD_HEIGHT - 1 - *row;
8938 #undef Max /* just in case */
8940 #define Max(a, b) ((a) > (b) ? (a) : (b))
8941 #define Min(a, b) ((a) < (b) ? (a) : (b))
8944 SetRect(rect, x, y, width, height)
8945 XRectangle * rect; int x; int y; int width; int height;
8949 rect->width = width;
8950 rect->height = height;
8953 /* Test if two frames overlap. If they do, return
8954 intersection rect within old and location of
8955 that rect within new. */
8958 Intersect(old, new, size, area, pt)
8959 XPoint * old; XPoint * new;
8960 int size; XRectangle * area; XPoint * pt;
8962 if (old->x > new->x + size || new->x > old->x + size ||
8963 old->y > new->y + size || new->y > old->y + size) {
8966 SetRect(area, Max(new->x - old->x, 0), Max(new->y - old->y, 0),
8967 size - abs(old->x - new->x), size - abs(old->y - new->y));
8968 pt->x = Max(old->x - new->x, 0);
8969 pt->y = Max(old->y - new->y, 0);
8974 /* For two overlapping frames, return the rect(s)
8975 in the old that do not intersect with the new. */
8978 CalcUpdateRects(old, new, size, update, nUpdates)
8979 XPoint * old; XPoint * new; int size;
8980 XRectangle update[]; int * nUpdates;
8984 /* If old = new (shouldn't happen) then nothing to draw */
8985 if (old->x == new->x && old->y == new->y) {
8989 /* Work out what bits overlap. Since we know the rects
8990 are the same size we don't need a full intersect calc. */
8992 /* Top or bottom edge? */
8993 if (new->y > old->y) {
8994 SetRect(&(update[count]), old->x, old->y, size, new->y - old->y);
8996 } else if (old->y > new->y) {
8997 SetRect(&(update[count]), old->x, old->y + size - (old->y - new->y),
8998 size, old->y - new->y);
9001 /* Left or right edge - don't overlap any update calculated above. */
9002 if (new->x > old->x) {
9003 SetRect(&(update[count]), old->x, Max(new->y, old->y),
9004 new->x - old->x, size - abs(new->y - old->y));
9006 } else if (old->x > new->x) {
9007 SetRect(&(update[count]), new->x + size, Max(new->y, old->y),
9008 old->x - new->x, size - abs(new->y - old->y));
9015 /* Generate a series of frame coords from start->mid->finish.
9016 The movement rate doubles until the half way point is
9017 reached, then halves back down to the final destination,
9018 which gives a nice slow in/out effect. The algorithmn
9019 may seem to generate too many intermediates for short
9020 moves, but remember that the purpose is to attract the
9021 viewers attention to the piece about to be moved and
9022 then to where it ends up. Too few frames would be less
9026 Tween(start, mid, finish, factor, frames, nFrames)
9027 XPoint * start; XPoint * mid;
9028 XPoint * finish; int factor;
9029 XPoint frames[]; int * nFrames;
9031 int fraction, n, count;
9035 /* Slow in, stepping 1/16th, then 1/8th, ... */
9037 for (n = 0; n < factor; n++)
9039 for (n = 0; n < factor; n++) {
9040 frames[count].x = start->x + (mid->x - start->x) / fraction;
9041 frames[count].y = start->y + (mid->y - start->y) / fraction;
9043 fraction = fraction / 2;
9047 frames[count] = *mid;
9050 /* Slow out, stepping 1/2, then 1/4, ... */
9052 for (n = 0; n < factor; n++) {
9053 frames[count].x = finish->x - (finish->x - mid->x) / fraction;
9054 frames[count].y = finish->y - (finish->y - mid->y) / fraction;
9056 fraction = fraction * 2;
9061 /* Draw a piece on the screen without disturbing what's there */
9064 SelectGCMask(piece, clip, outline, mask)
9065 ChessSquare piece; GC * clip; GC * outline; Pixmap * mask;
9069 /* Bitmap for piece being moved. */
9070 if (appData.monoMode) {
9071 *mask = *pieceToSolid(piece);
9072 } else if (useImages) {
9074 *mask = xpmMask[piece];
9076 *mask = ximMaskPm[piece];
9079 *mask = *pieceToSolid(piece);
9082 /* GC for piece being moved. Square color doesn't matter, but
9083 since it gets modified we make a copy of the original. */
9085 if (appData.monoMode)
9090 if (appData.monoMode)
9095 XCopyGC(xDisplay, source, 0xFFFFFFFF, *clip);
9097 /* Outline only used in mono mode and is not modified */
9099 *outline = bwPieceGC;
9101 *outline = wbPieceGC;
9105 OverlayPiece(piece, clip, outline, dest)
9106 ChessSquare piece; GC clip; GC outline; Drawable dest;
9111 /* Draw solid rectangle which will be clipped to shape of piece */
9112 XFillRectangle(xDisplay, dest, clip,
9113 0, 0, squareSize, squareSize);
9114 if (appData.monoMode)
9115 /* Also draw outline in contrasting color for black
9116 on black / white on white cases */
9117 XCopyPlane(xDisplay, *pieceToOutline(piece), dest, outline,
9118 0, 0, squareSize, squareSize, 0, 0, 1);
9120 /* Copy the piece */
9125 XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
9127 0, 0, squareSize, squareSize,
9132 /* Animate the movement of a single piece */
9135 BeginAnimation(anim, piece, startColor, start)
9143 /* The old buffer is initialised with the start square (empty) */
9144 BlankSquare(0, 0, startColor, EmptySquare, anim->saveBuf);
9145 anim->prevFrame = *start;
9147 /* The piece will be drawn using its own bitmap as a matte */
9148 SelectGCMask(piece, &anim->pieceGC, &anim->outlineGC, &mask);
9149 XSetClipMask(xDisplay, anim->pieceGC, mask);
9153 AnimationFrame(anim, frame, piece)
9158 XRectangle updates[4];
9163 /* Save what we are about to draw into the new buffer */
9164 XCopyArea(xDisplay, xBoardWindow, anim->newBuf, anim->blitGC,
9165 frame->x, frame->y, squareSize, squareSize,
9168 /* Erase bits of the previous frame */
9169 if (Intersect(&anim->prevFrame, frame, squareSize, &overlap, &pt)) {
9170 /* Where the new frame overlapped the previous,
9171 the contents in newBuf are wrong. */
9172 XCopyArea(xDisplay, anim->saveBuf, anim->newBuf, anim->blitGC,
9173 overlap.x, overlap.y,
9174 overlap.width, overlap.height,
9176 /* Repaint the areas in the old that don't overlap new */
9177 CalcUpdateRects(&anim->prevFrame, frame, squareSize, updates, &count);
9178 for (i = 0; i < count; i++)
9179 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9180 updates[i].x - anim->prevFrame.x,
9181 updates[i].y - anim->prevFrame.y,
9182 updates[i].width, updates[i].height,
9183 updates[i].x, updates[i].y);
9185 /* Easy when no overlap */
9186 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9187 0, 0, squareSize, squareSize,
9188 anim->prevFrame.x, anim->prevFrame.y);
9191 /* Save this frame for next time round */
9192 XCopyArea(xDisplay, anim->newBuf, anim->saveBuf, anim->blitGC,
9193 0, 0, squareSize, squareSize,
9195 anim->prevFrame = *frame;
9197 /* Draw piece over original screen contents, not current,
9198 and copy entire rect. Wipes out overlapping piece images. */
9199 OverlayPiece(piece, anim->pieceGC, anim->outlineGC, anim->newBuf);
9200 XCopyArea(xDisplay, anim->newBuf, xBoardWindow, anim->blitGC,
9201 0, 0, squareSize, squareSize,
9202 frame->x, frame->y);
9206 EndAnimation (anim, finish)
9210 XRectangle updates[4];
9215 /* The main code will redraw the final square, so we
9216 only need to erase the bits that don't overlap. */
9217 if (Intersect(&anim->prevFrame, finish, squareSize, &overlap, &pt)) {
9218 CalcUpdateRects(&anim->prevFrame, finish, squareSize, updates, &count);
9219 for (i = 0; i < count; i++)
9220 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9221 updates[i].x - anim->prevFrame.x,
9222 updates[i].y - anim->prevFrame.y,
9223 updates[i].width, updates[i].height,
9224 updates[i].x, updates[i].y);
9226 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9227 0, 0, squareSize, squareSize,
9228 anim->prevFrame.x, anim->prevFrame.y);
9233 FrameSequence(anim, piece, startColor, start, finish, frames, nFrames)
9235 ChessSquare piece; int startColor;
9236 XPoint * start; XPoint * finish;
9237 XPoint frames[]; int nFrames;
9241 BeginAnimation(anim, piece, startColor, start);
9242 for (n = 0; n < nFrames; n++) {
9243 AnimationFrame(anim, &(frames[n]), piece);
9244 FrameDelay(appData.animSpeed);
9246 EndAnimation(anim, finish);
9249 /* Main control logic for deciding what to animate and how */
9252 AnimateMove(board, fromX, fromY, toX, toY)
9261 XPoint start, finish, mid;
9262 XPoint frames[kFactor * 2 + 1];
9263 int nFrames, startColor, endColor;
9265 /* Are we animating? */
9266 if (!appData.animate || appData.blindfold)
9269 if(board[toY][toX] == WhiteRook && board[fromY][fromX] == WhiteKing ||
9270 board[toY][toX] == BlackRook && board[fromY][fromX] == BlackKing)
9271 return; // [HGM] FRC: no animtion of FRC castlings, as to-square is not true to-square
9273 if (fromY < 0 || fromX < 0 || toX < 0 || toY < 0) return;
9274 piece = board[fromY][fromX];
9275 if (piece >= EmptySquare) return;
9280 hop = (piece == WhiteKnight || piece == BlackKnight);
9283 if (appData.debugMode) {
9284 fprintf(debugFP, hop ? _("AnimateMove: piece %d hops from %d,%d to %d,%d \n") :
9285 _("AnimateMove: piece %d slides from %d,%d to %d,%d \n"),
9286 piece, fromX, fromY, toX, toY); }
9288 ScreenSquare(fromX, fromY, &start, &startColor);
9289 ScreenSquare(toX, toY, &finish, &endColor);
9292 /* Knight: make diagonal movement then straight */
9293 if (abs(toY - fromY) < abs(toX - fromX)) {
9294 mid.x = start.x + (finish.x - start.x) / 2;
9298 mid.y = start.y + (finish.y - start.y) / 2;
9301 mid.x = start.x + (finish.x - start.x) / 2;
9302 mid.y = start.y + (finish.y - start.y) / 2;
9305 /* Don't use as many frames for very short moves */
9306 if (abs(toY - fromY) + abs(toX - fromX) <= 2)
9307 Tween(&start, &mid, &finish, kFactor - 1, frames, &nFrames);
9309 Tween(&start, &mid, &finish, kFactor, frames, &nFrames);
9310 FrameSequence(&game, piece, startColor, &start, &finish, frames, nFrames);
9312 /* Be sure end square is redrawn */
9313 damage[toY][toX] = True;
9317 DragPieceBegin(x, y)
9320 int boardX, boardY, color;
9323 /* Are we animating? */
9324 if (!appData.animateDragging || appData.blindfold)
9327 /* Figure out which square we start in and the
9328 mouse position relative to top left corner. */
9329 BoardSquare(x, y, &boardX, &boardY);
9330 player.startBoardX = boardX;
9331 player.startBoardY = boardY;
9332 ScreenSquare(boardX, boardY, &corner, &color);
9333 player.startSquare = corner;
9334 player.startColor = color;
9336 /* Start from exactly where the piece is. This can be confusing
9337 if you start dragging far from the center of the square; most
9338 or all of the piece can be over a different square from the one
9339 the mouse pointer is in. */
9340 player.mouseDelta.x = x - corner.x;
9341 player.mouseDelta.y = y - corner.y;
9343 /* As soon as we start dragging, the piece will jump slightly to
9344 be centered over the mouse pointer. */
9345 player.mouseDelta.x = squareSize/2;
9346 player.mouseDelta.y = squareSize/2;
9348 /* Initialise animation */
9349 player.dragPiece = PieceForSquare(boardX, boardY);
9351 if (player.dragPiece >= 0 && player.dragPiece < EmptySquare) {
9352 player.dragActive = True;
9353 BeginAnimation(&player, player.dragPiece, color, &corner);
9354 /* Mark this square as needing to be redrawn. Note that
9355 we don't remove the piece though, since logically (ie
9356 as seen by opponent) the move hasn't been made yet. */
9357 if(boardX == BOARD_RGHT+1 && PieceForSquare(boardX-1, boardY) > 1 ||
9358 boardX == BOARD_LEFT-2 && PieceForSquare(boardX+1, boardY) > 1)
9359 XCopyArea(xDisplay, xBoardWindow, player.saveBuf, player.blitGC,
9360 corner.x, corner.y, squareSize, squareSize,
9361 0, 0); // [HGM] zh: unstack in stead of grab
9362 damage[boardY][boardX] = True;
9364 player.dragActive = False;
9374 /* Are we animating? */
9375 if (!appData.animateDragging || appData.blindfold)
9379 if (! player.dragActive)
9381 /* Move piece, maintaining same relative position
9382 of mouse within square */
9383 corner.x = x - player.mouseDelta.x;
9384 corner.y = y - player.mouseDelta.y;
9385 AnimationFrame(&player, &corner, player.dragPiece);
9387 if (appData.highlightDragging) {
9389 BoardSquare(x, y, &boardX, &boardY);
9390 SetHighlights(fromX, fromY, boardX, boardY);
9399 int boardX, boardY, color;
9402 /* Are we animating? */
9403 if (!appData.animateDragging || appData.blindfold)
9407 if (! player.dragActive)
9409 /* Last frame in sequence is square piece is
9410 placed on, which may not match mouse exactly. */
9411 BoardSquare(x, y, &boardX, &boardY);
9412 ScreenSquare(boardX, boardY, &corner, &color);
9413 EndAnimation(&player, &corner);
9415 /* Be sure end square is redrawn */
9416 damage[boardY][boardX] = True;
9418 /* This prevents weird things happening with fast successive
9419 clicks which on my Sun at least can cause motion events
9420 without corresponding press/release. */
9421 player.dragActive = False;
9424 /* Handle expose event while piece being dragged */
9429 if (!player.dragActive || appData.blindfold)
9432 /* What we're doing: logically, the move hasn't been made yet,
9433 so the piece is still in it's original square. But visually
9434 it's being dragged around the board. So we erase the square
9435 that the piece is on and draw it at the last known drag point. */
9436 BlankSquare(player.startSquare.x, player.startSquare.y,
9437 player.startColor, EmptySquare, xBoardWindow);
9438 AnimationFrame(&player, &player.prevFrame, player.dragPiece);
9439 damage[player.startBoardY][player.startBoardX] = TRUE;
9443 SetProgramStats( FrontEndProgramStats * stats )
9446 // [HGM] done, but perhaps backend should call this directly?
9447 EngineOutputUpdate( stats );