2 * xboard.c -- X front end for XBoard
3 * $Id: xboard.c,v 2.2 2003/11/06 07:22:14 mann Exp $
5 * Copyright 1991 by Digital Equipment Corporation, Maynard,
6 * Massachusetts. Enhancements Copyright
7 * 1992-2001,2002,2003,2004,2005,2006,2007,2008,2009 Free Software
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 xpmPieceBitmap[4][(int)BlackPawn]; /* LL, LD, DL, DD */
499 Pixmap xpmLightSquare, xpmDarkSquare, xpmJailSquare;
500 int useImages, useImageSqs;
501 XImage *ximPieceBitmap[4][(int)BlackPawn]; /* LL, LD, DL, DD */
502 Pixmap ximMaskPm[(int)BlackPawn]; /* clipmasks, used for XIM pieces */
503 XImage *ximLightSquare, *ximDarkSquare;
506 #define pieceToSolid(piece) &pieceBitmap[SOLID][((int)(piece)) % (int)BlackPawn]
507 #define pieceToOutline(piece) &pieceBitmap[OUTLINE][((int)(piece)) % (int)BlackPawn]
509 #define White(piece) ((int)(piece) < (int)BlackPawn)
511 /* Variables for doing smooth animation. This whole thing
512 would be much easier if the board was double-buffered,
513 but that would require a fairly major rewrite. */
518 GC blitGC, pieceGC, outlineGC;
519 XPoint startSquare, prevFrame, mouseDelta;
523 int startBoardX, startBoardY;
526 /* There can be two pieces being animated at once: a player
527 can begin dragging a piece before the remote opponent has moved. */
529 static AnimState game, player;
531 /* Bitmaps for use as masks when drawing XPM pieces.
532 Need one for each black and white piece. */
533 static Pixmap xpmMask[BlackKing + 1];
535 /* This magic number is the number of intermediate frames used
536 in each half of the animation. For short moves it's reduced
537 by 1. The total number of frames will be factor * 2 + 1. */
540 SizeDefaults sizeDefaults[] = SIZE_DEFAULTS;
542 MenuItem fileMenu[] = {
543 {N_("New Game"), ResetProc},
544 {N_("New Shuffle Game ..."), ShuffleMenuProc},
545 {N_("New Variant ..."), NewVariantProc}, // [HGM] variant: not functional yet
546 {"----", NothingProc},
547 {N_("Load Game"), LoadGameProc},
548 {N_("Load Next Game"), LoadNextGameProc},
549 {N_("Load Previous Game"), LoadPrevGameProc},
550 {N_("Reload Same Game"), ReloadGameProc},
551 {N_("Save Game"), SaveGameProc},
552 {"----", NothingProc},
553 {N_("Copy Game"), CopyGameProc},
554 {N_("Paste Game"), PasteGameProc},
555 {"----", NothingProc},
556 {N_("Load Position"), LoadPositionProc},
557 {N_("Load Next Position"), LoadNextPositionProc},
558 {N_("Load Previous Position"), LoadPrevPositionProc},
559 {N_("Reload Same Position"), ReloadPositionProc},
560 {N_("Save Position"), SavePositionProc},
561 {"----", NothingProc},
562 {N_("Copy Position"), CopyPositionProc},
563 {N_("Paste Position"), PastePositionProc},
564 {"----", NothingProc},
565 {N_("Mail Move"), MailMoveProc},
566 {N_("Reload CMail Message"), ReloadCmailMsgProc},
567 {"----", NothingProc},
568 {N_("Exit"), QuitProc},
572 MenuItem modeMenu[] = {
573 {N_("Machine White"), MachineWhiteProc},
574 {N_("Machine Black"), MachineBlackProc},
575 {N_("Two Machines"), TwoMachinesProc},
576 {N_("Analysis Mode"), AnalyzeModeProc},
577 {N_("Analyze File"), AnalyzeFileProc },
578 {N_("ICS Client"), IcsClientProc},
579 {N_("Edit Game"), EditGameProc},
580 {N_("Edit Position"), EditPositionProc},
581 {N_("Training"), TrainingProc},
582 {"----", NothingProc},
583 {N_("Show Engine Output"), EngineOutputProc},
584 {N_("Show Evaluation Graph"), NothingProc}, // [HGM] evalgr: not functional yet
585 {N_("Show Game List"), ShowGameListProc},
586 {"Show Move History", HistoryShowProc}, // [HGM] hist: activate 4.2.7 code
587 {"----", NothingProc},
588 {N_("Edit Tags"), EditTagsProc},
589 {N_("Edit Comment"), EditCommentProc},
590 {N_("ICS Input Box"), IcsInputBoxProc},
591 {N_("Pause"), PauseProc},
595 MenuItem actionMenu[] = {
596 {N_("Accept"), AcceptProc},
597 {N_("Decline"), DeclineProc},
598 {N_("Rematch"), RematchProc},
599 {"----", NothingProc},
600 {N_("Call Flag"), CallFlagProc},
601 {N_("Draw"), DrawProc},
602 {N_("Adjourn"), AdjournProc},
603 {N_("Abort"), AbortProc},
604 {N_("Resign"), ResignProc},
605 {"----", NothingProc},
606 {N_("Stop Observing"), StopObservingProc},
607 {N_("Stop Examining"), StopExaminingProc},
608 {"----", NothingProc},
609 {N_("Adjudicate to White"), AdjuWhiteProc},
610 {N_("Adjudicate to Black"), AdjuBlackProc},
611 {N_("Adjudicate Draw"), AdjuDrawProc},
615 MenuItem stepMenu[] = {
616 {N_("Backward"), BackwardProc},
617 {N_("Forward"), ForwardProc},
618 {N_("Back to Start"), ToStartProc},
619 {N_("Forward to End"), ToEndProc},
620 {N_("Revert"), RevertProc},
621 {N_("Truncate Game"), TruncateGameProc},
622 {"----", NothingProc},
623 {N_("Move Now"), MoveNowProc},
624 {N_("Retract Move"), RetractMoveProc},
628 MenuItem optionsMenu[] = {
629 {N_("Flip View"), FlipViewProc},
630 {"----", NothingProc},
631 {N_("Adjudications ..."), EngineMenuProc},
632 {N_("General Settings ..."), UciMenuProc},
633 {N_("Engine #1 Settings ..."), FirstSettingsProc},
634 {N_("Engine #2 Settings ..."), SecondSettingsProc},
635 {N_("Time Control ..."), TimeControlProc},
636 {"----", NothingProc},
637 {N_("Always Queen"), AlwaysQueenProc},
638 {N_("Animate Dragging"), AnimateDraggingProc},
639 {N_("Animate Moving"), AnimateMovingProc},
640 {N_("Auto Comment"), AutocommProc},
641 {N_("Auto Flag"), AutoflagProc},
642 {N_("Auto Flip View"), AutoflipProc},
643 {N_("Auto Observe"), AutobsProc},
644 {N_("Auto Raise Board"), AutoraiseProc},
645 {N_("Auto Save"), AutosaveProc},
646 {N_("Blindfold"), BlindfoldProc},
647 {N_("Flash Moves"), FlashMovesProc},
648 {N_("Get Move List"), GetMoveListProc},
650 {N_("Highlight Dragging"), HighlightDraggingProc},
652 {N_("Highlight Last Move"), HighlightLastMoveProc},
653 {N_("Move Sound"), MoveSoundProc},
654 {N_("ICS Alarm"), IcsAlarmProc},
655 {N_("Old Save Style"), OldSaveStyleProc},
656 {N_("Periodic Updates"), PeriodicUpdatesProc},
657 {N_("Ponder Next Move"), PonderNextMoveProc},
658 {N_("Popup Exit Message"), PopupExitMessageProc},
659 {N_("Popup Move Errors"), PopupMoveErrorsProc},
660 {N_("Premove"), PremoveProc},
661 {N_("Quiet Play"), QuietPlayProc},
662 {N_("Show Coords"), ShowCoordsProc},
663 {N_("Hide Thinking"), HideThinkingProc},
664 {N_("Test Legality"), TestLegalityProc},
668 MenuItem helpMenu[] = {
669 {N_("Info XBoard"), InfoProc},
670 {N_("Man XBoard"), ManProc},
671 {"----", NothingProc},
672 {N_("Hint"), HintProc},
673 {N_("Book"), BookProc},
674 {"----", NothingProc},
675 {N_("About XBoard"), AboutProc},
680 {N_("File"), fileMenu},
681 {N_("Mode"), modeMenu},
682 {N_("Action"), actionMenu},
683 {N_("Step"), stepMenu},
684 {N_("Options"), optionsMenu},
685 {N_("Help"), helpMenu},
689 #define PAUSE_BUTTON N_("P")
690 MenuItem buttonBar[] = {
693 {PAUSE_BUTTON, PauseProc},
699 #define PIECE_MENU_SIZE 18
700 String pieceMenuStrings[2][PIECE_MENU_SIZE] = {
701 { N_("White"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
702 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
703 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
704 N_("Empty square"), N_("Clear board") },
705 { N_("Black"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
706 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
707 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
708 N_("Empty square"), N_("Clear board") }
710 /* must be in same order as PieceMenuStrings! */
711 ChessSquare pieceMenuTranslation[2][PIECE_MENU_SIZE] = {
712 { WhitePlay, (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
713 WhiteRook, WhiteQueen, WhiteKing, (ChessSquare) 0, WhiteAlfil,
714 WhiteCannon, WhiteAngel, WhiteMarshall, (ChessSquare) 0,
715 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
716 { BlackPlay, (ChessSquare) 0, BlackPawn, BlackKnight, BlackBishop,
717 BlackRook, BlackQueen, BlackKing, (ChessSquare) 0, BlackAlfil,
718 BlackCannon, BlackAngel, BlackMarshall, (ChessSquare) 0,
719 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
722 #define DROP_MENU_SIZE 6
723 String dropMenuStrings[DROP_MENU_SIZE] = {
724 "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"), N_("Queen")
726 /* must be in same order as PieceMenuStrings! */
727 ChessSquare dropMenuTranslation[DROP_MENU_SIZE] = {
728 (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
729 WhiteRook, WhiteQueen
737 DropMenuEnables dmEnables[] = {
755 { XtNborderWidth, 0 },
756 { XtNdefaultDistance, 0 },
760 { XtNborderWidth, 0 },
761 { XtNresizable, (XtArgVal) True },
765 { XtNborderWidth, 0 },
771 { XtNjustify, (XtArgVal) XtJustifyRight },
772 { XtNlabel, (XtArgVal) "..." },
773 { XtNresizable, (XtArgVal) True },
774 { XtNresize, (XtArgVal) False }
777 Arg messageArgs[] = {
778 { XtNjustify, (XtArgVal) XtJustifyLeft },
779 { XtNlabel, (XtArgVal) "..." },
780 { XtNresizable, (XtArgVal) True },
781 { XtNresize, (XtArgVal) False }
785 { XtNborderWidth, 0 },
786 { XtNjustify, (XtArgVal) XtJustifyLeft }
789 XtResource clientResources[] = {
790 { "whitePieceColor", "whitePieceColor", XtRString, sizeof(String),
791 XtOffset(AppDataPtr, whitePieceColor), XtRString,
793 { "blackPieceColor", "blackPieceColor", XtRString, sizeof(String),
794 XtOffset(AppDataPtr, blackPieceColor), XtRString,
796 { "lightSquareColor", "lightSquareColor", XtRString,
797 sizeof(String), XtOffset(AppDataPtr, lightSquareColor),
798 XtRString, LIGHT_SQUARE_COLOR },
799 { "darkSquareColor", "darkSquareColor", XtRString, sizeof(String),
800 XtOffset(AppDataPtr, darkSquareColor), XtRString,
802 { "highlightSquareColor", "highlightSquareColor", XtRString,
803 sizeof(String), XtOffset(AppDataPtr, highlightSquareColor),
804 XtRString, HIGHLIGHT_SQUARE_COLOR },
805 { "premoveHighlightColor", "premoveHighlightColor", XtRString,
806 sizeof(String), XtOffset(AppDataPtr, premoveHighlightColor),
807 XtRString, PREMOVE_HIGHLIGHT_COLOR },
808 { "movesPerSession", "movesPerSession", XtRInt, sizeof(int),
809 XtOffset(AppDataPtr, movesPerSession), XtRImmediate,
810 (XtPointer) MOVES_PER_SESSION },
811 { "timeIncrement", "timeIncrement", XtRInt, sizeof(int),
812 XtOffset(AppDataPtr, timeIncrement), XtRImmediate,
813 (XtPointer) TIME_INCREMENT },
814 { "initString", "initString", XtRString, sizeof(String),
815 XtOffset(AppDataPtr, initString), XtRString, INIT_STRING },
816 { "secondInitString", "secondInitString", XtRString, sizeof(String),
817 XtOffset(AppDataPtr, secondInitString), XtRString, INIT_STRING },
818 { "firstComputerString", "firstComputerString", XtRString,
819 sizeof(String), XtOffset(AppDataPtr, firstComputerString), XtRString,
821 { "secondComputerString", "secondComputerString", XtRString,
822 sizeof(String), XtOffset(AppDataPtr, secondComputerString), XtRString,
824 { "firstChessProgram", "firstChessProgram", XtRString,
825 sizeof(String), XtOffset(AppDataPtr, firstChessProgram),
826 XtRString, FIRST_CHESS_PROGRAM },
827 { "secondChessProgram", "secondChessProgram", XtRString,
828 sizeof(String), XtOffset(AppDataPtr, secondChessProgram),
829 XtRString, SECOND_CHESS_PROGRAM },
830 { "firstPlaysBlack", "firstPlaysBlack", XtRBoolean,
831 sizeof(Boolean), XtOffset(AppDataPtr, firstPlaysBlack),
832 XtRImmediate, (XtPointer) False },
833 { "noChessProgram", "noChessProgram", XtRBoolean,
834 sizeof(Boolean), XtOffset(AppDataPtr, noChessProgram),
835 XtRImmediate, (XtPointer) False },
836 { "firstHost", "firstHost", XtRString, sizeof(String),
837 XtOffset(AppDataPtr, firstHost), XtRString, FIRST_HOST },
838 { "secondHost", "secondHost", XtRString, sizeof(String),
839 XtOffset(AppDataPtr, secondHost), XtRString, SECOND_HOST },
840 { "firstDirectory", "firstDirectory", XtRString, sizeof(String),
841 XtOffset(AppDataPtr, firstDirectory), XtRString, "." },
842 { "secondDirectory", "secondDirectory", XtRString, sizeof(String),
843 XtOffset(AppDataPtr, secondDirectory), XtRString, "." },
844 { "bitmapDirectory", "bitmapDirectory", XtRString,
845 sizeof(String), XtOffset(AppDataPtr, bitmapDirectory),
847 { "remoteShell", "remoteShell", XtRString, sizeof(String),
848 XtOffset(AppDataPtr, remoteShell), XtRString, REMOTE_SHELL },
849 { "remoteUser", "remoteUser", XtRString, sizeof(String),
850 XtOffset(AppDataPtr, remoteUser), XtRString, "" },
851 { "timeDelay", "timeDelay", XtRFloat, sizeof(float),
852 XtOffset(AppDataPtr, timeDelay), XtRString,
853 (XtPointer) TIME_DELAY_QUOTE },
854 { "timeControl", "timeControl", XtRString, sizeof(String),
855 XtOffset(AppDataPtr, timeControl), XtRString,
856 (XtPointer) TIME_CONTROL },
857 { "internetChessServerMode", "internetChessServerMode",
858 XtRBoolean, sizeof(Boolean),
859 XtOffset(AppDataPtr, icsActive), XtRImmediate,
861 { "internetChessServerHost", "internetChessServerHost",
862 XtRString, sizeof(String),
863 XtOffset(AppDataPtr, icsHost),
864 XtRString, (XtPointer) ICS_HOST },
865 { "internetChessServerPort", "internetChessServerPort",
866 XtRString, sizeof(String),
867 XtOffset(AppDataPtr, icsPort), XtRString,
868 (XtPointer) ICS_PORT },
869 { "internetChessServerCommPort", "internetChessServerCommPort",
870 XtRString, sizeof(String),
871 XtOffset(AppDataPtr, icsCommPort), XtRString,
873 { "internetChessServerLogonScript", "internetChessServerLogonScript",
874 XtRString, sizeof(String),
875 XtOffset(AppDataPtr, icsLogon), XtRString,
877 { "internetChessServerHelper", "internetChessServerHelper",
878 XtRString, sizeof(String),
879 XtOffset(AppDataPtr, icsHelper), XtRString, "" },
880 { "internetChessServerInputBox", "internetChessServerInputBox",
881 XtRBoolean, sizeof(Boolean),
882 XtOffset(AppDataPtr, icsInputBox), XtRImmediate,
884 { "icsAlarm", "icsAlarm",
885 XtRBoolean, sizeof(Boolean),
886 XtOffset(AppDataPtr, icsAlarm), XtRImmediate,
888 { "icsAlarmTime", "icsAlarmTime",
890 XtOffset(AppDataPtr, icsAlarmTime), XtRImmediate,
892 { "useTelnet", "useTelnet", XtRBoolean, sizeof(Boolean),
893 XtOffset(AppDataPtr, useTelnet), XtRImmediate,
895 { "telnetProgram", "telnetProgram", XtRString, sizeof(String),
896 XtOffset(AppDataPtr, telnetProgram), XtRString, TELNET_PROGRAM },
897 { "gateway", "gateway", XtRString, sizeof(String),
898 XtOffset(AppDataPtr, gateway), XtRString, "" },
899 { "loadGameFile", "loadGameFile", XtRString, sizeof(String),
900 XtOffset(AppDataPtr, loadGameFile), XtRString, "" },
901 { "loadGameIndex", "loadGameIndex",
903 XtOffset(AppDataPtr, loadGameIndex), XtRImmediate,
905 { "saveGameFile", "saveGameFile", XtRString, sizeof(String),
906 XtOffset(AppDataPtr, saveGameFile), XtRString, "" },
907 { "autoRaiseBoard", "autoRaiseBoard", XtRBoolean,
908 sizeof(Boolean), XtOffset(AppDataPtr, autoRaiseBoard),
909 XtRImmediate, (XtPointer) True },
910 { "autoSaveGames", "autoSaveGames", XtRBoolean,
911 sizeof(Boolean), XtOffset(AppDataPtr, autoSaveGames),
912 XtRImmediate, (XtPointer) False },
913 { "blindfold", "blindfold", XtRBoolean,
914 sizeof(Boolean), XtOffset(AppDataPtr, blindfold),
915 XtRImmediate, (XtPointer) False },
916 { "loadPositionFile", "loadPositionFile", XtRString,
917 sizeof(String), XtOffset(AppDataPtr, loadPositionFile),
919 { "loadPositionIndex", "loadPositionIndex",
921 XtOffset(AppDataPtr, loadPositionIndex), XtRImmediate,
923 { "savePositionFile", "savePositionFile", XtRString,
924 sizeof(String), XtOffset(AppDataPtr, savePositionFile),
926 { "matchMode", "matchMode", XtRBoolean, sizeof(Boolean),
927 XtOffset(AppDataPtr, matchMode), XtRImmediate, (XtPointer) False },
928 { "matchGames", "matchGames", XtRInt, sizeof(int),
929 XtOffset(AppDataPtr, matchGames), XtRImmediate,
931 { "monoMode", "monoMode", XtRBoolean, sizeof(Boolean),
932 XtOffset(AppDataPtr, monoMode), XtRImmediate,
934 { "debugMode", "debugMode", XtRBoolean, sizeof(Boolean),
935 XtOffset(AppDataPtr, debugMode), XtRImmediate,
937 { "clockMode", "clockMode", XtRBoolean, sizeof(Boolean),
938 XtOffset(AppDataPtr, clockMode), XtRImmediate,
940 { "boardSize", "boardSize", XtRString, sizeof(String),
941 XtOffset(AppDataPtr, boardSize), XtRString, "" },
942 { "searchTime", "searchTime", XtRString, sizeof(String),
943 XtOffset(AppDataPtr, searchTime), XtRString,
945 { "searchDepth", "searchDepth", XtRInt, sizeof(int),
946 XtOffset(AppDataPtr, searchDepth), XtRImmediate,
948 { "showCoords", "showCoords", XtRBoolean, sizeof(Boolean),
949 XtOffset(AppDataPtr, showCoords), XtRImmediate,
951 { "showJail", "showJail", XtRInt, sizeof(int),
952 XtOffset(AppDataPtr, showJail), XtRImmediate,
954 { "showThinking", "showThinking", XtRBoolean, sizeof(Boolean),
955 XtOffset(AppDataPtr, showThinking), XtRImmediate,
957 { "ponderNextMove", "ponderNextMove", XtRBoolean, sizeof(Boolean),
958 XtOffset(AppDataPtr, ponderNextMove), XtRImmediate,
960 { "periodicUpdates", "periodicUpdates", XtRBoolean, sizeof(Boolean),
961 XtOffset(AppDataPtr, periodicUpdates), XtRImmediate,
963 { "clockFont", "clockFont", XtRString, sizeof(String),
964 XtOffset(AppDataPtr, clockFont), XtRString, CLOCK_FONT },
965 { "coordFont", "coordFont", XtRString, sizeof(String),
966 XtOffset(AppDataPtr, coordFont), XtRString, COORD_FONT },
967 { "font", "font", XtRString, sizeof(String),
968 XtOffset(AppDataPtr, font), XtRString, DEFAULT_FONT },
969 { "ringBellAfterMoves", "ringBellAfterMoves",
970 XtRBoolean, sizeof(Boolean),
971 XtOffset(AppDataPtr, ringBellAfterMoves),
972 XtRImmediate, (XtPointer) False },
973 { "autoCallFlag", "autoCallFlag", XtRBoolean,
974 sizeof(Boolean), XtOffset(AppDataPtr, autoCallFlag),
975 XtRImmediate, (XtPointer) False },
976 { "autoFlipView", "autoFlipView", XtRBoolean,
977 sizeof(Boolean), XtOffset(AppDataPtr, autoFlipView),
978 XtRImmediate, (XtPointer) True },
979 { "autoObserve", "autoObserve", XtRBoolean,
980 sizeof(Boolean), XtOffset(AppDataPtr, autoObserve),
981 XtRImmediate, (XtPointer) False },
982 { "autoComment", "autoComment", XtRBoolean,
983 sizeof(Boolean), XtOffset(AppDataPtr, autoComment),
984 XtRImmediate, (XtPointer) False },
985 { "getMoveList", "getMoveList", XtRBoolean,
986 sizeof(Boolean), XtOffset(AppDataPtr, getMoveList),
987 XtRImmediate, (XtPointer) True },
989 { "highlightDragging", "highlightDragging", XtRBoolean,
990 sizeof(Boolean), XtOffset(AppDataPtr, highlightDragging),
991 XtRImmediate, (XtPointer) False },
993 { "highlightLastMove", "highlightLastMove", XtRBoolean,
994 sizeof(Boolean), XtOffset(AppDataPtr, highlightLastMove),
995 XtRImmediate, (XtPointer) False },
996 { "premove", "premove", XtRBoolean,
997 sizeof(Boolean), XtOffset(AppDataPtr, premove),
998 XtRImmediate, (XtPointer) True },
999 { "testLegality", "testLegality", XtRBoolean,
1000 sizeof(Boolean), XtOffset(AppDataPtr, testLegality),
1001 XtRImmediate, (XtPointer) True },
1002 { "flipView", "flipView", XtRBoolean,
1003 sizeof(Boolean), XtOffset(AppDataPtr, flipView),
1004 XtRImmediate, (XtPointer) False },
1005 { "cmail", "cmailGameName", XtRString, sizeof(String),
1006 XtOffset(AppDataPtr, cmailGameName), XtRString, "" },
1007 { "alwaysPromoteToQueen", "alwaysPromoteToQueen", XtRBoolean,
1008 sizeof(Boolean), XtOffset(AppDataPtr, alwaysPromoteToQueen),
1009 XtRImmediate, (XtPointer) False },
1010 { "oldSaveStyle", "oldSaveStyle", XtRBoolean,
1011 sizeof(Boolean), XtOffset(AppDataPtr, oldSaveStyle),
1012 XtRImmediate, (XtPointer) False },
1013 { "quietPlay", "quietPlay", XtRBoolean,
1014 sizeof(Boolean), XtOffset(AppDataPtr, quietPlay),
1015 XtRImmediate, (XtPointer) False },
1016 { "titleInWindow", "titleInWindow", XtRBoolean,
1017 sizeof(Boolean), XtOffset(AppDataPtr, titleInWindow),
1018 XtRImmediate, (XtPointer) False },
1019 { "localLineEditing", "localLineEditing", XtRBoolean,
1020 sizeof(Boolean), XtOffset(AppDataPtr, localLineEditing),
1021 XtRImmediate, (XtPointer) True }, /* not implemented, must be True */
1023 { "zippyTalk", "zippyTalk", XtRBoolean,
1024 sizeof(Boolean), XtOffset(AppDataPtr, zippyTalk),
1025 XtRImmediate, (XtPointer) ZIPPY_TALK },
1026 { "zippyPlay", "zippyPlay", XtRBoolean,
1027 sizeof(Boolean), XtOffset(AppDataPtr, zippyPlay),
1028 XtRImmediate, (XtPointer) ZIPPY_PLAY },
1029 { "zippyLines", "zippyLines", XtRString, sizeof(String),
1030 XtOffset(AppDataPtr, zippyLines), XtRString, ZIPPY_LINES },
1031 { "zippyPinhead", "zippyPinhead", XtRString, sizeof(String),
1032 XtOffset(AppDataPtr, zippyPinhead), XtRString, ZIPPY_PINHEAD },
1033 { "zippyPassword", "zippyPassword", XtRString, sizeof(String),
1034 XtOffset(AppDataPtr, zippyPassword), XtRString, ZIPPY_PASSWORD },
1035 { "zippyPassword2", "zippyPassword2", XtRString, sizeof(String),
1036 XtOffset(AppDataPtr, zippyPassword2), XtRString, ZIPPY_PASSWORD2 },
1037 { "zippyWrongPassword", "zippyWrongPassword", XtRString, sizeof(String),
1038 XtOffset(AppDataPtr, zippyWrongPassword), XtRString,
1039 ZIPPY_WRONG_PASSWORD },
1040 { "zippyAcceptOnly", "zippyAcceptOnly", XtRString, sizeof(String),
1041 XtOffset(AppDataPtr, zippyAcceptOnly), XtRString, ZIPPY_ACCEPT_ONLY },
1042 { "zippyUseI", "zippyUseI", XtRBoolean,
1043 sizeof(Boolean), XtOffset(AppDataPtr, zippyUseI),
1044 XtRImmediate, (XtPointer) ZIPPY_USE_I },
1045 { "zippyBughouse", "zippyBughouse", XtRInt,
1046 sizeof(int), XtOffset(AppDataPtr, zippyBughouse),
1047 XtRImmediate, (XtPointer) ZIPPY_BUGHOUSE },
1048 { "zippyNoplayCrafty", "zippyNoplayCrafty", XtRBoolean,
1049 sizeof(Boolean), XtOffset(AppDataPtr, zippyNoplayCrafty),
1050 XtRImmediate, (XtPointer) ZIPPY_NOPLAY_CRAFTY },
1051 { "zippyGameEnd", "zippyGameEnd", XtRString, sizeof(String),
1052 XtOffset(AppDataPtr, zippyGameEnd), XtRString, ZIPPY_GAME_END },
1053 { "zippyGameStart", "zippyGameStart", XtRString, sizeof(String),
1054 XtOffset(AppDataPtr, zippyGameStart), XtRString, ZIPPY_GAME_START },
1055 { "zippyAdjourn", "zippyAdjourn", XtRBoolean,
1056 sizeof(Boolean), XtOffset(AppDataPtr, zippyAdjourn),
1057 XtRImmediate, (XtPointer) ZIPPY_ADJOURN },
1058 { "zippyAbort", "zippyAbort", XtRBoolean,
1059 sizeof(Boolean), XtOffset(AppDataPtr, zippyAbort),
1060 XtRImmediate, (XtPointer) ZIPPY_ABORT },
1061 { "zippyVariants", "zippyVariants", XtRString, sizeof(String),
1062 XtOffset(AppDataPtr, zippyVariants), XtRString, ZIPPY_VARIANTS },
1063 { "zippyMaxGames", "zippyMaxGames", XtRInt, sizeof(int),
1064 XtOffset(AppDataPtr, zippyMaxGames), XtRImmediate,
1065 (XtPointer) ZIPPY_MAX_GAMES },
1066 { "zippyReplayTimeout", "zippyReplayTimeout", XtRInt, sizeof(int),
1067 XtOffset(AppDataPtr, zippyReplayTimeout), XtRImmediate,
1068 (XtPointer) ZIPPY_REPLAY_TIMEOUT },
1069 { "zippyShortGame", "zippyShortGame", XtRInt, sizeof(int),
1070 XtOffset(AppDataPtr, zippyShortGame), XtRImmediate,
1073 { "flashCount", "flashCount", XtRInt, sizeof(int),
1074 XtOffset(AppDataPtr, flashCount), XtRImmediate,
1075 (XtPointer) FLASH_COUNT },
1076 { "flashRate", "flashRate", XtRInt, sizeof(int),
1077 XtOffset(AppDataPtr, flashRate), XtRImmediate,
1078 (XtPointer) FLASH_RATE },
1079 { "pixmapDirectory", "pixmapDirectory", XtRString,
1080 sizeof(String), XtOffset(AppDataPtr, pixmapDirectory),
1082 { "msLoginDelay", "msLoginDelay", XtRInt, sizeof(int),
1083 XtOffset(AppDataPtr, msLoginDelay), XtRImmediate,
1084 (XtPointer) MS_LOGIN_DELAY },
1085 { "colorizeMessages", "colorizeMessages", XtRBoolean,
1086 sizeof(Boolean), XtOffset(AppDataPtr, colorize),
1087 XtRImmediate, (XtPointer) False },
1088 { "colorShout", "colorShout", XtRString,
1089 sizeof(String), XtOffset(AppDataPtr, colorShout),
1090 XtRString, COLOR_SHOUT },
1091 { "colorSShout", "colorSShout", XtRString,
1092 sizeof(String), XtOffset(AppDataPtr, colorSShout),
1093 XtRString, COLOR_SSHOUT },
1094 { "colorChannel1", "colorChannel1", XtRString,
1095 sizeof(String), XtOffset(AppDataPtr, colorChannel1),
1096 XtRString, COLOR_CHANNEL1 },
1097 { "colorChannel", "colorChannel", XtRString,
1098 sizeof(String), XtOffset(AppDataPtr, colorChannel),
1099 XtRString, COLOR_CHANNEL },
1100 { "colorKibitz", "colorKibitz", XtRString,
1101 sizeof(String), XtOffset(AppDataPtr, colorKibitz),
1102 XtRString, COLOR_KIBITZ },
1103 { "colorTell", "colorTell", XtRString,
1104 sizeof(String), XtOffset(AppDataPtr, colorTell),
1105 XtRString, COLOR_TELL },
1106 { "colorChallenge", "colorChallenge", XtRString,
1107 sizeof(String), XtOffset(AppDataPtr, colorChallenge),
1108 XtRString, COLOR_CHALLENGE },
1109 { "colorRequest", "colorRequest", XtRString,
1110 sizeof(String), XtOffset(AppDataPtr, colorRequest),
1111 XtRString, COLOR_REQUEST },
1112 { "colorSeek", "colorSeek", XtRString,
1113 sizeof(String), XtOffset(AppDataPtr, colorSeek),
1114 XtRString, COLOR_SEEK },
1115 { "colorNormal", "colorNormal", XtRString,
1116 sizeof(String), XtOffset(AppDataPtr, colorNormal),
1117 XtRString, COLOR_NORMAL },
1118 { "soundProgram", "soundProgram", XtRString,
1119 sizeof(String), XtOffset(AppDataPtr, soundProgram),
1120 XtRString, "play" },
1121 { "soundShout", "soundShout", XtRString,
1122 sizeof(String), XtOffset(AppDataPtr, soundShout),
1124 { "soundSShout", "soundSShout", XtRString,
1125 sizeof(String), XtOffset(AppDataPtr, soundSShout),
1127 { "soundChannel1", "soundChannel1", XtRString,
1128 sizeof(String), XtOffset(AppDataPtr, soundChannel1),
1130 { "soundChannel", "soundChannel", XtRString,
1131 sizeof(String), XtOffset(AppDataPtr, soundChannel),
1133 { "soundKibitz", "soundKibitz", XtRString,
1134 sizeof(String), XtOffset(AppDataPtr, soundKibitz),
1136 { "soundTell", "soundTell", XtRString,
1137 sizeof(String), XtOffset(AppDataPtr, soundTell),
1139 { "soundChallenge", "soundChallenge", XtRString,
1140 sizeof(String), XtOffset(AppDataPtr, soundChallenge),
1142 { "soundRequest", "soundRequest", XtRString,
1143 sizeof(String), XtOffset(AppDataPtr, soundRequest),
1145 { "soundSeek", "soundSeek", XtRString,
1146 sizeof(String), XtOffset(AppDataPtr, soundSeek),
1148 { "soundMove", "soundMove", XtRString,
1149 sizeof(String), XtOffset(AppDataPtr, soundMove),
1151 { "soundIcsWin", "soundIcsWin", XtRString,
1152 sizeof(String), XtOffset(AppDataPtr, soundIcsWin),
1154 { "soundIcsLoss", "soundIcsLoss", XtRString,
1155 sizeof(String), XtOffset(AppDataPtr, soundIcsLoss),
1157 { "soundIcsDraw", "soundIcsDraw", XtRString,
1158 sizeof(String), XtOffset(AppDataPtr, soundIcsDraw),
1160 { "soundIcsUnfinished", "soundIcsUnfinished", XtRString,
1161 sizeof(String), XtOffset(AppDataPtr, soundIcsUnfinished),
1163 { "soundIcsAlarm", "soundIcsAlarm", XtRString,
1164 sizeof(String), XtOffset(AppDataPtr, soundIcsAlarm),
1166 { "reuseFirst", "reuseFirst", XtRBoolean,
1167 sizeof(Boolean), XtOffset(AppDataPtr, reuseFirst),
1168 XtRImmediate, (XtPointer) True },
1169 { "reuseSecond", "reuseSecond", XtRBoolean,
1170 sizeof(Boolean), XtOffset(AppDataPtr, reuseSecond),
1171 XtRImmediate, (XtPointer) True },
1172 { "animateDragging", "animateDragging", XtRBoolean,
1173 sizeof(Boolean), XtOffset(AppDataPtr, animateDragging),
1174 XtRImmediate, (XtPointer) True },
1175 { "animateMoving", "animateMoving", XtRBoolean,
1176 sizeof(Boolean), XtOffset(AppDataPtr, animate),
1177 XtRImmediate, (XtPointer) True },
1178 { "animateSpeed", "animateSpeed", XtRInt,
1179 sizeof(int), XtOffset(AppDataPtr, animSpeed),
1180 XtRImmediate, (XtPointer)10 },
1181 { "popupExitMessage", "popupExitMessage", XtRBoolean,
1182 sizeof(Boolean), XtOffset(AppDataPtr, popupExitMessage),
1183 XtRImmediate, (XtPointer) True },
1184 { "popupMoveErrors", "popupMoveErrors", XtRBoolean,
1185 sizeof(Boolean), XtOffset(AppDataPtr, popupMoveErrors),
1186 XtRImmediate, (XtPointer) False },
1187 { "fontSizeTolerance", "fontSizeTolerance", XtRInt,
1188 sizeof(int), XtOffset(AppDataPtr, fontSizeTolerance),
1189 XtRImmediate, (XtPointer)4 },
1190 { "initialMode", "initialMode", XtRString,
1191 sizeof(String), XtOffset(AppDataPtr, initialMode),
1192 XtRImmediate, (XtPointer) "" },
1193 { "variant", "variant", XtRString,
1194 sizeof(String), XtOffset(AppDataPtr, variant),
1195 XtRImmediate, (XtPointer) "normal" },
1196 { "firstProtocolVersion", "firstProtocolVersion", XtRInt,
1197 sizeof(int), XtOffset(AppDataPtr, firstProtocolVersion),
1198 XtRImmediate, (XtPointer)PROTOVER },
1199 { "secondProtocolVersion", "secondProtocolVersion", XtRInt,
1200 sizeof(int), XtOffset(AppDataPtr, secondProtocolVersion),
1201 XtRImmediate, (XtPointer)PROTOVER },
1202 { "showButtonBar", "showButtonBar", XtRBoolean,
1203 sizeof(Boolean), XtOffset(AppDataPtr, showButtonBar),
1204 XtRImmediate, (XtPointer) True },
1205 { "lowTimeWarningColor", "lowTimeWarningColor", XtRString,
1206 sizeof(String), XtOffset(AppDataPtr, lowTimeWarningColor),
1207 XtRString, COLOR_LOWTIMEWARNING },
1208 { "lowTimeWarning", "lowTimeWarning", XtRBoolean,
1209 sizeof(Boolean), XtOffset(AppDataPtr, lowTimeWarning),
1210 XtRImmediate, (XtPointer) False },
1211 {"icsEngineAnalyze", "icsEngineAnalyze", XtRBoolean, /* [DM] icsEngineAnalyze */
1212 sizeof(Boolean), XtOffset(AppDataPtr, icsEngineAnalyze),
1213 XtRImmediate, (XtPointer) False },
1214 { "firstScoreAbs", "firstScoreAbs", XtRBoolean,
1215 sizeof(Boolean), XtOffset(AppDataPtr, firstScoreIsAbsolute),
1216 XtRImmediate, (XtPointer) False },
1217 { "secondScoreAbs", "secondScoreAbs", XtRBoolean,
1218 sizeof(Boolean), XtOffset(AppDataPtr, secondScoreIsAbsolute),
1219 XtRImmediate, (XtPointer) False },
1220 { "pgnExtendedInfo", "pgnExtendedInfo", XtRBoolean,
1221 sizeof(Boolean), XtOffset(AppDataPtr, saveExtendedInfoInPGN),
1222 XtRImmediate, (XtPointer) False },
1223 { "hideThinkingFromHuman", "hideThinkingFromHuman", XtRBoolean,
1224 sizeof(Boolean), XtOffset(AppDataPtr, hideThinkingFromHuman),
1225 XtRImmediate, (XtPointer) True },
1226 { "adjudicateLossThreshold", "adjudicateLossThreshold", XtRInt,
1227 sizeof(int), XtOffset(AppDataPtr, adjudicateLossThreshold),
1228 XtRImmediate, (XtPointer) 0},
1229 { "pgnEventHeader", "pgnEventHeader", XtRString,
1230 sizeof(String), XtOffset(AppDataPtr, pgnEventHeader),
1231 XtRImmediate, (XtPointer) "Computer Chess Game" },
1232 { "defaultFrcPosition", "defaultFrcPositon", XtRInt,
1233 sizeof(int), XtOffset(AppDataPtr, defaultFrcPosition),
1234 XtRImmediate, (XtPointer) -1},
1235 { "gameListTags", "gameListTags", XtRString,
1236 sizeof(String), XtOffset(AppDataPtr, gameListTags),
1237 XtRImmediate, (XtPointer) GLT_DEFAULT_TAGS },
1239 // [HGM] 4.3.xx options
1240 { "boardWidth", "boardWidth", XtRInt,
1241 sizeof(int), XtOffset(AppDataPtr, NrFiles),
1242 XtRImmediate, (XtPointer) -1},
1243 { "boardHeight", "boardHeight", XtRInt,
1244 sizeof(int), XtOffset(AppDataPtr, NrRanks),
1245 XtRImmediate, (XtPointer) -1},
1246 { "matchPause", "matchPause", XtRInt,
1247 sizeof(int), XtOffset(AppDataPtr, matchPause),
1248 XtRImmediate, (XtPointer) 10000},
1249 { "holdingsSize", "holdingsSize", XtRInt,
1250 sizeof(int), XtOffset(AppDataPtr, holdingsSize),
1251 XtRImmediate, (XtPointer) -1},
1252 { "flipBlack", "flipBlack", XtRBoolean,
1253 sizeof(Boolean), XtOffset(AppDataPtr, upsideDown),
1254 XtRImmediate, (XtPointer) False},
1255 { "allWhite", "allWhite", XtRBoolean,
1256 sizeof(Boolean), XtOffset(AppDataPtr, allWhite),
1257 XtRImmediate, (XtPointer) False},
1258 { "pieceToCharTable", "pieceToCharTable", XtRString,
1259 sizeof(String), XtOffset(AppDataPtr, pieceToCharTable),
1260 XtRImmediate, (XtPointer) 0},
1261 { "alphaRank", "alphaRank", XtRBoolean,
1262 sizeof(Boolean), XtOffset(AppDataPtr, alphaRank),
1263 XtRImmediate, (XtPointer) False},
1264 { "testClaims", "testClaims", XtRBoolean,
1265 sizeof(Boolean), XtOffset(AppDataPtr, testClaims),
1266 XtRImmediate, (XtPointer) True},
1267 { "checkMates", "checkMates", XtRBoolean,
1268 sizeof(Boolean), XtOffset(AppDataPtr, checkMates),
1269 XtRImmediate, (XtPointer) True},
1270 { "materialDraws", "materialDraws", XtRBoolean,
1271 sizeof(Boolean), XtOffset(AppDataPtr, materialDraws),
1272 XtRImmediate, (XtPointer) True},
1273 { "trivialDraws", "trivialDraws", XtRBoolean,
1274 sizeof(Boolean), XtOffset(AppDataPtr, trivialDraws),
1275 XtRImmediate, (XtPointer) False},
1276 { "ruleMoves", "ruleMoves", XtRInt,
1277 sizeof(int), XtOffset(AppDataPtr, ruleMoves),
1278 XtRImmediate, (XtPointer) 51},
1279 { "repeatsToDraw", "repeatsToDraw", XtRInt,
1280 sizeof(int), XtOffset(AppDataPtr, drawRepeats),
1281 XtRImmediate, (XtPointer) 6},
1282 { "engineDebugOutput", "engineDebugOutput", XtRInt,
1283 sizeof(int), XtOffset(AppDataPtr, engineComments),
1284 XtRImmediate, (XtPointer) 1},
1285 { "userName", "userName", XtRString,
1286 sizeof(int), XtOffset(AppDataPtr, userName),
1287 XtRImmediate, (XtPointer) 0},
1288 { "autoKibitz", "autoKibitz", XtRBoolean,
1289 sizeof(Boolean), XtOffset(AppDataPtr, autoKibitz),
1290 XtRImmediate, (XtPointer) False},
1291 { "firstTimeOdds", "firstTimeOdds", XtRInt,
1292 sizeof(int), XtOffset(AppDataPtr, firstTimeOdds),
1293 XtRImmediate, (XtPointer) 1},
1294 { "secondTimeOdds", "secondTimeOdds", XtRInt,
1295 sizeof(int), XtOffset(AppDataPtr, secondTimeOdds),
1296 XtRImmediate, (XtPointer) 1},
1297 { "timeOddsMode", "timeOddsMode", XtRInt,
1298 sizeof(int), XtOffset(AppDataPtr, timeOddsMode),
1299 XtRImmediate, (XtPointer) 0},
1300 { "firstAccumulateTC", "firstAccumulateTC", XtRInt,
1301 sizeof(int), XtOffset(AppDataPtr, firstAccumulateTC),
1302 XtRImmediate, (XtPointer) 1},
1303 { "secondAccumulateTC", "secondAccumulateTC", XtRInt,
1304 sizeof(int), XtOffset(AppDataPtr, secondAccumulateTC),
1305 XtRImmediate, (XtPointer) 1},
1306 { "firstNPS", "firstNPS", XtRInt,
1307 sizeof(int), XtOffset(AppDataPtr, firstNPS),
1308 XtRImmediate, (XtPointer) -1},
1309 { "secondNPS", "secondNPS", XtRInt,
1310 sizeof(int), XtOffset(AppDataPtr, secondNPS),
1311 XtRImmediate, (XtPointer) -1},
1312 { "serverMoves", "serverMoves", XtRString,
1313 sizeof(String), XtOffset(AppDataPtr, serverMovesName),
1314 XtRImmediate, (XtPointer) 0},
1315 { "serverPause", "serverPause", XtRInt,
1316 sizeof(int), XtOffset(AppDataPtr, serverPause),
1317 XtRImmediate, (XtPointer) 0},
1318 { "suppressLoadMoves", "suppressLoadMoves", XtRBoolean,
1319 sizeof(Boolean), XtOffset(AppDataPtr, suppressLoadMoves),
1320 XtRImmediate, (XtPointer) False},
1321 { "userName", "userName", XtRString,
1322 sizeof(String), XtOffset(AppDataPtr, userName),
1323 XtRImmediate, (XtPointer) 0},
1324 { "egtFormats", "egtFormats", XtRString,
1325 sizeof(String), XtOffset(AppDataPtr, egtFormats),
1326 XtRImmediate, (XtPointer) 0},
1327 { "rewindIndex", "rewindIndex", XtRInt,
1328 sizeof(int), XtOffset(AppDataPtr, rewindIndex),
1329 XtRImmediate, (XtPointer) 0},
1330 { "sameColorGames", "sameColorGames", XtRInt,
1331 sizeof(int), XtOffset(AppDataPtr, sameColorGames),
1332 XtRImmediate, (XtPointer) 0},
1333 { "smpCores", "smpCores", XtRInt,
1334 sizeof(int), XtOffset(AppDataPtr, smpCores),
1335 XtRImmediate, (XtPointer) 1},
1336 { "niceEngines", "niceEngines", XtRInt,
1337 sizeof(int), XtOffset(AppDataPtr, niceEngines),
1338 XtRImmediate, (XtPointer) 0},
1339 { "nameOfDebugFile", "nameOfDebugFile", XtRString,
1340 sizeof(String), XtOffset(AppDataPtr, nameOfDebugFile),
1341 XtRImmediate, (XtPointer) "xboard.debug"},
1342 { "engineDebugOutput", "engineDebugOutput", XtRInt,
1343 sizeof(int), XtOffset(AppDataPtr, engineComments),
1344 XtRImmediate, (XtPointer) 0},
1345 { "noGUI", "noGUI", XtRBoolean,
1346 sizeof(Boolean), XtOffset(AppDataPtr, noGUI),
1347 XtRImmediate, (XtPointer) 0},
1348 { "firstOptions", "firstOptions", XtRString,
1349 sizeof(String), XtOffset(AppDataPtr, firstOptions),
1350 XtRImmediate, (XtPointer) "" },
1351 { "secondOptions", "secondOptions", XtRString,
1352 sizeof(String), XtOffset(AppDataPtr, secondOptions),
1353 XtRImmediate, (XtPointer) "" },
1354 { "firstNeedsNoncompliantFEN", "firstNeedsNoncompliantFEN", XtRString,
1355 sizeof(String), XtOffset(AppDataPtr, fenOverride1),
1356 XtRImmediate, (XtPointer) 0 },
1357 { "secondNeedsNoncompliantFEN", "secondNeedsNoncompliantFEN", XtRString,
1358 sizeof(String), XtOffset(AppDataPtr, fenOverride2),
1359 XtRImmediate, (XtPointer) 0 },
1361 // [HGM] Winboard_x UCI options
1362 { "firstIsUCI", "firstIsUCI", XtRBoolean,
1363 sizeof(Boolean), XtOffset(AppDataPtr, firstIsUCI),
1364 XtRImmediate, (XtPointer) False},
1365 { "secondIsUCI", "secondIsUCI", XtRBoolean,
1366 sizeof(Boolean), XtOffset(AppDataPtr, secondIsUCI),
1367 XtRImmediate, (XtPointer) False},
1368 { "firstHasOwnBookUCI", "firstHasOwnBookUCI", XtRBoolean,
1369 sizeof(Boolean), XtOffset(AppDataPtr, firstHasOwnBookUCI),
1370 XtRImmediate, (XtPointer) True},
1371 { "secondHasOwnBookUCI", "secondHasOwnBookUCI", XtRBoolean,
1372 sizeof(Boolean), XtOffset(AppDataPtr, secondHasOwnBookUCI),
1373 XtRImmediate, (XtPointer) True},
1374 { "usePolyglotBook", "usePolyglotBook", XtRBoolean,
1375 sizeof(Boolean), XtOffset(AppDataPtr, usePolyglotBook),
1376 XtRImmediate, (XtPointer) False},
1377 { "defaultHashSize", "defaultHashSize", XtRInt,
1378 sizeof(int), XtOffset(AppDataPtr, defaultHashSize),
1379 XtRImmediate, (XtPointer) 64},
1380 { "defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XtRInt,
1381 sizeof(int), XtOffset(AppDataPtr, defaultCacheSizeEGTB),
1382 XtRImmediate, (XtPointer) 4},
1383 { "polyglotDir", "polyglotDir", XtRString,
1384 sizeof(String), XtOffset(AppDataPtr, polyglotDir),
1385 XtRImmediate, (XtPointer) "." },
1386 { "polyglotBook", "polyglotBook", XtRString,
1387 sizeof(String), XtOffset(AppDataPtr, polyglotBook),
1388 XtRImmediate, (XtPointer) "" },
1389 { "defaultPathEGTB", "defaultPathEGTB", XtRString,
1390 sizeof(String), XtOffset(AppDataPtr, defaultPathEGTB),
1391 XtRImmediate, (XtPointer) "/usr/local/share/egtb"},
1392 { "delayBeforeQuit", "delayBeforeQuit", XtRInt,
1393 sizeof(int), XtOffset(AppDataPtr, delayBeforeQuit),
1394 XtRImmediate, (XtPointer) 0},
1395 { "delayAfterQuit", "delayAfterQuit", XtRInt,
1396 sizeof(int), XtOffset(AppDataPtr, delayAfterQuit),
1397 XtRImmediate, (XtPointer) 0},
1400 XrmOptionDescRec shellOptions[] = {
1401 { "-whitePieceColor", "whitePieceColor", XrmoptionSepArg, NULL },
1402 { "-blackPieceColor", "blackPieceColor", XrmoptionSepArg, NULL },
1403 { "-lightSquareColor", "lightSquareColor", XrmoptionSepArg, NULL },
1404 { "-darkSquareColor", "darkSquareColor", XrmoptionSepArg, NULL },
1405 { "-highlightSquareColor", "highlightSquareColor", XrmoptionSepArg, NULL },
1406 { "-premoveHighlightColor", "premoveHighlightColor", XrmoptionSepArg,NULL},
1407 { "-movesPerSession", "movesPerSession", XrmoptionSepArg, NULL },
1408 { "-mps", "movesPerSession", XrmoptionSepArg, NULL },
1409 { "-timeIncrement", "timeIncrement", XrmoptionSepArg, NULL },
1410 { "-inc", "timeIncrement", XrmoptionSepArg, NULL },
1411 { "-initString", "initString", XrmoptionSepArg, NULL },
1412 { "-firstInitString", "initString", XrmoptionSepArg, NULL },
1413 { "-secondInitString", "secondInitString", XrmoptionSepArg, NULL },
1414 { "-firstComputerString", "firstComputerString", XrmoptionSepArg, NULL },
1415 { "-secondComputerString", "secondComputerString", XrmoptionSepArg, NULL },
1416 { "-firstChessProgram", "firstChessProgram", XrmoptionSepArg, NULL },
1417 { "-fcp", "firstChessProgram", XrmoptionSepArg, NULL },
1418 { "-secondChessProgram", "secondChessProgram", XrmoptionSepArg, NULL },
1419 { "-scp", "secondChessProgram", XrmoptionSepArg, NULL },
1420 { "-firstPlaysBlack", "firstPlaysBlack", XrmoptionSepArg, NULL },
1421 { "-fb", "firstPlaysBlack", XrmoptionNoArg, "True" },
1422 { "-xfb", "firstPlaysBlack", XrmoptionNoArg, "False" },
1423 { "-noChessProgram", "noChessProgram", XrmoptionSepArg, NULL },
1424 { "-ncp", "noChessProgram", XrmoptionNoArg, "True" },
1425 { "-xncp", "noChessProgram", XrmoptionNoArg, "False" },
1426 { "-firstHost", "firstHost", XrmoptionSepArg, NULL },
1427 { "-fh", "firstHost", XrmoptionSepArg, NULL },
1428 { "-secondHost", "secondHost", XrmoptionSepArg, NULL },
1429 { "-sh", "secondHost", XrmoptionSepArg, NULL },
1430 { "-firstDirectory", "firstDirectory", XrmoptionSepArg, NULL },
1431 { "-fd", "firstDirectory", XrmoptionSepArg, NULL },
1432 { "-secondDirectory", "secondDirectory", XrmoptionSepArg, NULL },
1433 { "-sd", "secondDirectory", XrmoptionSepArg, NULL },
1434 { "-bitmapDirectory", "bitmapDirectory", XrmoptionSepArg, NULL },
1435 { "-bm", "bitmapDirectory", XrmoptionSepArg, NULL },
1436 { "-remoteShell", "remoteShell", XrmoptionSepArg, NULL },
1437 { "-rsh", "remoteShell", XrmoptionSepArg, NULL },
1438 { "-remoteUser", "remoteUser", XrmoptionSepArg, NULL },
1439 { "-ruser", "remoteUser", XrmoptionSepArg, NULL },
1440 { "-timeDelay", "timeDelay", XrmoptionSepArg, NULL },
1441 { "-td", "timeDelay", XrmoptionSepArg, NULL },
1442 { "-timeControl", "timeControl", XrmoptionSepArg, NULL },
1443 { "-tc", "timeControl", XrmoptionSepArg, NULL },
1444 { "-internetChessServerMode", "internetChessServerMode",
1445 XrmoptionSepArg, NULL },
1446 { "-ics", "internetChessServerMode", XrmoptionNoArg, "True" },
1447 { "-xics", "internetChessServerMode", XrmoptionNoArg, "False" },
1448 { "-internetChessServerHost", "internetChessServerHost",
1449 XrmoptionSepArg, NULL },
1450 { "-icshost", "internetChessServerHost", XrmoptionSepArg, NULL },
1451 { "-internetChessServerPort", "internetChessServerPort",
1452 XrmoptionSepArg, NULL },
1453 { "-icsport", "internetChessServerPort", XrmoptionSepArg, NULL },
1454 { "-internetChessServerCommPort", "internetChessServerCommPort",
1455 XrmoptionSepArg, NULL },
1456 { "-icscomm", "internetChessServerCommPort", XrmoptionSepArg, NULL },
1457 { "-internetChessServerLogonScript", "internetChessServerLogonScript",
1458 XrmoptionSepArg, NULL },
1459 { "-icslogon", "internetChessServerLogonScript", XrmoptionSepArg, NULL },
1460 { "-internetChessServerHelper", "internetChessServerHelper",
1461 XrmoptionSepArg, NULL },
1462 { "-icshelper", "internetChessServerHelper", XrmoptionSepArg, NULL },
1463 { "-internetChessServerInputBox", "internetChessServerInputBox",
1464 XrmoptionSepArg, NULL },
1465 { "-icsinput", "internetChessServerInputBox", XrmoptionNoArg, "True" },
1466 { "-xicsinput", "internetChessServerInputBox", XrmoptionNoArg, "False" },
1467 { "-icsAlarm", "icsAlarm", XrmoptionSepArg, NULL },
1468 { "-alarm", "icsAlarm", XrmoptionNoArg, "True" },
1469 { "-xalarm", "icsAlarm", XrmoptionNoArg, "False" },
1470 { "-icsAlarmTime", "icsAlarmTime", XrmoptionSepArg, NULL },
1471 { "-useTelnet", "useTelnet", XrmoptionSepArg, NULL },
1472 { "-telnet", "useTelnet", XrmoptionNoArg, "True" },
1473 { "-xtelnet", "useTelnet", XrmoptionNoArg, "False" },
1474 { "-telnetProgram", "telnetProgram", XrmoptionSepArg, NULL },
1475 { "-gateway", "gateway", XrmoptionSepArg, NULL },
1476 { "-loadGameFile", "loadGameFile", XrmoptionSepArg, NULL },
1477 { "-lgf", "loadGameFile", XrmoptionSepArg, NULL },
1478 { "-loadGameIndex", "loadGameIndex", XrmoptionSepArg, NULL },
1479 { "-lgi", "loadGameIndex", XrmoptionSepArg, NULL },
1480 { "-saveGameFile", "saveGameFile", XrmoptionSepArg, NULL },
1481 { "-sgf", "saveGameFile", XrmoptionSepArg, NULL },
1482 { "-autoSaveGames", "autoSaveGames", XrmoptionSepArg, NULL },
1483 { "-autosave", "autoSaveGames", XrmoptionNoArg, "True" },
1484 { "-xautosave", "autoSaveGames", XrmoptionNoArg, "False" },
1485 { "-autoRaiseBoard", "autoRaiseBoard", XrmoptionSepArg, NULL },
1486 { "-autoraise", "autoRaiseBoard", XrmoptionNoArg, "True" },
1487 { "-xautoraise", "autoRaiseBoard", XrmoptionNoArg, "False" },
1488 { "-blindfold", "blindfold", XrmoptionSepArg, NULL },
1489 { "-blind", "blindfold", XrmoptionNoArg, "True" },
1490 { "-xblind", "blindfold", XrmoptionNoArg, "False" },
1491 { "-loadPositionFile", "loadPositionFile", XrmoptionSepArg, NULL },
1492 { "-lpf", "loadPositionFile", XrmoptionSepArg, NULL },
1493 { "-loadPositionIndex", "loadPositionIndex", XrmoptionSepArg, NULL },
1494 { "-lpi", "loadPositionIndex", XrmoptionSepArg, NULL },
1495 { "-savePositionFile", "savePositionFile", XrmoptionSepArg, NULL },
1496 { "-spf", "savePositionFile", XrmoptionSepArg, NULL },
1497 { "-matchMode", "matchMode", XrmoptionSepArg, NULL },
1498 { "-mm", "matchMode", XrmoptionNoArg, "True" },
1499 { "-xmm", "matchMode", XrmoptionNoArg, "False" },
1500 { "-matchGames", "matchGames", XrmoptionSepArg, NULL },
1501 { "-mg", "matchGames", XrmoptionSepArg, NULL },
1502 { "-monoMode", "monoMode", XrmoptionSepArg, NULL },
1503 { "-mono", "monoMode", XrmoptionNoArg, "True" },
1504 { "-xmono", "monoMode", XrmoptionNoArg, "False" },
1505 { "-debugMode", "debugMode", XrmoptionSepArg, NULL },
1506 { "-debug", "debugMode", XrmoptionNoArg, "True" },
1507 { "-xdebug", "debugMode", XrmoptionNoArg, "False" },
1508 { "-clockMode", "clockMode", XrmoptionSepArg, NULL },
1509 { "-clock", "clockMode", XrmoptionNoArg, "True" },
1510 { "-xclock", "clockMode", XrmoptionNoArg, "False" },
1511 { "-boardSize", "boardSize", XrmoptionSepArg, NULL },
1512 { "-size", "boardSize", XrmoptionSepArg, NULL },
1513 { "-searchTime", "searchTime", XrmoptionSepArg, NULL },
1514 { "-st", "searchTime", XrmoptionSepArg, NULL },
1515 { "-searchDepth", "searchDepth", XrmoptionSepArg, NULL },
1516 { "-depth", "searchDepth", XrmoptionSepArg, NULL },
1517 { "-showCoords", "showCoords", XrmoptionSepArg, NULL },
1518 { "-coords", "showCoords", XrmoptionNoArg, "True" },
1519 { "-xcoords", "showCoords", XrmoptionNoArg, "False" },
1521 { "-showJail", "showJail", XrmoptionSepArg, NULL },
1522 { "-jail", "showJail", XrmoptionNoArg, "1" },
1523 { "-sidejail", "showJail", XrmoptionNoArg, "2" },
1524 { "-xjail", "showJail", XrmoptionNoArg, "0" },
1526 { "-showThinking", "showThinking", XrmoptionSepArg, NULL },
1527 { "-thinking", "showThinking", XrmoptionNoArg, "True" },
1528 { "-xthinking", "showThinking", XrmoptionNoArg, "False" },
1529 { "-ponderNextMove", "ponderNextMove", XrmoptionSepArg, NULL },
1530 { "-ponder", "ponderNextMove", XrmoptionNoArg, "True" },
1531 { "-xponder", "ponderNextMove", XrmoptionNoArg, "False" },
1532 { "-periodicUpdates", "periodicUpdates", XrmoptionSepArg, NULL },
1533 { "-periodic", "periodicUpdates", XrmoptionNoArg, "True" },
1534 { "-xperiodic", "periodicUpdates", XrmoptionNoArg, "False" },
1535 { "-clockFont", "clockFont", XrmoptionSepArg, NULL },
1536 { "-coordFont", "coordFont", XrmoptionSepArg, NULL },
1537 { "-font", "font", XrmoptionSepArg, NULL },
1538 { "-ringBellAfterMoves", "ringBellAfterMoves", XrmoptionSepArg, NULL },
1539 { "-bell", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1540 { "-xbell", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1541 { "-movesound", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1542 { "-xmovesound", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1543 { "-autoCallFlag", "autoCallFlag", XrmoptionSepArg, NULL },
1544 { "-autoflag", "autoCallFlag", XrmoptionNoArg, "True" },
1545 { "-xautoflag", "autoCallFlag", XrmoptionNoArg, "False" },
1546 { "-autoFlipView", "autoFlipView", XrmoptionSepArg, NULL },
1547 { "-autoflip", "autoFlipView", XrmoptionNoArg, "True" },
1548 { "-xautoflip", "autoFlipView", XrmoptionNoArg, "False" },
1549 { "-autoObserve", "autoObserve", XrmoptionSepArg, NULL },
1550 { "-autobs", "autoObserve", XrmoptionNoArg, "True" },
1551 { "-xautobs", "autoObserve", XrmoptionNoArg, "False" },
1552 { "-autoComment", "autoComment", XrmoptionSepArg, NULL },
1553 { "-autocomm", "autoComment", XrmoptionNoArg, "True" },
1554 { "-xautocomm", "autoComment", XrmoptionNoArg, "False" },
1555 { "-getMoveList", "getMoveList", XrmoptionSepArg, NULL },
1556 { "-moves", "getMoveList", XrmoptionNoArg, "True" },
1557 { "-xmoves", "getMoveList", XrmoptionNoArg, "False" },
1559 { "-highlightDragging", "highlightDragging", XrmoptionSepArg, NULL },
1560 { "-highdrag", "highlightDragging", XrmoptionNoArg, "True" },
1561 { "-xhighdrag", "highlightDragging", XrmoptionNoArg, "False" },
1563 { "-highlightLastMove", "highlightLastMove", XrmoptionSepArg, NULL },
1564 { "-highlight", "highlightLastMove", XrmoptionNoArg, "True" },
1565 { "-xhighlight", "highlightLastMove", XrmoptionNoArg, "False" },
1566 { "-premove", "premove", XrmoptionSepArg, NULL },
1567 { "-pre", "premove", XrmoptionNoArg, "True" },
1568 { "-xpre", "premove", XrmoptionNoArg, "False" },
1569 { "-testLegality", "testLegality", XrmoptionSepArg, NULL },
1570 { "-legal", "testLegality", XrmoptionNoArg, "True" },
1571 { "-xlegal", "testLegality", XrmoptionNoArg, "False" },
1572 { "-flipView", "flipView", XrmoptionSepArg, NULL },
1573 { "-flip", "flipView", XrmoptionNoArg, "True" },
1574 { "-xflip", "flipView", XrmoptionNoArg, "False" },
1575 { "-cmail", "cmailGameName", XrmoptionSepArg, NULL },
1576 { "-alwaysPromoteToQueen", "alwaysPromoteToQueen",
1577 XrmoptionSepArg, NULL },
1578 { "-queen", "alwaysPromoteToQueen", XrmoptionNoArg, "True" },
1579 { "-xqueen", "alwaysPromoteToQueen", XrmoptionNoArg, "False" },
1580 { "-oldSaveStyle", "oldSaveStyle", XrmoptionSepArg, NULL },
1581 { "-oldsave", "oldSaveStyle", XrmoptionNoArg, "True" },
1582 { "-xoldsave", "oldSaveStyle", XrmoptionNoArg, "False" },
1583 { "-quietPlay", "quietPlay", XrmoptionSepArg, NULL },
1584 { "-quiet", "quietPlay", XrmoptionNoArg, "True" },
1585 { "-xquiet", "quietPlay", XrmoptionNoArg, "False" },
1586 { "-titleInWindow", "titleInWindow", XrmoptionSepArg, NULL },
1587 { "-title", "titleInWindow", XrmoptionNoArg, "True" },
1588 { "-xtitle", "titleInWindow", XrmoptionNoArg, "False" },
1590 { "-zippyTalk", "zippyTalk", XrmoptionSepArg, NULL },
1591 { "-zt", "zippyTalk", XrmoptionNoArg, "True" },
1592 { "-xzt", "zippyTalk", XrmoptionNoArg, "False" },
1593 { "-zippyPlay", "zippyPlay", XrmoptionSepArg, NULL },
1594 { "-zp", "zippyPlay", XrmoptionNoArg, "True" },
1595 { "-xzp", "zippyPlay", XrmoptionNoArg, "False" },
1596 { "-zippyLines", "zippyLines", XrmoptionSepArg, NULL },
1597 { "-zippyPinhead", "zippyPinhead", XrmoptionSepArg, NULL },
1598 { "-zippyPassword", "zippyPassword", XrmoptionSepArg, NULL },
1599 { "-zippyPassword2", "zippyPassword2", XrmoptionSepArg, NULL },
1600 { "-zippyWrongPassword", "zippyWrongPassword", XrmoptionSepArg, NULL },
1601 { "-zippyAcceptOnly", "zippyAcceptOnly", XrmoptionSepArg, NULL },
1602 { "-zippyUseI", "zippyUseI", XrmoptionSepArg, NULL },
1603 { "-zui", "zippyUseI", XrmoptionNoArg, "True" },
1604 { "-xzui", "zippyUseI", XrmoptionNoArg, "False" },
1605 { "-zippyBughouse", "zippyBughouse", XrmoptionSepArg, NULL },
1606 { "-zippyNoplayCrafty", "zippyNoplayCrafty", XrmoptionSepArg, NULL },
1607 { "-znc", "zippyNoplayCrafty", XrmoptionNoArg, "True" },
1608 { "-xznc", "zippyNoplayCrafty", XrmoptionNoArg, "False" },
1609 { "-zippyGameEnd", "zippyGameEnd", XrmoptionSepArg, NULL },
1610 { "-zippyGameStart", "zippyGameStart", XrmoptionSepArg, NULL },
1611 { "-zippyAdjourn", "zippyAdjourn", XrmoptionSepArg, NULL },
1612 { "-zadj", "zippyAdjourn", XrmoptionNoArg, "True" },
1613 { "-xzadj", "zippyAdjourn", XrmoptionNoArg, "False" },
1614 { "-zippyAbort", "zippyAbort", XrmoptionSepArg, NULL },
1615 { "-zab", "zippyAbort", XrmoptionNoArg, "True" },
1616 { "-xzab", "zippyAbort", XrmoptionNoArg, "False" },
1617 { "-zippyVariants", "zippyVariants", XrmoptionSepArg, NULL },
1618 { "-zippyMaxGames", "zippyMaxGames", XrmoptionSepArg, NULL },
1619 { "-zippyReplayTimeout", "zippyReplayTimeout", XrmoptionSepArg, NULL },
1620 { "-zippyShortGame", "zippyShortGame", XrmoptionSepArg, NULL },
1622 { "-flashCount", "flashCount", XrmoptionSepArg, NULL },
1623 { "-flash", "flashCount", XrmoptionNoArg, "3" },
1624 { "-xflash", "flashCount", XrmoptionNoArg, "0" },
1625 { "-flashRate", "flashRate", XrmoptionSepArg, NULL },
1626 { "-pixmapDirectory", "pixmapDirectory", XrmoptionSepArg, NULL },
1627 { "-msLoginDelay", "msLoginDelay", XrmoptionSepArg, NULL },
1628 { "-pixmap", "pixmapDirectory", XrmoptionSepArg, NULL },
1629 { "-colorizeMessages", "colorizeMessages", XrmoptionSepArg, NULL },
1630 { "-colorize", "colorizeMessages", XrmoptionNoArg, "True" },
1631 { "-xcolorize", "colorizeMessages", XrmoptionNoArg, "False" },
1632 { "-colorShout", "colorShout", XrmoptionSepArg, NULL },
1633 { "-colorSShout", "colorSShout", XrmoptionSepArg, NULL },
1634 { "-colorCShout", "colorSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1635 { "-colorChannel1", "colorChannel1", XrmoptionSepArg, NULL },
1636 { "-colorChannel", "colorChannel", XrmoptionSepArg, NULL },
1637 { "-colorKibitz", "colorKibitz", XrmoptionSepArg, NULL },
1638 { "-colorTell", "colorTell", XrmoptionSepArg, NULL },
1639 { "-colorChallenge", "colorChallenge", XrmoptionSepArg, NULL },
1640 { "-colorRequest", "colorRequest", XrmoptionSepArg, NULL },
1641 { "-colorSeek", "colorSeek", XrmoptionSepArg, NULL },
1642 { "-colorNormal", "colorNormal", XrmoptionSepArg, NULL },
1643 { "-soundProgram", "soundProgram", XrmoptionSepArg, NULL },
1644 { "-soundShout", "soundShout", XrmoptionSepArg, NULL },
1645 { "-soundSShout", "soundSShout", XrmoptionSepArg, NULL },
1646 { "-soundCShout", "soundSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1647 { "-soundChannel1", "soundChannel1", XrmoptionSepArg, NULL },
1648 { "-soundChannel", "soundChannel", XrmoptionSepArg, NULL },
1649 { "-soundKibitz", "soundKibitz", XrmoptionSepArg, NULL },
1650 { "-soundTell", "soundTell", XrmoptionSepArg, NULL },
1651 { "-soundChallenge", "soundChallenge", XrmoptionSepArg, NULL },
1652 { "-soundRequest", "soundRequest", XrmoptionSepArg, NULL },
1653 { "-soundSeek", "soundSeek", XrmoptionSepArg, NULL },
1654 { "-soundMove", "soundMove", XrmoptionSepArg, NULL },
1655 { "-soundIcsWin", "soundIcsWin", XrmoptionSepArg, NULL },
1656 { "-soundIcsLoss", "soundIcsLoss", XrmoptionSepArg, NULL },
1657 { "-soundIcsDraw", "soundIcsDraw", XrmoptionSepArg, NULL },
1658 { "-soundIcsUnfinished", "soundIcsUnfinished", XrmoptionSepArg, NULL },
1659 { "-soundIcsAlarm", "soundIcsAlarm", XrmoptionSepArg, NULL },
1660 { "-reuseFirst", "reuseFirst", XrmoptionSepArg, NULL },
1661 { "-reuseChessPrograms", "reuseFirst", XrmoptionSepArg, NULL }, /*compat*/
1662 { "-reuse", "reuseFirst", XrmoptionNoArg, "True" },
1663 { "-xreuse", "reuseFirst", XrmoptionNoArg, "False" },
1664 { "-reuseSecond", "reuseSecond", XrmoptionSepArg, NULL },
1665 { "-reuse2", "reuseSecond", XrmoptionNoArg, "True" },
1666 { "-xreuse2", "reuseSecond", XrmoptionNoArg, "False" },
1667 { "-animateMoving", "animateMoving", XrmoptionSepArg, NULL },
1668 { "-animate", "animateMoving", XrmoptionNoArg, "True" },
1669 { "-xanimate", "animateMoving", XrmoptionNoArg, "False" },
1670 { "-animateDragging", "animateDragging", XrmoptionSepArg, NULL },
1671 { "-drag", "animateDragging", XrmoptionNoArg, "True" },
1672 { "-xdrag", "animateDragging", XrmoptionNoArg, "False" },
1673 { "-animateSpeed", "animateSpeed", XrmoptionSepArg, NULL },
1674 { "-popupExitMessage", "popupExitMessage", XrmoptionSepArg, NULL },
1675 { "-exit", "popupExitMessage", XrmoptionNoArg, "True" },
1676 { "-xexit", "popupExitMessage", XrmoptionNoArg, "False" },
1677 { "-popupMoveErrors", "popupMoveErrors", XrmoptionSepArg, NULL },
1678 { "-popup", "popupMoveErrors", XrmoptionNoArg, "True" },
1679 { "-xpopup", "popupMoveErrors", XrmoptionNoArg, "False" },
1680 { "-fontSizeTolerance", "fontSizeTolerance", XrmoptionSepArg, NULL },
1681 { "-initialMode", "initialMode", XrmoptionSepArg, NULL },
1682 { "-mode", "initialMode", XrmoptionSepArg, NULL },
1683 { "-variant", "variant", XrmoptionSepArg, NULL },
1684 { "-firstProtocolVersion", "firstProtocolVersion", XrmoptionSepArg, NULL },
1685 { "-secondProtocolVersion","secondProtocolVersion",XrmoptionSepArg, NULL },
1686 { "-showButtonBar", "showButtonBar", XrmoptionSepArg, NULL },
1687 { "-buttons", "showButtonBar", XrmoptionNoArg, "True" },
1688 { "-xbuttons", "showButtonBar", XrmoptionNoArg, "False" },
1689 { "-lowTimeWarningColor", "lowTimeWarningColor", XrmoptionSepArg, NULL },
1690 { "-lowTimeWarning", "lowTimeWarning", XrmoptionSepArg, NULL },
1691 /* [AS,HR] New features */
1692 { "-firstScoreAbs", "firstScoreAbs", XrmoptionSepArg, NULL },
1693 { "-secondScoreAbs", "secondScoreAbs", XrmoptionSepArg, NULL },
1694 { "-pgnExtendedInfo", "pgnExtendedInfo", XrmoptionSepArg, NULL },
1695 { "-hideThinkingFromHuman", "hideThinkingFromHuman", XrmoptionSepArg, NULL },
1696 { "-adjudicateLossThreshold", "adjudicateLossThreshold", XrmoptionSepArg, NULL },
1697 { "-pgnEventHeader", "pgnEventHeader", XrmoptionSepArg, NULL },
1698 { "-firstIsUCI", "firstIsUCI", XrmoptionSepArg, NULL },
1699 { "-secondIsUCI", "secondIsUCI", XrmoptionSepArg, NULL },
1700 { "-fUCI", "firstIsUCI", XrmoptionNoArg, "True" },
1701 { "-sUCI", "secondIsUCI", XrmoptionNoArg, "True" },
1702 { "-firstHasOwnBookUCI", "firstHasOwnBookUCI", XrmoptionSepArg, NULL },
1703 { "-secondHasOwnBookUCI", "secondHasOwnBookUCI", XrmoptionSepArg, NULL },
1704 { "-fNoOwnBookUCI", "firstHasOwnBookUCI", XrmoptionNoArg, "False" },
1705 { "-sNoOwnBookUCI", "secondHasOwnBookUCI", XrmoptionNoArg, "False" },
1706 { "-firstXBook", "firstHasOwnBookUCI", XrmoptionNoArg, "False" },
1707 { "-secondXBook", "secondHasOwnBookUCI", XrmoptionNoArg, "False" },
1708 { "-polyglotDir", "polyglotDir", XrmoptionSepArg, NULL },
1709 { "-usePolyglotBook", "usePolyglotBook", XrmoptionSepArg, NULL },
1710 { "-polyglotBook", "polyglotBook", XrmoptionSepArg, NULL },
1711 { "-defaultHashSize", "defaultHashSize", XrmoptionSepArg, NULL },
1712 { "-defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XrmoptionSepArg, NULL },
1713 { "-defaultPathEGTB", "defaultPathEGTB", XrmoptionSepArg, NULL },
1714 { "-defaultFrcPosition", "defaultFrcPosition", XrmoptionSepArg, NULL },
1715 { "-gameListTags", "gameListTags", XrmoptionSepArg, NULL },
1716 // [HGM] I am sure AS added many more options, but we have to fish them out, from the list in winboard.c
1718 /* [HGM,HR] User-selectable board size */
1719 { "-boardWidth", "boardWidth", XrmoptionSepArg, NULL },
1720 { "-boardHeight", "boardHeight", XrmoptionSepArg, NULL },
1721 { "-matchPause", "matchPause", XrmoptionSepArg, NULL },
1723 /* [HGM] new arguments of 4.3.xx. All except first three are back-end options, which should work immediately */
1724 { "-holdingsSize", "holdingsSize", XrmoptionSepArg, NULL }, // requires extensive front-end changes to work
1725 { "-flipBlack", "flipBlack", XrmoptionSepArg, NULL }, // requires front-end changes to work
1726 { "-allWhite", "allWhite", XrmoptionSepArg, NULL }, // requires front-end changes to work
1727 { "-pieceToCharTable", "pieceToCharTable", XrmoptionSepArg, NULL },
1728 { "-alphaRank", "alphaRank", XrmoptionSepArg, NULL },
1729 { "-testClaims", "testClaims", XrmoptionSepArg, NULL },
1730 { "-checkMates", "checkMates", XrmoptionSepArg, NULL },
1731 { "-materialDraws", "materialDraws", XrmoptionSepArg, NULL },
1732 { "-trivialDraws", "trivialDraws", XrmoptionSepArg, NULL },
1733 { "-ruleMoves", "ruleMoves", XrmoptionSepArg, NULL },
1734 { "-repeatsToDraw", "repeatsToDraw", XrmoptionSepArg, NULL },
1735 { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL },
1736 { "-userName", "userName", XrmoptionSepArg, NULL },
1737 { "-autoKibitz", "autoKibitz", XrmoptionNoArg, "True" },
1738 { "-firstTimeOdds", "firstTimeOdds", XrmoptionSepArg, NULL },
1739 { "-secondTimeOdds", "secondTimeOdds", XrmoptionSepArg, NULL },
1740 { "-timeOddsMode", "timeOddsMode", XrmoptionSepArg, NULL },
1741 { "-firstAccumulateTC", "firstAccumulateTC", XrmoptionSepArg, NULL },
1742 { "-secondAccumulateTC", "secondAccumulateTC", XrmoptionSepArg, NULL },
1743 { "-firstNPS", "firstNPS", XrmoptionSepArg, NULL },
1744 { "-secondNPS", "secondNPS", XrmoptionSepArg, NULL },
1745 { "-serverMoves", "serverMoves", XrmoptionSepArg, NULL },
1746 { "-serverPause", "serverPause", XrmoptionSepArg, NULL },
1747 { "-suppressLoadMoves", "suppressLoadMoves", XrmoptionSepArg, NULL },
1748 { "-egtFormats", "egtFormats", XrmoptionSepArg, NULL },
1749 { "-userName", "userName", XrmoptionSepArg, NULL },
1750 { "-smpCores", "smpCores", XrmoptionSepArg, NULL },
1751 { "-sameColorGames", "sameColorGames", XrmoptionSepArg, NULL },
1752 { "-rewindIndex", "rewindIndex", XrmoptionSepArg, NULL },
1753 { "-niceEngines", "niceEngines", XrmoptionSepArg, NULL },
1754 { "-delayBeforeQuit", "delayBeforeQuit", XrmoptionSepArg, NULL },
1755 { "-delayAfterQuit", "delayAfterQuit", XrmoptionSepArg, NULL },
1756 { "-nameOfDebugFile", "nameOfDebugFile", XrmoptionSepArg, NULL },
1757 { "-debugFile", "nameOfDebugFile", XrmoptionSepArg, NULL },
1758 { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL },
1759 { "-noGUI", "noGUI", XrmoptionNoArg, "True" },
1760 { "-firstOptions", "firstOptions", XrmoptionSepArg, NULL },
1761 { "-secondOptions", "secondOptions", XrmoptionSepArg, NULL },
1762 { "-firstNeedsNoncompliantFEN", "firstNeedsNoncompliantFEN", XrmoptionSepArg, NULL },
1763 { "-secondNeedsNoncompliantFEN", "secondNeedsNoncompliantFEN", XrmoptionSepArg, NULL },
1767 XtActionsRec boardActions[] = {
1768 { "DrawPosition", DrawPositionProc },
1769 { "HandleUserMove", HandleUserMove },
1770 { "AnimateUserMove", AnimateUserMove },
1771 { "FileNameAction", FileNameAction },
1772 { "AskQuestionProc", AskQuestionProc },
1773 { "AskQuestionReplyAction", AskQuestionReplyAction },
1774 { "PieceMenuPopup", PieceMenuPopup },
1775 { "WhiteClock", WhiteClock },
1776 { "BlackClock", BlackClock },
1777 { "Iconify", Iconify },
1778 { "ResetProc", ResetProc },
1779 { "LoadGameProc", LoadGameProc },
1780 { "LoadNextGameProc", LoadNextGameProc },
1781 { "LoadPrevGameProc", LoadPrevGameProc },
1782 { "LoadSelectedProc", LoadSelectedProc },
1783 { "ReloadGameProc", ReloadGameProc },
1784 { "LoadPositionProc", LoadPositionProc },
1785 { "LoadNextPositionProc", LoadNextPositionProc },
1786 { "LoadPrevPositionProc", LoadPrevPositionProc },
1787 { "ReloadPositionProc", ReloadPositionProc },
1788 { "CopyPositionProc", CopyPositionProc },
1789 { "PastePositionProc", PastePositionProc },
1790 { "CopyGameProc", CopyGameProc },
1791 { "PasteGameProc", PasteGameProc },
1792 { "SaveGameProc", SaveGameProc },
1793 { "SavePositionProc", SavePositionProc },
1794 { "MailMoveProc", MailMoveProc },
1795 { "ReloadCmailMsgProc", ReloadCmailMsgProc },
1796 { "QuitProc", QuitProc },
1797 { "MachineWhiteProc", MachineWhiteProc },
1798 { "MachineBlackProc", MachineBlackProc },
1799 { "AnalysisModeProc", AnalyzeModeProc },
1800 { "AnalyzeFileProc", AnalyzeFileProc },
1801 { "TwoMachinesProc", TwoMachinesProc },
1802 { "IcsClientProc", IcsClientProc },
1803 { "EditGameProc", EditGameProc },
1804 { "EditPositionProc", EditPositionProc },
1805 { "TrainingProc", EditPositionProc },
1806 { "EngineOutputProc", EngineOutputProc}, // [HGM] Winboard_x engine-output window
1807 { "ShowGameListProc", ShowGameListProc },
1808 { "ShowMoveListProc", HistoryShowProc},
1809 { "EditTagsProc", EditCommentProc },
1810 { "EditCommentProc", EditCommentProc },
1811 { "IcsAlarmProc", IcsAlarmProc },
1812 { "IcsInputBoxProc", IcsInputBoxProc },
1813 { "PauseProc", PauseProc },
1814 { "AcceptProc", AcceptProc },
1815 { "DeclineProc", DeclineProc },
1816 { "RematchProc", RematchProc },
1817 { "CallFlagProc", CallFlagProc },
1818 { "DrawProc", DrawProc },
1819 { "AdjournProc", AdjournProc },
1820 { "AbortProc", AbortProc },
1821 { "ResignProc", ResignProc },
1822 { "AdjuWhiteProc", AdjuWhiteProc },
1823 { "AdjuBlackProc", AdjuBlackProc },
1824 { "AdjuDrawProc", AdjuDrawProc },
1825 { "EnterKeyProc", EnterKeyProc },
1826 { "StopObservingProc", StopObservingProc },
1827 { "StopExaminingProc", StopExaminingProc },
1828 { "BackwardProc", BackwardProc },
1829 { "ForwardProc", ForwardProc },
1830 { "ToStartProc", ToStartProc },
1831 { "ToEndProc", ToEndProc },
1832 { "RevertProc", RevertProc },
1833 { "TruncateGameProc", TruncateGameProc },
1834 { "MoveNowProc", MoveNowProc },
1835 { "RetractMoveProc", RetractMoveProc },
1836 { "AlwaysQueenProc", AlwaysQueenProc },
1837 { "AnimateDraggingProc", AnimateDraggingProc },
1838 { "AnimateMovingProc", AnimateMovingProc },
1839 { "AutoflagProc", AutoflagProc },
1840 { "AutoflipProc", AutoflipProc },
1841 { "AutobsProc", AutobsProc },
1842 { "AutoraiseProc", AutoraiseProc },
1843 { "AutosaveProc", AutosaveProc },
1844 { "BlindfoldProc", BlindfoldProc },
1845 { "FlashMovesProc", FlashMovesProc },
1846 { "FlipViewProc", FlipViewProc },
1847 { "GetMoveListProc", GetMoveListProc },
1849 { "HighlightDraggingProc", HighlightDraggingProc },
1851 { "HighlightLastMoveProc", HighlightLastMoveProc },
1852 { "IcsAlarmProc", IcsAlarmProc },
1853 { "MoveSoundProc", MoveSoundProc },
1854 { "OldSaveStyleProc", OldSaveStyleProc },
1855 { "PeriodicUpdatesProc", PeriodicUpdatesProc },
1856 { "PonderNextMoveProc", PonderNextMoveProc },
1857 { "PopupExitMessageProc", PopupExitMessageProc },
1858 { "PopupMoveErrorsProc", PopupMoveErrorsProc },
1859 { "PremoveProc", PremoveProc },
1860 { "QuietPlayProc", QuietPlayProc },
1861 { "ShowCoordsProc", ShowCoordsProc },
1862 { "ShowThinkingProc", ShowThinkingProc },
1863 { "HideThinkingProc", HideThinkingProc },
1864 { "TestLegalityProc", TestLegalityProc },
1865 { "InfoProc", InfoProc },
1866 { "ManProc", ManProc },
1867 { "HintProc", HintProc },
1868 { "BookProc", BookProc },
1869 { "AboutGameProc", AboutGameProc },
1870 { "AboutProc", AboutProc },
1871 { "DebugProc", DebugProc },
1872 { "NothingProc", NothingProc },
1873 { "CommentPopDown", (XtActionProc) CommentPopDown },
1874 { "EditCommentPopDown", (XtActionProc) EditCommentPopDown },
1875 { "TagsPopDown", (XtActionProc) TagsPopDown },
1876 { "ErrorPopDown", (XtActionProc) ErrorPopDown },
1877 { "ICSInputBoxPopDown", (XtActionProc) ICSInputBoxPopDown },
1878 { "AnalysisPopDown", (XtActionProc) AnalysisPopDown },
1879 { "FileNamePopDown", (XtActionProc) FileNamePopDown },
1880 { "AskQuestionPopDown", (XtActionProc) AskQuestionPopDown },
1881 { "GameListPopDown", (XtActionProc) GameListPopDown },
1882 { "PromotionPopDown", (XtActionProc) PromotionPopDown },
1883 { "HistoryPopDown", (XtActionProc) HistoryPopDown },
1884 { "EngineOutputPopDown", (XtActionProc) EngineOutputPopDown },
1885 { "ShufflePopDown", (XtActionProc) ShufflePopDown },
1886 { "EnginePopDown", (XtActionProc) EnginePopDown },
1887 { "UciPopDown", (XtActionProc) UciPopDown },
1888 { "TimeControlPopDown", (XtActionProc) TimeControlPopDown },
1889 { "NewVariantPopDown", (XtActionProc) NewVariantPopDown },
1890 { "SettingsPopDown", (XtActionProc) SettingsPopDown },
1893 char globalTranslations[] =
1894 ":<Key>R: ResignProc() \n \
1895 :<Key>r: ResetProc() \n \
1896 :<Key>g: LoadGameProc() \n \
1897 :<Key>N: LoadNextGameProc() \n \
1898 :<Key>P: LoadPrevGameProc() \n \
1899 :<Key>Q: QuitProc() \n \
1900 :<Key>F: ToEndProc() \n \
1901 :<Key>f: ForwardProc() \n \
1902 :<Key>B: ToStartProc() \n \
1903 :<Key>b: BackwardProc() \n \
1904 :<Key>p: PauseProc() \n \
1905 :<Key>d: DrawProc() \n \
1906 :<Key>t: CallFlagProc() \n \
1907 :<Key>i: Iconify() \n \
1908 :<Key>c: Iconify() \n \
1909 :<Key>v: FlipViewProc() \n \
1910 <KeyDown>Control_L: BackwardProc() \n \
1911 <KeyUp>Control_L: ForwardProc() \n \
1912 <KeyDown>Control_R: BackwardProc() \n \
1913 <KeyUp>Control_R: ForwardProc() \n \
1914 Shift<Key>1: AskQuestionProc(\"Direct command\",\
1915 \"Send to chess program:\",,1) \n \
1916 Shift<Key>2: AskQuestionProc(\"Direct command\",\
1917 \"Send to second chess program:\",,2) \n";
1919 char boardTranslations[] =
1920 "<Btn1Down>: HandleUserMove() \n \
1921 <Btn1Up>: HandleUserMove() \n \
1922 <Btn1Motion>: AnimateUserMove() \n \
1923 Shift<Btn2Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD)\
1924 PieceMenuPopup(menuB) \n \
1925 Any<Btn2Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD) \
1926 PieceMenuPopup(menuW) \n \
1927 Shift<Btn3Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD)\
1928 PieceMenuPopup(menuW) \n \
1929 Any<Btn3Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD) \
1930 PieceMenuPopup(menuB) \n";
1932 char whiteTranslations[] = "<BtnDown>: WhiteClock()\n";
1933 char blackTranslations[] = "<BtnDown>: BlackClock()\n";
1935 char ICSInputTranslations[] =
1936 "<Key>Return: EnterKeyProc() \n";
1938 String xboardResources[] = {
1939 "*fileName*value.translations: #override\\n <Key>Return: FileNameAction()",
1940 "*question*value.translations: #override\\n <Key>Return: AskQuestionReplyAction()",
1941 "*errorpopup*translations: #override\\n <Key>Return: ErrorPopDown()",
1946 /* Max possible square size */
1947 #define MAXSQSIZE 256
1949 static int xpm_avail[MAXSQSIZE];
1951 #ifdef HAVE_DIR_STRUCT
1953 /* Extract piece size from filename */
1955 xpm_getsize(name, len, ext)
1966 if ((p=strchr(name, '.')) == NULL ||
1967 StrCaseCmp(p+1, ext) != 0)
1973 while (*p && isdigit(*p))
1980 /* Setup xpm_avail */
1982 xpm_getavail(dirname, ext)
1990 for (i=0; i<MAXSQSIZE; ++i)
1993 if (appData.debugMode)
1994 fprintf(stderr, "XPM dir:%s:ext:%s:\n", dirname, ext);
1996 dir = opendir(dirname);
1999 fprintf(stderr, _("%s: Can't access XPM directory %s\n"),
2000 programName, dirname);
2004 while ((ent=readdir(dir)) != NULL) {
2005 i = xpm_getsize(ent->d_name, NAMLEN(ent), ext);
2006 if (i > 0 && i < MAXSQSIZE)
2016 xpm_print_avail(fp, ext)
2022 fprintf(fp, _("Available `%s' sizes:\n"), ext);
2023 for (i=1; i<MAXSQSIZE; ++i) {
2029 /* Return XPM piecesize closest to size */
2031 xpm_closest_to(dirname, size, ext)
2037 int sm_diff = MAXSQSIZE;
2041 xpm_getavail(dirname, ext);
2043 if (appData.debugMode)
2044 xpm_print_avail(stderr, ext);
2046 for (i=1; i<MAXSQSIZE; ++i) {
2049 diff = (diff<0) ? -diff : diff;
2050 if (diff < sm_diff) {
2058 fprintf(stderr, _("Error: No `%s' files!\n"), ext);
2064 #else /* !HAVE_DIR_STRUCT */
2065 /* If we are on a system without a DIR struct, we can't
2066 read the directory, so we can't collect a list of
2067 filenames, etc., so we can't do any size-fitting. */
2069 xpm_closest_to(dirname, size, ext)
2074 fprintf(stderr, _("\
2075 Warning: No DIR structure found on this system --\n\
2076 Unable to autosize for XPM/XIM pieces.\n\
2077 Please report this error to frankm@hiwaay.net.\n\
2078 Include system type & operating system in message.\n"));
2081 #endif /* HAVE_DIR_STRUCT */
2083 static char *cnames[9] = { "black", "red", "green", "yellow", "blue",
2084 "magenta", "cyan", "white" };
2088 TextColors textColors[(int)NColorClasses];
2090 /* String is: "fg, bg, attr". Which is 0, 1, 2 */
2092 parse_color(str, which)
2096 char *p, buf[100], *d;
2099 if (strlen(str) > 99) /* watch bounds on buf */
2104 for (i=0; i<which; ++i) {
2111 /* Could be looking at something like:
2113 .. in which case we want to stop on a comma also */
2114 while (*p && *p != ',' && !isalpha(*p) && !isdigit(*p))
2118 return -1; /* Use default for empty field */
2121 if (which == 2 || isdigit(*p))
2124 while (*p && isalpha(*p))
2129 for (i=0; i<8; ++i) {
2130 if (!StrCaseCmp(buf, cnames[i]))
2131 return which? (i+40) : (i+30);
2133 if (!StrCaseCmp(buf, "default")) return -1;
2135 fprintf(stderr, _("%s: unrecognized color %s\n"), programName, buf);
2140 parse_cpair(cc, str)
2144 if ((textColors[(int)cc].fg=parse_color(str, 0)) == -2) {
2145 fprintf(stderr, _("%s: can't parse foreground color in `%s'\n"),
2150 /* bg and attr are optional */
2151 textColors[(int)cc].bg = parse_color(str, 1);
2152 if ((textColors[(int)cc].attr = parse_color(str, 2)) < 0) {
2153 textColors[(int)cc].attr = 0;
2159 /* Arrange to catch delete-window events */
2160 Atom wm_delete_window;
2162 CatchDeleteWindow(Widget w, String procname)
2165 XSetWMProtocols(xDisplay, XtWindow(w), &wm_delete_window, 1);
2166 snprintf(buf, sizeof(buf), "<Message>WM_PROTOCOLS: %s() \n", procname);
2167 XtAugmentTranslations(w, XtParseTranslationTable(buf));
2174 XtSetArg(args[0], XtNiconic, False);
2175 XtSetValues(shellWidget, args, 1);
2177 XtPopup(shellWidget, XtGrabNone); /* Raise if lowered */
2181 // eventually, all layout determining code should go into a subroutine, but until then IDSIZE remains undefined
2183 #define BoardSize int
2184 void InitDrawingSizes(BoardSize boardSize, int flags)
2185 { // [HGM] resize is functional now, but for board format changes only (nr of ranks, files)
2186 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
2188 XtGeometryResult gres;
2191 if(!formWidget) return;
2194 * Enable shell resizing.
2196 shellArgs[0].value = (XtArgVal) &w;
2197 shellArgs[1].value = (XtArgVal) &h;
2198 XtGetValues(shellWidget, shellArgs, 2);
2200 shellArgs[4].value = 2*w; shellArgs[2].value = 10;
2201 shellArgs[5].value = 2*h; shellArgs[3].value = 10;
2202 XtSetValues(shellWidget, &shellArgs[2], 4);
2204 XtSetArg(args[0], XtNdefaultDistance, &sep);
2205 XtGetValues(formWidget, args, 1);
2207 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2208 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2211 XtSetArg(args[0], XtNwidth, boardWidth);
2212 XtSetArg(args[1], XtNheight, boardHeight);
2213 XtSetValues(boardWidget, args, 2);
2215 timerWidth = (boardWidth - sep) / 2;
2216 XtSetArg(args[0], XtNwidth, timerWidth);
2217 XtSetValues(whiteTimerWidget, args, 1);
2218 XtSetValues(blackTimerWidget, args, 1);
2220 XawFormDoLayout(formWidget, False);
2222 if (appData.titleInWindow) {
2224 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2225 XtSetArg(args[i], XtNheight, &h); i++;
2226 XtGetValues(titleWidget, args, i);
2228 w = boardWidth - 2*bor;
2230 XtSetArg(args[0], XtNwidth, &w);
2231 XtGetValues(menuBarWidget, args, 1);
2232 w = boardWidth - w - sep - 2*bor - 2; // WIDTH_FUDGE
2235 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
2236 if (gres != XtGeometryYes && appData.debugMode) {
2238 _("%s: titleWidget geometry error %d %d %d %d %d\n"),
2239 programName, gres, w, h, wr, hr);
2243 XawFormDoLayout(formWidget, True);
2246 * Inhibit shell resizing.
2248 shellArgs[0].value = w = (XtArgVal) boardWidth + marginW;
2249 shellArgs[1].value = h = (XtArgVal) boardHeight + marginH;
2250 shellArgs[4].value = shellArgs[2].value = w;
2251 shellArgs[5].value = shellArgs[3].value = h;
2252 XtSetValues(shellWidget, &shellArgs[0], 6);
2261 int i, j, clockFontPxlSize, coordFontPxlSize, fontPxlSize;
2262 XSetWindowAttributes window_attributes;
2264 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
2265 XrmValue vFrom, vTo;
2266 XtGeometryResult gres;
2269 int forceMono = False;
2272 // [HGM] before anything else, expand any indirection files amongst options
2273 char *argvCopy[1000]; // 1000 seems enough
2274 char newArgs[10000]; // holds actual characters
2277 srandom(time(0)); // [HGM] book: make random truly random
2280 for(i=0; i<argc; i++) {
2281 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2282 //fprintf(stderr, "arg %s\n", argv[i]);
2283 if(argv[i][0] != '@') argvCopy[j++] = argv[i]; else {
2285 FILE *f = fopen(argv[i]+1, "rb");
2286 if(f == NULL) { fprintf(stderr, _("ignore %s\n"), argv[i]); continue; } // do not expand non-existing
2287 argvCopy[j++] = newArgs + k; // get ready for first argument from file
2288 while((c = fgetc(f)) != EOF) { // each line of file inserts 1 argument in the list
2290 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2291 newArgs[k++] = 0; // terminate current arg
2292 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2293 argvCopy[j++] = newArgs + k; // get ready for next
2295 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2308 if(appData.debugMode,1) { // OK, appData is not initialized here yet...
2309 for(i=0; i<argc; i++) fprintf(stderr, "argv[%2d] = '%s'\n", i, argv[i]);
2315 setbuf(stdout, NULL);
2316 setbuf(stderr, NULL);
2319 programName = strrchr(argv[0], '/');
2320 if (programName == NULL)
2321 programName = argv[0];
2326 XtSetLanguageProc(NULL, NULL, NULL);
2327 bindtextdomain(PRODUCT, LOCALEDIR);
2328 textdomain(PRODUCT);
2332 XtAppInitialize(&appContext, "XBoard", shellOptions,
2333 XtNumber(shellOptions),
2334 &argc, argv, xboardResources, NULL, 0);
2336 fprintf(stderr, _("%s: unrecognized argument %s\n"),
2337 programName, argv[1]);
2338 fprintf(stderr, "Recognized options:\n");
2339 for(i = 0; i < XtNumber(shellOptions); i++) {
2340 j = fprintf(stderr, " %s%s", shellOptions[i].option,
2341 (shellOptions[i].argKind == XrmoptionSepArg
2343 if (i++ < XtNumber(shellOptions)) {
2344 fprintf(stderr, "%*c%s%s\n", 40 - j, ' ',
2345 shellOptions[i].option,
2346 (shellOptions[i].argKind == XrmoptionSepArg
2349 fprintf(stderr, "\n");
2355 if ((chessDir = (char *) getenv("CHESSDIR")) == NULL) {
2358 if (chdir(chessDir) != 0) {
2359 fprintf(stderr, _("%s: can't cd to CHESSDIR: "), programName);
2366 if (p == NULL) p = "/tmp";
2367 i = strlen(p) + strlen("/.xboardXXXXXx.pgn") + 1;
2368 gameCopyFilename = (char*) malloc(i);
2369 gamePasteFilename = (char*) malloc(i);
2370 snprintf(gameCopyFilename,i, "%s/.xboard%05uc.pgn", p, getpid());
2371 snprintf(gamePasteFilename,i, "%s/.xboard%05up.pgn", p, getpid());
2373 XtGetApplicationResources(shellWidget, (XtPointer) &appData,
2374 clientResources, XtNumber(clientResources),
2377 if (appData.debugMode && appData.nameOfDebugFile && strcmp(appData.nameOfDebugFile, "stderr")) {
2378 /* [DM] debug info to file [HGM] make the filename a command-line option, and allow it to remain stderr */
2379 if ((debugFP = fopen(appData.nameOfDebugFile, "w")) == NULL) {
2380 printf(_("Failed to open file '%s'\n"), appData.nameOfDebugFile);
2383 setbuf(debugFP, NULL);
2386 /* [HGM,HR] make sure board size is acceptable */
2387 if(appData.NrFiles > BOARD_SIZE ||
2388 appData.NrRanks > BOARD_SIZE )
2389 DisplayFatalError(_("Recompile with BOARD_SIZE > 12, to support this size"), 0, 2);
2392 /* This feature does not work; animation needs a rewrite */
2393 appData.highlightDragging = FALSE;
2397 xDisplay = XtDisplay(shellWidget);
2398 xScreen = DefaultScreen(xDisplay);
2399 wm_delete_window = XInternAtom(xDisplay, "WM_DELETE_WINDOW", True);
2401 gameInfo.variant = StringToVariant(appData.variant);
2402 InitPosition(FALSE);
2405 * Determine boardSize
2407 gameInfo.boardWidth = gameInfo.boardHeight = 8; // [HGM] boardsize: make sure we start as 8x8
2410 // [HGM] as long as we have not created the possibility to change size while running, start with requested size
2411 gameInfo.boardWidth = appData.NrFiles > 0 ? appData.NrFiles : 8;
2412 gameInfo.boardHeight = appData.NrRanks > 0 ? appData.NrRanks : 8;
2413 gameInfo.holdingsWidth = appData.holdingsSize > 0 ? 2 : 0;
2418 InitDrawingSizes(-1, 0); // [HGM] initsize: make this into a subroutine
2420 if (isdigit(appData.boardSize[0])) {
2421 i = sscanf(appData.boardSize, "%d,%d,%d,%d,%d,%d,%d", &squareSize,
2422 &lineGap, &clockFontPxlSize, &coordFontPxlSize,
2423 &fontPxlSize, &smallLayout, &tinyLayout);
2425 fprintf(stderr, _("%s: bad boardSize syntax %s\n"),
2426 programName, appData.boardSize);
2430 /* Find some defaults; use the nearest known size */
2431 SizeDefaults *szd, *nearest;
2432 int distance = 99999;
2433 nearest = szd = sizeDefaults;
2434 while (szd->name != NULL) {
2435 if (abs(szd->squareSize - squareSize) < distance) {
2437 distance = abs(szd->squareSize - squareSize);
2438 if (distance == 0) break;
2442 if (i < 2) lineGap = nearest->lineGap;
2443 if (i < 3) clockFontPxlSize = nearest->clockFontPxlSize;
2444 if (i < 4) coordFontPxlSize = nearest->coordFontPxlSize;
2445 if (i < 5) fontPxlSize = nearest->fontPxlSize;
2446 if (i < 6) smallLayout = nearest->smallLayout;
2447 if (i < 7) tinyLayout = nearest->tinyLayout;
2450 SizeDefaults *szd = sizeDefaults;
2451 if (*appData.boardSize == NULLCHAR) {
2452 while (DisplayWidth(xDisplay, xScreen) < szd->minScreenSize ||
2453 DisplayHeight(xDisplay, xScreen) < szd->minScreenSize) {
2456 if (szd->name == NULL) szd--;
2458 while (szd->name != NULL &&
2459 StrCaseCmp(szd->name, appData.boardSize) != 0) szd++;
2460 if (szd->name == NULL) {
2461 fprintf(stderr, _("%s: unrecognized boardSize name %s\n"),
2462 programName, appData.boardSize);
2466 squareSize = szd->squareSize;
2467 lineGap = szd->lineGap;
2468 clockFontPxlSize = szd->clockFontPxlSize;
2469 coordFontPxlSize = szd->coordFontPxlSize;
2470 fontPxlSize = szd->fontPxlSize;
2471 smallLayout = szd->smallLayout;
2472 tinyLayout = szd->tinyLayout;
2475 /* Now, using squareSize as a hint, find a good XPM/XIM set size */
2476 if (strlen(appData.pixmapDirectory) > 0) {
2477 p = ExpandPathName(appData.pixmapDirectory);
2479 fprintf(stderr, _("Error expanding path name \"%s\"\n"),
2480 appData.pixmapDirectory);
2483 if (appData.debugMode) {
2484 fprintf(stderr, _("\
2485 XBoard square size (hint): %d\n\
2486 %s fulldir:%s:\n"), squareSize, IMAGE_EXT, p);
2488 squareSize = xpm_closest_to(p, squareSize, IMAGE_EXT);
2489 if (appData.debugMode) {
2490 fprintf(stderr, _("Closest %s size: %d\n"), IMAGE_EXT, squareSize);
2494 /* [HR] height treated separately (hacked) */
2495 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2496 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2497 if (appData.showJail == 1) {
2498 /* Jail on top and bottom */
2499 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2500 XtSetArg(boardArgs[2], XtNheight,
2501 boardHeight + 2*(lineGap + squareSize));
2502 } else if (appData.showJail == 2) {
2504 XtSetArg(boardArgs[1], XtNwidth,
2505 boardWidth + 2*(lineGap + squareSize));
2506 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2509 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2510 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2514 * Determine what fonts to use.
2516 appData.clockFont = FindFont(appData.clockFont, clockFontPxlSize);
2517 clockFontID = XLoadFont(xDisplay, appData.clockFont);
2518 clockFontStruct = XQueryFont(xDisplay, clockFontID);
2519 appData.coordFont = FindFont(appData.coordFont, coordFontPxlSize);
2520 coordFontID = XLoadFont(xDisplay, appData.coordFont);
2521 coordFontStruct = XQueryFont(xDisplay, coordFontID);
2522 appData.font = FindFont(appData.font, fontPxlSize);
2523 countFontID = XLoadFont(xDisplay, appData.coordFont); // [HGM] holdings
2524 countFontStruct = XQueryFont(xDisplay, countFontID);
2525 // appData.font = FindFont(appData.font, fontPxlSize);
2527 xdb = XtDatabase(xDisplay);
2528 XrmPutStringResource(&xdb, "*font", appData.font);
2531 * Detect if there are not enough colors available and adapt.
2533 if (DefaultDepth(xDisplay, xScreen) <= 2) {
2534 appData.monoMode = True;
2537 if (!appData.monoMode) {
2538 vFrom.addr = (caddr_t) appData.lightSquareColor;
2539 vFrom.size = strlen(appData.lightSquareColor);
2540 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2541 if (vTo.addr == NULL) {
2542 appData.monoMode = True;
2545 lightSquareColor = *(Pixel *) vTo.addr;
2548 if (!appData.monoMode) {
2549 vFrom.addr = (caddr_t) appData.darkSquareColor;
2550 vFrom.size = strlen(appData.darkSquareColor);
2551 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2552 if (vTo.addr == NULL) {
2553 appData.monoMode = True;
2556 darkSquareColor = *(Pixel *) vTo.addr;
2559 if (!appData.monoMode) {
2560 vFrom.addr = (caddr_t) appData.whitePieceColor;
2561 vFrom.size = strlen(appData.whitePieceColor);
2562 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2563 if (vTo.addr == NULL) {
2564 appData.monoMode = True;
2567 whitePieceColor = *(Pixel *) vTo.addr;
2570 if (!appData.monoMode) {
2571 vFrom.addr = (caddr_t) appData.blackPieceColor;
2572 vFrom.size = strlen(appData.blackPieceColor);
2573 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2574 if (vTo.addr == NULL) {
2575 appData.monoMode = True;
2578 blackPieceColor = *(Pixel *) vTo.addr;
2582 if (!appData.monoMode) {
2583 vFrom.addr = (caddr_t) appData.highlightSquareColor;
2584 vFrom.size = strlen(appData.highlightSquareColor);
2585 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2586 if (vTo.addr == NULL) {
2587 appData.monoMode = True;
2590 highlightSquareColor = *(Pixel *) vTo.addr;
2594 if (!appData.monoMode) {
2595 vFrom.addr = (caddr_t) appData.premoveHighlightColor;
2596 vFrom.size = strlen(appData.premoveHighlightColor);
2597 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2598 if (vTo.addr == NULL) {
2599 appData.monoMode = True;
2602 premoveHighlightColor = *(Pixel *) vTo.addr;
2607 fprintf(stderr, _("%s: too few colors available; trying monochrome mode\n"),
2610 if (appData.bitmapDirectory == NULL ||
2611 appData.bitmapDirectory[0] == NULLCHAR)
2612 appData.bitmapDirectory = DEF_BITMAP_DIR;
2615 if (appData.lowTimeWarning && !appData.monoMode) {
2616 vFrom.addr = (caddr_t) appData.lowTimeWarningColor;
2617 vFrom.size = strlen(appData.lowTimeWarningColor);
2618 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2619 if (vTo.addr == NULL)
2620 appData.monoMode = True;
2622 lowTimeWarningColor = *(Pixel *) vTo.addr;
2625 if (appData.monoMode && appData.debugMode) {
2626 fprintf(stderr, _("white pixel = 0x%lx, black pixel = 0x%lx\n"),
2627 (unsigned long) XWhitePixel(xDisplay, xScreen),
2628 (unsigned long) XBlackPixel(xDisplay, xScreen));
2631 if (parse_cpair(ColorShout, appData.colorShout) < 0 ||
2632 parse_cpair(ColorSShout, appData.colorSShout) < 0 ||
2633 parse_cpair(ColorChannel1, appData.colorChannel1) < 0 ||
2634 parse_cpair(ColorChannel, appData.colorChannel) < 0 ||
2635 parse_cpair(ColorKibitz, appData.colorKibitz) < 0 ||
2636 parse_cpair(ColorTell, appData.colorTell) < 0 ||
2637 parse_cpair(ColorChallenge, appData.colorChallenge) < 0 ||
2638 parse_cpair(ColorRequest, appData.colorRequest) < 0 ||
2639 parse_cpair(ColorSeek, appData.colorSeek) < 0 ||
2640 parse_cpair(ColorNormal, appData.colorNormal) < 0)
2642 if (appData.colorize) {
2644 _("%s: can't parse color names; disabling colorization\n"),
2647 appData.colorize = FALSE;
2649 textColors[ColorNone].fg = textColors[ColorNone].bg = -1;
2650 textColors[ColorNone].attr = 0;
2652 XtAppAddActions(appContext, boardActions, XtNumber(boardActions));
2658 layoutName = "tinyLayout";
2659 } else if (smallLayout) {
2660 layoutName = "smallLayout";
2662 layoutName = "normalLayout";
2664 /* Outer layoutWidget is there only to provide a name for use in
2665 resources that depend on the layout style */
2667 XtCreateManagedWidget(layoutName, formWidgetClass, shellWidget,
2668 layoutArgs, XtNumber(layoutArgs));
2670 XtCreateManagedWidget("form", formWidgetClass, layoutWidget,
2671 formArgs, XtNumber(formArgs));
2672 XtSetArg(args[0], XtNdefaultDistance, &sep);
2673 XtGetValues(formWidget, args, 1);
2676 widgetList[j++] = menuBarWidget = CreateMenuBar(menuBar);
2677 XtSetArg(args[0], XtNtop, XtChainTop);
2678 XtSetArg(args[1], XtNbottom, XtChainTop);
2679 XtSetValues(menuBarWidget, args, 2);
2681 widgetList[j++] = whiteTimerWidget =
2682 XtCreateWidget("whiteTime", labelWidgetClass,
2683 formWidget, timerArgs, XtNumber(timerArgs));
2684 XtSetArg(args[0], XtNfont, clockFontStruct);
2685 XtSetArg(args[1], XtNtop, XtChainTop);
2686 XtSetArg(args[2], XtNbottom, XtChainTop);
2687 XtSetValues(whiteTimerWidget, args, 3);
2689 widgetList[j++] = blackTimerWidget =
2690 XtCreateWidget("blackTime", labelWidgetClass,
2691 formWidget, timerArgs, XtNumber(timerArgs));
2692 XtSetArg(args[0], XtNfont, clockFontStruct);
2693 XtSetArg(args[1], XtNtop, XtChainTop);
2694 XtSetArg(args[2], XtNbottom, XtChainTop);
2695 XtSetValues(blackTimerWidget, args, 3);
2697 if (appData.titleInWindow) {
2698 widgetList[j++] = titleWidget =
2699 XtCreateWidget("title", labelWidgetClass, formWidget,
2700 titleArgs, XtNumber(titleArgs));
2701 XtSetArg(args[0], XtNtop, XtChainTop);
2702 XtSetArg(args[1], XtNbottom, XtChainTop);
2703 XtSetValues(titleWidget, args, 2);
2706 if (appData.showButtonBar) {
2707 widgetList[j++] = buttonBarWidget = CreateButtonBar(buttonBar);
2708 XtSetArg(args[0], XtNleft, XtChainRight); // [HGM] glue to right window edge
2709 XtSetArg(args[1], XtNright, XtChainRight); // for good run-time sizing
2710 XtSetArg(args[2], XtNtop, XtChainTop);
2711 XtSetArg(args[3], XtNbottom, XtChainTop);
2712 XtSetValues(buttonBarWidget, args, 4);
2715 widgetList[j++] = messageWidget =
2716 XtCreateWidget("message", labelWidgetClass, formWidget,
2717 messageArgs, XtNumber(messageArgs));
2718 XtSetArg(args[0], XtNtop, XtChainTop);
2719 XtSetArg(args[1], XtNbottom, XtChainTop);
2720 XtSetValues(messageWidget, args, 2);
2722 widgetList[j++] = boardWidget =
2723 XtCreateWidget("board", widgetClass, formWidget, boardArgs,
2724 XtNumber(boardArgs));
2726 XtManageChildren(widgetList, j);
2728 timerWidth = (boardWidth - sep) / 2;
2729 XtSetArg(args[0], XtNwidth, timerWidth);
2730 XtSetValues(whiteTimerWidget, args, 1);
2731 XtSetValues(blackTimerWidget, args, 1);
2733 XtSetArg(args[0], XtNbackground, &timerBackgroundPixel);
2734 XtSetArg(args[1], XtNforeground, &timerForegroundPixel);
2735 XtGetValues(whiteTimerWidget, args, 2);
2737 if (appData.showButtonBar) {
2738 XtSetArg(args[0], XtNbackground, &buttonBackgroundPixel);
2739 XtSetArg(args[1], XtNforeground, &buttonForegroundPixel);
2740 XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
2744 * formWidget uses these constraints but they are stored
2748 XtSetArg(args[i], XtNfromHoriz, 0); i++;
2749 XtSetValues(menuBarWidget, args, i);
2750 if (appData.titleInWindow) {
2753 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2754 XtSetValues(whiteTimerWidget, args, i);
2756 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2757 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2758 XtSetValues(blackTimerWidget, args, i);
2760 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2761 XtSetArg(args[i], XtNjustify, XtJustifyLeft); i++;
2762 XtSetValues(titleWidget, args, i);
2764 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2765 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2766 XtSetValues(messageWidget, args, i);
2767 if (appData.showButtonBar) {
2769 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2770 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2771 XtSetValues(buttonBarWidget, args, i);
2775 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2776 XtSetValues(whiteTimerWidget, args, i);
2778 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2779 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2780 XtSetValues(blackTimerWidget, args, i);
2782 XtSetArg(args[i], XtNfromHoriz, menuBarWidget); i++;
2783 XtSetValues(titleWidget, args, i);
2785 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2786 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2787 XtSetValues(messageWidget, args, i);
2788 if (appData.showButtonBar) {
2790 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2791 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2792 XtSetValues(buttonBarWidget, args, i);
2797 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2798 XtSetValues(whiteTimerWidget, args, i);
2800 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2801 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2802 XtSetValues(blackTimerWidget, args, i);
2804 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2805 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2806 XtSetValues(messageWidget, args, i);
2807 if (appData.showButtonBar) {
2809 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2810 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2811 XtSetValues(buttonBarWidget, args, i);
2815 XtSetArg(args[0], XtNfromVert, messageWidget);
2816 XtSetArg(args[1], XtNtop, XtChainTop);
2817 XtSetArg(args[2], XtNbottom, XtChainBottom);
2818 XtSetArg(args[3], XtNleft, XtChainLeft);
2819 XtSetArg(args[4], XtNright, XtChainRight);
2820 XtSetValues(boardWidget, args, 5);
2822 XtRealizeWidget(shellWidget);
2825 * Correct the width of the message and title widgets.
2826 * It is not known why some systems need the extra fudge term.
2827 * The value "2" is probably larger than needed.
2829 XawFormDoLayout(formWidget, False);
2831 #define WIDTH_FUDGE 2
2833 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2834 XtSetArg(args[i], XtNheight, &h); i++;
2835 XtGetValues(messageWidget, args, i);
2836 if (appData.showButtonBar) {
2838 XtSetArg(args[i], XtNwidth, &w); i++;
2839 XtGetValues(buttonBarWidget, args, i);
2840 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2842 w = boardWidth - 2*bor + 1; /*!! +1 compensates for kludge below */
2845 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2846 if (gres != XtGeometryYes && appData.debugMode) {
2847 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2848 programName, gres, w, h, wr, hr);
2851 /* !! Horrible hack to work around bug in XFree86 4.0.1 (X11R6.4.3) */
2852 /* The size used for the child widget in layout lags one resize behind
2853 its true size, so we resize a second time, 1 pixel smaller. Yeech! */
2855 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2856 if (gres != XtGeometryYes && appData.debugMode) {
2857 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2858 programName, gres, w, h, wr, hr);
2861 XtSetArg(args[0], XtNleft, XtChainLeft); // [HGM] glue ends for good run-time sizing
2862 XtSetArg(args[1], XtNright, XtChainRight);
2863 XtSetValues(messageWidget, args, 2);
2865 if (appData.titleInWindow) {
2867 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2868 XtSetArg(args[i], XtNheight, &h); i++;
2869 XtGetValues(titleWidget, args, i);
2871 w = boardWidth - 2*bor;
2873 XtSetArg(args[0], XtNwidth, &w);
2874 XtGetValues(menuBarWidget, args, 1);
2875 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2878 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
2879 if (gres != XtGeometryYes && appData.debugMode) {
2881 _("%s: titleWidget geometry error %d %d %d %d %d\n"),
2882 programName, gres, w, h, wr, hr);
2885 XawFormDoLayout(formWidget, True);
2887 xBoardWindow = XtWindow(boardWidget);
2889 // [HGM] it seems the layout code ends here, but perhaps the color stuff is size independent and would
2890 // not need to go into InitDrawingSizes().
2894 * Create X checkmark bitmap and initialize option menu checks.
2896 ReadBitmap(&xMarkPixmap, "checkmark.bm",
2897 checkmark_bits, checkmark_width, checkmark_height);
2898 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
2899 if (appData.alwaysPromoteToQueen) {
2900 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
2903 if (appData.animateDragging) {
2904 XtSetValues(XtNameToWidget(menuBarWidget,
2905 "menuOptions.Animate Dragging"),
2908 if (appData.animate) {
2909 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
2912 if (appData.autoComment) {
2913 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
2916 if (appData.autoCallFlag) {
2917 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
2920 if (appData.autoFlipView) {
2921 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Auto Flip View"),
2924 if (appData.autoObserve) {
2925 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
2928 if (appData.autoRaiseBoard) {
2929 XtSetValues(XtNameToWidget(menuBarWidget,
2930 "menuOptions.Auto Raise Board"), args, 1);
2932 if (appData.autoSaveGames) {
2933 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
2936 if (appData.saveGameFile[0] != NULLCHAR) {
2937 /* Can't turn this off from menu */
2938 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
2940 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
2944 if (appData.blindfold) {
2945 XtSetValues(XtNameToWidget(menuBarWidget,
2946 "menuOptions.Blindfold"), args, 1);
2948 if (appData.flashCount > 0) {
2949 XtSetValues(XtNameToWidget(menuBarWidget,
2950 "menuOptions.Flash Moves"),
2953 if (appData.getMoveList) {
2954 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
2958 if (appData.highlightDragging) {
2959 XtSetValues(XtNameToWidget(menuBarWidget,
2960 "menuOptions.Highlight Dragging"),
2964 if (appData.highlightLastMove) {
2965 XtSetValues(XtNameToWidget(menuBarWidget,
2966 "menuOptions.Highlight Last Move"),
2969 if (appData.icsAlarm) {
2970 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.ICS Alarm"),
2973 if (appData.ringBellAfterMoves) {
2974 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
2977 if (appData.oldSaveStyle) {
2978 XtSetValues(XtNameToWidget(menuBarWidget,
2979 "menuOptions.Old Save Style"), args, 1);
2981 if (appData.periodicUpdates) {
2982 XtSetValues(XtNameToWidget(menuBarWidget,
2983 "menuOptions.Periodic Updates"), args, 1);
2985 if (appData.ponderNextMove) {
2986 XtSetValues(XtNameToWidget(menuBarWidget,
2987 "menuOptions.Ponder Next Move"), args, 1);
2989 if (appData.popupExitMessage) {
2990 XtSetValues(XtNameToWidget(menuBarWidget,
2991 "menuOptions.Popup Exit Message"), args, 1);
2993 if (appData.popupMoveErrors) {
2994 XtSetValues(XtNameToWidget(menuBarWidget,
2995 "menuOptions.Popup Move Errors"), args, 1);
2997 if (appData.premove) {
2998 XtSetValues(XtNameToWidget(menuBarWidget,
2999 "menuOptions.Premove"), args, 1);
3001 if (appData.quietPlay) {
3002 XtSetValues(XtNameToWidget(menuBarWidget,
3003 "menuOptions.Quiet Play"), args, 1);
3005 if (appData.showCoords) {
3006 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
3009 if (appData.hideThinkingFromHuman) {
3010 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
3013 if (appData.testLegality) {
3014 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Test Legality"),
3021 ReadBitmap(&wIconPixmap, "icon_white.bm",
3022 icon_white_bits, icon_white_width, icon_white_height);
3023 ReadBitmap(&bIconPixmap, "icon_black.bm",
3024 icon_black_bits, icon_black_width, icon_black_height);
3025 iconPixmap = wIconPixmap;
3027 XtSetArg(args[i], XtNiconPixmap, iconPixmap); i++;
3028 XtSetValues(shellWidget, args, i);
3031 * Create a cursor for the board widget.
3033 window_attributes.cursor = XCreateFontCursor(xDisplay, XC_hand2);
3034 XChangeWindowAttributes(xDisplay, xBoardWindow,
3035 CWCursor, &window_attributes);
3038 * Inhibit shell resizing.
3040 shellArgs[0].value = (XtArgVal) &w;
3041 shellArgs[1].value = (XtArgVal) &h;
3042 XtGetValues(shellWidget, shellArgs, 2);
3043 shellArgs[4].value = shellArgs[2].value = w;
3044 shellArgs[5].value = shellArgs[3].value = h;
3045 XtSetValues(shellWidget, &shellArgs[2], 4);
3046 marginW = w - boardWidth; // [HGM] needed to set new shellWidget size when we resize board
3047 marginH = h - boardHeight;
3049 CatchDeleteWindow(shellWidget, "QuitProc");
3054 if (appData.bitmapDirectory[0] != NULLCHAR) {
3061 /* Create regular pieces */
3062 if (!useImages) CreatePieces();
3067 if (appData.animate || appData.animateDragging)
3070 XtAugmentTranslations(formWidget,
3071 XtParseTranslationTable(globalTranslations));
3072 XtAugmentTranslations(boardWidget,
3073 XtParseTranslationTable(boardTranslations));
3074 XtAugmentTranslations(whiteTimerWidget,
3075 XtParseTranslationTable(whiteTranslations));
3076 XtAugmentTranslations(blackTimerWidget,
3077 XtParseTranslationTable(blackTranslations));
3079 /* Why is the following needed on some versions of X instead
3080 * of a translation? */
3081 XtAddEventHandler(boardWidget, ExposureMask, False,
3082 (XtEventHandler) EventProc, NULL);
3087 if (errorExitStatus == -1) {
3088 if (appData.icsActive) {
3089 /* We now wait until we see "login:" from the ICS before
3090 sending the logon script (problems with timestamp otherwise) */
3091 /*ICSInitScript();*/
3092 if (appData.icsInputBox) ICSInputBoxPopUp();
3095 signal(SIGINT, IntSigHandler);
3096 signal(SIGTERM, IntSigHandler);
3097 if (*appData.cmailGameName != NULLCHAR) {
3098 signal(SIGUSR1, CmailSigHandler);
3103 XtAppMainLoop(appContext);
3104 if (appData.debugMode) fclose(debugFP); // [DM] debug
3111 if (appData.icsActive && oldICSInteractionTitle != NULL) {
3112 DisplayIcsInteractionTitle(oldICSInteractionTitle);
3114 unlink(gameCopyFilename);
3115 unlink(gamePasteFilename);
3126 CmailSigHandler(sig)
3132 signal(SIGUSR1, SIG_IGN); /* suspend handler */
3134 /* Activate call-back function CmailSigHandlerCallBack() */
3135 OutputToProcess(cmailPR, (char *)(&dummy), sizeof(int), &error);
3137 signal(SIGUSR1, CmailSigHandler); /* re-activate handler */
3141 CmailSigHandlerCallBack(isr, closure, message, count, error)
3149 ReloadCmailMsgEvent(TRUE); /* Reload cmail msg */
3151 /**** end signal code ****/
3161 f = fopen(appData.icsLogon, "r");
3167 strcat(buf, appData.icsLogon);
3168 f = fopen(buf, "r");
3172 ProcessICSInitScript(f);
3179 EditCommentPopDown();
3190 SetMenuEnables(enab)
3194 if (!menuBarWidget) return;
3195 while (enab->name != NULL) {
3196 w = XtNameToWidget(menuBarWidget, enab->name);
3198 DisplayError(enab->name, 0);
3200 XtSetSensitive(w, enab->value);
3206 Enables icsEnables[] = {
3207 { "menuFile.Mail Move", False },
3208 { "menuFile.Reload CMail Message", False },
3209 { "menuMode.Machine Black", False },
3210 { "menuMode.Machine White", False },
3211 { "menuMode.Analysis Mode", False },
3212 { "menuMode.Analyze File", False },
3213 { "menuMode.Two Machines", False },
3215 { "menuHelp.Hint", False },
3216 { "menuHelp.Book", False },
3217 { "menuStep.Move Now", False },
3218 { "menuOptions.Periodic Updates", False },
3219 { "menuOptions.Hide Thinking", False },
3220 { "menuOptions.Ponder Next Move", False },
3225 Enables ncpEnables[] = {
3226 { "menuFile.Mail Move", False },
3227 { "menuFile.Reload CMail Message", False },
3228 { "menuMode.Machine White", False },
3229 { "menuMode.Machine Black", False },
3230 { "menuMode.Analysis Mode", False },
3231 { "menuMode.Analyze File", False },
3232 { "menuMode.Two Machines", False },
3233 { "menuMode.ICS Client", False },
3234 { "menuMode.ICS Input Box", False },
3235 { "Action", False },
3236 { "menuStep.Revert", False },
3237 { "menuStep.Move Now", False },
3238 { "menuStep.Retract Move", False },
3239 { "menuOptions.Auto Comment", False },
3240 { "menuOptions.Auto Flag", False },
3241 { "menuOptions.Auto Flip View", False },
3242 { "menuOptions.Auto Observe", False },
3243 { "menuOptions.Auto Raise Board", False },
3244 { "menuOptions.Get Move List", False },
3245 { "menuOptions.ICS Alarm", False },
3246 { "menuOptions.Move Sound", False },
3247 { "menuOptions.Quiet Play", False },
3248 { "menuOptions.Hide Thinking", False },
3249 { "menuOptions.Periodic Updates", False },
3250 { "menuOptions.Ponder Next Move", False },
3251 { "menuHelp.Hint", False },
3252 { "menuHelp.Book", False },
3256 Enables gnuEnables[] = {
3257 { "menuMode.ICS Client", False },
3258 { "menuMode.ICS Input Box", False },
3259 { "menuAction.Accept", False },
3260 { "menuAction.Decline", False },
3261 { "menuAction.Rematch", False },
3262 { "menuAction.Adjourn", False },
3263 { "menuAction.Stop Examining", False },
3264 { "menuAction.Stop Observing", False },
3265 { "menuStep.Revert", False },
3266 { "menuOptions.Auto Comment", False },
3267 { "menuOptions.Auto Observe", False },
3268 { "menuOptions.Auto Raise Board", False },
3269 { "menuOptions.Get Move List", False },
3270 { "menuOptions.Premove", False },
3271 { "menuOptions.Quiet Play", False },
3273 /* The next two options rely on SetCmailMode being called *after* */
3274 /* SetGNUMode so that when GNU is being used to give hints these */
3275 /* menu options are still available */
3277 { "menuFile.Mail Move", False },
3278 { "menuFile.Reload CMail Message", False },
3282 Enables cmailEnables[] = {
3284 { "menuAction.Call Flag", False },
3285 { "menuAction.Draw", True },
3286 { "menuAction.Adjourn", False },
3287 { "menuAction.Abort", False },
3288 { "menuAction.Stop Observing", False },
3289 { "menuAction.Stop Examining", False },
3290 { "menuFile.Mail Move", True },
3291 { "menuFile.Reload CMail Message", True },
3295 Enables trainingOnEnables[] = {
3296 { "menuMode.Edit Comment", False },
3297 { "menuMode.Pause", False },
3298 { "menuStep.Forward", False },
3299 { "menuStep.Backward", False },
3300 { "menuStep.Forward to End", False },
3301 { "menuStep.Back to Start", False },
3302 { "menuStep.Move Now", False },
3303 { "menuStep.Truncate Game", False },
3307 Enables trainingOffEnables[] = {
3308 { "menuMode.Edit Comment", True },
3309 { "menuMode.Pause", True },
3310 { "menuStep.Forward", True },
3311 { "menuStep.Backward", True },
3312 { "menuStep.Forward to End", True },
3313 { "menuStep.Back to Start", True },
3314 { "menuStep.Move Now", True },
3315 { "menuStep.Truncate Game", True },
3319 Enables machineThinkingEnables[] = {
3320 { "menuFile.Load Game", False },
3321 { "menuFile.Load Next Game", False },
3322 { "menuFile.Load Previous Game", False },
3323 { "menuFile.Reload Same Game", False },
3324 { "menuFile.Paste Game", False },
3325 { "menuFile.Load Position", False },
3326 { "menuFile.Load Next Position", False },
3327 { "menuFile.Load Previous Position", False },
3328 { "menuFile.Reload Same Position", False },
3329 { "menuFile.Paste Position", False },
3330 { "menuMode.Machine White", False },
3331 { "menuMode.Machine Black", False },
3332 { "menuMode.Two Machines", False },
3333 { "menuStep.Retract Move", False },
3337 Enables userThinkingEnables[] = {
3338 { "menuFile.Load Game", True },
3339 { "menuFile.Load Next Game", True },
3340 { "menuFile.Load Previous Game", True },
3341 { "menuFile.Reload Same Game", True },
3342 { "menuFile.Paste Game", True },
3343 { "menuFile.Load Position", True },
3344 { "menuFile.Load Next Position", True },
3345 { "menuFile.Load Previous Position", True },
3346 { "menuFile.Reload Same Position", True },
3347 { "menuFile.Paste Position", True },
3348 { "menuMode.Machine White", True },
3349 { "menuMode.Machine Black", True },
3350 { "menuMode.Two Machines", True },
3351 { "menuStep.Retract Move", True },
3357 SetMenuEnables(icsEnables);
3360 if (appData.zippyPlay && !appData.noChessProgram) /* [DM] icsEngineAnalyze */
3361 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Analysis Mode"), True);
3368 SetMenuEnables(ncpEnables);
3374 SetMenuEnables(gnuEnables);
3380 SetMenuEnables(cmailEnables);
3386 SetMenuEnables(trainingOnEnables);
3387 if (appData.showButtonBar) {
3388 XtSetSensitive(buttonBarWidget, False);
3394 SetTrainingModeOff()
3396 SetMenuEnables(trainingOffEnables);
3397 if (appData.showButtonBar) {
3398 XtSetSensitive(buttonBarWidget, True);
3403 SetUserThinkingEnables()
3405 if (appData.noChessProgram) return;
3406 SetMenuEnables(userThinkingEnables);
3410 SetMachineThinkingEnables()
3412 if (appData.noChessProgram) return;
3413 SetMenuEnables(machineThinkingEnables);
3415 case MachinePlaysBlack:
3416 case MachinePlaysWhite:
3417 case TwoMachinesPlay:
3418 XtSetSensitive(XtNameToWidget(menuBarWidget,
3419 ModeToWidgetName(gameMode)), True);
3426 #define Abs(n) ((n)<0 ? -(n) : (n))
3429 * Find a font that matches "pattern" that is as close as
3430 * possible to the targetPxlSize. Prefer fonts that are k
3431 * pixels smaller to fonts that are k pixels larger. The
3432 * pattern must be in the X Consortium standard format,
3433 * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".
3434 * The return value should be freed with XtFree when no
3437 char *FindFont(pattern, targetPxlSize)
3441 char **fonts, *p, *best, *scalable, *scalableTail;
3442 int i, j, nfonts, minerr, err, pxlSize;
3445 char **missing_list;
3447 char *def_string, *base_fnt_lst, strInt[3];
3449 XFontStruct **fnt_list;
3451 base_fnt_lst = calloc(1, strlen(pattern) + 3);
3452 sprintf(strInt, "%d", targetPxlSize);
3453 p = strstr(pattern, "--");
3454 strncpy(base_fnt_lst, pattern, p - pattern + 2);
3455 strcat(base_fnt_lst, strInt);
3456 strcat(base_fnt_lst, strchr(p + 2, '-'));
3458 if ((fntSet = XCreateFontSet(xDisplay,
3462 &def_string)) == NULL) {
3464 fprintf(stderr, _("Unable to create font set.\n"));
3468 nfonts = XFontsOfFontSet(fntSet, &fnt_list, &fonts);
3470 fonts = XListFonts(xDisplay, pattern, 999999, &nfonts);
3472 fprintf(stderr, _("%s: no fonts match pattern %s\n"),
3473 programName, pattern);
3481 for (i=0; i<nfonts; i++) {
3484 if (*p != '-') continue;
3486 if (*p == NULLCHAR) break;
3487 if (*p++ == '-') j++;
3489 if (j < 7) continue;
3492 scalable = fonts[i];
3495 err = pxlSize - targetPxlSize;
3496 if (Abs(err) < Abs(minerr) ||
3497 (minerr > 0 && err < 0 && -err == minerr)) {
3503 if (scalable && Abs(minerr) > appData.fontSizeTolerance) {
3504 /* If the error is too big and there is a scalable font,
3505 use the scalable font. */
3506 int headlen = scalableTail - scalable;
3507 p = (char *) XtMalloc(strlen(scalable) + 10);
3508 while (isdigit(*scalableTail)) scalableTail++;
3509 sprintf(p, "%.*s%d%s", headlen, scalable, targetPxlSize, scalableTail);
3511 p = (char *) XtMalloc(strlen(best) + 1);
3514 if (appData.debugMode) {
3515 fprintf(debugFP, _("resolved %s at pixel size %d\n to %s\n"),
3516 pattern, targetPxlSize, p);
3519 if (missing_count > 0)
3520 XFreeStringList(missing_list);
3521 XFreeFontSet(xDisplay, fntSet);
3523 XFreeFontNames(fonts);
3530 XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
3531 | GCBackground | GCFunction | GCPlaneMask;
3532 XGCValues gc_values;
3535 gc_values.plane_mask = AllPlanes;
3536 gc_values.line_width = lineGap;
3537 gc_values.line_style = LineSolid;
3538 gc_values.function = GXcopy;
3540 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3541 gc_values.background = XBlackPixel(xDisplay, xScreen);
3542 lineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3544 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3545 gc_values.background = XWhitePixel(xDisplay, xScreen);
3546 coordGC = XtGetGC(shellWidget, value_mask, &gc_values);
3547 XSetFont(xDisplay, coordGC, coordFontID);
3549 // [HGM] make font for holdings counts (white on black0
3550 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3551 gc_values.background = XBlackPixel(xDisplay, xScreen);
3552 countGC = XtGetGC(shellWidget, value_mask, &gc_values);
3553 XSetFont(xDisplay, countGC, countFontID);
3555 if (appData.monoMode) {
3556 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3557 gc_values.background = XWhitePixel(xDisplay, xScreen);
3558 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3560 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3561 gc_values.background = XBlackPixel(xDisplay, xScreen);
3562 lightSquareGC = wbPieceGC
3563 = XtGetGC(shellWidget, value_mask, &gc_values);
3565 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3566 gc_values.background = XWhitePixel(xDisplay, xScreen);
3567 darkSquareGC = bwPieceGC
3568 = XtGetGC(shellWidget, value_mask, &gc_values);
3570 if (DefaultDepth(xDisplay, xScreen) == 1) {
3571 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
3572 gc_values.function = GXcopyInverted;
3573 copyInvertedGC = XtGetGC(shellWidget, value_mask, &gc_values);
3574 gc_values.function = GXcopy;
3575 if (XBlackPixel(xDisplay, xScreen) == 1) {
3576 bwPieceGC = darkSquareGC;
3577 wbPieceGC = copyInvertedGC;
3579 bwPieceGC = copyInvertedGC;
3580 wbPieceGC = lightSquareGC;
3584 gc_values.foreground = highlightSquareColor;
3585 gc_values.background = highlightSquareColor;
3586 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3588 gc_values.foreground = premoveHighlightColor;
3589 gc_values.background = premoveHighlightColor;
3590 prelineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3592 gc_values.foreground = lightSquareColor;
3593 gc_values.background = darkSquareColor;
3594 lightSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3596 gc_values.foreground = darkSquareColor;
3597 gc_values.background = lightSquareColor;
3598 darkSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3600 gc_values.foreground = jailSquareColor;
3601 gc_values.background = jailSquareColor;
3602 jailSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3604 gc_values.foreground = whitePieceColor;
3605 gc_values.background = darkSquareColor;
3606 wdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3608 gc_values.foreground = whitePieceColor;
3609 gc_values.background = lightSquareColor;
3610 wlPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3612 gc_values.foreground = whitePieceColor;
3613 gc_values.background = jailSquareColor;
3614 wjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3616 gc_values.foreground = blackPieceColor;
3617 gc_values.background = darkSquareColor;
3618 bdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3620 gc_values.foreground = blackPieceColor;
3621 gc_values.background = lightSquareColor;
3622 blPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3624 gc_values.foreground = blackPieceColor;
3625 gc_values.background = jailSquareColor;
3626 bjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3630 void loadXIM(xim, xmask, filename, dest, mask)
3643 fp = fopen(filename, "rb");
3645 fprintf(stderr, _("%s: error loading XIM!\n"), programName);
3652 for (y=0; y<h; ++y) {
3653 for (x=0; x<h; ++x) {
3658 XPutPixel(xim, x, y, blackPieceColor);
3660 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3663 XPutPixel(xim, x, y, darkSquareColor);
3665 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3668 XPutPixel(xim, x, y, whitePieceColor);
3670 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3673 XPutPixel(xim, x, y, lightSquareColor);
3675 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3681 /* create Pixmap of piece */
3682 *dest = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3684 XPutImage(xDisplay, *dest, lightSquareGC, xim,
3687 /* create Pixmap of clipmask
3688 Note: We assume the white/black pieces have the same
3689 outline, so we make only 6 masks. This is okay
3690 since the XPM clipmask routines do the same. */
3692 temp = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3694 XPutImage(xDisplay, temp, lightSquareGC, xmask,
3697 /* now create the 1-bit version */
3698 *mask = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3701 values.foreground = 1;
3702 values.background = 0;
3704 /* Don't use XtGetGC, not read only */
3705 maskGC = XCreateGC(xDisplay, *mask,
3706 GCForeground | GCBackground, &values);
3707 XCopyPlane(xDisplay, temp, *mask, maskGC,
3708 0, 0, squareSize, squareSize, 0, 0, 1);
3709 XFreePixmap(xDisplay, temp);
3713 void CreateXIMPieces()
3718 static char *ximkind[] = { "ll", "ld", "dl", "dd" };
3723 /* The XSynchronize calls were copied from CreatePieces.
3724 Not sure if needed, but can't hurt */
3725 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3728 /* temp needed by loadXIM() */
3729 ximtemp = XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3730 0, 0, ss, ss, AllPlanes, XYPixmap);
3732 if (strlen(appData.pixmapDirectory) == 0) {
3736 if (appData.monoMode) {
3737 DisplayFatalError(_("XIM pieces cannot be used in monochrome mode"),
3741 fprintf(stderr, _("\nLoading XIMs...\n"));
3743 for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
3744 fprintf(stderr, "%d", piece+1);
3745 for (kind=0; kind<4; kind++) {
3746 fprintf(stderr, ".");
3747 snprintf(buf, sizeof(buf), "%s/%c%s%u.xim",
3748 ExpandPathName(appData.pixmapDirectory),
3749 ToLower(PieceToChar((ChessSquare)piece)),
3751 ximPieceBitmap[kind][piece] =
3752 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3753 0, 0, ss, ss, AllPlanes, XYPixmap);
3754 if (appData.debugMode)
3755 fprintf(stderr, _("(File:%s:) "), buf);
3756 loadXIM(ximPieceBitmap[kind][piece],
3758 &(xpmPieceBitmap[kind][piece]),
3759 &(ximMaskPm[piece%(int)BlackPawn]));
3761 fprintf(stderr," ");
3763 /* Load light and dark squares */
3764 /* If the LSQ and DSQ pieces don't exist, we will
3765 draw them with solid squares. */
3766 snprintf(buf,sizeof(buf), "%s/lsq%u.xim", ExpandPathName(appData.pixmapDirectory), ss);
3767 if (access(buf, 0) != 0) {
3771 fprintf(stderr, _("light square "));
3773 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3774 0, 0, ss, ss, AllPlanes, XYPixmap);
3775 if (appData.debugMode)
3776 fprintf(stderr, _("(File:%s:) "), buf);
3778 loadXIM(ximLightSquare, NULL, buf, &xpmLightSquare, NULL);
3779 fprintf(stderr, _("dark square "));
3780 snprintf(buf,sizeof(buf), "%s/dsq%u.xim",
3781 ExpandPathName(appData.pixmapDirectory), ss);
3782 if (appData.debugMode)
3783 fprintf(stderr, _("(File:%s:) "), buf);
3785 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3786 0, 0, ss, ss, AllPlanes, XYPixmap);
3787 loadXIM(ximDarkSquare, NULL, buf, &xpmDarkSquare, NULL);
3788 xpmJailSquare = xpmLightSquare;
3790 fprintf(stderr, _("Done.\n"));
3792 XSynchronize(xDisplay, False); /* Work-around for xlib/xt buffering bug */
3795 char pieceBitmapNames[] = "pnbrqfeacwmohijgdvlsuk";
3798 void CreateXPMPieces()
3802 u_int ss = squareSize;
3804 static char *xpmkind[] = { "ll", "ld", "dl", "dd" };
3805 XpmColorSymbol symbols[4];
3808 /* Apparently some versions of Xpm don't define XpmFormat at all --tpm */
3809 if (appData.debugMode) {
3810 fprintf(stderr, "XPM Library Version: %d.%d%c\n",
3811 XpmFormat, XpmVersion, (char)('a' + XpmRevision - 1));
3815 /* The XSynchronize calls were copied from CreatePieces.
3816 Not sure if needed, but can't hurt */
3817 XSynchronize(xDisplay, True); /* Work-around for xlib/xt buffering bug */
3819 /* Setup translations so piece colors match square colors */
3820 symbols[0].name = "light_piece";
3821 symbols[0].value = appData.whitePieceColor;
3822 symbols[1].name = "dark_piece";
3823 symbols[1].value = appData.blackPieceColor;
3824 symbols[2].name = "light_square";
3825 symbols[2].value = appData.lightSquareColor;
3826 symbols[3].name = "dark_square";
3827 symbols[3].value = appData.darkSquareColor;
3829 attr.valuemask = XpmColorSymbols;
3830 attr.colorsymbols = symbols;
3831 attr.numsymbols = 4;
3833 if (appData.monoMode) {
3834 DisplayFatalError(_("XPM pieces cannot be used in monochrome mode"),
3838 if (strlen(appData.pixmapDirectory) == 0) {
3839 XpmPieces* pieces = builtInXpms;
3842 while (pieces->size != squareSize && pieces->size) pieces++;
3843 if (!pieces->size) {
3844 fprintf(stderr, _("No builtin XPM pieces of size %d\n"), squareSize);
3847 for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
3848 for (kind=0; kind<4; kind++) {
3850 if ((r=XpmCreatePixmapFromData(xDisplay, xBoardWindow,
3851 pieces->xpm[piece][kind],
3852 &(xpmPieceBitmap[kind][piece]),
3853 NULL, &attr)) != 0) {
3854 fprintf(stderr, _("Error %d loading XPM image \"%s\"\n"),
3861 xpmJailSquare = xpmLightSquare;
3865 fprintf(stderr, _("\nLoading XPMs...\n"));
3868 for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
3869 fprintf(stderr, "%d ", piece+1);
3870 for (kind=0; kind<4; kind++) {
3871 snprintf(buf, sizeof(buf), "%s/%c%s%u.xpm",
3872 ExpandPathName(appData.pixmapDirectory),
3873 pieceBitmapNames[piece],
3875 if (appData.debugMode) {
3876 fprintf(stderr, _("(File:%s:) "), buf);
3878 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3879 &(xpmPieceBitmap[kind][piece]),
3880 NULL, &attr)) != 0) {
3881 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"),
3887 /* Load light and dark squares */
3888 /* If the LSQ and DSQ pieces don't exist, we will
3889 draw them with solid squares. */
3890 fprintf(stderr, _("light square "));
3891 snprintf(buf, sizeof(buf), "%s/lsq%u.xpm", ExpandPathName(appData.pixmapDirectory), ss);
3892 if (access(buf, 0) != 0) {
3896 if (appData.debugMode)
3897 fprintf(stderr, _("(File:%s:) "), buf);
3899 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3900 &xpmLightSquare, NULL, &attr)) != 0) {
3901 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
3904 fprintf(stderr, _("dark square "));
3905 snprintf(buf, sizeof(buf), "%s/dsq%u.xpm",
3906 ExpandPathName(appData.pixmapDirectory), ss);
3907 if (appData.debugMode) {
3908 fprintf(stderr, _("(File:%s:) "), buf);
3910 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3911 &xpmDarkSquare, NULL, &attr)) != 0) {
3912 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
3916 xpmJailSquare = xpmLightSquare;
3917 fprintf(stderr, _("Done.\n"));
3919 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3922 #endif /* HAVE_LIBXPM */
3925 /* No built-in bitmaps */
3930 u_int ss = squareSize;
3932 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3935 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
3936 for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
3937 sprintf(buf, "%c%u%c.bm", pieceBitmapNames[piece],
3938 ss, kind == SOLID ? 's' : 'o');
3939 ReadBitmap(&pieceBitmap[kind][piece], buf, NULL, ss, ss);
3943 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3947 /* With built-in bitmaps */
3950 BuiltInBits* bib = builtInBits;
3953 u_int ss = squareSize;
3955 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3958 while (bib->squareSize != ss && bib->squareSize != 0) bib++;
3960 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
3961 for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
3962 sprintf(buf, "%c%u%c.bm", pieceBitmapNames[piece],
3963 ss, kind == SOLID ? 's' : 'o');
3964 ReadBitmap(&pieceBitmap[kind][piece], buf,
3965 bib->bits[kind][piece], ss, ss);
3969 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3974 void ReadBitmap(pm, name, bits, wreq, hreq)
3977 unsigned char bits[];
3983 char msg[MSG_SIZ], fullname[MSG_SIZ];
3985 if (*appData.bitmapDirectory != NULLCHAR) {
3986 strcpy(fullname, appData.bitmapDirectory);
3987 strcat(fullname, "/");
3988 strcat(fullname, name);
3989 errcode = XReadBitmapFile(xDisplay, xBoardWindow, fullname,
3990 &w, &h, pm, &x_hot, &y_hot);
3991 fprintf(stderr, "load %s\n", name);
3992 if (errcode != BitmapSuccess) {
3994 case BitmapOpenFailed:
3995 snprintf(msg, sizeof(msg), _("Can't open bitmap file %s"), fullname);
3997 case BitmapFileInvalid:
3998 snprintf(msg, sizeof(msg), _("Invalid bitmap in file %s"), fullname);
4000 case BitmapNoMemory:
4001 snprintf(msg, sizeof(msg), _("Ran out of memory reading bitmap file %s"),
4005 snprintf(msg, sizeof(msg), _("Unknown XReadBitmapFile error %d on file %s"),
4009 fprintf(stderr, _("%s: %s...using built-in\n"),
4011 } else if (w != wreq || h != hreq) {
4013 _("%s: Bitmap %s is %dx%d, not %dx%d...using built-in\n"),
4014 programName, fullname, w, h, wreq, hreq);
4021 fprintf(stderr, _("%s: No built-in bitmap for %s; giving up\n"),
4025 ; // [HGM] bitmaps: make it non-fatal if we have no bitmap;
4027 *pm = XCreateBitmapFromData(xDisplay, xBoardWindow, (char *) bits,
4036 if (lineGap == 0) return;
4038 /* [HR] Split this into 2 loops for non-square boards. */
4040 for (i = 0; i < BOARD_HEIGHT + 1; i++) {
4041 gridSegments[i].x1 = 0;
4042 gridSegments[i].x2 =
4043 lineGap + BOARD_WIDTH * (squareSize + lineGap);
4044 gridSegments[i].y1 = gridSegments[i].y2
4045 = lineGap / 2 + (i * (squareSize + lineGap));
4048 for (j = 0; j < BOARD_WIDTH + 1; j++) {
4049 gridSegments[j + i].y1 = 0;
4050 gridSegments[j + i].y2 =
4051 lineGap + BOARD_HEIGHT * (squareSize + lineGap);
4052 gridSegments[j + i].x1 = gridSegments[j + i].x2
4053 = lineGap / 2 + (j * (squareSize + lineGap));
4057 static void MenuBarSelect(w, addr, index)
4062 XtActionProc proc = (XtActionProc) addr;
4064 (proc)(NULL, NULL, NULL, NULL);
4067 void CreateMenuBarPopup(parent, name, mb)
4077 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
4080 XtSetArg(args[j], XtNleftMargin, 20); j++;
4081 XtSetArg(args[j], XtNrightMargin, 20); j++;
4083 while (mi->string != NULL) {
4084 if (strcmp(mi->string, "----") == 0) {
4085 entry = XtCreateManagedWidget(mi->string, smeLineObjectClass,
4088 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string)));
4089 entry = XtCreateManagedWidget(mi->string, smeBSBObjectClass,
4091 XtAddCallback(entry, XtNcallback,
4092 (XtCallbackProc) MenuBarSelect,
4093 (caddr_t) mi->proc);
4099 Widget CreateMenuBar(mb)
4103 Widget anchor, menuBar;
4105 char menuName[MSG_SIZ];
4108 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
4109 XtSetArg(args[j], XtNvSpace, 0); j++;
4110 XtSetArg(args[j], XtNborderWidth, 0); j++;
4111 menuBar = XtCreateWidget("menuBar", boxWidgetClass,
4112 formWidget, args, j);
4114 while (mb->name != NULL) {
4115 strcpy(menuName, "menu");
4116 strcat(menuName, mb->name);
4118 XtSetArg(args[j], XtNmenuName, XtNewString(menuName)); j++;
4121 shortName[0] = _(mb->name)[0];
4122 shortName[1] = NULLCHAR;
4123 XtSetArg(args[j], XtNlabel, XtNewString(shortName)); j++;
4126 XtSetArg(args[j], XtNlabel, XtNewString(_(mb->name))); j++;
4129 XtSetArg(args[j], XtNborderWidth, 0); j++;
4130 anchor = XtCreateManagedWidget(mb->name, menuButtonWidgetClass,
4132 CreateMenuBarPopup(menuBar, menuName, mb);
4138 Widget CreateButtonBar(mi)
4142 Widget button, buttonBar;
4146 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
4148 XtSetArg(args[j], XtNhSpace, 0); j++;
4150 XtSetArg(args[j], XtNborderWidth, 0); j++;
4151 XtSetArg(args[j], XtNvSpace, 0); j++;
4152 buttonBar = XtCreateWidget("buttonBar", boxWidgetClass,
4153 formWidget, args, j);
4155 while (mi->string != NULL) {
4158 XtSetArg(args[j], XtNinternalWidth, 2); j++;
4159 XtSetArg(args[j], XtNborderWidth, 0); j++;
4161 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string))); j++;
4162 button = XtCreateManagedWidget(mi->string, commandWidgetClass,
4163 buttonBar, args, j);
4164 XtAddCallback(button, XtNcallback,
4165 (XtCallbackProc) MenuBarSelect,
4166 (caddr_t) mi->proc);
4173 CreatePieceMenu(name, color)
4180 ChessSquare selection;
4182 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
4183 boardWidget, args, 0);
4185 for (i = 0; i < PIECE_MENU_SIZE; i++) {
4186 String item = pieceMenuStrings[color][i];
4188 if (strcmp(item, "----") == 0) {
4189 entry = XtCreateManagedWidget(item, smeLineObjectClass,
4192 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
4193 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
4195 selection = pieceMenuTranslation[color][i];
4196 XtAddCallback(entry, XtNcallback,
4197 (XtCallbackProc) PieceMenuSelect,
4198 (caddr_t) selection);
4199 if (selection == WhitePawn || selection == BlackPawn) {
4200 XtSetArg(args[0], XtNpopupOnEntry, entry);
4201 XtSetValues(menu, args, 1);
4214 ChessSquare selection;
4216 whitePieceMenu = CreatePieceMenu("menuW", 0);
4217 blackPieceMenu = CreatePieceMenu("menuB", 1);
4219 XtRegisterGrabAction(PieceMenuPopup, True,
4220 (unsigned)(ButtonPressMask|ButtonReleaseMask),
4221 GrabModeAsync, GrabModeAsync);
4223 XtSetArg(args[0], XtNlabel, _("Drop"));
4224 dropMenu = XtCreatePopupShell("menuD", simpleMenuWidgetClass,
4225 boardWidget, args, 1);
4226 for (i = 0; i < DROP_MENU_SIZE; i++) {
4227 String item = dropMenuStrings[i];
4229 if (strcmp(item, "----") == 0) {
4230 entry = XtCreateManagedWidget(item, smeLineObjectClass,
4233 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
4234 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
4236 selection = dropMenuTranslation[i];
4237 XtAddCallback(entry, XtNcallback,
4238 (XtCallbackProc) DropMenuSelect,
4239 (caddr_t) selection);
4244 void SetupDropMenu()
4252 for (i=0; i<sizeof(dmEnables)/sizeof(DropMenuEnables); i++) {
4253 entry = XtNameToWidget(dropMenu, dmEnables[i].widget);
4254 p = strchr(gameMode == IcsPlayingWhite ? white_holding : black_holding,
4255 dmEnables[i].piece);
4256 XtSetSensitive(entry, p != NULL || !appData.testLegality
4257 /*!!temp:*/ || (gameInfo.variant == VariantCrazyhouse
4258 && !appData.icsActive));
4260 while (p && *p++ == dmEnables[i].piece) count++;
4261 snprintf(label, sizeof(label), "%s %d", dmEnables[i].widget, count);
4263 XtSetArg(args[j], XtNlabel, label); j++;
4264 XtSetValues(entry, args, j);
4268 void PieceMenuPopup(w, event, params, num_params)
4272 Cardinal *num_params;
4275 if (event->type != ButtonPress) return;
4276 if (errorUp) ErrorPopDown();
4280 whichMenu = params[0];
4282 case IcsPlayingWhite:
4283 case IcsPlayingBlack:
4285 case MachinePlaysWhite:
4286 case MachinePlaysBlack:
4287 if (appData.testLegality &&
4288 gameInfo.variant != VariantBughouse &&
4289 gameInfo.variant != VariantCrazyhouse) return;
4291 whichMenu = "menuD";
4297 if (((pmFromX = EventToSquare(event->xbutton.x, BOARD_WIDTH)) < 0) ||
4298 ((pmFromY = EventToSquare(event->xbutton.y, BOARD_HEIGHT)) < 0)) {
4299 pmFromX = pmFromY = -1;
4303 pmFromX = BOARD_WIDTH - 1 - pmFromX;
4305 pmFromY = BOARD_HEIGHT - 1 - pmFromY;
4307 XtPopupSpringLoaded(XtNameToWidget(boardWidget, whichMenu));
4310 static void PieceMenuSelect(w, piece, junk)
4315 if (pmFromX < 0 || pmFromY < 0) return;
4316 EditPositionMenuEvent(piece, pmFromX, pmFromY);
4319 static void DropMenuSelect(w, piece, junk)
4324 if (pmFromX < 0 || pmFromY < 0) return;
4325 DropMenuEvent(piece, pmFromX, pmFromY);
4328 void WhiteClock(w, event, prms, nprms)
4334 if (gameMode == EditPosition || gameMode == IcsExamining) {
4335 SetWhiteToPlayEvent();
4336 } else if (gameMode == IcsPlayingBlack || gameMode == MachinePlaysWhite) {
4341 void BlackClock(w, event, prms, nprms)
4347 if (gameMode == EditPosition || gameMode == IcsExamining) {
4348 SetBlackToPlayEvent();
4349 } else if (gameMode == IcsPlayingWhite || gameMode == MachinePlaysBlack) {
4356 * If the user selects on a border boundary, return -1; if off the board,
4357 * return -2. Otherwise map the event coordinate to the square.
4359 int EventToSquare(x, limit)
4367 if ((x % (squareSize + lineGap)) >= squareSize)
4369 x /= (squareSize + lineGap);
4375 static void do_flash_delay(msec)
4381 static void drawHighlight(file, rank, gc)
4387 if (lineGap == 0 || appData.blindfold) return;
4390 x = lineGap/2 + ((BOARD_WIDTH-1)-file) *
4391 (squareSize + lineGap);
4392 y = lineGap/2 + rank * (squareSize + lineGap);
4394 x = lineGap/2 + file * (squareSize + lineGap);
4395 y = lineGap/2 + ((BOARD_HEIGHT-1)-rank) *
4396 (squareSize + lineGap);
4399 XDrawRectangle(xDisplay, xBoardWindow, gc, x, y,
4400 squareSize+lineGap, squareSize+lineGap);
4403 int hi1X = -1, hi1Y = -1, hi2X = -1, hi2Y = -1;
4404 int pm1X = -1, pm1Y = -1, pm2X = -1, pm2Y = -1;
4407 SetHighlights(fromX, fromY, toX, toY)
4408 int fromX, fromY, toX, toY;
4410 if (hi1X != fromX || hi1Y != fromY) {
4411 if (hi1X >= 0 && hi1Y >= 0) {
4412 drawHighlight(hi1X, hi1Y, lineGC);
4414 if (fromX >= 0 && fromY >= 0) {
4415 drawHighlight(fromX, fromY, highlineGC);
4418 if (hi2X != toX || hi2Y != toY) {
4419 if (hi2X >= 0 && hi2Y >= 0) {
4420 drawHighlight(hi2X, hi2Y, lineGC);
4422 if (toX >= 0 && toY >= 0) {
4423 drawHighlight(toX, toY, highlineGC);
4435 SetHighlights(-1, -1, -1, -1);
4440 SetPremoveHighlights(fromX, fromY, toX, toY)
4441 int fromX, fromY, toX, toY;
4443 if (pm1X != fromX || pm1Y != fromY) {
4444 if (pm1X >= 0 && pm1Y >= 0) {
4445 drawHighlight(pm1X, pm1Y, lineGC);
4447 if (fromX >= 0 && fromY >= 0) {
4448 drawHighlight(fromX, fromY, prelineGC);
4451 if (pm2X != toX || pm2Y != toY) {
4452 if (pm2X >= 0 && pm2Y >= 0) {
4453 drawHighlight(pm2X, pm2Y, lineGC);
4455 if (toX >= 0 && toY >= 0) {
4456 drawHighlight(toX, toY, prelineGC);
4466 ClearPremoveHighlights()
4468 SetPremoveHighlights(-1, -1, -1, -1);
4471 static void BlankSquare(x, y, color, piece, dest)
4476 if (useImages && useImageSqs) {
4480 pm = xpmLightSquare;
4485 case 2: /* neutral */
4490 XCopyArea(xDisplay, pm, dest, wlPieceGC, 0, 0,
4491 squareSize, squareSize, x, y);
4501 case 2: /* neutral */
4506 XFillRectangle(xDisplay, dest, gc, x, y, squareSize, squareSize);
4511 I split out the routines to draw a piece so that I could
4512 make a generic flash routine.
4514 static void monoDrawPiece_1bit(piece, square_color, x, y, dest)
4516 int square_color, x, y;
4519 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
4520 switch (square_color) {
4522 case 2: /* neutral */
4524 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
4525 ? *pieceToOutline(piece)
4526 : *pieceToSolid(piece),
4527 dest, bwPieceGC, 0, 0,
4528 squareSize, squareSize, x, y);
4531 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
4532 ? *pieceToSolid(piece)
4533 : *pieceToOutline(piece),
4534 dest, wbPieceGC, 0, 0,
4535 squareSize, squareSize, x, y);
4540 static void monoDrawPiece(piece, square_color, x, y, dest)
4542 int square_color, x, y;
4545 switch (square_color) {
4547 case 2: /* neutral */
4549 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
4550 ? *pieceToOutline(piece)
4551 : *pieceToSolid(piece),
4552 dest, bwPieceGC, 0, 0,
4553 squareSize, squareSize, x, y, 1);
4556 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
4557 ? *pieceToSolid(piece)
4558 : *pieceToOutline(piece),
4559 dest, wbPieceGC, 0, 0,
4560 squareSize, squareSize, x, y, 1);
4565 static void colorDrawPiece(piece, square_color, x, y, dest)
4567 int square_color, x, y;
4570 if(pieceToSolid(piece) == NULL) return; // [HGM] bitmaps: make it non-fatal if we have no bitmap;
4571 switch (square_color) {
4573 XCopyPlane(xDisplay, *pieceToSolid(piece),
4574 dest, (int) piece < (int) BlackPawn
4575 ? wlPieceGC : blPieceGC, 0, 0,
4576 squareSize, squareSize, x, y, 1);
4579 XCopyPlane(xDisplay, *pieceToSolid(piece),
4580 dest, (int) piece < (int) BlackPawn
4581 ? wdPieceGC : bdPieceGC, 0, 0,
4582 squareSize, squareSize, x, y, 1);
4584 case 2: /* neutral */
4586 XCopyPlane(xDisplay, *pieceToSolid(piece),
4587 dest, (int) piece < (int) BlackPawn
4588 ? wjPieceGC : bjPieceGC, 0, 0,
4589 squareSize, squareSize, x, y, 1);
4594 static void colorDrawPieceImage(piece, square_color, x, y, dest)
4596 int square_color, x, y;
4601 switch (square_color) {
4603 case 2: /* neutral */
4605 if ((int)piece < (int) BlackPawn) {
4613 if ((int)piece < (int) BlackPawn) {
4621 XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
4622 dest, wlPieceGC, 0, 0,
4623 squareSize, squareSize, x, y);
4626 typedef void (*DrawFunc)();
4628 DrawFunc ChooseDrawFunc()
4630 if (appData.monoMode) {
4631 if (DefaultDepth(xDisplay, xScreen) == 1) {
4632 return monoDrawPiece_1bit;
4634 return monoDrawPiece;
4638 return colorDrawPieceImage;
4640 return colorDrawPiece;
4644 /* [HR] determine square color depending on chess variant. */
4645 static int SquareColor(row, column)
4650 if (gameInfo.variant == VariantXiangqi) {
4651 if (column >= 3 && column <= 5 && row >= 0 && row <= 2) {
4653 } else if (column >= 3 && column <= 5 && row >= 7 && row <= 9) {
4655 } else if (row <= 4) {
4661 square_color = ((column + row) % 2) == 1;
4664 /* [hgm] holdings: next line makes all holdings squares light */
4665 if(column < BOARD_LEFT || column >= BOARD_RGHT) square_color = 1;
4667 return square_color;
4670 void DrawSquare(row, column, piece, do_flash)
4671 int row, column, do_flash;
4674 int square_color, x, y, direction, font_ascent, font_descent;
4677 XCharStruct overall;
4681 if(gameInfo.variant == VariantShogi) { // [HGM] shogi: in shogi Q is used for Lance
4682 if(piece == WhiteQueen) piece = WhiteLance; else
4683 if(piece == BlackQueen) piece = BlackLance;
4686 else if(gameInfo.variant == VariantGothic) { // [HGM] shogi: in Gothic Chancelor has alternative look
4687 if(piece == WhiteMarshall) piece = WhiteSilver; else
4688 if(piece == BlackMarshall) piece = BlackSilver;
4692 /* Calculate delay in milliseconds (2-delays per complete flash) */
4693 flash_delay = 500 / appData.flashRate;
4696 x = lineGap + ((BOARD_WIDTH-1)-column) *
4697 (squareSize + lineGap);
4698 y = lineGap + row * (squareSize + lineGap);
4700 x = lineGap + column * (squareSize + lineGap);
4701 y = lineGap + ((BOARD_HEIGHT-1)-row) *
4702 (squareSize + lineGap);
4705 square_color = SquareColor(row, column);
4707 if ( // [HGM] holdings: blank out area between board and holdings
4708 column == BOARD_LEFT-1 || column == BOARD_RGHT
4709 || (column == BOARD_LEFT-2 && row < BOARD_HEIGHT-gameInfo.holdingsSize)
4710 || (column == BOARD_RGHT+1 && row >= gameInfo.holdingsSize) ) {
4711 BlankSquare(x, y, 2, EmptySquare, xBoardWindow);
4713 // [HGM] print piece counts next to holdings
4714 string[1] = NULLCHAR;
4715 if (column == (flipView ? BOARD_LEFT-1 : BOARD_RGHT) && piece > 1 ) {
4716 string[0] = '0' + piece;
4717 XTextExtents(countFontStruct, string, 1, &direction,
4718 &font_ascent, &font_descent, &overall);
4719 if (appData.monoMode) {
4720 XDrawImageString(xDisplay, xBoardWindow, countGC,
4721 x + squareSize - overall.width - 2,
4722 y + font_ascent + 1, string, 1);
4724 XDrawString(xDisplay, xBoardWindow, countGC,
4725 x + squareSize - overall.width - 2,
4726 y + font_ascent + 1, string, 1);
4729 if (column == (flipView ? BOARD_RGHT : BOARD_LEFT-1) && piece > 1) {
4730 string[0] = '0' + piece;
4731 XTextExtents(countFontStruct, string, 1, &direction,
4732 &font_ascent, &font_descent, &overall);
4733 if (appData.monoMode) {
4734 XDrawImageString(xDisplay, xBoardWindow, countGC,
4735 x + 2, y + font_ascent + 1, string, 1);
4737 XDrawString(xDisplay, xBoardWindow, countGC,
4738 x + 2, y + font_ascent + 1, string, 1);
4742 if (piece == EmptySquare || appData.blindfold) {
4743 BlankSquare(x, y, square_color, piece, xBoardWindow);
4745 drawfunc = ChooseDrawFunc();
4746 if (do_flash && appData.flashCount > 0) {
4747 for (i=0; i<appData.flashCount; ++i) {
4749 drawfunc(piece, square_color, x, y, xBoardWindow);
4750 XSync(xDisplay, False);
4751 do_flash_delay(flash_delay);
4753 BlankSquare(x, y, square_color, piece, xBoardWindow);
4754 XSync(xDisplay, False);
4755 do_flash_delay(flash_delay);
4758 drawfunc(piece, square_color, x, y, xBoardWindow);
4762 string[1] = NULLCHAR;
4763 if (appData.showCoords && row == (flipView ? BOARD_HEIGHT-1 : 0)
4764 && column >= BOARD_LEFT && column < BOARD_RGHT) {
4765 string[0] = 'a' + column - BOARD_LEFT;
4766 XTextExtents(coordFontStruct, string, 1, &direction,
4767 &font_ascent, &font_descent, &overall);
4768 if (appData.monoMode) {
4769 XDrawImageString(xDisplay, xBoardWindow, coordGC,
4770 x + squareSize - overall.width - 2,
4771 y + squareSize - font_descent - 1, string, 1);
4773 XDrawString(xDisplay, xBoardWindow, coordGC,
4774 x + squareSize - overall.width - 2,
4775 y + squareSize - font_descent - 1, string, 1);
4778 if (appData.showCoords && column == (flipView ? BOARD_RGHT-1 : BOARD_LEFT)) {
4779 string[0] = ONE + row;
4780 XTextExtents(coordFontStruct, string, 1, &direction,
4781 &font_ascent, &font_descent, &overall);
4782 if (appData.monoMode) {
4783 XDrawImageString(xDisplay, xBoardWindow, coordGC,
4784 x + 2, y + font_ascent + 1, string, 1);
4786 XDrawString(xDisplay, xBoardWindow, coordGC,
4787 x + 2, y + font_ascent + 1, string, 1);
4793 /* Why is this needed on some versions of X? */
4794 void EventProc(widget, unused, event)
4799 if (!XtIsRealized(widget))
4802 switch (event->type) {
4804 if (event->xexpose.count > 0) return; /* no clipping is done */
4805 XDrawPosition(widget, True, NULL);
4813 void DrawPosition(fullRedraw, board)
4814 /*Boolean*/int fullRedraw;
4817 XDrawPosition(boardWidget, fullRedraw, board);
4820 /* Returns 1 if there are "too many" differences between b1 and b2
4821 (i.e. more than 1 move was made) */
4822 static int too_many_diffs(b1, b2)
4828 for (i=0; i<BOARD_HEIGHT; ++i) {
4829 for (j=0; j<BOARD_WIDTH; ++j) {
4830 if (b1[i][j] != b2[i][j]) {
4831 if (++c > 4) /* Castling causes 4 diffs */
4840 /* Matrix describing castling maneuvers */
4841 /* Row, ColRookFrom, ColKingFrom, ColRookTo, ColKingTo */
4842 static int castling_matrix[4][5] = {
4843 { 0, 0, 4, 3, 2 }, /* 0-0-0, white */
4844 { 0, 7, 4, 5, 6 }, /* 0-0, white */
4845 { 7, 0, 4, 3, 2 }, /* 0-0-0, black */
4846 { 7, 7, 4, 5, 6 } /* 0-0, black */
4849 /* Checks whether castling occurred. If it did, *rrow and *rcol
4850 are set to the destination (row,col) of the rook that moved.
4852 Returns 1 if castling occurred, 0 if not.
4854 Note: Only handles a max of 1 castling move, so be sure
4855 to call too_many_diffs() first.
4857 static int check_castle_draw(newb, oldb, rrow, rcol)
4864 /* For each type of castling... */
4865 for (i=0; i<4; ++i) {
4866 r = castling_matrix[i];
4868 /* Check the 4 squares involved in the castling move */
4870 for (j=1; j<=4; ++j) {
4871 if (newb[r[0]][r[j]] == oldb[r[0]][r[j]]) {
4878 /* All 4 changed, so it must be a castling move */
4887 static int damage[BOARD_SIZE][BOARD_SIZE];
4890 * event handler for redrawing the board
4892 void XDrawPosition(w, repaint, board)
4894 /*Boolean*/int repaint;
4898 static int lastFlipView = 0;
4899 static int lastBoardValid = 0;
4900 static Board lastBoard;
4904 if (board == NULL) {
4905 if (!lastBoardValid) return;
4908 if (!lastBoardValid || lastFlipView != flipView) {
4909 XtSetArg(args[0], XtNleftBitmap, (flipView ? xMarkPixmap : None));
4910 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flip View"),
4915 * It would be simpler to clear the window with XClearWindow()
4916 * but this causes a very distracting flicker.
4919 if (!repaint && lastBoardValid && lastFlipView == flipView) {
4921 /* If too much changes (begin observing new game, etc.), don't
4923 do_flash = too_many_diffs(board, lastBoard) ? 0 : 1;
4925 /* Special check for castling so we don't flash both the king
4926 and the rook (just flash the king). */
4928 if (check_castle_draw(board, lastBoard, &rrow, &rcol)) {
4929 /* Draw rook with NO flashing. King will be drawn flashing later */
4930 DrawSquare(rrow, rcol, board[rrow][rcol], 0);
4931 lastBoard[rrow][rcol] = board[rrow][rcol];
4935 /* First pass -- Draw (newly) empty squares and repair damage.
4936 This prevents you from having a piece show up twice while it
4937 is flashing on its new square */
4938 for (i = 0; i < BOARD_HEIGHT; i++)
4939 for (j = 0; j < BOARD_WIDTH; j++)
4940 if ((board[i][j] != lastBoard[i][j] && board[i][j] == EmptySquare)
4942 DrawSquare(i, j, board[i][j], 0);
4943 damage[i][j] = False;
4946 /* Second pass -- Draw piece(s) in new position and flash them */
4947 for (i = 0; i < BOARD_HEIGHT; i++)
4948 for (j = 0; j < BOARD_WIDTH; j++)
4949 if (board[i][j] != lastBoard[i][j]) {
4950 DrawSquare(i, j, board[i][j], do_flash);
4954 XDrawSegments(xDisplay, xBoardWindow, lineGC,
4955 gridSegments, BOARD_HEIGHT + BOARD_WIDTH + 2);
4957 for (i = 0; i < BOARD_HEIGHT; i++)
4958 for (j = 0; j < BOARD_WIDTH; j++) {
4959 DrawSquare(i, j, board[i][j], 0);
4960 damage[i][j] = False;
4964 CopyBoard(lastBoard, board);
4966 lastFlipView = flipView;
4968 /* Draw highlights */
4969 if (pm1X >= 0 && pm1Y >= 0) {
4970 drawHighlight(pm1X, pm1Y, prelineGC);
4972 if (pm2X >= 0 && pm2Y >= 0) {
4973 drawHighlight(pm2X, pm2Y, prelineGC);
4975 if (hi1X >= 0 && hi1Y >= 0) {
4976 drawHighlight(hi1X, hi1Y, highlineGC);
4978 if (hi2X >= 0 && hi2Y >= 0) {
4979 drawHighlight(hi2X, hi2Y, highlineGC);
4982 /* If piece being dragged around board, must redraw that too */
4985 XSync(xDisplay, False);
4990 * event handler for redrawing the board
4992 void DrawPositionProc(w, event, prms, nprms)
4998 XDrawPosition(w, True, NULL);
5003 * event handler for parsing user moves
5005 // [HGM] This routine will need quite some reworking. Although the backend still supports the old
5006 // way of doing things, by calling UserMoveEvent() to test the legality of the move and then perform
5007 // it at the end, and doing all kind of preliminary tests here (e.g. to weed out self-captures), it
5008 // should be made to use the new way, of calling UserMoveTest early to determine the legality of the
5009 // move, (which will weed out the illegal selfcaptures and moves into the holdings, and flag promotions),
5010 // and at the end FinishMove() to perform the move after optional promotion popups.
5011 // For now I patched it to allow self-capture with King, and suppress clicks between board and holdings.
5012 void HandleUserMove(w, event, prms, nprms)
5019 Boolean saveAnimate;
5020 static int second = 0;
5022 if (w != boardWidget || errorExitStatus != -1) return;
5024 if (event->type == ButtonPress) ErrorPopDown();
5027 if (event->type == ButtonPress) {
5028 XtPopdown(promotionShell);
5029 XtDestroyWidget(promotionShell);
5030 promotionUp = False;
5038 x = EventToSquare(event->xbutton.x, BOARD_WIDTH);
5039 y = EventToSquare(event->xbutton.y, BOARD_HEIGHT);
5040 if (!flipView && y >= 0) {
5041 y = BOARD_HEIGHT - 1 - y;
5043 if (flipView && x >= 0) {
5044 x = BOARD_WIDTH - 1 - x;
5047 /* [HGM] holdings: next 5 lines: ignore all clicks between board and holdings */
5048 if(event->type == ButtonPress
5049 && ( x == BOARD_LEFT-1 || x == BOARD_RGHT
5050 || x == BOARD_LEFT-2 && y < BOARD_HEIGHT-gameInfo.holdingsSize
5051 || x == BOARD_RGHT+1 && y >= gameInfo.holdingsSize) )
5055 if (event->type == ButtonPress) {
5057 if (OKToStartUserMove(x, y)) {
5061 DragPieceBegin(event->xbutton.x, event->xbutton.y);
5062 if (appData.highlightDragging) {
5063 SetHighlights(x, y, -1, -1);
5071 if (event->type == ButtonPress && gameMode != EditPosition &&
5076 /* Check if clicking again on the same color piece */
5077 fromP = boards[currentMove][fromY][fromX];
5078 toP = boards[currentMove][y][x];
5079 if ((WhitePawn <= fromP && fromP < WhiteKing && // [HGM] this test should go, as UserMoveTest now does it.
5080 WhitePawn <= toP && toP <= WhiteKing) || // For now I made it less critical by exempting King
5081 (BlackPawn <= fromP && fromP < BlackKing && // moves, to not interfere with FRC castlings.
5082 BlackPawn <= toP && toP <= BlackKing)) {
5083 /* Clicked again on same color piece -- changed his mind */
5084 second = (x == fromX && y == fromY);
5085 if (appData.highlightDragging) {
5086 SetHighlights(x, y, -1, -1);
5090 if (OKToStartUserMove(x, y)) {
5093 DragPieceBegin(event->xbutton.x, event->xbutton.y);
5099 if (event->type == ButtonRelease && x == fromX && y == fromY) {
5100 DragPieceEnd(event->xbutton.x, event->xbutton.y);
5101 if (appData.animateDragging) {
5102 /* Undo animation damage if any */
5103 DrawPosition(FALSE, NULL);
5106 /* Second up/down in same square; just abort move */
5111 ClearPremoveHighlights();
5113 /* First upclick in same square; start click-click mode */
5114 SetHighlights(x, y, -1, -1);
5119 /* Completed move */
5122 saveAnimate = appData.animate;
5123 if (event->type == ButtonPress) {
5124 /* Finish clickclick move */
5125 if (appData.animate || appData.highlightLastMove) {
5126 SetHighlights(fromX, fromY, toX, toY);
5131 /* Finish drag move */
5132 if (appData.highlightLastMove) {
5133 SetHighlights(fromX, fromY, toX, toY);
5137 DragPieceEnd(event->xbutton.x, event->xbutton.y);
5138 /* Don't animate move and drag both */
5139 appData.animate = FALSE;
5141 if (IsPromotion(fromX, fromY, toX, toY)) {
5142 if (appData.alwaysPromoteToQueen) {
5143 UserMoveEvent(fromX, fromY, toX, toY, 'q');
5144 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
5145 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
5148 SetHighlights(fromX, fromY, toX, toY);
5152 UserMoveEvent(fromX, fromY, toX, toY, NULLCHAR);
5153 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
5154 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
5157 appData.animate = saveAnimate;
5158 if (appData.animate || appData.animateDragging) {
5159 /* Undo animation damage if needed */
5160 DrawPosition(FALSE, NULL);
5164 void AnimateUserMove (Widget w, XEvent * event,
5165 String * params, Cardinal * nParams)
5167 DragPieceMove(event->xmotion.x, event->xmotion.y);
5170 Widget CommentCreate(name, text, mutable, callback, lines)
5172 int /*Boolean*/ mutable;
5173 XtCallbackProc callback;
5177 Widget shell, layout, form, edit, b_ok, b_cancel, b_clear, b_close, b_edit;
5182 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5183 XtGetValues(boardWidget, args, j);
5186 XtSetArg(args[j], XtNresizable, True); j++;
5189 XtCreatePopupShell(name, topLevelShellWidgetClass,
5190 shellWidget, args, j);
5193 XtCreatePopupShell(name, transientShellWidgetClass,
5194 shellWidget, args, j);
5197 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
5198 layoutArgs, XtNumber(layoutArgs));
5200 XtCreateManagedWidget("form", formWidgetClass, layout,
5201 formArgs, XtNumber(formArgs));
5205 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
5206 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
5208 XtSetArg(args[j], XtNstring, text); j++;
5209 XtSetArg(args[j], XtNtop, XtChainTop); j++;
5210 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5211 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5212 XtSetArg(args[j], XtNright, XtChainRight); j++;
5213 XtSetArg(args[j], XtNresizable, True); j++;
5214 XtSetArg(args[j], XtNwidth, bw_width); j++; /*force wider than buttons*/
5216 XtSetArg(args[j], XtNscrollVertical, XawtextScrollWhenNeeded); j++;
5218 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
5219 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
5221 XtSetArg(args[j], XtNautoFill, True); j++;
5222 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
5224 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
5228 XtSetArg(args[j], XtNfromVert, edit); j++;
5229 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5230 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5231 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5232 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5234 XtCreateManagedWidget(_("ok"), commandWidgetClass, form, args, j);
5235 XtAddCallback(b_ok, XtNcallback, callback, (XtPointer) 0);
5238 XtSetArg(args[j], XtNfromVert, edit); j++;
5239 XtSetArg(args[j], XtNfromHoriz, b_ok); j++;
5240 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5241 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5242 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5243 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5245 XtCreateManagedWidget(_("cancel"), commandWidgetClass, form, args, j);
5246 XtAddCallback(b_cancel, XtNcallback, callback, (XtPointer) 0);
5249 XtSetArg(args[j], XtNfromVert, edit); j++;
5250 XtSetArg(args[j], XtNfromHoriz, b_cancel); j++;
5251 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5252 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5253 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5254 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5256 XtCreateManagedWidget(_("clear"), commandWidgetClass, form, args, j);
5257 XtAddCallback(b_clear, XtNcallback, callback, (XtPointer) 0);
5260 XtSetArg(args[j], XtNfromVert, edit); j++;
5261 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5262 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5263 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5264 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5266 XtCreateManagedWidget(_("close"), commandWidgetClass, form, args, j);
5267 XtAddCallback(b_close, XtNcallback, callback, (XtPointer) 0);
5270 XtSetArg(args[j], XtNfromVert, edit); j++;
5271 XtSetArg(args[j], XtNfromHoriz, b_close); j++;
5272 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5273 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5274 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5275 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5277 XtCreateManagedWidget(_("edit"), commandWidgetClass, form, args, j);
5278 XtAddCallback(b_edit, XtNcallback, callback, (XtPointer) 0);
5281 XtRealizeWidget(shell);
5283 if (commentX == -1) {
5286 Dimension pw_height;
5287 Dimension ew_height;
5290 XtSetArg(args[j], XtNheight, &ew_height); j++;
5291 XtGetValues(edit, args, j);
5294 XtSetArg(args[j], XtNheight, &pw_height); j++;
5295 XtGetValues(shell, args, j);
5296 commentH = pw_height + (lines - 1) * ew_height;
5297 commentW = bw_width - 16;
5299 XSync(xDisplay, False);
5301 /* This code seems to tickle an X bug if it is executed too soon
5302 after xboard starts up. The coordinates get transformed as if
5303 the main window was positioned at (0, 0).
5305 XtTranslateCoords(shellWidget,
5306 (bw_width - commentW) / 2, 0 - commentH / 2,
5307 &commentX, &commentY);
5309 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
5310 RootWindowOfScreen(XtScreen(shellWidget)),
5311 (bw_width - commentW) / 2, 0 - commentH / 2,
5316 if (commentY < 0) commentY = 0; /*avoid positioning top offscreen*/
5319 XtSetArg(args[j], XtNheight, commentH); j++;
5320 XtSetArg(args[j], XtNwidth, commentW); j++;
5321 XtSetArg(args[j], XtNx, commentX); j++;
5322 XtSetArg(args[j], XtNy, commentY); j++;
5323 XtSetValues(shell, args, j);
5324 XtSetKeyboardFocus(shell, edit);
5329 /* Used for analysis window and ICS input window */
5330 Widget MiscCreate(name, text, mutable, callback, lines)
5332 int /*Boolean*/ mutable;
5333 XtCallbackProc callback;
5337 Widget shell, layout, form, edit;
5339 Dimension bw_width, pw_height, ew_height, w, h;
5345 XtSetArg(args[j], XtNresizable, True); j++;
5348 XtCreatePopupShell(name, topLevelShellWidgetClass,
5349 shellWidget, args, j);
5352 XtCreatePopupShell(name, transientShellWidgetClass,
5353 shellWidget, args, j);
5356 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
5357 layoutArgs, XtNumber(layoutArgs));
5359 XtCreateManagedWidget("form", formWidgetClass, layout,
5360 formArgs, XtNumber(formArgs));
5364 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
5365 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
5367 XtSetArg(args[j], XtNstring, text); j++;
5368 XtSetArg(args[j], XtNtop, XtChainTop); j++;
5369 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5370 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5371 XtSetArg(args[j], XtNright, XtChainRight); j++;
5372 XtSetArg(args[j], XtNresizable, True); j++;
5374 XtSetArg(args[j], XtNscrollVertical, XawtextScrollWhenNeeded); j++;
5376 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
5377 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
5379 XtSetArg(args[j], XtNautoFill, True); j++;
5380 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
5382 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
5384 XtRealizeWidget(shell);
5387 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5388 XtGetValues(boardWidget, args, j);
5391 XtSetArg(args[j], XtNheight, &ew_height); j++;
5392 XtGetValues(edit, args, j);
5395 XtSetArg(args[j], XtNheight, &pw_height); j++;
5396 XtGetValues(shell, args, j);
5397 h = pw_height + (lines - 1) * ew_height;
5400 XSync(xDisplay, False);
5402 /* This code seems to tickle an X bug if it is executed too soon
5403 after xboard starts up. The coordinates get transformed as if
5404 the main window was positioned at (0, 0).
5406 XtTranslateCoords(shellWidget, (bw_width - w) / 2, 0 - h / 2, &x, &y);
5408 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
5409 RootWindowOfScreen(XtScreen(shellWidget)),
5410 (bw_width - w) / 2, 0 - h / 2, &xx, &yy, &junk);
5414 if (y < 0) y = 0; /*avoid positioning top offscreen*/
5417 XtSetArg(args[j], XtNheight, h); j++;
5418 XtSetArg(args[j], XtNwidth, w); j++;
5419 XtSetArg(args[j], XtNx, x); j++;
5420 XtSetArg(args[j], XtNy, y); j++;
5421 XtSetValues(shell, args, j);
5427 static int savedIndex; /* gross that this is global */
5429 void EditCommentPopUp(index, title, text)
5438 if (text == NULL) text = "";
5440 if (editShell == NULL) {
5442 CommentCreate(title, text, True, EditCommentCallback, 4);
5443 XtRealizeWidget(editShell);
5444 CatchDeleteWindow(editShell, "EditCommentPopDown");
5446 edit = XtNameToWidget(editShell, "*form.text");
5448 XtSetArg(args[j], XtNstring, text); j++;
5449 XtSetValues(edit, args, j);
5451 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5452 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5453 XtSetValues(editShell, args, j);
5456 XtPopup(editShell, XtGrabNone);
5460 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
5461 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
5465 void EditCommentCallback(w, client_data, call_data)
5467 XtPointer client_data, call_data;
5475 XtSetArg(args[j], XtNlabel, &name); j++;
5476 XtGetValues(w, args, j);
5478 if (strcmp(name, _("ok")) == 0) {
5479 edit = XtNameToWidget(editShell, "*form.text");
5481 XtSetArg(args[j], XtNstring, &val); j++;
5482 XtGetValues(edit, args, j);
5483 ReplaceComment(savedIndex, val);
5484 EditCommentPopDown();
5485 } else if (strcmp(name, _("cancel")) == 0) {
5486 EditCommentPopDown();
5487 } else if (strcmp(name, _("clear")) == 0) {
5488 edit = XtNameToWidget(editShell, "*form.text");
5489 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
5490 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
5494 void EditCommentPopDown()
5499 if (!editUp) return;
5501 XtSetArg(args[j], XtNx, &commentX); j++;
5502 XtSetArg(args[j], XtNy, &commentY); j++;
5503 XtSetArg(args[j], XtNheight, &commentH); j++;
5504 XtSetArg(args[j], XtNwidth, &commentW); j++;
5505 XtGetValues(editShell, args, j);
5506 XtPopdown(editShell);
5509 XtSetArg(args[j], XtNleftBitmap, None); j++;
5510 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
5514 void ICSInputBoxPopUp()
5519 char *title = _("ICS Input");
5522 if (ICSInputShell == NULL) {
5523 ICSInputShell = MiscCreate(title, "", True, NULL, 1);
5524 tr = XtParseTranslationTable(ICSInputTranslations);
5525 edit = XtNameToWidget(ICSInputShell, "*form.text");
5526 XtOverrideTranslations(edit, tr);
5527 XtRealizeWidget(ICSInputShell);
5528 CatchDeleteWindow(ICSInputShell, "ICSInputBoxPopDown");
5531 edit = XtNameToWidget(ICSInputShell, "*form.text");
5533 XtSetArg(args[j], XtNstring, ""); j++;
5534 XtSetValues(edit, args, j);
5536 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5537 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5538 XtSetValues(ICSInputShell, args, j);
5541 XtPopup(ICSInputShell, XtGrabNone);
5542 XtSetKeyboardFocus(ICSInputShell, edit);
5544 ICSInputBoxUp = True;
5546 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
5547 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
5551 void ICSInputSendText()
5558 edit = XtNameToWidget(ICSInputShell, "*form.text");
5560 XtSetArg(args[j], XtNstring, &val); j++;
5561 XtGetValues(edit, args, j);
5562 SendMultiLineToICS(val);
5563 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
5564 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
5567 void ICSInputBoxPopDown()
5572 if (!ICSInputBoxUp) return;
5574 XtPopdown(ICSInputShell);
5575 ICSInputBoxUp = False;
5577 XtSetArg(args[j], XtNleftBitmap, None); j++;
5578 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
5582 void CommentPopUp(title, text)
5589 if (commentShell == NULL) {
5591 CommentCreate(title, text, False, CommentCallback, 4);
5592 XtRealizeWidget(commentShell);
5593 CatchDeleteWindow(commentShell, "CommentPopDown");
5595 edit = XtNameToWidget(commentShell, "*form.text");
5597 XtSetArg(args[j], XtNstring, text); j++;
5598 XtSetValues(edit, args, j);
5600 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5601 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5602 XtSetValues(commentShell, args, j);
5605 XtPopup(commentShell, XtGrabNone);
5606 XSync(xDisplay, False);
5611 void AnalysisPopUp(title, text)
5618 if (analysisShell == NULL) {
5619 analysisShell = MiscCreate(title, text, False, NULL, 4);
5620 XtRealizeWidget(analysisShell);
5621 CatchDeleteWindow(analysisShell, "AnalysisPopDown");
5624 edit = XtNameToWidget(analysisShell, "*form.text");
5626 XtSetArg(args[j], XtNstring, text); j++;
5627 XtSetValues(edit, args, j);
5629 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5630 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5631 XtSetValues(analysisShell, args, j);
5635 XtPopup(analysisShell, XtGrabNone);
5637 XSync(xDisplay, False);
5642 void CommentCallback(w, client_data, call_data)
5644 XtPointer client_data, call_data;
5651 XtSetArg(args[j], XtNlabel, &name); j++;
5652 XtGetValues(w, args, j);
5654 if (strcmp(name, _("close")) == 0) {
5656 } else if (strcmp(name, _("edit")) == 0) {
5663 void CommentPopDown()
5668 if (!commentUp) return;
5670 XtSetArg(args[j], XtNx, &commentX); j++;
5671 XtSetArg(args[j], XtNy, &commentY); j++;
5672 XtSetArg(args[j], XtNwidth, &commentW); j++;
5673 XtSetArg(args[j], XtNheight, &commentH); j++;
5674 XtGetValues(commentShell, args, j);
5675 XtPopdown(commentShell);
5676 XSync(xDisplay, False);
5680 void AnalysisPopDown()
5682 if (!analysisUp) return;
5683 XtPopdown(analysisShell);
5684 XSync(xDisplay, False);
5686 if (appData.icsEngineAnalyze) ExitAnalyzeMode(); /* [DM] icsEngineAnalyze */
5690 void FileNamePopUp(label, def, proc, openMode)
5697 Widget popup, layout, dialog, edit;
5703 fileProc = proc; /* I can't see a way not */
5704 fileOpenMode = openMode; /* to use globals here */
5707 XtSetArg(args[i], XtNresizable, True); i++;
5708 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
5709 XtSetArg(args[i], XtNtitle, XtNewString(_("File name prompt"))); i++;
5710 fileNameShell = popup =
5711 XtCreatePopupShell("File name prompt", transientShellWidgetClass,
5712 shellWidget, args, i);
5715 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
5716 layoutArgs, XtNumber(layoutArgs));
5719 XtSetArg(args[i], XtNlabel, label); i++;
5720 XtSetArg(args[i], XtNvalue, def); i++;
5721 XtSetArg(args[i], XtNborderWidth, 0); i++;
5722 dialog = XtCreateManagedWidget("fileName", dialogWidgetClass,
5725 XawDialogAddButton(dialog, _("ok"), FileNameCallback, (XtPointer) dialog);
5726 XawDialogAddButton(dialog, _("cancel"), FileNameCallback,
5727 (XtPointer) dialog);
5729 XtRealizeWidget(popup);
5730 CatchDeleteWindow(popup, "FileNamePopDown");
5732 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
5733 &x, &y, &win_x, &win_y, &mask);
5735 XtSetArg(args[0], XtNx, x - 10);
5736 XtSetArg(args[1], XtNy, y - 30);
5737 XtSetValues(popup, args, 2);
5739 XtPopup(popup, XtGrabExclusive);
5742 edit = XtNameToWidget(dialog, "*value");
5743 XtSetKeyboardFocus(popup, edit);
5746 void FileNamePopDown()
5748 if (!filenameUp) return;
5749 XtPopdown(fileNameShell);
5750 XtDestroyWidget(fileNameShell);
5755 void FileNameCallback(w, client_data, call_data)
5757 XtPointer client_data, call_data;
5762 XtSetArg(args[0], XtNlabel, &name);
5763 XtGetValues(w, args, 1);
5765 if (strcmp(name, _("cancel")) == 0) {
5770 FileNameAction(w, NULL, NULL, NULL);
5773 void FileNameAction(w, event, prms, nprms)
5785 name = XawDialogGetValueString(w = XtParent(w));
5787 if ((name != NULL) && (*name != NULLCHAR)) {
5789 XtPopdown(w = XtParent(XtParent(w)));
5793 p = strrchr(buf, ' ');
5800 fullname = ExpandPathName(buf);
5802 ErrorPopUp(_("Error"), _("Can't open file"), FALSE);
5805 f = fopen(fullname, fileOpenMode);
5807 DisplayError(_("Failed to open file"), errno);
5809 (void) (*fileProc)(f, index, buf);
5816 XtPopdown(w = XtParent(XtParent(w)));
5822 void PromotionPopUp()
5825 Widget dialog, layout;
5827 Dimension bw_width, pw_width;
5831 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5832 XtGetValues(boardWidget, args, j);
5835 XtSetArg(args[j], XtNresizable, True); j++;
5836 XtSetArg(args[j], XtNtitle, XtNewString(_("Promotion"))); j++;
5838 XtCreatePopupShell("Promotion", transientShellWidgetClass,
5839 shellWidget, args, j);
5841 XtCreateManagedWidget(layoutName, formWidgetClass, promotionShell,
5842 layoutArgs, XtNumber(layoutArgs));
5845 XtSetArg(args[j], XtNlabel, _("Promote to what?")); j++;
5846 XtSetArg(args[j], XtNborderWidth, 0); j++;
5847 dialog = XtCreateManagedWidget("promotion", dialogWidgetClass,
5850 if(gameInfo.variant != VariantShogi) {
5851 XawDialogAddButton(dialog, _("Queen"), PromotionCallback,
5852 (XtPointer) dialog);
5853 XawDialogAddButton(dialog, _("Rook"), PromotionCallback,
5854 (XtPointer) dialog);
5855 XawDialogAddButton(dialog, _("Bishop"), PromotionCallback,
5856 (XtPointer) dialog);
5857 XawDialogAddButton(dialog, _("Knight"), PromotionCallback,
5858 (XtPointer) dialog);
5859 if (!appData.testLegality || gameInfo.variant == VariantSuicide ||
5860 gameInfo.variant == VariantGiveaway) {
5861 XawDialogAddButton(dialog, _("King"), PromotionCallback,
5862 (XtPointer) dialog);
5864 if(gameInfo.variant == VariantCapablanca ||
5865 gameInfo.variant == VariantGothic ||
5866 gameInfo.variant == VariantCapaRandom) {
5867 XawDialogAddButton(dialog, _("Archbishop"), PromotionCallback,
5868 (XtPointer) dialog);
5869 XawDialogAddButton(dialog, _("Chancellor"), PromotionCallback,
5870 (XtPointer) dialog);
5872 } else // [HGM] shogi
5874 XawDialogAddButton(dialog, _("Promote"), PromotionCallback,
5875 (XtPointer) dialog);
5876 XawDialogAddButton(dialog, _("Defer"), PromotionCallback,
5877 (XtPointer) dialog);
5879 XawDialogAddButton(dialog, _("cancel"), PromotionCallback,
5880 (XtPointer) dialog);
5882 XtRealizeWidget(promotionShell);
5883 CatchDeleteWindow(promotionShell, "PromotionPopDown");
5886 XtSetArg(args[j], XtNwidth, &pw_width); j++;
5887 XtGetValues(promotionShell, args, j);
5889 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
5890 lineGap + squareSize/3 +
5891 ((toY == BOARD_HEIGHT-1) ^ (flipView) ?
5892 0 : 6*(squareSize + lineGap)), &x, &y);
5895 XtSetArg(args[j], XtNx, x); j++;
5896 XtSetArg(args[j], XtNy, y); j++;
5897 XtSetValues(promotionShell, args, j);
5899 XtPopup(promotionShell, XtGrabNone);
5904 void PromotionPopDown()
5906 if (!promotionUp) return;
5907 XtPopdown(promotionShell);
5908 XtDestroyWidget(promotionShell);
5909 promotionUp = False;
5912 void PromotionCallback(w, client_data, call_data)
5914 XtPointer client_data, call_data;
5920 XtSetArg(args[0], XtNlabel, &name);
5921 XtGetValues(w, args, 1);
5925 if (fromX == -1) return;
5927 if (strcmp(name, _("cancel")) == 0) {
5931 } else if (strcmp(name, _("Knight")) == 0) {
5933 } else if (strcmp(name, _("Promote")) == 0) {
5935 } else if (strcmp(name, _("Defer")) == 0) {
5938 promoChar = ToLower(name[0]);
5941 UserMoveEvent(fromX, fromY, toX, toY, promoChar);
5943 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
5944 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
5949 void ErrorCallback(w, client_data, call_data)
5951 XtPointer client_data, call_data;
5954 XtPopdown(w = XtParent(XtParent(XtParent(w))));
5956 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
5962 if (!errorUp) return;
5964 XtPopdown(errorShell);
5965 XtDestroyWidget(errorShell);
5966 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
5969 void ErrorPopUp(title, label, modal)
5970 char *title, *label;
5974 Widget dialog, layout;
5978 Dimension bw_width, pw_width;
5979 Dimension pw_height;
5983 XtSetArg(args[i], XtNresizable, True); i++;
5984 XtSetArg(args[i], XtNtitle, title); i++;
5986 XtCreatePopupShell("errorpopup", transientShellWidgetClass,
5987 shellWidget, args, i);
5989 XtCreateManagedWidget(layoutName, formWidgetClass, errorShell,
5990 layoutArgs, XtNumber(layoutArgs));
5993 XtSetArg(args[i], XtNlabel, label); i++;
5994 XtSetArg(args[i], XtNborderWidth, 0); i++;
5995 dialog = XtCreateManagedWidget("dialog", dialogWidgetClass,
5998 XawDialogAddButton(dialog, _("ok"), ErrorCallback, (XtPointer) dialog);
6000 XtRealizeWidget(errorShell);
6001 CatchDeleteWindow(errorShell, "ErrorPopDown");
6004 XtSetArg(args[i], XtNwidth, &bw_width); i++;
6005 XtGetValues(boardWidget, args, i);
6007 XtSetArg(args[i], XtNwidth, &pw_width); i++;
6008 XtSetArg(args[i], XtNheight, &pw_height); i++;
6009 XtGetValues(errorShell, args, i);
6012 /* This code seems to tickle an X bug if it is executed too soon
6013 after xboard starts up. The coordinates get transformed as if
6014 the main window was positioned at (0, 0).
6016 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
6017 0 - pw_height + squareSize / 3, &x, &y);
6019 XTranslateCoordinates(xDisplay, XtWindow(boardWidget),
6020 RootWindowOfScreen(XtScreen(boardWidget)),
6021 (bw_width - pw_width) / 2,
6022 0 - pw_height + squareSize / 3, &xx, &yy, &junk);
6026 if (y < 0) y = 0; /*avoid positioning top offscreen*/
6029 XtSetArg(args[i], XtNx, x); i++;
6030 XtSetArg(args[i], XtNy, y); i++;
6031 XtSetValues(errorShell, args, i);
6034 XtPopup(errorShell, modal ? XtGrabExclusive : XtGrabNone);
6037 /* Disable all user input other than deleting the window */
6038 static int frozen = 0;
6042 /* Grab by a widget that doesn't accept input */
6043 XtAddGrab(messageWidget, TRUE, FALSE);
6047 /* Undo a FreezeUI */
6050 if (!frozen) return;
6051 XtRemoveGrab(messageWidget);
6055 char *ModeToWidgetName(mode)
6059 case BeginningOfGame:
6060 if (appData.icsActive)
6061 return "menuMode.ICS Client";
6062 else if (appData.noChessProgram ||
6063 *appData.cmailGameName != NULLCHAR)
6064 return "menuMode.Edit Game";
6066 return "menuMode.Machine Black";
6067 case MachinePlaysBlack:
6068 return "menuMode.Machine Black";
6069 case MachinePlaysWhite:
6070 return "menuMode.Machine White";
6072 return "menuMode.Analysis Mode";
6074 return "menuMode.Analyze File";
6075 case TwoMachinesPlay:
6076 return "menuMode.Two Machines";
6078 return "menuMode.Edit Game";
6079 case PlayFromGameFile:
6080 return "menuFile.Load Game";
6082 return "menuMode.Edit Position";
6084 return "menuMode.Training";
6085 case IcsPlayingWhite:
6086 case IcsPlayingBlack:
6090 return "menuMode.ICS Client";
6097 void ModeHighlight()
6100 static int oldPausing = FALSE;
6101 static GameMode oldmode = (GameMode) -1;
6104 if (!boardWidget || !XtIsRealized(boardWidget)) return;
6106 if (pausing != oldPausing) {
6107 oldPausing = pausing;
6109 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6111 XtSetArg(args[0], XtNleftBitmap, None);
6113 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Pause"),
6116 if (appData.showButtonBar) {
6119 XtSetArg(args[0], XtNbackground, buttonForegroundPixel);
6120 XtSetArg(args[1], XtNforeground, buttonBackgroundPixel);
6122 XtSetArg(args[0], XtNbackground, buttonBackgroundPixel);
6123 XtSetArg(args[1], XtNforeground, buttonForegroundPixel);
6126 /* Always toggle, don't set. Previous code messes up when
6127 invoked while the button is pressed, as releasing it
6128 toggles the state again. */
6131 XtSetArg(args[0], XtNbackground, &oldbg);
6132 XtSetArg(args[1], XtNforeground, &oldfg);
6133 XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON),
6135 XtSetArg(args[0], XtNbackground, oldfg);
6136 XtSetArg(args[1], XtNforeground, oldbg);
6139 XtSetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
6143 wname = ModeToWidgetName(oldmode);
6144 if (wname != NULL) {
6145 XtSetArg(args[0], XtNleftBitmap, None);
6146 XtSetValues(XtNameToWidget(menuBarWidget, wname), args, 1);
6148 wname = ModeToWidgetName(gameMode);
6149 if (wname != NULL) {
6150 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6151 XtSetValues(XtNameToWidget(menuBarWidget, wname), args, 1);
6155 /* Maybe all the enables should be handled here, not just this one */
6156 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Training"),
6157 gameMode == Training || gameMode == PlayFromGameFile);
6162 * Button/menu procedures
6164 void ResetProc(w, event, prms, nprms)
6174 int LoadGamePopUp(f, gameNumber, title)
6179 cmailMsgLoaded = FALSE;
6180 if (gameNumber == 0) {
6181 int error = GameListBuild(f);
6183 DisplayError(_("Cannot build game list"), error);
6184 } else if (!ListEmpty(&gameList) &&
6185 ((ListGame *) gameList.tailPred)->number > 1) {
6186 GameListPopUp(f, title);
6192 return LoadGame(f, gameNumber, title, FALSE);
6195 void LoadGameProc(w, event, prms, nprms)
6201 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
6204 FileNamePopUp(_("Load game file name?"), "", LoadGamePopUp, "rb");
6207 void LoadNextGameProc(w, event, prms, nprms)
6216 void LoadPrevGameProc(w, event, prms, nprms)
6225 void ReloadGameProc(w, event, prms, nprms)
6234 void LoadNextPositionProc(w, event, prms, nprms)
6243 void LoadPrevPositionProc(w, event, prms, nprms)
6252 void ReloadPositionProc(w, event, prms, nprms)
6261 void LoadPositionProc(w, event, prms, nprms)
6267 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
6270 FileNamePopUp(_("Load position file name?"), "", LoadPosition, "rb");
6273 void SaveGameProc(w, event, prms, nprms)
6279 FileNamePopUp(_("Save game file name?"),
6280 DefaultFileName(appData.oldSaveStyle ? "game" : "pgn"),
6284 void SavePositionProc(w, event, prms, nprms)
6290 FileNamePopUp(_("Save position file name?"),
6291 DefaultFileName(appData.oldSaveStyle ? "pos" : "fen"),
6295 void ReloadCmailMsgProc(w, event, prms, nprms)
6301 ReloadCmailMsgEvent(FALSE);
6304 void MailMoveProc(w, event, prms, nprms)
6313 /* this variable is shared between CopyPositionProc and SendPositionSelection */
6314 static char *selected_fen_position=NULL;
6317 SendPositionSelection(Widget w, Atom *selection, Atom *target,
6318 Atom *type_return, XtPointer *value_return,
6319 unsigned long *length_return, int *format_return)
6321 char *selection_tmp;
6323 if (!selected_fen_position) return False; /* should never happen */
6324 if (*target == XA_STRING){
6325 /* note: since no XtSelectionDoneProc was registered, Xt will
6326 * automatically call XtFree on the value returned. So have to
6327 * make a copy of it allocated with XtMalloc */
6328 selection_tmp= XtMalloc(strlen(selected_fen_position)+16);
6329 strcpy(selection_tmp, selected_fen_position);
6331 *value_return=selection_tmp;
6332 *length_return=strlen(selection_tmp);
6333 *type_return=XA_STRING;
6334 *format_return = 8; /* bits per byte */
6341 /* note: when called from menu all parameters are NULL, so no clue what the
6342 * Widget which was clicked on was, or what the click event was
6344 void CopyPositionProc(w, event, prms, nprms)
6352 if (selected_fen_position) free(selected_fen_position);
6353 selected_fen_position = (char *)PositionToFEN(currentMove, NULL);
6354 if (!selected_fen_position) return;
6355 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
6357 SendPositionSelection,
6358 NULL/* lose_ownership_proc */ ,
6359 NULL/* transfer_done_proc */);
6361 free(selected_fen_position);
6362 selected_fen_position=NULL;
6366 /* function called when the data to Paste is ready */
6368 PastePositionCB(Widget w, XtPointer client_data, Atom *selection,
6369 Atom *type, XtPointer value, unsigned long *len, int *format)
6372 if (value==NULL || *len==0) return; /* nothing had been selected to copy */
6373 fenstr[*len]='\0'; /* normally this string is terminated, but be safe */
6374 EditPositionPasteFEN(fenstr);
6378 /* called when Paste Position button is pressed,
6379 * all parameters will be NULL */
6380 void PastePositionProc(w, event, prms, nprms)
6386 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
6387 /* (XtSelectionCallbackProc) */ PastePositionCB,
6388 NULL, /* client_data passed to PastePositionCB */
6390 /* better to use the time field from the event that triggered the
6391 * call to this function, but that isn't trivial to get
6399 SendGameSelection(Widget w, Atom *selection, Atom *target,
6400 Atom *type_return, XtPointer *value_return,
6401 unsigned long *length_return, int *format_return)
6403 char *selection_tmp;
6405 if (*target == XA_STRING){
6406 FILE* f = fopen(gameCopyFilename, "r");
6409 if (f == NULL) return False;
6413 selection_tmp = XtMalloc(len + 1);
6414 count = fread(selection_tmp, 1, len, f);
6416 XtFree(selection_tmp);
6419 selection_tmp[len] = NULLCHAR;
6420 *value_return = selection_tmp;
6421 *length_return = len;
6422 *type_return = XA_STRING;
6423 *format_return = 8; /* bits per byte */
6430 /* note: when called from menu all parameters are NULL, so no clue what the
6431 * Widget which was clicked on was, or what the click event was
6433 void CopyGameProc(w, event, prms, nprms)
6441 ret = SaveGameToFile(gameCopyFilename, FALSE);
6444 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
6447 NULL/* lose_ownership_proc */ ,
6448 NULL/* transfer_done_proc */);
6451 /* function called when the data to Paste is ready */
6453 PasteGameCB(Widget w, XtPointer client_data, Atom *selection,
6454 Atom *type, XtPointer value, unsigned long *len, int *format)
6457 if (value == NULL || *len == 0) {
6458 return; /* nothing had been selected to copy */
6460 f = fopen(gamePasteFilename, "w");
6462 DisplayError(_("Can't open temp file"), errno);
6465 fwrite(value, 1, *len, f);
6468 LoadGameFromFile(gamePasteFilename, 0, gamePasteFilename, TRUE);
6471 /* called when Paste Game button is pressed,
6472 * all parameters will be NULL */
6473 void PasteGameProc(w, event, prms, nprms)
6479 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
6480 /* (XtSelectionCallbackProc) */ PasteGameCB,
6481 NULL, /* client_data passed to PasteGameCB */
6483 /* better to use the time field from the event that triggered the
6484 * call to this function, but that isn't trivial to get
6494 SaveGameProc(NULL, NULL, NULL, NULL);
6498 void QuitProc(w, event, prms, nprms)
6507 void PauseProc(w, event, prms, nprms)
6517 void MachineBlackProc(w, event, prms, nprms)
6523 MachineBlackEvent();
6526 void MachineWhiteProc(w, event, prms, nprms)
6532 MachineWhiteEvent();
6535 void AnalyzeModeProc(w, event, prms, nprms)
6543 if (!first.analysisSupport) {
6544 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
6545 DisplayError(buf, 0);
6548 /* [DM] icsEngineAnalyze [HGM] This is horrible code; reverse the gameMode and isEngineAnalyze tests! */
6549 if (appData.icsActive) {
6550 if (gameMode != IcsObserving) {
6551 sprintf(buf,_("You are not observing a game"));
6552 DisplayError(buf, 0);
6554 if (appData.icsEngineAnalyze) {
6555 if (appData.debugMode)
6556 fprintf(debugFP, _("Found unexpected active ICS engine analyze \n"));
6562 /* if enable, use want disable icsEngineAnalyze */
6563 if (appData.icsEngineAnalyze) {
6568 appData.icsEngineAnalyze = TRUE;
6569 if (appData.debugMode)
6570 fprintf(debugFP, _("ICS engine analyze starting... \n"));
6572 if (!appData.showThinking)
6573 ShowThinkingProc(w,event,prms,nprms);
6578 void AnalyzeFileProc(w, event, prms, nprms)
6584 if (!first.analysisSupport) {
6586 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
6587 DisplayError(buf, 0);
6592 if (!appData.showThinking)
6593 ShowThinkingProc(w,event,prms,nprms);
6596 FileNamePopUp(_("File to analyze"), "", LoadGamePopUp, "rb");
6597 AnalysisPeriodicEvent(1);
6600 void TwoMachinesProc(w, event, prms, nprms)
6609 void IcsClientProc(w, event, prms, nprms)
6618 void EditGameProc(w, event, prms, nprms)
6627 void EditPositionProc(w, event, prms, nprms)
6633 EditPositionEvent();
6636 void TrainingProc(w, event, prms, nprms)
6645 void EditCommentProc(w, event, prms, nprms)
6652 EditCommentPopDown();
6658 void IcsInputBoxProc(w, event, prms, nprms)
6664 if (ICSInputBoxUp) {
6665 ICSInputBoxPopDown();
6671 void AcceptProc(w, event, prms, nprms)
6680 void DeclineProc(w, event, prms, nprms)
6689 void RematchProc(w, event, prms, nprms)
6698 void CallFlagProc(w, event, prms, nprms)
6707 void DrawProc(w, event, prms, nprms)
6716 void AbortProc(w, event, prms, nprms)
6725 void AdjournProc(w, event, prms, nprms)
6734 void ResignProc(w, event, prms, nprms)
6743 void AdjuWhiteProc(w, event, prms, nprms)
6749 UserAdjudicationEvent(+1);
6752 void AdjuBlackProc(w, event, prms, nprms)
6758 UserAdjudicationEvent(-1);
6761 void AdjuDrawProc(w, event, prms, nprms)
6767 UserAdjudicationEvent(0);
6770 void EnterKeyProc(w, event, prms, nprms)
6776 if (ICSInputBoxUp == True)
6780 void StopObservingProc(w, event, prms, nprms)
6786 StopObservingEvent();
6789 void StopExaminingProc(w, event, prms, nprms)
6795 StopExaminingEvent();
6799 void ForwardProc(w, event, prms, nprms)
6809 void BackwardProc(w, event, prms, nprms)
6818 void ToStartProc(w, event, prms, nprms)
6827 void ToEndProc(w, event, prms, nprms)
6836 void RevertProc(w, event, prms, nprms)
6845 void TruncateGameProc(w, event, prms, nprms)
6851 TruncateGameEvent();
6853 void RetractMoveProc(w, event, prms, nprms)
6862 void MoveNowProc(w, event, prms, nprms)
6872 void AlwaysQueenProc(w, event, prms, nprms)
6880 appData.alwaysPromoteToQueen = !appData.alwaysPromoteToQueen;
6882 if (appData.alwaysPromoteToQueen) {
6883 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6885 XtSetArg(args[0], XtNleftBitmap, None);
6887 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
6891 void AnimateDraggingProc(w, event, prms, nprms)
6899 appData.animateDragging = !appData.animateDragging;
6901 if (appData.animateDragging) {
6902 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6905 XtSetArg(args[0], XtNleftBitmap, None);
6907 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Dragging"),
6911 void AnimateMovingProc(w, event, prms, nprms)
6919 appData.animate = !appData.animate;
6921 if (appData.animate) {
6922 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6925 XtSetArg(args[0], XtNleftBitmap, None);
6927 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
6931 void AutocommProc(w, event, prms, nprms)
6939 appData.autoComment = !appData.autoComment;
6941 if (appData.autoComment) {
6942 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6944 XtSetArg(args[0], XtNleftBitmap, None);
6946 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
6951 void AutoflagProc(w, event, prms, nprms)
6959 appData.autoCallFlag = !appData.autoCallFlag;
6961 if (appData.autoCallFlag) {
6962 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6964 XtSetArg(args[0], XtNleftBitmap, None);
6966 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
6970 void AutoflipProc(w, event, prms, nprms)
6978 appData.autoFlipView = !appData.autoFlipView;
6980 if (appData.autoFlipView) {
6981 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6983 XtSetArg(args[0], XtNleftBitmap, None);
6985 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flip View"),
6989 void AutobsProc(w, event, prms, nprms)
6997 appData.autoObserve = !appData.autoObserve;
6999 if (appData.autoObserve) {
7000 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7002 XtSetArg(args[0], XtNleftBitmap, None);
7004 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
7008 void AutoraiseProc(w, event, prms, nprms)
7016 appData.autoRaiseBoard = !appData.autoRaiseBoard;
7018 if (appData.autoRaiseBoard) {
7019 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7021 XtSetArg(args[0], XtNleftBitmap, None);
7023 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Raise Board"),
7027 void AutosaveProc(w, event, prms, nprms)
7035 appData.autoSaveGames = !appData.autoSaveGames;
7037 if (appData.autoSaveGames) {
7038 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7040 XtSetArg(args[0], XtNleftBitmap, None);
7042 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
7046 void BlindfoldProc(w, event, prms, nprms)
7054 appData.blindfold = !appData.blindfold;
7056 if (appData.blindfold) {
7057 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7059 XtSetArg(args[0], XtNleftBitmap, None);
7061 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Blindfold"),
7064 DrawPosition(True, NULL);
7067 void TestLegalityProc(w, event, prms, nprms)
7075 appData.testLegality = !appData.testLegality;
7077 if (appData.testLegality) {
7078 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7080 XtSetArg(args[0], XtNleftBitmap, None);
7082 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Test Legality"),
7087 void FlashMovesProc(w, event, prms, nprms)
7095 if (appData.flashCount == 0) {
7096 appData.flashCount = 3;
7098 appData.flashCount = -appData.flashCount;
7101 if (appData.flashCount > 0) {
7102 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7104 XtSetArg(args[0], XtNleftBitmap, None);
7106 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flash Moves"),
7110 void FlipViewProc(w, event, prms, nprms)
7116 flipView = !flipView;
7117 DrawPosition(True, NULL);
7120 void GetMoveListProc(w, event, prms, nprms)
7128 appData.getMoveList = !appData.getMoveList;
7130 if (appData.getMoveList) {
7131 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7134 XtSetArg(args[0], XtNleftBitmap, None);
7136 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
7141 void HighlightDraggingProc(w, event, prms, nprms)
7149 appData.highlightDragging = !appData.highlightDragging;
7151 if (appData.highlightDragging) {
7152 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7154 XtSetArg(args[0], XtNleftBitmap, None);
7156 XtSetValues(XtNameToWidget(menuBarWidget,
7157 "menuOptions.Highlight Dragging"), args, 1);
7161 void HighlightLastMoveProc(w, event, prms, nprms)
7169 appData.highlightLastMove = !appData.highlightLastMove;
7171 if (appData.highlightLastMove) {
7172 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7174 XtSetArg(args[0], XtNleftBitmap, None);
7176 XtSetValues(XtNameToWidget(menuBarWidget,
7177 "menuOptions.Highlight Last Move"), args, 1);
7180 void IcsAlarmProc(w, event, prms, nprms)
7188 appData.icsAlarm = !appData.icsAlarm;
7190 if (appData.icsAlarm) {
7191 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7193 XtSetArg(args[0], XtNleftBitmap, None);
7195 XtSetValues(XtNameToWidget(menuBarWidget,
7196 "menuOptions.ICS Alarm"), args, 1);
7199 void MoveSoundProc(w, event, prms, nprms)
7207 appData.ringBellAfterMoves = !appData.ringBellAfterMoves;
7209 if (appData.ringBellAfterMoves) {
7210 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7212 XtSetArg(args[0], XtNleftBitmap, None);
7214 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
7219 void OldSaveStyleProc(w, event, prms, nprms)
7227 appData.oldSaveStyle = !appData.oldSaveStyle;
7229 if (appData.oldSaveStyle) {
7230 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7232 XtSetArg(args[0], XtNleftBitmap, None);
7234 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Old Save Style"),
7238 void PeriodicUpdatesProc(w, event, prms, nprms)
7246 PeriodicUpdatesEvent(!appData.periodicUpdates);
7248 if (appData.periodicUpdates) {
7249 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7251 XtSetArg(args[0], XtNleftBitmap, None);
7253 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Periodic Updates"),
7257 void PonderNextMoveProc(w, event, prms, nprms)
7265 PonderNextMoveEvent(!appData.ponderNextMove);
7267 if (appData.ponderNextMove) {
7268 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7270 XtSetArg(args[0], XtNleftBitmap, None);
7272 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Ponder Next Move"),
7276 void PopupExitMessageProc(w, event, prms, nprms)
7284 appData.popupExitMessage = !appData.popupExitMessage;
7286 if (appData.popupExitMessage) {
7287 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7289 XtSetArg(args[0], XtNleftBitmap, None);
7291 XtSetValues(XtNameToWidget(menuBarWidget,
7292 "menuOptions.Popup Exit Message"), args, 1);
7295 void PopupMoveErrorsProc(w, event, prms, nprms)
7303 appData.popupMoveErrors = !appData.popupMoveErrors;
7305 if (appData.popupMoveErrors) {
7306 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7308 XtSetArg(args[0], XtNleftBitmap, None);
7310 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Popup Move Errors"),
7314 void PremoveProc(w, event, prms, nprms)
7322 appData.premove = !appData.premove;
7324 if (appData.premove) {
7325 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7327 XtSetArg(args[0], XtNleftBitmap, None);
7329 XtSetValues(XtNameToWidget(menuBarWidget,
7330 "menuOptions.Premove"), args, 1);
7333 void QuietPlayProc(w, event, prms, nprms)
7341 appData.quietPlay = !appData.quietPlay;
7343 if (appData.quietPlay) {
7344 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7346 XtSetArg(args[0], XtNleftBitmap, None);
7348 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Quiet Play"),
7352 void ShowCoordsProc(w, event, prms, nprms)
7360 appData.showCoords = !appData.showCoords;
7362 if (appData.showCoords) {
7363 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7365 XtSetArg(args[0], XtNleftBitmap, None);
7367 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
7370 DrawPosition(True, NULL);
7373 void ShowThinkingProc(w, event, prms, nprms)
7381 appData.showThinking = !appData.showThinking; // [HGM] thinking: tken out of ShowThinkingEvent
7382 ShowThinkingEvent();
7384 // [HGM] thinking: currently no suc menu item; replaced by Hide Thinking (From Human)
7385 if (appData.showThinking) {
7386 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7388 XtSetArg(args[0], XtNleftBitmap, None);
7390 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Thinking"),
7395 void HideThinkingProc(w, event, prms, nprms)
7403 appData.hideThinkingFromHuman = !appData.hideThinkingFromHuman; // [HGM] thinking: tken out of ShowThinkingEvent
7404 ShowThinkingEvent();
7406 if (appData.hideThinkingFromHuman) {
7407 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7409 XtSetArg(args[0], XtNleftBitmap, None);
7411 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
7415 void InfoProc(w, event, prms, nprms)
7422 snprintf(buf, sizeof(buf), "xterm -e info --directory %s --directory . -f %s &",
7427 void ManProc(w, event, prms, nprms)
7435 if (nprms && *nprms > 0)
7439 snprintf(buf, sizeof(buf), "xterm -e man %s &", name);
7443 void HintProc(w, event, prms, nprms)
7452 void BookProc(w, event, prms, nprms)
7461 void AboutProc(w, event, prms, nprms)
7469 char *zippy = " (with Zippy code)";
7473 snprintf(buf, sizeof(buf), "%s%s\n\n%s\n%s\n%s\n\n%s%s\n%s",
7474 programVersion, zippy,
7475 "Copyright 1991 Digital Equipment Corporation",
7476 "Enhancements Copyright 1992-2009 Free Software Foundation",
7477 "Enhancements Copyright 2005 Alessandro Scotti",
7478 PRODUCT, " is free software and carries NO WARRANTY;",
7479 "see the file COPYING for more information.");
7480 ErrorPopUp(_("About XBoard"), buf, FALSE);
7483 void DebugProc(w, event, prms, nprms)
7489 appData.debugMode = !appData.debugMode;
7492 void AboutGameProc(w, event, prms, nprms)
7501 void NothingProc(w, event, prms, nprms)
7510 void Iconify(w, event, prms, nprms)
7519 XtSetArg(args[0], XtNiconic, True);
7520 XtSetValues(shellWidget, args, 1);
7523 void DisplayMessage(message, extMessage)
7524 char *message, *extMessage;
7531 snprintf(buf, sizeof(buf), "%s %s", message, extMessage);
7534 message = extMessage;
7537 XtSetArg(arg, XtNlabel, message);
7538 XtSetValues(messageWidget, &arg, 1);
7541 void DisplayTitle(text)
7546 char title[MSG_SIZ];
7549 if (text == NULL) text = "";
7551 if (appData.titleInWindow) {
7553 XtSetArg(args[i], XtNlabel, text); i++;
7554 XtSetValues(titleWidget, args, i);
7557 if (*text != NULLCHAR) {
7559 strcpy(title, text);
7560 } else if (appData.icsActive) {
7561 snprintf(icon, sizeof(icon), "%s", appData.icsHost);
7562 snprintf(title, sizeof(title), "%s: %s", programName, appData.icsHost);
7563 } else if (appData.cmailGameName[0] != NULLCHAR) {
7564 snprintf(icon, sizeof(icon), "%s", "CMail");
7565 snprintf(title,sizeof(title), "%s: %s", programName, "CMail");
7567 // [HGM] license: This stuff should really be done in back-end, but WinBoard already had a pop-up for it
7568 } else if (gameInfo.variant == VariantGothic) {
7569 strcpy(icon, programName);
7570 strcpy(title, GOTHIC);
7573 } else if (gameInfo.variant == VariantFalcon) {
7574 strcpy(icon, programName);
7575 strcpy(title, FALCON);
7577 } else if (appData.noChessProgram) {
7578 strcpy(icon, programName);
7579 strcpy(title, programName);
7581 strcpy(icon, first.tidy);
7582 snprintf(title,sizeof(title), "%s: %s", programName, first.tidy);
7585 XtSetArg(args[i], XtNiconName, (XtArgVal) icon); i++;
7586 XtSetArg(args[i], XtNtitle, (XtArgVal) title); i++;
7587 XtSetValues(shellWidget, args, i);
7591 void DisplayError(message, error)
7598 if (appData.debugMode || appData.matchMode) {
7599 fprintf(stderr, "%s: %s\n", programName, message);
7602 if (appData.debugMode || appData.matchMode) {
7603 fprintf(stderr, "%s: %s: %s\n",
7604 programName, message, strerror(error));
7606 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
7609 ErrorPopUp(_("Error"), message, FALSE);
7613 void DisplayMoveError(message)
7618 DrawPosition(FALSE, NULL);
7619 if (appData.debugMode || appData.matchMode) {
7620 fprintf(stderr, "%s: %s\n", programName, message);
7622 if (appData.popupMoveErrors) {
7623 ErrorPopUp(_("Error"), message, FALSE);
7625 DisplayMessage(message, "");
7630 void DisplayFatalError(message, error, status)
7636 errorExitStatus = status;
7638 fprintf(stderr, "%s: %s\n", programName, message);
7640 fprintf(stderr, "%s: %s: %s\n",
7641 programName, message, strerror(error));
7642 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
7645 if (appData.popupExitMessage && boardWidget && XtIsRealized(boardWidget)) {
7646 ErrorPopUp(status ? _("Fatal Error") : _("Exiting"), message, TRUE);
7652 void DisplayInformation(message)
7656 ErrorPopUp(_("Information"), message, TRUE);
7659 void DisplayNote(message)
7663 ErrorPopUp(_("Note"), message, FALSE);
7667 NullXErrorCheck(dpy, error_event)
7669 XErrorEvent *error_event;
7674 void DisplayIcsInteractionTitle(message)
7677 if (oldICSInteractionTitle == NULL) {
7678 /* Magic to find the old window title, adapted from vim */
7679 char *wina = getenv("WINDOWID");
7681 Window win = (Window) atoi(wina);
7682 Window root, parent, *children;
7683 unsigned int nchildren;
7684 int (*oldHandler)() = XSetErrorHandler(NullXErrorCheck);
7686 if (XFetchName(xDisplay, win, &oldICSInteractionTitle)) break;
7687 if (!XQueryTree(xDisplay, win, &root, &parent,
7688 &children, &nchildren)) break;
7689 if (children) XFree((void *)children);
7690 if (parent == root || parent == 0) break;
7693 XSetErrorHandler(oldHandler);
7695 if (oldICSInteractionTitle == NULL) {
7696 oldICSInteractionTitle = "xterm";
7699 printf("\033]0;%s\007", message);
7703 char pendingReplyPrefix[MSG_SIZ];
7704 ProcRef pendingReplyPR;
7706 void AskQuestionProc(w, event, prms, nprms)
7713 fprintf(stderr, _("AskQuestionProc needed 4 parameters, got %d\n"),
7717 AskQuestionEvent(prms[0], prms[1], prms[2], prms[3]);
7720 void AskQuestionPopDown()
7722 if (!askQuestionUp) return;
7723 XtPopdown(askQuestionShell);
7724 XtDestroyWidget(askQuestionShell);
7725 askQuestionUp = False;
7728 void AskQuestionReplyAction(w, event, prms, nprms)
7738 reply = XawDialogGetValueString(w = XtParent(w));
7739 strcpy(buf, pendingReplyPrefix);
7740 if (*buf) strcat(buf, " ");
7743 OutputToProcess(pendingReplyPR, buf, strlen(buf), &err);
7744 AskQuestionPopDown();
7746 if (err) DisplayFatalError(_("Error writing to chess program"), err, 0);
7749 void AskQuestionCallback(w, client_data, call_data)
7751 XtPointer client_data, call_data;
7756 XtSetArg(args[0], XtNlabel, &name);
7757 XtGetValues(w, args, 1);
7759 if (strcmp(name, _("cancel")) == 0) {
7760 AskQuestionPopDown();
7762 AskQuestionReplyAction(w, NULL, NULL, NULL);
7766 void AskQuestion(title, question, replyPrefix, pr)
7767 char *title, *question, *replyPrefix;
7771 Widget popup, layout, dialog, edit;
7777 strcpy(pendingReplyPrefix, replyPrefix);
7778 pendingReplyPR = pr;
7781 XtSetArg(args[i], XtNresizable, True); i++;
7782 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
7783 askQuestionShell = popup =
7784 XtCreatePopupShell(title, transientShellWidgetClass,
7785 shellWidget, args, i);
7788 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
7789 layoutArgs, XtNumber(layoutArgs));
7792 XtSetArg(args[i], XtNlabel, question); i++;
7793 XtSetArg(args[i], XtNvalue, ""); i++;
7794 XtSetArg(args[i], XtNborderWidth, 0); i++;
7795 dialog = XtCreateManagedWidget("question", dialogWidgetClass,
7798 XawDialogAddButton(dialog, _("enter"), AskQuestionCallback,
7799 (XtPointer) dialog);
7800 XawDialogAddButton(dialog, _("cancel"), AskQuestionCallback,
7801 (XtPointer) dialog);
7803 XtRealizeWidget(popup);
7804 CatchDeleteWindow(popup, "AskQuestionPopDown");
7806 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
7807 &x, &y, &win_x, &win_y, &mask);
7809 XtSetArg(args[0], XtNx, x - 10);
7810 XtSetArg(args[1], XtNy, y - 30);
7811 XtSetValues(popup, args, 2);
7813 XtPopup(popup, XtGrabExclusive);
7814 askQuestionUp = True;
7816 edit = XtNameToWidget(dialog, "*value");
7817 XtSetKeyboardFocus(popup, edit);
7825 if (*name == NULLCHAR) {
7827 } else if (strcmp(name, "$") == 0) {
7828 putc(BELLCHAR, stderr);
7831 snprintf(buf, sizeof(buf), "%s '%s' &", appData.soundProgram, name);
7839 PlaySound(appData.soundMove);
7845 PlaySound(appData.soundIcsWin);
7851 PlaySound(appData.soundIcsLoss);
7857 PlaySound(appData.soundIcsDraw);
7861 PlayIcsUnfinishedSound()
7863 PlaySound(appData.soundIcsUnfinished);
7869 PlaySound(appData.soundIcsAlarm);
7875 system("stty echo");
7881 system("stty -echo");
7885 Colorize(cc, continuation)
7890 int count, outCount, error;
7892 if (textColors[(int)cc].bg > 0) {
7893 if (textColors[(int)cc].fg > 0) {
7894 sprintf(buf, "\033[0;%d;%d;%dm", textColors[(int)cc].attr,
7895 textColors[(int)cc].fg, textColors[(int)cc].bg);
7897 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
7898 textColors[(int)cc].bg);
7901 if (textColors[(int)cc].fg > 0) {
7902 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
7903 textColors[(int)cc].fg);
7905 sprintf(buf, "\033[0;%dm", textColors[(int)cc].attr);
7908 count = strlen(buf);
7909 outCount = OutputToProcess(NoProc, buf, count, &error);
7910 if (outCount < count) {
7911 DisplayFatalError(_("Error writing to display"), error, 1);
7914 if (continuation) return;
7917 PlaySound(appData.soundShout);
7920 PlaySound(appData.soundSShout);
7923 PlaySound(appData.soundChannel1);
7926 PlaySound(appData.soundChannel);
7929 PlaySound(appData.soundKibitz);
7932 PlaySound(appData.soundTell);
7934 case ColorChallenge:
7935 PlaySound(appData.soundChallenge);
7938 PlaySound(appData.soundRequest);
7941 PlaySound(appData.soundSeek);
7952 return getpwuid(getuid())->pw_name;
7955 static char *ExpandPathName(path)
7958 static char static_buf[2000];
7959 char *d, *s, buf[2000];
7965 while (*s && isspace(*s))
7974 if (*(s+1) == '/') {
7975 strcpy(d, getpwuid(getuid())->pw_dir);
7980 *strchr(buf, '/') = 0;
7981 pwd = getpwnam(buf);
7984 fprintf(stderr, _("ERROR: Unknown user %s (in path %s)\n"),
7988 strcpy(d, pwd->pw_dir);
7989 strcat(d, strchr(s+1, '/'));
8000 static char host_name[MSG_SIZ];
8002 #if HAVE_GETHOSTNAME
8003 gethostname(host_name, MSG_SIZ);
8005 #else /* not HAVE_GETHOSTNAME */
8006 # if HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H
8007 sysinfo(SI_HOSTNAME, host_name, MSG_SIZ);
8009 # else /* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
8011 # endif/* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
8012 #endif /* not HAVE_GETHOSTNAME */
8015 XtIntervalId delayedEventTimerXID = 0;
8016 DelayedEventCallback delayedEventCallback = 0;
8021 delayedEventTimerXID = 0;
8022 delayedEventCallback();
8026 ScheduleDelayedEvent(cb, millisec)
8027 DelayedEventCallback cb; long millisec;
8029 delayedEventCallback = cb;
8030 delayedEventTimerXID =
8031 XtAppAddTimeOut(appContext, millisec,
8032 (XtTimerCallbackProc) FireDelayedEvent, (XtPointer) 0);
8035 DelayedEventCallback
8038 if (delayedEventTimerXID) {
8039 return delayedEventCallback;
8046 CancelDelayedEvent()
8048 if (delayedEventTimerXID) {
8049 XtRemoveTimeOut(delayedEventTimerXID);
8050 delayedEventTimerXID = 0;
8054 XtIntervalId loadGameTimerXID = 0;
8056 int LoadGameTimerRunning()
8058 return loadGameTimerXID != 0;
8061 int StopLoadGameTimer()
8063 if (loadGameTimerXID != 0) {
8064 XtRemoveTimeOut(loadGameTimerXID);
8065 loadGameTimerXID = 0;
8073 LoadGameTimerCallback(arg, id)
8077 loadGameTimerXID = 0;
8082 StartLoadGameTimer(millisec)
8086 XtAppAddTimeOut(appContext, millisec,
8087 (XtTimerCallbackProc) LoadGameTimerCallback,
8091 XtIntervalId analysisClockXID = 0;
8094 AnalysisClockCallback(arg, id)
8098 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile
8099 || appData.icsEngineAnalyze) { // [DM]
8100 AnalysisPeriodicEvent(0);
8101 StartAnalysisClock();
8106 StartAnalysisClock()
8109 XtAppAddTimeOut(appContext, 2000,
8110 (XtTimerCallbackProc) AnalysisClockCallback,
8114 XtIntervalId clockTimerXID = 0;
8116 int ClockTimerRunning()
8118 return clockTimerXID != 0;
8121 int StopClockTimer()
8123 if (clockTimerXID != 0) {
8124 XtRemoveTimeOut(clockTimerXID);
8133 ClockTimerCallback(arg, id)
8142 StartClockTimer(millisec)
8146 XtAppAddTimeOut(appContext, millisec,
8147 (XtTimerCallbackProc) ClockTimerCallback,
8152 DisplayTimerLabel(w, color, timer, highlight)
8161 Pixel foregroundOrWarningColor = timerForegroundPixel;
8164 && appData.lowTimeWarning
8165 && (timer / 1000) < appData.icsAlarmTime)
8167 foregroundOrWarningColor = lowTimeWarningColor;
8169 if (appData.clockMode) {
8170 sprintf(buf, "%s: %s", color, TimeString(timer));
8171 XtSetArg(args[0], XtNlabel, buf);
8173 sprintf(buf, "%s ", color);
8174 XtSetArg(args[0], XtNlabel, buf);
8179 XtSetArg(args[1], XtNbackground, foregroundOrWarningColor);
8180 XtSetArg(args[2], XtNforeground, timerBackgroundPixel);
8182 XtSetArg(args[1], XtNbackground, timerBackgroundPixel);
8183 XtSetArg(args[2], XtNforeground, foregroundOrWarningColor);
8186 XtSetValues(w, args, 3);
8190 DisplayWhiteClock(timeRemaining, highlight)
8196 if(appData.noGUI) return;
8197 DisplayTimerLabel(whiteTimerWidget, _("White"), timeRemaining, highlight);
8198 if (highlight && iconPixmap == bIconPixmap) {
8199 iconPixmap = wIconPixmap;
8200 XtSetArg(args[0], XtNiconPixmap, iconPixmap);
8201 XtSetValues(shellWidget, args, 1);
8206 DisplayBlackClock(timeRemaining, highlight)
8212 if(appData.noGUI) return;
8213 DisplayTimerLabel(blackTimerWidget, _("Black"), timeRemaining, highlight);
8214 if (highlight && iconPixmap == wIconPixmap) {
8215 iconPixmap = bIconPixmap;
8216 XtSetArg(args[0], XtNiconPixmap, iconPixmap);
8217 XtSetValues(shellWidget, args, 1);
8235 int StartChildProcess(cmdLine, dir, pr)
8242 int to_prog[2], from_prog[2];
8246 if (appData.debugMode) {
8247 fprintf(stderr, "StartChildProcess (dir=\"%s\") %s\n",dir, cmdLine);
8250 /* We do NOT feed the cmdLine to the shell; we just
8251 parse it into blank-separated arguments in the
8252 most simple-minded way possible.
8255 strcpy(buf, cmdLine);
8260 if (p == NULL) break;
8265 SetUpChildIO(to_prog, from_prog);
8267 if ((pid = fork()) == 0) {
8269 // [HGM] PSWBTM: made order resistant against case where fd of created pipe was 0 or 1
8270 close(to_prog[1]); // first close the unused pipe ends
8271 close(from_prog[0]);
8272 dup2(to_prog[0], 0); // to_prog was created first, nd is the only one to use 0 or 1
8273 dup2(from_prog[1], 1);
8274 if(to_prog[0] >= 2) close(to_prog[0]); // if 0 or 1, the dup2 already cosed the original
8275 close(from_prog[1]); // and closing again loses one of the pipes!
8276 if(fileno(stderr) >= 2) // better safe than sorry...
8277 dup2(1, fileno(stderr)); /* force stderr to the pipe */
8279 if (dir[0] != NULLCHAR && chdir(dir) != 0) {
8284 nice(appData.niceEngines); // [HGM] nice: adjust priority of engine proc
8286 execvp(argv[0], argv);
8288 /* If we get here, exec failed */
8293 /* Parent process */
8295 close(from_prog[1]);
8297 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8300 cp->fdFrom = from_prog[0];
8301 cp->fdTo = to_prog[1];
8306 // [HGM] kill: implement the 'hard killing' of AS's Winboard_x
8307 static RETSIGTYPE AlarmCallBack(int n)
8313 DestroyChildProcess(pr, signalType)
8317 ChildProc *cp = (ChildProc *) pr;
8319 if (cp->kind != CPReal) return;
8321 if (signalType == 10) { // [HGM] kill: if it does not terminate in 3 sec, kill
8322 signal(SIGALRM, AlarmCallBack);
8324 if(wait((int *) 0) == -1) { // process does not terminate on its own accord
8325 kill(cp->pid, SIGKILL); // kill it forcefully
8326 wait((int *) 0); // and wait again
8330 kill(cp->pid, signalType == 9 ? SIGKILL : SIGTERM); // [HGM] kill: use hard kill if so requested
8332 /* Process is exiting either because of the kill or because of
8333 a quit command sent by the backend; either way, wait for it to die.
8342 InterruptChildProcess(pr)
8345 ChildProc *cp = (ChildProc *) pr;
8347 if (cp->kind != CPReal) return;
8348 (void) kill(cp->pid, SIGINT); /* stop it thinking */
8351 int OpenTelnet(host, port, pr)
8356 char cmdLine[MSG_SIZ];
8358 if (port[0] == NULLCHAR) {
8359 snprintf(cmdLine, sizeof(cmdLine), "%s %s", appData.telnetProgram, host);
8361 snprintf(cmdLine,sizeof(cmdLine), "%s %s %s", appData.telnetProgram, host, port);
8363 return StartChildProcess(cmdLine, "", pr);
8366 int OpenTCP(host, port, pr)
8372 DisplayFatalError(_("Socket support is not configured in"), 0, 2);
8373 #else /* !OMIT_SOCKETS */
8375 struct sockaddr_in sa;
8377 unsigned short uport;
8380 if ((s = socket(AF_INET, SOCK_STREAM, 6)) < 0) {
8384 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
8385 sa.sin_family = AF_INET;
8386 sa.sin_addr.s_addr = INADDR_ANY;
8387 uport = (unsigned short) 0;
8388 sa.sin_port = htons(uport);
8389 if (bind(s, (struct sockaddr *) &sa, sizeof(struct sockaddr_in)) < 0) {
8393 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
8394 if (!(hp = gethostbyname(host))) {
8396 if (sscanf(host, "%d.%d.%d.%d", &b0, &b1, &b2, &b3) == 4) {
8397 hp = (struct hostent *) calloc(1, sizeof(struct hostent));
8398 hp->h_addrtype = AF_INET;
8400 hp->h_addr_list = (char **) calloc(2, sizeof(char *));
8401 hp->h_addr_list[0] = (char *) malloc(4);
8402 hp->h_addr_list[0][0] = b0;
8403 hp->h_addr_list[0][1] = b1;
8404 hp->h_addr_list[0][2] = b2;
8405 hp->h_addr_list[0][3] = b3;
8410 sa.sin_family = hp->h_addrtype;
8411 uport = (unsigned short) atoi(port);
8412 sa.sin_port = htons(uport);
8413 memcpy((char *) &sa.sin_addr, hp->h_addr, hp->h_length);
8415 if (connect(s, (struct sockaddr *) &sa,
8416 sizeof(struct sockaddr_in)) < 0) {
8420 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8427 #endif /* !OMIT_SOCKETS */
8432 int OpenCommPort(name, pr)
8439 fd = open(name, 2, 0);
8440 if (fd < 0) return errno;
8442 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8452 int OpenLoopback(pr)
8458 SetUpChildIO(to, from);
8460 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8463 cp->fdFrom = to[0]; /* note not from[0]; we are doing a loopback */
8470 int OpenRcmd(host, user, cmd, pr)
8471 char *host, *user, *cmd;
8474 DisplayFatalError(_("internal rcmd not implemented for Unix"), 0, 1);
8478 #define INPUT_SOURCE_BUF_SIZE 8192
8487 char buf[INPUT_SOURCE_BUF_SIZE];
8492 DoInputCallback(closure, source, xid)
8497 InputSource *is = (InputSource *) closure;
8502 if (is->lineByLine) {
8503 count = read(is->fd, is->unused,
8504 INPUT_SOURCE_BUF_SIZE - (is->unused - is->buf));
8506 (is->func)(is, is->closure, is->buf, count, count ? errno : 0);
8509 is->unused += count;
8511 while (p < is->unused) {
8512 q = memchr(p, '\n', is->unused - p);
8513 if (q == NULL) break;
8515 (is->func)(is, is->closure, p, q - p, 0);
8519 while (p < is->unused) {
8524 count = read(is->fd, is->buf, INPUT_SOURCE_BUF_SIZE);
8529 (is->func)(is, is->closure, is->buf, count, error);
8533 InputSourceRef AddInputSource(pr, lineByLine, func, closure)
8540 ChildProc *cp = (ChildProc *) pr;
8542 is = (InputSource *) calloc(1, sizeof(InputSource));
8543 is->lineByLine = lineByLine;
8547 is->fd = fileno(stdin);
8549 is->kind = cp->kind;
8550 is->fd = cp->fdFrom;
8553 is->unused = is->buf;
8556 is->xid = XtAppAddInput(appContext, is->fd,
8557 (XtPointer) (XtInputReadMask),
8558 (XtInputCallbackProc) DoInputCallback,
8560 is->closure = closure;
8561 return (InputSourceRef) is;
8565 RemoveInputSource(isr)
8568 InputSource *is = (InputSource *) isr;
8570 if (is->xid == 0) return;
8571 XtRemoveInput(is->xid);
8575 int OutputToProcess(pr, message, count, outError)
8581 ChildProc *cp = (ChildProc *) pr;
8585 outCount = fwrite(message, 1, count, stdout);
8587 outCount = write(cp->fdTo, message, count);
8597 /* Output message to process, with "ms" milliseconds of delay
8598 between each character. This is needed when sending the logon
8599 script to ICC, which for some reason doesn't like the
8600 instantaneous send. */
8601 int OutputToProcessDelayed(pr, message, count, outError, msdelay)
8608 ChildProc *cp = (ChildProc *) pr;
8613 r = write(cp->fdTo, message++, 1);
8626 /**** Animation code by Hugh Fisher, DCS, ANU.
8628 Known problem: if a window overlapping the board is
8629 moved away while a piece is being animated underneath,
8630 the newly exposed area won't be updated properly.
8631 I can live with this.
8633 Known problem: if you look carefully at the animation
8634 of pieces in mono mode, they are being drawn as solid
8635 shapes without interior detail while moving. Fixing
8636 this would be a major complication for minimal return.
8639 /* Masks for XPM pieces. Black and white pieces can have
8640 different shapes, but in the interest of retaining my
8641 sanity pieces must have the same outline on both light
8642 and dark squares, and all pieces must use the same
8643 background square colors/images. */
8646 CreateAnimMasks (pieceDepth)
8653 unsigned long plane;
8656 /* Need a bitmap just to get a GC with right depth */
8657 buf = XCreatePixmap(xDisplay, xBoardWindow,
8659 values.foreground = 1;
8660 values.background = 0;
8661 /* Don't use XtGetGC, not read only */
8662 maskGC = XCreateGC(xDisplay, buf,
8663 GCForeground | GCBackground, &values);
8664 XFreePixmap(xDisplay, buf);
8666 buf = XCreatePixmap(xDisplay, xBoardWindow,
8667 squareSize, squareSize, pieceDepth);
8668 values.foreground = XBlackPixel(xDisplay, xScreen);
8669 values.background = XWhitePixel(xDisplay, xScreen);
8670 bufGC = XCreateGC(xDisplay, buf,
8671 GCForeground | GCBackground, &values);
8673 for (piece = WhitePawn; piece <= BlackKing; piece++) {
8674 /* Begin with empty mask */
8675 xpmMask[piece] = XCreatePixmap(xDisplay, xBoardWindow,
8676 squareSize, squareSize, 1);
8677 XSetFunction(xDisplay, maskGC, GXclear);
8678 XFillRectangle(xDisplay, xpmMask[piece], maskGC,
8679 0, 0, squareSize, squareSize);
8681 /* Take a copy of the piece */
8686 XSetFunction(xDisplay, bufGC, GXcopy);
8687 XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % (int)BlackPawn],
8689 0, 0, squareSize, squareSize, 0, 0);
8691 /* XOR the background (light) over the piece */
8692 XSetFunction(xDisplay, bufGC, GXxor);
8694 XCopyArea(xDisplay, xpmLightSquare, buf, bufGC,
8695 0, 0, squareSize, squareSize, 0, 0);
8697 XSetForeground(xDisplay, bufGC, lightSquareColor);
8698 XFillRectangle(xDisplay, buf, bufGC, 0, 0, squareSize, squareSize);
8701 /* We now have an inverted piece image with the background
8702 erased. Construct mask by just selecting all the non-zero
8703 pixels - no need to reconstruct the original image. */
8704 XSetFunction(xDisplay, maskGC, GXor);
8706 /* Might be quicker to download an XImage and create bitmap
8707 data from it rather than this N copies per piece, but it
8708 only takes a fraction of a second and there is a much
8709 longer delay for loading the pieces. */
8710 for (n = 0; n < pieceDepth; n ++) {
8711 XCopyPlane(xDisplay, buf, xpmMask[piece], maskGC,
8712 0, 0, squareSize, squareSize,
8718 XFreePixmap(xDisplay, buf);
8719 XFreeGC(xDisplay, bufGC);
8720 XFreeGC(xDisplay, maskGC);
8724 InitAnimState (anim, info)
8726 XWindowAttributes * info;
8731 /* Each buffer is square size, same depth as window */
8732 anim->saveBuf = XCreatePixmap(xDisplay, xBoardWindow,
8733 squareSize, squareSize, info->depth);
8734 anim->newBuf = XCreatePixmap(xDisplay, xBoardWindow,
8735 squareSize, squareSize, info->depth);
8737 /* Create a plain GC for blitting */
8738 mask = GCForeground | GCBackground | GCFunction |
8739 GCPlaneMask | GCGraphicsExposures;
8740 values.foreground = XBlackPixel(xDisplay, xScreen);
8741 values.background = XWhitePixel(xDisplay, xScreen);
8742 values.function = GXcopy;
8743 values.plane_mask = AllPlanes;
8744 values.graphics_exposures = False;
8745 anim->blitGC = XCreateGC(xDisplay, xBoardWindow, mask, &values);
8747 /* Piece will be copied from an existing context at
8748 the start of each new animation/drag. */
8749 anim->pieceGC = XCreateGC(xDisplay, xBoardWindow, 0, &values);
8751 /* Outline will be a read-only copy of an existing */
8752 anim->outlineGC = None;
8758 static int done = 0;
8759 XWindowAttributes info;
8763 XGetWindowAttributes(xDisplay, xBoardWindow, &info);
8765 InitAnimState(&game, &info);
8766 InitAnimState(&player, &info);
8768 /* For XPM pieces, we need bitmaps to use as masks. */
8770 CreateAnimMasks(info.depth);
8775 static Boolean frameWaiting;
8777 static RETSIGTYPE FrameAlarm (sig)
8780 frameWaiting = False;
8781 /* In case System-V style signals. Needed?? */
8782 signal(SIGALRM, FrameAlarm);
8789 struct itimerval delay;
8791 XSync(xDisplay, False);
8794 frameWaiting = True;
8795 signal(SIGALRM, FrameAlarm);
8796 delay.it_interval.tv_sec =
8797 delay.it_value.tv_sec = time / 1000;
8798 delay.it_interval.tv_usec =
8799 delay.it_value.tv_usec = (time % 1000) * 1000;
8800 setitimer(ITIMER_REAL, &delay, NULL);
8802 /* Ugh -- busy-wait! --tpm */
8803 while (frameWaiting);
8805 while (frameWaiting) pause();
8807 delay.it_interval.tv_sec = delay.it_value.tv_sec = 0;
8808 delay.it_interval.tv_usec = delay.it_value.tv_usec = 0;
8809 setitimer(ITIMER_REAL, &delay, NULL);
8819 XSync(xDisplay, False);
8821 usleep(time * 1000);
8826 /* Convert board position to corner of screen rect and color */
8829 ScreenSquare(column, row, pt, color)
8830 int column; int row; XPoint * pt; int * color;
8833 pt->x = lineGap + ((BOARD_WIDTH-1)-column) * (squareSize + lineGap);
8834 pt->y = lineGap + row * (squareSize + lineGap);
8836 pt->x = lineGap + column * (squareSize + lineGap);
8837 pt->y = lineGap + ((BOARD_HEIGHT-1)-row) * (squareSize + lineGap);
8839 *color = SquareColor(row, column);
8842 /* Convert window coords to square */
8845 BoardSquare(x, y, column, row)
8846 int x; int y; int * column; int * row;
8848 *column = EventToSquare(x, BOARD_WIDTH);
8849 if (flipView && *column >= 0)
8850 *column = BOARD_WIDTH - 1 - *column;
8851 *row = EventToSquare(y, BOARD_HEIGHT);
8852 if (!flipView && *row >= 0)
8853 *row = BOARD_HEIGHT - 1 - *row;
8858 #undef Max /* just in case */
8860 #define Max(a, b) ((a) > (b) ? (a) : (b))
8861 #define Min(a, b) ((a) < (b) ? (a) : (b))
8864 SetRect(rect, x, y, width, height)
8865 XRectangle * rect; int x; int y; int width; int height;
8869 rect->width = width;
8870 rect->height = height;
8873 /* Test if two frames overlap. If they do, return
8874 intersection rect within old and location of
8875 that rect within new. */
8878 Intersect(old, new, size, area, pt)
8879 XPoint * old; XPoint * new;
8880 int size; XRectangle * area; XPoint * pt;
8882 if (old->x > new->x + size || new->x > old->x + size ||
8883 old->y > new->y + size || new->y > old->y + size) {
8886 SetRect(area, Max(new->x - old->x, 0), Max(new->y - old->y, 0),
8887 size - abs(old->x - new->x), size - abs(old->y - new->y));
8888 pt->x = Max(old->x - new->x, 0);
8889 pt->y = Max(old->y - new->y, 0);
8894 /* For two overlapping frames, return the rect(s)
8895 in the old that do not intersect with the new. */
8898 CalcUpdateRects(old, new, size, update, nUpdates)
8899 XPoint * old; XPoint * new; int size;
8900 XRectangle update[]; int * nUpdates;
8904 /* If old = new (shouldn't happen) then nothing to draw */
8905 if (old->x == new->x && old->y == new->y) {
8909 /* Work out what bits overlap. Since we know the rects
8910 are the same size we don't need a full intersect calc. */
8912 /* Top or bottom edge? */
8913 if (new->y > old->y) {
8914 SetRect(&(update[count]), old->x, old->y, size, new->y - old->y);
8916 } else if (old->y > new->y) {
8917 SetRect(&(update[count]), old->x, old->y + size - (old->y - new->y),
8918 size, old->y - new->y);
8921 /* Left or right edge - don't overlap any update calculated above. */
8922 if (new->x > old->x) {
8923 SetRect(&(update[count]), old->x, Max(new->y, old->y),
8924 new->x - old->x, size - abs(new->y - old->y));
8926 } else if (old->x > new->x) {
8927 SetRect(&(update[count]), new->x + size, Max(new->y, old->y),
8928 old->x - new->x, size - abs(new->y - old->y));
8935 /* Generate a series of frame coords from start->mid->finish.
8936 The movement rate doubles until the half way point is
8937 reached, then halves back down to the final destination,
8938 which gives a nice slow in/out effect. The algorithmn
8939 may seem to generate too many intermediates for short
8940 moves, but remember that the purpose is to attract the
8941 viewers attention to the piece about to be moved and
8942 then to where it ends up. Too few frames would be less
8946 Tween(start, mid, finish, factor, frames, nFrames)
8947 XPoint * start; XPoint * mid;
8948 XPoint * finish; int factor;
8949 XPoint frames[]; int * nFrames;
8951 int fraction, n, count;
8955 /* Slow in, stepping 1/16th, then 1/8th, ... */
8957 for (n = 0; n < factor; n++)
8959 for (n = 0; n < factor; n++) {
8960 frames[count].x = start->x + (mid->x - start->x) / fraction;
8961 frames[count].y = start->y + (mid->y - start->y) / fraction;
8963 fraction = fraction / 2;
8967 frames[count] = *mid;
8970 /* Slow out, stepping 1/2, then 1/4, ... */
8972 for (n = 0; n < factor; n++) {
8973 frames[count].x = finish->x - (finish->x - mid->x) / fraction;
8974 frames[count].y = finish->y - (finish->y - mid->y) / fraction;
8976 fraction = fraction * 2;
8981 /* Draw a piece on the screen without disturbing what's there */
8984 SelectGCMask(piece, clip, outline, mask)
8985 ChessSquare piece; GC * clip; GC * outline; Pixmap * mask;
8989 /* Bitmap for piece being moved. */
8990 if (appData.monoMode) {
8991 *mask = *pieceToSolid(piece);
8992 } else if (useImages) {
8994 *mask = xpmMask[piece];
8996 *mask = ximMaskPm[piece%(int)BlackPawn];
8999 *mask = *pieceToSolid(piece);
9002 /* GC for piece being moved. Square color doesn't matter, but
9003 since it gets modified we make a copy of the original. */
9005 if (appData.monoMode)
9010 if (appData.monoMode)
9015 XCopyGC(xDisplay, source, 0xFFFFFFFF, *clip);
9017 /* Outline only used in mono mode and is not modified */
9019 *outline = bwPieceGC;
9021 *outline = wbPieceGC;
9025 OverlayPiece(piece, clip, outline, dest)
9026 ChessSquare piece; GC clip; GC outline; Drawable dest;
9031 /* Draw solid rectangle which will be clipped to shape of piece */
9032 XFillRectangle(xDisplay, dest, clip,
9033 0, 0, squareSize, squareSize);
9034 if (appData.monoMode)
9035 /* Also draw outline in contrasting color for black
9036 on black / white on white cases */
9037 XCopyPlane(xDisplay, *pieceToOutline(piece), dest, outline,
9038 0, 0, squareSize, squareSize, 0, 0, 1);
9040 /* Copy the piece */
9045 XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % (int)BlackPawn],
9047 0, 0, squareSize, squareSize,
9052 /* Animate the movement of a single piece */
9055 BeginAnimation(anim, piece, startColor, start)
9063 /* The old buffer is initialised with the start square (empty) */
9064 BlankSquare(0, 0, startColor, EmptySquare, anim->saveBuf);
9065 anim->prevFrame = *start;
9067 /* The piece will be drawn using its own bitmap as a matte */
9068 SelectGCMask(piece, &anim->pieceGC, &anim->outlineGC, &mask);
9069 XSetClipMask(xDisplay, anim->pieceGC, mask);
9073 AnimationFrame(anim, frame, piece)
9078 XRectangle updates[4];
9083 /* Save what we are about to draw into the new buffer */
9084 XCopyArea(xDisplay, xBoardWindow, anim->newBuf, anim->blitGC,
9085 frame->x, frame->y, squareSize, squareSize,
9088 /* Erase bits of the previous frame */
9089 if (Intersect(&anim->prevFrame, frame, squareSize, &overlap, &pt)) {
9090 /* Where the new frame overlapped the previous,
9091 the contents in newBuf are wrong. */
9092 XCopyArea(xDisplay, anim->saveBuf, anim->newBuf, anim->blitGC,
9093 overlap.x, overlap.y,
9094 overlap.width, overlap.height,
9096 /* Repaint the areas in the old that don't overlap new */
9097 CalcUpdateRects(&anim->prevFrame, frame, squareSize, updates, &count);
9098 for (i = 0; i < count; i++)
9099 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9100 updates[i].x - anim->prevFrame.x,
9101 updates[i].y - anim->prevFrame.y,
9102 updates[i].width, updates[i].height,
9103 updates[i].x, updates[i].y);
9105 /* Easy when no overlap */
9106 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9107 0, 0, squareSize, squareSize,
9108 anim->prevFrame.x, anim->prevFrame.y);
9111 /* Save this frame for next time round */
9112 XCopyArea(xDisplay, anim->newBuf, anim->saveBuf, anim->blitGC,
9113 0, 0, squareSize, squareSize,
9115 anim->prevFrame = *frame;
9117 /* Draw piece over original screen contents, not current,
9118 and copy entire rect. Wipes out overlapping piece images. */
9119 OverlayPiece(piece, anim->pieceGC, anim->outlineGC, anim->newBuf);
9120 XCopyArea(xDisplay, anim->newBuf, xBoardWindow, anim->blitGC,
9121 0, 0, squareSize, squareSize,
9122 frame->x, frame->y);
9126 EndAnimation (anim, finish)
9130 XRectangle updates[4];
9135 /* The main code will redraw the final square, so we
9136 only need to erase the bits that don't overlap. */
9137 if (Intersect(&anim->prevFrame, finish, squareSize, &overlap, &pt)) {
9138 CalcUpdateRects(&anim->prevFrame, finish, squareSize, updates, &count);
9139 for (i = 0; i < count; i++)
9140 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9141 updates[i].x - anim->prevFrame.x,
9142 updates[i].y - anim->prevFrame.y,
9143 updates[i].width, updates[i].height,
9144 updates[i].x, updates[i].y);
9146 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9147 0, 0, squareSize, squareSize,
9148 anim->prevFrame.x, anim->prevFrame.y);
9153 FrameSequence(anim, piece, startColor, start, finish, frames, nFrames)
9155 ChessSquare piece; int startColor;
9156 XPoint * start; XPoint * finish;
9157 XPoint frames[]; int nFrames;
9161 BeginAnimation(anim, piece, startColor, start);
9162 for (n = 0; n < nFrames; n++) {
9163 AnimationFrame(anim, &(frames[n]), piece);
9164 FrameDelay(appData.animSpeed);
9166 EndAnimation(anim, finish);
9169 /* Main control logic for deciding what to animate and how */
9172 AnimateMove(board, fromX, fromY, toX, toY)
9181 XPoint start, finish, mid;
9182 XPoint frames[kFactor * 2 + 1];
9183 int nFrames, startColor, endColor;
9185 /* Are we animating? */
9186 if (!appData.animate || appData.blindfold)
9189 if (fromY < 0 || fromX < 0 || toX < 0 || toY < 0) return;
9190 piece = board[fromY][fromX];
9191 if (piece >= EmptySquare) return;
9196 hop = (piece == WhiteKnight || piece == BlackKnight);
9199 if (appData.debugMode) {
9200 fprintf(debugFP, hop ? _("AnimateMove: piece %d hops from %d,%d to %d,%d \n") :
9201 _("AnimateMove: piece %d slides from %d,%d to %d,%d \n"),
9202 piece, fromX, fromY, toX, toY); }
9204 ScreenSquare(fromX, fromY, &start, &startColor);
9205 ScreenSquare(toX, toY, &finish, &endColor);
9208 /* Knight: make diagonal movement then straight */
9209 if (abs(toY - fromY) < abs(toX - fromX)) {
9210 mid.x = start.x + (finish.x - start.x) / 2;
9214 mid.y = start.y + (finish.y - start.y) / 2;
9217 mid.x = start.x + (finish.x - start.x) / 2;
9218 mid.y = start.y + (finish.y - start.y) / 2;
9221 /* Don't use as many frames for very short moves */
9222 if (abs(toY - fromY) + abs(toX - fromX) <= 2)
9223 Tween(&start, &mid, &finish, kFactor - 1, frames, &nFrames);
9225 Tween(&start, &mid, &finish, kFactor, frames, &nFrames);
9226 FrameSequence(&game, piece, startColor, &start, &finish, frames, nFrames);
9228 /* Be sure end square is redrawn */
9229 damage[toY][toX] = True;
9233 DragPieceBegin(x, y)
9236 int boardX, boardY, color;
9239 /* Are we animating? */
9240 if (!appData.animateDragging || appData.blindfold)
9243 /* Figure out which square we start in and the
9244 mouse position relative to top left corner. */
9245 BoardSquare(x, y, &boardX, &boardY);
9246 player.startBoardX = boardX;
9247 player.startBoardY = boardY;
9248 ScreenSquare(boardX, boardY, &corner, &color);
9249 player.startSquare = corner;
9250 player.startColor = color;
9252 /* Start from exactly where the piece is. This can be confusing
9253 if you start dragging far from the center of the square; most
9254 or all of the piece can be over a different square from the one
9255 the mouse pointer is in. */
9256 player.mouseDelta.x = x - corner.x;
9257 player.mouseDelta.y = y - corner.y;
9259 /* As soon as we start dragging, the piece will jump slightly to
9260 be centered over the mouse pointer. */
9261 player.mouseDelta.x = squareSize/2;
9262 player.mouseDelta.y = squareSize/2;
9264 /* Initialise animation */
9265 player.dragPiece = PieceForSquare(boardX, boardY);
9267 if (player.dragPiece >= 0 && player.dragPiece < EmptySquare) {
9268 player.dragActive = True;
9269 BeginAnimation(&player, player.dragPiece, color, &corner);
9270 /* Mark this square as needing to be redrawn. Note that
9271 we don't remove the piece though, since logically (ie
9272 as seen by opponent) the move hasn't been made yet. */
9273 if(boardX == BOARD_RGHT+1 && PieceForSquare(boardX-1, boardY) > 1 ||
9274 boardX == BOARD_LEFT-2 && PieceForSquare(boardX+1, boardY) > 1)
9275 XCopyArea(xDisplay, xBoardWindow, player.saveBuf, player.blitGC,
9276 corner.x, corner.y, squareSize, squareSize,
9277 0, 0); // [HGM] zh: unstack in stead of grab
9278 damage[boardY][boardX] = True;
9280 player.dragActive = False;
9290 /* Are we animating? */
9291 if (!appData.animateDragging || appData.blindfold)
9295 if (! player.dragActive)
9297 /* Move piece, maintaining same relative position
9298 of mouse within square */
9299 corner.x = x - player.mouseDelta.x;
9300 corner.y = y - player.mouseDelta.y;
9301 AnimationFrame(&player, &corner, player.dragPiece);
9303 if (appData.highlightDragging) {
9305 BoardSquare(x, y, &boardX, &boardY);
9306 SetHighlights(fromX, fromY, boardX, boardY);
9315 int boardX, boardY, color;
9318 /* Are we animating? */
9319 if (!appData.animateDragging || appData.blindfold)
9323 if (! player.dragActive)
9325 /* Last frame in sequence is square piece is
9326 placed on, which may not match mouse exactly. */
9327 BoardSquare(x, y, &boardX, &boardY);
9328 ScreenSquare(boardX, boardY, &corner, &color);
9329 EndAnimation(&player, &corner);
9331 /* Be sure end square is redrawn */
9332 damage[boardY][boardX] = True;
9334 /* This prevents weird things happening with fast successive
9335 clicks which on my Sun at least can cause motion events
9336 without corresponding press/release. */
9337 player.dragActive = False;
9340 /* Handle expose event while piece being dragged */
9345 if (!player.dragActive || appData.blindfold)
9348 /* What we're doing: logically, the move hasn't been made yet,
9349 so the piece is still in it's original square. But visually
9350 it's being dragged around the board. So we erase the square
9351 that the piece is on and draw it at the last known drag point. */
9352 BlankSquare(player.startSquare.x, player.startSquare.y,
9353 player.startColor, EmptySquare, xBoardWindow);
9354 AnimationFrame(&player, &player.prevFrame, player.dragPiece);
9355 damage[player.startBoardY][player.startBoardX] = TRUE;
9359 SetProgramStats( FrontEndProgramStats * stats )
9362 // [HGM] done, but perhaps backend should call this directly?
9363 EngineOutputUpdate( stats );