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 GC lightSquareGC, darkSquareGC, jailSquareGC, lineGC, wdPieceGC, wlPieceGC,
460 bdPieceGC, blPieceGC, wbPieceGC, bwPieceGC, coordGC, highlineGC,
461 wjPieceGC, bjPieceGC, prelineGC, countGC;
462 Pixmap iconPixmap, wIconPixmap, bIconPixmap, xMarkPixmap;
463 Widget shellWidget, layoutWidget, formWidget, boardWidget, messageWidget,
464 whiteTimerWidget, blackTimerWidget, titleWidget, widgetList[16],
465 commentShell, promotionShell, whitePieceMenu, blackPieceMenu, dropMenu,
466 menuBarWidget, buttonBarWidget, editShell, errorShell, analysisShell,
467 ICSInputShell, fileNameShell, askQuestionShell;
468 XSegment gridSegments[(BOARD_SIZE + 1) * 2];
469 XSegment jailGridSegments[(BOARD_SIZE + 3) * 2];
470 Font clockFontID, coordFontID, countFontID;
471 XFontStruct *clockFontStruct, *coordFontStruct, *countFontStruct;
472 XtAppContext appContext;
474 char *oldICSInteractionTitle;
478 char installDir[] = "."; // [HGM] UCI: needed for UCI; probably needs run-time initializtion
480 Position commentX = -1, commentY = -1;
481 Dimension commentW, commentH;
483 int squareSize, smallLayout = 0, tinyLayout = 0,
484 marginW, marginH, // [HGM] for run-time resizing
485 fromX = -1, fromY = -1, toX, toY, commentUp = False, analysisUp = False,
486 ICSInputBoxUp = False, askQuestionUp = False,
487 filenameUp = False, promotionUp = False, pmFromX = -1, pmFromY = -1,
488 editUp = False, errorUp = False, errorExitStatus = -1, lineGap;
489 Pixel timerForegroundPixel, timerBackgroundPixel;
490 Pixel buttonForegroundPixel, buttonBackgroundPixel;
491 char *chessDir, *programName, *programVersion,
492 *gameCopyFilename, *gamePasteFilename;
496 Pixmap pieceBitmap[2][(int)BlackPawn];
497 Pixmap xpmPieceBitmap[4][(int)BlackPawn]; /* LL, LD, DL, DD */
498 Pixmap xpmLightSquare, xpmDarkSquare, xpmJailSquare;
499 int useImages, useImageSqs;
500 XImage *ximPieceBitmap[4][(int)BlackPawn]; /* LL, LD, DL, DD */
501 Pixmap ximMaskPm[(int)BlackPawn]; /* clipmasks, used for XIM pieces */
502 XImage *ximLightSquare, *ximDarkSquare;
505 #define pieceToSolid(piece) &pieceBitmap[SOLID][((int)(piece)) % (int)BlackPawn]
506 #define pieceToOutline(piece) &pieceBitmap[OUTLINE][((int)(piece)) % (int)BlackPawn]
508 #define White(piece) ((int)(piece) < (int)BlackPawn)
510 /* Variables for doing smooth animation. This whole thing
511 would be much easier if the board was double-buffered,
512 but that would require a fairly major rewrite. */
517 GC blitGC, pieceGC, outlineGC;
518 XPoint startSquare, prevFrame, mouseDelta;
522 int startBoardX, startBoardY;
525 /* There can be two pieces being animated at once: a player
526 can begin dragging a piece before the remote opponent has moved. */
528 static AnimState game, player;
530 /* Bitmaps for use as masks when drawing XPM pieces.
531 Need one for each black and white piece. */
532 static Pixmap xpmMask[BlackKing + 1];
534 /* This magic number is the number of intermediate frames used
535 in each half of the animation. For short moves it's reduced
536 by 1. The total number of frames will be factor * 2 + 1. */
539 SizeDefaults sizeDefaults[] = SIZE_DEFAULTS;
541 MenuItem fileMenu[] = {
542 {N_("New Game"), ResetProc},
543 {N_("New Shuffle Game ..."), ShuffleMenuProc},
544 {N_("New Variant ..."), NewVariantProc}, // [HGM] variant: not functional yet
545 {"----", NothingProc},
546 {N_("Load Game"), LoadGameProc},
547 {N_("Load Next Game"), LoadNextGameProc},
548 {N_("Load Previous Game"), LoadPrevGameProc},
549 {N_("Reload Same Game"), ReloadGameProc},
550 {N_("Save Game"), SaveGameProc},
551 {"----", NothingProc},
552 {N_("Copy Game"), CopyGameProc},
553 {N_("Paste Game"), PasteGameProc},
554 {"----", NothingProc},
555 {N_("Load Position"), LoadPositionProc},
556 {N_("Load Next Position"), LoadNextPositionProc},
557 {N_("Load Previous Position"), LoadPrevPositionProc},
558 {N_("Reload Same Position"), ReloadPositionProc},
559 {N_("Save Position"), SavePositionProc},
560 {"----", NothingProc},
561 {N_("Copy Position"), CopyPositionProc},
562 {N_("Paste Position"), PastePositionProc},
563 {"----", NothingProc},
564 {N_("Mail Move"), MailMoveProc},
565 {N_("Reload CMail Message"), ReloadCmailMsgProc},
566 {"----", NothingProc},
567 {N_("Exit"), QuitProc},
571 MenuItem modeMenu[] = {
572 {N_("Machine White"), MachineWhiteProc},
573 {N_("Machine Black"), MachineBlackProc},
574 {N_("Two Machines"), TwoMachinesProc},
575 {N_("Analysis Mode"), AnalyzeModeProc},
576 {N_("Analyze File"), AnalyzeFileProc },
577 {N_("ICS Client"), IcsClientProc},
578 {N_("Edit Game"), EditGameProc},
579 {N_("Edit Position"), EditPositionProc},
580 {N_("Training"), TrainingProc},
581 {"----", NothingProc},
582 {N_("Show Engine Output"), EngineOutputProc},
583 {N_("Show Evaluation Graph"), NothingProc}, // [HGM] evalgr: not functional yet
584 {N_("Show Game List"), ShowGameListProc},
585 {"Show Move History", HistoryShowProc}, // [HGM] hist: activate 4.2.7 code
586 {"----", NothingProc},
587 {N_("Edit Tags"), EditTagsProc},
588 {N_("Edit Comment"), EditCommentProc},
589 {N_("ICS Input Box"), IcsInputBoxProc},
590 {N_("Pause"), PauseProc},
594 MenuItem actionMenu[] = {
595 {N_("Accept"), AcceptProc},
596 {N_("Decline"), DeclineProc},
597 {N_("Rematch"), RematchProc},
598 {"----", NothingProc},
599 {N_("Call Flag"), CallFlagProc},
600 {N_("Draw"), DrawProc},
601 {N_("Adjourn"), AdjournProc},
602 {N_("Abort"), AbortProc},
603 {N_("Resign"), ResignProc},
604 {"----", NothingProc},
605 {N_("Stop Observing"), StopObservingProc},
606 {N_("Stop Examining"), StopExaminingProc},
607 {"----", NothingProc},
608 {N_("Adjudicate to White"), AdjuWhiteProc},
609 {N_("Adjudicate to Black"), AdjuBlackProc},
610 {N_("Adjudicate Draw"), AdjuDrawProc},
614 MenuItem stepMenu[] = {
615 {N_("Backward"), BackwardProc},
616 {N_("Forward"), ForwardProc},
617 {N_("Back to Start"), ToStartProc},
618 {N_("Forward to End"), ToEndProc},
619 {N_("Revert"), RevertProc},
620 {N_("Truncate Game"), TruncateGameProc},
621 {"----", NothingProc},
622 {N_("Move Now"), MoveNowProc},
623 {N_("Retract Move"), RetractMoveProc},
627 MenuItem optionsMenu[] = {
628 {N_("Flip View"), FlipViewProc},
629 {"----", NothingProc},
630 {N_("Adjudications ..."), EngineMenuProc},
631 {N_("General Settings ..."), UciMenuProc},
632 {N_("Engine #1 Settings ..."), FirstSettingsProc},
633 {N_("Engine #2 Settings ..."), SecondSettingsProc},
634 {N_("Time Control ..."), TimeControlProc},
635 {"----", NothingProc},
636 {N_("Always Queen"), AlwaysQueenProc},
637 {N_("Animate Dragging"), AnimateDraggingProc},
638 {N_("Animate Moving"), AnimateMovingProc},
639 {N_("Auto Comment"), AutocommProc},
640 {N_("Auto Flag"), AutoflagProc},
641 {N_("Auto Flip View"), AutoflipProc},
642 {N_("Auto Observe"), AutobsProc},
643 {N_("Auto Raise Board"), AutoraiseProc},
644 {N_("Auto Save"), AutosaveProc},
645 {N_("Blindfold"), BlindfoldProc},
646 {N_("Flash Moves"), FlashMovesProc},
647 {N_("Get Move List"), GetMoveListProc},
649 {N_("Highlight Dragging"), HighlightDraggingProc},
651 {N_("Highlight Last Move"), HighlightLastMoveProc},
652 {N_("Move Sound"), MoveSoundProc},
653 {N_("ICS Alarm"), IcsAlarmProc},
654 {N_("Old Save Style"), OldSaveStyleProc},
655 {N_("Periodic Updates"), PeriodicUpdatesProc},
656 {N_("Ponder Next Move"), PonderNextMoveProc},
657 {N_("Popup Exit Message"), PopupExitMessageProc},
658 {N_("Popup Move Errors"), PopupMoveErrorsProc},
659 {N_("Premove"), PremoveProc},
660 {N_("Quiet Play"), QuietPlayProc},
661 {N_("Show Coords"), ShowCoordsProc},
662 {N_("Hide Thinking"), HideThinkingProc},
663 {N_("Test Legality"), TestLegalityProc},
667 MenuItem helpMenu[] = {
668 {N_("Info XBoard"), InfoProc},
669 {N_("Man XBoard"), ManProc},
670 {"----", NothingProc},
671 {N_("Hint"), HintProc},
672 {N_("Book"), BookProc},
673 {"----", NothingProc},
674 {N_("About XBoard"), AboutProc},
679 {N_("File"), fileMenu},
680 {N_("Mode"), modeMenu},
681 {N_("Action"), actionMenu},
682 {N_("Step"), stepMenu},
683 {N_("Options"), optionsMenu},
684 {N_("Help"), helpMenu},
688 #define PAUSE_BUTTON N_("P")
689 MenuItem buttonBar[] = {
692 {PAUSE_BUTTON, PauseProc},
698 #define PIECE_MENU_SIZE 11
699 String pieceMenuStrings[2][PIECE_MENU_SIZE] = {
700 { N_("White"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
701 N_("Queen"), N_("King"), "----", N_("Empty square"), N_("Clear board") },
702 { N_("Black"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
703 N_("Queen"), N_("King"), "----", N_("Empty square"), N_("Clear board") },
705 /* must be in same order as PieceMenuStrings! */
706 ChessSquare pieceMenuTranslation[2][PIECE_MENU_SIZE] = {
707 { WhitePlay, (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
708 WhiteRook, WhiteQueen, WhiteKing,
709 (ChessSquare) 0, EmptySquare, ClearBoard },
710 { BlackPlay, (ChessSquare) 0, BlackPawn, BlackKnight, BlackBishop,
711 BlackRook, BlackQueen, BlackKing,
712 (ChessSquare) 0, EmptySquare, ClearBoard },
715 #define DROP_MENU_SIZE 6
716 String dropMenuStrings[DROP_MENU_SIZE] = {
717 "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"), N_("Queen")
719 /* must be in same order as PieceMenuStrings! */
720 ChessSquare dropMenuTranslation[DROP_MENU_SIZE] = {
721 (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
722 WhiteRook, WhiteQueen
730 DropMenuEnables dmEnables[] = {
748 { XtNborderWidth, 0 },
749 { XtNdefaultDistance, 0 },
753 { XtNborderWidth, 0 },
754 { XtNresizable, (XtArgVal) True },
758 { XtNborderWidth, 0 },
764 { XtNjustify, (XtArgVal) XtJustifyRight },
765 { XtNlabel, (XtArgVal) "..." },
766 { XtNresizable, (XtArgVal) True },
767 { XtNresize, (XtArgVal) False }
770 Arg messageArgs[] = {
771 { XtNjustify, (XtArgVal) XtJustifyLeft },
772 { XtNlabel, (XtArgVal) "..." },
773 { XtNresizable, (XtArgVal) True },
774 { XtNresize, (XtArgVal) False }
778 { XtNborderWidth, 0 },
779 { XtNjustify, (XtArgVal) XtJustifyLeft }
782 XtResource clientResources[] = {
783 { "whitePieceColor", "whitePieceColor", XtRString, sizeof(String),
784 XtOffset(AppDataPtr, whitePieceColor), XtRString,
786 { "blackPieceColor", "blackPieceColor", XtRString, sizeof(String),
787 XtOffset(AppDataPtr, blackPieceColor), XtRString,
789 { "lightSquareColor", "lightSquareColor", XtRString,
790 sizeof(String), XtOffset(AppDataPtr, lightSquareColor),
791 XtRString, LIGHT_SQUARE_COLOR },
792 { "darkSquareColor", "darkSquareColor", XtRString, sizeof(String),
793 XtOffset(AppDataPtr, darkSquareColor), XtRString,
795 { "highlightSquareColor", "highlightSquareColor", XtRString,
796 sizeof(String), XtOffset(AppDataPtr, highlightSquareColor),
797 XtRString, HIGHLIGHT_SQUARE_COLOR },
798 { "premoveHighlightColor", "premoveHighlightColor", XtRString,
799 sizeof(String), XtOffset(AppDataPtr, premoveHighlightColor),
800 XtRString, PREMOVE_HIGHLIGHT_COLOR },
801 { "movesPerSession", "movesPerSession", XtRInt, sizeof(int),
802 XtOffset(AppDataPtr, movesPerSession), XtRImmediate,
803 (XtPointer) MOVES_PER_SESSION },
804 { "timeIncrement", "timeIncrement", XtRInt, sizeof(int),
805 XtOffset(AppDataPtr, timeIncrement), XtRImmediate,
806 (XtPointer) TIME_INCREMENT },
807 { "initString", "initString", XtRString, sizeof(String),
808 XtOffset(AppDataPtr, initString), XtRString, INIT_STRING },
809 { "secondInitString", "secondInitString", XtRString, sizeof(String),
810 XtOffset(AppDataPtr, secondInitString), XtRString, INIT_STRING },
811 { "firstComputerString", "firstComputerString", XtRString,
812 sizeof(String), XtOffset(AppDataPtr, firstComputerString), XtRString,
814 { "secondComputerString", "secondComputerString", XtRString,
815 sizeof(String), XtOffset(AppDataPtr, secondComputerString), XtRString,
817 { "firstChessProgram", "firstChessProgram", XtRString,
818 sizeof(String), XtOffset(AppDataPtr, firstChessProgram),
819 XtRString, FIRST_CHESS_PROGRAM },
820 { "secondChessProgram", "secondChessProgram", XtRString,
821 sizeof(String), XtOffset(AppDataPtr, secondChessProgram),
822 XtRString, SECOND_CHESS_PROGRAM },
823 { "firstPlaysBlack", "firstPlaysBlack", XtRBoolean,
824 sizeof(Boolean), XtOffset(AppDataPtr, firstPlaysBlack),
825 XtRImmediate, (XtPointer) False },
826 { "noChessProgram", "noChessProgram", XtRBoolean,
827 sizeof(Boolean), XtOffset(AppDataPtr, noChessProgram),
828 XtRImmediate, (XtPointer) False },
829 { "firstHost", "firstHost", XtRString, sizeof(String),
830 XtOffset(AppDataPtr, firstHost), XtRString, FIRST_HOST },
831 { "secondHost", "secondHost", XtRString, sizeof(String),
832 XtOffset(AppDataPtr, secondHost), XtRString, SECOND_HOST },
833 { "firstDirectory", "firstDirectory", XtRString, sizeof(String),
834 XtOffset(AppDataPtr, firstDirectory), XtRString, "." },
835 { "secondDirectory", "secondDirectory", XtRString, sizeof(String),
836 XtOffset(AppDataPtr, secondDirectory), XtRString, "." },
837 { "bitmapDirectory", "bitmapDirectory", XtRString,
838 sizeof(String), XtOffset(AppDataPtr, bitmapDirectory),
840 { "remoteShell", "remoteShell", XtRString, sizeof(String),
841 XtOffset(AppDataPtr, remoteShell), XtRString, REMOTE_SHELL },
842 { "remoteUser", "remoteUser", XtRString, sizeof(String),
843 XtOffset(AppDataPtr, remoteUser), XtRString, "" },
844 { "timeDelay", "timeDelay", XtRFloat, sizeof(float),
845 XtOffset(AppDataPtr, timeDelay), XtRString,
846 (XtPointer) TIME_DELAY_QUOTE },
847 { "timeControl", "timeControl", XtRString, sizeof(String),
848 XtOffset(AppDataPtr, timeControl), XtRString,
849 (XtPointer) TIME_CONTROL },
850 { "internetChessServerMode", "internetChessServerMode",
851 XtRBoolean, sizeof(Boolean),
852 XtOffset(AppDataPtr, icsActive), XtRImmediate,
854 { "internetChessServerHost", "internetChessServerHost",
855 XtRString, sizeof(String),
856 XtOffset(AppDataPtr, icsHost),
857 XtRString, (XtPointer) ICS_HOST },
858 { "internetChessServerPort", "internetChessServerPort",
859 XtRString, sizeof(String),
860 XtOffset(AppDataPtr, icsPort), XtRString,
861 (XtPointer) ICS_PORT },
862 { "internetChessServerCommPort", "internetChessServerCommPort",
863 XtRString, sizeof(String),
864 XtOffset(AppDataPtr, icsCommPort), XtRString,
866 { "internetChessServerLogonScript", "internetChessServerLogonScript",
867 XtRString, sizeof(String),
868 XtOffset(AppDataPtr, icsLogon), XtRString,
870 { "internetChessServerHelper", "internetChessServerHelper",
871 XtRString, sizeof(String),
872 XtOffset(AppDataPtr, icsHelper), XtRString, "" },
873 { "internetChessServerInputBox", "internetChessServerInputBox",
874 XtRBoolean, sizeof(Boolean),
875 XtOffset(AppDataPtr, icsInputBox), XtRImmediate,
877 { "icsAlarm", "icsAlarm",
878 XtRBoolean, sizeof(Boolean),
879 XtOffset(AppDataPtr, icsAlarm), XtRImmediate,
881 { "icsAlarmTime", "icsAlarmTime",
883 XtOffset(AppDataPtr, icsAlarmTime), XtRImmediate,
885 { "useTelnet", "useTelnet", XtRBoolean, sizeof(Boolean),
886 XtOffset(AppDataPtr, useTelnet), XtRImmediate,
888 { "telnetProgram", "telnetProgram", XtRString, sizeof(String),
889 XtOffset(AppDataPtr, telnetProgram), XtRString, TELNET_PROGRAM },
890 { "gateway", "gateway", XtRString, sizeof(String),
891 XtOffset(AppDataPtr, gateway), XtRString, "" },
892 { "loadGameFile", "loadGameFile", XtRString, sizeof(String),
893 XtOffset(AppDataPtr, loadGameFile), XtRString, "" },
894 { "loadGameIndex", "loadGameIndex",
896 XtOffset(AppDataPtr, loadGameIndex), XtRImmediate,
898 { "saveGameFile", "saveGameFile", XtRString, sizeof(String),
899 XtOffset(AppDataPtr, saveGameFile), XtRString, "" },
900 { "autoRaiseBoard", "autoRaiseBoard", XtRBoolean,
901 sizeof(Boolean), XtOffset(AppDataPtr, autoRaiseBoard),
902 XtRImmediate, (XtPointer) True },
903 { "autoSaveGames", "autoSaveGames", XtRBoolean,
904 sizeof(Boolean), XtOffset(AppDataPtr, autoSaveGames),
905 XtRImmediate, (XtPointer) False },
906 { "blindfold", "blindfold", XtRBoolean,
907 sizeof(Boolean), XtOffset(AppDataPtr, blindfold),
908 XtRImmediate, (XtPointer) False },
909 { "loadPositionFile", "loadPositionFile", XtRString,
910 sizeof(String), XtOffset(AppDataPtr, loadPositionFile),
912 { "loadPositionIndex", "loadPositionIndex",
914 XtOffset(AppDataPtr, loadPositionIndex), XtRImmediate,
916 { "savePositionFile", "savePositionFile", XtRString,
917 sizeof(String), XtOffset(AppDataPtr, savePositionFile),
919 { "matchMode", "matchMode", XtRBoolean, sizeof(Boolean),
920 XtOffset(AppDataPtr, matchMode), XtRImmediate, (XtPointer) False },
921 { "matchGames", "matchGames", XtRInt, sizeof(int),
922 XtOffset(AppDataPtr, matchGames), XtRImmediate,
924 { "monoMode", "monoMode", XtRBoolean, sizeof(Boolean),
925 XtOffset(AppDataPtr, monoMode), XtRImmediate,
927 { "debugMode", "debugMode", XtRBoolean, sizeof(Boolean),
928 XtOffset(AppDataPtr, debugMode), XtRImmediate,
930 { "clockMode", "clockMode", XtRBoolean, sizeof(Boolean),
931 XtOffset(AppDataPtr, clockMode), XtRImmediate,
933 { "boardSize", "boardSize", XtRString, sizeof(String),
934 XtOffset(AppDataPtr, boardSize), XtRString, "" },
935 { "searchTime", "searchTime", XtRString, sizeof(String),
936 XtOffset(AppDataPtr, searchTime), XtRString,
938 { "searchDepth", "searchDepth", XtRInt, sizeof(int),
939 XtOffset(AppDataPtr, searchDepth), XtRImmediate,
941 { "showCoords", "showCoords", XtRBoolean, sizeof(Boolean),
942 XtOffset(AppDataPtr, showCoords), XtRImmediate,
944 { "showJail", "showJail", XtRInt, sizeof(int),
945 XtOffset(AppDataPtr, showJail), XtRImmediate,
947 { "showThinking", "showThinking", XtRBoolean, sizeof(Boolean),
948 XtOffset(AppDataPtr, showThinking), XtRImmediate,
950 { "ponderNextMove", "ponderNextMove", XtRBoolean, sizeof(Boolean),
951 XtOffset(AppDataPtr, ponderNextMove), XtRImmediate,
953 { "periodicUpdates", "periodicUpdates", XtRBoolean, sizeof(Boolean),
954 XtOffset(AppDataPtr, periodicUpdates), XtRImmediate,
956 { "clockFont", "clockFont", XtRString, sizeof(String),
957 XtOffset(AppDataPtr, clockFont), XtRString, CLOCK_FONT },
958 { "coordFont", "coordFont", XtRString, sizeof(String),
959 XtOffset(AppDataPtr, coordFont), XtRString, COORD_FONT },
960 { "font", "font", XtRString, sizeof(String),
961 XtOffset(AppDataPtr, font), XtRString, DEFAULT_FONT },
962 { "ringBellAfterMoves", "ringBellAfterMoves",
963 XtRBoolean, sizeof(Boolean),
964 XtOffset(AppDataPtr, ringBellAfterMoves),
965 XtRImmediate, (XtPointer) False },
966 { "autoCallFlag", "autoCallFlag", XtRBoolean,
967 sizeof(Boolean), XtOffset(AppDataPtr, autoCallFlag),
968 XtRImmediate, (XtPointer) False },
969 { "autoFlipView", "autoFlipView", XtRBoolean,
970 sizeof(Boolean), XtOffset(AppDataPtr, autoFlipView),
971 XtRImmediate, (XtPointer) True },
972 { "autoObserve", "autoObserve", XtRBoolean,
973 sizeof(Boolean), XtOffset(AppDataPtr, autoObserve),
974 XtRImmediate, (XtPointer) False },
975 { "autoComment", "autoComment", XtRBoolean,
976 sizeof(Boolean), XtOffset(AppDataPtr, autoComment),
977 XtRImmediate, (XtPointer) False },
978 { "getMoveList", "getMoveList", XtRBoolean,
979 sizeof(Boolean), XtOffset(AppDataPtr, getMoveList),
980 XtRImmediate, (XtPointer) True },
982 { "highlightDragging", "highlightDragging", XtRBoolean,
983 sizeof(Boolean), XtOffset(AppDataPtr, highlightDragging),
984 XtRImmediate, (XtPointer) False },
986 { "highlightLastMove", "highlightLastMove", XtRBoolean,
987 sizeof(Boolean), XtOffset(AppDataPtr, highlightLastMove),
988 XtRImmediate, (XtPointer) False },
989 { "premove", "premove", XtRBoolean,
990 sizeof(Boolean), XtOffset(AppDataPtr, premove),
991 XtRImmediate, (XtPointer) True },
992 { "testLegality", "testLegality", XtRBoolean,
993 sizeof(Boolean), XtOffset(AppDataPtr, testLegality),
994 XtRImmediate, (XtPointer) True },
995 { "flipView", "flipView", XtRBoolean,
996 sizeof(Boolean), XtOffset(AppDataPtr, flipView),
997 XtRImmediate, (XtPointer) False },
998 { "cmail", "cmailGameName", XtRString, sizeof(String),
999 XtOffset(AppDataPtr, cmailGameName), XtRString, "" },
1000 { "alwaysPromoteToQueen", "alwaysPromoteToQueen", XtRBoolean,
1001 sizeof(Boolean), XtOffset(AppDataPtr, alwaysPromoteToQueen),
1002 XtRImmediate, (XtPointer) False },
1003 { "oldSaveStyle", "oldSaveStyle", XtRBoolean,
1004 sizeof(Boolean), XtOffset(AppDataPtr, oldSaveStyle),
1005 XtRImmediate, (XtPointer) False },
1006 { "quietPlay", "quietPlay", XtRBoolean,
1007 sizeof(Boolean), XtOffset(AppDataPtr, quietPlay),
1008 XtRImmediate, (XtPointer) False },
1009 { "titleInWindow", "titleInWindow", XtRBoolean,
1010 sizeof(Boolean), XtOffset(AppDataPtr, titleInWindow),
1011 XtRImmediate, (XtPointer) False },
1012 { "localLineEditing", "localLineEditing", XtRBoolean,
1013 sizeof(Boolean), XtOffset(AppDataPtr, localLineEditing),
1014 XtRImmediate, (XtPointer) True }, /* not implemented, must be True */
1016 { "zippyTalk", "zippyTalk", XtRBoolean,
1017 sizeof(Boolean), XtOffset(AppDataPtr, zippyTalk),
1018 XtRImmediate, (XtPointer) ZIPPY_TALK },
1019 { "zippyPlay", "zippyPlay", XtRBoolean,
1020 sizeof(Boolean), XtOffset(AppDataPtr, zippyPlay),
1021 XtRImmediate, (XtPointer) ZIPPY_PLAY },
1022 { "zippyLines", "zippyLines", XtRString, sizeof(String),
1023 XtOffset(AppDataPtr, zippyLines), XtRString, ZIPPY_LINES },
1024 { "zippyPinhead", "zippyPinhead", XtRString, sizeof(String),
1025 XtOffset(AppDataPtr, zippyPinhead), XtRString, ZIPPY_PINHEAD },
1026 { "zippyPassword", "zippyPassword", XtRString, sizeof(String),
1027 XtOffset(AppDataPtr, zippyPassword), XtRString, ZIPPY_PASSWORD },
1028 { "zippyPassword2", "zippyPassword2", XtRString, sizeof(String),
1029 XtOffset(AppDataPtr, zippyPassword2), XtRString, ZIPPY_PASSWORD2 },
1030 { "zippyWrongPassword", "zippyWrongPassword", XtRString, sizeof(String),
1031 XtOffset(AppDataPtr, zippyWrongPassword), XtRString,
1032 ZIPPY_WRONG_PASSWORD },
1033 { "zippyAcceptOnly", "zippyAcceptOnly", XtRString, sizeof(String),
1034 XtOffset(AppDataPtr, zippyAcceptOnly), XtRString, ZIPPY_ACCEPT_ONLY },
1035 { "zippyUseI", "zippyUseI", XtRBoolean,
1036 sizeof(Boolean), XtOffset(AppDataPtr, zippyUseI),
1037 XtRImmediate, (XtPointer) ZIPPY_USE_I },
1038 { "zippyBughouse", "zippyBughouse", XtRInt,
1039 sizeof(int), XtOffset(AppDataPtr, zippyBughouse),
1040 XtRImmediate, (XtPointer) ZIPPY_BUGHOUSE },
1041 { "zippyNoplayCrafty", "zippyNoplayCrafty", XtRBoolean,
1042 sizeof(Boolean), XtOffset(AppDataPtr, zippyNoplayCrafty),
1043 XtRImmediate, (XtPointer) ZIPPY_NOPLAY_CRAFTY },
1044 { "zippyGameEnd", "zippyGameEnd", XtRString, sizeof(String),
1045 XtOffset(AppDataPtr, zippyGameEnd), XtRString, ZIPPY_GAME_END },
1046 { "zippyGameStart", "zippyGameStart", XtRString, sizeof(String),
1047 XtOffset(AppDataPtr, zippyGameStart), XtRString, ZIPPY_GAME_START },
1048 { "zippyAdjourn", "zippyAdjourn", XtRBoolean,
1049 sizeof(Boolean), XtOffset(AppDataPtr, zippyAdjourn),
1050 XtRImmediate, (XtPointer) ZIPPY_ADJOURN },
1051 { "zippyAbort", "zippyAbort", XtRBoolean,
1052 sizeof(Boolean), XtOffset(AppDataPtr, zippyAbort),
1053 XtRImmediate, (XtPointer) ZIPPY_ABORT },
1054 { "zippyVariants", "zippyVariants", XtRString, sizeof(String),
1055 XtOffset(AppDataPtr, zippyVariants), XtRString, ZIPPY_VARIANTS },
1056 { "zippyMaxGames", "zippyMaxGames", XtRInt, sizeof(int),
1057 XtOffset(AppDataPtr, zippyMaxGames), XtRImmediate,
1058 (XtPointer) ZIPPY_MAX_GAMES },
1059 { "zippyReplayTimeout", "zippyReplayTimeout", XtRInt, sizeof(int),
1060 XtOffset(AppDataPtr, zippyReplayTimeout), XtRImmediate,
1061 (XtPointer) ZIPPY_REPLAY_TIMEOUT },
1062 { "zippyShortGame", "zippyShortGame", XtRInt, sizeof(int),
1063 XtOffset(AppDataPtr, zippyShortGame), XtRImmediate,
1066 { "flashCount", "flashCount", XtRInt, sizeof(int),
1067 XtOffset(AppDataPtr, flashCount), XtRImmediate,
1068 (XtPointer) FLASH_COUNT },
1069 { "flashRate", "flashRate", XtRInt, sizeof(int),
1070 XtOffset(AppDataPtr, flashRate), XtRImmediate,
1071 (XtPointer) FLASH_RATE },
1072 { "pixmapDirectory", "pixmapDirectory", XtRString,
1073 sizeof(String), XtOffset(AppDataPtr, pixmapDirectory),
1075 { "msLoginDelay", "msLoginDelay", XtRInt, sizeof(int),
1076 XtOffset(AppDataPtr, msLoginDelay), XtRImmediate,
1077 (XtPointer) MS_LOGIN_DELAY },
1078 { "colorizeMessages", "colorizeMessages", XtRBoolean,
1079 sizeof(Boolean), XtOffset(AppDataPtr, colorize),
1080 XtRImmediate, (XtPointer) False },
1081 { "colorShout", "colorShout", XtRString,
1082 sizeof(String), XtOffset(AppDataPtr, colorShout),
1083 XtRString, COLOR_SHOUT },
1084 { "colorSShout", "colorSShout", XtRString,
1085 sizeof(String), XtOffset(AppDataPtr, colorSShout),
1086 XtRString, COLOR_SSHOUT },
1087 { "colorChannel1", "colorChannel1", XtRString,
1088 sizeof(String), XtOffset(AppDataPtr, colorChannel1),
1089 XtRString, COLOR_CHANNEL1 },
1090 { "colorChannel", "colorChannel", XtRString,
1091 sizeof(String), XtOffset(AppDataPtr, colorChannel),
1092 XtRString, COLOR_CHANNEL },
1093 { "colorKibitz", "colorKibitz", XtRString,
1094 sizeof(String), XtOffset(AppDataPtr, colorKibitz),
1095 XtRString, COLOR_KIBITZ },
1096 { "colorTell", "colorTell", XtRString,
1097 sizeof(String), XtOffset(AppDataPtr, colorTell),
1098 XtRString, COLOR_TELL },
1099 { "colorChallenge", "colorChallenge", XtRString,
1100 sizeof(String), XtOffset(AppDataPtr, colorChallenge),
1101 XtRString, COLOR_CHALLENGE },
1102 { "colorRequest", "colorRequest", XtRString,
1103 sizeof(String), XtOffset(AppDataPtr, colorRequest),
1104 XtRString, COLOR_REQUEST },
1105 { "colorSeek", "colorSeek", XtRString,
1106 sizeof(String), XtOffset(AppDataPtr, colorSeek),
1107 XtRString, COLOR_SEEK },
1108 { "colorNormal", "colorNormal", XtRString,
1109 sizeof(String), XtOffset(AppDataPtr, colorNormal),
1110 XtRString, COLOR_NORMAL },
1111 { "soundProgram", "soundProgram", XtRString,
1112 sizeof(String), XtOffset(AppDataPtr, soundProgram),
1113 XtRString, "play" },
1114 { "soundShout", "soundShout", XtRString,
1115 sizeof(String), XtOffset(AppDataPtr, soundShout),
1117 { "soundSShout", "soundSShout", XtRString,
1118 sizeof(String), XtOffset(AppDataPtr, soundSShout),
1120 { "soundChannel1", "soundChannel1", XtRString,
1121 sizeof(String), XtOffset(AppDataPtr, soundChannel1),
1123 { "soundChannel", "soundChannel", XtRString,
1124 sizeof(String), XtOffset(AppDataPtr, soundChannel),
1126 { "soundKibitz", "soundKibitz", XtRString,
1127 sizeof(String), XtOffset(AppDataPtr, soundKibitz),
1129 { "soundTell", "soundTell", XtRString,
1130 sizeof(String), XtOffset(AppDataPtr, soundTell),
1132 { "soundChallenge", "soundChallenge", XtRString,
1133 sizeof(String), XtOffset(AppDataPtr, soundChallenge),
1135 { "soundRequest", "soundRequest", XtRString,
1136 sizeof(String), XtOffset(AppDataPtr, soundRequest),
1138 { "soundSeek", "soundSeek", XtRString,
1139 sizeof(String), XtOffset(AppDataPtr, soundSeek),
1141 { "soundMove", "soundMove", XtRString,
1142 sizeof(String), XtOffset(AppDataPtr, soundMove),
1144 { "soundIcsWin", "soundIcsWin", XtRString,
1145 sizeof(String), XtOffset(AppDataPtr, soundIcsWin),
1147 { "soundIcsLoss", "soundIcsLoss", XtRString,
1148 sizeof(String), XtOffset(AppDataPtr, soundIcsLoss),
1150 { "soundIcsDraw", "soundIcsDraw", XtRString,
1151 sizeof(String), XtOffset(AppDataPtr, soundIcsDraw),
1153 { "soundIcsUnfinished", "soundIcsUnfinished", XtRString,
1154 sizeof(String), XtOffset(AppDataPtr, soundIcsUnfinished),
1156 { "soundIcsAlarm", "soundIcsAlarm", XtRString,
1157 sizeof(String), XtOffset(AppDataPtr, soundIcsAlarm),
1159 { "reuseFirst", "reuseFirst", XtRBoolean,
1160 sizeof(Boolean), XtOffset(AppDataPtr, reuseFirst),
1161 XtRImmediate, (XtPointer) True },
1162 { "reuseSecond", "reuseSecond", XtRBoolean,
1163 sizeof(Boolean), XtOffset(AppDataPtr, reuseSecond),
1164 XtRImmediate, (XtPointer) True },
1165 { "animateDragging", "animateDragging", XtRBoolean,
1166 sizeof(Boolean), XtOffset(AppDataPtr, animateDragging),
1167 XtRImmediate, (XtPointer) True },
1168 { "animateMoving", "animateMoving", XtRBoolean,
1169 sizeof(Boolean), XtOffset(AppDataPtr, animate),
1170 XtRImmediate, (XtPointer) True },
1171 { "animateSpeed", "animateSpeed", XtRInt,
1172 sizeof(int), XtOffset(AppDataPtr, animSpeed),
1173 XtRImmediate, (XtPointer)10 },
1174 { "popupExitMessage", "popupExitMessage", XtRBoolean,
1175 sizeof(Boolean), XtOffset(AppDataPtr, popupExitMessage),
1176 XtRImmediate, (XtPointer) True },
1177 { "popupMoveErrors", "popupMoveErrors", XtRBoolean,
1178 sizeof(Boolean), XtOffset(AppDataPtr, popupMoveErrors),
1179 XtRImmediate, (XtPointer) False },
1180 { "fontSizeTolerance", "fontSizeTolerance", XtRInt,
1181 sizeof(int), XtOffset(AppDataPtr, fontSizeTolerance),
1182 XtRImmediate, (XtPointer)4 },
1183 { "initialMode", "initialMode", XtRString,
1184 sizeof(String), XtOffset(AppDataPtr, initialMode),
1185 XtRImmediate, (XtPointer) "" },
1186 { "variant", "variant", XtRString,
1187 sizeof(String), XtOffset(AppDataPtr, variant),
1188 XtRImmediate, (XtPointer) "normal" },
1189 { "firstProtocolVersion", "firstProtocolVersion", XtRInt,
1190 sizeof(int), XtOffset(AppDataPtr, firstProtocolVersion),
1191 XtRImmediate, (XtPointer)PROTOVER },
1192 { "secondProtocolVersion", "secondProtocolVersion", XtRInt,
1193 sizeof(int), XtOffset(AppDataPtr, secondProtocolVersion),
1194 XtRImmediate, (XtPointer)PROTOVER },
1195 { "showButtonBar", "showButtonBar", XtRBoolean,
1196 sizeof(Boolean), XtOffset(AppDataPtr, showButtonBar),
1197 XtRImmediate, (XtPointer) True },
1198 {"icsEngineAnalyze", "icsEngineAnalyze", XtRBoolean, /* [DM] icsEngineAnalyze */
1199 sizeof(Boolean), XtOffset(AppDataPtr, icsEngineAnalyze),
1200 XtRImmediate, (XtPointer) False },
1201 { "firstScoreAbs", "firstScoreAbs", XtRBoolean,
1202 sizeof(Boolean), XtOffset(AppDataPtr, firstScoreIsAbsolute),
1203 XtRImmediate, (XtPointer) False },
1204 { "secondScoreAbs", "secondScoreAbs", XtRBoolean,
1205 sizeof(Boolean), XtOffset(AppDataPtr, secondScoreIsAbsolute),
1206 XtRImmediate, (XtPointer) False },
1207 { "pgnExtendedInfo", "pgnExtendedInfo", XtRBoolean,
1208 sizeof(Boolean), XtOffset(AppDataPtr, saveExtendedInfoInPGN),
1209 XtRImmediate, (XtPointer) False },
1210 { "hideThinkingFromHuman", "hideThinkingFromHuman", XtRBoolean,
1211 sizeof(Boolean), XtOffset(AppDataPtr, hideThinkingFromHuman),
1212 XtRImmediate, (XtPointer) True },
1213 { "adjudicateLossThreshold", "adjudicateLossThreshold", XtRInt,
1214 sizeof(int), XtOffset(AppDataPtr, adjudicateLossThreshold),
1215 XtRImmediate, (XtPointer) 0},
1216 { "pgnEventHeader", "pgnEventHeader", XtRString,
1217 sizeof(String), XtOffset(AppDataPtr, pgnEventHeader),
1218 XtRImmediate, (XtPointer) "Computer Chess Game" },
1219 { "defaultFrcPosition", "defaultFrcPositon", XtRInt,
1220 sizeof(int), XtOffset(AppDataPtr, defaultFrcPosition),
1221 XtRImmediate, (XtPointer) -1},
1222 { "gameListTags", "gameListTags", XtRString,
1223 sizeof(String), XtOffset(AppDataPtr, gameListTags),
1224 XtRImmediate, (XtPointer) GLT_DEFAULT_TAGS },
1226 // [HGM] 4.3.xx options
1227 { "boardWidth", "boardWidth", XtRInt,
1228 sizeof(int), XtOffset(AppDataPtr, NrFiles),
1229 XtRImmediate, (XtPointer) -1},
1230 { "boardHeight", "boardHeight", XtRInt,
1231 sizeof(int), XtOffset(AppDataPtr, NrRanks),
1232 XtRImmediate, (XtPointer) -1},
1233 { "matchPause", "matchPause", XtRInt,
1234 sizeof(int), XtOffset(AppDataPtr, matchPause),
1235 XtRImmediate, (XtPointer) 10000},
1236 { "holdingsSize", "holdingsSize", XtRInt,
1237 sizeof(int), XtOffset(AppDataPtr, holdingsSize),
1238 XtRImmediate, (XtPointer) -1},
1239 { "flipBlack", "flipBlack", XtRBoolean,
1240 sizeof(Boolean), XtOffset(AppDataPtr, upsideDown),
1241 XtRImmediate, (XtPointer) False},
1242 { "allWhite", "allWhite", XtRBoolean,
1243 sizeof(Boolean), XtOffset(AppDataPtr, allWhite),
1244 XtRImmediate, (XtPointer) False},
1245 { "pieceToCharTable", "pieceToCharTable", XtRString,
1246 sizeof(String), XtOffset(AppDataPtr, pieceToCharTable),
1247 XtRImmediate, (XtPointer) 0},
1248 { "alphaRank", "alphaRank", XtRBoolean,
1249 sizeof(Boolean), XtOffset(AppDataPtr, alphaRank),
1250 XtRImmediate, (XtPointer) False},
1251 { "testClaims", "testClaims", XtRBoolean,
1252 sizeof(Boolean), XtOffset(AppDataPtr, testClaims),
1253 XtRImmediate, (XtPointer) True},
1254 { "checkMates", "checkMates", XtRBoolean,
1255 sizeof(Boolean), XtOffset(AppDataPtr, checkMates),
1256 XtRImmediate, (XtPointer) True},
1257 { "materialDraws", "materialDraws", XtRBoolean,
1258 sizeof(Boolean), XtOffset(AppDataPtr, materialDraws),
1259 XtRImmediate, (XtPointer) True},
1260 { "trivialDraws", "trivialDraws", XtRBoolean,
1261 sizeof(Boolean), XtOffset(AppDataPtr, trivialDraws),
1262 XtRImmediate, (XtPointer) False},
1263 { "ruleMoves", "ruleMoves", XtRInt,
1264 sizeof(int), XtOffset(AppDataPtr, ruleMoves),
1265 XtRImmediate, (XtPointer) 51},
1266 { "repeatsToDraw", "repeatsToDraw", XtRInt,
1267 sizeof(int), XtOffset(AppDataPtr, drawRepeats),
1268 XtRImmediate, (XtPointer) 6},
1269 { "engineDebugOutput", "engineDebugOutput", XtRInt,
1270 sizeof(int), XtOffset(AppDataPtr, engineComments),
1271 XtRImmediate, (XtPointer) 1},
1272 { "userName", "userName", XtRString,
1273 sizeof(int), XtOffset(AppDataPtr, userName),
1274 XtRImmediate, (XtPointer) 0},
1275 { "autoKibitz", "autoKibitz", XtRBoolean,
1276 sizeof(Boolean), XtOffset(AppDataPtr, autoKibitz),
1277 XtRImmediate, (XtPointer) False},
1278 { "firstTimeOdds", "firstTimeOdds", XtRInt,
1279 sizeof(int), XtOffset(AppDataPtr, firstTimeOdds),
1280 XtRImmediate, (XtPointer) 1},
1281 { "secondTimeOdds", "secondTimeOdds", XtRInt,
1282 sizeof(int), XtOffset(AppDataPtr, secondTimeOdds),
1283 XtRImmediate, (XtPointer) 1},
1284 { "timeOddsMode", "timeOddsMode", XtRInt,
1285 sizeof(int), XtOffset(AppDataPtr, timeOddsMode),
1286 XtRImmediate, (XtPointer) 0},
1287 { "firstAccumulateTC", "firstAccumulateTC", XtRInt,
1288 sizeof(int), XtOffset(AppDataPtr, firstAccumulateTC),
1289 XtRImmediate, (XtPointer) 1},
1290 { "secondAccumulateTC", "secondAccumulateTC", XtRInt,
1291 sizeof(int), XtOffset(AppDataPtr, secondAccumulateTC),
1292 XtRImmediate, (XtPointer) 1},
1293 { "firstNPS", "firstNPS", XtRInt,
1294 sizeof(int), XtOffset(AppDataPtr, firstNPS),
1295 XtRImmediate, (XtPointer) -1},
1296 { "secondNPS", "secondNPS", XtRInt,
1297 sizeof(int), XtOffset(AppDataPtr, secondNPS),
1298 XtRImmediate, (XtPointer) -1},
1299 { "serverMoves", "serverMoves", XtRString,
1300 sizeof(String), XtOffset(AppDataPtr, serverMovesName),
1301 XtRImmediate, (XtPointer) 0},
1302 { "serverPause", "serverPause", XtRInt,
1303 sizeof(int), XtOffset(AppDataPtr, serverPause),
1304 XtRImmediate, (XtPointer) 0},
1305 { "suppressLoadMoves", "suppressLoadMoves", XtRBoolean,
1306 sizeof(Boolean), XtOffset(AppDataPtr, suppressLoadMoves),
1307 XtRImmediate, (XtPointer) False},
1308 { "userName", "userName", XtRString,
1309 sizeof(String), XtOffset(AppDataPtr, userName),
1310 XtRImmediate, (XtPointer) 0},
1311 { "egtFormats", "egtFormats", XtRString,
1312 sizeof(String), XtOffset(AppDataPtr, egtFormats),
1313 XtRImmediate, (XtPointer) 0},
1314 { "rewindIndex", "rewindIndex", XtRInt,
1315 sizeof(int), XtOffset(AppDataPtr, rewindIndex),
1316 XtRImmediate, (XtPointer) 0},
1317 { "sameColorGames", "sameColorGames", XtRInt,
1318 sizeof(int), XtOffset(AppDataPtr, sameColorGames),
1319 XtRImmediate, (XtPointer) 0},
1320 { "smpCores", "smpCores", XtRInt,
1321 sizeof(int), XtOffset(AppDataPtr, smpCores),
1322 XtRImmediate, (XtPointer) 1},
1323 { "niceEngines", "niceEngines", XtRInt,
1324 sizeof(int), XtOffset(AppDataPtr, niceEngines),
1325 XtRImmediate, (XtPointer) 0},
1326 { "nameOfDebugFile", "nameOfDebugFile", XtRString,
1327 sizeof(String), XtOffset(AppDataPtr, nameOfDebugFile),
1328 XtRImmediate, (XtPointer) "xboard.debug"},
1329 { "engineDebugOutput", "engineDebugOutput", XtRInt,
1330 sizeof(int), XtOffset(AppDataPtr, engineComments),
1331 XtRImmediate, (XtPointer) 0},
1332 { "noGUI", "noGUI", XtRBoolean,
1333 sizeof(Boolean), XtOffset(AppDataPtr, noGUI),
1334 XtRImmediate, (XtPointer) 0},
1335 { "firstOptions", "firstOptions", XtRString,
1336 sizeof(String), XtOffset(AppDataPtr, firstOptions),
1337 XtRImmediate, (XtPointer) "" },
1338 { "secondOptions", "secondOptions", XtRString,
1339 sizeof(String), XtOffset(AppDataPtr, secondOptions),
1340 XtRImmediate, (XtPointer) "" },
1341 { "firstNeedsNoncompliantFEN", "firstNeedsNoncompliantFEN", XtRString,
1342 sizeof(String), XtOffset(AppDataPtr, fenOverride1),
1343 XtRImmediate, (XtPointer) 0 },
1344 { "secondNeedsNoncompliantFEN", "secondNeedsNoncompliantFEN", XtRString,
1345 sizeof(String), XtOffset(AppDataPtr, fenOverride2),
1346 XtRImmediate, (XtPointer) 0 },
1348 // [HGM] Winboard_x UCI options
1349 { "firstIsUCI", "firstIsUCI", XtRBoolean,
1350 sizeof(Boolean), XtOffset(AppDataPtr, firstIsUCI),
1351 XtRImmediate, (XtPointer) False},
1352 { "secondIsUCI", "secondIsUCI", XtRBoolean,
1353 sizeof(Boolean), XtOffset(AppDataPtr, secondIsUCI),
1354 XtRImmediate, (XtPointer) False},
1355 { "firstHasOwnBookUCI", "firstHasOwnBookUCI", XtRBoolean,
1356 sizeof(Boolean), XtOffset(AppDataPtr, firstHasOwnBookUCI),
1357 XtRImmediate, (XtPointer) True},
1358 { "secondHasOwnBookUCI", "secondHasOwnBookUCI", XtRBoolean,
1359 sizeof(Boolean), XtOffset(AppDataPtr, secondHasOwnBookUCI),
1360 XtRImmediate, (XtPointer) True},
1361 { "usePolyglotBook", "usePolyglotBook", XtRBoolean,
1362 sizeof(Boolean), XtOffset(AppDataPtr, usePolyglotBook),
1363 XtRImmediate, (XtPointer) False},
1364 { "defaultHashSize", "defaultHashSize", XtRInt,
1365 sizeof(int), XtOffset(AppDataPtr, defaultHashSize),
1366 XtRImmediate, (XtPointer) 64},
1367 { "defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XtRInt,
1368 sizeof(int), XtOffset(AppDataPtr, defaultCacheSizeEGTB),
1369 XtRImmediate, (XtPointer) 4},
1370 { "polyglotDir", "polyglotDir", XtRString,
1371 sizeof(String), XtOffset(AppDataPtr, polyglotDir),
1372 XtRImmediate, (XtPointer) "." },
1373 { "polyglotBook", "polyglotBook", XtRString,
1374 sizeof(String), XtOffset(AppDataPtr, polyglotBook),
1375 XtRImmediate, (XtPointer) "" },
1376 { "defaultPathEGTB", "defaultPathEGTB", XtRString,
1377 sizeof(String), XtOffset(AppDataPtr, defaultPathEGTB),
1378 XtRImmediate, (XtPointer) "/usr/local/share/egtb"},
1379 { "delayBeforeQuit", "delayBeforeQuit", XtRInt,
1380 sizeof(int), XtOffset(AppDataPtr, delayBeforeQuit),
1381 XtRImmediate, (XtPointer) 0},
1382 { "delayAfterQuit", "delayAfterQuit", XtRInt,
1383 sizeof(int), XtOffset(AppDataPtr, delayAfterQuit),
1384 XtRImmediate, (XtPointer) 0},
1387 XrmOptionDescRec shellOptions[] = {
1388 { "-whitePieceColor", "whitePieceColor", XrmoptionSepArg, NULL },
1389 { "-blackPieceColor", "blackPieceColor", XrmoptionSepArg, NULL },
1390 { "-lightSquareColor", "lightSquareColor", XrmoptionSepArg, NULL },
1391 { "-darkSquareColor", "darkSquareColor", XrmoptionSepArg, NULL },
1392 { "-highlightSquareColor", "highlightSquareColor", XrmoptionSepArg, NULL },
1393 { "-premoveHighlightColor", "premoveHighlightColor", XrmoptionSepArg,NULL},
1394 { "-movesPerSession", "movesPerSession", XrmoptionSepArg, NULL },
1395 { "-mps", "movesPerSession", XrmoptionSepArg, NULL },
1396 { "-timeIncrement", "timeIncrement", XrmoptionSepArg, NULL },
1397 { "-inc", "timeIncrement", XrmoptionSepArg, NULL },
1398 { "-initString", "initString", XrmoptionSepArg, NULL },
1399 { "-firstInitString", "initString", XrmoptionSepArg, NULL },
1400 { "-secondInitString", "secondInitString", XrmoptionSepArg, NULL },
1401 { "-firstComputerString", "firstComputerString", XrmoptionSepArg, NULL },
1402 { "-secondComputerString", "secondComputerString", XrmoptionSepArg, NULL },
1403 { "-firstChessProgram", "firstChessProgram", XrmoptionSepArg, NULL },
1404 { "-fcp", "firstChessProgram", XrmoptionSepArg, NULL },
1405 { "-secondChessProgram", "secondChessProgram", XrmoptionSepArg, NULL },
1406 { "-scp", "secondChessProgram", XrmoptionSepArg, NULL },
1407 { "-firstPlaysBlack", "firstPlaysBlack", XrmoptionSepArg, NULL },
1408 { "-fb", "firstPlaysBlack", XrmoptionNoArg, "True" },
1409 { "-xfb", "firstPlaysBlack", XrmoptionNoArg, "False" },
1410 { "-noChessProgram", "noChessProgram", XrmoptionSepArg, NULL },
1411 { "-ncp", "noChessProgram", XrmoptionNoArg, "True" },
1412 { "-xncp", "noChessProgram", XrmoptionNoArg, "False" },
1413 { "-firstHost", "firstHost", XrmoptionSepArg, NULL },
1414 { "-fh", "firstHost", XrmoptionSepArg, NULL },
1415 { "-secondHost", "secondHost", XrmoptionSepArg, NULL },
1416 { "-sh", "secondHost", XrmoptionSepArg, NULL },
1417 { "-firstDirectory", "firstDirectory", XrmoptionSepArg, NULL },
1418 { "-fd", "firstDirectory", XrmoptionSepArg, NULL },
1419 { "-secondDirectory", "secondDirectory", XrmoptionSepArg, NULL },
1420 { "-sd", "secondDirectory", XrmoptionSepArg, NULL },
1421 { "-bitmapDirectory", "bitmapDirectory", XrmoptionSepArg, NULL },
1422 { "-bm", "bitmapDirectory", XrmoptionSepArg, NULL },
1423 { "-remoteShell", "remoteShell", XrmoptionSepArg, NULL },
1424 { "-rsh", "remoteShell", XrmoptionSepArg, NULL },
1425 { "-remoteUser", "remoteUser", XrmoptionSepArg, NULL },
1426 { "-ruser", "remoteUser", XrmoptionSepArg, NULL },
1427 { "-timeDelay", "timeDelay", XrmoptionSepArg, NULL },
1428 { "-td", "timeDelay", XrmoptionSepArg, NULL },
1429 { "-timeControl", "timeControl", XrmoptionSepArg, NULL },
1430 { "-tc", "timeControl", XrmoptionSepArg, NULL },
1431 { "-internetChessServerMode", "internetChessServerMode",
1432 XrmoptionSepArg, NULL },
1433 { "-ics", "internetChessServerMode", XrmoptionNoArg, "True" },
1434 { "-xics", "internetChessServerMode", XrmoptionNoArg, "False" },
1435 { "-internetChessServerHost", "internetChessServerHost",
1436 XrmoptionSepArg, NULL },
1437 { "-icshost", "internetChessServerHost", XrmoptionSepArg, NULL },
1438 { "-internetChessServerPort", "internetChessServerPort",
1439 XrmoptionSepArg, NULL },
1440 { "-icsport", "internetChessServerPort", XrmoptionSepArg, NULL },
1441 { "-internetChessServerCommPort", "internetChessServerCommPort",
1442 XrmoptionSepArg, NULL },
1443 { "-icscomm", "internetChessServerCommPort", XrmoptionSepArg, NULL },
1444 { "-internetChessServerLogonScript", "internetChessServerLogonScript",
1445 XrmoptionSepArg, NULL },
1446 { "-icslogon", "internetChessServerLogonScript", XrmoptionSepArg, NULL },
1447 { "-internetChessServerHelper", "internetChessServerHelper",
1448 XrmoptionSepArg, NULL },
1449 { "-icshelper", "internetChessServerHelper", XrmoptionSepArg, NULL },
1450 { "-internetChessServerInputBox", "internetChessServerInputBox",
1451 XrmoptionSepArg, NULL },
1452 { "-icsinput", "internetChessServerInputBox", XrmoptionNoArg, "True" },
1453 { "-xicsinput", "internetChessServerInputBox", XrmoptionNoArg, "False" },
1454 { "-icsAlarm", "icsAlarm", XrmoptionSepArg, NULL },
1455 { "-alarm", "icsAlarm", XrmoptionNoArg, "True" },
1456 { "-xalarm", "icsAlarm", XrmoptionNoArg, "False" },
1457 { "-icsAlarmTime", "icsAlarmTime", XrmoptionSepArg, NULL },
1458 { "-useTelnet", "useTelnet", XrmoptionSepArg, NULL },
1459 { "-telnet", "useTelnet", XrmoptionNoArg, "True" },
1460 { "-xtelnet", "useTelnet", XrmoptionNoArg, "False" },
1461 { "-telnetProgram", "telnetProgram", XrmoptionSepArg, NULL },
1462 { "-gateway", "gateway", XrmoptionSepArg, NULL },
1463 { "-loadGameFile", "loadGameFile", XrmoptionSepArg, NULL },
1464 { "-lgf", "loadGameFile", XrmoptionSepArg, NULL },
1465 { "-loadGameIndex", "loadGameIndex", XrmoptionSepArg, NULL },
1466 { "-lgi", "loadGameIndex", XrmoptionSepArg, NULL },
1467 { "-saveGameFile", "saveGameFile", XrmoptionSepArg, NULL },
1468 { "-sgf", "saveGameFile", XrmoptionSepArg, NULL },
1469 { "-autoSaveGames", "autoSaveGames", XrmoptionSepArg, NULL },
1470 { "-autosave", "autoSaveGames", XrmoptionNoArg, "True" },
1471 { "-xautosave", "autoSaveGames", XrmoptionNoArg, "False" },
1472 { "-autoRaiseBoard", "autoRaiseBoard", XrmoptionSepArg, NULL },
1473 { "-autoraise", "autoRaiseBoard", XrmoptionNoArg, "True" },
1474 { "-xautoraise", "autoRaiseBoard", XrmoptionNoArg, "False" },
1475 { "-blindfold", "blindfold", XrmoptionSepArg, NULL },
1476 { "-blind", "blindfold", XrmoptionNoArg, "True" },
1477 { "-xblind", "blindfold", XrmoptionNoArg, "False" },
1478 { "-loadPositionFile", "loadPositionFile", XrmoptionSepArg, NULL },
1479 { "-lpf", "loadPositionFile", XrmoptionSepArg, NULL },
1480 { "-loadPositionIndex", "loadPositionIndex", XrmoptionSepArg, NULL },
1481 { "-lpi", "loadPositionIndex", XrmoptionSepArg, NULL },
1482 { "-savePositionFile", "savePositionFile", XrmoptionSepArg, NULL },
1483 { "-spf", "savePositionFile", XrmoptionSepArg, NULL },
1484 { "-matchMode", "matchMode", XrmoptionSepArg, NULL },
1485 { "-mm", "matchMode", XrmoptionNoArg, "True" },
1486 { "-xmm", "matchMode", XrmoptionNoArg, "False" },
1487 { "-matchGames", "matchGames", XrmoptionSepArg, NULL },
1488 { "-mg", "matchGames", XrmoptionSepArg, NULL },
1489 { "-monoMode", "monoMode", XrmoptionSepArg, NULL },
1490 { "-mono", "monoMode", XrmoptionNoArg, "True" },
1491 { "-xmono", "monoMode", XrmoptionNoArg, "False" },
1492 { "-debugMode", "debugMode", XrmoptionSepArg, NULL },
1493 { "-debug", "debugMode", XrmoptionNoArg, "True" },
1494 { "-xdebug", "debugMode", XrmoptionNoArg, "False" },
1495 { "-clockMode", "clockMode", XrmoptionSepArg, NULL },
1496 { "-clock", "clockMode", XrmoptionNoArg, "True" },
1497 { "-xclock", "clockMode", XrmoptionNoArg, "False" },
1498 { "-boardSize", "boardSize", XrmoptionSepArg, NULL },
1499 { "-size", "boardSize", XrmoptionSepArg, NULL },
1500 { "-searchTime", "searchTime", XrmoptionSepArg, NULL },
1501 { "-st", "searchTime", XrmoptionSepArg, NULL },
1502 { "-searchDepth", "searchDepth", XrmoptionSepArg, NULL },
1503 { "-depth", "searchDepth", XrmoptionSepArg, NULL },
1504 { "-showCoords", "showCoords", XrmoptionSepArg, NULL },
1505 { "-coords", "showCoords", XrmoptionNoArg, "True" },
1506 { "-xcoords", "showCoords", XrmoptionNoArg, "False" },
1508 { "-showJail", "showJail", XrmoptionSepArg, NULL },
1509 { "-jail", "showJail", XrmoptionNoArg, "1" },
1510 { "-sidejail", "showJail", XrmoptionNoArg, "2" },
1511 { "-xjail", "showJail", XrmoptionNoArg, "0" },
1513 { "-showThinking", "showThinking", XrmoptionSepArg, NULL },
1514 { "-thinking", "showThinking", XrmoptionNoArg, "True" },
1515 { "-xthinking", "showThinking", XrmoptionNoArg, "False" },
1516 { "-ponderNextMove", "ponderNextMove", XrmoptionSepArg, NULL },
1517 { "-ponder", "ponderNextMove", XrmoptionNoArg, "True" },
1518 { "-xponder", "ponderNextMove", XrmoptionNoArg, "False" },
1519 { "-periodicUpdates", "periodicUpdates", XrmoptionSepArg, NULL },
1520 { "-periodic", "periodicUpdates", XrmoptionNoArg, "True" },
1521 { "-xperiodic", "periodicUpdates", XrmoptionNoArg, "False" },
1522 { "-clockFont", "clockFont", XrmoptionSepArg, NULL },
1523 { "-coordFont", "coordFont", XrmoptionSepArg, NULL },
1524 { "-font", "font", XrmoptionSepArg, NULL },
1525 { "-ringBellAfterMoves", "ringBellAfterMoves", XrmoptionSepArg, NULL },
1526 { "-bell", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1527 { "-xbell", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1528 { "-movesound", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1529 { "-xmovesound", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1530 { "-autoCallFlag", "autoCallFlag", XrmoptionSepArg, NULL },
1531 { "-autoflag", "autoCallFlag", XrmoptionNoArg, "True" },
1532 { "-xautoflag", "autoCallFlag", XrmoptionNoArg, "False" },
1533 { "-autoFlipView", "autoFlipView", XrmoptionSepArg, NULL },
1534 { "-autoflip", "autoFlipView", XrmoptionNoArg, "True" },
1535 { "-xautoflip", "autoFlipView", XrmoptionNoArg, "False" },
1536 { "-autoObserve", "autoObserve", XrmoptionSepArg, NULL },
1537 { "-autobs", "autoObserve", XrmoptionNoArg, "True" },
1538 { "-xautobs", "autoObserve", XrmoptionNoArg, "False" },
1539 { "-autoComment", "autoComment", XrmoptionSepArg, NULL },
1540 { "-autocomm", "autoComment", XrmoptionNoArg, "True" },
1541 { "-xautocomm", "autoComment", XrmoptionNoArg, "False" },
1542 { "-getMoveList", "getMoveList", XrmoptionSepArg, NULL },
1543 { "-moves", "getMoveList", XrmoptionNoArg, "True" },
1544 { "-xmoves", "getMoveList", XrmoptionNoArg, "False" },
1546 { "-highlightDragging", "highlightDragging", XrmoptionSepArg, NULL },
1547 { "-highdrag", "highlightDragging", XrmoptionNoArg, "True" },
1548 { "-xhighdrag", "highlightDragging", XrmoptionNoArg, "False" },
1550 { "-highlightLastMove", "highlightLastMove", XrmoptionSepArg, NULL },
1551 { "-highlight", "highlightLastMove", XrmoptionNoArg, "True" },
1552 { "-xhighlight", "highlightLastMove", XrmoptionNoArg, "False" },
1553 { "-premove", "premove", XrmoptionSepArg, NULL },
1554 { "-pre", "premove", XrmoptionNoArg, "True" },
1555 { "-xpre", "premove", XrmoptionNoArg, "False" },
1556 { "-testLegality", "testLegality", XrmoptionSepArg, NULL },
1557 { "-legal", "testLegality", XrmoptionNoArg, "True" },
1558 { "-xlegal", "testLegality", XrmoptionNoArg, "False" },
1559 { "-flipView", "flipView", XrmoptionSepArg, NULL },
1560 { "-flip", "flipView", XrmoptionNoArg, "True" },
1561 { "-xflip", "flipView", XrmoptionNoArg, "False" },
1562 { "-cmail", "cmailGameName", XrmoptionSepArg, NULL },
1563 { "-alwaysPromoteToQueen", "alwaysPromoteToQueen",
1564 XrmoptionSepArg, NULL },
1565 { "-queen", "alwaysPromoteToQueen", XrmoptionNoArg, "True" },
1566 { "-xqueen", "alwaysPromoteToQueen", XrmoptionNoArg, "False" },
1567 { "-oldSaveStyle", "oldSaveStyle", XrmoptionSepArg, NULL },
1568 { "-oldsave", "oldSaveStyle", XrmoptionNoArg, "True" },
1569 { "-xoldsave", "oldSaveStyle", XrmoptionNoArg, "False" },
1570 { "-quietPlay", "quietPlay", XrmoptionSepArg, NULL },
1571 { "-quiet", "quietPlay", XrmoptionNoArg, "True" },
1572 { "-xquiet", "quietPlay", XrmoptionNoArg, "False" },
1573 { "-titleInWindow", "titleInWindow", XrmoptionSepArg, NULL },
1574 { "-title", "titleInWindow", XrmoptionNoArg, "True" },
1575 { "-xtitle", "titleInWindow", XrmoptionNoArg, "False" },
1577 { "-zippyTalk", "zippyTalk", XrmoptionSepArg, NULL },
1578 { "-zt", "zippyTalk", XrmoptionNoArg, "True" },
1579 { "-xzt", "zippyTalk", XrmoptionNoArg, "False" },
1580 { "-zippyPlay", "zippyPlay", XrmoptionSepArg, NULL },
1581 { "-zp", "zippyPlay", XrmoptionNoArg, "True" },
1582 { "-xzp", "zippyPlay", XrmoptionNoArg, "False" },
1583 { "-zippyLines", "zippyLines", XrmoptionSepArg, NULL },
1584 { "-zippyPinhead", "zippyPinhead", XrmoptionSepArg, NULL },
1585 { "-zippyPassword", "zippyPassword", XrmoptionSepArg, NULL },
1586 { "-zippyPassword2", "zippyPassword2", XrmoptionSepArg, NULL },
1587 { "-zippyWrongPassword", "zippyWrongPassword", XrmoptionSepArg, NULL },
1588 { "-zippyAcceptOnly", "zippyAcceptOnly", XrmoptionSepArg, NULL },
1589 { "-zippyUseI", "zippyUseI", XrmoptionSepArg, NULL },
1590 { "-zui", "zippyUseI", XrmoptionNoArg, "True" },
1591 { "-xzui", "zippyUseI", XrmoptionNoArg, "False" },
1592 { "-zippyBughouse", "zippyBughouse", XrmoptionSepArg, NULL },
1593 { "-zippyNoplayCrafty", "zippyNoplayCrafty", XrmoptionSepArg, NULL },
1594 { "-znc", "zippyNoplayCrafty", XrmoptionNoArg, "True" },
1595 { "-xznc", "zippyNoplayCrafty", XrmoptionNoArg, "False" },
1596 { "-zippyGameEnd", "zippyGameEnd", XrmoptionSepArg, NULL },
1597 { "-zippyGameStart", "zippyGameStart", XrmoptionSepArg, NULL },
1598 { "-zippyAdjourn", "zippyAdjourn", XrmoptionSepArg, NULL },
1599 { "-zadj", "zippyAdjourn", XrmoptionNoArg, "True" },
1600 { "-xzadj", "zippyAdjourn", XrmoptionNoArg, "False" },
1601 { "-zippyAbort", "zippyAbort", XrmoptionSepArg, NULL },
1602 { "-zab", "zippyAbort", XrmoptionNoArg, "True" },
1603 { "-xzab", "zippyAbort", XrmoptionNoArg, "False" },
1604 { "-zippyVariants", "zippyVariants", XrmoptionSepArg, NULL },
1605 { "-zippyMaxGames", "zippyMaxGames", XrmoptionSepArg, NULL },
1606 { "-zippyReplayTimeout", "zippyReplayTimeout", XrmoptionSepArg, NULL },
1607 { "-zippyShortGame", "zippyShortGame", XrmoptionSepArg, NULL },
1609 { "-flashCount", "flashCount", XrmoptionSepArg, NULL },
1610 { "-flash", "flashCount", XrmoptionNoArg, "3" },
1611 { "-xflash", "flashCount", XrmoptionNoArg, "0" },
1612 { "-flashRate", "flashRate", XrmoptionSepArg, NULL },
1613 { "-pixmapDirectory", "pixmapDirectory", XrmoptionSepArg, NULL },
1614 { "-msLoginDelay", "msLoginDelay", XrmoptionSepArg, NULL },
1615 { "-pixmap", "pixmapDirectory", XrmoptionSepArg, NULL },
1616 { "-colorizeMessages", "colorizeMessages", XrmoptionSepArg, NULL },
1617 { "-colorize", "colorizeMessages", XrmoptionNoArg, "True" },
1618 { "-xcolorize", "colorizeMessages", XrmoptionNoArg, "False" },
1619 { "-colorShout", "colorShout", XrmoptionSepArg, NULL },
1620 { "-colorSShout", "colorSShout", XrmoptionSepArg, NULL },
1621 { "-colorCShout", "colorSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1622 { "-colorChannel1", "colorChannel1", XrmoptionSepArg, NULL },
1623 { "-colorChannel", "colorChannel", XrmoptionSepArg, NULL },
1624 { "-colorKibitz", "colorKibitz", XrmoptionSepArg, NULL },
1625 { "-colorTell", "colorTell", XrmoptionSepArg, NULL },
1626 { "-colorChallenge", "colorChallenge", XrmoptionSepArg, NULL },
1627 { "-colorRequest", "colorRequest", XrmoptionSepArg, NULL },
1628 { "-colorSeek", "colorSeek", XrmoptionSepArg, NULL },
1629 { "-colorNormal", "colorNormal", XrmoptionSepArg, NULL },
1630 { "-soundProgram", "soundProgram", XrmoptionSepArg, NULL },
1631 { "-soundShout", "soundShout", XrmoptionSepArg, NULL },
1632 { "-soundSShout", "soundSShout", XrmoptionSepArg, NULL },
1633 { "-soundCShout", "soundSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1634 { "-soundChannel1", "soundChannel1", XrmoptionSepArg, NULL },
1635 { "-soundChannel", "soundChannel", XrmoptionSepArg, NULL },
1636 { "-soundKibitz", "soundKibitz", XrmoptionSepArg, NULL },
1637 { "-soundTell", "soundTell", XrmoptionSepArg, NULL },
1638 { "-soundChallenge", "soundChallenge", XrmoptionSepArg, NULL },
1639 { "-soundRequest", "soundRequest", XrmoptionSepArg, NULL },
1640 { "-soundSeek", "soundSeek", XrmoptionSepArg, NULL },
1641 { "-soundMove", "soundMove", XrmoptionSepArg, NULL },
1642 { "-soundIcsWin", "soundIcsWin", XrmoptionSepArg, NULL },
1643 { "-soundIcsLoss", "soundIcsLoss", XrmoptionSepArg, NULL },
1644 { "-soundIcsDraw", "soundIcsDraw", XrmoptionSepArg, NULL },
1645 { "-soundIcsUnfinished", "soundIcsUnfinished", XrmoptionSepArg, NULL },
1646 { "-soundIcsAlarm", "soundIcsAlarm", XrmoptionSepArg, NULL },
1647 { "-reuseFirst", "reuseFirst", XrmoptionSepArg, NULL },
1648 { "-reuseChessPrograms", "reuseFirst", XrmoptionSepArg, NULL }, /*compat*/
1649 { "-reuse", "reuseFirst", XrmoptionNoArg, "True" },
1650 { "-xreuse", "reuseFirst", XrmoptionNoArg, "False" },
1651 { "-reuseSecond", "reuseSecond", XrmoptionSepArg, NULL },
1652 { "-reuse2", "reuseSecond", XrmoptionNoArg, "True" },
1653 { "-xreuse2", "reuseSecond", XrmoptionNoArg, "False" },
1654 { "-animateMoving", "animateMoving", XrmoptionSepArg, NULL },
1655 { "-animate", "animateMoving", XrmoptionNoArg, "True" },
1656 { "-xanimate", "animateMoving", XrmoptionNoArg, "False" },
1657 { "-animateDragging", "animateDragging", XrmoptionSepArg, NULL },
1658 { "-drag", "animateDragging", XrmoptionNoArg, "True" },
1659 { "-xdrag", "animateDragging", XrmoptionNoArg, "False" },
1660 { "-animateSpeed", "animateSpeed", XrmoptionSepArg, NULL },
1661 { "-popupExitMessage", "popupExitMessage", XrmoptionSepArg, NULL },
1662 { "-exit", "popupExitMessage", XrmoptionNoArg, "True" },
1663 { "-xexit", "popupExitMessage", XrmoptionNoArg, "False" },
1664 { "-popupMoveErrors", "popupMoveErrors", XrmoptionSepArg, NULL },
1665 { "-popup", "popupMoveErrors", XrmoptionNoArg, "True" },
1666 { "-xpopup", "popupMoveErrors", XrmoptionNoArg, "False" },
1667 { "-fontSizeTolerance", "fontSizeTolerance", XrmoptionSepArg, NULL },
1668 { "-initialMode", "initialMode", XrmoptionSepArg, NULL },
1669 { "-mode", "initialMode", XrmoptionSepArg, NULL },
1670 { "-variant", "variant", XrmoptionSepArg, NULL },
1671 { "-firstProtocolVersion", "firstProtocolVersion", XrmoptionSepArg, NULL },
1672 { "-secondProtocolVersion","secondProtocolVersion",XrmoptionSepArg, NULL },
1673 { "-showButtonBar", "showButtonBar", XrmoptionSepArg, NULL },
1674 { "-buttons", "showButtonBar", XrmoptionNoArg, "True" },
1675 { "-xbuttons", "showButtonBar", XrmoptionNoArg, "False" },
1676 /* [AS,HR] New features */
1677 { "-firstScoreAbs", "firstScoreAbs", XrmoptionSepArg, NULL },
1678 { "-secondScoreAbs", "secondScoreAbs", XrmoptionSepArg, NULL },
1679 { "-pgnExtendedInfo", "pgnExtendedInfo", XrmoptionSepArg, NULL },
1680 { "-hideThinkingFromHuman", "hideThinkingFromHuman", XrmoptionSepArg, NULL },
1681 { "-adjudicateLossThreshold", "adjudicateLossThreshold", XrmoptionSepArg, NULL },
1682 { "-pgnEventHeader", "pgnEventHeader", XrmoptionSepArg, NULL },
1683 { "-firstIsUCI", "firstIsUCI", XrmoptionSepArg, NULL },
1684 { "-secondIsUCI", "secondIsUCI", XrmoptionSepArg, NULL },
1685 { "-fUCI", "firstIsUCI", XrmoptionNoArg, "True" },
1686 { "-sUCI", "secondIsUCI", XrmoptionNoArg, "True" },
1687 { "-firstHasOwnBookUCI", "firstHasOwnBookUCI", XrmoptionSepArg, NULL },
1688 { "-secondHasOwnBookUCI", "secondHasOwnBookUCI", XrmoptionSepArg, NULL },
1689 { "-fNoOwnBookUCI", "firstHasOwnBookUCI", XrmoptionNoArg, "False" },
1690 { "-sNoOwnBookUCI", "secondHasOwnBookUCI", XrmoptionNoArg, "False" },
1691 { "-firstXBook", "firstHasOwnBookUCI", XrmoptionNoArg, "False" },
1692 { "-secondXBook", "secondHasOwnBookUCI", XrmoptionNoArg, "False" },
1693 { "-polyglotDir", "polyglotDir", XrmoptionSepArg, NULL },
1694 { "-usePolyglotBook", "usePolyglotBook", XrmoptionSepArg, NULL },
1695 { "-polyglotBook", "polyglotBook", XrmoptionSepArg, NULL },
1696 { "-defaultHashSize", "defaultHashSize", XrmoptionSepArg, NULL },
1697 { "-defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XrmoptionSepArg, NULL },
1698 { "-defaultPathEGTB", "defaultPathEGTB", XrmoptionSepArg, NULL },
1699 { "-defaultFrcPosition", "defaultFrcPosition", XrmoptionSepArg, NULL },
1700 { "-gameListTags", "gameListTags", XrmoptionSepArg, NULL },
1701 // [HGM] I am sure AS added many more options, but we have to fish them out, from the list in winboard.c
1703 /* [HGM,HR] User-selectable board size */
1704 { "-boardWidth", "boardWidth", XrmoptionSepArg, NULL },
1705 { "-boardHeight", "boardHeight", XrmoptionSepArg, NULL },
1706 { "-matchPause", "matchPause", XrmoptionSepArg, NULL },
1708 /* [HGM] new arguments of 4.3.xx. All except first three are back-end options, which should work immediately */
1709 { "-holdingsSize", "holdingsSize", XrmoptionSepArg, NULL }, // requires extensive front-end changes to work
1710 { "-flipBlack", "flipBlack", XrmoptionSepArg, NULL }, // requires front-end changes to work
1711 { "-allWhite", "allWhite", XrmoptionSepArg, NULL }, // requires front-end changes to work
1712 { "-pieceToCharTable", "pieceToCharTable", XrmoptionSepArg, NULL },
1713 { "-alphaRank", "alphaRank", XrmoptionSepArg, NULL },
1714 { "-testClaims", "testClaims", XrmoptionSepArg, NULL },
1715 { "-checkMates", "checkMates", XrmoptionSepArg, NULL },
1716 { "-materialDraws", "materialDraws", XrmoptionSepArg, NULL },
1717 { "-trivialDraws", "trivialDraws", XrmoptionSepArg, NULL },
1718 { "-ruleMoves", "ruleMoves", XrmoptionSepArg, NULL },
1719 { "-repeatsToDraw", "repeatsToDraw", XrmoptionSepArg, NULL },
1720 { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL },
1721 { "-userName", "userName", XrmoptionSepArg, NULL },
1722 { "-autoKibitz", "autoKibitz", XrmoptionNoArg, "True" },
1723 { "-firstTimeOdds", "firstTimeOdds", XrmoptionSepArg, NULL },
1724 { "-secondTimeOdds", "secondTimeOdds", XrmoptionSepArg, NULL },
1725 { "-timeOddsMode", "timeOddsMode", XrmoptionSepArg, NULL },
1726 { "-firstAccumulateTC", "firstAccumulateTC", XrmoptionSepArg, NULL },
1727 { "-secondAccumulateTC", "secondAccumulateTC", XrmoptionSepArg, NULL },
1728 { "-firstNPS", "firstNPS", XrmoptionSepArg, NULL },
1729 { "-secondNPS", "secondNPS", XrmoptionSepArg, NULL },
1730 { "-serverMoves", "serverMoves", XrmoptionSepArg, NULL },
1731 { "-serverPause", "serverPause", XrmoptionSepArg, NULL },
1732 { "-suppressLoadMoves", "suppressLoadMoves", XrmoptionSepArg, NULL },
1733 { "-egtFormats", "egtFormats", XrmoptionSepArg, NULL },
1734 { "-userName", "userName", XrmoptionSepArg, NULL },
1735 { "-smpCores", "smpCores", XrmoptionSepArg, NULL },
1736 { "-sameColorGames", "sameColorGames", XrmoptionSepArg, NULL },
1737 { "-rewindIndex", "rewindIndex", XrmoptionSepArg, NULL },
1738 { "-niceEngines", "niceEngines", XrmoptionSepArg, NULL },
1739 { "-delayBeforeQuit", "delayBeforeQuit", XrmoptionSepArg, NULL },
1740 { "-delayAfterQuit", "delayAfterQuit", XrmoptionSepArg, NULL },
1741 { "-nameOfDebugFile", "nameOfDebugFile", XrmoptionSepArg, NULL },
1742 { "-debugFile", "nameOfDebugFile", XrmoptionSepArg, NULL },
1743 { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL },
1744 { "-noGUI", "noGUI", XrmoptionNoArg, "True" },
1745 { "-firstOptions", "firstOptions", XrmoptionSepArg, NULL },
1746 { "-secondOptions", "secondOptions", XrmoptionSepArg, NULL },
1747 { "-firstNeedsNoncompliantFEN", "firstNeedsNoncompliantFEN", XrmoptionSepArg, NULL },
1748 { "-secondNeedsNoncompliantFEN", "secondNeedsNoncompliantFEN", XrmoptionSepArg, NULL },
1752 XtActionsRec boardActions[] = {
1753 { "DrawPosition", DrawPositionProc },
1754 { "HandleUserMove", HandleUserMove },
1755 { "AnimateUserMove", AnimateUserMove },
1756 { "FileNameAction", FileNameAction },
1757 { "AskQuestionProc", AskQuestionProc },
1758 { "AskQuestionReplyAction", AskQuestionReplyAction },
1759 { "PieceMenuPopup", PieceMenuPopup },
1760 { "WhiteClock", WhiteClock },
1761 { "BlackClock", BlackClock },
1762 { "Iconify", Iconify },
1763 { "ResetProc", ResetProc },
1764 { "LoadGameProc", LoadGameProc },
1765 { "LoadNextGameProc", LoadNextGameProc },
1766 { "LoadPrevGameProc", LoadPrevGameProc },
1767 { "LoadSelectedProc", LoadSelectedProc },
1768 { "ReloadGameProc", ReloadGameProc },
1769 { "LoadPositionProc", LoadPositionProc },
1770 { "LoadNextPositionProc", LoadNextPositionProc },
1771 { "LoadPrevPositionProc", LoadPrevPositionProc },
1772 { "ReloadPositionProc", ReloadPositionProc },
1773 { "CopyPositionProc", CopyPositionProc },
1774 { "PastePositionProc", PastePositionProc },
1775 { "CopyGameProc", CopyGameProc },
1776 { "PasteGameProc", PasteGameProc },
1777 { "SaveGameProc", SaveGameProc },
1778 { "SavePositionProc", SavePositionProc },
1779 { "MailMoveProc", MailMoveProc },
1780 { "ReloadCmailMsgProc", ReloadCmailMsgProc },
1781 { "QuitProc", QuitProc },
1782 { "MachineWhiteProc", MachineWhiteProc },
1783 { "MachineBlackProc", MachineBlackProc },
1784 { "AnalysisModeProc", AnalyzeModeProc },
1785 { "AnalyzeFileProc", AnalyzeFileProc },
1786 { "TwoMachinesProc", TwoMachinesProc },
1787 { "IcsClientProc", IcsClientProc },
1788 { "EditGameProc", EditGameProc },
1789 { "EditPositionProc", EditPositionProc },
1790 { "TrainingProc", EditPositionProc },
1791 { "EngineOutputProc", EngineOutputProc}, // [HGM] Winboard_x engine-output window
1792 { "ShowGameListProc", ShowGameListProc },
1793 { "ShowMoveListProc", HistoryShowProc},
1794 { "EditTagsProc", EditCommentProc },
1795 { "EditCommentProc", EditCommentProc },
1796 { "IcsAlarmProc", IcsAlarmProc },
1797 { "IcsInputBoxProc", IcsInputBoxProc },
1798 { "PauseProc", PauseProc },
1799 { "AcceptProc", AcceptProc },
1800 { "DeclineProc", DeclineProc },
1801 { "RematchProc", RematchProc },
1802 { "CallFlagProc", CallFlagProc },
1803 { "DrawProc", DrawProc },
1804 { "AdjournProc", AdjournProc },
1805 { "AbortProc", AbortProc },
1806 { "ResignProc", ResignProc },
1807 { "AdjuWhiteProc", AdjuWhiteProc },
1808 { "AdjuBlackProc", AdjuBlackProc },
1809 { "AdjuDrawProc", AdjuDrawProc },
1810 { "EnterKeyProc", EnterKeyProc },
1811 { "StopObservingProc", StopObservingProc },
1812 { "StopExaminingProc", StopExaminingProc },
1813 { "BackwardProc", BackwardProc },
1814 { "ForwardProc", ForwardProc },
1815 { "ToStartProc", ToStartProc },
1816 { "ToEndProc", ToEndProc },
1817 { "RevertProc", RevertProc },
1818 { "TruncateGameProc", TruncateGameProc },
1819 { "MoveNowProc", MoveNowProc },
1820 { "RetractMoveProc", RetractMoveProc },
1821 { "AlwaysQueenProc", AlwaysQueenProc },
1822 { "AnimateDraggingProc", AnimateDraggingProc },
1823 { "AnimateMovingProc", AnimateMovingProc },
1824 { "AutoflagProc", AutoflagProc },
1825 { "AutoflipProc", AutoflipProc },
1826 { "AutobsProc", AutobsProc },
1827 { "AutoraiseProc", AutoraiseProc },
1828 { "AutosaveProc", AutosaveProc },
1829 { "BlindfoldProc", BlindfoldProc },
1830 { "FlashMovesProc", FlashMovesProc },
1831 { "FlipViewProc", FlipViewProc },
1832 { "GetMoveListProc", GetMoveListProc },
1834 { "HighlightDraggingProc", HighlightDraggingProc },
1836 { "HighlightLastMoveProc", HighlightLastMoveProc },
1837 { "IcsAlarmProc", IcsAlarmProc },
1838 { "MoveSoundProc", MoveSoundProc },
1839 { "OldSaveStyleProc", OldSaveStyleProc },
1840 { "PeriodicUpdatesProc", PeriodicUpdatesProc },
1841 { "PonderNextMoveProc", PonderNextMoveProc },
1842 { "PopupExitMessageProc", PopupExitMessageProc },
1843 { "PopupMoveErrorsProc", PopupMoveErrorsProc },
1844 { "PremoveProc", PremoveProc },
1845 { "QuietPlayProc", QuietPlayProc },
1846 { "ShowCoordsProc", ShowCoordsProc },
1847 { "ShowThinkingProc", ShowThinkingProc },
1848 { "HideThinkingProc", HideThinkingProc },
1849 { "TestLegalityProc", TestLegalityProc },
1850 { "InfoProc", InfoProc },
1851 { "ManProc", ManProc },
1852 { "HintProc", HintProc },
1853 { "BookProc", BookProc },
1854 { "AboutGameProc", AboutGameProc },
1855 { "AboutProc", AboutProc },
1856 { "DebugProc", DebugProc },
1857 { "NothingProc", NothingProc },
1858 { "CommentPopDown", (XtActionProc) CommentPopDown },
1859 { "EditCommentPopDown", (XtActionProc) EditCommentPopDown },
1860 { "TagsPopDown", (XtActionProc) TagsPopDown },
1861 { "ErrorPopDown", (XtActionProc) ErrorPopDown },
1862 { "ICSInputBoxPopDown", (XtActionProc) ICSInputBoxPopDown },
1863 { "AnalysisPopDown", (XtActionProc) AnalysisPopDown },
1864 { "FileNamePopDown", (XtActionProc) FileNamePopDown },
1865 { "AskQuestionPopDown", (XtActionProc) AskQuestionPopDown },
1866 { "GameListPopDown", (XtActionProc) GameListPopDown },
1867 { "PromotionPopDown", (XtActionProc) PromotionPopDown },
1868 { "HistoryPopDown", (XtActionProc) HistoryPopDown },
1869 { "EngineOutputPopDown", (XtActionProc) EngineOutputPopDown },
1870 { "ShufflePopDown", (XtActionProc) ShufflePopDown },
1871 { "EnginePopDown", (XtActionProc) EnginePopDown },
1872 { "UciPopDown", (XtActionProc) UciPopDown },
1873 { "TimeControlPopDown", (XtActionProc) TimeControlPopDown },
1874 { "NewVariantPopDown", (XtActionProc) NewVariantPopDown },
1875 { "SettingsPopDown", (XtActionProc) SettingsPopDown },
1878 char globalTranslations[] =
1879 ":<Key>R: ResignProc() \n \
1880 :<Key>r: ResetProc() \n \
1881 :<Key>g: LoadGameProc() \n \
1882 :<Key>N: LoadNextGameProc() \n \
1883 :<Key>P: LoadPrevGameProc() \n \
1884 :<Key>Q: QuitProc() \n \
1885 :<Key>F: ToEndProc() \n \
1886 :<Key>f: ForwardProc() \n \
1887 :<Key>B: ToStartProc() \n \
1888 :<Key>b: BackwardProc() \n \
1889 :<Key>p: PauseProc() \n \
1890 :<Key>d: DrawProc() \n \
1891 :<Key>t: CallFlagProc() \n \
1892 :<Key>i: Iconify() \n \
1893 :<Key>c: Iconify() \n \
1894 :<Key>v: FlipViewProc() \n \
1895 <KeyDown>Control_L: BackwardProc() \n \
1896 <KeyUp>Control_L: ForwardProc() \n \
1897 <KeyDown>Control_R: BackwardProc() \n \
1898 <KeyUp>Control_R: ForwardProc() \n \
1899 Shift<Key>1: AskQuestionProc(\"Direct command\",\
1900 \"Send to chess program:\",,1) \n \
1901 Shift<Key>2: AskQuestionProc(\"Direct command\",\
1902 \"Send to second chess program:\",,2) \n";
1904 char boardTranslations[] =
1905 "<Btn1Down>: HandleUserMove() \n \
1906 <Btn1Up>: HandleUserMove() \n \
1907 <Btn1Motion>: AnimateUserMove() \n \
1908 Shift<Btn2Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD)\
1909 PieceMenuPopup(menuB) \n \
1910 Any<Btn2Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD) \
1911 PieceMenuPopup(menuW) \n \
1912 Shift<Btn3Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD)\
1913 PieceMenuPopup(menuW) \n \
1914 Any<Btn3Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD) \
1915 PieceMenuPopup(menuB) \n";
1917 char whiteTranslations[] = "<BtnDown>: WhiteClock()\n";
1918 char blackTranslations[] = "<BtnDown>: BlackClock()\n";
1920 char ICSInputTranslations[] =
1921 "<Key>Return: EnterKeyProc() \n";
1923 String xboardResources[] = {
1924 "*fileName*value.translations: #override\\n <Key>Return: FileNameAction()",
1925 "*question*value.translations: #override\\n <Key>Return: AskQuestionReplyAction()",
1926 "*errorpopup*translations: #override\\n <Key>Return: ErrorPopDown()",
1931 /* Max possible square size */
1932 #define MAXSQSIZE 256
1934 static int xpm_avail[MAXSQSIZE];
1936 #ifdef HAVE_DIR_STRUCT
1938 /* Extract piece size from filename */
1940 xpm_getsize(name, len, ext)
1951 if ((p=strchr(name, '.')) == NULL ||
1952 StrCaseCmp(p+1, ext) != 0)
1958 while (*p && isdigit(*p))
1965 /* Setup xpm_avail */
1967 xpm_getavail(dirname, ext)
1975 for (i=0; i<MAXSQSIZE; ++i)
1978 if (appData.debugMode)
1979 fprintf(stderr, "XPM dir:%s:ext:%s:\n", dirname, ext);
1981 dir = opendir(dirname);
1984 fprintf(stderr, _("%s: Can't access XPM directory %s\n"),
1985 programName, dirname);
1989 while ((ent=readdir(dir)) != NULL) {
1990 i = xpm_getsize(ent->d_name, NAMLEN(ent), ext);
1991 if (i > 0 && i < MAXSQSIZE)
2001 xpm_print_avail(fp, ext)
2007 fprintf(fp, _("Available `%s' sizes:\n"), ext);
2008 for (i=1; i<MAXSQSIZE; ++i) {
2014 /* Return XPM piecesize closest to size */
2016 xpm_closest_to(dirname, size, ext)
2022 int sm_diff = MAXSQSIZE;
2026 xpm_getavail(dirname, ext);
2028 if (appData.debugMode)
2029 xpm_print_avail(stderr, ext);
2031 for (i=1; i<MAXSQSIZE; ++i) {
2034 diff = (diff<0) ? -diff : diff;
2035 if (diff < sm_diff) {
2043 fprintf(stderr, _("Error: No `%s' files!\n"), ext);
2049 #else /* !HAVE_DIR_STRUCT */
2050 /* If we are on a system without a DIR struct, we can't
2051 read the directory, so we can't collect a list of
2052 filenames, etc., so we can't do any size-fitting. */
2054 xpm_closest_to(dirname, size, ext)
2059 fprintf(stderr, _("\
2060 Warning: No DIR structure found on this system --\n\
2061 Unable to autosize for XPM/XIM pieces.\n\
2062 Please report this error to frankm@hiwaay.net.\n\
2063 Include system type & operating system in message.\n"));
2066 #endif /* HAVE_DIR_STRUCT */
2068 static char *cnames[9] = { "black", "red", "green", "yellow", "blue",
2069 "magenta", "cyan", "white" };
2073 TextColors textColors[(int)NColorClasses];
2075 /* String is: "fg, bg, attr". Which is 0, 1, 2 */
2077 parse_color(str, which)
2081 char *p, buf[100], *d;
2084 if (strlen(str) > 99) /* watch bounds on buf */
2089 for (i=0; i<which; ++i) {
2096 /* Could be looking at something like:
2098 .. in which case we want to stop on a comma also */
2099 while (*p && *p != ',' && !isalpha(*p) && !isdigit(*p))
2103 return -1; /* Use default for empty field */
2106 if (which == 2 || isdigit(*p))
2109 while (*p && isalpha(*p))
2114 for (i=0; i<8; ++i) {
2115 if (!StrCaseCmp(buf, cnames[i]))
2116 return which? (i+40) : (i+30);
2118 if (!StrCaseCmp(buf, "default")) return -1;
2120 fprintf(stderr, _("%s: unrecognized color %s\n"), programName, buf);
2125 parse_cpair(cc, str)
2129 if ((textColors[(int)cc].fg=parse_color(str, 0)) == -2) {
2130 fprintf(stderr, _("%s: can't parse foreground color in `%s'\n"),
2135 /* bg and attr are optional */
2136 textColors[(int)cc].bg = parse_color(str, 1);
2137 if ((textColors[(int)cc].attr = parse_color(str, 2)) < 0) {
2138 textColors[(int)cc].attr = 0;
2144 /* Arrange to catch delete-window events */
2145 Atom wm_delete_window;
2147 CatchDeleteWindow(Widget w, String procname)
2150 XSetWMProtocols(xDisplay, XtWindow(w), &wm_delete_window, 1);
2151 sprintf(buf, "<Message>WM_PROTOCOLS: %s() \n", procname);
2152 XtAugmentTranslations(w, XtParseTranslationTable(buf));
2159 XtSetArg(args[0], XtNiconic, False);
2160 XtSetValues(shellWidget, args, 1);
2162 XtPopup(shellWidget, XtGrabNone); /* Raise if lowered */
2166 // eventually, all layout determining code should go into a subroutine, but until then IDSIZE remains undefined
2168 #define BoardSize int
2169 void InitDrawingSizes(BoardSize boardSize, int flags)
2170 { // [HGM] resize is functional now, but for board format changes only (nr of ranks, files)
2171 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
2173 XtGeometryResult gres;
2176 if(!formWidget) return;
2179 * Enable shell resizing.
2181 shellArgs[0].value = (XtArgVal) &w;
2182 shellArgs[1].value = (XtArgVal) &h;
2183 XtGetValues(shellWidget, shellArgs, 2);
2185 shellArgs[4].value = 2*w; shellArgs[2].value = 10;
2186 shellArgs[5].value = 2*h; shellArgs[3].value = 10;
2187 XtSetValues(shellWidget, &shellArgs[2], 4);
2189 XtSetArg(args[0], XtNdefaultDistance, &sep);
2190 XtGetValues(formWidget, args, 1);
2192 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2193 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2196 XtSetArg(args[0], XtNwidth, boardWidth);
2197 XtSetArg(args[1], XtNheight, boardHeight);
2198 XtSetValues(boardWidget, args, 2);
2200 timerWidth = (boardWidth - sep) / 2;
2201 XtSetArg(args[0], XtNwidth, timerWidth);
2202 XtSetValues(whiteTimerWidget, args, 1);
2203 XtSetValues(blackTimerWidget, args, 1);
2205 XawFormDoLayout(formWidget, False);
2207 if (appData.titleInWindow) {
2209 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2210 XtSetArg(args[i], XtNheight, &h); i++;
2211 XtGetValues(titleWidget, args, i);
2213 w = boardWidth - 2*bor;
2215 XtSetArg(args[0], XtNwidth, &w);
2216 XtGetValues(menuBarWidget, args, 1);
2217 w = boardWidth - w - sep - 2*bor - 2; // WIDTH_FUDGE
2220 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
2221 if (gres != XtGeometryYes && appData.debugMode) {
2223 _("%s: titleWidget geometry error %d %d %d %d %d\n"),
2224 programName, gres, w, h, wr, hr);
2228 XawFormDoLayout(formWidget, True);
2231 * Inhibit shell resizing.
2233 shellArgs[0].value = w = (XtArgVal) boardWidth + marginW;
2234 shellArgs[1].value = h = (XtArgVal) boardHeight + marginH;
2235 shellArgs[4].value = shellArgs[2].value = w;
2236 shellArgs[5].value = shellArgs[3].value = h;
2237 XtSetValues(shellWidget, &shellArgs[0], 6);
2246 int i, j, clockFontPxlSize, coordFontPxlSize, fontPxlSize;
2247 XSetWindowAttributes window_attributes;
2249 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
2250 XrmValue vFrom, vTo;
2251 XtGeometryResult gres;
2254 int forceMono = False;
2257 // [HGM] before anything else, expand any indirection files amongst options
2258 char *argvCopy[1000]; // 1000 seems enough
2259 char newArgs[10000]; // holds actual characters
2262 srandom(time(0)); // [HGM] book: make random truly random
2265 for(i=0; i<argc; i++) {
2266 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2267 //fprintf(stderr, "arg %s\n", argv[i]);
2268 if(argv[i][0] != '@') argvCopy[j++] = argv[i]; else {
2270 FILE *f = fopen(argv[i]+1, "rb");
2271 if(f == NULL) { fprintf(stderr, _("ignore %s\n"), argv[i]); continue; } // do not expand non-existing
2272 argvCopy[j++] = newArgs + k; // get ready for first argument from file
2273 while((c = fgetc(f)) != EOF) { // each line of file inserts 1 argument in the list
2275 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2276 newArgs[k++] = 0; // terminate current arg
2277 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2278 argvCopy[j++] = newArgs + k; // get ready for next
2280 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2293 if(appData.debugMode,1) { // OK, appData is not initialized here yet...
2294 for(i=0; i<argc; i++) fprintf(stderr, "argv[%2d] = '%s'\n", i, argv[i]);
2300 setbuf(stdout, NULL);
2301 setbuf(stderr, NULL);
2304 programName = strrchr(argv[0], '/');
2305 if (programName == NULL)
2306 programName = argv[0];
2311 XtSetLanguageProc(NULL, NULL, NULL);
2312 bindtextdomain(PRODUCT, LOCALEDIR);
2313 textdomain(PRODUCT);
2317 XtAppInitialize(&appContext, "XBoard", shellOptions,
2318 XtNumber(shellOptions),
2319 &argc, argv, xboardResources, NULL, 0);
2321 fprintf(stderr, _("%s: unrecognized argument %s\n"),
2322 programName, argv[1]);
2326 if ((chessDir = (char *) getenv("CHESSDIR")) == NULL) {
2329 if (chdir(chessDir) != 0) {
2330 fprintf(stderr, _("%s: can't cd to CHESSDIR: "), programName);
2337 if (p == NULL) p = "/tmp";
2338 i = strlen(p) + strlen("/.xboardXXXXXx.pgn") + 1;
2339 gameCopyFilename = (char*) malloc(i);
2340 gamePasteFilename = (char*) malloc(i);
2341 sprintf(gameCopyFilename, "%s/.xboard%05uc.pgn", p, getpid());
2342 sprintf(gamePasteFilename, "%s/.xboard%05up.pgn", p, getpid());
2344 XtGetApplicationResources(shellWidget, (XtPointer) &appData,
2345 clientResources, XtNumber(clientResources),
2348 if (appData.debugMode && appData.nameOfDebugFile && strcmp(appData.nameOfDebugFile, "stderr")) {
2349 /* [DM] debug info to file [HGM] make the filename a command-line option, and allow it to remain stderr */
2350 if ((debugFP = fopen(appData.nameOfDebugFile, "w")) == NULL) {
2351 printf(_("Failed to open file '%s'\n"), appData.nameOfDebugFile);
2354 setbuf(debugFP, NULL);
2357 /* [HGM,HR] make sure board size is acceptable */
2358 if(appData.NrFiles > BOARD_SIZE ||
2359 appData.NrRanks > BOARD_SIZE )
2360 DisplayFatalError(_("Recompile with BOARD_SIZE > 12, to support this size"), 0, 2);
2363 /* This feature does not work; animation needs a rewrite */
2364 appData.highlightDragging = FALSE;
2368 xDisplay = XtDisplay(shellWidget);
2369 xScreen = DefaultScreen(xDisplay);
2370 wm_delete_window = XInternAtom(xDisplay, "WM_DELETE_WINDOW", True);
2372 gameInfo.variant = StringToVariant(appData.variant);
2373 InitPosition(FALSE);
2376 * Determine boardSize
2378 gameInfo.boardWidth = gameInfo.boardHeight = 8; // [HGM] boardsize: make sure we start as 8x8
2381 // [HGM] as long as we have not created the possibility to change size while running, start with requested size
2382 gameInfo.boardWidth = appData.NrFiles > 0 ? appData.NrFiles : 8;
2383 gameInfo.boardHeight = appData.NrRanks > 0 ? appData.NrRanks : 8;
2384 gameInfo.holdingsWidth = appData.holdingsSize > 0 ? 2 : 0;
2389 InitDrawingSizes(-1, 0); // [HGM] initsize: make this into a subroutine
2391 if (isdigit(appData.boardSize[0])) {
2392 i = sscanf(appData.boardSize, "%d,%d,%d,%d,%d,%d,%d", &squareSize,
2393 &lineGap, &clockFontPxlSize, &coordFontPxlSize,
2394 &fontPxlSize, &smallLayout, &tinyLayout);
2396 fprintf(stderr, _("%s: bad boardSize syntax %s\n"),
2397 programName, appData.boardSize);
2401 /* Find some defaults; use the nearest known size */
2402 SizeDefaults *szd, *nearest;
2403 int distance = 99999;
2404 nearest = szd = sizeDefaults;
2405 while (szd->name != NULL) {
2406 if (abs(szd->squareSize - squareSize) < distance) {
2408 distance = abs(szd->squareSize - squareSize);
2409 if (distance == 0) break;
2413 if (i < 2) lineGap = nearest->lineGap;
2414 if (i < 3) clockFontPxlSize = nearest->clockFontPxlSize;
2415 if (i < 4) coordFontPxlSize = nearest->coordFontPxlSize;
2416 if (i < 5) fontPxlSize = nearest->fontPxlSize;
2417 if (i < 6) smallLayout = nearest->smallLayout;
2418 if (i < 7) tinyLayout = nearest->tinyLayout;
2421 SizeDefaults *szd = sizeDefaults;
2422 if (*appData.boardSize == NULLCHAR) {
2423 while (DisplayWidth(xDisplay, xScreen) < szd->minScreenSize ||
2424 DisplayHeight(xDisplay, xScreen) < szd->minScreenSize) {
2427 if (szd->name == NULL) szd--;
2429 while (szd->name != NULL &&
2430 StrCaseCmp(szd->name, appData.boardSize) != 0) szd++;
2431 if (szd->name == NULL) {
2432 fprintf(stderr, _("%s: unrecognized boardSize name %s\n"),
2433 programName, appData.boardSize);
2437 squareSize = szd->squareSize;
2438 lineGap = szd->lineGap;
2439 clockFontPxlSize = szd->clockFontPxlSize;
2440 coordFontPxlSize = szd->coordFontPxlSize;
2441 fontPxlSize = szd->fontPxlSize;
2442 smallLayout = szd->smallLayout;
2443 tinyLayout = szd->tinyLayout;
2446 /* Now, using squareSize as a hint, find a good XPM/XIM set size */
2447 if (strlen(appData.pixmapDirectory) > 0) {
2448 p = ExpandPathName(appData.pixmapDirectory);
2450 fprintf(stderr, _("Error expanding path name \"%s\"\n"),
2451 appData.pixmapDirectory);
2454 if (appData.debugMode) {
2455 fprintf(stderr, _("\
2456 XBoard square size (hint): %d\n\
2457 %s fulldir:%s:\n"), squareSize, IMAGE_EXT, p);
2459 squareSize = xpm_closest_to(p, squareSize, IMAGE_EXT);
2460 if (appData.debugMode) {
2461 fprintf(stderr, _("Closest %s size: %d\n"), IMAGE_EXT, squareSize);
2465 /* [HR] height treated separately (hacked) */
2466 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2467 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2468 if (appData.showJail == 1) {
2469 /* Jail on top and bottom */
2470 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2471 XtSetArg(boardArgs[2], XtNheight,
2472 boardHeight + 2*(lineGap + squareSize));
2473 } else if (appData.showJail == 2) {
2475 XtSetArg(boardArgs[1], XtNwidth,
2476 boardWidth + 2*(lineGap + squareSize));
2477 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2480 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2481 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2485 * Determine what fonts to use.
2487 appData.clockFont = FindFont(appData.clockFont, clockFontPxlSize);
2488 clockFontID = XLoadFont(xDisplay, appData.clockFont);
2489 clockFontStruct = XQueryFont(xDisplay, clockFontID);
2490 appData.coordFont = FindFont(appData.coordFont, coordFontPxlSize);
2491 coordFontID = XLoadFont(xDisplay, appData.coordFont);
2492 coordFontStruct = XQueryFont(xDisplay, coordFontID);
2493 appData.font = FindFont(appData.font, fontPxlSize);
2494 countFontID = XLoadFont(xDisplay, appData.coordFont); // [HGM] holdings
2495 countFontStruct = XQueryFont(xDisplay, countFontID);
2496 // appData.font = FindFont(appData.font, fontPxlSize);
2498 xdb = XtDatabase(xDisplay);
2499 XrmPutStringResource(&xdb, "*font", appData.font);
2502 * Detect if there are not enough colors available and adapt.
2504 if (DefaultDepth(xDisplay, xScreen) <= 2) {
2505 appData.monoMode = True;
2508 if (!appData.monoMode) {
2509 vFrom.addr = (caddr_t) appData.lightSquareColor;
2510 vFrom.size = strlen(appData.lightSquareColor);
2511 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2512 if (vTo.addr == NULL) {
2513 appData.monoMode = True;
2516 lightSquareColor = *(Pixel *) vTo.addr;
2519 if (!appData.monoMode) {
2520 vFrom.addr = (caddr_t) appData.darkSquareColor;
2521 vFrom.size = strlen(appData.darkSquareColor);
2522 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2523 if (vTo.addr == NULL) {
2524 appData.monoMode = True;
2527 darkSquareColor = *(Pixel *) vTo.addr;
2530 if (!appData.monoMode) {
2531 vFrom.addr = (caddr_t) appData.whitePieceColor;
2532 vFrom.size = strlen(appData.whitePieceColor);
2533 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2534 if (vTo.addr == NULL) {
2535 appData.monoMode = True;
2538 whitePieceColor = *(Pixel *) vTo.addr;
2541 if (!appData.monoMode) {
2542 vFrom.addr = (caddr_t) appData.blackPieceColor;
2543 vFrom.size = strlen(appData.blackPieceColor);
2544 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2545 if (vTo.addr == NULL) {
2546 appData.monoMode = True;
2549 blackPieceColor = *(Pixel *) vTo.addr;
2553 if (!appData.monoMode) {
2554 vFrom.addr = (caddr_t) appData.highlightSquareColor;
2555 vFrom.size = strlen(appData.highlightSquareColor);
2556 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2557 if (vTo.addr == NULL) {
2558 appData.monoMode = True;
2561 highlightSquareColor = *(Pixel *) vTo.addr;
2565 if (!appData.monoMode) {
2566 vFrom.addr = (caddr_t) appData.premoveHighlightColor;
2567 vFrom.size = strlen(appData.premoveHighlightColor);
2568 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2569 if (vTo.addr == NULL) {
2570 appData.monoMode = True;
2573 premoveHighlightColor = *(Pixel *) vTo.addr;
2578 fprintf(stderr, _("%s: too few colors available; trying monochrome mode\n"),
2582 if (appData.monoMode && appData.debugMode) {
2583 fprintf(stderr, _("white pixel = 0x%lx, black pixel = 0x%lx\n"),
2584 (unsigned long) XWhitePixel(xDisplay, xScreen),
2585 (unsigned long) XBlackPixel(xDisplay, xScreen));
2588 if (parse_cpair(ColorShout, appData.colorShout) < 0 ||
2589 parse_cpair(ColorSShout, appData.colorSShout) < 0 ||
2590 parse_cpair(ColorChannel1, appData.colorChannel1) < 0 ||
2591 parse_cpair(ColorChannel, appData.colorChannel) < 0 ||
2592 parse_cpair(ColorKibitz, appData.colorKibitz) < 0 ||
2593 parse_cpair(ColorTell, appData.colorTell) < 0 ||
2594 parse_cpair(ColorChallenge, appData.colorChallenge) < 0 ||
2595 parse_cpair(ColorRequest, appData.colorRequest) < 0 ||
2596 parse_cpair(ColorSeek, appData.colorSeek) < 0 ||
2597 parse_cpair(ColorNormal, appData.colorNormal) < 0)
2599 if (appData.colorize) {
2601 _("%s: can't parse color names; disabling colorization\n"),
2604 appData.colorize = FALSE;
2606 textColors[ColorNone].fg = textColors[ColorNone].bg = -1;
2607 textColors[ColorNone].attr = 0;
2609 XtAppAddActions(appContext, boardActions, XtNumber(boardActions));
2615 layoutName = "tinyLayout";
2616 } else if (smallLayout) {
2617 layoutName = "smallLayout";
2619 layoutName = "normalLayout";
2621 /* Outer layoutWidget is there only to provide a name for use in
2622 resources that depend on the layout style */
2624 XtCreateManagedWidget(layoutName, formWidgetClass, shellWidget,
2625 layoutArgs, XtNumber(layoutArgs));
2627 XtCreateManagedWidget("form", formWidgetClass, layoutWidget,
2628 formArgs, XtNumber(formArgs));
2629 XtSetArg(args[0], XtNdefaultDistance, &sep);
2630 XtGetValues(formWidget, args, 1);
2633 widgetList[j++] = menuBarWidget = CreateMenuBar(menuBar);
2634 XtSetArg(args[0], XtNtop, XtChainTop);
2635 XtSetArg(args[1], XtNbottom, XtChainTop);
2636 XtSetValues(menuBarWidget, args, 2);
2638 widgetList[j++] = whiteTimerWidget =
2639 XtCreateWidget("whiteTime", labelWidgetClass,
2640 formWidget, timerArgs, XtNumber(timerArgs));
2641 XtSetArg(args[0], XtNfont, clockFontStruct);
2642 XtSetArg(args[1], XtNtop, XtChainTop);
2643 XtSetArg(args[2], XtNbottom, XtChainTop);
2644 XtSetValues(whiteTimerWidget, args, 3);
2646 widgetList[j++] = blackTimerWidget =
2647 XtCreateWidget("blackTime", labelWidgetClass,
2648 formWidget, timerArgs, XtNumber(timerArgs));
2649 XtSetArg(args[0], XtNfont, clockFontStruct);
2650 XtSetArg(args[1], XtNtop, XtChainTop);
2651 XtSetArg(args[2], XtNbottom, XtChainTop);
2652 XtSetValues(blackTimerWidget, args, 3);
2654 if (appData.titleInWindow) {
2655 widgetList[j++] = titleWidget =
2656 XtCreateWidget("title", labelWidgetClass, formWidget,
2657 titleArgs, XtNumber(titleArgs));
2658 XtSetArg(args[0], XtNtop, XtChainTop);
2659 XtSetArg(args[1], XtNbottom, XtChainTop);
2660 XtSetValues(titleWidget, args, 2);
2663 if (appData.showButtonBar) {
2664 widgetList[j++] = buttonBarWidget = CreateButtonBar(buttonBar);
2665 XtSetArg(args[0], XtNleft, XtChainRight); // [HGM] glue to right window edge
2666 XtSetArg(args[1], XtNright, XtChainRight); // for good run-time sizing
2667 XtSetArg(args[2], XtNtop, XtChainTop);
2668 XtSetArg(args[3], XtNbottom, XtChainTop);
2669 XtSetValues(buttonBarWidget, args, 4);
2672 widgetList[j++] = messageWidget =
2673 XtCreateWidget("message", labelWidgetClass, formWidget,
2674 messageArgs, XtNumber(messageArgs));
2675 XtSetArg(args[0], XtNtop, XtChainTop);
2676 XtSetArg(args[1], XtNbottom, XtChainTop);
2677 XtSetValues(messageWidget, args, 2);
2679 widgetList[j++] = boardWidget =
2680 XtCreateWidget("board", widgetClass, formWidget, boardArgs,
2681 XtNumber(boardArgs));
2683 XtManageChildren(widgetList, j);
2685 timerWidth = (boardWidth - sep) / 2;
2686 XtSetArg(args[0], XtNwidth, timerWidth);
2687 XtSetValues(whiteTimerWidget, args, 1);
2688 XtSetValues(blackTimerWidget, args, 1);
2690 XtSetArg(args[0], XtNbackground, &timerBackgroundPixel);
2691 XtSetArg(args[1], XtNforeground, &timerForegroundPixel);
2692 XtGetValues(whiteTimerWidget, args, 2);
2694 if (appData.showButtonBar) {
2695 XtSetArg(args[0], XtNbackground, &buttonBackgroundPixel);
2696 XtSetArg(args[1], XtNforeground, &buttonForegroundPixel);
2697 XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
2701 * formWidget uses these constraints but they are stored
2705 XtSetArg(args[i], XtNfromHoriz, 0); i++;
2706 XtSetValues(menuBarWidget, args, i);
2707 if (appData.titleInWindow) {
2710 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2711 XtSetValues(whiteTimerWidget, args, i);
2713 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2714 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2715 XtSetValues(blackTimerWidget, args, i);
2717 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2718 XtSetArg(args[i], XtNjustify, XtJustifyLeft); i++;
2719 XtSetValues(titleWidget, args, i);
2721 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2722 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2723 XtSetValues(messageWidget, args, i);
2724 if (appData.showButtonBar) {
2726 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2727 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2728 XtSetValues(buttonBarWidget, args, i);
2732 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2733 XtSetValues(whiteTimerWidget, args, i);
2735 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2736 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2737 XtSetValues(blackTimerWidget, args, i);
2739 XtSetArg(args[i], XtNfromHoriz, menuBarWidget); i++;
2740 XtSetValues(titleWidget, args, i);
2742 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2743 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2744 XtSetValues(messageWidget, args, i);
2745 if (appData.showButtonBar) {
2747 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2748 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2749 XtSetValues(buttonBarWidget, args, i);
2754 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2755 XtSetValues(whiteTimerWidget, args, i);
2757 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2758 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2759 XtSetValues(blackTimerWidget, args, i);
2761 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2762 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2763 XtSetValues(messageWidget, args, i);
2764 if (appData.showButtonBar) {
2766 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2767 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2768 XtSetValues(buttonBarWidget, args, i);
2772 XtSetArg(args[0], XtNfromVert, messageWidget);
2773 XtSetArg(args[1], XtNtop, XtChainTop);
2774 XtSetArg(args[2], XtNbottom, XtChainBottom);
2775 XtSetArg(args[3], XtNleft, XtChainLeft);
2776 XtSetArg(args[4], XtNright, XtChainRight);
2777 XtSetValues(boardWidget, args, 5);
2779 XtRealizeWidget(shellWidget);
2782 * Correct the width of the message and title widgets.
2783 * It is not known why some systems need the extra fudge term.
2784 * The value "2" is probably larger than needed.
2786 XawFormDoLayout(formWidget, False);
2788 #define WIDTH_FUDGE 2
2790 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2791 XtSetArg(args[i], XtNheight, &h); i++;
2792 XtGetValues(messageWidget, args, i);
2793 if (appData.showButtonBar) {
2795 XtSetArg(args[i], XtNwidth, &w); i++;
2796 XtGetValues(buttonBarWidget, args, i);
2797 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2799 w = boardWidth - 2*bor + 1; /*!! +1 compensates for kludge below */
2802 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2803 if (gres != XtGeometryYes && appData.debugMode) {
2804 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2805 programName, gres, w, h, wr, hr);
2808 /* !! Horrible hack to work around bug in XFree86 4.0.1 (X11R6.4.3) */
2809 /* The size used for the child widget in layout lags one resize behind
2810 its true size, so we resize a second time, 1 pixel smaller. Yeech! */
2812 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2813 if (gres != XtGeometryYes && appData.debugMode) {
2814 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2815 programName, gres, w, h, wr, hr);
2818 XtSetArg(args[0], XtNleft, XtChainLeft); // [HGM] glue ends for good run-time sizing
2819 XtSetArg(args[1], XtNright, XtChainRight);
2820 XtSetValues(messageWidget, args, 2);
2822 if (appData.titleInWindow) {
2824 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2825 XtSetArg(args[i], XtNheight, &h); i++;
2826 XtGetValues(titleWidget, args, i);
2828 w = boardWidth - 2*bor;
2830 XtSetArg(args[0], XtNwidth, &w);
2831 XtGetValues(menuBarWidget, args, 1);
2832 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2835 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
2836 if (gres != XtGeometryYes && appData.debugMode) {
2838 _("%s: titleWidget geometry error %d %d %d %d %d\n"),
2839 programName, gres, w, h, wr, hr);
2842 XawFormDoLayout(formWidget, True);
2844 xBoardWindow = XtWindow(boardWidget);
2846 // [HGM] it seems the layout code ends here, but perhaps the color stuff is size independent and would
2847 // not need to go into InitDrawingSizes().
2851 * Create X checkmark bitmap and initialize option menu checks.
2853 ReadBitmap(&xMarkPixmap, "checkmark.bm",
2854 checkmark_bits, checkmark_width, checkmark_height);
2855 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
2856 if (appData.alwaysPromoteToQueen) {
2857 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
2860 if (appData.animateDragging) {
2861 XtSetValues(XtNameToWidget(menuBarWidget,
2862 "menuOptions.Animate Dragging"),
2865 if (appData.animate) {
2866 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
2869 if (appData.autoComment) {
2870 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
2873 if (appData.autoCallFlag) {
2874 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
2877 if (appData.autoFlipView) {
2878 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Auto Flip View"),
2881 if (appData.autoObserve) {
2882 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
2885 if (appData.autoRaiseBoard) {
2886 XtSetValues(XtNameToWidget(menuBarWidget,
2887 "menuOptions.Auto Raise Board"), args, 1);
2889 if (appData.autoSaveGames) {
2890 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
2893 if (appData.saveGameFile[0] != NULLCHAR) {
2894 /* Can't turn this off from menu */
2895 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
2897 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
2901 if (appData.blindfold) {
2902 XtSetValues(XtNameToWidget(menuBarWidget,
2903 "menuOptions.Blindfold"), args, 1);
2905 if (appData.flashCount > 0) {
2906 XtSetValues(XtNameToWidget(menuBarWidget,
2907 "menuOptions.Flash Moves"),
2910 if (appData.getMoveList) {
2911 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
2915 if (appData.highlightDragging) {
2916 XtSetValues(XtNameToWidget(menuBarWidget,
2917 "menuOptions.Highlight Dragging"),
2921 if (appData.highlightLastMove) {
2922 XtSetValues(XtNameToWidget(menuBarWidget,
2923 "menuOptions.Highlight Last Move"),
2926 if (appData.icsAlarm) {
2927 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.ICS Alarm"),
2930 if (appData.ringBellAfterMoves) {
2931 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
2934 if (appData.oldSaveStyle) {
2935 XtSetValues(XtNameToWidget(menuBarWidget,
2936 "menuOptions.Old Save Style"), args, 1);
2938 if (appData.periodicUpdates) {
2939 XtSetValues(XtNameToWidget(menuBarWidget,
2940 "menuOptions.Periodic Updates"), args, 1);
2942 if (appData.ponderNextMove) {
2943 XtSetValues(XtNameToWidget(menuBarWidget,
2944 "menuOptions.Ponder Next Move"), args, 1);
2946 if (appData.popupExitMessage) {
2947 XtSetValues(XtNameToWidget(menuBarWidget,
2948 "menuOptions.Popup Exit Message"), args, 1);
2950 if (appData.popupMoveErrors) {
2951 XtSetValues(XtNameToWidget(menuBarWidget,
2952 "menuOptions.Popup Move Errors"), args, 1);
2954 if (appData.premove) {
2955 XtSetValues(XtNameToWidget(menuBarWidget,
2956 "menuOptions.Premove"), args, 1);
2958 if (appData.quietPlay) {
2959 XtSetValues(XtNameToWidget(menuBarWidget,
2960 "menuOptions.Quiet Play"), args, 1);
2962 if (appData.showCoords) {
2963 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
2966 if (appData.hideThinkingFromHuman) {
2967 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
2970 if (appData.testLegality) {
2971 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Test Legality"),
2978 ReadBitmap(&wIconPixmap, "icon_white.bm",
2979 icon_white_bits, icon_white_width, icon_white_height);
2980 ReadBitmap(&bIconPixmap, "icon_black.bm",
2981 icon_black_bits, icon_black_width, icon_black_height);
2982 iconPixmap = wIconPixmap;
2984 XtSetArg(args[i], XtNiconPixmap, iconPixmap); i++;
2985 XtSetValues(shellWidget, args, i);
2988 * Create a cursor for the board widget.
2990 window_attributes.cursor = XCreateFontCursor(xDisplay, XC_hand2);
2991 XChangeWindowAttributes(xDisplay, xBoardWindow,
2992 CWCursor, &window_attributes);
2995 * Inhibit shell resizing.
2997 shellArgs[0].value = (XtArgVal) &w;
2998 shellArgs[1].value = (XtArgVal) &h;
2999 XtGetValues(shellWidget, shellArgs, 2);
3000 shellArgs[4].value = shellArgs[2].value = w;
3001 shellArgs[5].value = shellArgs[3].value = h;
3002 XtSetValues(shellWidget, &shellArgs[2], 4);
3003 marginW = w - boardWidth; // [HGM] needed to set new shellWidget size when we resize board
3004 marginH = h - boardHeight;
3006 CatchDeleteWindow(shellWidget, "QuitProc");
3011 if (appData.bitmapDirectory[0] != NULLCHAR) {
3018 /* Create regular pieces */
3019 if (!useImages) CreatePieces();
3024 if (appData.animate || appData.animateDragging)
3027 XtAugmentTranslations(formWidget,
3028 XtParseTranslationTable(globalTranslations));
3029 XtAugmentTranslations(boardWidget,
3030 XtParseTranslationTable(boardTranslations));
3031 XtAugmentTranslations(whiteTimerWidget,
3032 XtParseTranslationTable(whiteTranslations));
3033 XtAugmentTranslations(blackTimerWidget,
3034 XtParseTranslationTable(blackTranslations));
3036 /* Why is the following needed on some versions of X instead
3037 * of a translation? */
3038 XtAddEventHandler(boardWidget, ExposureMask, False,
3039 (XtEventHandler) EventProc, NULL);
3044 if (errorExitStatus == -1) {
3045 if (appData.icsActive) {
3046 /* We now wait until we see "login:" from the ICS before
3047 sending the logon script (problems with timestamp otherwise) */
3048 /*ICSInitScript();*/
3049 if (appData.icsInputBox) ICSInputBoxPopUp();
3052 signal(SIGINT, IntSigHandler);
3053 signal(SIGTERM, IntSigHandler);
3054 if (*appData.cmailGameName != NULLCHAR) {
3055 signal(SIGUSR1, CmailSigHandler);
3060 XtAppMainLoop(appContext);
3061 if (appData.debugMode) fclose(debugFP); // [DM] debug
3068 if (appData.icsActive && oldICSInteractionTitle != NULL) {
3069 DisplayIcsInteractionTitle(oldICSInteractionTitle);
3071 unlink(gameCopyFilename);
3072 unlink(gamePasteFilename);
3083 CmailSigHandler(sig)
3089 signal(SIGUSR1, SIG_IGN); /* suspend handler */
3091 /* Activate call-back function CmailSigHandlerCallBack() */
3092 OutputToProcess(cmailPR, (char *)(&dummy), sizeof(int), &error);
3094 signal(SIGUSR1, CmailSigHandler); /* re-activate handler */
3098 CmailSigHandlerCallBack(isr, closure, message, count, error)
3106 ReloadCmailMsgEvent(TRUE); /* Reload cmail msg */
3108 /**** end signal code ****/
3118 f = fopen(appData.icsLogon, "r");
3124 strcat(buf, appData.icsLogon);
3125 f = fopen(buf, "r");
3129 ProcessICSInitScript(f);
3136 EditCommentPopDown();
3147 SetMenuEnables(enab)
3151 if (!menuBarWidget) return;
3152 while (enab->name != NULL) {
3153 w = XtNameToWidget(menuBarWidget, enab->name);
3155 DisplayError(enab->name, 0);
3157 XtSetSensitive(w, enab->value);
3163 Enables icsEnables[] = {
3164 { "menuFile.Mail Move", False },
3165 { "menuFile.Reload CMail Message", False },
3166 { "menuMode.Machine Black", False },
3167 { "menuMode.Machine White", False },
3168 { "menuMode.Analysis Mode", False },
3169 { "menuMode.Analyze File", False },
3170 { "menuMode.Two Machines", False },
3172 { "menuHelp.Hint", False },
3173 { "menuHelp.Book", False },
3174 { "menuStep.Move Now", False },
3175 { "menuOptions.Periodic Updates", False },
3176 { "menuOptions.Hide Thinking", False },
3177 { "menuOptions.Ponder Next Move", False },
3182 Enables ncpEnables[] = {
3183 { "menuFile.Mail Move", False },
3184 { "menuFile.Reload CMail Message", False },
3185 { "menuMode.Machine White", False },
3186 { "menuMode.Machine Black", False },
3187 { "menuMode.Analysis Mode", False },
3188 { "menuMode.Analyze File", False },
3189 { "menuMode.Two Machines", False },
3190 { "menuMode.ICS Client", False },
3191 { "menuMode.ICS Input Box", False },
3192 { "Action", False },
3193 { "menuStep.Revert", False },
3194 { "menuStep.Move Now", False },
3195 { "menuStep.Retract Move", False },
3196 { "menuOptions.Auto Comment", False },
3197 { "menuOptions.Auto Flag", False },
3198 { "menuOptions.Auto Flip View", False },
3199 { "menuOptions.Auto Observe", False },
3200 { "menuOptions.Auto Raise Board", False },
3201 { "menuOptions.Get Move List", False },
3202 { "menuOptions.ICS Alarm", False },
3203 { "menuOptions.Move Sound", False },
3204 { "menuOptions.Quiet Play", False },
3205 { "menuOptions.Hide Thinking", False },
3206 { "menuOptions.Periodic Updates", False },
3207 { "menuOptions.Ponder Next Move", False },
3208 { "menuHelp.Hint", False },
3209 { "menuHelp.Book", False },
3213 Enables gnuEnables[] = {
3214 { "menuMode.ICS Client", False },
3215 { "menuMode.ICS Input Box", False },
3216 { "menuAction.Accept", False },
3217 { "menuAction.Decline", False },
3218 { "menuAction.Rematch", False },
3219 { "menuAction.Adjourn", False },
3220 { "menuAction.Stop Examining", False },
3221 { "menuAction.Stop Observing", False },
3222 { "menuStep.Revert", False },
3223 { "menuOptions.Auto Comment", False },
3224 { "menuOptions.Auto Observe", False },
3225 { "menuOptions.Auto Raise Board", False },
3226 { "menuOptions.Get Move List", False },
3227 { "menuOptions.Premove", False },
3228 { "menuOptions.Quiet Play", False },
3230 /* The next two options rely on SetCmailMode being called *after* */
3231 /* SetGNUMode so that when GNU is being used to give hints these */
3232 /* menu options are still available */
3234 { "menuFile.Mail Move", False },
3235 { "menuFile.Reload CMail Message", False },
3239 Enables cmailEnables[] = {
3241 { "menuAction.Call Flag", False },
3242 { "menuAction.Draw", True },
3243 { "menuAction.Adjourn", False },
3244 { "menuAction.Abort", False },
3245 { "menuAction.Stop Observing", False },
3246 { "menuAction.Stop Examining", False },
3247 { "menuFile.Mail Move", True },
3248 { "menuFile.Reload CMail Message", True },
3252 Enables trainingOnEnables[] = {
3253 { "menuMode.Edit Comment", False },
3254 { "menuMode.Pause", False },
3255 { "menuStep.Forward", False },
3256 { "menuStep.Backward", False },
3257 { "menuStep.Forward to End", False },
3258 { "menuStep.Back to Start", False },
3259 { "menuStep.Move Now", False },
3260 { "menuStep.Truncate Game", False },
3264 Enables trainingOffEnables[] = {
3265 { "menuMode.Edit Comment", True },
3266 { "menuMode.Pause", True },
3267 { "menuStep.Forward", True },
3268 { "menuStep.Backward", True },
3269 { "menuStep.Forward to End", True },
3270 { "menuStep.Back to Start", True },
3271 { "menuStep.Move Now", True },
3272 { "menuStep.Truncate Game", True },
3276 Enables machineThinkingEnables[] = {
3277 { "menuFile.Load Game", False },
3278 { "menuFile.Load Next Game", False },
3279 { "menuFile.Load Previous Game", False },
3280 { "menuFile.Reload Same Game", False },
3281 { "menuFile.Paste Game", False },
3282 { "menuFile.Load Position", False },
3283 { "menuFile.Load Next Position", False },
3284 { "menuFile.Load Previous Position", False },
3285 { "menuFile.Reload Same Position", False },
3286 { "menuFile.Paste Position", False },
3287 { "menuMode.Machine White", False },
3288 { "menuMode.Machine Black", False },
3289 { "menuMode.Two Machines", False },
3290 { "menuStep.Retract Move", False },
3294 Enables userThinkingEnables[] = {
3295 { "menuFile.Load Game", True },
3296 { "menuFile.Load Next Game", True },
3297 { "menuFile.Load Previous Game", True },
3298 { "menuFile.Reload Same Game", True },
3299 { "menuFile.Paste Game", True },
3300 { "menuFile.Load Position", True },
3301 { "menuFile.Load Next Position", True },
3302 { "menuFile.Load Previous Position", True },
3303 { "menuFile.Reload Same Position", True },
3304 { "menuFile.Paste Position", True },
3305 { "menuMode.Machine White", True },
3306 { "menuMode.Machine Black", True },
3307 { "menuMode.Two Machines", True },
3308 { "menuStep.Retract Move", True },
3314 SetMenuEnables(icsEnables);
3317 if (appData.zippyPlay && !appData.noChessProgram) /* [DM] icsEngineAnalyze */
3318 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Analysis Mode"), True);
3325 SetMenuEnables(ncpEnables);
3331 SetMenuEnables(gnuEnables);
3337 SetMenuEnables(cmailEnables);
3343 SetMenuEnables(trainingOnEnables);
3344 if (appData.showButtonBar) {
3345 XtSetSensitive(buttonBarWidget, False);
3351 SetTrainingModeOff()
3353 SetMenuEnables(trainingOffEnables);
3354 if (appData.showButtonBar) {
3355 XtSetSensitive(buttonBarWidget, True);
3360 SetUserThinkingEnables()
3362 if (appData.noChessProgram) return;
3363 SetMenuEnables(userThinkingEnables);
3367 SetMachineThinkingEnables()
3369 if (appData.noChessProgram) return;
3370 SetMenuEnables(machineThinkingEnables);
3372 case MachinePlaysBlack:
3373 case MachinePlaysWhite:
3374 case TwoMachinesPlay:
3375 XtSetSensitive(XtNameToWidget(menuBarWidget,
3376 ModeToWidgetName(gameMode)), True);
3383 #define Abs(n) ((n)<0 ? -(n) : (n))
3386 * Find a font that matches "pattern" that is as close as
3387 * possible to the targetPxlSize. Prefer fonts that are k
3388 * pixels smaller to fonts that are k pixels larger. The
3389 * pattern must be in the X Consortium standard format,
3390 * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".
3391 * The return value should be freed with XtFree when no
3394 char *FindFont(pattern, targetPxlSize)
3398 char **fonts, *p, *best, *scalable, *scalableTail;
3399 int i, j, nfonts, minerr, err, pxlSize;
3402 char **missing_list;
3404 char *def_string, *base_fnt_lst, strInt[3];
3406 XFontStruct **fnt_list;
3408 base_fnt_lst = calloc(1, strlen(pattern) + 3);
3409 sprintf(strInt, "%d", targetPxlSize);
3410 p = strstr(pattern, "--");
3411 strncpy(base_fnt_lst, pattern, p - pattern + 2);
3412 strcat(base_fnt_lst, strInt);
3413 strcat(base_fnt_lst, strchr(p + 2, '-'));
3415 if ((fntSet = XCreateFontSet(xDisplay,
3419 &def_string)) == NULL) {
3421 fprintf(stderr, _("Unable to create font set.\n"));
3425 nfonts = XFontsOfFontSet(fntSet, &fnt_list, &fonts);
3427 fonts = XListFonts(xDisplay, pattern, 999999, &nfonts);
3429 fprintf(stderr, _("%s: no fonts match pattern %s\n"),
3430 programName, pattern);
3438 for (i=0; i<nfonts; i++) {
3441 if (*p != '-') continue;
3443 if (*p == NULLCHAR) break;
3444 if (*p++ == '-') j++;
3446 if (j < 7) continue;
3449 scalable = fonts[i];
3452 err = pxlSize - targetPxlSize;
3453 if (Abs(err) < Abs(minerr) ||
3454 (minerr > 0 && err < 0 && -err == minerr)) {
3460 if (scalable && Abs(minerr) > appData.fontSizeTolerance) {
3461 /* If the error is too big and there is a scalable font,
3462 use the scalable font. */
3463 int headlen = scalableTail - scalable;
3464 p = (char *) XtMalloc(strlen(scalable) + 10);
3465 while (isdigit(*scalableTail)) scalableTail++;
3466 sprintf(p, "%.*s%d%s", headlen, scalable, targetPxlSize, scalableTail);
3468 p = (char *) XtMalloc(strlen(best) + 1);
3471 if (appData.debugMode) {
3472 fprintf(debugFP, _("resolved %s at pixel size %d\n to %s\n"),
3473 pattern, targetPxlSize, p);
3476 if (missing_count > 0)
3477 XFreeStringList(missing_list);
3478 XFreeFontSet(xDisplay, fntSet);
3480 XFreeFontNames(fonts);
3487 XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
3488 | GCBackground | GCFunction | GCPlaneMask;
3489 XGCValues gc_values;
3492 gc_values.plane_mask = AllPlanes;
3493 gc_values.line_width = lineGap;
3494 gc_values.line_style = LineSolid;
3495 gc_values.function = GXcopy;
3497 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3498 gc_values.background = XBlackPixel(xDisplay, xScreen);
3499 lineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3501 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3502 gc_values.background = XWhitePixel(xDisplay, xScreen);
3503 coordGC = XtGetGC(shellWidget, value_mask, &gc_values);
3504 XSetFont(xDisplay, coordGC, coordFontID);
3506 // [HGM] make font for holdings counts (white on black0
3507 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3508 gc_values.background = XBlackPixel(xDisplay, xScreen);
3509 countGC = XtGetGC(shellWidget, value_mask, &gc_values);
3510 XSetFont(xDisplay, countGC, countFontID);
3512 if (appData.monoMode) {
3513 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3514 gc_values.background = XWhitePixel(xDisplay, xScreen);
3515 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3517 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3518 gc_values.background = XBlackPixel(xDisplay, xScreen);
3519 lightSquareGC = wbPieceGC
3520 = XtGetGC(shellWidget, value_mask, &gc_values);
3522 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3523 gc_values.background = XWhitePixel(xDisplay, xScreen);
3524 darkSquareGC = bwPieceGC
3525 = XtGetGC(shellWidget, value_mask, &gc_values);
3527 if (DefaultDepth(xDisplay, xScreen) == 1) {
3528 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
3529 gc_values.function = GXcopyInverted;
3530 copyInvertedGC = XtGetGC(shellWidget, value_mask, &gc_values);
3531 gc_values.function = GXcopy;
3532 if (XBlackPixel(xDisplay, xScreen) == 1) {
3533 bwPieceGC = darkSquareGC;
3534 wbPieceGC = copyInvertedGC;
3536 bwPieceGC = copyInvertedGC;
3537 wbPieceGC = lightSquareGC;
3541 gc_values.foreground = highlightSquareColor;
3542 gc_values.background = highlightSquareColor;
3543 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3545 gc_values.foreground = premoveHighlightColor;
3546 gc_values.background = premoveHighlightColor;
3547 prelineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3549 gc_values.foreground = lightSquareColor;
3550 gc_values.background = darkSquareColor;
3551 lightSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3553 gc_values.foreground = darkSquareColor;
3554 gc_values.background = lightSquareColor;
3555 darkSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3557 gc_values.foreground = jailSquareColor;
3558 gc_values.background = jailSquareColor;
3559 jailSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3561 gc_values.foreground = whitePieceColor;
3562 gc_values.background = darkSquareColor;
3563 wdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3565 gc_values.foreground = whitePieceColor;
3566 gc_values.background = lightSquareColor;
3567 wlPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3569 gc_values.foreground = whitePieceColor;
3570 gc_values.background = jailSquareColor;
3571 wjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3573 gc_values.foreground = blackPieceColor;
3574 gc_values.background = darkSquareColor;
3575 bdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3577 gc_values.foreground = blackPieceColor;
3578 gc_values.background = lightSquareColor;
3579 blPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3581 gc_values.foreground = blackPieceColor;
3582 gc_values.background = jailSquareColor;
3583 bjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3587 void loadXIM(xim, xmask, filename, dest, mask)
3600 fp = fopen(filename, "rb");
3602 fprintf(stderr, _("%s: error loading XIM!\n"), programName);
3609 for (y=0; y<h; ++y) {
3610 for (x=0; x<h; ++x) {
3615 XPutPixel(xim, x, y, blackPieceColor);
3617 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3620 XPutPixel(xim, x, y, darkSquareColor);
3622 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3625 XPutPixel(xim, x, y, whitePieceColor);
3627 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3630 XPutPixel(xim, x, y, lightSquareColor);
3632 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3638 /* create Pixmap of piece */
3639 *dest = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3641 XPutImage(xDisplay, *dest, lightSquareGC, xim,
3644 /* create Pixmap of clipmask
3645 Note: We assume the white/black pieces have the same
3646 outline, so we make only 6 masks. This is okay
3647 since the XPM clipmask routines do the same. */
3649 temp = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3651 XPutImage(xDisplay, temp, lightSquareGC, xmask,
3654 /* now create the 1-bit version */
3655 *mask = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3658 values.foreground = 1;
3659 values.background = 0;
3661 /* Don't use XtGetGC, not read only */
3662 maskGC = XCreateGC(xDisplay, *mask,
3663 GCForeground | GCBackground, &values);
3664 XCopyPlane(xDisplay, temp, *mask, maskGC,
3665 0, 0, squareSize, squareSize, 0, 0, 1);
3666 XFreePixmap(xDisplay, temp);
3670 void CreateXIMPieces()
3675 static char *ximkind[] = { "ll", "ld", "dl", "dd" };
3680 /* The XSynchronize calls were copied from CreatePieces.
3681 Not sure if needed, but can't hurt */
3682 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3685 /* temp needed by loadXIM() */
3686 ximtemp = XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3687 0, 0, ss, ss, AllPlanes, XYPixmap);
3689 if (strlen(appData.pixmapDirectory) == 0) {
3693 if (appData.monoMode) {
3694 DisplayFatalError(_("XIM pieces cannot be used in monochrome mode"),
3698 fprintf(stderr, _("\nLoading XIMs...\n"));
3700 for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
3701 fprintf(stderr, "%d", piece+1);
3702 for (kind=0; kind<4; kind++) {
3703 fprintf(stderr, ".");
3704 sprintf(buf, "%s/%c%s%u.xim",
3705 ExpandPathName(appData.pixmapDirectory),
3706 ToLower(PieceToChar((ChessSquare)piece)),
3708 ximPieceBitmap[kind][piece] =
3709 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3710 0, 0, ss, ss, AllPlanes, XYPixmap);
3711 if (appData.debugMode)
3712 fprintf(stderr, _("(File:%s:) "), buf);
3713 loadXIM(ximPieceBitmap[kind][piece],
3715 &(xpmPieceBitmap[kind][piece]),
3716 &(ximMaskPm[piece%(int)BlackPawn]));
3718 fprintf(stderr," ");
3720 /* Load light and dark squares */
3721 /* If the LSQ and DSQ pieces don't exist, we will
3722 draw them with solid squares. */
3723 sprintf(buf, "%s/lsq%u.xim", ExpandPathName(appData.pixmapDirectory), ss);
3724 if (access(buf, 0) != 0) {
3728 fprintf(stderr, _("light square "));
3730 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3731 0, 0, ss, ss, AllPlanes, XYPixmap);
3732 if (appData.debugMode)
3733 fprintf(stderr, _("(File:%s:) "), buf);
3735 loadXIM(ximLightSquare, NULL, buf, &xpmLightSquare, NULL);
3736 fprintf(stderr, _("dark square "));
3737 sprintf(buf, "%s/dsq%u.xim",
3738 ExpandPathName(appData.pixmapDirectory), ss);
3739 if (appData.debugMode)
3740 fprintf(stderr, _("(File:%s:) "), buf);
3742 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3743 0, 0, ss, ss, AllPlanes, XYPixmap);
3744 loadXIM(ximDarkSquare, NULL, buf, &xpmDarkSquare, NULL);
3745 xpmJailSquare = xpmLightSquare;
3747 fprintf(stderr, _("Done.\n"));
3749 XSynchronize(xDisplay, False); /* Work-around for xlib/xt buffering bug */
3753 void CreateXPMPieces()
3757 u_int ss = squareSize;
3759 static char *xpmkind[] = { "ll", "ld", "dl", "dd" };
3760 XpmColorSymbol symbols[4];
3763 /* Apparently some versions of Xpm don't define XpmFormat at all --tpm */
3764 if (appData.debugMode) {
3765 fprintf(stderr, "XPM Library Version: %d.%d%c\n",
3766 XpmFormat, XpmVersion, (char)('a' + XpmRevision - 1));
3770 /* The XSynchronize calls were copied from CreatePieces.
3771 Not sure if needed, but can't hurt */
3772 XSynchronize(xDisplay, True); /* Work-around for xlib/xt buffering bug */
3774 /* Setup translations so piece colors match square colors */
3775 symbols[0].name = "light_piece";
3776 symbols[0].value = appData.whitePieceColor;
3777 symbols[1].name = "dark_piece";
3778 symbols[1].value = appData.blackPieceColor;
3779 symbols[2].name = "light_square";
3780 symbols[2].value = appData.lightSquareColor;
3781 symbols[3].name = "dark_square";
3782 symbols[3].value = appData.darkSquareColor;
3784 attr.valuemask = XpmColorSymbols;
3785 attr.colorsymbols = symbols;
3786 attr.numsymbols = 4;
3788 if (appData.monoMode) {
3789 DisplayFatalError(_("XPM pieces cannot be used in monochrome mode"),
3793 if (strlen(appData.pixmapDirectory) == 0) {
3794 XpmPieces* pieces = builtInXpms;
3797 while (pieces->size != squareSize && pieces->size) pieces++;
3798 if (!pieces->size) {
3799 fprintf(stderr, _("No builtin XPM pieces of size %d\n"), squareSize);
3802 for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
3803 for (kind=0; kind<4; kind++) {
3805 if ((r=XpmCreatePixmapFromData(xDisplay, xBoardWindow,
3806 pieces->xpm[piece][kind],
3807 &(xpmPieceBitmap[kind][piece]),
3808 NULL, &attr)) != 0) {
3809 fprintf(stderr, _("Error %d loading XPM image \"%s\"\n"),
3816 xpmJailSquare = xpmLightSquare;
3820 fprintf(stderr, _("\nLoading XPMs...\n"));
3823 for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
3824 fprintf(stderr, "%d ", piece+1);
3825 for (kind=0; kind<4; kind++) {
3826 sprintf(buf, "%s/%c%s%u.xpm",
3827 ExpandPathName(appData.pixmapDirectory),
3828 ToLower(PieceToChar((ChessSquare)piece)),
3830 if (appData.debugMode) {
3831 fprintf(stderr, _("(File:%s:) "), buf);
3833 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3834 &(xpmPieceBitmap[kind][piece]),
3835 NULL, &attr)) != 0) {
3836 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"),
3842 /* Load light and dark squares */
3843 /* If the LSQ and DSQ pieces don't exist, we will
3844 draw them with solid squares. */
3845 fprintf(stderr, _("light square "));
3846 sprintf(buf, "%s/lsq%u.xpm", ExpandPathName(appData.pixmapDirectory), ss);
3847 if (access(buf, 0) != 0) {
3851 if (appData.debugMode)
3852 fprintf(stderr, _("(File:%s:) "), buf);
3854 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3855 &xpmLightSquare, NULL, &attr)) != 0) {
3856 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
3859 fprintf(stderr, _("dark square "));
3860 sprintf(buf, "%s/dsq%u.xpm",
3861 ExpandPathName(appData.pixmapDirectory), ss);
3862 if (appData.debugMode) {
3863 fprintf(stderr, _("(File:%s:) "), buf);
3865 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3866 &xpmDarkSquare, NULL, &attr)) != 0) {
3867 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
3871 xpmJailSquare = xpmLightSquare;
3872 fprintf(stderr, _("Done.\n"));
3874 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3877 #endif /* HAVE_LIBXPM */
3880 /* No built-in bitmaps */
3885 u_int ss = squareSize;
3887 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3890 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
3891 for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
3892 sprintf(buf, "%c%u%c.bm", ToLower(PieceToChar((ChessSquare)piece)),
3893 ss, kind == SOLID ? 's' : 'o');
3894 ReadBitmap(&pieceBitmap[kind][piece], buf, NULL, ss, ss);
3898 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3902 /* With built-in bitmaps */
3905 BuiltInBits* bib = builtInBits;
3908 u_int ss = squareSize;
3910 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3913 while (bib->squareSize != ss && bib->squareSize != 0) bib++;
3915 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
3916 for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
3917 sprintf(buf, "%c%u%c.bm", ToLower(PieceToChar((ChessSquare)piece)),
3918 ss, kind == SOLID ? 's' : 'o');
3919 ReadBitmap(&pieceBitmap[kind][piece], buf,
3920 bib->bits[kind][piece], ss, ss);
3924 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3929 void ReadBitmap(pm, name, bits, wreq, hreq)
3932 unsigned char bits[];
3938 char msg[MSG_SIZ], fullname[MSG_SIZ];
3940 if (*appData.bitmapDirectory != NULLCHAR) {
3941 strcpy(fullname, appData.bitmapDirectory);
3942 strcat(fullname, "/");
3943 strcat(fullname, name);
3944 errcode = XReadBitmapFile(xDisplay, xBoardWindow, fullname,
3945 &w, &h, pm, &x_hot, &y_hot);
3946 if (errcode != BitmapSuccess) {
3948 case BitmapOpenFailed:
3949 sprintf(msg, _("Can't open bitmap file %s"), fullname);
3951 case BitmapFileInvalid:
3952 sprintf(msg, _("Invalid bitmap in file %s"), fullname);
3954 case BitmapNoMemory:
3955 sprintf(msg, _("Ran out of memory reading bitmap file %s"),
3959 sprintf(msg, _("Unknown XReadBitmapFile error %d on file %s"),
3963 fprintf(stderr, _("%s: %s...using built-in\n"),
3965 } else if (w != wreq || h != hreq) {
3967 _("%s: Bitmap %s is %dx%d, not %dx%d...using built-in\n"),
3968 programName, fullname, w, h, wreq, hreq);
3975 fprintf(stderr, _("%s: No built-in bitmap for %s; giving up\n"),
3979 ; // [HGM] bitmaps: make it non-fatal if we have no bitmap;
3981 *pm = XCreateBitmapFromData(xDisplay, xBoardWindow, (char *) bits,
3990 if (lineGap == 0) return;
3992 /* [HR] Split this into 2 loops for non-square boards. */
3994 for (i = 0; i < BOARD_HEIGHT + 1; i++) {
3995 gridSegments[i].x1 = 0;
3996 gridSegments[i].x2 =
3997 lineGap + BOARD_WIDTH * (squareSize + lineGap);
3998 gridSegments[i].y1 = gridSegments[i].y2
3999 = lineGap / 2 + (i * (squareSize + lineGap));
4002 for (j = 0; j < BOARD_WIDTH + 1; j++) {
4003 gridSegments[j + i].y1 = 0;
4004 gridSegments[j + i].y2 =
4005 lineGap + BOARD_HEIGHT * (squareSize + lineGap);
4006 gridSegments[j + i].x1 = gridSegments[j + i].x2
4007 = lineGap / 2 + (j * (squareSize + lineGap));
4011 static void MenuBarSelect(w, addr, index)
4016 XtActionProc proc = (XtActionProc) addr;
4018 (proc)(NULL, NULL, NULL, NULL);
4021 void CreateMenuBarPopup(parent, name, mb)
4031 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
4034 XtSetArg(args[j], XtNleftMargin, 20); j++;
4035 XtSetArg(args[j], XtNrightMargin, 20); j++;
4037 while (mi->string != NULL) {
4038 if (strcmp(mi->string, "----") == 0) {
4039 entry = XtCreateManagedWidget(mi->string, smeLineObjectClass,
4042 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string)));
4043 entry = XtCreateManagedWidget(mi->string, smeBSBObjectClass,
4045 XtAddCallback(entry, XtNcallback,
4046 (XtCallbackProc) MenuBarSelect,
4047 (caddr_t) mi->proc);
4053 Widget CreateMenuBar(mb)
4057 Widget anchor, menuBar;
4059 char menuName[MSG_SIZ];
4062 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
4063 XtSetArg(args[j], XtNvSpace, 0); j++;
4064 XtSetArg(args[j], XtNborderWidth, 0); j++;
4065 menuBar = XtCreateWidget("menuBar", boxWidgetClass,
4066 formWidget, args, j);
4068 while (mb->name != NULL) {
4069 strcpy(menuName, "menu");
4070 strcat(menuName, mb->name);
4072 XtSetArg(args[j], XtNmenuName, XtNewString(menuName)); j++;
4075 shortName[0] = _(mb->name)[0];
4076 shortName[1] = NULLCHAR;
4077 XtSetArg(args[j], XtNlabel, XtNewString(shortName)); j++;
4080 XtSetArg(args[j], XtNlabel, XtNewString(_(mb->name))); j++;
4083 XtSetArg(args[j], XtNborderWidth, 0); j++;
4084 anchor = XtCreateManagedWidget(mb->name, menuButtonWidgetClass,
4086 CreateMenuBarPopup(menuBar, menuName, mb);
4092 Widget CreateButtonBar(mi)
4096 Widget button, buttonBar;
4100 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
4102 XtSetArg(args[j], XtNhSpace, 0); j++;
4104 XtSetArg(args[j], XtNborderWidth, 0); j++;
4105 XtSetArg(args[j], XtNvSpace, 0); j++;
4106 buttonBar = XtCreateWidget("buttonBar", boxWidgetClass,
4107 formWidget, args, j);
4109 while (mi->string != NULL) {
4112 XtSetArg(args[j], XtNinternalWidth, 2); j++;
4113 XtSetArg(args[j], XtNborderWidth, 0); j++;
4115 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string))); j++;
4116 button = XtCreateManagedWidget(mi->string, commandWidgetClass,
4117 buttonBar, args, j);
4118 XtAddCallback(button, XtNcallback,
4119 (XtCallbackProc) MenuBarSelect,
4120 (caddr_t) mi->proc);
4127 CreatePieceMenu(name, color)
4134 ChessSquare selection;
4136 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
4137 boardWidget, args, 0);
4139 for (i = 0; i < PIECE_MENU_SIZE; i++) {
4140 String item = pieceMenuStrings[color][i];
4142 if (strcmp(item, "----") == 0) {
4143 entry = XtCreateManagedWidget(item, smeLineObjectClass,
4146 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
4147 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
4149 selection = pieceMenuTranslation[color][i];
4150 XtAddCallback(entry, XtNcallback,
4151 (XtCallbackProc) PieceMenuSelect,
4152 (caddr_t) selection);
4153 if (selection == WhitePawn || selection == BlackPawn) {
4154 XtSetArg(args[0], XtNpopupOnEntry, entry);
4155 XtSetValues(menu, args, 1);
4168 ChessSquare selection;
4170 whitePieceMenu = CreatePieceMenu("menuW", 0);
4171 blackPieceMenu = CreatePieceMenu("menuB", 1);
4173 XtRegisterGrabAction(PieceMenuPopup, True,
4174 (unsigned)(ButtonPressMask|ButtonReleaseMask),
4175 GrabModeAsync, GrabModeAsync);
4177 XtSetArg(args[0], XtNlabel, _("Drop"));
4178 dropMenu = XtCreatePopupShell("menuD", simpleMenuWidgetClass,
4179 boardWidget, args, 1);
4180 for (i = 0; i < DROP_MENU_SIZE; i++) {
4181 String item = dropMenuStrings[i];
4183 if (strcmp(item, "----") == 0) {
4184 entry = XtCreateManagedWidget(item, smeLineObjectClass,
4187 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
4188 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
4190 selection = dropMenuTranslation[i];
4191 XtAddCallback(entry, XtNcallback,
4192 (XtCallbackProc) DropMenuSelect,
4193 (caddr_t) selection);
4198 void SetupDropMenu()
4206 for (i=0; i<sizeof(dmEnables)/sizeof(DropMenuEnables); i++) {
4207 entry = XtNameToWidget(dropMenu, dmEnables[i].widget);
4208 p = strchr(gameMode == IcsPlayingWhite ? white_holding : black_holding,
4209 dmEnables[i].piece);
4210 XtSetSensitive(entry, p != NULL || !appData.testLegality
4211 /*!!temp:*/ || (gameInfo.variant == VariantCrazyhouse
4212 && !appData.icsActive));
4214 while (p && *p++ == dmEnables[i].piece) count++;
4215 sprintf(label, "%s %d", dmEnables[i].widget, count);
4217 XtSetArg(args[j], XtNlabel, label); j++;
4218 XtSetValues(entry, args, j);
4222 void PieceMenuPopup(w, event, params, num_params)
4226 Cardinal *num_params;
4229 if (event->type != ButtonPress) return;
4230 if (errorUp) ErrorPopDown();
4234 whichMenu = params[0];
4236 case IcsPlayingWhite:
4237 case IcsPlayingBlack:
4239 case MachinePlaysWhite:
4240 case MachinePlaysBlack:
4241 if (appData.testLegality &&
4242 gameInfo.variant != VariantBughouse &&
4243 gameInfo.variant != VariantCrazyhouse) return;
4245 whichMenu = "menuD";
4251 if (((pmFromX = EventToSquare(event->xbutton.x, BOARD_WIDTH)) < 0) ||
4252 ((pmFromY = EventToSquare(event->xbutton.y, BOARD_HEIGHT)) < 0)) {
4253 pmFromX = pmFromY = -1;
4257 pmFromX = BOARD_WIDTH - 1 - pmFromX;
4259 pmFromY = BOARD_HEIGHT - 1 - pmFromY;
4261 XtPopupSpringLoaded(XtNameToWidget(boardWidget, whichMenu));
4264 static void PieceMenuSelect(w, piece, junk)
4269 if (pmFromX < 0 || pmFromY < 0) return;
4270 EditPositionMenuEvent(piece, pmFromX, pmFromY);
4273 static void DropMenuSelect(w, piece, junk)
4278 if (pmFromX < 0 || pmFromY < 0) return;
4279 DropMenuEvent(piece, pmFromX, pmFromY);
4282 void WhiteClock(w, event, prms, nprms)
4288 if (gameMode == EditPosition || gameMode == IcsExamining) {
4289 SetWhiteToPlayEvent();
4290 } else if (gameMode == IcsPlayingBlack || gameMode == MachinePlaysWhite) {
4295 void BlackClock(w, event, prms, nprms)
4301 if (gameMode == EditPosition || gameMode == IcsExamining) {
4302 SetBlackToPlayEvent();
4303 } else if (gameMode == IcsPlayingWhite || gameMode == MachinePlaysBlack) {
4310 * If the user selects on a border boundary, return -1; if off the board,
4311 * return -2. Otherwise map the event coordinate to the square.
4313 int EventToSquare(x, limit)
4321 if ((x % (squareSize + lineGap)) >= squareSize)
4323 x /= (squareSize + lineGap);
4329 static void do_flash_delay(msec)
4335 static void drawHighlight(file, rank, gc)
4341 if (lineGap == 0 || appData.blindfold) return;
4344 x = lineGap/2 + ((BOARD_WIDTH-1)-file) *
4345 (squareSize + lineGap);
4346 y = lineGap/2 + rank * (squareSize + lineGap);
4348 x = lineGap/2 + file * (squareSize + lineGap);
4349 y = lineGap/2 + ((BOARD_HEIGHT-1)-rank) *
4350 (squareSize + lineGap);
4353 XDrawRectangle(xDisplay, xBoardWindow, gc, x, y,
4354 squareSize+lineGap, squareSize+lineGap);
4357 int hi1X = -1, hi1Y = -1, hi2X = -1, hi2Y = -1;
4358 int pm1X = -1, pm1Y = -1, pm2X = -1, pm2Y = -1;
4361 SetHighlights(fromX, fromY, toX, toY)
4362 int fromX, fromY, toX, toY;
4364 if (hi1X != fromX || hi1Y != fromY) {
4365 if (hi1X >= 0 && hi1Y >= 0) {
4366 drawHighlight(hi1X, hi1Y, lineGC);
4368 if (fromX >= 0 && fromY >= 0) {
4369 drawHighlight(fromX, fromY, highlineGC);
4372 if (hi2X != toX || hi2Y != toY) {
4373 if (hi2X >= 0 && hi2Y >= 0) {
4374 drawHighlight(hi2X, hi2Y, lineGC);
4376 if (toX >= 0 && toY >= 0) {
4377 drawHighlight(toX, toY, highlineGC);
4389 SetHighlights(-1, -1, -1, -1);
4394 SetPremoveHighlights(fromX, fromY, toX, toY)
4395 int fromX, fromY, toX, toY;
4397 if (pm1X != fromX || pm1Y != fromY) {
4398 if (pm1X >= 0 && pm1Y >= 0) {
4399 drawHighlight(pm1X, pm1Y, lineGC);
4401 if (fromX >= 0 && fromY >= 0) {
4402 drawHighlight(fromX, fromY, prelineGC);
4405 if (pm2X != toX || pm2Y != toY) {
4406 if (pm2X >= 0 && pm2Y >= 0) {
4407 drawHighlight(pm2X, pm2Y, lineGC);
4409 if (toX >= 0 && toY >= 0) {
4410 drawHighlight(toX, toY, prelineGC);
4420 ClearPremoveHighlights()
4422 SetPremoveHighlights(-1, -1, -1, -1);
4425 static void BlankSquare(x, y, color, piece, dest)
4430 if (useImages && useImageSqs) {
4434 pm = xpmLightSquare;
4439 case 2: /* neutral */
4444 XCopyArea(xDisplay, pm, dest, wlPieceGC, 0, 0,
4445 squareSize, squareSize, x, y);
4455 case 2: /* neutral */
4460 XFillRectangle(xDisplay, dest, gc, x, y, squareSize, squareSize);
4465 I split out the routines to draw a piece so that I could
4466 make a generic flash routine.
4468 static void monoDrawPiece_1bit(piece, square_color, x, y, dest)
4470 int square_color, x, y;
4473 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
4474 switch (square_color) {
4476 case 2: /* neutral */
4478 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
4479 ? *pieceToOutline(piece)
4480 : *pieceToSolid(piece),
4481 dest, bwPieceGC, 0, 0,
4482 squareSize, squareSize, x, y);
4485 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
4486 ? *pieceToSolid(piece)
4487 : *pieceToOutline(piece),
4488 dest, wbPieceGC, 0, 0,
4489 squareSize, squareSize, x, y);
4494 static void monoDrawPiece(piece, square_color, x, y, dest)
4496 int square_color, x, y;
4499 switch (square_color) {
4501 case 2: /* neutral */
4503 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
4504 ? *pieceToOutline(piece)
4505 : *pieceToSolid(piece),
4506 dest, bwPieceGC, 0, 0,
4507 squareSize, squareSize, x, y, 1);
4510 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
4511 ? *pieceToSolid(piece)
4512 : *pieceToOutline(piece),
4513 dest, wbPieceGC, 0, 0,
4514 squareSize, squareSize, x, y, 1);
4519 static void colorDrawPiece(piece, square_color, x, y, dest)
4521 int square_color, x, y;
4524 if(pieceToSolid(piece) == NULL) return; // [HGM] bitmaps: make it non-fatal if we have no bitmap;
4525 switch (square_color) {
4527 XCopyPlane(xDisplay, *pieceToSolid(piece),
4528 dest, (int) piece < (int) BlackPawn
4529 ? wlPieceGC : blPieceGC, 0, 0,
4530 squareSize, squareSize, x, y, 1);
4533 XCopyPlane(xDisplay, *pieceToSolid(piece),
4534 dest, (int) piece < (int) BlackPawn
4535 ? wdPieceGC : bdPieceGC, 0, 0,
4536 squareSize, squareSize, x, y, 1);
4538 case 2: /* neutral */
4540 XCopyPlane(xDisplay, *pieceToSolid(piece),
4541 dest, (int) piece < (int) BlackPawn
4542 ? wjPieceGC : bjPieceGC, 0, 0,
4543 squareSize, squareSize, x, y, 1);
4548 static void colorDrawPieceImage(piece, square_color, x, y, dest)
4550 int square_color, x, y;
4555 switch (square_color) {
4557 case 2: /* neutral */
4559 if ((int)piece < (int) BlackPawn) {
4567 if ((int)piece < (int) BlackPawn) {
4575 XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
4576 dest, wlPieceGC, 0, 0,
4577 squareSize, squareSize, x, y);
4580 typedef void (*DrawFunc)();
4582 DrawFunc ChooseDrawFunc()
4584 if (appData.monoMode) {
4585 if (DefaultDepth(xDisplay, xScreen) == 1) {
4586 return monoDrawPiece_1bit;
4588 return monoDrawPiece;
4592 return colorDrawPieceImage;
4594 return colorDrawPiece;
4598 /* [HR] determine square color depending on chess variant. */
4599 static int SquareColor(row, column)
4604 if (gameInfo.variant == VariantXiangqi) {
4605 if (column >= 3 && column <= 5 && row >= 0 && row <= 2) {
4607 } else if (column >= 3 && column <= 5 && row >= 7 && row <= 9) {
4609 } else if (row <= 4) {
4615 square_color = ((column + row) % 2) == 1;
4618 /* [hgm] holdings: next line makes all holdings squares light */
4619 if(column < BOARD_LEFT || column >= BOARD_RGHT) square_color = 1;
4621 return square_color;
4624 void DrawSquare(row, column, piece, do_flash)
4625 int row, column, do_flash;
4628 int square_color, x, y, direction, font_ascent, font_descent;
4631 XCharStruct overall;
4635 if(gameInfo.variant == VariantShogi) { // [HGM] shogi: in shogi Q is used for Lance
4636 if(piece == WhiteQueen) piece = WhiteLance; else
4637 if(piece == BlackQueen) piece = BlackLance;
4640 else if(gameInfo.variant == VariantGothic) { // [HGM] shogi: in Gothic Chancelor has alternative look
4641 if(piece == WhiteMarshall) piece = WhiteSilver; else
4642 if(piece == BlackMarshall) piece = BlackSilver;
4646 /* Calculate delay in milliseconds (2-delays per complete flash) */
4647 flash_delay = 500 / appData.flashRate;
4650 x = lineGap + ((BOARD_WIDTH-1)-column) *
4651 (squareSize + lineGap);
4652 y = lineGap + row * (squareSize + lineGap);
4654 x = lineGap + column * (squareSize + lineGap);
4655 y = lineGap + ((BOARD_HEIGHT-1)-row) *
4656 (squareSize + lineGap);
4659 square_color = SquareColor(row, column);
4661 if ( // [HGM] holdings: blank out area between board and holdings
4662 column == BOARD_LEFT-1 || column == BOARD_RGHT
4663 || (column == BOARD_LEFT-2 && row < BOARD_HEIGHT-gameInfo.holdingsSize)
4664 || (column == BOARD_RGHT+1 && row >= gameInfo.holdingsSize) ) {
4665 BlankSquare(x, y, 2, EmptySquare, xBoardWindow);
4667 // [HGM] print piece counts next to holdings
4668 string[1] = NULLCHAR;
4669 if (column == (flipView ? BOARD_LEFT-1 : BOARD_RGHT) && piece > 1 ) {
4670 string[0] = '0' + piece;
4671 XTextExtents(countFontStruct, string, 1, &direction,
4672 &font_ascent, &font_descent, &overall);
4673 if (appData.monoMode) {
4674 XDrawImageString(xDisplay, xBoardWindow, countGC,
4675 x + squareSize - overall.width - 2,
4676 y + font_ascent + 1, string, 1);
4678 XDrawString(xDisplay, xBoardWindow, countGC,
4679 x + squareSize - overall.width - 2,
4680 y + font_ascent + 1, string, 1);
4683 if (column == (flipView ? BOARD_RGHT : BOARD_LEFT-1) && piece > 1) {
4684 string[0] = '0' + piece;
4685 XTextExtents(countFontStruct, string, 1, &direction,
4686 &font_ascent, &font_descent, &overall);
4687 if (appData.monoMode) {
4688 XDrawImageString(xDisplay, xBoardWindow, countGC,
4689 x + 2, y + font_ascent + 1, string, 1);
4691 XDrawString(xDisplay, xBoardWindow, countGC,
4692 x + 2, y + font_ascent + 1, string, 1);
4696 if (piece == EmptySquare || appData.blindfold) {
4697 BlankSquare(x, y, square_color, piece, xBoardWindow);
4699 drawfunc = ChooseDrawFunc();
4700 if (do_flash && appData.flashCount > 0) {
4701 for (i=0; i<appData.flashCount; ++i) {
4703 drawfunc(piece, square_color, x, y, xBoardWindow);
4704 XSync(xDisplay, False);
4705 do_flash_delay(flash_delay);
4707 BlankSquare(x, y, square_color, piece, xBoardWindow);
4708 XSync(xDisplay, False);
4709 do_flash_delay(flash_delay);
4712 drawfunc(piece, square_color, x, y, xBoardWindow);
4716 string[1] = NULLCHAR;
4717 if (appData.showCoords && row == (flipView ? BOARD_HEIGHT-1 : 0)
4718 && column >= BOARD_LEFT && column < BOARD_RGHT) {
4719 string[0] = 'a' + column - BOARD_LEFT;
4720 XTextExtents(coordFontStruct, string, 1, &direction,
4721 &font_ascent, &font_descent, &overall);
4722 if (appData.monoMode) {
4723 XDrawImageString(xDisplay, xBoardWindow, coordGC,
4724 x + squareSize - overall.width - 2,
4725 y + squareSize - font_descent - 1, string, 1);
4727 XDrawString(xDisplay, xBoardWindow, coordGC,
4728 x + squareSize - overall.width - 2,
4729 y + squareSize - font_descent - 1, string, 1);
4732 if (appData.showCoords && column == (flipView ? BOARD_RGHT-1 : BOARD_LEFT)) {
4733 string[0] = ONE + row;
4734 XTextExtents(coordFontStruct, string, 1, &direction,
4735 &font_ascent, &font_descent, &overall);
4736 if (appData.monoMode) {
4737 XDrawImageString(xDisplay, xBoardWindow, coordGC,
4738 x + 2, y + font_ascent + 1, string, 1);
4740 XDrawString(xDisplay, xBoardWindow, coordGC,
4741 x + 2, y + font_ascent + 1, string, 1);
4747 /* Why is this needed on some versions of X? */
4748 void EventProc(widget, unused, event)
4753 if (!XtIsRealized(widget))
4756 switch (event->type) {
4758 if (event->xexpose.count > 0) return; /* no clipping is done */
4759 XDrawPosition(widget, True, NULL);
4767 void DrawPosition(fullRedraw, board)
4768 /*Boolean*/int fullRedraw;
4771 XDrawPosition(boardWidget, fullRedraw, board);
4774 /* Returns 1 if there are "too many" differences between b1 and b2
4775 (i.e. more than 1 move was made) */
4776 static int too_many_diffs(b1, b2)
4782 for (i=0; i<BOARD_HEIGHT; ++i) {
4783 for (j=0; j<BOARD_WIDTH; ++j) {
4784 if (b1[i][j] != b2[i][j]) {
4785 if (++c > 4) /* Castling causes 4 diffs */
4794 /* Matrix describing castling maneuvers */
4795 /* Row, ColRookFrom, ColKingFrom, ColRookTo, ColKingTo */
4796 static int castling_matrix[4][5] = {
4797 { 0, 0, 4, 3, 2 }, /* 0-0-0, white */
4798 { 0, 7, 4, 5, 6 }, /* 0-0, white */
4799 { 7, 0, 4, 3, 2 }, /* 0-0-0, black */
4800 { 7, 7, 4, 5, 6 } /* 0-0, black */
4803 /* Checks whether castling occurred. If it did, *rrow and *rcol
4804 are set to the destination (row,col) of the rook that moved.
4806 Returns 1 if castling occurred, 0 if not.
4808 Note: Only handles a max of 1 castling move, so be sure
4809 to call too_many_diffs() first.
4811 static int check_castle_draw(newb, oldb, rrow, rcol)
4818 /* For each type of castling... */
4819 for (i=0; i<4; ++i) {
4820 r = castling_matrix[i];
4822 /* Check the 4 squares involved in the castling move */
4824 for (j=1; j<=4; ++j) {
4825 if (newb[r[0]][r[j]] == oldb[r[0]][r[j]]) {
4832 /* All 4 changed, so it must be a castling move */
4841 static int damage[BOARD_SIZE][BOARD_SIZE];
4844 * event handler for redrawing the board
4846 void XDrawPosition(w, repaint, board)
4848 /*Boolean*/int repaint;
4852 static int lastFlipView = 0;
4853 static int lastBoardValid = 0;
4854 static Board lastBoard;
4858 if (board == NULL) {
4859 if (!lastBoardValid) return;
4862 if (!lastBoardValid || lastFlipView != flipView) {
4863 XtSetArg(args[0], XtNleftBitmap, (flipView ? xMarkPixmap : None));
4864 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flip View"),
4869 * It would be simpler to clear the window with XClearWindow()
4870 * but this causes a very distracting flicker.
4873 if (!repaint && lastBoardValid && lastFlipView == flipView) {
4875 /* If too much changes (begin observing new game, etc.), don't
4877 do_flash = too_many_diffs(board, lastBoard) ? 0 : 1;
4879 /* Special check for castling so we don't flash both the king
4880 and the rook (just flash the king). */
4882 if (check_castle_draw(board, lastBoard, &rrow, &rcol)) {
4883 /* Draw rook with NO flashing. King will be drawn flashing later */
4884 DrawSquare(rrow, rcol, board[rrow][rcol], 0);
4885 lastBoard[rrow][rcol] = board[rrow][rcol];
4889 /* First pass -- Draw (newly) empty squares and repair damage.
4890 This prevents you from having a piece show up twice while it
4891 is flashing on its new square */
4892 for (i = 0; i < BOARD_HEIGHT; i++)
4893 for (j = 0; j < BOARD_WIDTH; j++)
4894 if ((board[i][j] != lastBoard[i][j] && board[i][j] == EmptySquare)
4896 DrawSquare(i, j, board[i][j], 0);
4897 damage[i][j] = False;
4900 /* Second pass -- Draw piece(s) in new position and flash them */
4901 for (i = 0; i < BOARD_HEIGHT; i++)
4902 for (j = 0; j < BOARD_WIDTH; j++)
4903 if (board[i][j] != lastBoard[i][j]) {
4904 DrawSquare(i, j, board[i][j], do_flash);
4908 XDrawSegments(xDisplay, xBoardWindow, lineGC,
4909 gridSegments, BOARD_HEIGHT + BOARD_WIDTH + 2);
4911 for (i = 0; i < BOARD_HEIGHT; i++)
4912 for (j = 0; j < BOARD_WIDTH; j++) {
4913 DrawSquare(i, j, board[i][j], 0);
4914 damage[i][j] = False;
4918 CopyBoard(lastBoard, board);
4920 lastFlipView = flipView;
4922 /* Draw highlights */
4923 if (pm1X >= 0 && pm1Y >= 0) {
4924 drawHighlight(pm1X, pm1Y, prelineGC);
4926 if (pm2X >= 0 && pm2Y >= 0) {
4927 drawHighlight(pm2X, pm2Y, prelineGC);
4929 if (hi1X >= 0 && hi1Y >= 0) {
4930 drawHighlight(hi1X, hi1Y, highlineGC);
4932 if (hi2X >= 0 && hi2Y >= 0) {
4933 drawHighlight(hi2X, hi2Y, highlineGC);
4936 /* If piece being dragged around board, must redraw that too */
4939 XSync(xDisplay, False);
4944 * event handler for redrawing the board
4946 void DrawPositionProc(w, event, prms, nprms)
4952 XDrawPosition(w, True, NULL);
4957 * event handler for parsing user moves
4959 // [HGM] This routine will need quite some reworking. Although the backend still supports the old
4960 // way of doing things, by calling UserMoveEvent() to test the legality of the move and then perform
4961 // it at the end, and doing all kind of preliminary tests here (e.g. to weed out self-captures), it
4962 // should be made to use the new way, of calling UserMoveTest early to determine the legality of the
4963 // move, (which will weed out the illegal selfcaptures and moves into the holdings, and flag promotions),
4964 // and at the end FinishMove() to perform the move after optional promotion popups.
4965 // For now I patched it to allow self-capture with King, and suppress clicks between board and holdings.
4966 void HandleUserMove(w, event, prms, nprms)
4973 Boolean saveAnimate;
4974 static int second = 0;
4976 if (w != boardWidget || errorExitStatus != -1) return;
4978 if (event->type == ButtonPress) ErrorPopDown();
4981 if (event->type == ButtonPress) {
4982 XtPopdown(promotionShell);
4983 XtDestroyWidget(promotionShell);
4984 promotionUp = False;
4992 x = EventToSquare(event->xbutton.x, BOARD_WIDTH);
4993 y = EventToSquare(event->xbutton.y, BOARD_HEIGHT);
4994 if (!flipView && y >= 0) {
4995 y = BOARD_HEIGHT - 1 - y;
4997 if (flipView && x >= 0) {
4998 x = BOARD_WIDTH - 1 - x;
5001 /* [HGM] holdings: next 5 lines: ignore all clicks between board and holdings */
5002 if(event->type == ButtonPress
5003 && ( x == BOARD_LEFT-1 || x == BOARD_RGHT
5004 || x == BOARD_LEFT-2 && y < BOARD_HEIGHT-gameInfo.holdingsSize
5005 || x == BOARD_RGHT+1 && y >= gameInfo.holdingsSize) )
5009 if (event->type == ButtonPress) {
5011 if (OKToStartUserMove(x, y)) {
5015 DragPieceBegin(event->xbutton.x, event->xbutton.y);
5016 if (appData.highlightDragging) {
5017 SetHighlights(x, y, -1, -1);
5025 if (event->type == ButtonPress && gameMode != EditPosition &&
5030 /* Check if clicking again on the same color piece */
5031 fromP = boards[currentMove][fromY][fromX];
5032 toP = boards[currentMove][y][x];
5033 if ((WhitePawn <= fromP && fromP < WhiteKing && // [HGM] this test should go, as UserMoveTest now does it.
5034 WhitePawn <= toP && toP <= WhiteKing) || // For now I made it less critical by exempting King
5035 (BlackPawn <= fromP && fromP < BlackKing && // moves, to not interfere with FRC castlings.
5036 BlackPawn <= toP && toP <= BlackKing)) {
5037 /* Clicked again on same color piece -- changed his mind */
5038 second = (x == fromX && y == fromY);
5039 if (appData.highlightDragging) {
5040 SetHighlights(x, y, -1, -1);
5044 if (OKToStartUserMove(x, y)) {
5047 DragPieceBegin(event->xbutton.x, event->xbutton.y);
5053 if (event->type == ButtonRelease && x == fromX && y == fromY) {
5054 DragPieceEnd(event->xbutton.x, event->xbutton.y);
5055 if (appData.animateDragging) {
5056 /* Undo animation damage if any */
5057 DrawPosition(FALSE, NULL);
5060 /* Second up/down in same square; just abort move */
5065 ClearPremoveHighlights();
5067 /* First upclick in same square; start click-click mode */
5068 SetHighlights(x, y, -1, -1);
5073 /* Completed move */
5076 saveAnimate = appData.animate;
5077 if (event->type == ButtonPress) {
5078 /* Finish clickclick move */
5079 if (appData.animate || appData.highlightLastMove) {
5080 SetHighlights(fromX, fromY, toX, toY);
5085 /* Finish drag move */
5086 if (appData.highlightLastMove) {
5087 SetHighlights(fromX, fromY, toX, toY);
5091 DragPieceEnd(event->xbutton.x, event->xbutton.y);
5092 /* Don't animate move and drag both */
5093 appData.animate = FALSE;
5095 if (IsPromotion(fromX, fromY, toX, toY)) {
5096 if (appData.alwaysPromoteToQueen) {
5097 UserMoveEvent(fromX, fromY, toX, toY, 'q');
5098 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
5099 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
5102 SetHighlights(fromX, fromY, toX, toY);
5106 UserMoveEvent(fromX, fromY, toX, toY, NULLCHAR);
5107 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
5108 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
5111 appData.animate = saveAnimate;
5112 if (appData.animate || appData.animateDragging) {
5113 /* Undo animation damage if needed */
5114 DrawPosition(FALSE, NULL);
5118 void AnimateUserMove (Widget w, XEvent * event,
5119 String * params, Cardinal * nParams)
5121 DragPieceMove(event->xmotion.x, event->xmotion.y);
5124 Widget CommentCreate(name, text, mutable, callback, lines)
5126 int /*Boolean*/ mutable;
5127 XtCallbackProc callback;
5131 Widget shell, layout, form, edit, b_ok, b_cancel, b_clear, b_close, b_edit;
5136 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5137 XtGetValues(boardWidget, args, j);
5140 XtSetArg(args[j], XtNresizable, True); j++;
5143 XtCreatePopupShell(name, topLevelShellWidgetClass,
5144 shellWidget, args, j);
5147 XtCreatePopupShell(name, transientShellWidgetClass,
5148 shellWidget, args, j);
5151 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
5152 layoutArgs, XtNumber(layoutArgs));
5154 XtCreateManagedWidget("form", formWidgetClass, layout,
5155 formArgs, XtNumber(formArgs));
5159 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
5160 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
5162 XtSetArg(args[j], XtNstring, text); j++;
5163 XtSetArg(args[j], XtNtop, XtChainTop); j++;
5164 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5165 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5166 XtSetArg(args[j], XtNright, XtChainRight); j++;
5167 XtSetArg(args[j], XtNresizable, True); j++;
5168 XtSetArg(args[j], XtNwidth, bw_width); j++; /*force wider than buttons*/
5170 XtSetArg(args[j], XtNscrollVertical, XawtextScrollWhenNeeded); j++;
5172 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
5173 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
5175 XtSetArg(args[j], XtNautoFill, True); j++;
5176 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
5178 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
5182 XtSetArg(args[j], XtNfromVert, edit); j++;
5183 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5184 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5185 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5186 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5188 XtCreateManagedWidget(_("ok"), commandWidgetClass, form, args, j);
5189 XtAddCallback(b_ok, XtNcallback, callback, (XtPointer) 0);
5192 XtSetArg(args[j], XtNfromVert, edit); j++;
5193 XtSetArg(args[j], XtNfromHoriz, b_ok); j++;
5194 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5195 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5196 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5197 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5199 XtCreateManagedWidget(_("cancel"), commandWidgetClass, form, args, j);
5200 XtAddCallback(b_cancel, XtNcallback, callback, (XtPointer) 0);
5203 XtSetArg(args[j], XtNfromVert, edit); j++;
5204 XtSetArg(args[j], XtNfromHoriz, b_cancel); j++;
5205 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5206 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5207 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5208 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5210 XtCreateManagedWidget(_("clear"), commandWidgetClass, form, args, j);
5211 XtAddCallback(b_clear, XtNcallback, callback, (XtPointer) 0);
5214 XtSetArg(args[j], XtNfromVert, edit); j++;
5215 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5216 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5217 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5218 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5220 XtCreateManagedWidget(_("close"), commandWidgetClass, form, args, j);
5221 XtAddCallback(b_close, XtNcallback, callback, (XtPointer) 0);
5224 XtSetArg(args[j], XtNfromVert, edit); j++;
5225 XtSetArg(args[j], XtNfromHoriz, b_close); j++;
5226 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5227 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5228 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5229 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5231 XtCreateManagedWidget(_("edit"), commandWidgetClass, form, args, j);
5232 XtAddCallback(b_edit, XtNcallback, callback, (XtPointer) 0);
5235 XtRealizeWidget(shell);
5237 if (commentX == -1) {
5240 Dimension pw_height;
5241 Dimension ew_height;
5244 XtSetArg(args[j], XtNheight, &ew_height); j++;
5245 XtGetValues(edit, args, j);
5248 XtSetArg(args[j], XtNheight, &pw_height); j++;
5249 XtGetValues(shell, args, j);
5250 commentH = pw_height + (lines - 1) * ew_height;
5251 commentW = bw_width - 16;
5253 XSync(xDisplay, False);
5255 /* This code seems to tickle an X bug if it is executed too soon
5256 after xboard starts up. The coordinates get transformed as if
5257 the main window was positioned at (0, 0).
5259 XtTranslateCoords(shellWidget,
5260 (bw_width - commentW) / 2, 0 - commentH / 2,
5261 &commentX, &commentY);
5263 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
5264 RootWindowOfScreen(XtScreen(shellWidget)),
5265 (bw_width - commentW) / 2, 0 - commentH / 2,
5270 if (commentY < 0) commentY = 0; /*avoid positioning top offscreen*/
5273 XtSetArg(args[j], XtNheight, commentH); j++;
5274 XtSetArg(args[j], XtNwidth, commentW); j++;
5275 XtSetArg(args[j], XtNx, commentX); j++;
5276 XtSetArg(args[j], XtNy, commentY); j++;
5277 XtSetValues(shell, args, j);
5278 XtSetKeyboardFocus(shell, edit);
5283 /* Used for analysis window and ICS input window */
5284 Widget MiscCreate(name, text, mutable, callback, lines)
5286 int /*Boolean*/ mutable;
5287 XtCallbackProc callback;
5291 Widget shell, layout, form, edit;
5293 Dimension bw_width, pw_height, ew_height, w, h;
5299 XtSetArg(args[j], XtNresizable, True); j++;
5302 XtCreatePopupShell(name, topLevelShellWidgetClass,
5303 shellWidget, args, j);
5306 XtCreatePopupShell(name, transientShellWidgetClass,
5307 shellWidget, args, j);
5310 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
5311 layoutArgs, XtNumber(layoutArgs));
5313 XtCreateManagedWidget("form", formWidgetClass, layout,
5314 formArgs, XtNumber(formArgs));
5318 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
5319 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
5321 XtSetArg(args[j], XtNstring, text); j++;
5322 XtSetArg(args[j], XtNtop, XtChainTop); j++;
5323 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5324 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5325 XtSetArg(args[j], XtNright, XtChainRight); j++;
5326 XtSetArg(args[j], XtNresizable, True); j++;
5328 XtSetArg(args[j], XtNscrollVertical, XawtextScrollWhenNeeded); j++;
5330 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
5331 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
5333 XtSetArg(args[j], XtNautoFill, True); j++;
5334 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
5336 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
5338 XtRealizeWidget(shell);
5341 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5342 XtGetValues(boardWidget, args, j);
5345 XtSetArg(args[j], XtNheight, &ew_height); j++;
5346 XtGetValues(edit, args, j);
5349 XtSetArg(args[j], XtNheight, &pw_height); j++;
5350 XtGetValues(shell, args, j);
5351 h = pw_height + (lines - 1) * ew_height;
5354 XSync(xDisplay, False);
5356 /* This code seems to tickle an X bug if it is executed too soon
5357 after xboard starts up. The coordinates get transformed as if
5358 the main window was positioned at (0, 0).
5360 XtTranslateCoords(shellWidget, (bw_width - w) / 2, 0 - h / 2, &x, &y);
5362 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
5363 RootWindowOfScreen(XtScreen(shellWidget)),
5364 (bw_width - w) / 2, 0 - h / 2, &xx, &yy, &junk);
5368 if (y < 0) y = 0; /*avoid positioning top offscreen*/
5371 XtSetArg(args[j], XtNheight, h); j++;
5372 XtSetArg(args[j], XtNwidth, w); j++;
5373 XtSetArg(args[j], XtNx, x); j++;
5374 XtSetArg(args[j], XtNy, y); j++;
5375 XtSetValues(shell, args, j);
5381 static int savedIndex; /* gross that this is global */
5383 void EditCommentPopUp(index, title, text)
5392 if (text == NULL) text = "";
5394 if (editShell == NULL) {
5396 CommentCreate(title, text, True, EditCommentCallback, 4);
5397 XtRealizeWidget(editShell);
5398 CatchDeleteWindow(editShell, "EditCommentPopDown");
5400 edit = XtNameToWidget(editShell, "*form.text");
5402 XtSetArg(args[j], XtNstring, text); j++;
5403 XtSetValues(edit, args, j);
5405 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5406 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5407 XtSetValues(editShell, args, j);
5410 XtPopup(editShell, XtGrabNone);
5414 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
5415 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
5419 void EditCommentCallback(w, client_data, call_data)
5421 XtPointer client_data, call_data;
5429 XtSetArg(args[j], XtNlabel, &name); j++;
5430 XtGetValues(w, args, j);
5432 if (strcmp(name, _("ok")) == 0) {
5433 edit = XtNameToWidget(editShell, "*form.text");
5435 XtSetArg(args[j], XtNstring, &val); j++;
5436 XtGetValues(edit, args, j);
5437 ReplaceComment(savedIndex, val);
5438 EditCommentPopDown();
5439 } else if (strcmp(name, _("cancel")) == 0) {
5440 EditCommentPopDown();
5441 } else if (strcmp(name, _("clear")) == 0) {
5442 edit = XtNameToWidget(editShell, "*form.text");
5443 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
5444 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
5448 void EditCommentPopDown()
5453 if (!editUp) return;
5455 XtSetArg(args[j], XtNx, &commentX); j++;
5456 XtSetArg(args[j], XtNy, &commentY); j++;
5457 XtSetArg(args[j], XtNheight, &commentH); j++;
5458 XtSetArg(args[j], XtNwidth, &commentW); j++;
5459 XtGetValues(editShell, args, j);
5460 XtPopdown(editShell);
5463 XtSetArg(args[j], XtNleftBitmap, None); j++;
5464 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
5468 void ICSInputBoxPopUp()
5473 char *title = _("ICS Input");
5476 if (ICSInputShell == NULL) {
5477 ICSInputShell = MiscCreate(title, "", True, NULL, 1);
5478 tr = XtParseTranslationTable(ICSInputTranslations);
5479 edit = XtNameToWidget(ICSInputShell, "*form.text");
5480 XtOverrideTranslations(edit, tr);
5481 XtRealizeWidget(ICSInputShell);
5482 CatchDeleteWindow(ICSInputShell, "ICSInputBoxPopDown");
5485 edit = XtNameToWidget(ICSInputShell, "*form.text");
5487 XtSetArg(args[j], XtNstring, ""); j++;
5488 XtSetValues(edit, args, j);
5490 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5491 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5492 XtSetValues(ICSInputShell, args, j);
5495 XtPopup(ICSInputShell, XtGrabNone);
5496 XtSetKeyboardFocus(ICSInputShell, edit);
5498 ICSInputBoxUp = True;
5500 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
5501 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
5505 void ICSInputSendText()
5512 edit = XtNameToWidget(ICSInputShell, "*form.text");
5514 XtSetArg(args[j], XtNstring, &val); j++;
5515 XtGetValues(edit, args, j);
5516 SendMultiLineToICS(val);
5517 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
5518 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
5521 void ICSInputBoxPopDown()
5526 if (!ICSInputBoxUp) return;
5528 XtPopdown(ICSInputShell);
5529 ICSInputBoxUp = False;
5531 XtSetArg(args[j], XtNleftBitmap, None); j++;
5532 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
5536 void CommentPopUp(title, text)
5543 if (commentShell == NULL) {
5545 CommentCreate(title, text, False, CommentCallback, 4);
5546 XtRealizeWidget(commentShell);
5547 CatchDeleteWindow(commentShell, "CommentPopDown");
5549 edit = XtNameToWidget(commentShell, "*form.text");
5551 XtSetArg(args[j], XtNstring, text); j++;
5552 XtSetValues(edit, args, j);
5554 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5555 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5556 XtSetValues(commentShell, args, j);
5559 XtPopup(commentShell, XtGrabNone);
5560 XSync(xDisplay, False);
5565 void AnalysisPopUp(title, text)
5572 if (analysisShell == NULL) {
5573 analysisShell = MiscCreate(title, text, False, NULL, 4);
5574 XtRealizeWidget(analysisShell);
5575 CatchDeleteWindow(analysisShell, "AnalysisPopDown");
5578 edit = XtNameToWidget(analysisShell, "*form.text");
5580 XtSetArg(args[j], XtNstring, text); j++;
5581 XtSetValues(edit, args, j);
5583 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5584 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5585 XtSetValues(analysisShell, args, j);
5589 XtPopup(analysisShell, XtGrabNone);
5591 XSync(xDisplay, False);
5596 void CommentCallback(w, client_data, call_data)
5598 XtPointer client_data, call_data;
5605 XtSetArg(args[j], XtNlabel, &name); j++;
5606 XtGetValues(w, args, j);
5608 if (strcmp(name, _("close")) == 0) {
5610 } else if (strcmp(name, _("edit")) == 0) {
5617 void CommentPopDown()
5622 if (!commentUp) return;
5624 XtSetArg(args[j], XtNx, &commentX); j++;
5625 XtSetArg(args[j], XtNy, &commentY); j++;
5626 XtSetArg(args[j], XtNwidth, &commentW); j++;
5627 XtSetArg(args[j], XtNheight, &commentH); j++;
5628 XtGetValues(commentShell, args, j);
5629 XtPopdown(commentShell);
5630 XSync(xDisplay, False);
5634 void AnalysisPopDown()
5636 if (!analysisUp) return;
5637 XtPopdown(analysisShell);
5638 XSync(xDisplay, False);
5640 if (appData.icsEngineAnalyze) ExitAnalyzeMode(); /* [DM] icsEngineAnalyze */
5644 void FileNamePopUp(label, def, proc, openMode)
5651 Widget popup, layout, dialog, edit;
5657 fileProc = proc; /* I can't see a way not */
5658 fileOpenMode = openMode; /* to use globals here */
5661 XtSetArg(args[i], XtNresizable, True); i++;
5662 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
5663 XtSetArg(args[i], XtNtitle, XtNewString(_("File name prompt"))); i++;
5664 fileNameShell = popup =
5665 XtCreatePopupShell("File name prompt", transientShellWidgetClass,
5666 shellWidget, args, i);
5669 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
5670 layoutArgs, XtNumber(layoutArgs));
5673 XtSetArg(args[i], XtNlabel, label); i++;
5674 XtSetArg(args[i], XtNvalue, def); i++;
5675 XtSetArg(args[i], XtNborderWidth, 0); i++;
5676 dialog = XtCreateManagedWidget("fileName", dialogWidgetClass,
5679 XawDialogAddButton(dialog, _("ok"), FileNameCallback, (XtPointer) dialog);
5680 XawDialogAddButton(dialog, _("cancel"), FileNameCallback,
5681 (XtPointer) dialog);
5683 XtRealizeWidget(popup);
5684 CatchDeleteWindow(popup, "FileNamePopDown");
5686 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
5687 &x, &y, &win_x, &win_y, &mask);
5689 XtSetArg(args[0], XtNx, x - 10);
5690 XtSetArg(args[1], XtNy, y - 30);
5691 XtSetValues(popup, args, 2);
5693 XtPopup(popup, XtGrabExclusive);
5696 edit = XtNameToWidget(dialog, "*value");
5697 XtSetKeyboardFocus(popup, edit);
5700 void FileNamePopDown()
5702 if (!filenameUp) return;
5703 XtPopdown(fileNameShell);
5704 XtDestroyWidget(fileNameShell);
5709 void FileNameCallback(w, client_data, call_data)
5711 XtPointer client_data, call_data;
5716 XtSetArg(args[0], XtNlabel, &name);
5717 XtGetValues(w, args, 1);
5719 if (strcmp(name, _("cancel")) == 0) {
5724 FileNameAction(w, NULL, NULL, NULL);
5727 void FileNameAction(w, event, prms, nprms)
5739 name = XawDialogGetValueString(w = XtParent(w));
5741 if ((name != NULL) && (*name != NULLCHAR)) {
5743 XtPopdown(w = XtParent(XtParent(w)));
5747 p = strrchr(buf, ' ');
5754 fullname = ExpandPathName(buf);
5756 ErrorPopUp(_("Error"), _("Can't open file"), FALSE);
5759 f = fopen(fullname, fileOpenMode);
5761 DisplayError(_("Failed to open file"), errno);
5763 (void) (*fileProc)(f, index, buf);
5770 XtPopdown(w = XtParent(XtParent(w)));
5776 void PromotionPopUp()
5779 Widget dialog, layout;
5781 Dimension bw_width, pw_width;
5785 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5786 XtGetValues(boardWidget, args, j);
5789 XtSetArg(args[j], XtNresizable, True); j++;
5790 XtSetArg(args[j], XtNtitle, XtNewString(_("Promotion"))); j++;
5792 XtCreatePopupShell("Promotion", transientShellWidgetClass,
5793 shellWidget, args, j);
5795 XtCreateManagedWidget(layoutName, formWidgetClass, promotionShell,
5796 layoutArgs, XtNumber(layoutArgs));
5799 XtSetArg(args[j], XtNlabel, _("Promote pawn to what?")); j++;
5800 XtSetArg(args[j], XtNborderWidth, 0); j++;
5801 dialog = XtCreateManagedWidget("promotion", dialogWidgetClass,
5804 XawDialogAddButton(dialog, _("Queen"), PromotionCallback,
5805 (XtPointer) dialog);
5806 XawDialogAddButton(dialog, _("Rook"), PromotionCallback,
5807 (XtPointer) dialog);
5808 XawDialogAddButton(dialog, _("Bishop"), PromotionCallback,
5809 (XtPointer) dialog);
5810 XawDialogAddButton(dialog, _("Knight"), PromotionCallback,
5811 (XtPointer) dialog);
5812 if (!appData.testLegality || gameInfo.variant == VariantSuicide ||
5813 gameInfo.variant == VariantGiveaway) {
5814 XawDialogAddButton(dialog, _("King"), PromotionCallback,
5815 (XtPointer) dialog);
5817 XawDialogAddButton(dialog, _("cancel"), PromotionCallback,
5818 (XtPointer) dialog);
5820 XtRealizeWidget(promotionShell);
5821 CatchDeleteWindow(promotionShell, "PromotionPopDown");
5824 XtSetArg(args[j], XtNwidth, &pw_width); j++;
5825 XtGetValues(promotionShell, args, j);
5827 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
5828 lineGap + squareSize/3 +
5829 ((toY == BOARD_HEIGHT-1) ^ (flipView) ?
5830 0 : 6*(squareSize + lineGap)), &x, &y);
5833 XtSetArg(args[j], XtNx, x); j++;
5834 XtSetArg(args[j], XtNy, y); j++;
5835 XtSetValues(promotionShell, args, j);
5837 XtPopup(promotionShell, XtGrabNone);
5842 void PromotionPopDown()
5844 if (!promotionUp) return;
5845 XtPopdown(promotionShell);
5846 XtDestroyWidget(promotionShell);
5847 promotionUp = False;
5850 void PromotionCallback(w, client_data, call_data)
5852 XtPointer client_data, call_data;
5858 XtSetArg(args[0], XtNlabel, &name);
5859 XtGetValues(w, args, 1);
5863 if (fromX == -1) return;
5865 if (strcmp(name, _("cancel")) == 0) {
5869 } else if (strcmp(name, _("Knight")) == 0) {
5872 promoChar = ToLower(name[0]);
5875 UserMoveEvent(fromX, fromY, toX, toY, promoChar);
5877 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
5878 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
5883 void ErrorCallback(w, client_data, call_data)
5885 XtPointer client_data, call_data;
5888 XtPopdown(w = XtParent(XtParent(XtParent(w))));
5890 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
5896 if (!errorUp) return;
5898 XtPopdown(errorShell);
5899 XtDestroyWidget(errorShell);
5900 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
5903 void ErrorPopUp(title, label, modal)
5904 char *title, *label;
5908 Widget dialog, layout;
5912 Dimension bw_width, pw_width;
5913 Dimension pw_height;
5917 XtSetArg(args[i], XtNresizable, True); i++;
5918 XtSetArg(args[i], XtNtitle, title); i++;
5920 XtCreatePopupShell("errorpopup", transientShellWidgetClass,
5921 shellWidget, args, i);
5923 XtCreateManagedWidget(layoutName, formWidgetClass, errorShell,
5924 layoutArgs, XtNumber(layoutArgs));
5927 XtSetArg(args[i], XtNlabel, label); i++;
5928 XtSetArg(args[i], XtNborderWidth, 0); i++;
5929 dialog = XtCreateManagedWidget("dialog", dialogWidgetClass,
5932 XawDialogAddButton(dialog, _("ok"), ErrorCallback, (XtPointer) dialog);
5934 XtRealizeWidget(errorShell);
5935 CatchDeleteWindow(errorShell, "ErrorPopDown");
5938 XtSetArg(args[i], XtNwidth, &bw_width); i++;
5939 XtGetValues(boardWidget, args, i);
5941 XtSetArg(args[i], XtNwidth, &pw_width); i++;
5942 XtSetArg(args[i], XtNheight, &pw_height); i++;
5943 XtGetValues(errorShell, args, i);
5946 /* This code seems to tickle an X bug if it is executed too soon
5947 after xboard starts up. The coordinates get transformed as if
5948 the main window was positioned at (0, 0).
5950 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
5951 0 - pw_height + squareSize / 3, &x, &y);
5953 XTranslateCoordinates(xDisplay, XtWindow(boardWidget),
5954 RootWindowOfScreen(XtScreen(boardWidget)),
5955 (bw_width - pw_width) / 2,
5956 0 - pw_height + squareSize / 3, &xx, &yy, &junk);
5960 if (y < 0) y = 0; /*avoid positioning top offscreen*/
5963 XtSetArg(args[i], XtNx, x); i++;
5964 XtSetArg(args[i], XtNy, y); i++;
5965 XtSetValues(errorShell, args, i);
5968 XtPopup(errorShell, modal ? XtGrabExclusive : XtGrabNone);
5971 /* Disable all user input other than deleting the window */
5972 static int frozen = 0;
5976 /* Grab by a widget that doesn't accept input */
5977 XtAddGrab(messageWidget, TRUE, FALSE);
5981 /* Undo a FreezeUI */
5984 if (!frozen) return;
5985 XtRemoveGrab(messageWidget);
5989 char *ModeToWidgetName(mode)
5993 case BeginningOfGame:
5994 if (appData.icsActive)
5995 return "menuMode.ICS Client";
5996 else if (appData.noChessProgram ||
5997 *appData.cmailGameName != NULLCHAR)
5998 return "menuMode.Edit Game";
6000 return "menuMode.Machine Black";
6001 case MachinePlaysBlack:
6002 return "menuMode.Machine Black";
6003 case MachinePlaysWhite:
6004 return "menuMode.Machine White";
6006 return "menuMode.Analysis Mode";
6008 return "menuMode.Analyze File";
6009 case TwoMachinesPlay:
6010 return "menuMode.Two Machines";
6012 return "menuMode.Edit Game";
6013 case PlayFromGameFile:
6014 return "menuFile.Load Game";
6016 return "menuMode.Edit Position";
6018 return "menuMode.Training";
6019 case IcsPlayingWhite:
6020 case IcsPlayingBlack:
6024 return "menuMode.ICS Client";
6031 void ModeHighlight()
6034 static int oldPausing = FALSE;
6035 static GameMode oldmode = (GameMode) -1;
6038 if (!boardWidget || !XtIsRealized(boardWidget)) return;
6040 if (pausing != oldPausing) {
6041 oldPausing = pausing;
6043 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6045 XtSetArg(args[0], XtNleftBitmap, None);
6047 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Pause"),
6050 if (appData.showButtonBar) {
6053 XtSetArg(args[0], XtNbackground, buttonForegroundPixel);
6054 XtSetArg(args[1], XtNforeground, buttonBackgroundPixel);
6056 XtSetArg(args[0], XtNbackground, buttonBackgroundPixel);
6057 XtSetArg(args[1], XtNforeground, buttonForegroundPixel);
6060 /* Always toggle, don't set. Previous code messes up when
6061 invoked while the button is pressed, as releasing it
6062 toggles the state again. */
6065 XtSetArg(args[0], XtNbackground, &oldbg);
6066 XtSetArg(args[1], XtNforeground, &oldfg);
6067 XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON),
6069 XtSetArg(args[0], XtNbackground, oldfg);
6070 XtSetArg(args[1], XtNforeground, oldbg);
6073 XtSetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
6077 wname = ModeToWidgetName(oldmode);
6078 if (wname != NULL) {
6079 XtSetArg(args[0], XtNleftBitmap, None);
6080 XtSetValues(XtNameToWidget(menuBarWidget, wname), args, 1);
6082 wname = ModeToWidgetName(gameMode);
6083 if (wname != NULL) {
6084 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6085 XtSetValues(XtNameToWidget(menuBarWidget, wname), args, 1);
6089 /* Maybe all the enables should be handled here, not just this one */
6090 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Training"),
6091 gameMode == Training || gameMode == PlayFromGameFile);
6096 * Button/menu procedures
6098 void ResetProc(w, event, prms, nprms)
6108 int LoadGamePopUp(f, gameNumber, title)
6113 cmailMsgLoaded = FALSE;
6114 if (gameNumber == 0) {
6115 int error = GameListBuild(f);
6117 DisplayError(_("Cannot build game list"), error);
6118 } else if (!ListEmpty(&gameList) &&
6119 ((ListGame *) gameList.tailPred)->number > 1) {
6120 GameListPopUp(f, title);
6126 return LoadGame(f, gameNumber, title, FALSE);
6129 void LoadGameProc(w, event, prms, nprms)
6135 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
6138 FileNamePopUp(_("Load game file name?"), "", LoadGamePopUp, "rb");
6141 void LoadNextGameProc(w, event, prms, nprms)
6150 void LoadPrevGameProc(w, event, prms, nprms)
6159 void ReloadGameProc(w, event, prms, nprms)
6168 void LoadNextPositionProc(w, event, prms, nprms)
6177 void LoadPrevPositionProc(w, event, prms, nprms)
6186 void ReloadPositionProc(w, event, prms, nprms)
6195 void LoadPositionProc(w, event, prms, nprms)
6201 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
6204 FileNamePopUp(_("Load position file name?"), "", LoadPosition, "rb");
6207 void SaveGameProc(w, event, prms, nprms)
6213 FileNamePopUp(_("Save game file name?"),
6214 DefaultFileName(appData.oldSaveStyle ? "game" : "pgn"),
6218 void SavePositionProc(w, event, prms, nprms)
6224 FileNamePopUp(_("Save position file name?"),
6225 DefaultFileName(appData.oldSaveStyle ? "pos" : "fen"),
6229 void ReloadCmailMsgProc(w, event, prms, nprms)
6235 ReloadCmailMsgEvent(FALSE);
6238 void MailMoveProc(w, event, prms, nprms)
6247 /* this variable is shared between CopyPositionProc and SendPositionSelection */
6248 static char *selected_fen_position=NULL;
6251 SendPositionSelection(Widget w, Atom *selection, Atom *target,
6252 Atom *type_return, XtPointer *value_return,
6253 unsigned long *length_return, int *format_return)
6255 char *selection_tmp;
6257 if (!selected_fen_position) return False; /* should never happen */
6258 if (*target == XA_STRING){
6259 /* note: since no XtSelectionDoneProc was registered, Xt will
6260 * automatically call XtFree on the value returned. So have to
6261 * make a copy of it allocated with XtMalloc */
6262 selection_tmp= XtMalloc(strlen(selected_fen_position)+16);
6263 strcpy(selection_tmp, selected_fen_position);
6265 *value_return=selection_tmp;
6266 *length_return=strlen(selection_tmp);
6267 *type_return=XA_STRING;
6268 *format_return = 8; /* bits per byte */
6275 /* note: when called from menu all parameters are NULL, so no clue what the
6276 * Widget which was clicked on was, or what the click event was
6278 void CopyPositionProc(w, event, prms, nprms)
6286 if (selected_fen_position) free(selected_fen_position);
6287 selected_fen_position = (char *)PositionToFEN(currentMove, NULL);
6288 if (!selected_fen_position) return;
6289 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
6291 SendPositionSelection,
6292 NULL/* lose_ownership_proc */ ,
6293 NULL/* transfer_done_proc */);
6295 free(selected_fen_position);
6296 selected_fen_position=NULL;
6300 /* function called when the data to Paste is ready */
6302 PastePositionCB(Widget w, XtPointer client_data, Atom *selection,
6303 Atom *type, XtPointer value, unsigned long *len, int *format)
6306 if (value==NULL || *len==0) return; /* nothing had been selected to copy */
6307 fenstr[*len]='\0'; /* normally this string is terminated, but be safe */
6308 EditPositionPasteFEN(fenstr);
6312 /* called when Paste Position button is pressed,
6313 * all parameters will be NULL */
6314 void PastePositionProc(w, event, prms, nprms)
6320 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
6321 /* (XtSelectionCallbackProc) */ PastePositionCB,
6322 NULL, /* client_data passed to PastePositionCB */
6324 /* better to use the time field from the event that triggered the
6325 * call to this function, but that isn't trivial to get
6333 SendGameSelection(Widget w, Atom *selection, Atom *target,
6334 Atom *type_return, XtPointer *value_return,
6335 unsigned long *length_return, int *format_return)
6337 char *selection_tmp;
6339 if (*target == XA_STRING){
6340 FILE* f = fopen(gameCopyFilename, "r");
6343 if (f == NULL) return False;
6347 selection_tmp = XtMalloc(len + 1);
6348 count = fread(selection_tmp, 1, len, f);
6350 XtFree(selection_tmp);
6353 selection_tmp[len] = NULLCHAR;
6354 *value_return = selection_tmp;
6355 *length_return = len;
6356 *type_return = XA_STRING;
6357 *format_return = 8; /* bits per byte */
6364 /* note: when called from menu all parameters are NULL, so no clue what the
6365 * Widget which was clicked on was, or what the click event was
6367 void CopyGameProc(w, event, prms, nprms)
6375 ret = SaveGameToFile(gameCopyFilename, FALSE);
6378 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
6381 NULL/* lose_ownership_proc */ ,
6382 NULL/* transfer_done_proc */);
6385 /* function called when the data to Paste is ready */
6387 PasteGameCB(Widget w, XtPointer client_data, Atom *selection,
6388 Atom *type, XtPointer value, unsigned long *len, int *format)
6391 if (value == NULL || *len == 0) {
6392 return; /* nothing had been selected to copy */
6394 f = fopen(gamePasteFilename, "w");
6396 DisplayError(_("Can't open temp file"), errno);
6399 fwrite(value, 1, *len, f);
6402 LoadGameFromFile(gamePasteFilename, 0, gamePasteFilename, TRUE);
6405 /* called when Paste Game button is pressed,
6406 * all parameters will be NULL */
6407 void PasteGameProc(w, event, prms, nprms)
6413 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
6414 /* (XtSelectionCallbackProc) */ PasteGameCB,
6415 NULL, /* client_data passed to PasteGameCB */
6417 /* better to use the time field from the event that triggered the
6418 * call to this function, but that isn't trivial to get
6428 SaveGameProc(NULL, NULL, NULL, NULL);
6432 void QuitProc(w, event, prms, nprms)
6441 void PauseProc(w, event, prms, nprms)
6451 void MachineBlackProc(w, event, prms, nprms)
6457 MachineBlackEvent();
6460 void MachineWhiteProc(w, event, prms, nprms)
6466 MachineWhiteEvent();
6469 void AnalyzeModeProc(w, event, prms, nprms)
6477 if (!first.analysisSupport) {
6478 sprintf(buf, _("%s does not support analysis"), first.tidy);
6479 DisplayError(buf, 0);
6482 /* [DM] icsEngineAnalyze [HGM] This is horrible code; reverse the gameMode and isEngineAnalyze tests! */
6483 if (appData.icsActive) {
6484 if (gameMode != IcsObserving) {
6485 sprintf(buf,_("You are not observing a game"));
6486 DisplayError(buf, 0);
6488 if (appData.icsEngineAnalyze) {
6489 if (appData.debugMode)
6490 fprintf(debugFP, _("Found unexpected active ICS engine analyze \n"));
6496 /* if enable, use want disable icsEngineAnalyze */
6497 if (appData.icsEngineAnalyze) {
6502 appData.icsEngineAnalyze = TRUE;
6503 if (appData.debugMode)
6504 fprintf(debugFP, _("ICS engine analyze starting... \n"));
6506 if (!appData.showThinking)
6507 ShowThinkingProc(w,event,prms,nprms);
6512 void AnalyzeFileProc(w, event, prms, nprms)
6518 if (!first.analysisSupport) {
6520 sprintf(buf, _("%s does not support analysis"), first.tidy);
6521 DisplayError(buf, 0);
6526 if (!appData.showThinking)
6527 ShowThinkingProc(w,event,prms,nprms);
6530 FileNamePopUp(_("File to analyze"), "", LoadGamePopUp, "rb");
6531 AnalysisPeriodicEvent(1);
6534 void TwoMachinesProc(w, event, prms, nprms)
6543 void IcsClientProc(w, event, prms, nprms)
6552 void EditGameProc(w, event, prms, nprms)
6561 void EditPositionProc(w, event, prms, nprms)
6567 EditPositionEvent();
6570 void TrainingProc(w, event, prms, nprms)
6579 void EditCommentProc(w, event, prms, nprms)
6586 EditCommentPopDown();
6592 void IcsInputBoxProc(w, event, prms, nprms)
6598 if (ICSInputBoxUp) {
6599 ICSInputBoxPopDown();
6605 void AcceptProc(w, event, prms, nprms)
6614 void DeclineProc(w, event, prms, nprms)
6623 void RematchProc(w, event, prms, nprms)
6632 void CallFlagProc(w, event, prms, nprms)
6641 void DrawProc(w, event, prms, nprms)
6650 void AbortProc(w, event, prms, nprms)
6659 void AdjournProc(w, event, prms, nprms)
6668 void ResignProc(w, event, prms, nprms)
6677 void AdjuWhiteProc(w, event, prms, nprms)
6683 UserAdjudicationEvent(+1);
6686 void AdjuBlackProc(w, event, prms, nprms)
6692 UserAdjudicationEvent(-1);
6695 void AdjuDrawProc(w, event, prms, nprms)
6701 UserAdjudicationEvent(0);
6704 void EnterKeyProc(w, event, prms, nprms)
6710 if (ICSInputBoxUp == True)
6714 void StopObservingProc(w, event, prms, nprms)
6720 StopObservingEvent();
6723 void StopExaminingProc(w, event, prms, nprms)
6729 StopExaminingEvent();
6733 void ForwardProc(w, event, prms, nprms)
6743 void BackwardProc(w, event, prms, nprms)
6752 void ToStartProc(w, event, prms, nprms)
6761 void ToEndProc(w, event, prms, nprms)
6770 void RevertProc(w, event, prms, nprms)
6779 void TruncateGameProc(w, event, prms, nprms)
6785 TruncateGameEvent();
6787 void RetractMoveProc(w, event, prms, nprms)
6796 void MoveNowProc(w, event, prms, nprms)
6806 void AlwaysQueenProc(w, event, prms, nprms)
6814 appData.alwaysPromoteToQueen = !appData.alwaysPromoteToQueen;
6816 if (appData.alwaysPromoteToQueen) {
6817 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6819 XtSetArg(args[0], XtNleftBitmap, None);
6821 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
6825 void AnimateDraggingProc(w, event, prms, nprms)
6833 appData.animateDragging = !appData.animateDragging;
6835 if (appData.animateDragging) {
6836 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6839 XtSetArg(args[0], XtNleftBitmap, None);
6841 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Dragging"),
6845 void AnimateMovingProc(w, event, prms, nprms)
6853 appData.animate = !appData.animate;
6855 if (appData.animate) {
6856 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6859 XtSetArg(args[0], XtNleftBitmap, None);
6861 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
6865 void AutocommProc(w, event, prms, nprms)
6873 appData.autoComment = !appData.autoComment;
6875 if (appData.autoComment) {
6876 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6878 XtSetArg(args[0], XtNleftBitmap, None);
6880 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
6885 void AutoflagProc(w, event, prms, nprms)
6893 appData.autoCallFlag = !appData.autoCallFlag;
6895 if (appData.autoCallFlag) {
6896 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6898 XtSetArg(args[0], XtNleftBitmap, None);
6900 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
6904 void AutoflipProc(w, event, prms, nprms)
6912 appData.autoFlipView = !appData.autoFlipView;
6914 if (appData.autoFlipView) {
6915 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6917 XtSetArg(args[0], XtNleftBitmap, None);
6919 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flip View"),
6923 void AutobsProc(w, event, prms, nprms)
6931 appData.autoObserve = !appData.autoObserve;
6933 if (appData.autoObserve) {
6934 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6936 XtSetArg(args[0], XtNleftBitmap, None);
6938 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
6942 void AutoraiseProc(w, event, prms, nprms)
6950 appData.autoRaiseBoard = !appData.autoRaiseBoard;
6952 if (appData.autoRaiseBoard) {
6953 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6955 XtSetArg(args[0], XtNleftBitmap, None);
6957 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Raise Board"),
6961 void AutosaveProc(w, event, prms, nprms)
6969 appData.autoSaveGames = !appData.autoSaveGames;
6971 if (appData.autoSaveGames) {
6972 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6974 XtSetArg(args[0], XtNleftBitmap, None);
6976 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
6980 void BlindfoldProc(w, event, prms, nprms)
6988 appData.blindfold = !appData.blindfold;
6990 if (appData.blindfold) {
6991 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6993 XtSetArg(args[0], XtNleftBitmap, None);
6995 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Blindfold"),
6998 DrawPosition(True, NULL);
7001 void TestLegalityProc(w, event, prms, nprms)
7009 appData.testLegality = !appData.testLegality;
7011 if (appData.testLegality) {
7012 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7014 XtSetArg(args[0], XtNleftBitmap, None);
7016 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Test Legality"),
7021 void FlashMovesProc(w, event, prms, nprms)
7029 if (appData.flashCount == 0) {
7030 appData.flashCount = 3;
7032 appData.flashCount = -appData.flashCount;
7035 if (appData.flashCount > 0) {
7036 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7038 XtSetArg(args[0], XtNleftBitmap, None);
7040 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flash Moves"),
7044 void FlipViewProc(w, event, prms, nprms)
7050 flipView = !flipView;
7051 DrawPosition(True, NULL);
7054 void GetMoveListProc(w, event, prms, nprms)
7062 appData.getMoveList = !appData.getMoveList;
7064 if (appData.getMoveList) {
7065 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7068 XtSetArg(args[0], XtNleftBitmap, None);
7070 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
7075 void HighlightDraggingProc(w, event, prms, nprms)
7083 appData.highlightDragging = !appData.highlightDragging;
7085 if (appData.highlightDragging) {
7086 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7088 XtSetArg(args[0], XtNleftBitmap, None);
7090 XtSetValues(XtNameToWidget(menuBarWidget,
7091 "menuOptions.Highlight Dragging"), args, 1);
7095 void HighlightLastMoveProc(w, event, prms, nprms)
7103 appData.highlightLastMove = !appData.highlightLastMove;
7105 if (appData.highlightLastMove) {
7106 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7108 XtSetArg(args[0], XtNleftBitmap, None);
7110 XtSetValues(XtNameToWidget(menuBarWidget,
7111 "menuOptions.Highlight Last Move"), args, 1);
7114 void IcsAlarmProc(w, event, prms, nprms)
7122 appData.icsAlarm = !appData.icsAlarm;
7124 if (appData.icsAlarm) {
7125 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7127 XtSetArg(args[0], XtNleftBitmap, None);
7129 XtSetValues(XtNameToWidget(menuBarWidget,
7130 "menuOptions.ICS Alarm"), args, 1);
7133 void MoveSoundProc(w, event, prms, nprms)
7141 appData.ringBellAfterMoves = !appData.ringBellAfterMoves;
7143 if (appData.ringBellAfterMoves) {
7144 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7146 XtSetArg(args[0], XtNleftBitmap, None);
7148 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
7153 void OldSaveStyleProc(w, event, prms, nprms)
7161 appData.oldSaveStyle = !appData.oldSaveStyle;
7163 if (appData.oldSaveStyle) {
7164 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7166 XtSetArg(args[0], XtNleftBitmap, None);
7168 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Old Save Style"),
7172 void PeriodicUpdatesProc(w, event, prms, nprms)
7180 PeriodicUpdatesEvent(!appData.periodicUpdates);
7182 if (appData.periodicUpdates) {
7183 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7185 XtSetArg(args[0], XtNleftBitmap, None);
7187 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Periodic Updates"),
7191 void PonderNextMoveProc(w, event, prms, nprms)
7199 PonderNextMoveEvent(!appData.ponderNextMove);
7201 if (appData.ponderNextMove) {
7202 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7204 XtSetArg(args[0], XtNleftBitmap, None);
7206 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Ponder Next Move"),
7210 void PopupExitMessageProc(w, event, prms, nprms)
7218 appData.popupExitMessage = !appData.popupExitMessage;
7220 if (appData.popupExitMessage) {
7221 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7223 XtSetArg(args[0], XtNleftBitmap, None);
7225 XtSetValues(XtNameToWidget(menuBarWidget,
7226 "menuOptions.Popup Exit Message"), args, 1);
7229 void PopupMoveErrorsProc(w, event, prms, nprms)
7237 appData.popupMoveErrors = !appData.popupMoveErrors;
7239 if (appData.popupMoveErrors) {
7240 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7242 XtSetArg(args[0], XtNleftBitmap, None);
7244 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Popup Move Errors"),
7248 void PremoveProc(w, event, prms, nprms)
7256 appData.premove = !appData.premove;
7258 if (appData.premove) {
7259 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7261 XtSetArg(args[0], XtNleftBitmap, None);
7263 XtSetValues(XtNameToWidget(menuBarWidget,
7264 "menuOptions.Premove"), args, 1);
7267 void QuietPlayProc(w, event, prms, nprms)
7275 appData.quietPlay = !appData.quietPlay;
7277 if (appData.quietPlay) {
7278 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7280 XtSetArg(args[0], XtNleftBitmap, None);
7282 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Quiet Play"),
7286 void ShowCoordsProc(w, event, prms, nprms)
7294 appData.showCoords = !appData.showCoords;
7296 if (appData.showCoords) {
7297 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7299 XtSetArg(args[0], XtNleftBitmap, None);
7301 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
7304 DrawPosition(True, NULL);
7307 void ShowThinkingProc(w, event, prms, nprms)
7315 appData.showThinking = !appData.showThinking; // [HGM] thinking: tken out of ShowThinkingEvent
7316 ShowThinkingEvent();
7318 // [HGM] thinking: currently no suc menu item; replaced by Hide Thinking (From Human)
7319 if (appData.showThinking) {
7320 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7322 XtSetArg(args[0], XtNleftBitmap, None);
7324 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Thinking"),
7329 void HideThinkingProc(w, event, prms, nprms)
7337 appData.hideThinkingFromHuman = !appData.hideThinkingFromHuman; // [HGM] thinking: tken out of ShowThinkingEvent
7338 ShowThinkingEvent();
7340 if (appData.hideThinkingFromHuman) {
7341 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7343 XtSetArg(args[0], XtNleftBitmap, None);
7345 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
7349 void InfoProc(w, event, prms, nprms)
7356 sprintf(buf, "xterm -e info --directory %s --directory . -f %s &",
7361 void ManProc(w, event, prms, nprms)
7369 if (nprms && *nprms > 0)
7373 sprintf(buf, "xterm -e man %s &", name);
7377 void HintProc(w, event, prms, nprms)
7386 void BookProc(w, event, prms, nprms)
7395 void AboutProc(w, event, prms, nprms)
7403 char *zippy = " (with Zippy code)";
7407 sprintf(buf, "%s%s\n\n%s\n%s\n%s\n\n%s%s\n%s",
7408 programVersion, zippy,
7409 "Copyright 1991 Digital Equipment Corporation",
7410 "Enhancements Copyright 1992-2009 Free Software Foundation",
7411 "Enhancements Copyright 2005 Alessandro Scotti",
7412 PRODUCT, " is free software and carries NO WARRANTY;",
7413 "see the file COPYING for more information.");
7414 ErrorPopUp(_("About XBoard"), buf, FALSE);
7417 void DebugProc(w, event, prms, nprms)
7423 appData.debugMode = !appData.debugMode;
7426 void AboutGameProc(w, event, prms, nprms)
7435 void NothingProc(w, event, prms, nprms)
7444 void Iconify(w, event, prms, nprms)
7453 XtSetArg(args[0], XtNiconic, True);
7454 XtSetValues(shellWidget, args, 1);
7457 void DisplayMessage(message, extMessage)
7458 char *message, *extMessage;
7465 sprintf(buf, "%s %s", message, extMessage);
7468 message = extMessage;
7471 XtSetArg(arg, XtNlabel, message);
7472 XtSetValues(messageWidget, &arg, 1);
7475 void DisplayTitle(text)
7480 char title[MSG_SIZ];
7483 if (text == NULL) text = "";
7485 if (appData.titleInWindow) {
7487 XtSetArg(args[i], XtNlabel, text); i++;
7488 XtSetValues(titleWidget, args, i);
7491 if (*text != NULLCHAR) {
7493 strcpy(title, text);
7494 } else if (appData.icsActive) {
7495 sprintf(icon, "%s", appData.icsHost);
7496 sprintf(title, "%s: %s", programName, appData.icsHost);
7497 } else if (appData.cmailGameName[0] != NULLCHAR) {
7498 sprintf(icon, "%s", "CMail");
7499 sprintf(title, "%s: %s", programName, "CMail");
7501 // [HGM] license: This stuff should really be done in back-end, but WinBoard already had a pop-up for it
7502 } else if (gameInfo.variant == VariantGothic) {
7503 strcpy(icon, programName);
7504 strcpy(title, GOTHIC);
7507 } else if (gameInfo.variant == VariantFalcon) {
7508 strcpy(icon, programName);
7509 strcpy(title, FALCON);
7511 } else if (appData.noChessProgram) {
7512 strcpy(icon, programName);
7513 strcpy(title, programName);
7515 strcpy(icon, first.tidy);
7516 sprintf(title, "%s: %s", programName, first.tidy);
7519 XtSetArg(args[i], XtNiconName, (XtArgVal) icon); i++;
7520 XtSetArg(args[i], XtNtitle, (XtArgVal) title); i++;
7521 XtSetValues(shellWidget, args, i);
7525 void DisplayError(message, error)
7532 if (appData.debugMode || appData.matchMode) {
7533 fprintf(stderr, "%s: %s\n", programName, message);
7536 if (appData.debugMode || appData.matchMode) {
7537 fprintf(stderr, "%s: %s: %s\n",
7538 programName, message, strerror(error));
7540 sprintf(buf, "%s: %s", message, strerror(error));
7543 ErrorPopUp(_("Error"), message, FALSE);
7547 void DisplayMoveError(message)
7552 DrawPosition(FALSE, NULL);
7553 if (appData.debugMode || appData.matchMode) {
7554 fprintf(stderr, "%s: %s\n", programName, message);
7556 if (appData.popupMoveErrors) {
7557 ErrorPopUp(_("Error"), message, FALSE);
7559 DisplayMessage(message, "");
7564 void DisplayFatalError(message, error, status)
7570 errorExitStatus = status;
7572 fprintf(stderr, "%s: %s\n", programName, message);
7574 fprintf(stderr, "%s: %s: %s\n",
7575 programName, message, strerror(error));
7576 sprintf(buf, "%s: %s", message, strerror(error));
7579 if (appData.popupExitMessage && boardWidget && XtIsRealized(boardWidget)) {
7580 ErrorPopUp(status ? _("Fatal Error") : _("Exiting"), message, TRUE);
7586 void DisplayInformation(message)
7590 ErrorPopUp(_("Information"), message, TRUE);
7593 void DisplayNote(message)
7597 ErrorPopUp(_("Note"), message, FALSE);
7601 NullXErrorCheck(dpy, error_event)
7603 XErrorEvent *error_event;
7608 void DisplayIcsInteractionTitle(message)
7611 if (oldICSInteractionTitle == NULL) {
7612 /* Magic to find the old window title, adapted from vim */
7613 char *wina = getenv("WINDOWID");
7615 Window win = (Window) atoi(wina);
7616 Window root, parent, *children;
7617 unsigned int nchildren;
7618 int (*oldHandler)() = XSetErrorHandler(NullXErrorCheck);
7620 if (XFetchName(xDisplay, win, &oldICSInteractionTitle)) break;
7621 if (!XQueryTree(xDisplay, win, &root, &parent,
7622 &children, &nchildren)) break;
7623 if (children) XFree((void *)children);
7624 if (parent == root || parent == 0) break;
7627 XSetErrorHandler(oldHandler);
7629 if (oldICSInteractionTitle == NULL) {
7630 oldICSInteractionTitle = "xterm";
7633 printf("\033]0;%s\007", message);
7637 char pendingReplyPrefix[MSG_SIZ];
7638 ProcRef pendingReplyPR;
7640 void AskQuestionProc(w, event, prms, nprms)
7647 fprintf(stderr, _("AskQuestionProc needed 4 parameters, got %d\n"),
7651 AskQuestionEvent(prms[0], prms[1], prms[2], prms[3]);
7654 void AskQuestionPopDown()
7656 if (!askQuestionUp) return;
7657 XtPopdown(askQuestionShell);
7658 XtDestroyWidget(askQuestionShell);
7659 askQuestionUp = False;
7662 void AskQuestionReplyAction(w, event, prms, nprms)
7672 reply = XawDialogGetValueString(w = XtParent(w));
7673 strcpy(buf, pendingReplyPrefix);
7674 if (*buf) strcat(buf, " ");
7677 OutputToProcess(pendingReplyPR, buf, strlen(buf), &err);
7678 AskQuestionPopDown();
7680 if (err) DisplayFatalError(_("Error writing to chess program"), err, 0);
7683 void AskQuestionCallback(w, client_data, call_data)
7685 XtPointer client_data, call_data;
7690 XtSetArg(args[0], XtNlabel, &name);
7691 XtGetValues(w, args, 1);
7693 if (strcmp(name, _("cancel")) == 0) {
7694 AskQuestionPopDown();
7696 AskQuestionReplyAction(w, NULL, NULL, NULL);
7700 void AskQuestion(title, question, replyPrefix, pr)
7701 char *title, *question, *replyPrefix;
7705 Widget popup, layout, dialog, edit;
7711 strcpy(pendingReplyPrefix, replyPrefix);
7712 pendingReplyPR = pr;
7715 XtSetArg(args[i], XtNresizable, True); i++;
7716 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
7717 askQuestionShell = popup =
7718 XtCreatePopupShell(title, transientShellWidgetClass,
7719 shellWidget, args, i);
7722 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
7723 layoutArgs, XtNumber(layoutArgs));
7726 XtSetArg(args[i], XtNlabel, question); i++;
7727 XtSetArg(args[i], XtNvalue, ""); i++;
7728 XtSetArg(args[i], XtNborderWidth, 0); i++;
7729 dialog = XtCreateManagedWidget("question", dialogWidgetClass,
7732 XawDialogAddButton(dialog, _("enter"), AskQuestionCallback,
7733 (XtPointer) dialog);
7734 XawDialogAddButton(dialog, _("cancel"), AskQuestionCallback,
7735 (XtPointer) dialog);
7737 XtRealizeWidget(popup);
7738 CatchDeleteWindow(popup, "AskQuestionPopDown");
7740 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
7741 &x, &y, &win_x, &win_y, &mask);
7743 XtSetArg(args[0], XtNx, x - 10);
7744 XtSetArg(args[1], XtNy, y - 30);
7745 XtSetValues(popup, args, 2);
7747 XtPopup(popup, XtGrabExclusive);
7748 askQuestionUp = True;
7750 edit = XtNameToWidget(dialog, "*value");
7751 XtSetKeyboardFocus(popup, edit);
7759 if (*name == NULLCHAR) {
7761 } else if (strcmp(name, "$") == 0) {
7762 putc(BELLCHAR, stderr);
7765 sprintf(buf, "%s '%s' &", appData.soundProgram, name);
7773 PlaySound(appData.soundMove);
7779 PlaySound(appData.soundIcsWin);
7785 PlaySound(appData.soundIcsLoss);
7791 PlaySound(appData.soundIcsDraw);
7795 PlayIcsUnfinishedSound()
7797 PlaySound(appData.soundIcsUnfinished);
7803 PlaySound(appData.soundIcsAlarm);
7809 system("stty echo");
7815 system("stty -echo");
7819 Colorize(cc, continuation)
7824 int count, outCount, error;
7826 if (textColors[(int)cc].bg > 0) {
7827 if (textColors[(int)cc].fg > 0) {
7828 sprintf(buf, "\033[0;%d;%d;%dm", textColors[(int)cc].attr,
7829 textColors[(int)cc].fg, textColors[(int)cc].bg);
7831 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
7832 textColors[(int)cc].bg);
7835 if (textColors[(int)cc].fg > 0) {
7836 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
7837 textColors[(int)cc].fg);
7839 sprintf(buf, "\033[0;%dm", textColors[(int)cc].attr);
7842 count = strlen(buf);
7843 outCount = OutputToProcess(NoProc, buf, count, &error);
7844 if (outCount < count) {
7845 DisplayFatalError(_("Error writing to display"), error, 1);
7848 if (continuation) return;
7851 PlaySound(appData.soundShout);
7854 PlaySound(appData.soundSShout);
7857 PlaySound(appData.soundChannel1);
7860 PlaySound(appData.soundChannel);
7863 PlaySound(appData.soundKibitz);
7866 PlaySound(appData.soundTell);
7868 case ColorChallenge:
7869 PlaySound(appData.soundChallenge);
7872 PlaySound(appData.soundRequest);
7875 PlaySound(appData.soundSeek);
7886 return getpwuid(getuid())->pw_name;
7889 static char *ExpandPathName(path)
7892 static char static_buf[2000];
7893 char *d, *s, buf[2000];
7899 while (*s && isspace(*s))
7908 if (*(s+1) == '/') {
7909 strcpy(d, getpwuid(getuid())->pw_dir);
7914 *strchr(buf, '/') = 0;
7915 pwd = getpwnam(buf);
7918 fprintf(stderr, _("ERROR: Unknown user %s (in path %s)\n"),
7922 strcpy(d, pwd->pw_dir);
7923 strcat(d, strchr(s+1, '/'));
7934 static char host_name[MSG_SIZ];
7936 #if HAVE_GETHOSTNAME
7937 gethostname(host_name, MSG_SIZ);
7939 #else /* not HAVE_GETHOSTNAME */
7940 # if HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H
7941 sysinfo(SI_HOSTNAME, host_name, MSG_SIZ);
7943 # else /* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
7945 # endif/* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
7946 #endif /* not HAVE_GETHOSTNAME */
7949 XtIntervalId delayedEventTimerXID = 0;
7950 DelayedEventCallback delayedEventCallback = 0;
7955 delayedEventTimerXID = 0;
7956 delayedEventCallback();
7960 ScheduleDelayedEvent(cb, millisec)
7961 DelayedEventCallback cb; long millisec;
7963 delayedEventCallback = cb;
7964 delayedEventTimerXID =
7965 XtAppAddTimeOut(appContext, millisec,
7966 (XtTimerCallbackProc) FireDelayedEvent, (XtPointer) 0);
7969 DelayedEventCallback
7972 if (delayedEventTimerXID) {
7973 return delayedEventCallback;
7980 CancelDelayedEvent()
7982 if (delayedEventTimerXID) {
7983 XtRemoveTimeOut(delayedEventTimerXID);
7984 delayedEventTimerXID = 0;
7988 XtIntervalId loadGameTimerXID = 0;
7990 int LoadGameTimerRunning()
7992 return loadGameTimerXID != 0;
7995 int StopLoadGameTimer()
7997 if (loadGameTimerXID != 0) {
7998 XtRemoveTimeOut(loadGameTimerXID);
7999 loadGameTimerXID = 0;
8007 LoadGameTimerCallback(arg, id)
8011 loadGameTimerXID = 0;
8016 StartLoadGameTimer(millisec)
8020 XtAppAddTimeOut(appContext, millisec,
8021 (XtTimerCallbackProc) LoadGameTimerCallback,
8025 XtIntervalId analysisClockXID = 0;
8028 AnalysisClockCallback(arg, id)
8032 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile
8033 || appData.icsEngineAnalyze) { // [DM]
8034 AnalysisPeriodicEvent(0);
8035 StartAnalysisClock();
8040 StartAnalysisClock()
8043 XtAppAddTimeOut(appContext, 2000,
8044 (XtTimerCallbackProc) AnalysisClockCallback,
8048 XtIntervalId clockTimerXID = 0;
8050 int ClockTimerRunning()
8052 return clockTimerXID != 0;
8055 int StopClockTimer()
8057 if (clockTimerXID != 0) {
8058 XtRemoveTimeOut(clockTimerXID);
8067 ClockTimerCallback(arg, id)
8076 StartClockTimer(millisec)
8080 XtAppAddTimeOut(appContext, millisec,
8081 (XtTimerCallbackProc) ClockTimerCallback,
8086 DisplayTimerLabel(w, color, timer, highlight)
8095 if (appData.clockMode) {
8096 sprintf(buf, "%s: %s", color, TimeString(timer));
8097 XtSetArg(args[0], XtNlabel, buf);
8099 sprintf(buf, "%s ", color);
8100 XtSetArg(args[0], XtNlabel, buf);
8104 XtSetArg(args[1], XtNbackground, timerForegroundPixel);
8105 XtSetArg(args[2], XtNforeground, timerBackgroundPixel);
8107 XtSetArg(args[1], XtNbackground, timerBackgroundPixel);
8108 XtSetArg(args[2], XtNforeground, timerForegroundPixel);
8111 XtSetValues(w, args, 3);
8115 DisplayWhiteClock(timeRemaining, highlight)
8121 if(appData.noGUI) return;
8122 DisplayTimerLabel(whiteTimerWidget, _("White"), timeRemaining, highlight);
8123 if (highlight && iconPixmap == bIconPixmap) {
8124 iconPixmap = wIconPixmap;
8125 XtSetArg(args[0], XtNiconPixmap, iconPixmap);
8126 XtSetValues(shellWidget, args, 1);
8131 DisplayBlackClock(timeRemaining, highlight)
8137 if(appData.noGUI) return;
8138 DisplayTimerLabel(blackTimerWidget, _("Black"), timeRemaining, highlight);
8139 if (highlight && iconPixmap == wIconPixmap) {
8140 iconPixmap = bIconPixmap;
8141 XtSetArg(args[0], XtNiconPixmap, iconPixmap);
8142 XtSetValues(shellWidget, args, 1);
8160 int StartChildProcess(cmdLine, dir, pr)
8167 int to_prog[2], from_prog[2];
8171 if (appData.debugMode) {
8172 fprintf(stderr, "StartChildProcess (dir=\"%s\") %s\n",dir, cmdLine);
8175 /* We do NOT feed the cmdLine to the shell; we just
8176 parse it into blank-separated arguments in the
8177 most simple-minded way possible.
8180 strcpy(buf, cmdLine);
8185 if (p == NULL) break;
8190 SetUpChildIO(to_prog, from_prog);
8192 if ((pid = fork()) == 0) {
8194 // [HGM] PSWBTM: made order resistant against case where fd of created pipe was 0 or 1
8195 close(to_prog[1]); // first close the unused pipe ends
8196 close(from_prog[0]);
8197 dup2(to_prog[0], 0); // to_prog was created first, nd is the only one to use 0 or 1
8198 dup2(from_prog[1], 1);
8199 if(to_prog[0] >= 2) close(to_prog[0]); // if 0 or 1, the dup2 already cosed the original
8200 close(from_prog[1]); // and closing again loses one of the pipes!
8201 if(fileno(stderr) >= 2) // better safe than sorry...
8202 dup2(1, fileno(stderr)); /* force stderr to the pipe */
8204 if (dir[0] != NULLCHAR && chdir(dir) != 0) {
8209 nice(appData.niceEngines); // [HGM] nice: adjust priority of engine proc
8211 execvp(argv[0], argv);
8213 /* If we get here, exec failed */
8218 /* Parent process */
8220 close(from_prog[1]);
8222 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8225 cp->fdFrom = from_prog[0];
8226 cp->fdTo = to_prog[1];
8231 // [HGM] kill: implement the 'hard killing' of AS's Winboard_x
8232 static RETSIGTYPE AlarmCallBack(int n)
8238 DestroyChildProcess(pr, signalType)
8242 ChildProc *cp = (ChildProc *) pr;
8244 if (cp->kind != CPReal) return;
8246 if (signalType == 10) { // [HGM] kill: if it does not terminate in 3 sec, kill
8247 signal(SIGALRM, AlarmCallBack);
8249 if(wait((int *) 0) == -1) { // process does not terminate on its own accord
8250 kill(cp->pid, SIGKILL); // kill it forcefully
8251 wait((int *) 0); // and wait again
8255 kill(cp->pid, signalType == 9 ? SIGKILL : SIGTERM); // [HGM] kill: use hard kill if so requested
8257 /* Process is exiting either because of the kill or because of
8258 a quit command sent by the backend; either way, wait for it to die.
8267 InterruptChildProcess(pr)
8270 ChildProc *cp = (ChildProc *) pr;
8272 if (cp->kind != CPReal) return;
8273 (void) kill(cp->pid, SIGINT); /* stop it thinking */
8276 int OpenTelnet(host, port, pr)
8281 char cmdLine[MSG_SIZ];
8283 if (port[0] == NULLCHAR) {
8284 sprintf(cmdLine, "%s %s", appData.telnetProgram, host);
8286 sprintf(cmdLine, "%s %s %s", appData.telnetProgram, host, port);
8288 return StartChildProcess(cmdLine, "", pr);
8291 int OpenTCP(host, port, pr)
8297 DisplayFatalError(_("Socket support is not configured in"), 0, 2);
8298 #else /* !OMIT_SOCKETS */
8300 struct sockaddr_in sa;
8302 unsigned short uport;
8305 if ((s = socket(AF_INET, SOCK_STREAM, 6)) < 0) {
8309 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
8310 sa.sin_family = AF_INET;
8311 sa.sin_addr.s_addr = INADDR_ANY;
8312 uport = (unsigned short) 0;
8313 sa.sin_port = htons(uport);
8314 if (bind(s, (struct sockaddr *) &sa, sizeof(struct sockaddr_in)) < 0) {
8318 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
8319 if (!(hp = gethostbyname(host))) {
8321 if (sscanf(host, "%d.%d.%d.%d", &b0, &b1, &b2, &b3) == 4) {
8322 hp = (struct hostent *) calloc(1, sizeof(struct hostent));
8323 hp->h_addrtype = AF_INET;
8325 hp->h_addr_list = (char **) calloc(2, sizeof(char *));
8326 hp->h_addr_list[0] = (char *) malloc(4);
8327 hp->h_addr_list[0][0] = b0;
8328 hp->h_addr_list[0][1] = b1;
8329 hp->h_addr_list[0][2] = b2;
8330 hp->h_addr_list[0][3] = b3;
8335 sa.sin_family = hp->h_addrtype;
8336 uport = (unsigned short) atoi(port);
8337 sa.sin_port = htons(uport);
8338 memcpy((char *) &sa.sin_addr, hp->h_addr, hp->h_length);
8340 if (connect(s, (struct sockaddr *) &sa,
8341 sizeof(struct sockaddr_in)) < 0) {
8345 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8352 #endif /* !OMIT_SOCKETS */
8357 int OpenCommPort(name, pr)
8364 fd = open(name, 2, 0);
8365 if (fd < 0) return errno;
8367 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8377 int OpenLoopback(pr)
8383 SetUpChildIO(to, from);
8385 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8388 cp->fdFrom = to[0]; /* note not from[0]; we are doing a loopback */
8395 int OpenRcmd(host, user, cmd, pr)
8396 char *host, *user, *cmd;
8399 DisplayFatalError(_("internal rcmd not implemented for Unix"), 0, 1);
8403 #define INPUT_SOURCE_BUF_SIZE 8192
8412 char buf[INPUT_SOURCE_BUF_SIZE];
8417 DoInputCallback(closure, source, xid)
8422 InputSource *is = (InputSource *) closure;
8427 if (is->lineByLine) {
8428 count = read(is->fd, is->unused,
8429 INPUT_SOURCE_BUF_SIZE - (is->unused - is->buf));
8431 (is->func)(is, is->closure, is->buf, count, count ? errno : 0);
8434 is->unused += count;
8436 while (p < is->unused) {
8437 q = memchr(p, '\n', is->unused - p);
8438 if (q == NULL) break;
8440 (is->func)(is, is->closure, p, q - p, 0);
8444 while (p < is->unused) {
8449 count = read(is->fd, is->buf, INPUT_SOURCE_BUF_SIZE);
8454 (is->func)(is, is->closure, is->buf, count, error);
8458 InputSourceRef AddInputSource(pr, lineByLine, func, closure)
8465 ChildProc *cp = (ChildProc *) pr;
8467 is = (InputSource *) calloc(1, sizeof(InputSource));
8468 is->lineByLine = lineByLine;
8472 is->fd = fileno(stdin);
8474 is->kind = cp->kind;
8475 is->fd = cp->fdFrom;
8478 is->unused = is->buf;
8481 is->xid = XtAppAddInput(appContext, is->fd,
8482 (XtPointer) (XtInputReadMask),
8483 (XtInputCallbackProc) DoInputCallback,
8485 is->closure = closure;
8486 return (InputSourceRef) is;
8490 RemoveInputSource(isr)
8493 InputSource *is = (InputSource *) isr;
8495 if (is->xid == 0) return;
8496 XtRemoveInput(is->xid);
8500 int OutputToProcess(pr, message, count, outError)
8506 ChildProc *cp = (ChildProc *) pr;
8510 outCount = fwrite(message, 1, count, stdout);
8512 outCount = write(cp->fdTo, message, count);
8522 /* Output message to process, with "ms" milliseconds of delay
8523 between each character. This is needed when sending the logon
8524 script to ICC, which for some reason doesn't like the
8525 instantaneous send. */
8526 int OutputToProcessDelayed(pr, message, count, outError, msdelay)
8533 ChildProc *cp = (ChildProc *) pr;
8538 r = write(cp->fdTo, message++, 1);
8551 /**** Animation code by Hugh Fisher, DCS, ANU.
8553 Known problem: if a window overlapping the board is
8554 moved away while a piece is being animated underneath,
8555 the newly exposed area won't be updated properly.
8556 I can live with this.
8558 Known problem: if you look carefully at the animation
8559 of pieces in mono mode, they are being drawn as solid
8560 shapes without interior detail while moving. Fixing
8561 this would be a major complication for minimal return.
8564 /* Masks for XPM pieces. Black and white pieces can have
8565 different shapes, but in the interest of retaining my
8566 sanity pieces must have the same outline on both light
8567 and dark squares, and all pieces must use the same
8568 background square colors/images. */
8571 CreateAnimMasks (pieceDepth)
8578 unsigned long plane;
8581 /* Need a bitmap just to get a GC with right depth */
8582 buf = XCreatePixmap(xDisplay, xBoardWindow,
8584 values.foreground = 1;
8585 values.background = 0;
8586 /* Don't use XtGetGC, not read only */
8587 maskGC = XCreateGC(xDisplay, buf,
8588 GCForeground | GCBackground, &values);
8589 XFreePixmap(xDisplay, buf);
8591 buf = XCreatePixmap(xDisplay, xBoardWindow,
8592 squareSize, squareSize, pieceDepth);
8593 values.foreground = XBlackPixel(xDisplay, xScreen);
8594 values.background = XWhitePixel(xDisplay, xScreen);
8595 bufGC = XCreateGC(xDisplay, buf,
8596 GCForeground | GCBackground, &values);
8598 for (piece = WhitePawn; piece <= BlackKing; piece++) {
8599 /* Begin with empty mask */
8600 xpmMask[piece] = XCreatePixmap(xDisplay, xBoardWindow,
8601 squareSize, squareSize, 1);
8602 XSetFunction(xDisplay, maskGC, GXclear);
8603 XFillRectangle(xDisplay, xpmMask[piece], maskGC,
8604 0, 0, squareSize, squareSize);
8606 /* Take a copy of the piece */
8611 XSetFunction(xDisplay, bufGC, GXcopy);
8612 XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % (int)BlackPawn],
8614 0, 0, squareSize, squareSize, 0, 0);
8616 /* XOR the background (light) over the piece */
8617 XSetFunction(xDisplay, bufGC, GXxor);
8619 XCopyArea(xDisplay, xpmLightSquare, buf, bufGC,
8620 0, 0, squareSize, squareSize, 0, 0);
8622 XSetForeground(xDisplay, bufGC, lightSquareColor);
8623 XFillRectangle(xDisplay, buf, bufGC, 0, 0, squareSize, squareSize);
8626 /* We now have an inverted piece image with the background
8627 erased. Construct mask by just selecting all the non-zero
8628 pixels - no need to reconstruct the original image. */
8629 XSetFunction(xDisplay, maskGC, GXor);
8631 /* Might be quicker to download an XImage and create bitmap
8632 data from it rather than this N copies per piece, but it
8633 only takes a fraction of a second and there is a much
8634 longer delay for loading the pieces. */
8635 for (n = 0; n < pieceDepth; n ++) {
8636 XCopyPlane(xDisplay, buf, xpmMask[piece], maskGC,
8637 0, 0, squareSize, squareSize,
8643 XFreePixmap(xDisplay, buf);
8644 XFreeGC(xDisplay, bufGC);
8645 XFreeGC(xDisplay, maskGC);
8649 InitAnimState (anim, info)
8651 XWindowAttributes * info;
8656 /* Each buffer is square size, same depth as window */
8657 anim->saveBuf = XCreatePixmap(xDisplay, xBoardWindow,
8658 squareSize, squareSize, info->depth);
8659 anim->newBuf = XCreatePixmap(xDisplay, xBoardWindow,
8660 squareSize, squareSize, info->depth);
8662 /* Create a plain GC for blitting */
8663 mask = GCForeground | GCBackground | GCFunction |
8664 GCPlaneMask | GCGraphicsExposures;
8665 values.foreground = XBlackPixel(xDisplay, xScreen);
8666 values.background = XWhitePixel(xDisplay, xScreen);
8667 values.function = GXcopy;
8668 values.plane_mask = AllPlanes;
8669 values.graphics_exposures = False;
8670 anim->blitGC = XCreateGC(xDisplay, xBoardWindow, mask, &values);
8672 /* Piece will be copied from an existing context at
8673 the start of each new animation/drag. */
8674 anim->pieceGC = XCreateGC(xDisplay, xBoardWindow, 0, &values);
8676 /* Outline will be a read-only copy of an existing */
8677 anim->outlineGC = None;
8683 static int done = 0;
8684 XWindowAttributes info;
8688 XGetWindowAttributes(xDisplay, xBoardWindow, &info);
8690 InitAnimState(&game, &info);
8691 InitAnimState(&player, &info);
8693 /* For XPM pieces, we need bitmaps to use as masks. */
8695 CreateAnimMasks(info.depth);
8700 static Boolean frameWaiting;
8702 static RETSIGTYPE FrameAlarm (sig)
8705 frameWaiting = False;
8706 /* In case System-V style signals. Needed?? */
8707 signal(SIGALRM, FrameAlarm);
8714 struct itimerval delay;
8716 XSync(xDisplay, False);
8719 frameWaiting = True;
8720 signal(SIGALRM, FrameAlarm);
8721 delay.it_interval.tv_sec =
8722 delay.it_value.tv_sec = time / 1000;
8723 delay.it_interval.tv_usec =
8724 delay.it_value.tv_usec = (time % 1000) * 1000;
8725 setitimer(ITIMER_REAL, &delay, NULL);
8727 /* Ugh -- busy-wait! --tpm */
8728 while (frameWaiting);
8730 while (frameWaiting) pause();
8732 delay.it_interval.tv_sec = delay.it_value.tv_sec = 0;
8733 delay.it_interval.tv_usec = delay.it_value.tv_usec = 0;
8734 setitimer(ITIMER_REAL, &delay, NULL);
8744 XSync(xDisplay, False);
8746 usleep(time * 1000);
8751 /* Convert board position to corner of screen rect and color */
8754 ScreenSquare(column, row, pt, color)
8755 int column; int row; XPoint * pt; int * color;
8758 pt->x = lineGap + ((BOARD_WIDTH-1)-column) * (squareSize + lineGap);
8759 pt->y = lineGap + row * (squareSize + lineGap);
8761 pt->x = lineGap + column * (squareSize + lineGap);
8762 pt->y = lineGap + ((BOARD_HEIGHT-1)-row) * (squareSize + lineGap);
8764 *color = SquareColor(row, column);
8767 /* Convert window coords to square */
8770 BoardSquare(x, y, column, row)
8771 int x; int y; int * column; int * row;
8773 *column = EventToSquare(x, BOARD_WIDTH);
8774 if (flipView && *column >= 0)
8775 *column = BOARD_WIDTH - 1 - *column;
8776 *row = EventToSquare(y, BOARD_HEIGHT);
8777 if (!flipView && *row >= 0)
8778 *row = BOARD_HEIGHT - 1 - *row;
8783 #undef Max /* just in case */
8785 #define Max(a, b) ((a) > (b) ? (a) : (b))
8786 #define Min(a, b) ((a) < (b) ? (a) : (b))
8789 SetRect(rect, x, y, width, height)
8790 XRectangle * rect; int x; int y; int width; int height;
8794 rect->width = width;
8795 rect->height = height;
8798 /* Test if two frames overlap. If they do, return
8799 intersection rect within old and location of
8800 that rect within new. */
8803 Intersect(old, new, size, area, pt)
8804 XPoint * old; XPoint * new;
8805 int size; XRectangle * area; XPoint * pt;
8807 if (old->x > new->x + size || new->x > old->x + size ||
8808 old->y > new->y + size || new->y > old->y + size) {
8811 SetRect(area, Max(new->x - old->x, 0), Max(new->y - old->y, 0),
8812 size - abs(old->x - new->x), size - abs(old->y - new->y));
8813 pt->x = Max(old->x - new->x, 0);
8814 pt->y = Max(old->y - new->y, 0);
8819 /* For two overlapping frames, return the rect(s)
8820 in the old that do not intersect with the new. */
8823 CalcUpdateRects(old, new, size, update, nUpdates)
8824 XPoint * old; XPoint * new; int size;
8825 XRectangle update[]; int * nUpdates;
8829 /* If old = new (shouldn't happen) then nothing to draw */
8830 if (old->x == new->x && old->y == new->y) {
8834 /* Work out what bits overlap. Since we know the rects
8835 are the same size we don't need a full intersect calc. */
8837 /* Top or bottom edge? */
8838 if (new->y > old->y) {
8839 SetRect(&(update[count]), old->x, old->y, size, new->y - old->y);
8841 } else if (old->y > new->y) {
8842 SetRect(&(update[count]), old->x, old->y + size - (old->y - new->y),
8843 size, old->y - new->y);
8846 /* Left or right edge - don't overlap any update calculated above. */
8847 if (new->x > old->x) {
8848 SetRect(&(update[count]), old->x, Max(new->y, old->y),
8849 new->x - old->x, size - abs(new->y - old->y));
8851 } else if (old->x > new->x) {
8852 SetRect(&(update[count]), new->x + size, Max(new->y, old->y),
8853 old->x - new->x, size - abs(new->y - old->y));
8860 /* Generate a series of frame coords from start->mid->finish.
8861 The movement rate doubles until the half way point is
8862 reached, then halves back down to the final destination,
8863 which gives a nice slow in/out effect. The algorithmn
8864 may seem to generate too many intermediates for short
8865 moves, but remember that the purpose is to attract the
8866 viewers attention to the piece about to be moved and
8867 then to where it ends up. Too few frames would be less
8871 Tween(start, mid, finish, factor, frames, nFrames)
8872 XPoint * start; XPoint * mid;
8873 XPoint * finish; int factor;
8874 XPoint frames[]; int * nFrames;
8876 int fraction, n, count;
8880 /* Slow in, stepping 1/16th, then 1/8th, ... */
8882 for (n = 0; n < factor; n++)
8884 for (n = 0; n < factor; n++) {
8885 frames[count].x = start->x + (mid->x - start->x) / fraction;
8886 frames[count].y = start->y + (mid->y - start->y) / fraction;
8888 fraction = fraction / 2;
8892 frames[count] = *mid;
8895 /* Slow out, stepping 1/2, then 1/4, ... */
8897 for (n = 0; n < factor; n++) {
8898 frames[count].x = finish->x - (finish->x - mid->x) / fraction;
8899 frames[count].y = finish->y - (finish->y - mid->y) / fraction;
8901 fraction = fraction * 2;
8906 /* Draw a piece on the screen without disturbing what's there */
8909 SelectGCMask(piece, clip, outline, mask)
8910 ChessSquare piece; GC * clip; GC * outline; Pixmap * mask;
8914 /* Bitmap for piece being moved. */
8915 if (appData.monoMode) {
8916 *mask = *pieceToSolid(piece);
8917 } else if (useImages) {
8919 *mask = xpmMask[piece];
8921 *mask = ximMaskPm[piece%(int)BlackPawn];
8924 *mask = *pieceToSolid(piece);
8927 /* GC for piece being moved. Square color doesn't matter, but
8928 since it gets modified we make a copy of the original. */
8930 if (appData.monoMode)
8935 if (appData.monoMode)
8940 XCopyGC(xDisplay, source, 0xFFFFFFFF, *clip);
8942 /* Outline only used in mono mode and is not modified */
8944 *outline = bwPieceGC;
8946 *outline = wbPieceGC;
8950 OverlayPiece(piece, clip, outline, dest)
8951 ChessSquare piece; GC clip; GC outline; Drawable dest;
8956 /* Draw solid rectangle which will be clipped to shape of piece */
8957 XFillRectangle(xDisplay, dest, clip,
8958 0, 0, squareSize, squareSize);
8959 if (appData.monoMode)
8960 /* Also draw outline in contrasting color for black
8961 on black / white on white cases */
8962 XCopyPlane(xDisplay, *pieceToOutline(piece), dest, outline,
8963 0, 0, squareSize, squareSize, 0, 0, 1);
8965 /* Copy the piece */
8970 XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % (int)BlackPawn],
8972 0, 0, squareSize, squareSize,
8977 /* Animate the movement of a single piece */
8980 BeginAnimation(anim, piece, startColor, start)
8988 /* The old buffer is initialised with the start square (empty) */
8989 BlankSquare(0, 0, startColor, EmptySquare, anim->saveBuf);
8990 anim->prevFrame = *start;
8992 /* The piece will be drawn using its own bitmap as a matte */
8993 SelectGCMask(piece, &anim->pieceGC, &anim->outlineGC, &mask);
8994 XSetClipMask(xDisplay, anim->pieceGC, mask);
8998 AnimationFrame(anim, frame, piece)
9003 XRectangle updates[4];
9008 /* Save what we are about to draw into the new buffer */
9009 XCopyArea(xDisplay, xBoardWindow, anim->newBuf, anim->blitGC,
9010 frame->x, frame->y, squareSize, squareSize,
9013 /* Erase bits of the previous frame */
9014 if (Intersect(&anim->prevFrame, frame, squareSize, &overlap, &pt)) {
9015 /* Where the new frame overlapped the previous,
9016 the contents in newBuf are wrong. */
9017 XCopyArea(xDisplay, anim->saveBuf, anim->newBuf, anim->blitGC,
9018 overlap.x, overlap.y,
9019 overlap.width, overlap.height,
9021 /* Repaint the areas in the old that don't overlap new */
9022 CalcUpdateRects(&anim->prevFrame, frame, squareSize, updates, &count);
9023 for (i = 0; i < count; i++)
9024 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9025 updates[i].x - anim->prevFrame.x,
9026 updates[i].y - anim->prevFrame.y,
9027 updates[i].width, updates[i].height,
9028 updates[i].x, updates[i].y);
9030 /* Easy when no overlap */
9031 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9032 0, 0, squareSize, squareSize,
9033 anim->prevFrame.x, anim->prevFrame.y);
9036 /* Save this frame for next time round */
9037 XCopyArea(xDisplay, anim->newBuf, anim->saveBuf, anim->blitGC,
9038 0, 0, squareSize, squareSize,
9040 anim->prevFrame = *frame;
9042 /* Draw piece over original screen contents, not current,
9043 and copy entire rect. Wipes out overlapping piece images. */
9044 OverlayPiece(piece, anim->pieceGC, anim->outlineGC, anim->newBuf);
9045 XCopyArea(xDisplay, anim->newBuf, xBoardWindow, anim->blitGC,
9046 0, 0, squareSize, squareSize,
9047 frame->x, frame->y);
9051 EndAnimation (anim, finish)
9055 XRectangle updates[4];
9060 /* The main code will redraw the final square, so we
9061 only need to erase the bits that don't overlap. */
9062 if (Intersect(&anim->prevFrame, finish, squareSize, &overlap, &pt)) {
9063 CalcUpdateRects(&anim->prevFrame, finish, squareSize, updates, &count);
9064 for (i = 0; i < count; i++)
9065 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9066 updates[i].x - anim->prevFrame.x,
9067 updates[i].y - anim->prevFrame.y,
9068 updates[i].width, updates[i].height,
9069 updates[i].x, updates[i].y);
9071 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9072 0, 0, squareSize, squareSize,
9073 anim->prevFrame.x, anim->prevFrame.y);
9078 FrameSequence(anim, piece, startColor, start, finish, frames, nFrames)
9080 ChessSquare piece; int startColor;
9081 XPoint * start; XPoint * finish;
9082 XPoint frames[]; int nFrames;
9086 BeginAnimation(anim, piece, startColor, start);
9087 for (n = 0; n < nFrames; n++) {
9088 AnimationFrame(anim, &(frames[n]), piece);
9089 FrameDelay(appData.animSpeed);
9091 EndAnimation(anim, finish);
9094 /* Main control logic for deciding what to animate and how */
9097 AnimateMove(board, fromX, fromY, toX, toY)
9106 XPoint start, finish, mid;
9107 XPoint frames[kFactor * 2 + 1];
9108 int nFrames, startColor, endColor;
9110 /* Are we animating? */
9111 if (!appData.animate || appData.blindfold)
9114 if (fromY < 0 || fromX < 0 || toX < 0 || toY < 0) return;
9115 piece = board[fromY][fromX];
9116 if (piece >= EmptySquare) return;
9121 hop = (piece == WhiteKnight || piece == BlackKnight);
9124 if (appData.debugMode) {
9125 fprintf(debugFP, hop ? _("AnimateMove: piece %d hops from %d,%d to %d,%d \n") :
9126 _("AnimateMove: piece %d slides from %d,%d to %d,%d \n"),
9127 piece, fromX, fromY, toX, toY); }
9129 ScreenSquare(fromX, fromY, &start, &startColor);
9130 ScreenSquare(toX, toY, &finish, &endColor);
9133 /* Knight: make diagonal movement then straight */
9134 if (abs(toY - fromY) < abs(toX - fromX)) {
9135 mid.x = start.x + (finish.x - start.x) / 2;
9139 mid.y = start.y + (finish.y - start.y) / 2;
9142 mid.x = start.x + (finish.x - start.x) / 2;
9143 mid.y = start.y + (finish.y - start.y) / 2;
9146 /* Don't use as many frames for very short moves */
9147 if (abs(toY - fromY) + abs(toX - fromX) <= 2)
9148 Tween(&start, &mid, &finish, kFactor - 1, frames, &nFrames);
9150 Tween(&start, &mid, &finish, kFactor, frames, &nFrames);
9151 FrameSequence(&game, piece, startColor, &start, &finish, frames, nFrames);
9153 /* Be sure end square is redrawn */
9154 damage[toY][toX] = True;
9158 DragPieceBegin(x, y)
9161 int boardX, boardY, color;
9164 /* Are we animating? */
9165 if (!appData.animateDragging || appData.blindfold)
9168 /* Figure out which square we start in and the
9169 mouse position relative to top left corner. */
9170 BoardSquare(x, y, &boardX, &boardY);
9171 player.startBoardX = boardX;
9172 player.startBoardY = boardY;
9173 ScreenSquare(boardX, boardY, &corner, &color);
9174 player.startSquare = corner;
9175 player.startColor = color;
9177 /* Start from exactly where the piece is. This can be confusing
9178 if you start dragging far from the center of the square; most
9179 or all of the piece can be over a different square from the one
9180 the mouse pointer is in. */
9181 player.mouseDelta.x = x - corner.x;
9182 player.mouseDelta.y = y - corner.y;
9184 /* As soon as we start dragging, the piece will jump slightly to
9185 be centered over the mouse pointer. */
9186 player.mouseDelta.x = squareSize/2;
9187 player.mouseDelta.y = squareSize/2;
9189 /* Initialise animation */
9190 player.dragPiece = PieceForSquare(boardX, boardY);
9192 if (player.dragPiece >= 0 && player.dragPiece < EmptySquare) {
9193 player.dragActive = True;
9194 BeginAnimation(&player, player.dragPiece, color, &corner);
9195 /* Mark this square as needing to be redrawn. Note that
9196 we don't remove the piece though, since logically (ie
9197 as seen by opponent) the move hasn't been made yet. */
9198 if(boardX == BOARD_RGHT+1 && PieceForSquare(boardX-1, boardY) > 1 ||
9199 boardX == BOARD_LEFT-2 && PieceForSquare(boardX+1, boardY) > 1)
9200 XCopyArea(xDisplay, xBoardWindow, player.saveBuf, player.blitGC,
9201 corner.x, corner.y, squareSize, squareSize,
9202 0, 0); // [HGM] zh: unstack in stead of grab
9203 damage[boardY][boardX] = True;
9205 player.dragActive = False;
9215 /* Are we animating? */
9216 if (!appData.animateDragging || appData.blindfold)
9220 if (! player.dragActive)
9222 /* Move piece, maintaining same relative position
9223 of mouse within square */
9224 corner.x = x - player.mouseDelta.x;
9225 corner.y = y - player.mouseDelta.y;
9226 AnimationFrame(&player, &corner, player.dragPiece);
9228 if (appData.highlightDragging) {
9230 BoardSquare(x, y, &boardX, &boardY);
9231 SetHighlights(fromX, fromY, boardX, boardY);
9240 int boardX, boardY, color;
9243 /* Are we animating? */
9244 if (!appData.animateDragging || appData.blindfold)
9248 if (! player.dragActive)
9250 /* Last frame in sequence is square piece is
9251 placed on, which may not match mouse exactly. */
9252 BoardSquare(x, y, &boardX, &boardY);
9253 ScreenSquare(boardX, boardY, &corner, &color);
9254 EndAnimation(&player, &corner);
9256 /* Be sure end square is redrawn */
9257 damage[boardY][boardX] = True;
9259 /* This prevents weird things happening with fast successive
9260 clicks which on my Sun at least can cause motion events
9261 without corresponding press/release. */
9262 player.dragActive = False;
9265 /* Handle expose event while piece being dragged */
9270 if (!player.dragActive || appData.blindfold)
9273 /* What we're doing: logically, the move hasn't been made yet,
9274 so the piece is still in it's original square. But visually
9275 it's being dragged around the board. So we erase the square
9276 that the piece is on and draw it at the last known drag point. */
9277 BlankSquare(player.startSquare.x, player.startSquare.y,
9278 player.startColor, EmptySquare, xBoardWindow);
9279 AnimationFrame(&player, &player.prevFrame, player.dragPiece);
9280 damage[player.startBoardY][player.startBoardX] = TRUE;
9284 SetProgramStats( FrontEndProgramStats * stats )
9287 // [HGM] done, but perhaps backend should call this directly?
9288 EngineOutputUpdate( stats );