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 },
1063 { "flashCount", "flashCount", XtRInt, sizeof(int),
1064 XtOffset(AppDataPtr, flashCount), XtRImmediate,
1065 (XtPointer) FLASH_COUNT },
1066 { "flashRate", "flashRate", XtRInt, sizeof(int),
1067 XtOffset(AppDataPtr, flashRate), XtRImmediate,
1068 (XtPointer) FLASH_RATE },
1069 { "pixmapDirectory", "pixmapDirectory", XtRString,
1070 sizeof(String), XtOffset(AppDataPtr, pixmapDirectory),
1072 { "msLoginDelay", "msLoginDelay", XtRInt, sizeof(int),
1073 XtOffset(AppDataPtr, msLoginDelay), XtRImmediate,
1074 (XtPointer) MS_LOGIN_DELAY },
1075 { "colorizeMessages", "colorizeMessages", XtRBoolean,
1076 sizeof(Boolean), XtOffset(AppDataPtr, colorize),
1077 XtRImmediate, (XtPointer) False },
1078 { "colorShout", "colorShout", XtRString,
1079 sizeof(String), XtOffset(AppDataPtr, colorShout),
1080 XtRString, COLOR_SHOUT },
1081 { "colorSShout", "colorSShout", XtRString,
1082 sizeof(String), XtOffset(AppDataPtr, colorSShout),
1083 XtRString, COLOR_SSHOUT },
1084 { "colorChannel1", "colorChannel1", XtRString,
1085 sizeof(String), XtOffset(AppDataPtr, colorChannel1),
1086 XtRString, COLOR_CHANNEL1 },
1087 { "colorChannel", "colorChannel", XtRString,
1088 sizeof(String), XtOffset(AppDataPtr, colorChannel),
1089 XtRString, COLOR_CHANNEL },
1090 { "colorKibitz", "colorKibitz", XtRString,
1091 sizeof(String), XtOffset(AppDataPtr, colorKibitz),
1092 XtRString, COLOR_KIBITZ },
1093 { "colorTell", "colorTell", XtRString,
1094 sizeof(String), XtOffset(AppDataPtr, colorTell),
1095 XtRString, COLOR_TELL },
1096 { "colorChallenge", "colorChallenge", XtRString,
1097 sizeof(String), XtOffset(AppDataPtr, colorChallenge),
1098 XtRString, COLOR_CHALLENGE },
1099 { "colorRequest", "colorRequest", XtRString,
1100 sizeof(String), XtOffset(AppDataPtr, colorRequest),
1101 XtRString, COLOR_REQUEST },
1102 { "colorSeek", "colorSeek", XtRString,
1103 sizeof(String), XtOffset(AppDataPtr, colorSeek),
1104 XtRString, COLOR_SEEK },
1105 { "colorNormal", "colorNormal", XtRString,
1106 sizeof(String), XtOffset(AppDataPtr, colorNormal),
1107 XtRString, COLOR_NORMAL },
1108 { "soundProgram", "soundProgram", XtRString,
1109 sizeof(String), XtOffset(AppDataPtr, soundProgram),
1110 XtRString, "play" },
1111 { "soundShout", "soundShout", XtRString,
1112 sizeof(String), XtOffset(AppDataPtr, soundShout),
1114 { "soundSShout", "soundSShout", XtRString,
1115 sizeof(String), XtOffset(AppDataPtr, soundSShout),
1117 { "soundChannel1", "soundChannel1", XtRString,
1118 sizeof(String), XtOffset(AppDataPtr, soundChannel1),
1120 { "soundChannel", "soundChannel", XtRString,
1121 sizeof(String), XtOffset(AppDataPtr, soundChannel),
1123 { "soundKibitz", "soundKibitz", XtRString,
1124 sizeof(String), XtOffset(AppDataPtr, soundKibitz),
1126 { "soundTell", "soundTell", XtRString,
1127 sizeof(String), XtOffset(AppDataPtr, soundTell),
1129 { "soundChallenge", "soundChallenge", XtRString,
1130 sizeof(String), XtOffset(AppDataPtr, soundChallenge),
1132 { "soundRequest", "soundRequest", XtRString,
1133 sizeof(String), XtOffset(AppDataPtr, soundRequest),
1135 { "soundSeek", "soundSeek", XtRString,
1136 sizeof(String), XtOffset(AppDataPtr, soundSeek),
1138 { "soundMove", "soundMove", XtRString,
1139 sizeof(String), XtOffset(AppDataPtr, soundMove),
1141 { "soundIcsWin", "soundIcsWin", XtRString,
1142 sizeof(String), XtOffset(AppDataPtr, soundIcsWin),
1144 { "soundIcsLoss", "soundIcsLoss", XtRString,
1145 sizeof(String), XtOffset(AppDataPtr, soundIcsLoss),
1147 { "soundIcsDraw", "soundIcsDraw", XtRString,
1148 sizeof(String), XtOffset(AppDataPtr, soundIcsDraw),
1150 { "soundIcsUnfinished", "soundIcsUnfinished", XtRString,
1151 sizeof(String), XtOffset(AppDataPtr, soundIcsUnfinished),
1153 { "soundIcsAlarm", "soundIcsAlarm", XtRString,
1154 sizeof(String), XtOffset(AppDataPtr, soundIcsAlarm),
1156 { "reuseFirst", "reuseFirst", XtRBoolean,
1157 sizeof(Boolean), XtOffset(AppDataPtr, reuseFirst),
1158 XtRImmediate, (XtPointer) True },
1159 { "reuseSecond", "reuseSecond", XtRBoolean,
1160 sizeof(Boolean), XtOffset(AppDataPtr, reuseSecond),
1161 XtRImmediate, (XtPointer) True },
1162 { "animateDragging", "animateDragging", XtRBoolean,
1163 sizeof(Boolean), XtOffset(AppDataPtr, animateDragging),
1164 XtRImmediate, (XtPointer) True },
1165 { "animateMoving", "animateMoving", XtRBoolean,
1166 sizeof(Boolean), XtOffset(AppDataPtr, animate),
1167 XtRImmediate, (XtPointer) True },
1168 { "animateSpeed", "animateSpeed", XtRInt,
1169 sizeof(int), XtOffset(AppDataPtr, animSpeed),
1170 XtRImmediate, (XtPointer)10 },
1171 { "popupExitMessage", "popupExitMessage", XtRBoolean,
1172 sizeof(Boolean), XtOffset(AppDataPtr, popupExitMessage),
1173 XtRImmediate, (XtPointer) True },
1174 { "popupMoveErrors", "popupMoveErrors", XtRBoolean,
1175 sizeof(Boolean), XtOffset(AppDataPtr, popupMoveErrors),
1176 XtRImmediate, (XtPointer) False },
1177 { "fontSizeTolerance", "fontSizeTolerance", XtRInt,
1178 sizeof(int), XtOffset(AppDataPtr, fontSizeTolerance),
1179 XtRImmediate, (XtPointer)4 },
1180 { "initialMode", "initialMode", XtRString,
1181 sizeof(String), XtOffset(AppDataPtr, initialMode),
1182 XtRImmediate, (XtPointer) "" },
1183 { "variant", "variant", XtRString,
1184 sizeof(String), XtOffset(AppDataPtr, variant),
1185 XtRImmediate, (XtPointer) "normal" },
1186 { "firstProtocolVersion", "firstProtocolVersion", XtRInt,
1187 sizeof(int), XtOffset(AppDataPtr, firstProtocolVersion),
1188 XtRImmediate, (XtPointer)PROTOVER },
1189 { "secondProtocolVersion", "secondProtocolVersion", XtRInt,
1190 sizeof(int), XtOffset(AppDataPtr, secondProtocolVersion),
1191 XtRImmediate, (XtPointer)PROTOVER },
1192 { "showButtonBar", "showButtonBar", XtRBoolean,
1193 sizeof(Boolean), XtOffset(AppDataPtr, showButtonBar),
1194 XtRImmediate, (XtPointer) True },
1195 {"icsEngineAnalyze", "icsEngineAnalyze", XtRBoolean, /* [DM] icsEngineAnalyze */
1196 sizeof(Boolean), XtOffset(AppDataPtr, icsEngineAnalyze),
1197 XtRImmediate, (XtPointer) False },
1198 { "firstScoreAbs", "firstScoreAbs", XtRBoolean,
1199 sizeof(Boolean), XtOffset(AppDataPtr, firstScoreIsAbsolute),
1200 XtRImmediate, (XtPointer) False },
1201 { "secondScoreAbs", "secondScoreAbs", XtRBoolean,
1202 sizeof(Boolean), XtOffset(AppDataPtr, secondScoreIsAbsolute),
1203 XtRImmediate, (XtPointer) False },
1204 { "pgnExtendedInfo", "pgnExtendedInfo", XtRBoolean,
1205 sizeof(Boolean), XtOffset(AppDataPtr, saveExtendedInfoInPGN),
1206 XtRImmediate, (XtPointer) False },
1207 { "hideThinkingFromHuman", "hideThinkingFromHuman", XtRBoolean,
1208 sizeof(Boolean), XtOffset(AppDataPtr, hideThinkingFromHuman),
1209 XtRImmediate, (XtPointer) True },
1210 { "adjudicateLossThreshold", "adjudicateLossThreshold", XtRInt,
1211 sizeof(int), XtOffset(AppDataPtr, adjudicateLossThreshold),
1212 XtRImmediate, (XtPointer) 0},
1213 { "pgnEventHeader", "pgnEventHeader", XtRString,
1214 sizeof(String), XtOffset(AppDataPtr, pgnEventHeader),
1215 XtRImmediate, (XtPointer) "Computer Chess Game" },
1216 { "defaultFrcPosition", "defaultFrcPositon", XtRInt,
1217 sizeof(int), XtOffset(AppDataPtr, defaultFrcPosition),
1218 XtRImmediate, (XtPointer) -1},
1219 { "gameListTags", "gameListTags", XtRString,
1220 sizeof(String), XtOffset(AppDataPtr, gameListTags),
1221 XtRImmediate, (XtPointer) GLT_DEFAULT_TAGS },
1223 // [HGM] 4.3.xx options
1224 { "boardWidth", "boardWidth", XtRInt,
1225 sizeof(int), XtOffset(AppDataPtr, NrFiles),
1226 XtRImmediate, (XtPointer) -1},
1227 { "boardHeight", "boardHeight", XtRInt,
1228 sizeof(int), XtOffset(AppDataPtr, NrRanks),
1229 XtRImmediate, (XtPointer) -1},
1230 { "matchPause", "matchPause", XtRInt,
1231 sizeof(int), XtOffset(AppDataPtr, matchPause),
1232 XtRImmediate, (XtPointer) 10000},
1233 { "holdingsSize", "holdingsSize", XtRInt,
1234 sizeof(int), XtOffset(AppDataPtr, holdingsSize),
1235 XtRImmediate, (XtPointer) -1},
1236 { "flipBlack", "flipBlack", XtRBoolean,
1237 sizeof(Boolean), XtOffset(AppDataPtr, upsideDown),
1238 XtRImmediate, (XtPointer) False},
1239 { "allWhite", "allWhite", XtRBoolean,
1240 sizeof(Boolean), XtOffset(AppDataPtr, allWhite),
1241 XtRImmediate, (XtPointer) False},
1242 { "pieceToCharTable", "pieceToCharTable", XtRString,
1243 sizeof(String), XtOffset(AppDataPtr, pieceToCharTable),
1244 XtRImmediate, (XtPointer) 0},
1245 { "alphaRank", "alphaRank", XtRBoolean,
1246 sizeof(Boolean), XtOffset(AppDataPtr, alphaRank),
1247 XtRImmediate, (XtPointer) False},
1248 { "testClaims", "testClaims", XtRBoolean,
1249 sizeof(Boolean), XtOffset(AppDataPtr, testClaims),
1250 XtRImmediate, (XtPointer) True},
1251 { "checkMates", "checkMates", XtRBoolean,
1252 sizeof(Boolean), XtOffset(AppDataPtr, checkMates),
1253 XtRImmediate, (XtPointer) True},
1254 { "materialDraws", "materialDraws", XtRBoolean,
1255 sizeof(Boolean), XtOffset(AppDataPtr, materialDraws),
1256 XtRImmediate, (XtPointer) True},
1257 { "trivialDraws", "trivialDraws", XtRBoolean,
1258 sizeof(Boolean), XtOffset(AppDataPtr, trivialDraws),
1259 XtRImmediate, (XtPointer) False},
1260 { "ruleMoves", "ruleMoves", XtRInt,
1261 sizeof(int), XtOffset(AppDataPtr, ruleMoves),
1262 XtRImmediate, (XtPointer) 51},
1263 { "repeatsToDraw", "repeatsToDraw", XtRInt,
1264 sizeof(int), XtOffset(AppDataPtr, drawRepeats),
1265 XtRImmediate, (XtPointer) 6},
1266 { "engineDebugOutput", "engineDebugOutput", XtRInt,
1267 sizeof(int), XtOffset(AppDataPtr, engineComments),
1268 XtRImmediate, (XtPointer) 1},
1269 { "userName", "userName", XtRString,
1270 sizeof(int), XtOffset(AppDataPtr, userName),
1271 XtRImmediate, (XtPointer) 0},
1272 { "autoKibitz", "autoKibitz", XtRBoolean,
1273 sizeof(Boolean), XtOffset(AppDataPtr, autoKibitz),
1274 XtRImmediate, (XtPointer) False},
1275 { "firstTimeOdds", "firstTimeOdds", XtRInt,
1276 sizeof(int), XtOffset(AppDataPtr, firstTimeOdds),
1277 XtRImmediate, (XtPointer) 1},
1278 { "secondTimeOdds", "secondTimeOdds", XtRInt,
1279 sizeof(int), XtOffset(AppDataPtr, secondTimeOdds),
1280 XtRImmediate, (XtPointer) 1},
1281 { "timeOddsMode", "timeOddsMode", XtRInt,
1282 sizeof(int), XtOffset(AppDataPtr, timeOddsMode),
1283 XtRImmediate, (XtPointer) 0},
1284 { "firstAccumulateTC", "firstAccumulateTC", XtRInt,
1285 sizeof(int), XtOffset(AppDataPtr, firstAccumulateTC),
1286 XtRImmediate, (XtPointer) 1},
1287 { "secondAccumulateTC", "secondAccumulateTC", XtRInt,
1288 sizeof(int), XtOffset(AppDataPtr, secondAccumulateTC),
1289 XtRImmediate, (XtPointer) 1},
1290 { "firstNPS", "firstNPS", XtRInt,
1291 sizeof(int), XtOffset(AppDataPtr, firstNPS),
1292 XtRImmediate, (XtPointer) -1},
1293 { "secondNPS", "secondNPS", XtRInt,
1294 sizeof(int), XtOffset(AppDataPtr, secondNPS),
1295 XtRImmediate, (XtPointer) -1},
1296 { "serverMoves", "serverMoves", XtRString,
1297 sizeof(String), XtOffset(AppDataPtr, serverMovesName),
1298 XtRImmediate, (XtPointer) 0},
1299 { "serverPause", "serverPause", XtRInt,
1300 sizeof(int), XtOffset(AppDataPtr, serverPause),
1301 XtRImmediate, (XtPointer) 0},
1302 { "suppressLoadMoves", "suppressLoadMoves", XtRBoolean,
1303 sizeof(Boolean), XtOffset(AppDataPtr, suppressLoadMoves),
1304 XtRImmediate, (XtPointer) False},
1305 { "userName", "userName", XtRString,
1306 sizeof(String), XtOffset(AppDataPtr, userName),
1307 XtRImmediate, (XtPointer) 0},
1308 { "egtFormats", "egtFormats", XtRString,
1309 sizeof(String), XtOffset(AppDataPtr, egtFormats),
1310 XtRImmediate, (XtPointer) 0},
1311 { "rewindIndex", "rewindIndex", XtRInt,
1312 sizeof(int), XtOffset(AppDataPtr, rewindIndex),
1313 XtRImmediate, (XtPointer) 0},
1314 { "sameColorGames", "sameColorGames", XtRInt,
1315 sizeof(int), XtOffset(AppDataPtr, sameColorGames),
1316 XtRImmediate, (XtPointer) 0},
1317 { "smpCores", "smpCores", XtRInt,
1318 sizeof(int), XtOffset(AppDataPtr, smpCores),
1319 XtRImmediate, (XtPointer) 1},
1320 { "niceEngines", "niceEngines", XtRInt,
1321 sizeof(int), XtOffset(AppDataPtr, niceEngines),
1322 XtRImmediate, (XtPointer) 0},
1323 { "nameOfDebugFile", "nameOfDebugFile", XtRString,
1324 sizeof(String), XtOffset(AppDataPtr, nameOfDebugFile),
1325 XtRImmediate, (XtPointer) "xboard.debug"},
1326 { "engineDebugOutput", "engineDebugOutput", XtRInt,
1327 sizeof(int), XtOffset(AppDataPtr, engineComments),
1328 XtRImmediate, (XtPointer) 0},
1329 { "noGUI", "noGUI", XtRBoolean,
1330 sizeof(Boolean), XtOffset(AppDataPtr, noGUI),
1331 XtRImmediate, (XtPointer) 0},
1332 { "firstOptions", "firstOptions", XtRString,
1333 sizeof(String), XtOffset(AppDataPtr, firstOptions),
1334 XtRImmediate, (XtPointer) "" },
1335 { "secondOptions", "secondOptions", XtRString,
1336 sizeof(String), XtOffset(AppDataPtr, secondOptions),
1337 XtRImmediate, (XtPointer) "" },
1338 { "firstNeedsNoncompliantFEN", "firstNeedsNoncompliantFEN", XtRString,
1339 sizeof(String), XtOffset(AppDataPtr, fenOverride1),
1340 XtRImmediate, (XtPointer) 0 },
1341 { "secondNeedsNoncompliantFEN", "secondNeedsNoncompliantFEN", XtRString,
1342 sizeof(String), XtOffset(AppDataPtr, fenOverride2),
1343 XtRImmediate, (XtPointer) 0 },
1345 // [HGM] Winboard_x UCI options
1346 { "firstIsUCI", "firstIsUCI", XtRBoolean,
1347 sizeof(Boolean), XtOffset(AppDataPtr, firstIsUCI),
1348 XtRImmediate, (XtPointer) False},
1349 { "secondIsUCI", "secondIsUCI", XtRBoolean,
1350 sizeof(Boolean), XtOffset(AppDataPtr, secondIsUCI),
1351 XtRImmediate, (XtPointer) False},
1352 { "firstHasOwnBookUCI", "firstHasOwnBookUCI", XtRBoolean,
1353 sizeof(Boolean), XtOffset(AppDataPtr, firstHasOwnBookUCI),
1354 XtRImmediate, (XtPointer) True},
1355 { "secondHasOwnBookUCI", "secondHasOwnBookUCI", XtRBoolean,
1356 sizeof(Boolean), XtOffset(AppDataPtr, secondHasOwnBookUCI),
1357 XtRImmediate, (XtPointer) True},
1358 { "usePolyglotBook", "usePolyglotBook", XtRBoolean,
1359 sizeof(Boolean), XtOffset(AppDataPtr, usePolyglotBook),
1360 XtRImmediate, (XtPointer) False},
1361 { "defaultHashSize", "defaultHashSize", XtRInt,
1362 sizeof(int), XtOffset(AppDataPtr, defaultHashSize),
1363 XtRImmediate, (XtPointer) 64},
1364 { "defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XtRInt,
1365 sizeof(int), XtOffset(AppDataPtr, defaultCacheSizeEGTB),
1366 XtRImmediate, (XtPointer) 4},
1367 { "polyglotDir", "polyglotDir", XtRString,
1368 sizeof(String), XtOffset(AppDataPtr, polyglotDir),
1369 XtRImmediate, (XtPointer) "." },
1370 { "polyglotBook", "polyglotBook", XtRString,
1371 sizeof(String), XtOffset(AppDataPtr, polyglotBook),
1372 XtRImmediate, (XtPointer) "" },
1373 { "defaultPathEGTB", "defaultPathEGTB", XtRString,
1374 sizeof(String), XtOffset(AppDataPtr, defaultPathEGTB),
1375 XtRImmediate, (XtPointer) "/usr/local/share/egtb"},
1376 { "delayBeforeQuit", "delayBeforeQuit", XtRInt,
1377 sizeof(int), XtOffset(AppDataPtr, delayBeforeQuit),
1378 XtRImmediate, (XtPointer) 0},
1379 { "delayAfterQuit", "delayAfterQuit", XtRInt,
1380 sizeof(int), XtOffset(AppDataPtr, delayAfterQuit),
1381 XtRImmediate, (XtPointer) 0},
1384 XrmOptionDescRec shellOptions[] = {
1385 { "-whitePieceColor", "whitePieceColor", XrmoptionSepArg, NULL },
1386 { "-blackPieceColor", "blackPieceColor", XrmoptionSepArg, NULL },
1387 { "-lightSquareColor", "lightSquareColor", XrmoptionSepArg, NULL },
1388 { "-darkSquareColor", "darkSquareColor", XrmoptionSepArg, NULL },
1389 { "-highlightSquareColor", "highlightSquareColor", XrmoptionSepArg, NULL },
1390 { "-premoveHighlightColor", "premoveHighlightColor", XrmoptionSepArg,NULL},
1391 { "-movesPerSession", "movesPerSession", XrmoptionSepArg, NULL },
1392 { "-mps", "movesPerSession", XrmoptionSepArg, NULL },
1393 { "-timeIncrement", "timeIncrement", XrmoptionSepArg, NULL },
1394 { "-inc", "timeIncrement", XrmoptionSepArg, NULL },
1395 { "-initString", "initString", XrmoptionSepArg, NULL },
1396 { "-firstInitString", "initString", XrmoptionSepArg, NULL },
1397 { "-secondInitString", "secondInitString", XrmoptionSepArg, NULL },
1398 { "-firstComputerString", "firstComputerString", XrmoptionSepArg, NULL },
1399 { "-secondComputerString", "secondComputerString", XrmoptionSepArg, NULL },
1400 { "-firstChessProgram", "firstChessProgram", XrmoptionSepArg, NULL },
1401 { "-fcp", "firstChessProgram", XrmoptionSepArg, NULL },
1402 { "-secondChessProgram", "secondChessProgram", XrmoptionSepArg, NULL },
1403 { "-scp", "secondChessProgram", XrmoptionSepArg, NULL },
1404 { "-firstPlaysBlack", "firstPlaysBlack", XrmoptionSepArg, NULL },
1405 { "-fb", "firstPlaysBlack", XrmoptionNoArg, "True" },
1406 { "-xfb", "firstPlaysBlack", XrmoptionNoArg, "False" },
1407 { "-noChessProgram", "noChessProgram", XrmoptionSepArg, NULL },
1408 { "-ncp", "noChessProgram", XrmoptionNoArg, "True" },
1409 { "-xncp", "noChessProgram", XrmoptionNoArg, "False" },
1410 { "-firstHost", "firstHost", XrmoptionSepArg, NULL },
1411 { "-fh", "firstHost", XrmoptionSepArg, NULL },
1412 { "-secondHost", "secondHost", XrmoptionSepArg, NULL },
1413 { "-sh", "secondHost", XrmoptionSepArg, NULL },
1414 { "-firstDirectory", "firstDirectory", XrmoptionSepArg, NULL },
1415 { "-fd", "firstDirectory", XrmoptionSepArg, NULL },
1416 { "-secondDirectory", "secondDirectory", XrmoptionSepArg, NULL },
1417 { "-sd", "secondDirectory", XrmoptionSepArg, NULL },
1418 { "-bitmapDirectory", "bitmapDirectory", XrmoptionSepArg, NULL },
1419 { "-bm", "bitmapDirectory", XrmoptionSepArg, NULL },
1420 { "-remoteShell", "remoteShell", XrmoptionSepArg, NULL },
1421 { "-rsh", "remoteShell", XrmoptionSepArg, NULL },
1422 { "-remoteUser", "remoteUser", XrmoptionSepArg, NULL },
1423 { "-ruser", "remoteUser", XrmoptionSepArg, NULL },
1424 { "-timeDelay", "timeDelay", XrmoptionSepArg, NULL },
1425 { "-td", "timeDelay", XrmoptionSepArg, NULL },
1426 { "-timeControl", "timeControl", XrmoptionSepArg, NULL },
1427 { "-tc", "timeControl", XrmoptionSepArg, NULL },
1428 { "-internetChessServerMode", "internetChessServerMode",
1429 XrmoptionSepArg, NULL },
1430 { "-ics", "internetChessServerMode", XrmoptionNoArg, "True" },
1431 { "-xics", "internetChessServerMode", XrmoptionNoArg, "False" },
1432 { "-internetChessServerHost", "internetChessServerHost",
1433 XrmoptionSepArg, NULL },
1434 { "-icshost", "internetChessServerHost", XrmoptionSepArg, NULL },
1435 { "-internetChessServerPort", "internetChessServerPort",
1436 XrmoptionSepArg, NULL },
1437 { "-icsport", "internetChessServerPort", XrmoptionSepArg, NULL },
1438 { "-internetChessServerCommPort", "internetChessServerCommPort",
1439 XrmoptionSepArg, NULL },
1440 { "-icscomm", "internetChessServerCommPort", XrmoptionSepArg, NULL },
1441 { "-internetChessServerLogonScript", "internetChessServerLogonScript",
1442 XrmoptionSepArg, NULL },
1443 { "-icslogon", "internetChessServerLogonScript", XrmoptionSepArg, NULL },
1444 { "-internetChessServerHelper", "internetChessServerHelper",
1445 XrmoptionSepArg, NULL },
1446 { "-icshelper", "internetChessServerHelper", XrmoptionSepArg, NULL },
1447 { "-internetChessServerInputBox", "internetChessServerInputBox",
1448 XrmoptionSepArg, NULL },
1449 { "-icsinput", "internetChessServerInputBox", XrmoptionNoArg, "True" },
1450 { "-xicsinput", "internetChessServerInputBox", XrmoptionNoArg, "False" },
1451 { "-icsAlarm", "icsAlarm", XrmoptionSepArg, NULL },
1452 { "-alarm", "icsAlarm", XrmoptionNoArg, "True" },
1453 { "-xalarm", "icsAlarm", XrmoptionNoArg, "False" },
1454 { "-icsAlarmTime", "icsAlarmTime", XrmoptionSepArg, NULL },
1455 { "-useTelnet", "useTelnet", XrmoptionSepArg, NULL },
1456 { "-telnet", "useTelnet", XrmoptionNoArg, "True" },
1457 { "-xtelnet", "useTelnet", XrmoptionNoArg, "False" },
1458 { "-telnetProgram", "telnetProgram", XrmoptionSepArg, NULL },
1459 { "-gateway", "gateway", XrmoptionSepArg, NULL },
1460 { "-loadGameFile", "loadGameFile", XrmoptionSepArg, NULL },
1461 { "-lgf", "loadGameFile", XrmoptionSepArg, NULL },
1462 { "-loadGameIndex", "loadGameIndex", XrmoptionSepArg, NULL },
1463 { "-lgi", "loadGameIndex", XrmoptionSepArg, NULL },
1464 { "-saveGameFile", "saveGameFile", XrmoptionSepArg, NULL },
1465 { "-sgf", "saveGameFile", XrmoptionSepArg, NULL },
1466 { "-autoSaveGames", "autoSaveGames", XrmoptionSepArg, NULL },
1467 { "-autosave", "autoSaveGames", XrmoptionNoArg, "True" },
1468 { "-xautosave", "autoSaveGames", XrmoptionNoArg, "False" },
1469 { "-autoRaiseBoard", "autoRaiseBoard", XrmoptionSepArg, NULL },
1470 { "-autoraise", "autoRaiseBoard", XrmoptionNoArg, "True" },
1471 { "-xautoraise", "autoRaiseBoard", XrmoptionNoArg, "False" },
1472 { "-blindfold", "blindfold", XrmoptionSepArg, NULL },
1473 { "-blind", "blindfold", XrmoptionNoArg, "True" },
1474 { "-xblind", "blindfold", XrmoptionNoArg, "False" },
1475 { "-loadPositionFile", "loadPositionFile", XrmoptionSepArg, NULL },
1476 { "-lpf", "loadPositionFile", XrmoptionSepArg, NULL },
1477 { "-loadPositionIndex", "loadPositionIndex", XrmoptionSepArg, NULL },
1478 { "-lpi", "loadPositionIndex", XrmoptionSepArg, NULL },
1479 { "-savePositionFile", "savePositionFile", XrmoptionSepArg, NULL },
1480 { "-spf", "savePositionFile", XrmoptionSepArg, NULL },
1481 { "-matchMode", "matchMode", XrmoptionSepArg, NULL },
1482 { "-mm", "matchMode", XrmoptionNoArg, "True" },
1483 { "-xmm", "matchMode", XrmoptionNoArg, "False" },
1484 { "-matchGames", "matchGames", XrmoptionSepArg, NULL },
1485 { "-mg", "matchGames", XrmoptionSepArg, NULL },
1486 { "-monoMode", "monoMode", XrmoptionSepArg, NULL },
1487 { "-mono", "monoMode", XrmoptionNoArg, "True" },
1488 { "-xmono", "monoMode", XrmoptionNoArg, "False" },
1489 { "-debugMode", "debugMode", XrmoptionSepArg, NULL },
1490 { "-debug", "debugMode", XrmoptionNoArg, "True" },
1491 { "-xdebug", "debugMode", XrmoptionNoArg, "False" },
1492 { "-clockMode", "clockMode", XrmoptionSepArg, NULL },
1493 { "-clock", "clockMode", XrmoptionNoArg, "True" },
1494 { "-xclock", "clockMode", XrmoptionNoArg, "False" },
1495 { "-boardSize", "boardSize", XrmoptionSepArg, NULL },
1496 { "-size", "boardSize", XrmoptionSepArg, NULL },
1497 { "-searchTime", "searchTime", XrmoptionSepArg, NULL },
1498 { "-st", "searchTime", XrmoptionSepArg, NULL },
1499 { "-searchDepth", "searchDepth", XrmoptionSepArg, NULL },
1500 { "-depth", "searchDepth", XrmoptionSepArg, NULL },
1501 { "-showCoords", "showCoords", XrmoptionSepArg, NULL },
1502 { "-coords", "showCoords", XrmoptionNoArg, "True" },
1503 { "-xcoords", "showCoords", XrmoptionNoArg, "False" },
1505 { "-showJail", "showJail", XrmoptionSepArg, NULL },
1506 { "-jail", "showJail", XrmoptionNoArg, "1" },
1507 { "-sidejail", "showJail", XrmoptionNoArg, "2" },
1508 { "-xjail", "showJail", XrmoptionNoArg, "0" },
1510 { "-showThinking", "showThinking", XrmoptionSepArg, NULL },
1511 { "-thinking", "showThinking", XrmoptionNoArg, "True" },
1512 { "-xthinking", "showThinking", XrmoptionNoArg, "False" },
1513 { "-ponderNextMove", "ponderNextMove", XrmoptionSepArg, NULL },
1514 { "-ponder", "ponderNextMove", XrmoptionNoArg, "True" },
1515 { "-xponder", "ponderNextMove", XrmoptionNoArg, "False" },
1516 { "-periodicUpdates", "periodicUpdates", XrmoptionSepArg, NULL },
1517 { "-periodic", "periodicUpdates", XrmoptionNoArg, "True" },
1518 { "-xperiodic", "periodicUpdates", XrmoptionNoArg, "False" },
1519 { "-clockFont", "clockFont", XrmoptionSepArg, NULL },
1520 { "-coordFont", "coordFont", XrmoptionSepArg, NULL },
1521 { "-font", "font", XrmoptionSepArg, NULL },
1522 { "-ringBellAfterMoves", "ringBellAfterMoves", XrmoptionSepArg, NULL },
1523 { "-bell", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1524 { "-xbell", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1525 { "-movesound", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1526 { "-xmovesound", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1527 { "-autoCallFlag", "autoCallFlag", XrmoptionSepArg, NULL },
1528 { "-autoflag", "autoCallFlag", XrmoptionNoArg, "True" },
1529 { "-xautoflag", "autoCallFlag", XrmoptionNoArg, "False" },
1530 { "-autoFlipView", "autoFlipView", XrmoptionSepArg, NULL },
1531 { "-autoflip", "autoFlipView", XrmoptionNoArg, "True" },
1532 { "-xautoflip", "autoFlipView", XrmoptionNoArg, "False" },
1533 { "-autoObserve", "autoObserve", XrmoptionSepArg, NULL },
1534 { "-autobs", "autoObserve", XrmoptionNoArg, "True" },
1535 { "-xautobs", "autoObserve", XrmoptionNoArg, "False" },
1536 { "-autoComment", "autoComment", XrmoptionSepArg, NULL },
1537 { "-autocomm", "autoComment", XrmoptionNoArg, "True" },
1538 { "-xautocomm", "autoComment", XrmoptionNoArg, "False" },
1539 { "-getMoveList", "getMoveList", XrmoptionSepArg, NULL },
1540 { "-moves", "getMoveList", XrmoptionNoArg, "True" },
1541 { "-xmoves", "getMoveList", XrmoptionNoArg, "False" },
1543 { "-highlightDragging", "highlightDragging", XrmoptionSepArg, NULL },
1544 { "-highdrag", "highlightDragging", XrmoptionNoArg, "True" },
1545 { "-xhighdrag", "highlightDragging", XrmoptionNoArg, "False" },
1547 { "-highlightLastMove", "highlightLastMove", XrmoptionSepArg, NULL },
1548 { "-highlight", "highlightLastMove", XrmoptionNoArg, "True" },
1549 { "-xhighlight", "highlightLastMove", XrmoptionNoArg, "False" },
1550 { "-premove", "premove", XrmoptionSepArg, NULL },
1551 { "-pre", "premove", XrmoptionNoArg, "True" },
1552 { "-xpre", "premove", XrmoptionNoArg, "False" },
1553 { "-testLegality", "testLegality", XrmoptionSepArg, NULL },
1554 { "-legal", "testLegality", XrmoptionNoArg, "True" },
1555 { "-xlegal", "testLegality", XrmoptionNoArg, "False" },
1556 { "-flipView", "flipView", XrmoptionSepArg, NULL },
1557 { "-flip", "flipView", XrmoptionNoArg, "True" },
1558 { "-xflip", "flipView", XrmoptionNoArg, "False" },
1559 { "-cmail", "cmailGameName", XrmoptionSepArg, NULL },
1560 { "-alwaysPromoteToQueen", "alwaysPromoteToQueen",
1561 XrmoptionSepArg, NULL },
1562 { "-queen", "alwaysPromoteToQueen", XrmoptionNoArg, "True" },
1563 { "-xqueen", "alwaysPromoteToQueen", XrmoptionNoArg, "False" },
1564 { "-oldSaveStyle", "oldSaveStyle", XrmoptionSepArg, NULL },
1565 { "-oldsave", "oldSaveStyle", XrmoptionNoArg, "True" },
1566 { "-xoldsave", "oldSaveStyle", XrmoptionNoArg, "False" },
1567 { "-quietPlay", "quietPlay", XrmoptionSepArg, NULL },
1568 { "-quiet", "quietPlay", XrmoptionNoArg, "True" },
1569 { "-xquiet", "quietPlay", XrmoptionNoArg, "False" },
1570 { "-titleInWindow", "titleInWindow", XrmoptionSepArg, NULL },
1571 { "-title", "titleInWindow", XrmoptionNoArg, "True" },
1572 { "-xtitle", "titleInWindow", XrmoptionNoArg, "False" },
1574 { "-zippyTalk", "zippyTalk", XrmoptionSepArg, NULL },
1575 { "-zt", "zippyTalk", XrmoptionNoArg, "True" },
1576 { "-xzt", "zippyTalk", XrmoptionNoArg, "False" },
1577 { "-zippyPlay", "zippyPlay", XrmoptionSepArg, NULL },
1578 { "-zp", "zippyPlay", XrmoptionNoArg, "True" },
1579 { "-xzp", "zippyPlay", XrmoptionNoArg, "False" },
1580 { "-zippyLines", "zippyLines", XrmoptionSepArg, NULL },
1581 { "-zippyPinhead", "zippyPinhead", XrmoptionSepArg, NULL },
1582 { "-zippyPassword", "zippyPassword", XrmoptionSepArg, NULL },
1583 { "-zippyPassword2", "zippyPassword2", XrmoptionSepArg, NULL },
1584 { "-zippyWrongPassword", "zippyWrongPassword", XrmoptionSepArg, NULL },
1585 { "-zippyAcceptOnly", "zippyAcceptOnly", XrmoptionSepArg, NULL },
1586 { "-zippyUseI", "zippyUseI", XrmoptionSepArg, NULL },
1587 { "-zui", "zippyUseI", XrmoptionNoArg, "True" },
1588 { "-xzui", "zippyUseI", XrmoptionNoArg, "False" },
1589 { "-zippyBughouse", "zippyBughouse", XrmoptionSepArg, NULL },
1590 { "-zippyNoplayCrafty", "zippyNoplayCrafty", XrmoptionSepArg, NULL },
1591 { "-znc", "zippyNoplayCrafty", XrmoptionNoArg, "True" },
1592 { "-xznc", "zippyNoplayCrafty", XrmoptionNoArg, "False" },
1593 { "-zippyGameEnd", "zippyGameEnd", XrmoptionSepArg, NULL },
1594 { "-zippyGameStart", "zippyGameStart", XrmoptionSepArg, NULL },
1595 { "-zippyAdjourn", "zippyAdjourn", XrmoptionSepArg, NULL },
1596 { "-zadj", "zippyAdjourn", XrmoptionNoArg, "True" },
1597 { "-xzadj", "zippyAdjourn", XrmoptionNoArg, "False" },
1598 { "-zippyAbort", "zippyAbort", XrmoptionSepArg, NULL },
1599 { "-zab", "zippyAbort", XrmoptionNoArg, "True" },
1600 { "-xzab", "zippyAbort", XrmoptionNoArg, "False" },
1601 { "-zippyVariants", "zippyVariants", XrmoptionSepArg, NULL },
1602 { "-zippyMaxGames", "zippyMaxGames", XrmoptionSepArg, NULL },
1603 { "-zippyReplayTimeout", "zippyReplayTimeout", XrmoptionSepArg, NULL },
1605 { "-flashCount", "flashCount", XrmoptionSepArg, NULL },
1606 { "-flash", "flashCount", XrmoptionNoArg, "3" },
1607 { "-xflash", "flashCount", XrmoptionNoArg, "0" },
1608 { "-flashRate", "flashRate", XrmoptionSepArg, NULL },
1609 { "-pixmapDirectory", "pixmapDirectory", XrmoptionSepArg, NULL },
1610 { "-msLoginDelay", "msLoginDelay", XrmoptionSepArg, NULL },
1611 { "-pixmap", "pixmapDirectory", XrmoptionSepArg, NULL },
1612 { "-colorizeMessages", "colorizeMessages", XrmoptionSepArg, NULL },
1613 { "-colorize", "colorizeMessages", XrmoptionNoArg, "True" },
1614 { "-xcolorize", "colorizeMessages", XrmoptionNoArg, "False" },
1615 { "-colorShout", "colorShout", XrmoptionSepArg, NULL },
1616 { "-colorSShout", "colorSShout", XrmoptionSepArg, NULL },
1617 { "-colorCShout", "colorSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1618 { "-colorChannel1", "colorChannel1", XrmoptionSepArg, NULL },
1619 { "-colorChannel", "colorChannel", XrmoptionSepArg, NULL },
1620 { "-colorKibitz", "colorKibitz", XrmoptionSepArg, NULL },
1621 { "-colorTell", "colorTell", XrmoptionSepArg, NULL },
1622 { "-colorChallenge", "colorChallenge", XrmoptionSepArg, NULL },
1623 { "-colorRequest", "colorRequest", XrmoptionSepArg, NULL },
1624 { "-colorSeek", "colorSeek", XrmoptionSepArg, NULL },
1625 { "-colorNormal", "colorNormal", XrmoptionSepArg, NULL },
1626 { "-soundProgram", "soundProgram", XrmoptionSepArg, NULL },
1627 { "-soundShout", "soundShout", XrmoptionSepArg, NULL },
1628 { "-soundSShout", "soundSShout", XrmoptionSepArg, NULL },
1629 { "-soundCShout", "soundSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1630 { "-soundChannel1", "soundChannel1", XrmoptionSepArg, NULL },
1631 { "-soundChannel", "soundChannel", XrmoptionSepArg, NULL },
1632 { "-soundKibitz", "soundKibitz", XrmoptionSepArg, NULL },
1633 { "-soundTell", "soundTell", XrmoptionSepArg, NULL },
1634 { "-soundChallenge", "soundChallenge", XrmoptionSepArg, NULL },
1635 { "-soundRequest", "soundRequest", XrmoptionSepArg, NULL },
1636 { "-soundSeek", "soundSeek", XrmoptionSepArg, NULL },
1637 { "-soundMove", "soundMove", XrmoptionSepArg, NULL },
1638 { "-soundIcsWin", "soundIcsWin", XrmoptionSepArg, NULL },
1639 { "-soundIcsLoss", "soundIcsLoss", XrmoptionSepArg, NULL },
1640 { "-soundIcsDraw", "soundIcsDraw", XrmoptionSepArg, NULL },
1641 { "-soundIcsUnfinished", "soundIcsUnfinished", XrmoptionSepArg, NULL },
1642 { "-soundIcsAlarm", "soundIcsAlarm", XrmoptionSepArg, NULL },
1643 { "-reuseFirst", "reuseFirst", XrmoptionSepArg, NULL },
1644 { "-reuseChessPrograms", "reuseFirst", XrmoptionSepArg, NULL }, /*compat*/
1645 { "-reuse", "reuseFirst", XrmoptionNoArg, "True" },
1646 { "-xreuse", "reuseFirst", XrmoptionNoArg, "False" },
1647 { "-reuseSecond", "reuseSecond", XrmoptionSepArg, NULL },
1648 { "-reuse2", "reuseSecond", XrmoptionNoArg, "True" },
1649 { "-xreuse2", "reuseSecond", XrmoptionNoArg, "False" },
1650 { "-animateMoving", "animateMoving", XrmoptionSepArg, NULL },
1651 { "-animate", "animateMoving", XrmoptionNoArg, "True" },
1652 { "-xanimate", "animateMoving", XrmoptionNoArg, "False" },
1653 { "-animateDragging", "animateDragging", XrmoptionSepArg, NULL },
1654 { "-drag", "animateDragging", XrmoptionNoArg, "True" },
1655 { "-xdrag", "animateDragging", XrmoptionNoArg, "False" },
1656 { "-animateSpeed", "animateSpeed", XrmoptionSepArg, NULL },
1657 { "-popupExitMessage", "popupExitMessage", XrmoptionSepArg, NULL },
1658 { "-exit", "popupExitMessage", XrmoptionNoArg, "True" },
1659 { "-xexit", "popupExitMessage", XrmoptionNoArg, "False" },
1660 { "-popupMoveErrors", "popupMoveErrors", XrmoptionSepArg, NULL },
1661 { "-popup", "popupMoveErrors", XrmoptionNoArg, "True" },
1662 { "-xpopup", "popupMoveErrors", XrmoptionNoArg, "False" },
1663 { "-fontSizeTolerance", "fontSizeTolerance", XrmoptionSepArg, NULL },
1664 { "-initialMode", "initialMode", XrmoptionSepArg, NULL },
1665 { "-mode", "initialMode", XrmoptionSepArg, NULL },
1666 { "-variant", "variant", XrmoptionSepArg, NULL },
1667 { "-firstProtocolVersion", "firstProtocolVersion", XrmoptionSepArg, NULL },
1668 { "-secondProtocolVersion","secondProtocolVersion",XrmoptionSepArg, NULL },
1669 { "-showButtonBar", "showButtonBar", XrmoptionSepArg, NULL },
1670 { "-buttons", "showButtonBar", XrmoptionNoArg, "True" },
1671 { "-xbuttons", "showButtonBar", XrmoptionNoArg, "False" },
1672 /* [AS,HR] New features */
1673 { "-firstScoreAbs", "firstScoreAbs", XrmoptionSepArg, NULL },
1674 { "-secondScoreAbs", "secondScoreAbs", XrmoptionSepArg, NULL },
1675 { "-pgnExtendedInfo", "pgnExtendedInfo", XrmoptionSepArg, NULL },
1676 { "-hideThinkingFromHuman", "hideThinkingFromHuman", XrmoptionSepArg, NULL },
1677 { "-adjudicateLossThreshold", "adjudicateLossThreshold", XrmoptionSepArg, NULL },
1678 { "-pgnEventHeader", "pgnEventHeader", XrmoptionSepArg, NULL },
1679 { "-firstIsUCI", "firstIsUCI", XrmoptionSepArg, NULL },
1680 { "-secondIsUCI", "secondIsUCI", XrmoptionSepArg, NULL },
1681 { "-fUCI", "firstIsUCI", XrmoptionNoArg, "True" },
1682 { "-sUCI", "secondIsUCI", XrmoptionNoArg, "True" },
1683 { "-firstHasOwnBookUCI", "firstHasOwnBookUCI", XrmoptionSepArg, NULL },
1684 { "-secondHasOwnBookUCI", "secondHasOwnBookUCI", XrmoptionSepArg, NULL },
1685 { "-fNoOwnBookUCI", "firstHasOwnBookUCI", XrmoptionNoArg, "False" },
1686 { "-sNoOwnBookUCI", "secondHasOwnBookUCI", XrmoptionNoArg, "False" },
1687 { "-firstXBook", "firstHasOwnBookUCI", XrmoptionNoArg, "False" },
1688 { "-secondXBook", "secondHasOwnBookUCI", XrmoptionNoArg, "False" },
1689 { "-polyglotDir", "polyglotDir", XrmoptionSepArg, NULL },
1690 { "-usePolyglotBook", "usePolyglotBook", XrmoptionSepArg, NULL },
1691 { "-polyglotBook", "polyglotBook", XrmoptionSepArg, NULL },
1692 { "-defaultHashSize", "defaultHashSize", XrmoptionSepArg, NULL },
1693 { "-defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XrmoptionSepArg, NULL },
1694 { "-defaultPathEGTB", "defaultPathEGTB", XrmoptionSepArg, NULL },
1695 { "-defaultFrcPosition", "defaultFrcPosition", XrmoptionSepArg, NULL },
1696 { "-gameListTags", "gameListTags", XrmoptionSepArg, NULL },
1697 // [HGM] I am sure AS added many more options, but we have to fish them out, from the list in winboard.c
1699 /* [HGM,HR] User-selectable board size */
1700 { "-boardWidth", "boardWidth", XrmoptionSepArg, NULL },
1701 { "-boardHeight", "boardHeight", XrmoptionSepArg, NULL },
1702 { "-matchPause", "matchPause", XrmoptionSepArg, NULL },
1704 /* [HGM] new arguments of 4.3.xx. All except first three are back-end options, which should work immediately */
1705 { "-holdingsSize", "holdingsSize", XrmoptionSepArg, NULL }, // requires extensive front-end changes to work
1706 { "-flipBlack", "flipBlack", XrmoptionSepArg, NULL }, // requires front-end changes to work
1707 { "-allWhite", "allWhite", XrmoptionSepArg, NULL }, // requires front-end changes to work
1708 { "-pieceToCharTable", "pieceToCharTable", XrmoptionSepArg, NULL },
1709 { "-alphaRank", "alphaRank", XrmoptionSepArg, NULL },
1710 { "-testClaims", "testClaims", XrmoptionSepArg, NULL },
1711 { "-checkMates", "checkMates", XrmoptionSepArg, NULL },
1712 { "-materialDraws", "materialDraws", XrmoptionSepArg, NULL },
1713 { "-trivialDraws", "trivialDraws", XrmoptionSepArg, NULL },
1714 { "-ruleMoves", "ruleMoves", XrmoptionSepArg, NULL },
1715 { "-repeatsToDraw", "repeatsToDraw", XrmoptionSepArg, NULL },
1716 { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL },
1717 { "-userName", "userName", XrmoptionSepArg, NULL },
1718 { "-autoKibitz", "autoKibitz", XrmoptionNoArg, "True" },
1719 { "-firstTimeOdds", "firstTimeOdds", XrmoptionSepArg, NULL },
1720 { "-secondTimeOdds", "secondTimeOdds", XrmoptionSepArg, NULL },
1721 { "-timeOddsMode", "timeOddsMode", XrmoptionSepArg, NULL },
1722 { "-firstAccumulateTC", "firstAccumulateTC", XrmoptionSepArg, NULL },
1723 { "-secondAccumulateTC", "secondAccumulateTC", XrmoptionSepArg, NULL },
1724 { "-firstNPS", "firstNPS", XrmoptionSepArg, NULL },
1725 { "-secondNPS", "secondNPS", XrmoptionSepArg, NULL },
1726 { "-serverMoves", "serverMoves", XrmoptionSepArg, NULL },
1727 { "-serverPause", "serverPause", XrmoptionSepArg, NULL },
1728 { "-suppressLoadMoves", "suppressLoadMoves", XrmoptionSepArg, NULL },
1729 { "-egtFormats", "egtFormats", XrmoptionSepArg, NULL },
1730 { "-userName", "userName", XrmoptionSepArg, NULL },
1731 { "-smpCores", "smpCores", XrmoptionSepArg, NULL },
1732 { "-sameColorGames", "sameColorGames", XrmoptionSepArg, NULL },
1733 { "-rewindIndex", "rewindIndex", XrmoptionSepArg, NULL },
1734 { "-niceEngines", "niceEngines", XrmoptionSepArg, NULL },
1735 { "-delayBeforeQuit", "delayBeforeQuit", XrmoptionSepArg, NULL },
1736 { "-delayAfterQuit", "delayAfterQuit", XrmoptionSepArg, NULL },
1737 { "-nameOfDebugFile", "nameOfDebugFile", XrmoptionSepArg, NULL },
1738 { "-debugFile", "nameOfDebugFile", XrmoptionSepArg, NULL },
1739 { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL },
1740 { "-noGUI", "noGUI", XrmoptionNoArg, "True" },
1741 { "-firstOptions", "firstOptions", XrmoptionSepArg, NULL },
1742 { "-secondOptions", "secondOptions", XrmoptionSepArg, NULL },
1743 { "-firstNeedsNoncompliantFEN", "firstNeedsNoncompliantFEN", XrmoptionSepArg, NULL },
1744 { "-secondNeedsNoncompliantFEN", "secondNeedsNoncompliantFEN", XrmoptionSepArg, NULL },
1748 XtActionsRec boardActions[] = {
1749 { "DrawPosition", DrawPositionProc },
1750 { "HandleUserMove", HandleUserMove },
1751 { "AnimateUserMove", AnimateUserMove },
1752 { "FileNameAction", FileNameAction },
1753 { "AskQuestionProc", AskQuestionProc },
1754 { "AskQuestionReplyAction", AskQuestionReplyAction },
1755 { "PieceMenuPopup", PieceMenuPopup },
1756 { "WhiteClock", WhiteClock },
1757 { "BlackClock", BlackClock },
1758 { "Iconify", Iconify },
1759 { "ResetProc", ResetProc },
1760 { "LoadGameProc", LoadGameProc },
1761 { "LoadNextGameProc", LoadNextGameProc },
1762 { "LoadPrevGameProc", LoadPrevGameProc },
1763 { "LoadSelectedProc", LoadSelectedProc },
1764 { "ReloadGameProc", ReloadGameProc },
1765 { "LoadPositionProc", LoadPositionProc },
1766 { "LoadNextPositionProc", LoadNextPositionProc },
1767 { "LoadPrevPositionProc", LoadPrevPositionProc },
1768 { "ReloadPositionProc", ReloadPositionProc },
1769 { "CopyPositionProc", CopyPositionProc },
1770 { "PastePositionProc", PastePositionProc },
1771 { "CopyGameProc", CopyGameProc },
1772 { "PasteGameProc", PasteGameProc },
1773 { "SaveGameProc", SaveGameProc },
1774 { "SavePositionProc", SavePositionProc },
1775 { "MailMoveProc", MailMoveProc },
1776 { "ReloadCmailMsgProc", ReloadCmailMsgProc },
1777 { "QuitProc", QuitProc },
1778 { "MachineWhiteProc", MachineWhiteProc },
1779 { "MachineBlackProc", MachineBlackProc },
1780 { "AnalysisModeProc", AnalyzeModeProc },
1781 { "AnalyzeFileProc", AnalyzeFileProc },
1782 { "TwoMachinesProc", TwoMachinesProc },
1783 { "IcsClientProc", IcsClientProc },
1784 { "EditGameProc", EditGameProc },
1785 { "EditPositionProc", EditPositionProc },
1786 { "TrainingProc", EditPositionProc },
1787 { "EngineOutputProc", EngineOutputProc}, // [HGM] Winboard_x engine-output window
1788 { "ShowGameListProc", ShowGameListProc },
1789 { "ShowMoveListProc", HistoryShowProc},
1790 { "EditTagsProc", EditCommentProc },
1791 { "EditCommentProc", EditCommentProc },
1792 { "IcsAlarmProc", IcsAlarmProc },
1793 { "IcsInputBoxProc", IcsInputBoxProc },
1794 { "PauseProc", PauseProc },
1795 { "AcceptProc", AcceptProc },
1796 { "DeclineProc", DeclineProc },
1797 { "RematchProc", RematchProc },
1798 { "CallFlagProc", CallFlagProc },
1799 { "DrawProc", DrawProc },
1800 { "AdjournProc", AdjournProc },
1801 { "AbortProc", AbortProc },
1802 { "ResignProc", ResignProc },
1803 { "AdjuWhiteProc", AdjuWhiteProc },
1804 { "AdjuBlackProc", AdjuBlackProc },
1805 { "AdjuDrawProc", AdjuDrawProc },
1806 { "EnterKeyProc", EnterKeyProc },
1807 { "StopObservingProc", StopObservingProc },
1808 { "StopExaminingProc", StopExaminingProc },
1809 { "BackwardProc", BackwardProc },
1810 { "ForwardProc", ForwardProc },
1811 { "ToStartProc", ToStartProc },
1812 { "ToEndProc", ToEndProc },
1813 { "RevertProc", RevertProc },
1814 { "TruncateGameProc", TruncateGameProc },
1815 { "MoveNowProc", MoveNowProc },
1816 { "RetractMoveProc", RetractMoveProc },
1817 { "AlwaysQueenProc", AlwaysQueenProc },
1818 { "AnimateDraggingProc", AnimateDraggingProc },
1819 { "AnimateMovingProc", AnimateMovingProc },
1820 { "AutoflagProc", AutoflagProc },
1821 { "AutoflipProc", AutoflipProc },
1822 { "AutobsProc", AutobsProc },
1823 { "AutoraiseProc", AutoraiseProc },
1824 { "AutosaveProc", AutosaveProc },
1825 { "BlindfoldProc", BlindfoldProc },
1826 { "FlashMovesProc", FlashMovesProc },
1827 { "FlipViewProc", FlipViewProc },
1828 { "GetMoveListProc", GetMoveListProc },
1830 { "HighlightDraggingProc", HighlightDraggingProc },
1832 { "HighlightLastMoveProc", HighlightLastMoveProc },
1833 { "IcsAlarmProc", IcsAlarmProc },
1834 { "MoveSoundProc", MoveSoundProc },
1835 { "OldSaveStyleProc", OldSaveStyleProc },
1836 { "PeriodicUpdatesProc", PeriodicUpdatesProc },
1837 { "PonderNextMoveProc", PonderNextMoveProc },
1838 { "PopupExitMessageProc", PopupExitMessageProc },
1839 { "PopupMoveErrorsProc", PopupMoveErrorsProc },
1840 { "PremoveProc", PremoveProc },
1841 { "QuietPlayProc", QuietPlayProc },
1842 { "ShowCoordsProc", ShowCoordsProc },
1843 { "ShowThinkingProc", ShowThinkingProc },
1844 { "HideThinkingProc", HideThinkingProc },
1845 { "TestLegalityProc", TestLegalityProc },
1846 { "InfoProc", InfoProc },
1847 { "ManProc", ManProc },
1848 { "HintProc", HintProc },
1849 { "BookProc", BookProc },
1850 { "AboutGameProc", AboutGameProc },
1851 { "AboutProc", AboutProc },
1852 { "DebugProc", DebugProc },
1853 { "NothingProc", NothingProc },
1854 { "CommentPopDown", (XtActionProc) CommentPopDown },
1855 { "EditCommentPopDown", (XtActionProc) EditCommentPopDown },
1856 { "TagsPopDown", (XtActionProc) TagsPopDown },
1857 { "ErrorPopDown", (XtActionProc) ErrorPopDown },
1858 { "ICSInputBoxPopDown", (XtActionProc) ICSInputBoxPopDown },
1859 { "AnalysisPopDown", (XtActionProc) AnalysisPopDown },
1860 { "FileNamePopDown", (XtActionProc) FileNamePopDown },
1861 { "AskQuestionPopDown", (XtActionProc) AskQuestionPopDown },
1862 { "GameListPopDown", (XtActionProc) GameListPopDown },
1863 { "PromotionPopDown", (XtActionProc) PromotionPopDown },
1864 { "HistoryPopDown", (XtActionProc) HistoryPopDown },
1865 { "EngineOutputPopDown", (XtActionProc) EngineOutputPopDown },
1866 { "ShufflePopDown", (XtActionProc) ShufflePopDown },
1867 { "EnginePopDown", (XtActionProc) EnginePopDown },
1868 { "UciPopDown", (XtActionProc) UciPopDown },
1869 { "TimeControlPopDown", (XtActionProc) TimeControlPopDown },
1870 { "NewVariantPopDown", (XtActionProc) NewVariantPopDown },
1871 { "SettingsPopDown", (XtActionProc) SettingsPopDown },
1874 char globalTranslations[] =
1875 ":<Key>R: ResignProc() \n \
1876 :<Key>r: ResetProc() \n \
1877 :<Key>g: LoadGameProc() \n \
1878 :<Key>N: LoadNextGameProc() \n \
1879 :<Key>P: LoadPrevGameProc() \n \
1880 :<Key>Q: QuitProc() \n \
1881 :<Key>F: ToEndProc() \n \
1882 :<Key>f: ForwardProc() \n \
1883 :<Key>B: ToStartProc() \n \
1884 :<Key>b: BackwardProc() \n \
1885 :<Key>p: PauseProc() \n \
1886 :<Key>d: DrawProc() \n \
1887 :<Key>t: CallFlagProc() \n \
1888 :<Key>i: Iconify() \n \
1889 :<Key>c: Iconify() \n \
1890 :<Key>v: FlipViewProc() \n \
1891 <KeyDown>Control_L: BackwardProc() \n \
1892 <KeyUp>Control_L: ForwardProc() \n \
1893 <KeyDown>Control_R: BackwardProc() \n \
1894 <KeyUp>Control_R: ForwardProc() \n \
1895 Shift<Key>1: AskQuestionProc(\"Direct command\",\
1896 \"Send to chess program:\",,1) \n \
1897 Shift<Key>2: AskQuestionProc(\"Direct command\",\
1898 \"Send to second chess program:\",,2) \n";
1900 char boardTranslations[] =
1901 "<Btn1Down>: HandleUserMove() \n \
1902 <Btn1Up>: HandleUserMove() \n \
1903 <Btn1Motion>: AnimateUserMove() \n \
1904 Shift<Btn2Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD)\
1905 PieceMenuPopup(menuB) \n \
1906 Any<Btn2Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD) \
1907 PieceMenuPopup(menuW) \n \
1908 Shift<Btn3Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD)\
1909 PieceMenuPopup(menuW) \n \
1910 Any<Btn3Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD) \
1911 PieceMenuPopup(menuB) \n";
1913 char whiteTranslations[] = "<BtnDown>: WhiteClock()\n";
1914 char blackTranslations[] = "<BtnDown>: BlackClock()\n";
1916 char ICSInputTranslations[] =
1917 "<Key>Return: EnterKeyProc() \n";
1919 String xboardResources[] = {
1920 "*fileName*value.translations: #override\\n <Key>Return: FileNameAction()",
1921 "*question*value.translations: #override\\n <Key>Return: AskQuestionReplyAction()",
1922 "*errorpopup*translations: #override\\n <Key>Return: ErrorPopDown()",
1927 /* Max possible square size */
1928 #define MAXSQSIZE 256
1930 static int xpm_avail[MAXSQSIZE];
1932 #ifdef HAVE_DIR_STRUCT
1934 /* Extract piece size from filename */
1936 xpm_getsize(name, len, ext)
1947 if ((p=strchr(name, '.')) == NULL ||
1948 StrCaseCmp(p+1, ext) != 0)
1954 while (*p && isdigit(*p))
1961 /* Setup xpm_avail */
1963 xpm_getavail(dirname, ext)
1971 for (i=0; i<MAXSQSIZE; ++i)
1974 if (appData.debugMode)
1975 fprintf(stderr, "XPM dir:%s:ext:%s:\n", dirname, ext);
1977 dir = opendir(dirname);
1980 fprintf(stderr, _("%s: Can't access XPM directory %s\n"),
1981 programName, dirname);
1985 while ((ent=readdir(dir)) != NULL) {
1986 i = xpm_getsize(ent->d_name, NAMLEN(ent), ext);
1987 if (i > 0 && i < MAXSQSIZE)
1997 xpm_print_avail(fp, ext)
2003 fprintf(fp, _("Available `%s' sizes:\n"), ext);
2004 for (i=1; i<MAXSQSIZE; ++i) {
2010 /* Return XPM piecesize closest to size */
2012 xpm_closest_to(dirname, size, ext)
2018 int sm_diff = MAXSQSIZE;
2022 xpm_getavail(dirname, ext);
2024 if (appData.debugMode)
2025 xpm_print_avail(stderr, ext);
2027 for (i=1; i<MAXSQSIZE; ++i) {
2030 diff = (diff<0) ? -diff : diff;
2031 if (diff < sm_diff) {
2039 fprintf(stderr, _("Error: No `%s' files!\n"), ext);
2045 #else /* !HAVE_DIR_STRUCT */
2046 /* If we are on a system without a DIR struct, we can't
2047 read the directory, so we can't collect a list of
2048 filenames, etc., so we can't do any size-fitting. */
2050 xpm_closest_to(dirname, size, ext)
2055 fprintf(stderr, _("\
2056 Warning: No DIR structure found on this system --\n\
2057 Unable to autosize for XPM/XIM pieces.\n\
2058 Please report this error to frankm@hiwaay.net.\n\
2059 Include system type & operating system in message.\n"));
2062 #endif /* HAVE_DIR_STRUCT */
2064 static char *cnames[9] = { "black", "red", "green", "yellow", "blue",
2065 "magenta", "cyan", "white" };
2069 TextColors textColors[(int)NColorClasses];
2071 /* String is: "fg, bg, attr". Which is 0, 1, 2 */
2073 parse_color(str, which)
2077 char *p, buf[100], *d;
2080 if (strlen(str) > 99) /* watch bounds on buf */
2085 for (i=0; i<which; ++i) {
2092 /* Could be looking at something like:
2094 .. in which case we want to stop on a comma also */
2095 while (*p && *p != ',' && !isalpha(*p) && !isdigit(*p))
2099 return -1; /* Use default for empty field */
2102 if (which == 2 || isdigit(*p))
2105 while (*p && isalpha(*p))
2110 for (i=0; i<8; ++i) {
2111 if (!StrCaseCmp(buf, cnames[i]))
2112 return which? (i+40) : (i+30);
2114 if (!StrCaseCmp(buf, "default")) return -1;
2116 fprintf(stderr, _("%s: unrecognized color %s\n"), programName, buf);
2121 parse_cpair(cc, str)
2125 if ((textColors[(int)cc].fg=parse_color(str, 0)) == -2) {
2126 fprintf(stderr, _("%s: can't parse foreground color in `%s'\n"),
2131 /* bg and attr are optional */
2132 textColors[(int)cc].bg = parse_color(str, 1);
2133 if ((textColors[(int)cc].attr = parse_color(str, 2)) < 0) {
2134 textColors[(int)cc].attr = 0;
2140 /* Arrange to catch delete-window events */
2141 Atom wm_delete_window;
2143 CatchDeleteWindow(Widget w, String procname)
2146 XSetWMProtocols(xDisplay, XtWindow(w), &wm_delete_window, 1);
2147 sprintf(buf, "<Message>WM_PROTOCOLS: %s() \n", procname);
2148 XtAugmentTranslations(w, XtParseTranslationTable(buf));
2155 XtSetArg(args[0], XtNiconic, False);
2156 XtSetValues(shellWidget, args, 1);
2158 XtPopup(shellWidget, XtGrabNone); /* Raise if lowered */
2162 // eventually, all layout determining code should go into a subroutine, but until then IDSIZE remains undefined
2164 #define BoardSize int
2165 void InitDrawingSizes(BoardSize boardSize, int flags)
2166 { // [HGM] resize is functional now, but for board format changes only (nr of ranks, files)
2167 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
2169 XtGeometryResult gres;
2172 if(!formWidget) return;
2175 * Enable shell resizing.
2177 shellArgs[0].value = (XtArgVal) &w;
2178 shellArgs[1].value = (XtArgVal) &h;
2179 XtGetValues(shellWidget, shellArgs, 2);
2181 shellArgs[4].value = 2*w; shellArgs[2].value = 10;
2182 shellArgs[5].value = 2*h; shellArgs[3].value = 10;
2183 XtSetValues(shellWidget, &shellArgs[2], 4);
2185 XtSetArg(args[0], XtNdefaultDistance, &sep);
2186 XtGetValues(formWidget, args, 1);
2188 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2189 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2192 XtSetArg(args[0], XtNwidth, boardWidth);
2193 XtSetArg(args[1], XtNheight, boardHeight);
2194 XtSetValues(boardWidget, args, 2);
2196 timerWidth = (boardWidth - sep) / 2;
2197 XtSetArg(args[0], XtNwidth, timerWidth);
2198 XtSetValues(whiteTimerWidget, args, 1);
2199 XtSetValues(blackTimerWidget, args, 1);
2201 XawFormDoLayout(formWidget, False);
2203 if (appData.titleInWindow) {
2205 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2206 XtSetArg(args[i], XtNheight, &h); i++;
2207 XtGetValues(titleWidget, args, i);
2209 w = boardWidth - 2*bor;
2211 XtSetArg(args[0], XtNwidth, &w);
2212 XtGetValues(menuBarWidget, args, 1);
2213 w = boardWidth - w - sep - 2*bor - 2; // WIDTH_FUDGE
2216 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
2217 if (gres != XtGeometryYes && appData.debugMode) {
2219 _("%s: titleWidget geometry error %d %d %d %d %d\n"),
2220 programName, gres, w, h, wr, hr);
2224 XawFormDoLayout(formWidget, True);
2227 * Inhibit shell resizing.
2229 shellArgs[0].value = w = (XtArgVal) boardWidth + marginW;
2230 shellArgs[1].value = h = (XtArgVal) boardHeight + marginH;
2231 shellArgs[4].value = shellArgs[2].value = w;
2232 shellArgs[5].value = shellArgs[3].value = h;
2233 XtSetValues(shellWidget, &shellArgs[0], 6);
2242 int i, j, clockFontPxlSize, coordFontPxlSize, fontPxlSize;
2243 XSetWindowAttributes window_attributes;
2245 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
2246 XrmValue vFrom, vTo;
2247 XtGeometryResult gres;
2250 int forceMono = False;
2253 // [HGM] before anything else, expand any indirection files amongst options
2254 char *argvCopy[1000]; // 1000 seems enough
2255 char newArgs[10000]; // holds actual characters
2258 srandom(time(0)); // [HGM] book: make random truly random
2261 for(i=0; i<argc; i++) {
2262 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2263 //fprintf(stderr, "arg %s\n", argv[i]);
2264 if(argv[i][0] != '@') argvCopy[j++] = argv[i]; else {
2266 FILE *f = fopen(argv[i]+1, "rb");
2267 if(f == NULL) { fprintf(stderr, _("ignore %s\n"), argv[i]); continue; } // do not expand non-existing
2268 argvCopy[j++] = newArgs + k; // get ready for first argument from file
2269 while((c = fgetc(f)) != EOF) { // each line of file inserts 1 argument in the list
2271 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2272 newArgs[k++] = 0; // terminate current arg
2273 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2274 argvCopy[j++] = newArgs + k; // get ready for next
2276 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2289 if(appData.debugMode,1) { // OK, appData is not initialized here yet...
2290 for(i=0; i<argc; i++) fprintf(stderr, "argv[%2d] = '%s'\n", i, argv[i]);
2296 setbuf(stdout, NULL);
2297 setbuf(stderr, NULL);
2300 programName = strrchr(argv[0], '/');
2301 if (programName == NULL)
2302 programName = argv[0];
2307 XtSetLanguageProc(NULL, NULL, NULL);
2308 bindtextdomain(PRODUCT, LOCALEDIR);
2309 textdomain(PRODUCT);
2313 XtAppInitialize(&appContext, "XBoard", shellOptions,
2314 XtNumber(shellOptions),
2315 &argc, argv, xboardResources, NULL, 0);
2317 fprintf(stderr, _("%s: unrecognized argument %s\n"),
2318 programName, argv[1]);
2322 if ((chessDir = (char *) getenv("CHESSDIR")) == NULL) {
2325 if (chdir(chessDir) != 0) {
2326 fprintf(stderr, _("%s: can't cd to CHESSDIR: "), programName);
2333 if (p == NULL) p = "/tmp";
2334 i = strlen(p) + strlen("/.xboardXXXXXx.pgn") + 1;
2335 gameCopyFilename = (char*) malloc(i);
2336 gamePasteFilename = (char*) malloc(i);
2337 sprintf(gameCopyFilename, "%s/.xboard%05uc.pgn", p, getpid());
2338 sprintf(gamePasteFilename, "%s/.xboard%05up.pgn", p, getpid());
2340 XtGetApplicationResources(shellWidget, (XtPointer) &appData,
2341 clientResources, XtNumber(clientResources),
2344 if (appData.debugMode && appData.nameOfDebugFile && strcmp(appData.nameOfDebugFile, "stderr")) {
2345 /* [DM] debug info to file [HGM] make the filename a command-line option, and allow it to remain stderr */
2346 if ((debugFP = fopen(appData.nameOfDebugFile, "w")) == NULL) {
2347 printf(_("Failed to open file '%s'\n"), appData.nameOfDebugFile);
2350 setbuf(debugFP, NULL);
2353 /* [HGM,HR] make sure board size is acceptable */
2354 if(appData.NrFiles > BOARD_SIZE ||
2355 appData.NrRanks > BOARD_SIZE )
2356 DisplayFatalError(_("Recompile with BOARD_SIZE > 12, to support this size"), 0, 2);
2359 /* This feature does not work; animation needs a rewrite */
2360 appData.highlightDragging = FALSE;
2364 xDisplay = XtDisplay(shellWidget);
2365 xScreen = DefaultScreen(xDisplay);
2366 wm_delete_window = XInternAtom(xDisplay, "WM_DELETE_WINDOW", True);
2368 gameInfo.variant = StringToVariant(appData.variant);
2369 InitPosition(FALSE);
2372 * Determine boardSize
2374 gameInfo.boardWidth = gameInfo.boardHeight = 8; // [HGM] boardsize: make sure we start as 8x8
2377 // [HGM] as long as we have not created the possibility to change size while running, start with requested size
2378 gameInfo.boardWidth = appData.NrFiles > 0 ? appData.NrFiles : 8;
2379 gameInfo.boardHeight = appData.NrRanks > 0 ? appData.NrRanks : 8;
2380 gameInfo.holdingsWidth = appData.holdingsSize > 0 ? 2 : 0;
2385 InitDrawingSizes(-1, 0); // [HGM] initsize: make this into a subroutine
2387 if (isdigit(appData.boardSize[0])) {
2388 i = sscanf(appData.boardSize, "%d,%d,%d,%d,%d,%d,%d", &squareSize,
2389 &lineGap, &clockFontPxlSize, &coordFontPxlSize,
2390 &fontPxlSize, &smallLayout, &tinyLayout);
2392 fprintf(stderr, _("%s: bad boardSize syntax %s\n"),
2393 programName, appData.boardSize);
2397 /* Find some defaults; use the nearest known size */
2398 SizeDefaults *szd, *nearest;
2399 int distance = 99999;
2400 nearest = szd = sizeDefaults;
2401 while (szd->name != NULL) {
2402 if (abs(szd->squareSize - squareSize) < distance) {
2404 distance = abs(szd->squareSize - squareSize);
2405 if (distance == 0) break;
2409 if (i < 2) lineGap = nearest->lineGap;
2410 if (i < 3) clockFontPxlSize = nearest->clockFontPxlSize;
2411 if (i < 4) coordFontPxlSize = nearest->coordFontPxlSize;
2412 if (i < 5) fontPxlSize = nearest->fontPxlSize;
2413 if (i < 6) smallLayout = nearest->smallLayout;
2414 if (i < 7) tinyLayout = nearest->tinyLayout;
2417 SizeDefaults *szd = sizeDefaults;
2418 if (*appData.boardSize == NULLCHAR) {
2419 while (DisplayWidth(xDisplay, xScreen) < szd->minScreenSize ||
2420 DisplayHeight(xDisplay, xScreen) < szd->minScreenSize) {
2423 if (szd->name == NULL) szd--;
2425 while (szd->name != NULL &&
2426 StrCaseCmp(szd->name, appData.boardSize) != 0) szd++;
2427 if (szd->name == NULL) {
2428 fprintf(stderr, _("%s: unrecognized boardSize name %s\n"),
2429 programName, appData.boardSize);
2433 squareSize = szd->squareSize;
2434 lineGap = szd->lineGap;
2435 clockFontPxlSize = szd->clockFontPxlSize;
2436 coordFontPxlSize = szd->coordFontPxlSize;
2437 fontPxlSize = szd->fontPxlSize;
2438 smallLayout = szd->smallLayout;
2439 tinyLayout = szd->tinyLayout;
2442 /* Now, using squareSize as a hint, find a good XPM/XIM set size */
2443 if (strlen(appData.pixmapDirectory) > 0) {
2444 p = ExpandPathName(appData.pixmapDirectory);
2446 fprintf(stderr, _("Error expanding path name \"%s\"\n"),
2447 appData.pixmapDirectory);
2450 if (appData.debugMode) {
2451 fprintf(stderr, _("\
2452 XBoard square size (hint): %d\n\
2453 %s fulldir:%s:\n"), squareSize, IMAGE_EXT, p);
2455 squareSize = xpm_closest_to(p, squareSize, IMAGE_EXT);
2456 if (appData.debugMode) {
2457 fprintf(stderr, _("Closest %s size: %d\n"), IMAGE_EXT, squareSize);
2461 /* [HR] height treated separately (hacked) */
2462 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2463 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2464 if (appData.showJail == 1) {
2465 /* Jail on top and bottom */
2466 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2467 XtSetArg(boardArgs[2], XtNheight,
2468 boardHeight + 2*(lineGap + squareSize));
2469 } else if (appData.showJail == 2) {
2471 XtSetArg(boardArgs[1], XtNwidth,
2472 boardWidth + 2*(lineGap + squareSize));
2473 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2476 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2477 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2481 * Determine what fonts to use.
2483 appData.clockFont = FindFont(appData.clockFont, clockFontPxlSize);
2484 clockFontID = XLoadFont(xDisplay, appData.clockFont);
2485 clockFontStruct = XQueryFont(xDisplay, clockFontID);
2486 appData.coordFont = FindFont(appData.coordFont, coordFontPxlSize);
2487 coordFontID = XLoadFont(xDisplay, appData.coordFont);
2488 coordFontStruct = XQueryFont(xDisplay, coordFontID);
2489 appData.font = FindFont(appData.font, fontPxlSize);
2490 countFontID = XLoadFont(xDisplay, appData.coordFont); // [HGM] holdings
2491 countFontStruct = XQueryFont(xDisplay, countFontID);
2492 // appData.font = FindFont(appData.font, fontPxlSize);
2494 xdb = XtDatabase(xDisplay);
2495 XrmPutStringResource(&xdb, "*font", appData.font);
2498 * Detect if there are not enough colors available and adapt.
2500 if (DefaultDepth(xDisplay, xScreen) <= 2) {
2501 appData.monoMode = True;
2504 if (!appData.monoMode) {
2505 vFrom.addr = (caddr_t) appData.lightSquareColor;
2506 vFrom.size = strlen(appData.lightSquareColor);
2507 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2508 if (vTo.addr == NULL) {
2509 appData.monoMode = True;
2512 lightSquareColor = *(Pixel *) vTo.addr;
2515 if (!appData.monoMode) {
2516 vFrom.addr = (caddr_t) appData.darkSquareColor;
2517 vFrom.size = strlen(appData.darkSquareColor);
2518 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2519 if (vTo.addr == NULL) {
2520 appData.monoMode = True;
2523 darkSquareColor = *(Pixel *) vTo.addr;
2526 if (!appData.monoMode) {
2527 vFrom.addr = (caddr_t) appData.whitePieceColor;
2528 vFrom.size = strlen(appData.whitePieceColor);
2529 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2530 if (vTo.addr == NULL) {
2531 appData.monoMode = True;
2534 whitePieceColor = *(Pixel *) vTo.addr;
2537 if (!appData.monoMode) {
2538 vFrom.addr = (caddr_t) appData.blackPieceColor;
2539 vFrom.size = strlen(appData.blackPieceColor);
2540 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2541 if (vTo.addr == NULL) {
2542 appData.monoMode = True;
2545 blackPieceColor = *(Pixel *) vTo.addr;
2549 if (!appData.monoMode) {
2550 vFrom.addr = (caddr_t) appData.highlightSquareColor;
2551 vFrom.size = strlen(appData.highlightSquareColor);
2552 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2553 if (vTo.addr == NULL) {
2554 appData.monoMode = True;
2557 highlightSquareColor = *(Pixel *) vTo.addr;
2561 if (!appData.monoMode) {
2562 vFrom.addr = (caddr_t) appData.premoveHighlightColor;
2563 vFrom.size = strlen(appData.premoveHighlightColor);
2564 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2565 if (vTo.addr == NULL) {
2566 appData.monoMode = True;
2569 premoveHighlightColor = *(Pixel *) vTo.addr;
2574 fprintf(stderr, _("%s: too few colors available; trying monochrome mode\n"),
2578 if (appData.monoMode && appData.debugMode) {
2579 fprintf(stderr, _("white pixel = 0x%lx, black pixel = 0x%lx\n"),
2580 (unsigned long) XWhitePixel(xDisplay, xScreen),
2581 (unsigned long) XBlackPixel(xDisplay, xScreen));
2584 if (parse_cpair(ColorShout, appData.colorShout) < 0 ||
2585 parse_cpair(ColorSShout, appData.colorSShout) < 0 ||
2586 parse_cpair(ColorChannel1, appData.colorChannel1) < 0 ||
2587 parse_cpair(ColorChannel, appData.colorChannel) < 0 ||
2588 parse_cpair(ColorKibitz, appData.colorKibitz) < 0 ||
2589 parse_cpair(ColorTell, appData.colorTell) < 0 ||
2590 parse_cpair(ColorChallenge, appData.colorChallenge) < 0 ||
2591 parse_cpair(ColorRequest, appData.colorRequest) < 0 ||
2592 parse_cpair(ColorSeek, appData.colorSeek) < 0 ||
2593 parse_cpair(ColorNormal, appData.colorNormal) < 0)
2595 if (appData.colorize) {
2597 _("%s: can't parse color names; disabling colorization\n"),
2600 appData.colorize = FALSE;
2602 textColors[ColorNone].fg = textColors[ColorNone].bg = -1;
2603 textColors[ColorNone].attr = 0;
2605 XtAppAddActions(appContext, boardActions, XtNumber(boardActions));
2611 layoutName = "tinyLayout";
2612 } else if (smallLayout) {
2613 layoutName = "smallLayout";
2615 layoutName = "normalLayout";
2617 /* Outer layoutWidget is there only to provide a name for use in
2618 resources that depend on the layout style */
2620 XtCreateManagedWidget(layoutName, formWidgetClass, shellWidget,
2621 layoutArgs, XtNumber(layoutArgs));
2623 XtCreateManagedWidget("form", formWidgetClass, layoutWidget,
2624 formArgs, XtNumber(formArgs));
2625 XtSetArg(args[0], XtNdefaultDistance, &sep);
2626 XtGetValues(formWidget, args, 1);
2629 widgetList[j++] = menuBarWidget = CreateMenuBar(menuBar);
2630 XtSetArg(args[0], XtNtop, XtChainTop);
2631 XtSetArg(args[1], XtNbottom, XtChainTop);
2632 XtSetValues(menuBarWidget, args, 2);
2634 widgetList[j++] = whiteTimerWidget =
2635 XtCreateWidget("whiteTime", labelWidgetClass,
2636 formWidget, timerArgs, XtNumber(timerArgs));
2637 XtSetArg(args[0], XtNfont, clockFontStruct);
2638 XtSetArg(args[1], XtNtop, XtChainTop);
2639 XtSetArg(args[2], XtNbottom, XtChainTop);
2640 XtSetValues(whiteTimerWidget, args, 3);
2642 widgetList[j++] = blackTimerWidget =
2643 XtCreateWidget("blackTime", labelWidgetClass,
2644 formWidget, timerArgs, XtNumber(timerArgs));
2645 XtSetArg(args[0], XtNfont, clockFontStruct);
2646 XtSetArg(args[1], XtNtop, XtChainTop);
2647 XtSetArg(args[2], XtNbottom, XtChainTop);
2648 XtSetValues(blackTimerWidget, args, 3);
2650 if (appData.titleInWindow) {
2651 widgetList[j++] = titleWidget =
2652 XtCreateWidget("title", labelWidgetClass, formWidget,
2653 titleArgs, XtNumber(titleArgs));
2654 XtSetArg(args[0], XtNtop, XtChainTop);
2655 XtSetArg(args[1], XtNbottom, XtChainTop);
2656 XtSetValues(titleWidget, args, 2);
2659 if (appData.showButtonBar) {
2660 widgetList[j++] = buttonBarWidget = CreateButtonBar(buttonBar);
2661 XtSetArg(args[0], XtNleft, XtChainRight); // [HGM] glue to right window edge
2662 XtSetArg(args[1], XtNright, XtChainRight); // for good run-time sizing
2663 XtSetArg(args[2], XtNtop, XtChainTop);
2664 XtSetArg(args[3], XtNbottom, XtChainTop);
2665 XtSetValues(buttonBarWidget, args, 4);
2668 widgetList[j++] = messageWidget =
2669 XtCreateWidget("message", labelWidgetClass, formWidget,
2670 messageArgs, XtNumber(messageArgs));
2671 XtSetArg(args[0], XtNtop, XtChainTop);
2672 XtSetArg(args[1], XtNbottom, XtChainTop);
2673 XtSetValues(messageWidget, args, 2);
2675 widgetList[j++] = boardWidget =
2676 XtCreateWidget("board", widgetClass, formWidget, boardArgs,
2677 XtNumber(boardArgs));
2679 XtManageChildren(widgetList, j);
2681 timerWidth = (boardWidth - sep) / 2;
2682 XtSetArg(args[0], XtNwidth, timerWidth);
2683 XtSetValues(whiteTimerWidget, args, 1);
2684 XtSetValues(blackTimerWidget, args, 1);
2686 XtSetArg(args[0], XtNbackground, &timerBackgroundPixel);
2687 XtSetArg(args[1], XtNforeground, &timerForegroundPixel);
2688 XtGetValues(whiteTimerWidget, args, 2);
2690 if (appData.showButtonBar) {
2691 XtSetArg(args[0], XtNbackground, &buttonBackgroundPixel);
2692 XtSetArg(args[1], XtNforeground, &buttonForegroundPixel);
2693 XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
2697 * formWidget uses these constraints but they are stored
2701 XtSetArg(args[i], XtNfromHoriz, 0); i++;
2702 XtSetValues(menuBarWidget, args, i);
2703 if (appData.titleInWindow) {
2706 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2707 XtSetValues(whiteTimerWidget, args, i);
2709 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2710 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2711 XtSetValues(blackTimerWidget, args, i);
2713 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2714 XtSetArg(args[i], XtNjustify, XtJustifyLeft); i++;
2715 XtSetValues(titleWidget, args, i);
2717 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2718 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2719 XtSetValues(messageWidget, args, i);
2720 if (appData.showButtonBar) {
2722 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2723 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2724 XtSetValues(buttonBarWidget, args, i);
2728 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2729 XtSetValues(whiteTimerWidget, args, i);
2731 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2732 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2733 XtSetValues(blackTimerWidget, args, i);
2735 XtSetArg(args[i], XtNfromHoriz, menuBarWidget); i++;
2736 XtSetValues(titleWidget, args, i);
2738 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2739 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2740 XtSetValues(messageWidget, args, i);
2741 if (appData.showButtonBar) {
2743 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2744 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2745 XtSetValues(buttonBarWidget, args, i);
2750 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2751 XtSetValues(whiteTimerWidget, args, i);
2753 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2754 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2755 XtSetValues(blackTimerWidget, args, i);
2757 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2758 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2759 XtSetValues(messageWidget, args, i);
2760 if (appData.showButtonBar) {
2762 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2763 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2764 XtSetValues(buttonBarWidget, args, i);
2768 XtSetArg(args[0], XtNfromVert, messageWidget);
2769 XtSetArg(args[1], XtNtop, XtChainTop);
2770 XtSetArg(args[2], XtNbottom, XtChainBottom);
2771 XtSetArg(args[3], XtNleft, XtChainLeft);
2772 XtSetArg(args[4], XtNright, XtChainRight);
2773 XtSetValues(boardWidget, args, 5);
2775 XtRealizeWidget(shellWidget);
2778 * Correct the width of the message and title widgets.
2779 * It is not known why some systems need the extra fudge term.
2780 * The value "2" is probably larger than needed.
2782 XawFormDoLayout(formWidget, False);
2784 #define WIDTH_FUDGE 2
2786 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2787 XtSetArg(args[i], XtNheight, &h); i++;
2788 XtGetValues(messageWidget, args, i);
2789 if (appData.showButtonBar) {
2791 XtSetArg(args[i], XtNwidth, &w); i++;
2792 XtGetValues(buttonBarWidget, args, i);
2793 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2795 w = boardWidth - 2*bor + 1; /*!! +1 compensates for kludge below */
2798 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2799 if (gres != XtGeometryYes && appData.debugMode) {
2800 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2801 programName, gres, w, h, wr, hr);
2804 /* !! Horrible hack to work around bug in XFree86 4.0.1 (X11R6.4.3) */
2805 /* The size used for the child widget in layout lags one resize behind
2806 its true size, so we resize a second time, 1 pixel smaller. Yeech! */
2808 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2809 if (gres != XtGeometryYes && appData.debugMode) {
2810 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2811 programName, gres, w, h, wr, hr);
2814 XtSetArg(args[0], XtNleft, XtChainLeft); // [HGM] glue ends for good run-time sizing
2815 XtSetArg(args[1], XtNright, XtChainRight);
2816 XtSetValues(messageWidget, args, 2);
2818 if (appData.titleInWindow) {
2820 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2821 XtSetArg(args[i], XtNheight, &h); i++;
2822 XtGetValues(titleWidget, args, i);
2824 w = boardWidth - 2*bor;
2826 XtSetArg(args[0], XtNwidth, &w);
2827 XtGetValues(menuBarWidget, args, 1);
2828 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2831 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
2832 if (gres != XtGeometryYes && appData.debugMode) {
2834 _("%s: titleWidget geometry error %d %d %d %d %d\n"),
2835 programName, gres, w, h, wr, hr);
2838 XawFormDoLayout(formWidget, True);
2840 xBoardWindow = XtWindow(boardWidget);
2842 // [HGM] it seems the layout code ends here, but perhaps the color stuff is size independent and would
2843 // not need to go into InitDrawingSizes().
2847 * Create X checkmark bitmap and initialize option menu checks.
2849 ReadBitmap(&xMarkPixmap, "checkmark.bm",
2850 checkmark_bits, checkmark_width, checkmark_height);
2851 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
2852 if (appData.alwaysPromoteToQueen) {
2853 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
2856 if (appData.animateDragging) {
2857 XtSetValues(XtNameToWidget(menuBarWidget,
2858 "menuOptions.Animate Dragging"),
2861 if (appData.animate) {
2862 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
2865 if (appData.autoComment) {
2866 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
2869 if (appData.autoCallFlag) {
2870 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
2873 if (appData.autoFlipView) {
2874 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Auto Flip View"),
2877 if (appData.autoObserve) {
2878 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
2881 if (appData.autoRaiseBoard) {
2882 XtSetValues(XtNameToWidget(menuBarWidget,
2883 "menuOptions.Auto Raise Board"), args, 1);
2885 if (appData.autoSaveGames) {
2886 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
2889 if (appData.saveGameFile[0] != NULLCHAR) {
2890 /* Can't turn this off from menu */
2891 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
2893 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
2897 if (appData.blindfold) {
2898 XtSetValues(XtNameToWidget(menuBarWidget,
2899 "menuOptions.Blindfold"), args, 1);
2901 if (appData.flashCount > 0) {
2902 XtSetValues(XtNameToWidget(menuBarWidget,
2903 "menuOptions.Flash Moves"),
2906 if (appData.getMoveList) {
2907 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
2911 if (appData.highlightDragging) {
2912 XtSetValues(XtNameToWidget(menuBarWidget,
2913 "menuOptions.Highlight Dragging"),
2917 if (appData.highlightLastMove) {
2918 XtSetValues(XtNameToWidget(menuBarWidget,
2919 "menuOptions.Highlight Last Move"),
2922 if (appData.icsAlarm) {
2923 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.ICS Alarm"),
2926 if (appData.ringBellAfterMoves) {
2927 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
2930 if (appData.oldSaveStyle) {
2931 XtSetValues(XtNameToWidget(menuBarWidget,
2932 "menuOptions.Old Save Style"), args, 1);
2934 if (appData.periodicUpdates) {
2935 XtSetValues(XtNameToWidget(menuBarWidget,
2936 "menuOptions.Periodic Updates"), args, 1);
2938 if (appData.ponderNextMove) {
2939 XtSetValues(XtNameToWidget(menuBarWidget,
2940 "menuOptions.Ponder Next Move"), args, 1);
2942 if (appData.popupExitMessage) {
2943 XtSetValues(XtNameToWidget(menuBarWidget,
2944 "menuOptions.Popup Exit Message"), args, 1);
2946 if (appData.popupMoveErrors) {
2947 XtSetValues(XtNameToWidget(menuBarWidget,
2948 "menuOptions.Popup Move Errors"), args, 1);
2950 if (appData.premove) {
2951 XtSetValues(XtNameToWidget(menuBarWidget,
2952 "menuOptions.Premove"), args, 1);
2954 if (appData.quietPlay) {
2955 XtSetValues(XtNameToWidget(menuBarWidget,
2956 "menuOptions.Quiet Play"), args, 1);
2958 if (appData.showCoords) {
2959 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
2962 if (appData.hideThinkingFromHuman) {
2963 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
2966 if (appData.testLegality) {
2967 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Test Legality"),
2974 ReadBitmap(&wIconPixmap, "icon_white.bm",
2975 icon_white_bits, icon_white_width, icon_white_height);
2976 ReadBitmap(&bIconPixmap, "icon_black.bm",
2977 icon_black_bits, icon_black_width, icon_black_height);
2978 iconPixmap = wIconPixmap;
2980 XtSetArg(args[i], XtNiconPixmap, iconPixmap); i++;
2981 XtSetValues(shellWidget, args, i);
2984 * Create a cursor for the board widget.
2986 window_attributes.cursor = XCreateFontCursor(xDisplay, XC_hand2);
2987 XChangeWindowAttributes(xDisplay, xBoardWindow,
2988 CWCursor, &window_attributes);
2991 * Inhibit shell resizing.
2993 shellArgs[0].value = (XtArgVal) &w;
2994 shellArgs[1].value = (XtArgVal) &h;
2995 XtGetValues(shellWidget, shellArgs, 2);
2996 shellArgs[4].value = shellArgs[2].value = w;
2997 shellArgs[5].value = shellArgs[3].value = h;
2998 XtSetValues(shellWidget, &shellArgs[2], 4);
2999 marginW = w - boardWidth; // [HGM] needed to set new shellWidget size when we resize board
3000 marginH = h - boardHeight;
3002 CatchDeleteWindow(shellWidget, "QuitProc");
3007 if (appData.bitmapDirectory[0] != NULLCHAR) {
3014 /* Create regular pieces */
3015 if (!useImages) CreatePieces();
3020 if (appData.animate || appData.animateDragging)
3023 XtAugmentTranslations(formWidget,
3024 XtParseTranslationTable(globalTranslations));
3025 XtAugmentTranslations(boardWidget,
3026 XtParseTranslationTable(boardTranslations));
3027 XtAugmentTranslations(whiteTimerWidget,
3028 XtParseTranslationTable(whiteTranslations));
3029 XtAugmentTranslations(blackTimerWidget,
3030 XtParseTranslationTable(blackTranslations));
3032 /* Why is the following needed on some versions of X instead
3033 * of a translation? */
3034 XtAddEventHandler(boardWidget, ExposureMask, False,
3035 (XtEventHandler) EventProc, NULL);
3040 if (errorExitStatus == -1) {
3041 if (appData.icsActive) {
3042 /* We now wait until we see "login:" from the ICS before
3043 sending the logon script (problems with timestamp otherwise) */
3044 /*ICSInitScript();*/
3045 if (appData.icsInputBox) ICSInputBoxPopUp();
3048 signal(SIGINT, IntSigHandler);
3049 signal(SIGTERM, IntSigHandler);
3050 if (*appData.cmailGameName != NULLCHAR) {
3051 signal(SIGUSR1, CmailSigHandler);
3056 XtAppMainLoop(appContext);
3057 if (appData.debugMode) fclose(debugFP); // [DM] debug
3064 if (appData.icsActive && oldICSInteractionTitle != NULL) {
3065 DisplayIcsInteractionTitle(oldICSInteractionTitle);
3067 unlink(gameCopyFilename);
3068 unlink(gamePasteFilename);
3079 CmailSigHandler(sig)
3085 signal(SIGUSR1, SIG_IGN); /* suspend handler */
3087 /* Activate call-back function CmailSigHandlerCallBack() */
3088 OutputToProcess(cmailPR, (char *)(&dummy), sizeof(int), &error);
3090 signal(SIGUSR1, CmailSigHandler); /* re-activate handler */
3094 CmailSigHandlerCallBack(isr, closure, message, count, error)
3102 ReloadCmailMsgEvent(TRUE); /* Reload cmail msg */
3104 /**** end signal code ****/
3114 f = fopen(appData.icsLogon, "r");
3120 strcat(buf, appData.icsLogon);
3121 f = fopen(buf, "r");
3125 ProcessICSInitScript(f);
3132 EditCommentPopDown();
3143 SetMenuEnables(enab)
3147 if (!menuBarWidget) return;
3148 while (enab->name != NULL) {
3149 w = XtNameToWidget(menuBarWidget, enab->name);
3151 DisplayError(enab->name, 0);
3153 XtSetSensitive(w, enab->value);
3159 Enables icsEnables[] = {
3160 { "menuFile.Mail Move", False },
3161 { "menuFile.Reload CMail Message", False },
3162 { "menuMode.Machine Black", False },
3163 { "menuMode.Machine White", False },
3164 { "menuMode.Analysis Mode", False },
3165 { "menuMode.Analyze File", False },
3166 { "menuMode.Two Machines", False },
3168 { "menuHelp.Hint", False },
3169 { "menuHelp.Book", False },
3170 { "menuStep.Move Now", False },
3171 { "menuOptions.Periodic Updates", False },
3172 { "menuOptions.Hide Thinking", False },
3173 { "menuOptions.Ponder Next Move", False },
3178 Enables ncpEnables[] = {
3179 { "menuFile.Mail Move", False },
3180 { "menuFile.Reload CMail Message", False },
3181 { "menuMode.Machine White", False },
3182 { "menuMode.Machine Black", False },
3183 { "menuMode.Analysis Mode", False },
3184 { "menuMode.Analyze File", False },
3185 { "menuMode.Two Machines", False },
3186 { "menuMode.ICS Client", False },
3187 { "menuMode.ICS Input Box", False },
3188 { "Action", False },
3189 { "menuStep.Revert", False },
3190 { "menuStep.Move Now", False },
3191 { "menuStep.Retract Move", False },
3192 { "menuOptions.Auto Comment", False },
3193 { "menuOptions.Auto Flag", False },
3194 { "menuOptions.Auto Flip View", False },
3195 { "menuOptions.Auto Observe", False },
3196 { "menuOptions.Auto Raise Board", False },
3197 { "menuOptions.Get Move List", False },
3198 { "menuOptions.ICS Alarm", False },
3199 { "menuOptions.Move Sound", False },
3200 { "menuOptions.Quiet Play", False },
3201 { "menuOptions.Hide Thinking", False },
3202 { "menuOptions.Periodic Updates", False },
3203 { "menuOptions.Ponder Next Move", False },
3204 { "menuHelp.Hint", False },
3205 { "menuHelp.Book", False },
3209 Enables gnuEnables[] = {
3210 { "menuMode.ICS Client", False },
3211 { "menuMode.ICS Input Box", False },
3212 { "menuAction.Accept", False },
3213 { "menuAction.Decline", False },
3214 { "menuAction.Rematch", False },
3215 { "menuAction.Adjourn", False },
3216 { "menuAction.Stop Examining", False },
3217 { "menuAction.Stop Observing", False },
3218 { "menuStep.Revert", False },
3219 { "menuOptions.Auto Comment", False },
3220 { "menuOptions.Auto Observe", False },
3221 { "menuOptions.Auto Raise Board", False },
3222 { "menuOptions.Get Move List", False },
3223 { "menuOptions.Premove", False },
3224 { "menuOptions.Quiet Play", False },
3226 /* The next two options rely on SetCmailMode being called *after* */
3227 /* SetGNUMode so that when GNU is being used to give hints these */
3228 /* menu options are still available */
3230 { "menuFile.Mail Move", False },
3231 { "menuFile.Reload CMail Message", False },
3235 Enables cmailEnables[] = {
3237 { "menuAction.Call Flag", False },
3238 { "menuAction.Draw", True },
3239 { "menuAction.Adjourn", False },
3240 { "menuAction.Abort", False },
3241 { "menuAction.Stop Observing", False },
3242 { "menuAction.Stop Examining", False },
3243 { "menuFile.Mail Move", True },
3244 { "menuFile.Reload CMail Message", True },
3248 Enables trainingOnEnables[] = {
3249 { "menuMode.Edit Comment", False },
3250 { "menuMode.Pause", False },
3251 { "menuStep.Forward", False },
3252 { "menuStep.Backward", False },
3253 { "menuStep.Forward to End", False },
3254 { "menuStep.Back to Start", False },
3255 { "menuStep.Move Now", False },
3256 { "menuStep.Truncate Game", False },
3260 Enables trainingOffEnables[] = {
3261 { "menuMode.Edit Comment", True },
3262 { "menuMode.Pause", True },
3263 { "menuStep.Forward", True },
3264 { "menuStep.Backward", True },
3265 { "menuStep.Forward to End", True },
3266 { "menuStep.Back to Start", True },
3267 { "menuStep.Move Now", True },
3268 { "menuStep.Truncate Game", True },
3272 Enables machineThinkingEnables[] = {
3273 { "menuFile.Load Game", False },
3274 { "menuFile.Load Next Game", False },
3275 { "menuFile.Load Previous Game", False },
3276 { "menuFile.Reload Same Game", False },
3277 { "menuFile.Paste Game", False },
3278 { "menuFile.Load Position", False },
3279 { "menuFile.Load Next Position", False },
3280 { "menuFile.Load Previous Position", False },
3281 { "menuFile.Reload Same Position", False },
3282 { "menuFile.Paste Position", False },
3283 { "menuMode.Machine White", False },
3284 { "menuMode.Machine Black", False },
3285 { "menuMode.Two Machines", False },
3286 { "menuStep.Retract Move", False },
3290 Enables userThinkingEnables[] = {
3291 { "menuFile.Load Game", True },
3292 { "menuFile.Load Next Game", True },
3293 { "menuFile.Load Previous Game", True },
3294 { "menuFile.Reload Same Game", True },
3295 { "menuFile.Paste Game", True },
3296 { "menuFile.Load Position", True },
3297 { "menuFile.Load Next Position", True },
3298 { "menuFile.Load Previous Position", True },
3299 { "menuFile.Reload Same Position", True },
3300 { "menuFile.Paste Position", True },
3301 { "menuMode.Machine White", True },
3302 { "menuMode.Machine Black", True },
3303 { "menuMode.Two Machines", True },
3304 { "menuStep.Retract Move", True },
3310 SetMenuEnables(icsEnables);
3313 if (appData.zippyPlay && !appData.noChessProgram) /* [DM] icsEngineAnalyze */
3314 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Analysis Mode"), True);
3321 SetMenuEnables(ncpEnables);
3327 SetMenuEnables(gnuEnables);
3333 SetMenuEnables(cmailEnables);
3339 SetMenuEnables(trainingOnEnables);
3340 if (appData.showButtonBar) {
3341 XtSetSensitive(buttonBarWidget, False);
3347 SetTrainingModeOff()
3349 SetMenuEnables(trainingOffEnables);
3350 if (appData.showButtonBar) {
3351 XtSetSensitive(buttonBarWidget, True);
3356 SetUserThinkingEnables()
3358 if (appData.noChessProgram) return;
3359 SetMenuEnables(userThinkingEnables);
3363 SetMachineThinkingEnables()
3365 if (appData.noChessProgram) return;
3366 SetMenuEnables(machineThinkingEnables);
3368 case MachinePlaysBlack:
3369 case MachinePlaysWhite:
3370 case TwoMachinesPlay:
3371 XtSetSensitive(XtNameToWidget(menuBarWidget,
3372 ModeToWidgetName(gameMode)), True);
3379 #define Abs(n) ((n)<0 ? -(n) : (n))
3382 * Find a font that matches "pattern" that is as close as
3383 * possible to the targetPxlSize. Prefer fonts that are k
3384 * pixels smaller to fonts that are k pixels larger. The
3385 * pattern must be in the X Consortium standard format,
3386 * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".
3387 * The return value should be freed with XtFree when no
3390 char *FindFont(pattern, targetPxlSize)
3394 char **fonts, *p, *best, *scalable, *scalableTail;
3395 int i, j, nfonts, minerr, err, pxlSize;
3398 char **missing_list;
3400 char *def_string, *base_fnt_lst, strInt[3];
3402 XFontStruct **fnt_list;
3404 base_fnt_lst = calloc(1, strlen(pattern) + 3);
3405 sprintf(strInt, "%d", targetPxlSize);
3406 p = strstr(pattern, "--");
3407 strncpy(base_fnt_lst, pattern, p - pattern + 2);
3408 strcat(base_fnt_lst, strInt);
3409 strcat(base_fnt_lst, strchr(p + 2, '-'));
3411 if ((fntSet = XCreateFontSet(xDisplay,
3415 &def_string)) == NULL) {
3417 fprintf(stderr, _("Unable to create font set.\n"));
3421 nfonts = XFontsOfFontSet(fntSet, &fnt_list, &fonts);
3423 fonts = XListFonts(xDisplay, pattern, 999999, &nfonts);
3425 fprintf(stderr, _("%s: no fonts match pattern %s\n"),
3426 programName, pattern);
3434 for (i=0; i<nfonts; i++) {
3437 if (*p != '-') continue;
3439 if (*p == NULLCHAR) break;
3440 if (*p++ == '-') j++;
3442 if (j < 7) continue;
3445 scalable = fonts[i];
3448 err = pxlSize - targetPxlSize;
3449 if (Abs(err) < Abs(minerr) ||
3450 (minerr > 0 && err < 0 && -err == minerr)) {
3456 if (scalable && Abs(minerr) > appData.fontSizeTolerance) {
3457 /* If the error is too big and there is a scalable font,
3458 use the scalable font. */
3459 int headlen = scalableTail - scalable;
3460 p = (char *) XtMalloc(strlen(scalable) + 10);
3461 while (isdigit(*scalableTail)) scalableTail++;
3462 sprintf(p, "%.*s%d%s", headlen, scalable, targetPxlSize, scalableTail);
3464 p = (char *) XtMalloc(strlen(best) + 1);
3467 if (appData.debugMode) {
3468 fprintf(debugFP, _("resolved %s at pixel size %d\n to %s\n"),
3469 pattern, targetPxlSize, p);
3472 if (missing_count > 0)
3473 XFreeStringList(missing_list);
3474 XFreeFontSet(xDisplay, fntSet);
3476 XFreeFontNames(fonts);
3483 XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
3484 | GCBackground | GCFunction | GCPlaneMask;
3485 XGCValues gc_values;
3488 gc_values.plane_mask = AllPlanes;
3489 gc_values.line_width = lineGap;
3490 gc_values.line_style = LineSolid;
3491 gc_values.function = GXcopy;
3493 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3494 gc_values.background = XBlackPixel(xDisplay, xScreen);
3495 lineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3497 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3498 gc_values.background = XWhitePixel(xDisplay, xScreen);
3499 coordGC = XtGetGC(shellWidget, value_mask, &gc_values);
3500 XSetFont(xDisplay, coordGC, coordFontID);
3502 // [HGM] make font for holdings counts (white on black0
3503 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3504 gc_values.background = XBlackPixel(xDisplay, xScreen);
3505 countGC = XtGetGC(shellWidget, value_mask, &gc_values);
3506 XSetFont(xDisplay, countGC, countFontID);
3508 if (appData.monoMode) {
3509 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3510 gc_values.background = XWhitePixel(xDisplay, xScreen);
3511 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3513 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3514 gc_values.background = XBlackPixel(xDisplay, xScreen);
3515 lightSquareGC = wbPieceGC
3516 = XtGetGC(shellWidget, value_mask, &gc_values);
3518 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3519 gc_values.background = XWhitePixel(xDisplay, xScreen);
3520 darkSquareGC = bwPieceGC
3521 = XtGetGC(shellWidget, value_mask, &gc_values);
3523 if (DefaultDepth(xDisplay, xScreen) == 1) {
3524 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
3525 gc_values.function = GXcopyInverted;
3526 copyInvertedGC = XtGetGC(shellWidget, value_mask, &gc_values);
3527 gc_values.function = GXcopy;
3528 if (XBlackPixel(xDisplay, xScreen) == 1) {
3529 bwPieceGC = darkSquareGC;
3530 wbPieceGC = copyInvertedGC;
3532 bwPieceGC = copyInvertedGC;
3533 wbPieceGC = lightSquareGC;
3537 gc_values.foreground = highlightSquareColor;
3538 gc_values.background = highlightSquareColor;
3539 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3541 gc_values.foreground = premoveHighlightColor;
3542 gc_values.background = premoveHighlightColor;
3543 prelineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3545 gc_values.foreground = lightSquareColor;
3546 gc_values.background = darkSquareColor;
3547 lightSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3549 gc_values.foreground = darkSquareColor;
3550 gc_values.background = lightSquareColor;
3551 darkSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3553 gc_values.foreground = jailSquareColor;
3554 gc_values.background = jailSquareColor;
3555 jailSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3557 gc_values.foreground = whitePieceColor;
3558 gc_values.background = darkSquareColor;
3559 wdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3561 gc_values.foreground = whitePieceColor;
3562 gc_values.background = lightSquareColor;
3563 wlPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3565 gc_values.foreground = whitePieceColor;
3566 gc_values.background = jailSquareColor;
3567 wjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3569 gc_values.foreground = blackPieceColor;
3570 gc_values.background = darkSquareColor;
3571 bdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3573 gc_values.foreground = blackPieceColor;
3574 gc_values.background = lightSquareColor;
3575 blPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3577 gc_values.foreground = blackPieceColor;
3578 gc_values.background = jailSquareColor;
3579 bjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3583 void loadXIM(xim, xmask, filename, dest, mask)
3596 fp = fopen(filename, "rb");
3598 fprintf(stderr, _("%s: error loading XIM!\n"), programName);
3605 for (y=0; y<h; ++y) {
3606 for (x=0; x<h; ++x) {
3611 XPutPixel(xim, x, y, blackPieceColor);
3613 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3616 XPutPixel(xim, x, y, darkSquareColor);
3618 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3621 XPutPixel(xim, x, y, whitePieceColor);
3623 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3626 XPutPixel(xim, x, y, lightSquareColor);
3628 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3634 /* create Pixmap of piece */
3635 *dest = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3637 XPutImage(xDisplay, *dest, lightSquareGC, xim,
3640 /* create Pixmap of clipmask
3641 Note: We assume the white/black pieces have the same
3642 outline, so we make only 6 masks. This is okay
3643 since the XPM clipmask routines do the same. */
3645 temp = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3647 XPutImage(xDisplay, temp, lightSquareGC, xmask,
3650 /* now create the 1-bit version */
3651 *mask = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3654 values.foreground = 1;
3655 values.background = 0;
3657 /* Don't use XtGetGC, not read only */
3658 maskGC = XCreateGC(xDisplay, *mask,
3659 GCForeground | GCBackground, &values);
3660 XCopyPlane(xDisplay, temp, *mask, maskGC,
3661 0, 0, squareSize, squareSize, 0, 0, 1);
3662 XFreePixmap(xDisplay, temp);
3666 void CreateXIMPieces()
3671 static char *ximkind[] = { "ll", "ld", "dl", "dd" };
3676 /* The XSynchronize calls were copied from CreatePieces.
3677 Not sure if needed, but can't hurt */
3678 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3681 /* temp needed by loadXIM() */
3682 ximtemp = XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3683 0, 0, ss, ss, AllPlanes, XYPixmap);
3685 if (strlen(appData.pixmapDirectory) == 0) {
3689 if (appData.monoMode) {
3690 DisplayFatalError(_("XIM pieces cannot be used in monochrome mode"),
3694 fprintf(stderr, _("\nLoading XIMs...\n"));
3696 for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
3697 fprintf(stderr, "%d", piece+1);
3698 for (kind=0; kind<4; kind++) {
3699 fprintf(stderr, ".");
3700 sprintf(buf, "%s/%c%s%u.xim",
3701 ExpandPathName(appData.pixmapDirectory),
3702 ToLower(PieceToChar((ChessSquare)piece)),
3704 ximPieceBitmap[kind][piece] =
3705 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3706 0, 0, ss, ss, AllPlanes, XYPixmap);
3707 if (appData.debugMode)
3708 fprintf(stderr, _("(File:%s:) "), buf);
3709 loadXIM(ximPieceBitmap[kind][piece],
3711 &(xpmPieceBitmap[kind][piece]),
3712 &(ximMaskPm[piece%(int)BlackPawn]));
3714 fprintf(stderr," ");
3716 /* Load light and dark squares */
3717 /* If the LSQ and DSQ pieces don't exist, we will
3718 draw them with solid squares. */
3719 sprintf(buf, "%s/lsq%u.xim", ExpandPathName(appData.pixmapDirectory), ss);
3720 if (access(buf, 0) != 0) {
3724 fprintf(stderr, _("light square "));
3726 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3727 0, 0, ss, ss, AllPlanes, XYPixmap);
3728 if (appData.debugMode)
3729 fprintf(stderr, _("(File:%s:) "), buf);
3731 loadXIM(ximLightSquare, NULL, buf, &xpmLightSquare, NULL);
3732 fprintf(stderr, _("dark square "));
3733 sprintf(buf, "%s/dsq%u.xim",
3734 ExpandPathName(appData.pixmapDirectory), ss);
3735 if (appData.debugMode)
3736 fprintf(stderr, _("(File:%s:) "), buf);
3738 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3739 0, 0, ss, ss, AllPlanes, XYPixmap);
3740 loadXIM(ximDarkSquare, NULL, buf, &xpmDarkSquare, NULL);
3741 xpmJailSquare = xpmLightSquare;
3743 fprintf(stderr, _("Done.\n"));
3745 XSynchronize(xDisplay, False); /* Work-around for xlib/xt buffering bug */
3749 void CreateXPMPieces()
3753 u_int ss = squareSize;
3755 static char *xpmkind[] = { "ll", "ld", "dl", "dd" };
3756 XpmColorSymbol symbols[4];
3759 /* Apparently some versions of Xpm don't define XpmFormat at all --tpm */
3760 if (appData.debugMode) {
3761 fprintf(stderr, "XPM Library Version: %d.%d%c\n",
3762 XpmFormat, XpmVersion, (char)('a' + XpmRevision - 1));
3766 /* The XSynchronize calls were copied from CreatePieces.
3767 Not sure if needed, but can't hurt */
3768 XSynchronize(xDisplay, True); /* Work-around for xlib/xt buffering bug */
3770 /* Setup translations so piece colors match square colors */
3771 symbols[0].name = "light_piece";
3772 symbols[0].value = appData.whitePieceColor;
3773 symbols[1].name = "dark_piece";
3774 symbols[1].value = appData.blackPieceColor;
3775 symbols[2].name = "light_square";
3776 symbols[2].value = appData.lightSquareColor;
3777 symbols[3].name = "dark_square";
3778 symbols[3].value = appData.darkSquareColor;
3780 attr.valuemask = XpmColorSymbols;
3781 attr.colorsymbols = symbols;
3782 attr.numsymbols = 4;
3784 if (appData.monoMode) {
3785 DisplayFatalError(_("XPM pieces cannot be used in monochrome mode"),
3789 if (strlen(appData.pixmapDirectory) == 0) {
3790 XpmPieces* pieces = builtInXpms;
3793 while (pieces->size != squareSize && pieces->size) pieces++;
3794 if (!pieces->size) {
3795 fprintf(stderr, _("No builtin XPM pieces of size %d\n"), squareSize);
3798 for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
3799 for (kind=0; kind<4; kind++) {
3801 if ((r=XpmCreatePixmapFromData(xDisplay, xBoardWindow,
3802 pieces->xpm[piece][kind],
3803 &(xpmPieceBitmap[kind][piece]),
3804 NULL, &attr)) != 0) {
3805 fprintf(stderr, _("Error %d loading XPM image \"%s\"\n"),
3812 xpmJailSquare = xpmLightSquare;
3816 fprintf(stderr, _("\nLoading XPMs...\n"));
3819 for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
3820 fprintf(stderr, "%d ", piece+1);
3821 for (kind=0; kind<4; kind++) {
3822 sprintf(buf, "%s/%c%s%u.xpm",
3823 ExpandPathName(appData.pixmapDirectory),
3824 ToLower(PieceToChar((ChessSquare)piece)),
3826 if (appData.debugMode) {
3827 fprintf(stderr, _("(File:%s:) "), buf);
3829 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3830 &(xpmPieceBitmap[kind][piece]),
3831 NULL, &attr)) != 0) {
3832 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"),
3838 /* Load light and dark squares */
3839 /* If the LSQ and DSQ pieces don't exist, we will
3840 draw them with solid squares. */
3841 fprintf(stderr, _("light square "));
3842 sprintf(buf, "%s/lsq%u.xpm", ExpandPathName(appData.pixmapDirectory), ss);
3843 if (access(buf, 0) != 0) {
3847 if (appData.debugMode)
3848 fprintf(stderr, _("(File:%s:) "), buf);
3850 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3851 &xpmLightSquare, NULL, &attr)) != 0) {
3852 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
3855 fprintf(stderr, _("dark square "));
3856 sprintf(buf, "%s/dsq%u.xpm",
3857 ExpandPathName(appData.pixmapDirectory), ss);
3858 if (appData.debugMode) {
3859 fprintf(stderr, _("(File:%s:) "), buf);
3861 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3862 &xpmDarkSquare, NULL, &attr)) != 0) {
3863 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
3867 xpmJailSquare = xpmLightSquare;
3868 fprintf(stderr, _("Done.\n"));
3870 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3873 #endif /* HAVE_LIBXPM */
3876 /* No built-in bitmaps */
3881 u_int ss = squareSize;
3883 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3886 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
3887 for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
3888 sprintf(buf, "%c%u%c.bm", ToLower(PieceToChar((ChessSquare)piece)),
3889 ss, kind == SOLID ? 's' : 'o');
3890 ReadBitmap(&pieceBitmap[kind][piece], buf, NULL, ss, ss);
3894 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3898 /* With built-in bitmaps */
3901 BuiltInBits* bib = builtInBits;
3904 u_int ss = squareSize;
3906 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3909 while (bib->squareSize != ss && bib->squareSize != 0) bib++;
3911 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
3912 for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
3913 sprintf(buf, "%c%u%c.bm", ToLower(PieceToChar((ChessSquare)piece)),
3914 ss, kind == SOLID ? 's' : 'o');
3915 ReadBitmap(&pieceBitmap[kind][piece], buf,
3916 bib->bits[kind][piece], ss, ss);
3920 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3925 void ReadBitmap(pm, name, bits, wreq, hreq)
3928 unsigned char bits[];
3934 char msg[MSG_SIZ], fullname[MSG_SIZ];
3936 if (*appData.bitmapDirectory != NULLCHAR) {
3937 strcpy(fullname, appData.bitmapDirectory);
3938 strcat(fullname, "/");
3939 strcat(fullname, name);
3940 errcode = XReadBitmapFile(xDisplay, xBoardWindow, fullname,
3941 &w, &h, pm, &x_hot, &y_hot);
3942 if (errcode != BitmapSuccess) {
3944 case BitmapOpenFailed:
3945 sprintf(msg, _("Can't open bitmap file %s"), fullname);
3947 case BitmapFileInvalid:
3948 sprintf(msg, _("Invalid bitmap in file %s"), fullname);
3950 case BitmapNoMemory:
3951 sprintf(msg, _("Ran out of memory reading bitmap file %s"),
3955 sprintf(msg, _("Unknown XReadBitmapFile error %d on file %s"),
3959 fprintf(stderr, _("%s: %s...using built-in\n"),
3961 } else if (w != wreq || h != hreq) {
3963 _("%s: Bitmap %s is %dx%d, not %dx%d...using built-in\n"),
3964 programName, fullname, w, h, wreq, hreq);
3971 fprintf(stderr, _("%s: No built-in bitmap for %s; giving up\n"),
3975 ; // [HGM] bitmaps: make it non-fatal if we have no bitmap;
3977 *pm = XCreateBitmapFromData(xDisplay, xBoardWindow, (char *) bits,
3986 if (lineGap == 0) return;
3988 /* [HR] Split this into 2 loops for non-square boards. */
3990 for (i = 0; i < BOARD_HEIGHT + 1; i++) {
3991 gridSegments[i].x1 = 0;
3992 gridSegments[i].x2 =
3993 lineGap + BOARD_WIDTH * (squareSize + lineGap);
3994 gridSegments[i].y1 = gridSegments[i].y2
3995 = lineGap / 2 + (i * (squareSize + lineGap));
3998 for (j = 0; j < BOARD_WIDTH + 1; j++) {
3999 gridSegments[j + i].y1 = 0;
4000 gridSegments[j + i].y2 =
4001 lineGap + BOARD_HEIGHT * (squareSize + lineGap);
4002 gridSegments[j + i].x1 = gridSegments[j + i].x2
4003 = lineGap / 2 + (j * (squareSize + lineGap));
4007 static void MenuBarSelect(w, addr, index)
4012 XtActionProc proc = (XtActionProc) addr;
4014 (proc)(NULL, NULL, NULL, NULL);
4017 void CreateMenuBarPopup(parent, name, mb)
4027 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
4030 XtSetArg(args[j], XtNleftMargin, 20); j++;
4031 XtSetArg(args[j], XtNrightMargin, 20); j++;
4033 while (mi->string != NULL) {
4034 if (strcmp(mi->string, "----") == 0) {
4035 entry = XtCreateManagedWidget(mi->string, smeLineObjectClass,
4038 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string)));
4039 entry = XtCreateManagedWidget(mi->string, smeBSBObjectClass,
4041 XtAddCallback(entry, XtNcallback,
4042 (XtCallbackProc) MenuBarSelect,
4043 (caddr_t) mi->proc);
4049 Widget CreateMenuBar(mb)
4053 Widget anchor, menuBar;
4055 char menuName[MSG_SIZ];
4058 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
4059 XtSetArg(args[j], XtNvSpace, 0); j++;
4060 XtSetArg(args[j], XtNborderWidth, 0); j++;
4061 menuBar = XtCreateWidget("menuBar", boxWidgetClass,
4062 formWidget, args, j);
4064 while (mb->name != NULL) {
4065 strcpy(menuName, "menu");
4066 strcat(menuName, mb->name);
4068 XtSetArg(args[j], XtNmenuName, XtNewString(menuName)); j++;
4071 shortName[0] = _(mb->name)[0];
4072 shortName[1] = NULLCHAR;
4073 XtSetArg(args[j], XtNlabel, XtNewString(shortName)); j++;
4076 XtSetArg(args[j], XtNlabel, XtNewString(_(mb->name))); j++;
4079 XtSetArg(args[j], XtNborderWidth, 0); j++;
4080 anchor = XtCreateManagedWidget(mb->name, menuButtonWidgetClass,
4082 CreateMenuBarPopup(menuBar, menuName, mb);
4088 Widget CreateButtonBar(mi)
4092 Widget button, buttonBar;
4096 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
4098 XtSetArg(args[j], XtNhSpace, 0); j++;
4100 XtSetArg(args[j], XtNborderWidth, 0); j++;
4101 XtSetArg(args[j], XtNvSpace, 0); j++;
4102 buttonBar = XtCreateWidget("buttonBar", boxWidgetClass,
4103 formWidget, args, j);
4105 while (mi->string != NULL) {
4108 XtSetArg(args[j], XtNinternalWidth, 2); j++;
4109 XtSetArg(args[j], XtNborderWidth, 0); j++;
4111 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string))); j++;
4112 button = XtCreateManagedWidget(mi->string, commandWidgetClass,
4113 buttonBar, args, j);
4114 XtAddCallback(button, XtNcallback,
4115 (XtCallbackProc) MenuBarSelect,
4116 (caddr_t) mi->proc);
4123 CreatePieceMenu(name, color)
4130 ChessSquare selection;
4132 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
4133 boardWidget, args, 0);
4135 for (i = 0; i < PIECE_MENU_SIZE; i++) {
4136 String item = pieceMenuStrings[color][i];
4138 if (strcmp(item, "----") == 0) {
4139 entry = XtCreateManagedWidget(item, smeLineObjectClass,
4142 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
4143 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
4145 selection = pieceMenuTranslation[color][i];
4146 XtAddCallback(entry, XtNcallback,
4147 (XtCallbackProc) PieceMenuSelect,
4148 (caddr_t) selection);
4149 if (selection == WhitePawn || selection == BlackPawn) {
4150 XtSetArg(args[0], XtNpopupOnEntry, entry);
4151 XtSetValues(menu, args, 1);
4164 ChessSquare selection;
4166 whitePieceMenu = CreatePieceMenu("menuW", 0);
4167 blackPieceMenu = CreatePieceMenu("menuB", 1);
4169 XtRegisterGrabAction(PieceMenuPopup, True,
4170 (unsigned)(ButtonPressMask|ButtonReleaseMask),
4171 GrabModeAsync, GrabModeAsync);
4173 XtSetArg(args[0], XtNlabel, _("Drop"));
4174 dropMenu = XtCreatePopupShell("menuD", simpleMenuWidgetClass,
4175 boardWidget, args, 1);
4176 for (i = 0; i < DROP_MENU_SIZE; i++) {
4177 String item = dropMenuStrings[i];
4179 if (strcmp(item, "----") == 0) {
4180 entry = XtCreateManagedWidget(item, smeLineObjectClass,
4183 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
4184 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
4186 selection = dropMenuTranslation[i];
4187 XtAddCallback(entry, XtNcallback,
4188 (XtCallbackProc) DropMenuSelect,
4189 (caddr_t) selection);
4194 void SetupDropMenu()
4202 for (i=0; i<sizeof(dmEnables)/sizeof(DropMenuEnables); i++) {
4203 entry = XtNameToWidget(dropMenu, dmEnables[i].widget);
4204 p = strchr(gameMode == IcsPlayingWhite ? white_holding : black_holding,
4205 dmEnables[i].piece);
4206 XtSetSensitive(entry, p != NULL || !appData.testLegality
4207 /*!!temp:*/ || (gameInfo.variant == VariantCrazyhouse
4208 && !appData.icsActive));
4210 while (p && *p++ == dmEnables[i].piece) count++;
4211 sprintf(label, "%s %d", dmEnables[i].widget, count);
4213 XtSetArg(args[j], XtNlabel, label); j++;
4214 XtSetValues(entry, args, j);
4218 void PieceMenuPopup(w, event, params, num_params)
4222 Cardinal *num_params;
4225 if (event->type != ButtonPress) return;
4226 if (errorUp) ErrorPopDown();
4230 whichMenu = params[0];
4232 case IcsPlayingWhite:
4233 case IcsPlayingBlack:
4235 case MachinePlaysWhite:
4236 case MachinePlaysBlack:
4237 if (appData.testLegality &&
4238 gameInfo.variant != VariantBughouse &&
4239 gameInfo.variant != VariantCrazyhouse) return;
4241 whichMenu = "menuD";
4247 if (((pmFromX = EventToSquare(event->xbutton.x, BOARD_WIDTH)) < 0) ||
4248 ((pmFromY = EventToSquare(event->xbutton.y, BOARD_HEIGHT)) < 0)) {
4249 pmFromX = pmFromY = -1;
4253 pmFromX = BOARD_WIDTH - 1 - pmFromX;
4255 pmFromY = BOARD_HEIGHT - 1 - pmFromY;
4257 XtPopupSpringLoaded(XtNameToWidget(boardWidget, whichMenu));
4260 static void PieceMenuSelect(w, piece, junk)
4265 if (pmFromX < 0 || pmFromY < 0) return;
4266 EditPositionMenuEvent(piece, pmFromX, pmFromY);
4269 static void DropMenuSelect(w, piece, junk)
4274 if (pmFromX < 0 || pmFromY < 0) return;
4275 DropMenuEvent(piece, pmFromX, pmFromY);
4278 void WhiteClock(w, event, prms, nprms)
4284 if (gameMode == EditPosition || gameMode == IcsExamining) {
4285 SetWhiteToPlayEvent();
4286 } else if (gameMode == IcsPlayingBlack || gameMode == MachinePlaysWhite) {
4291 void BlackClock(w, event, prms, nprms)
4297 if (gameMode == EditPosition || gameMode == IcsExamining) {
4298 SetBlackToPlayEvent();
4299 } else if (gameMode == IcsPlayingWhite || gameMode == MachinePlaysBlack) {
4306 * If the user selects on a border boundary, return -1; if off the board,
4307 * return -2. Otherwise map the event coordinate to the square.
4309 int EventToSquare(x, limit)
4317 if ((x % (squareSize + lineGap)) >= squareSize)
4319 x /= (squareSize + lineGap);
4325 static void do_flash_delay(msec)
4331 static void drawHighlight(file, rank, gc)
4337 if (lineGap == 0 || appData.blindfold) return;
4340 x = lineGap/2 + ((BOARD_WIDTH-1)-file) *
4341 (squareSize + lineGap);
4342 y = lineGap/2 + rank * (squareSize + lineGap);
4344 x = lineGap/2 + file * (squareSize + lineGap);
4345 y = lineGap/2 + ((BOARD_HEIGHT-1)-rank) *
4346 (squareSize + lineGap);
4349 XDrawRectangle(xDisplay, xBoardWindow, gc, x, y,
4350 squareSize+lineGap, squareSize+lineGap);
4353 int hi1X = -1, hi1Y = -1, hi2X = -1, hi2Y = -1;
4354 int pm1X = -1, pm1Y = -1, pm2X = -1, pm2Y = -1;
4357 SetHighlights(fromX, fromY, toX, toY)
4358 int fromX, fromY, toX, toY;
4360 if (hi1X != fromX || hi1Y != fromY) {
4361 if (hi1X >= 0 && hi1Y >= 0) {
4362 drawHighlight(hi1X, hi1Y, lineGC);
4364 if (fromX >= 0 && fromY >= 0) {
4365 drawHighlight(fromX, fromY, highlineGC);
4368 if (hi2X != toX || hi2Y != toY) {
4369 if (hi2X >= 0 && hi2Y >= 0) {
4370 drawHighlight(hi2X, hi2Y, lineGC);
4372 if (toX >= 0 && toY >= 0) {
4373 drawHighlight(toX, toY, highlineGC);
4385 SetHighlights(-1, -1, -1, -1);
4390 SetPremoveHighlights(fromX, fromY, toX, toY)
4391 int fromX, fromY, toX, toY;
4393 if (pm1X != fromX || pm1Y != fromY) {
4394 if (pm1X >= 0 && pm1Y >= 0) {
4395 drawHighlight(pm1X, pm1Y, lineGC);
4397 if (fromX >= 0 && fromY >= 0) {
4398 drawHighlight(fromX, fromY, prelineGC);
4401 if (pm2X != toX || pm2Y != toY) {
4402 if (pm2X >= 0 && pm2Y >= 0) {
4403 drawHighlight(pm2X, pm2Y, lineGC);
4405 if (toX >= 0 && toY >= 0) {
4406 drawHighlight(toX, toY, prelineGC);
4416 ClearPremoveHighlights()
4418 SetPremoveHighlights(-1, -1, -1, -1);
4421 static void BlankSquare(x, y, color, piece, dest)
4426 if (useImages && useImageSqs) {
4430 pm = xpmLightSquare;
4435 case 2: /* neutral */
4440 XCopyArea(xDisplay, pm, dest, wlPieceGC, 0, 0,
4441 squareSize, squareSize, x, y);
4451 case 2: /* neutral */
4456 XFillRectangle(xDisplay, dest, gc, x, y, squareSize, squareSize);
4461 I split out the routines to draw a piece so that I could
4462 make a generic flash routine.
4464 static void monoDrawPiece_1bit(piece, square_color, x, y, dest)
4466 int square_color, x, y;
4469 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
4470 switch (square_color) {
4472 case 2: /* neutral */
4474 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
4475 ? *pieceToOutline(piece)
4476 : *pieceToSolid(piece),
4477 dest, bwPieceGC, 0, 0,
4478 squareSize, squareSize, x, y);
4481 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
4482 ? *pieceToSolid(piece)
4483 : *pieceToOutline(piece),
4484 dest, wbPieceGC, 0, 0,
4485 squareSize, squareSize, x, y);
4490 static void monoDrawPiece(piece, square_color, x, y, dest)
4492 int square_color, x, y;
4495 switch (square_color) {
4497 case 2: /* neutral */
4499 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
4500 ? *pieceToOutline(piece)
4501 : *pieceToSolid(piece),
4502 dest, bwPieceGC, 0, 0,
4503 squareSize, squareSize, x, y, 1);
4506 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
4507 ? *pieceToSolid(piece)
4508 : *pieceToOutline(piece),
4509 dest, wbPieceGC, 0, 0,
4510 squareSize, squareSize, x, y, 1);
4515 static void colorDrawPiece(piece, square_color, x, y, dest)
4517 int square_color, x, y;
4520 if(pieceToSolid(piece) == NULL) return; // [HGM] bitmaps: make it non-fatal if we have no bitmap;
4521 switch (square_color) {
4523 XCopyPlane(xDisplay, *pieceToSolid(piece),
4524 dest, (int) piece < (int) BlackPawn
4525 ? wlPieceGC : blPieceGC, 0, 0,
4526 squareSize, squareSize, x, y, 1);
4529 XCopyPlane(xDisplay, *pieceToSolid(piece),
4530 dest, (int) piece < (int) BlackPawn
4531 ? wdPieceGC : bdPieceGC, 0, 0,
4532 squareSize, squareSize, x, y, 1);
4534 case 2: /* neutral */
4536 XCopyPlane(xDisplay, *pieceToSolid(piece),
4537 dest, (int) piece < (int) BlackPawn
4538 ? wjPieceGC : bjPieceGC, 0, 0,
4539 squareSize, squareSize, x, y, 1);
4544 static void colorDrawPieceImage(piece, square_color, x, y, dest)
4546 int square_color, x, y;
4551 switch (square_color) {
4553 case 2: /* neutral */
4555 if ((int)piece < (int) BlackPawn) {
4563 if ((int)piece < (int) BlackPawn) {
4571 XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
4572 dest, wlPieceGC, 0, 0,
4573 squareSize, squareSize, x, y);
4576 typedef void (*DrawFunc)();
4578 DrawFunc ChooseDrawFunc()
4580 if (appData.monoMode) {
4581 if (DefaultDepth(xDisplay, xScreen) == 1) {
4582 return monoDrawPiece_1bit;
4584 return monoDrawPiece;
4588 return colorDrawPieceImage;
4590 return colorDrawPiece;
4594 /* [HR] determine square color depending on chess variant. */
4595 static int SquareColor(row, column)
4600 if (gameInfo.variant == VariantXiangqi) {
4601 if (column >= 3 && column <= 5 && row >= 0 && row <= 2) {
4603 } else if (column >= 3 && column <= 5 && row >= 7 && row <= 9) {
4605 } else if (row <= 4) {
4611 square_color = ((column + row) % 2) == 1;
4614 /* [hgm] holdings: next line makes all holdings squares light */
4615 if(column < BOARD_LEFT || column >= BOARD_RGHT) square_color = 1;
4617 return square_color;
4620 void DrawSquare(row, column, piece, do_flash)
4621 int row, column, do_flash;
4624 int square_color, x, y, direction, font_ascent, font_descent;
4627 XCharStruct overall;
4631 if(gameInfo.variant == VariantShogi) { // [HGM] shogi: in shogi Q is used for Lance
4632 if(piece == WhiteQueen) piece = WhiteLance; else
4633 if(piece == BlackQueen) piece = BlackLance;
4636 else if(gameInfo.variant == VariantGothic) { // [HGM] shogi: in Gothic Chancelor has alternative look
4637 if(piece == WhiteMarshall) piece = WhiteSilver; else
4638 if(piece == BlackMarshall) piece = BlackSilver;
4642 /* Calculate delay in milliseconds (2-delays per complete flash) */
4643 flash_delay = 500 / appData.flashRate;
4646 x = lineGap + ((BOARD_WIDTH-1)-column) *
4647 (squareSize + lineGap);
4648 y = lineGap + row * (squareSize + lineGap);
4650 x = lineGap + column * (squareSize + lineGap);
4651 y = lineGap + ((BOARD_HEIGHT-1)-row) *
4652 (squareSize + lineGap);
4655 square_color = SquareColor(row, column);
4657 if ( // [HGM] holdings: blank out area between board and holdings
4658 column == BOARD_LEFT-1 || column == BOARD_RGHT
4659 || (column == BOARD_LEFT-2 && row < BOARD_HEIGHT-gameInfo.holdingsSize)
4660 || (column == BOARD_RGHT+1 && row >= gameInfo.holdingsSize) ) {
4661 BlankSquare(x, y, 2, EmptySquare, xBoardWindow);
4663 // [HGM] print piece counts next to holdings
4664 string[1] = NULLCHAR;
4665 if (column == (flipView ? BOARD_LEFT-1 : BOARD_RGHT) && piece > 1 ) {
4666 string[0] = '0' + piece;
4667 XTextExtents(countFontStruct, string, 1, &direction,
4668 &font_ascent, &font_descent, &overall);
4669 if (appData.monoMode) {
4670 XDrawImageString(xDisplay, xBoardWindow, countGC,
4671 x + squareSize - overall.width - 2,
4672 y + font_ascent + 1, string, 1);
4674 XDrawString(xDisplay, xBoardWindow, countGC,
4675 x + squareSize - overall.width - 2,
4676 y + font_ascent + 1, string, 1);
4679 if (column == (flipView ? BOARD_RGHT : BOARD_LEFT-1) && piece > 1) {
4680 string[0] = '0' + piece;
4681 XTextExtents(countFontStruct, string, 1, &direction,
4682 &font_ascent, &font_descent, &overall);
4683 if (appData.monoMode) {
4684 XDrawImageString(xDisplay, xBoardWindow, countGC,
4685 x + 2, y + font_ascent + 1, string, 1);
4687 XDrawString(xDisplay, xBoardWindow, countGC,
4688 x + 2, y + font_ascent + 1, string, 1);
4692 if (piece == EmptySquare || appData.blindfold) {
4693 BlankSquare(x, y, square_color, piece, xBoardWindow);
4695 drawfunc = ChooseDrawFunc();
4696 if (do_flash && appData.flashCount > 0) {
4697 for (i=0; i<appData.flashCount; ++i) {
4699 drawfunc(piece, square_color, x, y, xBoardWindow);
4700 XSync(xDisplay, False);
4701 do_flash_delay(flash_delay);
4703 BlankSquare(x, y, square_color, piece, xBoardWindow);
4704 XSync(xDisplay, False);
4705 do_flash_delay(flash_delay);
4708 drawfunc(piece, square_color, x, y, xBoardWindow);
4712 string[1] = NULLCHAR;
4713 if (appData.showCoords && row == (flipView ? BOARD_HEIGHT-1 : 0)
4714 && column >= BOARD_LEFT && column < BOARD_RGHT) {
4715 string[0] = 'a' + column - BOARD_LEFT;
4716 XTextExtents(coordFontStruct, string, 1, &direction,
4717 &font_ascent, &font_descent, &overall);
4718 if (appData.monoMode) {
4719 XDrawImageString(xDisplay, xBoardWindow, coordGC,
4720 x + squareSize - overall.width - 2,
4721 y + squareSize - font_descent - 1, string, 1);
4723 XDrawString(xDisplay, xBoardWindow, coordGC,
4724 x + squareSize - overall.width - 2,
4725 y + squareSize - font_descent - 1, string, 1);
4728 if (appData.showCoords && column == (flipView ? BOARD_RGHT-1 : BOARD_LEFT)) {
4729 string[0] = ONE + row;
4730 XTextExtents(coordFontStruct, string, 1, &direction,
4731 &font_ascent, &font_descent, &overall);
4732 if (appData.monoMode) {
4733 XDrawImageString(xDisplay, xBoardWindow, coordGC,
4734 x + 2, y + font_ascent + 1, string, 1);
4736 XDrawString(xDisplay, xBoardWindow, coordGC,
4737 x + 2, y + font_ascent + 1, string, 1);
4743 /* Why is this needed on some versions of X? */
4744 void EventProc(widget, unused, event)
4749 if (!XtIsRealized(widget))
4752 switch (event->type) {
4754 if (event->xexpose.count > 0) return; /* no clipping is done */
4755 XDrawPosition(widget, True, NULL);
4763 void DrawPosition(fullRedraw, board)
4764 /*Boolean*/int fullRedraw;
4767 XDrawPosition(boardWidget, fullRedraw, board);
4770 /* Returns 1 if there are "too many" differences between b1 and b2
4771 (i.e. more than 1 move was made) */
4772 static int too_many_diffs(b1, b2)
4778 for (i=0; i<BOARD_HEIGHT; ++i) {
4779 for (j=0; j<BOARD_WIDTH; ++j) {
4780 if (b1[i][j] != b2[i][j]) {
4781 if (++c > 4) /* Castling causes 4 diffs */
4790 /* Matrix describing castling maneuvers */
4791 /* Row, ColRookFrom, ColKingFrom, ColRookTo, ColKingTo */
4792 static int castling_matrix[4][5] = {
4793 { 0, 0, 4, 3, 2 }, /* 0-0-0, white */
4794 { 0, 7, 4, 5, 6 }, /* 0-0, white */
4795 { 7, 0, 4, 3, 2 }, /* 0-0-0, black */
4796 { 7, 7, 4, 5, 6 } /* 0-0, black */
4799 /* Checks whether castling occurred. If it did, *rrow and *rcol
4800 are set to the destination (row,col) of the rook that moved.
4802 Returns 1 if castling occurred, 0 if not.
4804 Note: Only handles a max of 1 castling move, so be sure
4805 to call too_many_diffs() first.
4807 static int check_castle_draw(newb, oldb, rrow, rcol)
4814 /* For each type of castling... */
4815 for (i=0; i<4; ++i) {
4816 r = castling_matrix[i];
4818 /* Check the 4 squares involved in the castling move */
4820 for (j=1; j<=4; ++j) {
4821 if (newb[r[0]][r[j]] == oldb[r[0]][r[j]]) {
4828 /* All 4 changed, so it must be a castling move */
4837 static int damage[BOARD_SIZE][BOARD_SIZE];
4840 * event handler for redrawing the board
4842 void XDrawPosition(w, repaint, board)
4844 /*Boolean*/int repaint;
4848 static int lastFlipView = 0;
4849 static int lastBoardValid = 0;
4850 static Board lastBoard;
4854 if (board == NULL) {
4855 if (!lastBoardValid) return;
4858 if (!lastBoardValid || lastFlipView != flipView) {
4859 XtSetArg(args[0], XtNleftBitmap, (flipView ? xMarkPixmap : None));
4860 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flip View"),
4865 * It would be simpler to clear the window with XClearWindow()
4866 * but this causes a very distracting flicker.
4869 if (!repaint && lastBoardValid && lastFlipView == flipView) {
4871 /* If too much changes (begin observing new game, etc.), don't
4873 do_flash = too_many_diffs(board, lastBoard) ? 0 : 1;
4875 /* Special check for castling so we don't flash both the king
4876 and the rook (just flash the king). */
4878 if (check_castle_draw(board, lastBoard, &rrow, &rcol)) {
4879 /* Draw rook with NO flashing. King will be drawn flashing later */
4880 DrawSquare(rrow, rcol, board[rrow][rcol], 0);
4881 lastBoard[rrow][rcol] = board[rrow][rcol];
4885 /* First pass -- Draw (newly) empty squares and repair damage.
4886 This prevents you from having a piece show up twice while it
4887 is flashing on its new square */
4888 for (i = 0; i < BOARD_HEIGHT; i++)
4889 for (j = 0; j < BOARD_WIDTH; j++)
4890 if ((board[i][j] != lastBoard[i][j] && board[i][j] == EmptySquare)
4892 DrawSquare(i, j, board[i][j], 0);
4893 damage[i][j] = False;
4896 /* Second pass -- Draw piece(s) in new position and flash them */
4897 for (i = 0; i < BOARD_HEIGHT; i++)
4898 for (j = 0; j < BOARD_WIDTH; j++)
4899 if (board[i][j] != lastBoard[i][j]) {
4900 DrawSquare(i, j, board[i][j], do_flash);
4904 XDrawSegments(xDisplay, xBoardWindow, lineGC,
4905 gridSegments, BOARD_HEIGHT + BOARD_WIDTH + 2);
4907 for (i = 0; i < BOARD_HEIGHT; i++)
4908 for (j = 0; j < BOARD_WIDTH; j++) {
4909 DrawSquare(i, j, board[i][j], 0);
4910 damage[i][j] = False;
4914 CopyBoard(lastBoard, board);
4916 lastFlipView = flipView;
4918 /* Draw highlights */
4919 if (pm1X >= 0 && pm1Y >= 0) {
4920 drawHighlight(pm1X, pm1Y, prelineGC);
4922 if (pm2X >= 0 && pm2Y >= 0) {
4923 drawHighlight(pm2X, pm2Y, prelineGC);
4925 if (hi1X >= 0 && hi1Y >= 0) {
4926 drawHighlight(hi1X, hi1Y, highlineGC);
4928 if (hi2X >= 0 && hi2Y >= 0) {
4929 drawHighlight(hi2X, hi2Y, highlineGC);
4932 /* If piece being dragged around board, must redraw that too */
4935 XSync(xDisplay, False);
4940 * event handler for redrawing the board
4942 void DrawPositionProc(w, event, prms, nprms)
4948 XDrawPosition(w, True, NULL);
4953 * event handler for parsing user moves
4955 // [HGM] This routine will need quite some reworking. Although the backend still supports the old
4956 // way of doing things, by calling UserMoveEvent() to test the legality of the move and then perform
4957 // it at the end, and doing all kind of preliminary tests here (e.g. to weed out self-captures), it
4958 // should be made to use the new way, of calling UserMoveTest early to determine the legality of the
4959 // move, (which will weed out the illegal selfcaptures and moves into the holdings, and flag promotions),
4960 // and at the end FinishMove() to perform the move after optional promotion popups.
4961 // For now I patched it to allow self-capture with King, and suppress clicks between board and holdings.
4962 void HandleUserMove(w, event, prms, nprms)
4969 Boolean saveAnimate;
4970 static int second = 0;
4972 if (w != boardWidget || errorExitStatus != -1) return;
4974 if (event->type == ButtonPress) ErrorPopDown();
4977 if (event->type == ButtonPress) {
4978 XtPopdown(promotionShell);
4979 XtDestroyWidget(promotionShell);
4980 promotionUp = False;
4988 x = EventToSquare(event->xbutton.x, BOARD_WIDTH);
4989 y = EventToSquare(event->xbutton.y, BOARD_HEIGHT);
4990 if (!flipView && y >= 0) {
4991 y = BOARD_HEIGHT - 1 - y;
4993 if (flipView && x >= 0) {
4994 x = BOARD_WIDTH - 1 - x;
4997 /* [HGM] holdings: next 5 lines: ignore all clicks between board and holdings */
4998 if(event->type == ButtonPress
4999 && ( x == BOARD_LEFT-1 || x == BOARD_RGHT
5000 || x == BOARD_LEFT-2 && y < BOARD_HEIGHT-gameInfo.holdingsSize
5001 || x == BOARD_RGHT+1 && y >= gameInfo.holdingsSize) )
5005 if (event->type == ButtonPress) {
5007 if (OKToStartUserMove(x, y)) {
5011 DragPieceBegin(event->xbutton.x, event->xbutton.y);
5012 if (appData.highlightDragging) {
5013 SetHighlights(x, y, -1, -1);
5021 if (event->type == ButtonPress && gameMode != EditPosition &&
5026 /* Check if clicking again on the same color piece */
5027 fromP = boards[currentMove][fromY][fromX];
5028 toP = boards[currentMove][y][x];
5029 if ((WhitePawn <= fromP && fromP < WhiteKing && // [HGM] this test should go, as UserMoveTest now does it.
5030 WhitePawn <= toP && toP <= WhiteKing) || // For now I made it less critical by exempting King
5031 (BlackPawn <= fromP && fromP < BlackKing && // moves, to not interfere with FRC castlings.
5032 BlackPawn <= toP && toP <= BlackKing)) {
5033 /* Clicked again on same color piece -- changed his mind */
5034 second = (x == fromX && y == fromY);
5035 if (appData.highlightDragging) {
5036 SetHighlights(x, y, -1, -1);
5040 if (OKToStartUserMove(x, y)) {
5043 DragPieceBegin(event->xbutton.x, event->xbutton.y);
5049 if (event->type == ButtonRelease && x == fromX && y == fromY) {
5050 DragPieceEnd(event->xbutton.x, event->xbutton.y);
5051 if (appData.animateDragging) {
5052 /* Undo animation damage if any */
5053 DrawPosition(FALSE, NULL);
5056 /* Second up/down in same square; just abort move */
5061 ClearPremoveHighlights();
5063 /* First upclick in same square; start click-click mode */
5064 SetHighlights(x, y, -1, -1);
5069 /* Completed move */
5072 saveAnimate = appData.animate;
5073 if (event->type == ButtonPress) {
5074 /* Finish clickclick move */
5075 if (appData.animate || appData.highlightLastMove) {
5076 SetHighlights(fromX, fromY, toX, toY);
5081 /* Finish drag move */
5082 if (appData.highlightLastMove) {
5083 SetHighlights(fromX, fromY, toX, toY);
5087 DragPieceEnd(event->xbutton.x, event->xbutton.y);
5088 /* Don't animate move and drag both */
5089 appData.animate = FALSE;
5091 if (IsPromotion(fromX, fromY, toX, toY)) {
5092 if (appData.alwaysPromoteToQueen) {
5093 UserMoveEvent(fromX, fromY, toX, toY, 'q');
5094 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
5095 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
5098 SetHighlights(fromX, fromY, toX, toY);
5102 UserMoveEvent(fromX, fromY, toX, toY, NULLCHAR);
5103 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
5104 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
5107 appData.animate = saveAnimate;
5108 if (appData.animate || appData.animateDragging) {
5109 /* Undo animation damage if needed */
5110 DrawPosition(FALSE, NULL);
5114 void AnimateUserMove (Widget w, XEvent * event,
5115 String * params, Cardinal * nParams)
5117 DragPieceMove(event->xmotion.x, event->xmotion.y);
5120 Widget CommentCreate(name, text, mutable, callback, lines)
5122 int /*Boolean*/ mutable;
5123 XtCallbackProc callback;
5127 Widget shell, layout, form, edit, b_ok, b_cancel, b_clear, b_close, b_edit;
5132 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5133 XtGetValues(boardWidget, args, j);
5136 XtSetArg(args[j], XtNresizable, True); j++;
5139 XtCreatePopupShell(name, topLevelShellWidgetClass,
5140 shellWidget, args, j);
5143 XtCreatePopupShell(name, transientShellWidgetClass,
5144 shellWidget, args, j);
5147 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
5148 layoutArgs, XtNumber(layoutArgs));
5150 XtCreateManagedWidget("form", formWidgetClass, layout,
5151 formArgs, XtNumber(formArgs));
5155 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
5156 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
5158 XtSetArg(args[j], XtNstring, text); j++;
5159 XtSetArg(args[j], XtNtop, XtChainTop); j++;
5160 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5161 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5162 XtSetArg(args[j], XtNright, XtChainRight); j++;
5163 XtSetArg(args[j], XtNresizable, True); j++;
5164 XtSetArg(args[j], XtNwidth, bw_width); j++; /*force wider than buttons*/
5166 XtSetArg(args[j], XtNscrollVertical, XawtextScrollWhenNeeded); j++;
5168 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
5169 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
5171 XtSetArg(args[j], XtNautoFill, True); j++;
5172 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
5174 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
5178 XtSetArg(args[j], XtNfromVert, edit); j++;
5179 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5180 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5181 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5182 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5184 XtCreateManagedWidget(_("ok"), commandWidgetClass, form, args, j);
5185 XtAddCallback(b_ok, XtNcallback, callback, (XtPointer) 0);
5188 XtSetArg(args[j], XtNfromVert, edit); j++;
5189 XtSetArg(args[j], XtNfromHoriz, b_ok); j++;
5190 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5191 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5192 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5193 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5195 XtCreateManagedWidget(_("cancel"), commandWidgetClass, form, args, j);
5196 XtAddCallback(b_cancel, XtNcallback, callback, (XtPointer) 0);
5199 XtSetArg(args[j], XtNfromVert, edit); j++;
5200 XtSetArg(args[j], XtNfromHoriz, b_cancel); j++;
5201 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5202 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5203 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5204 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5206 XtCreateManagedWidget(_("clear"), commandWidgetClass, form, args, j);
5207 XtAddCallback(b_clear, XtNcallback, callback, (XtPointer) 0);
5210 XtSetArg(args[j], XtNfromVert, edit); j++;
5211 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5212 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5213 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5214 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5216 XtCreateManagedWidget(_("close"), commandWidgetClass, form, args, j);
5217 XtAddCallback(b_close, XtNcallback, callback, (XtPointer) 0);
5220 XtSetArg(args[j], XtNfromVert, edit); j++;
5221 XtSetArg(args[j], XtNfromHoriz, b_close); j++;
5222 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5223 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5224 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5225 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5227 XtCreateManagedWidget(_("edit"), commandWidgetClass, form, args, j);
5228 XtAddCallback(b_edit, XtNcallback, callback, (XtPointer) 0);
5231 XtRealizeWidget(shell);
5233 if (commentX == -1) {
5236 Dimension pw_height;
5237 Dimension ew_height;
5240 XtSetArg(args[j], XtNheight, &ew_height); j++;
5241 XtGetValues(edit, args, j);
5244 XtSetArg(args[j], XtNheight, &pw_height); j++;
5245 XtGetValues(shell, args, j);
5246 commentH = pw_height + (lines - 1) * ew_height;
5247 commentW = bw_width - 16;
5249 XSync(xDisplay, False);
5251 /* This code seems to tickle an X bug if it is executed too soon
5252 after xboard starts up. The coordinates get transformed as if
5253 the main window was positioned at (0, 0).
5255 XtTranslateCoords(shellWidget,
5256 (bw_width - commentW) / 2, 0 - commentH / 2,
5257 &commentX, &commentY);
5259 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
5260 RootWindowOfScreen(XtScreen(shellWidget)),
5261 (bw_width - commentW) / 2, 0 - commentH / 2,
5266 if (commentY < 0) commentY = 0; /*avoid positioning top offscreen*/
5269 XtSetArg(args[j], XtNheight, commentH); j++;
5270 XtSetArg(args[j], XtNwidth, commentW); j++;
5271 XtSetArg(args[j], XtNx, commentX); j++;
5272 XtSetArg(args[j], XtNy, commentY); j++;
5273 XtSetValues(shell, args, j);
5274 XtSetKeyboardFocus(shell, edit);
5279 /* Used for analysis window and ICS input window */
5280 Widget MiscCreate(name, text, mutable, callback, lines)
5282 int /*Boolean*/ mutable;
5283 XtCallbackProc callback;
5287 Widget shell, layout, form, edit;
5289 Dimension bw_width, pw_height, ew_height, w, h;
5295 XtSetArg(args[j], XtNresizable, True); j++;
5298 XtCreatePopupShell(name, topLevelShellWidgetClass,
5299 shellWidget, args, j);
5302 XtCreatePopupShell(name, transientShellWidgetClass,
5303 shellWidget, args, j);
5306 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
5307 layoutArgs, XtNumber(layoutArgs));
5309 XtCreateManagedWidget("form", formWidgetClass, layout,
5310 formArgs, XtNumber(formArgs));
5314 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
5315 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
5317 XtSetArg(args[j], XtNstring, text); j++;
5318 XtSetArg(args[j], XtNtop, XtChainTop); j++;
5319 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5320 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5321 XtSetArg(args[j], XtNright, XtChainRight); j++;
5322 XtSetArg(args[j], XtNresizable, True); j++;
5324 XtSetArg(args[j], XtNscrollVertical, XawtextScrollWhenNeeded); j++;
5326 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
5327 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
5329 XtSetArg(args[j], XtNautoFill, True); j++;
5330 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
5332 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
5334 XtRealizeWidget(shell);
5337 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5338 XtGetValues(boardWidget, args, j);
5341 XtSetArg(args[j], XtNheight, &ew_height); j++;
5342 XtGetValues(edit, args, j);
5345 XtSetArg(args[j], XtNheight, &pw_height); j++;
5346 XtGetValues(shell, args, j);
5347 h = pw_height + (lines - 1) * ew_height;
5350 XSync(xDisplay, False);
5352 /* This code seems to tickle an X bug if it is executed too soon
5353 after xboard starts up. The coordinates get transformed as if
5354 the main window was positioned at (0, 0).
5356 XtTranslateCoords(shellWidget, (bw_width - w) / 2, 0 - h / 2, &x, &y);
5358 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
5359 RootWindowOfScreen(XtScreen(shellWidget)),
5360 (bw_width - w) / 2, 0 - h / 2, &xx, &yy, &junk);
5364 if (y < 0) y = 0; /*avoid positioning top offscreen*/
5367 XtSetArg(args[j], XtNheight, h); j++;
5368 XtSetArg(args[j], XtNwidth, w); j++;
5369 XtSetArg(args[j], XtNx, x); j++;
5370 XtSetArg(args[j], XtNy, y); j++;
5371 XtSetValues(shell, args, j);
5377 static int savedIndex; /* gross that this is global */
5379 void EditCommentPopUp(index, title, text)
5388 if (text == NULL) text = "";
5390 if (editShell == NULL) {
5392 CommentCreate(title, text, True, EditCommentCallback, 4);
5393 XtRealizeWidget(editShell);
5394 CatchDeleteWindow(editShell, "EditCommentPopDown");
5396 edit = XtNameToWidget(editShell, "*form.text");
5398 XtSetArg(args[j], XtNstring, text); j++;
5399 XtSetValues(edit, args, j);
5401 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5402 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5403 XtSetValues(editShell, args, j);
5406 XtPopup(editShell, XtGrabNone);
5410 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
5411 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
5415 void EditCommentCallback(w, client_data, call_data)
5417 XtPointer client_data, call_data;
5425 XtSetArg(args[j], XtNlabel, &name); j++;
5426 XtGetValues(w, args, j);
5428 if (strcmp(name, _("ok")) == 0) {
5429 edit = XtNameToWidget(editShell, "*form.text");
5431 XtSetArg(args[j], XtNstring, &val); j++;
5432 XtGetValues(edit, args, j);
5433 ReplaceComment(savedIndex, val);
5434 EditCommentPopDown();
5435 } else if (strcmp(name, _("cancel")) == 0) {
5436 EditCommentPopDown();
5437 } else if (strcmp(name, _("clear")) == 0) {
5438 edit = XtNameToWidget(editShell, "*form.text");
5439 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
5440 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
5444 void EditCommentPopDown()
5449 if (!editUp) return;
5451 XtSetArg(args[j], XtNx, &commentX); j++;
5452 XtSetArg(args[j], XtNy, &commentY); j++;
5453 XtSetArg(args[j], XtNheight, &commentH); j++;
5454 XtSetArg(args[j], XtNwidth, &commentW); j++;
5455 XtGetValues(editShell, args, j);
5456 XtPopdown(editShell);
5459 XtSetArg(args[j], XtNleftBitmap, None); j++;
5460 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
5464 void ICSInputBoxPopUp()
5469 char *title = _("ICS Input");
5472 if (ICSInputShell == NULL) {
5473 ICSInputShell = MiscCreate(title, "", True, NULL, 1);
5474 tr = XtParseTranslationTable(ICSInputTranslations);
5475 edit = XtNameToWidget(ICSInputShell, "*form.text");
5476 XtOverrideTranslations(edit, tr);
5477 XtRealizeWidget(ICSInputShell);
5478 CatchDeleteWindow(ICSInputShell, "ICSInputBoxPopDown");
5481 edit = XtNameToWidget(ICSInputShell, "*form.text");
5483 XtSetArg(args[j], XtNstring, ""); j++;
5484 XtSetValues(edit, args, j);
5486 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5487 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5488 XtSetValues(ICSInputShell, args, j);
5491 XtPopup(ICSInputShell, XtGrabNone);
5492 XtSetKeyboardFocus(ICSInputShell, edit);
5494 ICSInputBoxUp = True;
5496 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
5497 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
5501 void ICSInputSendText()
5508 edit = XtNameToWidget(ICSInputShell, "*form.text");
5510 XtSetArg(args[j], XtNstring, &val); j++;
5511 XtGetValues(edit, args, j);
5512 SendMultiLineToICS(val);
5513 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
5514 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
5517 void ICSInputBoxPopDown()
5522 if (!ICSInputBoxUp) return;
5524 XtPopdown(ICSInputShell);
5525 ICSInputBoxUp = False;
5527 XtSetArg(args[j], XtNleftBitmap, None); j++;
5528 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
5532 void CommentPopUp(title, text)
5539 if (commentShell == NULL) {
5541 CommentCreate(title, text, False, CommentCallback, 4);
5542 XtRealizeWidget(commentShell);
5543 CatchDeleteWindow(commentShell, "CommentPopDown");
5545 edit = XtNameToWidget(commentShell, "*form.text");
5547 XtSetArg(args[j], XtNstring, text); j++;
5548 XtSetValues(edit, args, j);
5550 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5551 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5552 XtSetValues(commentShell, args, j);
5555 XtPopup(commentShell, XtGrabNone);
5556 XSync(xDisplay, False);
5561 void AnalysisPopUp(title, text)
5568 if (analysisShell == NULL) {
5569 analysisShell = MiscCreate(title, text, False, NULL, 4);
5570 XtRealizeWidget(analysisShell);
5571 CatchDeleteWindow(analysisShell, "AnalysisPopDown");
5574 edit = XtNameToWidget(analysisShell, "*form.text");
5576 XtSetArg(args[j], XtNstring, text); j++;
5577 XtSetValues(edit, args, j);
5579 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5580 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5581 XtSetValues(analysisShell, args, j);
5585 XtPopup(analysisShell, XtGrabNone);
5587 XSync(xDisplay, False);
5592 void CommentCallback(w, client_data, call_data)
5594 XtPointer client_data, call_data;
5601 XtSetArg(args[j], XtNlabel, &name); j++;
5602 XtGetValues(w, args, j);
5604 if (strcmp(name, _("close")) == 0) {
5606 } else if (strcmp(name, _("edit")) == 0) {
5613 void CommentPopDown()
5618 if (!commentUp) return;
5620 XtSetArg(args[j], XtNx, &commentX); j++;
5621 XtSetArg(args[j], XtNy, &commentY); j++;
5622 XtSetArg(args[j], XtNwidth, &commentW); j++;
5623 XtSetArg(args[j], XtNheight, &commentH); j++;
5624 XtGetValues(commentShell, args, j);
5625 XtPopdown(commentShell);
5626 XSync(xDisplay, False);
5630 void AnalysisPopDown()
5632 if (!analysisUp) return;
5633 XtPopdown(analysisShell);
5634 XSync(xDisplay, False);
5636 if (appData.icsEngineAnalyze) ExitAnalyzeMode(); /* [DM] icsEngineAnalyze */
5640 void FileNamePopUp(label, def, proc, openMode)
5647 Widget popup, layout, dialog, edit;
5653 fileProc = proc; /* I can't see a way not */
5654 fileOpenMode = openMode; /* to use globals here */
5657 XtSetArg(args[i], XtNresizable, True); i++;
5658 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
5659 XtSetArg(args[i], XtNtitle, XtNewString(_("File name prompt"))); i++;
5660 fileNameShell = popup =
5661 XtCreatePopupShell("File name prompt", transientShellWidgetClass,
5662 shellWidget, args, i);
5665 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
5666 layoutArgs, XtNumber(layoutArgs));
5669 XtSetArg(args[i], XtNlabel, label); i++;
5670 XtSetArg(args[i], XtNvalue, def); i++;
5671 XtSetArg(args[i], XtNborderWidth, 0); i++;
5672 dialog = XtCreateManagedWidget("fileName", dialogWidgetClass,
5675 XawDialogAddButton(dialog, _("ok"), FileNameCallback, (XtPointer) dialog);
5676 XawDialogAddButton(dialog, _("cancel"), FileNameCallback,
5677 (XtPointer) dialog);
5679 XtRealizeWidget(popup);
5680 CatchDeleteWindow(popup, "FileNamePopDown");
5682 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
5683 &x, &y, &win_x, &win_y, &mask);
5685 XtSetArg(args[0], XtNx, x - 10);
5686 XtSetArg(args[1], XtNy, y - 30);
5687 XtSetValues(popup, args, 2);
5689 XtPopup(popup, XtGrabExclusive);
5692 edit = XtNameToWidget(dialog, "*value");
5693 XtSetKeyboardFocus(popup, edit);
5696 void FileNamePopDown()
5698 if (!filenameUp) return;
5699 XtPopdown(fileNameShell);
5700 XtDestroyWidget(fileNameShell);
5705 void FileNameCallback(w, client_data, call_data)
5707 XtPointer client_data, call_data;
5712 XtSetArg(args[0], XtNlabel, &name);
5713 XtGetValues(w, args, 1);
5715 if (strcmp(name, _("cancel")) == 0) {
5720 FileNameAction(w, NULL, NULL, NULL);
5723 void FileNameAction(w, event, prms, nprms)
5735 name = XawDialogGetValueString(w = XtParent(w));
5737 if ((name != NULL) && (*name != NULLCHAR)) {
5739 XtPopdown(w = XtParent(XtParent(w)));
5743 p = strrchr(buf, ' ');
5750 fullname = ExpandPathName(buf);
5752 ErrorPopUp(_("Error"), _("Can't open file"), FALSE);
5755 f = fopen(fullname, fileOpenMode);
5757 DisplayError(_("Failed to open file"), errno);
5759 (void) (*fileProc)(f, index, buf);
5766 XtPopdown(w = XtParent(XtParent(w)));
5772 void PromotionPopUp()
5775 Widget dialog, layout;
5777 Dimension bw_width, pw_width;
5781 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5782 XtGetValues(boardWidget, args, j);
5785 XtSetArg(args[j], XtNresizable, True); j++;
5786 XtSetArg(args[j], XtNtitle, XtNewString(_("Promotion"))); j++;
5788 XtCreatePopupShell("Promotion", transientShellWidgetClass,
5789 shellWidget, args, j);
5791 XtCreateManagedWidget(layoutName, formWidgetClass, promotionShell,
5792 layoutArgs, XtNumber(layoutArgs));
5795 XtSetArg(args[j], XtNlabel, _("Promote pawn to what?")); j++;
5796 XtSetArg(args[j], XtNborderWidth, 0); j++;
5797 dialog = XtCreateManagedWidget("promotion", dialogWidgetClass,
5800 XawDialogAddButton(dialog, _("Queen"), PromotionCallback,
5801 (XtPointer) dialog);
5802 XawDialogAddButton(dialog, _("Rook"), PromotionCallback,
5803 (XtPointer) dialog);
5804 XawDialogAddButton(dialog, _("Bishop"), PromotionCallback,
5805 (XtPointer) dialog);
5806 XawDialogAddButton(dialog, _("Knight"), PromotionCallback,
5807 (XtPointer) dialog);
5808 if (!appData.testLegality || gameInfo.variant == VariantSuicide ||
5809 gameInfo.variant == VariantGiveaway) {
5810 XawDialogAddButton(dialog, _("King"), PromotionCallback,
5811 (XtPointer) dialog);
5813 XawDialogAddButton(dialog, _("cancel"), PromotionCallback,
5814 (XtPointer) dialog);
5816 XtRealizeWidget(promotionShell);
5817 CatchDeleteWindow(promotionShell, "PromotionPopDown");
5820 XtSetArg(args[j], XtNwidth, &pw_width); j++;
5821 XtGetValues(promotionShell, args, j);
5823 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
5824 lineGap + squareSize/3 +
5825 ((toY == BOARD_HEIGHT-1) ^ (flipView) ?
5826 0 : 6*(squareSize + lineGap)), &x, &y);
5829 XtSetArg(args[j], XtNx, x); j++;
5830 XtSetArg(args[j], XtNy, y); j++;
5831 XtSetValues(promotionShell, args, j);
5833 XtPopup(promotionShell, XtGrabNone);
5838 void PromotionPopDown()
5840 if (!promotionUp) return;
5841 XtPopdown(promotionShell);
5842 XtDestroyWidget(promotionShell);
5843 promotionUp = False;
5846 void PromotionCallback(w, client_data, call_data)
5848 XtPointer client_data, call_data;
5854 XtSetArg(args[0], XtNlabel, &name);
5855 XtGetValues(w, args, 1);
5859 if (fromX == -1) return;
5861 if (strcmp(name, _("cancel")) == 0) {
5865 } else if (strcmp(name, _("Knight")) == 0) {
5868 promoChar = ToLower(name[0]);
5871 UserMoveEvent(fromX, fromY, toX, toY, promoChar);
5873 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
5874 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
5879 void ErrorCallback(w, client_data, call_data)
5881 XtPointer client_data, call_data;
5884 XtPopdown(w = XtParent(XtParent(XtParent(w))));
5886 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
5892 if (!errorUp) return;
5894 XtPopdown(errorShell);
5895 XtDestroyWidget(errorShell);
5896 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
5899 void ErrorPopUp(title, label, modal)
5900 char *title, *label;
5904 Widget dialog, layout;
5908 Dimension bw_width, pw_width;
5909 Dimension pw_height;
5913 XtSetArg(args[i], XtNresizable, True); i++;
5914 XtSetArg(args[i], XtNtitle, title); i++;
5916 XtCreatePopupShell("errorpopup", transientShellWidgetClass,
5917 shellWidget, args, i);
5919 XtCreateManagedWidget(layoutName, formWidgetClass, errorShell,
5920 layoutArgs, XtNumber(layoutArgs));
5923 XtSetArg(args[i], XtNlabel, label); i++;
5924 XtSetArg(args[i], XtNborderWidth, 0); i++;
5925 dialog = XtCreateManagedWidget("dialog", dialogWidgetClass,
5928 XawDialogAddButton(dialog, _("ok"), ErrorCallback, (XtPointer) dialog);
5930 XtRealizeWidget(errorShell);
5931 CatchDeleteWindow(errorShell, "ErrorPopDown");
5934 XtSetArg(args[i], XtNwidth, &bw_width); i++;
5935 XtGetValues(boardWidget, args, i);
5937 XtSetArg(args[i], XtNwidth, &pw_width); i++;
5938 XtSetArg(args[i], XtNheight, &pw_height); i++;
5939 XtGetValues(errorShell, args, i);
5942 /* This code seems to tickle an X bug if it is executed too soon
5943 after xboard starts up. The coordinates get transformed as if
5944 the main window was positioned at (0, 0).
5946 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
5947 0 - pw_height + squareSize / 3, &x, &y);
5949 XTranslateCoordinates(xDisplay, XtWindow(boardWidget),
5950 RootWindowOfScreen(XtScreen(boardWidget)),
5951 (bw_width - pw_width) / 2,
5952 0 - pw_height + squareSize / 3, &xx, &yy, &junk);
5956 if (y < 0) y = 0; /*avoid positioning top offscreen*/
5959 XtSetArg(args[i], XtNx, x); i++;
5960 XtSetArg(args[i], XtNy, y); i++;
5961 XtSetValues(errorShell, args, i);
5964 XtPopup(errorShell, modal ? XtGrabExclusive : XtGrabNone);
5967 /* Disable all user input other than deleting the window */
5968 static int frozen = 0;
5972 /* Grab by a widget that doesn't accept input */
5973 XtAddGrab(messageWidget, TRUE, FALSE);
5977 /* Undo a FreezeUI */
5980 if (!frozen) return;
5981 XtRemoveGrab(messageWidget);
5985 char *ModeToWidgetName(mode)
5989 case BeginningOfGame:
5990 if (appData.icsActive)
5991 return "menuMode.ICS Client";
5992 else if (appData.noChessProgram ||
5993 *appData.cmailGameName != NULLCHAR)
5994 return "menuMode.Edit Game";
5996 return "menuMode.Machine Black";
5997 case MachinePlaysBlack:
5998 return "menuMode.Machine Black";
5999 case MachinePlaysWhite:
6000 return "menuMode.Machine White";
6002 return "menuMode.Analysis Mode";
6004 return "menuMode.Analyze File";
6005 case TwoMachinesPlay:
6006 return "menuMode.Two Machines";
6008 return "menuMode.Edit Game";
6009 case PlayFromGameFile:
6010 return "menuFile.Load Game";
6012 return "menuMode.Edit Position";
6014 return "menuMode.Training";
6015 case IcsPlayingWhite:
6016 case IcsPlayingBlack:
6020 return "menuMode.ICS Client";
6027 void ModeHighlight()
6030 static int oldPausing = FALSE;
6031 static GameMode oldmode = (GameMode) -1;
6034 if (!boardWidget || !XtIsRealized(boardWidget)) return;
6036 if (pausing != oldPausing) {
6037 oldPausing = pausing;
6039 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6041 XtSetArg(args[0], XtNleftBitmap, None);
6043 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Pause"),
6046 if (appData.showButtonBar) {
6049 XtSetArg(args[0], XtNbackground, buttonForegroundPixel);
6050 XtSetArg(args[1], XtNforeground, buttonBackgroundPixel);
6052 XtSetArg(args[0], XtNbackground, buttonBackgroundPixel);
6053 XtSetArg(args[1], XtNforeground, buttonForegroundPixel);
6056 /* Always toggle, don't set. Previous code messes up when
6057 invoked while the button is pressed, as releasing it
6058 toggles the state again. */
6061 XtSetArg(args[0], XtNbackground, &oldbg);
6062 XtSetArg(args[1], XtNforeground, &oldfg);
6063 XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON),
6065 XtSetArg(args[0], XtNbackground, oldfg);
6066 XtSetArg(args[1], XtNforeground, oldbg);
6069 XtSetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
6073 wname = ModeToWidgetName(oldmode);
6074 if (wname != NULL) {
6075 XtSetArg(args[0], XtNleftBitmap, None);
6076 XtSetValues(XtNameToWidget(menuBarWidget, wname), args, 1);
6078 wname = ModeToWidgetName(gameMode);
6079 if (wname != NULL) {
6080 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6081 XtSetValues(XtNameToWidget(menuBarWidget, wname), args, 1);
6085 /* Maybe all the enables should be handled here, not just this one */
6086 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Training"),
6087 gameMode == Training || gameMode == PlayFromGameFile);
6092 * Button/menu procedures
6094 void ResetProc(w, event, prms, nprms)
6104 int LoadGamePopUp(f, gameNumber, title)
6109 cmailMsgLoaded = FALSE;
6110 if (gameNumber == 0) {
6111 int error = GameListBuild(f);
6113 DisplayError(_("Cannot build game list"), error);
6114 } else if (!ListEmpty(&gameList) &&
6115 ((ListGame *) gameList.tailPred)->number > 1) {
6116 GameListPopUp(f, title);
6122 return LoadGame(f, gameNumber, title, FALSE);
6125 void LoadGameProc(w, event, prms, nprms)
6131 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
6134 FileNamePopUp(_("Load game file name?"), "", LoadGamePopUp, "rb");
6137 void LoadNextGameProc(w, event, prms, nprms)
6146 void LoadPrevGameProc(w, event, prms, nprms)
6155 void ReloadGameProc(w, event, prms, nprms)
6164 void LoadNextPositionProc(w, event, prms, nprms)
6173 void LoadPrevPositionProc(w, event, prms, nprms)
6182 void ReloadPositionProc(w, event, prms, nprms)
6191 void LoadPositionProc(w, event, prms, nprms)
6197 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
6200 FileNamePopUp(_("Load position file name?"), "", LoadPosition, "rb");
6203 void SaveGameProc(w, event, prms, nprms)
6209 FileNamePopUp(_("Save game file name?"),
6210 DefaultFileName(appData.oldSaveStyle ? "game" : "pgn"),
6214 void SavePositionProc(w, event, prms, nprms)
6220 FileNamePopUp(_("Save position file name?"),
6221 DefaultFileName(appData.oldSaveStyle ? "pos" : "fen"),
6225 void ReloadCmailMsgProc(w, event, prms, nprms)
6231 ReloadCmailMsgEvent(FALSE);
6234 void MailMoveProc(w, event, prms, nprms)
6243 /* this variable is shared between CopyPositionProc and SendPositionSelection */
6244 static char *selected_fen_position=NULL;
6247 SendPositionSelection(Widget w, Atom *selection, Atom *target,
6248 Atom *type_return, XtPointer *value_return,
6249 unsigned long *length_return, int *format_return)
6251 char *selection_tmp;
6253 if (!selected_fen_position) return False; /* should never happen */
6254 if (*target == XA_STRING){
6255 /* note: since no XtSelectionDoneProc was registered, Xt will
6256 * automatically call XtFree on the value returned. So have to
6257 * make a copy of it allocated with XtMalloc */
6258 selection_tmp= XtMalloc(strlen(selected_fen_position)+16);
6259 strcpy(selection_tmp, selected_fen_position);
6261 *value_return=selection_tmp;
6262 *length_return=strlen(selection_tmp);
6263 *type_return=XA_STRING;
6264 *format_return = 8; /* bits per byte */
6271 /* note: when called from menu all parameters are NULL, so no clue what the
6272 * Widget which was clicked on was, or what the click event was
6274 void CopyPositionProc(w, event, prms, nprms)
6282 if (selected_fen_position) free(selected_fen_position);
6283 selected_fen_position = (char *)PositionToFEN(currentMove, NULL);
6284 if (!selected_fen_position) return;
6285 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
6287 SendPositionSelection,
6288 NULL/* lose_ownership_proc */ ,
6289 NULL/* transfer_done_proc */);
6291 free(selected_fen_position);
6292 selected_fen_position=NULL;
6296 /* function called when the data to Paste is ready */
6298 PastePositionCB(Widget w, XtPointer client_data, Atom *selection,
6299 Atom *type, XtPointer value, unsigned long *len, int *format)
6302 if (value==NULL || *len==0) return; /* nothing had been selected to copy */
6303 fenstr[*len]='\0'; /* normally this string is terminated, but be safe */
6304 EditPositionPasteFEN(fenstr);
6308 /* called when Paste Position button is pressed,
6309 * all parameters will be NULL */
6310 void PastePositionProc(w, event, prms, nprms)
6316 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
6317 /* (XtSelectionCallbackProc) */ PastePositionCB,
6318 NULL, /* client_data passed to PastePositionCB */
6320 /* better to use the time field from the event that triggered the
6321 * call to this function, but that isn't trivial to get
6329 SendGameSelection(Widget w, Atom *selection, Atom *target,
6330 Atom *type_return, XtPointer *value_return,
6331 unsigned long *length_return, int *format_return)
6333 char *selection_tmp;
6335 if (*target == XA_STRING){
6336 FILE* f = fopen(gameCopyFilename, "r");
6339 if (f == NULL) return False;
6343 selection_tmp = XtMalloc(len + 1);
6344 count = fread(selection_tmp, 1, len, f);
6346 XtFree(selection_tmp);
6349 selection_tmp[len] = NULLCHAR;
6350 *value_return = selection_tmp;
6351 *length_return = len;
6352 *type_return = XA_STRING;
6353 *format_return = 8; /* bits per byte */
6360 /* note: when called from menu all parameters are NULL, so no clue what the
6361 * Widget which was clicked on was, or what the click event was
6363 void CopyGameProc(w, event, prms, nprms)
6371 ret = SaveGameToFile(gameCopyFilename, FALSE);
6374 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
6377 NULL/* lose_ownership_proc */ ,
6378 NULL/* transfer_done_proc */);
6381 /* function called when the data to Paste is ready */
6383 PasteGameCB(Widget w, XtPointer client_data, Atom *selection,
6384 Atom *type, XtPointer value, unsigned long *len, int *format)
6387 if (value == NULL || *len == 0) {
6388 return; /* nothing had been selected to copy */
6390 f = fopen(gamePasteFilename, "w");
6392 DisplayError(_("Can't open temp file"), errno);
6395 fwrite(value, 1, *len, f);
6398 LoadGameFromFile(gamePasteFilename, 0, gamePasteFilename, TRUE);
6401 /* called when Paste Game button is pressed,
6402 * all parameters will be NULL */
6403 void PasteGameProc(w, event, prms, nprms)
6409 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
6410 /* (XtSelectionCallbackProc) */ PasteGameCB,
6411 NULL, /* client_data passed to PasteGameCB */
6413 /* better to use the time field from the event that triggered the
6414 * call to this function, but that isn't trivial to get
6424 SaveGameProc(NULL, NULL, NULL, NULL);
6428 void QuitProc(w, event, prms, nprms)
6437 void PauseProc(w, event, prms, nprms)
6447 void MachineBlackProc(w, event, prms, nprms)
6453 MachineBlackEvent();
6456 void MachineWhiteProc(w, event, prms, nprms)
6462 MachineWhiteEvent();
6465 void AnalyzeModeProc(w, event, prms, nprms)
6473 if (!first.analysisSupport) {
6474 sprintf(buf, _("%s does not support analysis"), first.tidy);
6475 DisplayError(buf, 0);
6478 /* [DM] icsEngineAnalyze [HGM] This is horrible code; reverse the gameMode and isEngineAnalyze tests! */
6479 if (appData.icsActive) {
6480 if (gameMode != IcsObserving) {
6481 sprintf(buf,_("You are not observing a game"));
6482 DisplayError(buf, 0);
6484 if (appData.icsEngineAnalyze) {
6485 if (appData.debugMode)
6486 fprintf(debugFP, _("Found unexpected active ICS engine analyze \n"));
6492 /* if enable, use want disable icsEngineAnalyze */
6493 if (appData.icsEngineAnalyze) {
6498 appData.icsEngineAnalyze = TRUE;
6499 if (appData.debugMode)
6500 fprintf(debugFP, _("ICS engine analyze starting... \n"));
6502 if (!appData.showThinking)
6503 ShowThinkingProc(w,event,prms,nprms);
6508 void AnalyzeFileProc(w, event, prms, nprms)
6514 if (!first.analysisSupport) {
6516 sprintf(buf, _("%s does not support analysis"), first.tidy);
6517 DisplayError(buf, 0);
6522 if (!appData.showThinking)
6523 ShowThinkingProc(w,event,prms,nprms);
6526 FileNamePopUp(_("File to analyze"), "", LoadGamePopUp, "rb");
6527 AnalysisPeriodicEvent(1);
6530 void TwoMachinesProc(w, event, prms, nprms)
6539 void IcsClientProc(w, event, prms, nprms)
6548 void EditGameProc(w, event, prms, nprms)
6557 void EditPositionProc(w, event, prms, nprms)
6563 EditPositionEvent();
6566 void TrainingProc(w, event, prms, nprms)
6575 void EditCommentProc(w, event, prms, nprms)
6582 EditCommentPopDown();
6588 void IcsInputBoxProc(w, event, prms, nprms)
6594 if (ICSInputBoxUp) {
6595 ICSInputBoxPopDown();
6601 void AcceptProc(w, event, prms, nprms)
6610 void DeclineProc(w, event, prms, nprms)
6619 void RematchProc(w, event, prms, nprms)
6628 void CallFlagProc(w, event, prms, nprms)
6637 void DrawProc(w, event, prms, nprms)
6646 void AbortProc(w, event, prms, nprms)
6655 void AdjournProc(w, event, prms, nprms)
6664 void ResignProc(w, event, prms, nprms)
6673 void AdjuWhiteProc(w, event, prms, nprms)
6679 UserAdjudicationEvent(+1);
6682 void AdjuBlackProc(w, event, prms, nprms)
6688 UserAdjudicationEvent(-1);
6691 void AdjuDrawProc(w, event, prms, nprms)
6697 UserAdjudicationEvent(0);
6700 void EnterKeyProc(w, event, prms, nprms)
6706 if (ICSInputBoxUp == True)
6710 void StopObservingProc(w, event, prms, nprms)
6716 StopObservingEvent();
6719 void StopExaminingProc(w, event, prms, nprms)
6725 StopExaminingEvent();
6729 void ForwardProc(w, event, prms, nprms)
6739 void BackwardProc(w, event, prms, nprms)
6748 void ToStartProc(w, event, prms, nprms)
6757 void ToEndProc(w, event, prms, nprms)
6766 void RevertProc(w, event, prms, nprms)
6775 void TruncateGameProc(w, event, prms, nprms)
6781 TruncateGameEvent();
6783 void RetractMoveProc(w, event, prms, nprms)
6792 void MoveNowProc(w, event, prms, nprms)
6802 void AlwaysQueenProc(w, event, prms, nprms)
6810 appData.alwaysPromoteToQueen = !appData.alwaysPromoteToQueen;
6812 if (appData.alwaysPromoteToQueen) {
6813 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6815 XtSetArg(args[0], XtNleftBitmap, None);
6817 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
6821 void AnimateDraggingProc(w, event, prms, nprms)
6829 appData.animateDragging = !appData.animateDragging;
6831 if (appData.animateDragging) {
6832 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6835 XtSetArg(args[0], XtNleftBitmap, None);
6837 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Dragging"),
6841 void AnimateMovingProc(w, event, prms, nprms)
6849 appData.animate = !appData.animate;
6851 if (appData.animate) {
6852 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6855 XtSetArg(args[0], XtNleftBitmap, None);
6857 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
6861 void AutocommProc(w, event, prms, nprms)
6869 appData.autoComment = !appData.autoComment;
6871 if (appData.autoComment) {
6872 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6874 XtSetArg(args[0], XtNleftBitmap, None);
6876 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
6881 void AutoflagProc(w, event, prms, nprms)
6889 appData.autoCallFlag = !appData.autoCallFlag;
6891 if (appData.autoCallFlag) {
6892 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6894 XtSetArg(args[0], XtNleftBitmap, None);
6896 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
6900 void AutoflipProc(w, event, prms, nprms)
6908 appData.autoFlipView = !appData.autoFlipView;
6910 if (appData.autoFlipView) {
6911 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6913 XtSetArg(args[0], XtNleftBitmap, None);
6915 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flip View"),
6919 void AutobsProc(w, event, prms, nprms)
6927 appData.autoObserve = !appData.autoObserve;
6929 if (appData.autoObserve) {
6930 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6932 XtSetArg(args[0], XtNleftBitmap, None);
6934 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
6938 void AutoraiseProc(w, event, prms, nprms)
6946 appData.autoRaiseBoard = !appData.autoRaiseBoard;
6948 if (appData.autoRaiseBoard) {
6949 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6951 XtSetArg(args[0], XtNleftBitmap, None);
6953 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Raise Board"),
6957 void AutosaveProc(w, event, prms, nprms)
6965 appData.autoSaveGames = !appData.autoSaveGames;
6967 if (appData.autoSaveGames) {
6968 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6970 XtSetArg(args[0], XtNleftBitmap, None);
6972 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
6976 void BlindfoldProc(w, event, prms, nprms)
6984 appData.blindfold = !appData.blindfold;
6986 if (appData.blindfold) {
6987 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6989 XtSetArg(args[0], XtNleftBitmap, None);
6991 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Blindfold"),
6994 DrawPosition(True, NULL);
6997 void TestLegalityProc(w, event, prms, nprms)
7005 appData.testLegality = !appData.testLegality;
7007 if (appData.testLegality) {
7008 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7010 XtSetArg(args[0], XtNleftBitmap, None);
7012 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Test Legality"),
7017 void FlashMovesProc(w, event, prms, nprms)
7025 if (appData.flashCount == 0) {
7026 appData.flashCount = 3;
7028 appData.flashCount = -appData.flashCount;
7031 if (appData.flashCount > 0) {
7032 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7034 XtSetArg(args[0], XtNleftBitmap, None);
7036 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flash Moves"),
7040 void FlipViewProc(w, event, prms, nprms)
7046 flipView = !flipView;
7047 DrawPosition(True, NULL);
7050 void GetMoveListProc(w, event, prms, nprms)
7058 appData.getMoveList = !appData.getMoveList;
7060 if (appData.getMoveList) {
7061 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7064 XtSetArg(args[0], XtNleftBitmap, None);
7066 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
7071 void HighlightDraggingProc(w, event, prms, nprms)
7079 appData.highlightDragging = !appData.highlightDragging;
7081 if (appData.highlightDragging) {
7082 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7084 XtSetArg(args[0], XtNleftBitmap, None);
7086 XtSetValues(XtNameToWidget(menuBarWidget,
7087 "menuOptions.Highlight Dragging"), args, 1);
7091 void HighlightLastMoveProc(w, event, prms, nprms)
7099 appData.highlightLastMove = !appData.highlightLastMove;
7101 if (appData.highlightLastMove) {
7102 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7104 XtSetArg(args[0], XtNleftBitmap, None);
7106 XtSetValues(XtNameToWidget(menuBarWidget,
7107 "menuOptions.Highlight Last Move"), args, 1);
7110 void IcsAlarmProc(w, event, prms, nprms)
7118 appData.icsAlarm = !appData.icsAlarm;
7120 if (appData.icsAlarm) {
7121 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7123 XtSetArg(args[0], XtNleftBitmap, None);
7125 XtSetValues(XtNameToWidget(menuBarWidget,
7126 "menuOptions.ICS Alarm"), args, 1);
7129 void MoveSoundProc(w, event, prms, nprms)
7137 appData.ringBellAfterMoves = !appData.ringBellAfterMoves;
7139 if (appData.ringBellAfterMoves) {
7140 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7142 XtSetArg(args[0], XtNleftBitmap, None);
7144 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
7149 void OldSaveStyleProc(w, event, prms, nprms)
7157 appData.oldSaveStyle = !appData.oldSaveStyle;
7159 if (appData.oldSaveStyle) {
7160 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7162 XtSetArg(args[0], XtNleftBitmap, None);
7164 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Old Save Style"),
7168 void PeriodicUpdatesProc(w, event, prms, nprms)
7176 PeriodicUpdatesEvent(!appData.periodicUpdates);
7178 if (appData.periodicUpdates) {
7179 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7181 XtSetArg(args[0], XtNleftBitmap, None);
7183 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Periodic Updates"),
7187 void PonderNextMoveProc(w, event, prms, nprms)
7195 PonderNextMoveEvent(!appData.ponderNextMove);
7197 if (appData.ponderNextMove) {
7198 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7200 XtSetArg(args[0], XtNleftBitmap, None);
7202 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Ponder Next Move"),
7206 void PopupExitMessageProc(w, event, prms, nprms)
7214 appData.popupExitMessage = !appData.popupExitMessage;
7216 if (appData.popupExitMessage) {
7217 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7219 XtSetArg(args[0], XtNleftBitmap, None);
7221 XtSetValues(XtNameToWidget(menuBarWidget,
7222 "menuOptions.Popup Exit Message"), args, 1);
7225 void PopupMoveErrorsProc(w, event, prms, nprms)
7233 appData.popupMoveErrors = !appData.popupMoveErrors;
7235 if (appData.popupMoveErrors) {
7236 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7238 XtSetArg(args[0], XtNleftBitmap, None);
7240 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Popup Move Errors"),
7244 void PremoveProc(w, event, prms, nprms)
7252 appData.premove = !appData.premove;
7254 if (appData.premove) {
7255 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7257 XtSetArg(args[0], XtNleftBitmap, None);
7259 XtSetValues(XtNameToWidget(menuBarWidget,
7260 "menuOptions.Premove"), args, 1);
7263 void QuietPlayProc(w, event, prms, nprms)
7271 appData.quietPlay = !appData.quietPlay;
7273 if (appData.quietPlay) {
7274 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7276 XtSetArg(args[0], XtNleftBitmap, None);
7278 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Quiet Play"),
7282 void ShowCoordsProc(w, event, prms, nprms)
7290 appData.showCoords = !appData.showCoords;
7292 if (appData.showCoords) {
7293 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7295 XtSetArg(args[0], XtNleftBitmap, None);
7297 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
7300 DrawPosition(True, NULL);
7303 void ShowThinkingProc(w, event, prms, nprms)
7311 appData.showThinking = !appData.showThinking; // [HGM] thinking: tken out of ShowThinkingEvent
7312 ShowThinkingEvent();
7314 // [HGM] thinking: currently no suc menu item; replaced by Hide Thinking (From Human)
7315 if (appData.showThinking) {
7316 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7318 XtSetArg(args[0], XtNleftBitmap, None);
7320 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Thinking"),
7325 void HideThinkingProc(w, event, prms, nprms)
7333 appData.hideThinkingFromHuman = !appData.hideThinkingFromHuman; // [HGM] thinking: tken out of ShowThinkingEvent
7334 ShowThinkingEvent();
7336 if (appData.hideThinkingFromHuman) {
7337 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7339 XtSetArg(args[0], XtNleftBitmap, None);
7341 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
7345 void InfoProc(w, event, prms, nprms)
7352 sprintf(buf, "xterm -e info --directory %s --directory . -f %s &",
7357 void ManProc(w, event, prms, nprms)
7365 if (nprms && *nprms > 0)
7369 sprintf(buf, "xterm -e man %s &", name);
7373 void HintProc(w, event, prms, nprms)
7382 void BookProc(w, event, prms, nprms)
7391 void AboutProc(w, event, prms, nprms)
7399 char *zippy = " (with Zippy code)";
7403 sprintf(buf, "%s%s\n\n%s\n%s\n%s\n\n%s%s\n%s",
7404 programVersion, zippy,
7405 "Copyright 1991 Digital Equipment Corporation",
7406 "Enhancements Copyright 1992-2009 Free Software Foundation",
7407 "Enhancements Copyright 2005 Alessandro Scotti",
7408 PRODUCT, " is free software and carries NO WARRANTY;",
7409 "see the file COPYING for more information.");
7410 ErrorPopUp(_("About XBoard"), buf, FALSE);
7413 void DebugProc(w, event, prms, nprms)
7419 appData.debugMode = !appData.debugMode;
7422 void AboutGameProc(w, event, prms, nprms)
7431 void NothingProc(w, event, prms, nprms)
7440 void Iconify(w, event, prms, nprms)
7449 XtSetArg(args[0], XtNiconic, True);
7450 XtSetValues(shellWidget, args, 1);
7453 void DisplayMessage(message, extMessage)
7454 char *message, *extMessage;
7461 sprintf(buf, "%s %s", message, extMessage);
7464 message = extMessage;
7467 XtSetArg(arg, XtNlabel, message);
7468 XtSetValues(messageWidget, &arg, 1);
7471 void DisplayTitle(text)
7476 char title[MSG_SIZ];
7479 if (text == NULL) text = "";
7481 if (appData.titleInWindow) {
7483 XtSetArg(args[i], XtNlabel, text); i++;
7484 XtSetValues(titleWidget, args, i);
7487 if (*text != NULLCHAR) {
7489 strcpy(title, text);
7490 } else if (appData.icsActive) {
7491 sprintf(icon, "%s", appData.icsHost);
7492 sprintf(title, "%s: %s", programName, appData.icsHost);
7493 } else if (appData.cmailGameName[0] != NULLCHAR) {
7494 sprintf(icon, "%s", "CMail");
7495 sprintf(title, "%s: %s", programName, "CMail");
7497 // [HGM] license: This stuff should really be done in back-end, but WinBoard already had a pop-up for it
7498 } else if (gameInfo.variant == VariantGothic) {
7499 strcpy(icon, programName);
7500 strcpy(title, GOTHIC);
7503 } else if (gameInfo.variant == VariantFalcon) {
7504 strcpy(icon, programName);
7505 strcpy(title, FALCON);
7507 } else if (appData.noChessProgram) {
7508 strcpy(icon, programName);
7509 strcpy(title, programName);
7511 strcpy(icon, first.tidy);
7512 sprintf(title, "%s: %s", programName, first.tidy);
7515 XtSetArg(args[i], XtNiconName, (XtArgVal) icon); i++;
7516 XtSetArg(args[i], XtNtitle, (XtArgVal) title); i++;
7517 XtSetValues(shellWidget, args, i);
7521 void DisplayError(message, error)
7528 if (appData.debugMode || appData.matchMode) {
7529 fprintf(stderr, "%s: %s\n", programName, message);
7532 if (appData.debugMode || appData.matchMode) {
7533 fprintf(stderr, "%s: %s: %s\n",
7534 programName, message, strerror(error));
7536 sprintf(buf, "%s: %s", message, strerror(error));
7539 ErrorPopUp(_("Error"), message, FALSE);
7543 void DisplayMoveError(message)
7548 DrawPosition(FALSE, NULL);
7549 if (appData.debugMode || appData.matchMode) {
7550 fprintf(stderr, "%s: %s\n", programName, message);
7552 if (appData.popupMoveErrors) {
7553 ErrorPopUp(_("Error"), message, FALSE);
7555 DisplayMessage(message, "");
7560 void DisplayFatalError(message, error, status)
7566 errorExitStatus = status;
7568 fprintf(stderr, "%s: %s\n", programName, message);
7570 fprintf(stderr, "%s: %s: %s\n",
7571 programName, message, strerror(error));
7572 sprintf(buf, "%s: %s", message, strerror(error));
7575 if (appData.popupExitMessage && boardWidget && XtIsRealized(boardWidget)) {
7576 ErrorPopUp(status ? _("Fatal Error") : _("Exiting"), message, TRUE);
7582 void DisplayInformation(message)
7586 ErrorPopUp(_("Information"), message, TRUE);
7589 void DisplayNote(message)
7593 ErrorPopUp(_("Note"), message, FALSE);
7597 NullXErrorCheck(dpy, error_event)
7599 XErrorEvent *error_event;
7604 void DisplayIcsInteractionTitle(message)
7607 if (oldICSInteractionTitle == NULL) {
7608 /* Magic to find the old window title, adapted from vim */
7609 char *wina = getenv("WINDOWID");
7611 Window win = (Window) atoi(wina);
7612 Window root, parent, *children;
7613 unsigned int nchildren;
7614 int (*oldHandler)() = XSetErrorHandler(NullXErrorCheck);
7616 if (XFetchName(xDisplay, win, &oldICSInteractionTitle)) break;
7617 if (!XQueryTree(xDisplay, win, &root, &parent,
7618 &children, &nchildren)) break;
7619 if (children) XFree((void *)children);
7620 if (parent == root || parent == 0) break;
7623 XSetErrorHandler(oldHandler);
7625 if (oldICSInteractionTitle == NULL) {
7626 oldICSInteractionTitle = "xterm";
7629 printf("\033]0;%s\007", message);
7633 char pendingReplyPrefix[MSG_SIZ];
7634 ProcRef pendingReplyPR;
7636 void AskQuestionProc(w, event, prms, nprms)
7643 fprintf(stderr, _("AskQuestionProc needed 4 parameters, got %d\n"),
7647 AskQuestionEvent(prms[0], prms[1], prms[2], prms[3]);
7650 void AskQuestionPopDown()
7652 if (!askQuestionUp) return;
7653 XtPopdown(askQuestionShell);
7654 XtDestroyWidget(askQuestionShell);
7655 askQuestionUp = False;
7658 void AskQuestionReplyAction(w, event, prms, nprms)
7668 reply = XawDialogGetValueString(w = XtParent(w));
7669 strcpy(buf, pendingReplyPrefix);
7670 if (*buf) strcat(buf, " ");
7673 OutputToProcess(pendingReplyPR, buf, strlen(buf), &err);
7674 AskQuestionPopDown();
7676 if (err) DisplayFatalError(_("Error writing to chess program"), err, 0);
7679 void AskQuestionCallback(w, client_data, call_data)
7681 XtPointer client_data, call_data;
7686 XtSetArg(args[0], XtNlabel, &name);
7687 XtGetValues(w, args, 1);
7689 if (strcmp(name, _("cancel")) == 0) {
7690 AskQuestionPopDown();
7692 AskQuestionReplyAction(w, NULL, NULL, NULL);
7696 void AskQuestion(title, question, replyPrefix, pr)
7697 char *title, *question, *replyPrefix;
7701 Widget popup, layout, dialog, edit;
7707 strcpy(pendingReplyPrefix, replyPrefix);
7708 pendingReplyPR = pr;
7711 XtSetArg(args[i], XtNresizable, True); i++;
7712 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
7713 askQuestionShell = popup =
7714 XtCreatePopupShell(title, transientShellWidgetClass,
7715 shellWidget, args, i);
7718 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
7719 layoutArgs, XtNumber(layoutArgs));
7722 XtSetArg(args[i], XtNlabel, question); i++;
7723 XtSetArg(args[i], XtNvalue, ""); i++;
7724 XtSetArg(args[i], XtNborderWidth, 0); i++;
7725 dialog = XtCreateManagedWidget("question", dialogWidgetClass,
7728 XawDialogAddButton(dialog, _("enter"), AskQuestionCallback,
7729 (XtPointer) dialog);
7730 XawDialogAddButton(dialog, _("cancel"), AskQuestionCallback,
7731 (XtPointer) dialog);
7733 XtRealizeWidget(popup);
7734 CatchDeleteWindow(popup, "AskQuestionPopDown");
7736 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
7737 &x, &y, &win_x, &win_y, &mask);
7739 XtSetArg(args[0], XtNx, x - 10);
7740 XtSetArg(args[1], XtNy, y - 30);
7741 XtSetValues(popup, args, 2);
7743 XtPopup(popup, XtGrabExclusive);
7744 askQuestionUp = True;
7746 edit = XtNameToWidget(dialog, "*value");
7747 XtSetKeyboardFocus(popup, edit);
7755 if (*name == NULLCHAR) {
7757 } else if (strcmp(name, "$") == 0) {
7758 putc(BELLCHAR, stderr);
7761 sprintf(buf, "%s '%s' &", appData.soundProgram, name);
7769 PlaySound(appData.soundMove);
7775 PlaySound(appData.soundIcsWin);
7781 PlaySound(appData.soundIcsLoss);
7787 PlaySound(appData.soundIcsDraw);
7791 PlayIcsUnfinishedSound()
7793 PlaySound(appData.soundIcsUnfinished);
7799 PlaySound(appData.soundIcsAlarm);
7805 system("stty echo");
7811 system("stty -echo");
7815 Colorize(cc, continuation)
7820 int count, outCount, error;
7822 if (textColors[(int)cc].bg > 0) {
7823 if (textColors[(int)cc].fg > 0) {
7824 sprintf(buf, "\033[0;%d;%d;%dm", textColors[(int)cc].attr,
7825 textColors[(int)cc].fg, textColors[(int)cc].bg);
7827 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
7828 textColors[(int)cc].bg);
7831 if (textColors[(int)cc].fg > 0) {
7832 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
7833 textColors[(int)cc].fg);
7835 sprintf(buf, "\033[0;%dm", textColors[(int)cc].attr);
7838 count = strlen(buf);
7839 outCount = OutputToProcess(NoProc, buf, count, &error);
7840 if (outCount < count) {
7841 DisplayFatalError(_("Error writing to display"), error, 1);
7844 if (continuation) return;
7847 PlaySound(appData.soundShout);
7850 PlaySound(appData.soundSShout);
7853 PlaySound(appData.soundChannel1);
7856 PlaySound(appData.soundChannel);
7859 PlaySound(appData.soundKibitz);
7862 PlaySound(appData.soundTell);
7864 case ColorChallenge:
7865 PlaySound(appData.soundChallenge);
7868 PlaySound(appData.soundRequest);
7871 PlaySound(appData.soundSeek);
7882 return getpwuid(getuid())->pw_name;
7885 static char *ExpandPathName(path)
7888 static char static_buf[2000];
7889 char *d, *s, buf[2000];
7895 while (*s && isspace(*s))
7904 if (*(s+1) == '/') {
7905 strcpy(d, getpwuid(getuid())->pw_dir);
7910 *strchr(buf, '/') = 0;
7911 pwd = getpwnam(buf);
7914 fprintf(stderr, _("ERROR: Unknown user %s (in path %s)\n"),
7918 strcpy(d, pwd->pw_dir);
7919 strcat(d, strchr(s+1, '/'));
7930 static char host_name[MSG_SIZ];
7932 #if HAVE_GETHOSTNAME
7933 gethostname(host_name, MSG_SIZ);
7935 #else /* not HAVE_GETHOSTNAME */
7936 # if HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H
7937 sysinfo(SI_HOSTNAME, host_name, MSG_SIZ);
7939 # else /* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
7941 # endif/* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
7942 #endif /* not HAVE_GETHOSTNAME */
7945 XtIntervalId delayedEventTimerXID = 0;
7946 DelayedEventCallback delayedEventCallback = 0;
7951 delayedEventTimerXID = 0;
7952 delayedEventCallback();
7956 ScheduleDelayedEvent(cb, millisec)
7957 DelayedEventCallback cb; long millisec;
7959 delayedEventCallback = cb;
7960 delayedEventTimerXID =
7961 XtAppAddTimeOut(appContext, millisec,
7962 (XtTimerCallbackProc) FireDelayedEvent, (XtPointer) 0);
7965 DelayedEventCallback
7968 if (delayedEventTimerXID) {
7969 return delayedEventCallback;
7976 CancelDelayedEvent()
7978 if (delayedEventTimerXID) {
7979 XtRemoveTimeOut(delayedEventTimerXID);
7980 delayedEventTimerXID = 0;
7984 XtIntervalId loadGameTimerXID = 0;
7986 int LoadGameTimerRunning()
7988 return loadGameTimerXID != 0;
7991 int StopLoadGameTimer()
7993 if (loadGameTimerXID != 0) {
7994 XtRemoveTimeOut(loadGameTimerXID);
7995 loadGameTimerXID = 0;
8003 LoadGameTimerCallback(arg, id)
8007 loadGameTimerXID = 0;
8012 StartLoadGameTimer(millisec)
8016 XtAppAddTimeOut(appContext, millisec,
8017 (XtTimerCallbackProc) LoadGameTimerCallback,
8021 XtIntervalId analysisClockXID = 0;
8024 AnalysisClockCallback(arg, id)
8028 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile
8029 || appData.icsEngineAnalyze) { // [DM]
8030 AnalysisPeriodicEvent(0);
8031 StartAnalysisClock();
8036 StartAnalysisClock()
8039 XtAppAddTimeOut(appContext, 2000,
8040 (XtTimerCallbackProc) AnalysisClockCallback,
8044 XtIntervalId clockTimerXID = 0;
8046 int ClockTimerRunning()
8048 return clockTimerXID != 0;
8051 int StopClockTimer()
8053 if (clockTimerXID != 0) {
8054 XtRemoveTimeOut(clockTimerXID);
8063 ClockTimerCallback(arg, id)
8072 StartClockTimer(millisec)
8076 XtAppAddTimeOut(appContext, millisec,
8077 (XtTimerCallbackProc) ClockTimerCallback,
8082 DisplayTimerLabel(w, color, timer, highlight)
8091 if (appData.clockMode) {
8092 sprintf(buf, "%s: %s", color, TimeString(timer));
8093 XtSetArg(args[0], XtNlabel, buf);
8095 sprintf(buf, "%s ", color);
8096 XtSetArg(args[0], XtNlabel, buf);
8100 XtSetArg(args[1], XtNbackground, timerForegroundPixel);
8101 XtSetArg(args[2], XtNforeground, timerBackgroundPixel);
8103 XtSetArg(args[1], XtNbackground, timerBackgroundPixel);
8104 XtSetArg(args[2], XtNforeground, timerForegroundPixel);
8107 XtSetValues(w, args, 3);
8111 DisplayWhiteClock(timeRemaining, highlight)
8117 if(appData.noGUI) return;
8118 DisplayTimerLabel(whiteTimerWidget, _("White"), timeRemaining, highlight);
8119 if (highlight && iconPixmap == bIconPixmap) {
8120 iconPixmap = wIconPixmap;
8121 XtSetArg(args[0], XtNiconPixmap, iconPixmap);
8122 XtSetValues(shellWidget, args, 1);
8127 DisplayBlackClock(timeRemaining, highlight)
8133 if(appData.noGUI) return;
8134 DisplayTimerLabel(blackTimerWidget, _("Black"), timeRemaining, highlight);
8135 if (highlight && iconPixmap == wIconPixmap) {
8136 iconPixmap = bIconPixmap;
8137 XtSetArg(args[0], XtNiconPixmap, iconPixmap);
8138 XtSetValues(shellWidget, args, 1);
8156 int StartChildProcess(cmdLine, dir, pr)
8163 int to_prog[2], from_prog[2];
8167 if (appData.debugMode) {
8168 fprintf(stderr, "StartChildProcess (dir=\"%s\") %s\n",dir, cmdLine);
8171 /* We do NOT feed the cmdLine to the shell; we just
8172 parse it into blank-separated arguments in the
8173 most simple-minded way possible.
8176 strcpy(buf, cmdLine);
8181 if (p == NULL) break;
8186 SetUpChildIO(to_prog, from_prog);
8188 if ((pid = fork()) == 0) {
8190 // [HGM] PSWBTM: made order resistant against case where fd of created pipe was 0 or 1
8191 close(to_prog[1]); // first close the unused pipe ends
8192 close(from_prog[0]);
8193 dup2(to_prog[0], 0); // to_prog was created first, nd is the only one to use 0 or 1
8194 dup2(from_prog[1], 1);
8195 if(to_prog[0] >= 2) close(to_prog[0]); // if 0 or 1, the dup2 already cosed the original
8196 close(from_prog[1]); // and closing again loses one of the pipes!
8197 if(fileno(stderr) >= 2) // better safe than sorry...
8198 dup2(1, fileno(stderr)); /* force stderr to the pipe */
8200 if (dir[0] != NULLCHAR && chdir(dir) != 0) {
8205 nice(appData.niceEngines); // [HGM] nice: adjust priority of engine proc
8207 execvp(argv[0], argv);
8209 /* If we get here, exec failed */
8214 /* Parent process */
8216 close(from_prog[1]);
8218 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8221 cp->fdFrom = from_prog[0];
8222 cp->fdTo = to_prog[1];
8227 // [HGM] kill: implement the 'hard killing' of AS's Winboard_x
8228 static RETSIGTYPE AlarmCallBack(int n)
8234 DestroyChildProcess(pr, signalType)
8238 ChildProc *cp = (ChildProc *) pr;
8240 if (cp->kind != CPReal) return;
8242 if (signalType == 10) { // [HGM] kill: if it does not terminate in 3 sec, kill
8243 signal(SIGALRM, AlarmCallBack);
8245 if(wait((int *) 0) == -1) { // process does not terminate on its own accord
8246 kill(cp->pid, SIGKILL); // kill it forcefully
8247 wait((int *) 0); // and wait again
8251 kill(cp->pid, signalType == 9 ? SIGKILL : SIGTERM); // [HGM] kill: use hard kill if so requested
8253 /* Process is exiting either because of the kill or because of
8254 a quit command sent by the backend; either way, wait for it to die.
8263 InterruptChildProcess(pr)
8266 ChildProc *cp = (ChildProc *) pr;
8268 if (cp->kind != CPReal) return;
8269 (void) kill(cp->pid, SIGINT); /* stop it thinking */
8272 int OpenTelnet(host, port, pr)
8277 char cmdLine[MSG_SIZ];
8279 if (port[0] == NULLCHAR) {
8280 sprintf(cmdLine, "%s %s", appData.telnetProgram, host);
8282 sprintf(cmdLine, "%s %s %s", appData.telnetProgram, host, port);
8284 return StartChildProcess(cmdLine, "", pr);
8287 int OpenTCP(host, port, pr)
8293 DisplayFatalError(_("Socket support is not configured in"), 0, 2);
8294 #else /* !OMIT_SOCKETS */
8296 struct sockaddr_in sa;
8298 unsigned short uport;
8301 if ((s = socket(AF_INET, SOCK_STREAM, 6)) < 0) {
8305 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
8306 sa.sin_family = AF_INET;
8307 sa.sin_addr.s_addr = INADDR_ANY;
8308 uport = (unsigned short) 0;
8309 sa.sin_port = htons(uport);
8310 if (bind(s, (struct sockaddr *) &sa, sizeof(struct sockaddr_in)) < 0) {
8314 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
8315 if (!(hp = gethostbyname(host))) {
8317 if (sscanf(host, "%d.%d.%d.%d", &b0, &b1, &b2, &b3) == 4) {
8318 hp = (struct hostent *) calloc(1, sizeof(struct hostent));
8319 hp->h_addrtype = AF_INET;
8321 hp->h_addr_list = (char **) calloc(2, sizeof(char *));
8322 hp->h_addr_list[0] = (char *) malloc(4);
8323 hp->h_addr_list[0][0] = b0;
8324 hp->h_addr_list[0][1] = b1;
8325 hp->h_addr_list[0][2] = b2;
8326 hp->h_addr_list[0][3] = b3;
8331 sa.sin_family = hp->h_addrtype;
8332 uport = (unsigned short) atoi(port);
8333 sa.sin_port = htons(uport);
8334 memcpy((char *) &sa.sin_addr, hp->h_addr, hp->h_length);
8336 if (connect(s, (struct sockaddr *) &sa,
8337 sizeof(struct sockaddr_in)) < 0) {
8341 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8348 #endif /* !OMIT_SOCKETS */
8353 int OpenCommPort(name, pr)
8360 fd = open(name, 2, 0);
8361 if (fd < 0) return errno;
8363 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8373 int OpenLoopback(pr)
8379 SetUpChildIO(to, from);
8381 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8384 cp->fdFrom = to[0]; /* note not from[0]; we are doing a loopback */
8391 int OpenRcmd(host, user, cmd, pr)
8392 char *host, *user, *cmd;
8395 DisplayFatalError(_("internal rcmd not implemented for Unix"), 0, 1);
8399 #define INPUT_SOURCE_BUF_SIZE 8192
8408 char buf[INPUT_SOURCE_BUF_SIZE];
8413 DoInputCallback(closure, source, xid)
8418 InputSource *is = (InputSource *) closure;
8423 if (is->lineByLine) {
8424 count = read(is->fd, is->unused,
8425 INPUT_SOURCE_BUF_SIZE - (is->unused - is->buf));
8427 (is->func)(is, is->closure, is->buf, count, count ? errno : 0);
8430 is->unused += count;
8432 while (p < is->unused) {
8433 q = memchr(p, '\n', is->unused - p);
8434 if (q == NULL) break;
8436 (is->func)(is, is->closure, p, q - p, 0);
8440 while (p < is->unused) {
8445 count = read(is->fd, is->buf, INPUT_SOURCE_BUF_SIZE);
8450 (is->func)(is, is->closure, is->buf, count, error);
8454 InputSourceRef AddInputSource(pr, lineByLine, func, closure)
8461 ChildProc *cp = (ChildProc *) pr;
8463 is = (InputSource *) calloc(1, sizeof(InputSource));
8464 is->lineByLine = lineByLine;
8468 is->fd = fileno(stdin);
8470 is->kind = cp->kind;
8471 is->fd = cp->fdFrom;
8474 is->unused = is->buf;
8477 is->xid = XtAppAddInput(appContext, is->fd,
8478 (XtPointer) (XtInputReadMask),
8479 (XtInputCallbackProc) DoInputCallback,
8481 is->closure = closure;
8482 return (InputSourceRef) is;
8486 RemoveInputSource(isr)
8489 InputSource *is = (InputSource *) isr;
8491 if (is->xid == 0) return;
8492 XtRemoveInput(is->xid);
8496 int OutputToProcess(pr, message, count, outError)
8502 ChildProc *cp = (ChildProc *) pr;
8506 outCount = fwrite(message, 1, count, stdout);
8508 outCount = write(cp->fdTo, message, count);
8518 /* Output message to process, with "ms" milliseconds of delay
8519 between each character. This is needed when sending the logon
8520 script to ICC, which for some reason doesn't like the
8521 instantaneous send. */
8522 int OutputToProcessDelayed(pr, message, count, outError, msdelay)
8529 ChildProc *cp = (ChildProc *) pr;
8534 r = write(cp->fdTo, message++, 1);
8547 /**** Animation code by Hugh Fisher, DCS, ANU.
8549 Known problem: if a window overlapping the board is
8550 moved away while a piece is being animated underneath,
8551 the newly exposed area won't be updated properly.
8552 I can live with this.
8554 Known problem: if you look carefully at the animation
8555 of pieces in mono mode, they are being drawn as solid
8556 shapes without interior detail while moving. Fixing
8557 this would be a major complication for minimal return.
8560 /* Masks for XPM pieces. Black and white pieces can have
8561 different shapes, but in the interest of retaining my
8562 sanity pieces must have the same outline on both light
8563 and dark squares, and all pieces must use the same
8564 background square colors/images. */
8567 CreateAnimMasks (pieceDepth)
8574 unsigned long plane;
8577 /* Need a bitmap just to get a GC with right depth */
8578 buf = XCreatePixmap(xDisplay, xBoardWindow,
8580 values.foreground = 1;
8581 values.background = 0;
8582 /* Don't use XtGetGC, not read only */
8583 maskGC = XCreateGC(xDisplay, buf,
8584 GCForeground | GCBackground, &values);
8585 XFreePixmap(xDisplay, buf);
8587 buf = XCreatePixmap(xDisplay, xBoardWindow,
8588 squareSize, squareSize, pieceDepth);
8589 values.foreground = XBlackPixel(xDisplay, xScreen);
8590 values.background = XWhitePixel(xDisplay, xScreen);
8591 bufGC = XCreateGC(xDisplay, buf,
8592 GCForeground | GCBackground, &values);
8594 for (piece = WhitePawn; piece <= BlackKing; piece++) {
8595 /* Begin with empty mask */
8596 xpmMask[piece] = XCreatePixmap(xDisplay, xBoardWindow,
8597 squareSize, squareSize, 1);
8598 XSetFunction(xDisplay, maskGC, GXclear);
8599 XFillRectangle(xDisplay, xpmMask[piece], maskGC,
8600 0, 0, squareSize, squareSize);
8602 /* Take a copy of the piece */
8607 XSetFunction(xDisplay, bufGC, GXcopy);
8608 XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % (int)BlackPawn],
8610 0, 0, squareSize, squareSize, 0, 0);
8612 /* XOR the background (light) over the piece */
8613 XSetFunction(xDisplay, bufGC, GXxor);
8615 XCopyArea(xDisplay, xpmLightSquare, buf, bufGC,
8616 0, 0, squareSize, squareSize, 0, 0);
8618 XSetForeground(xDisplay, bufGC, lightSquareColor);
8619 XFillRectangle(xDisplay, buf, bufGC, 0, 0, squareSize, squareSize);
8622 /* We now have an inverted piece image with the background
8623 erased. Construct mask by just selecting all the non-zero
8624 pixels - no need to reconstruct the original image. */
8625 XSetFunction(xDisplay, maskGC, GXor);
8627 /* Might be quicker to download an XImage and create bitmap
8628 data from it rather than this N copies per piece, but it
8629 only takes a fraction of a second and there is a much
8630 longer delay for loading the pieces. */
8631 for (n = 0; n < pieceDepth; n ++) {
8632 XCopyPlane(xDisplay, buf, xpmMask[piece], maskGC,
8633 0, 0, squareSize, squareSize,
8639 XFreePixmap(xDisplay, buf);
8640 XFreeGC(xDisplay, bufGC);
8641 XFreeGC(xDisplay, maskGC);
8645 InitAnimState (anim, info)
8647 XWindowAttributes * info;
8652 /* Each buffer is square size, same depth as window */
8653 anim->saveBuf = XCreatePixmap(xDisplay, xBoardWindow,
8654 squareSize, squareSize, info->depth);
8655 anim->newBuf = XCreatePixmap(xDisplay, xBoardWindow,
8656 squareSize, squareSize, info->depth);
8658 /* Create a plain GC for blitting */
8659 mask = GCForeground | GCBackground | GCFunction |
8660 GCPlaneMask | GCGraphicsExposures;
8661 values.foreground = XBlackPixel(xDisplay, xScreen);
8662 values.background = XWhitePixel(xDisplay, xScreen);
8663 values.function = GXcopy;
8664 values.plane_mask = AllPlanes;
8665 values.graphics_exposures = False;
8666 anim->blitGC = XCreateGC(xDisplay, xBoardWindow, mask, &values);
8668 /* Piece will be copied from an existing context at
8669 the start of each new animation/drag. */
8670 anim->pieceGC = XCreateGC(xDisplay, xBoardWindow, 0, &values);
8672 /* Outline will be a read-only copy of an existing */
8673 anim->outlineGC = None;
8679 static int done = 0;
8680 XWindowAttributes info;
8684 XGetWindowAttributes(xDisplay, xBoardWindow, &info);
8686 InitAnimState(&game, &info);
8687 InitAnimState(&player, &info);
8689 /* For XPM pieces, we need bitmaps to use as masks. */
8691 CreateAnimMasks(info.depth);
8696 static Boolean frameWaiting;
8698 static RETSIGTYPE FrameAlarm (sig)
8701 frameWaiting = False;
8702 /* In case System-V style signals. Needed?? */
8703 signal(SIGALRM, FrameAlarm);
8710 struct itimerval delay;
8712 XSync(xDisplay, False);
8715 frameWaiting = True;
8716 signal(SIGALRM, FrameAlarm);
8717 delay.it_interval.tv_sec =
8718 delay.it_value.tv_sec = time / 1000;
8719 delay.it_interval.tv_usec =
8720 delay.it_value.tv_usec = (time % 1000) * 1000;
8721 setitimer(ITIMER_REAL, &delay, NULL);
8723 /* Ugh -- busy-wait! --tpm */
8724 while (frameWaiting);
8726 while (frameWaiting) pause();
8728 delay.it_interval.tv_sec = delay.it_value.tv_sec = 0;
8729 delay.it_interval.tv_usec = delay.it_value.tv_usec = 0;
8730 setitimer(ITIMER_REAL, &delay, NULL);
8740 XSync(xDisplay, False);
8742 usleep(time * 1000);
8747 /* Convert board position to corner of screen rect and color */
8750 ScreenSquare(column, row, pt, color)
8751 int column; int row; XPoint * pt; int * color;
8754 pt->x = lineGap + ((BOARD_WIDTH-1)-column) * (squareSize + lineGap);
8755 pt->y = lineGap + row * (squareSize + lineGap);
8757 pt->x = lineGap + column * (squareSize + lineGap);
8758 pt->y = lineGap + ((BOARD_HEIGHT-1)-row) * (squareSize + lineGap);
8760 *color = SquareColor(row, column);
8763 /* Convert window coords to square */
8766 BoardSquare(x, y, column, row)
8767 int x; int y; int * column; int * row;
8769 *column = EventToSquare(x, BOARD_WIDTH);
8770 if (flipView && *column >= 0)
8771 *column = BOARD_WIDTH - 1 - *column;
8772 *row = EventToSquare(y, BOARD_HEIGHT);
8773 if (!flipView && *row >= 0)
8774 *row = BOARD_HEIGHT - 1 - *row;
8779 #undef Max /* just in case */
8781 #define Max(a, b) ((a) > (b) ? (a) : (b))
8782 #define Min(a, b) ((a) < (b) ? (a) : (b))
8785 SetRect(rect, x, y, width, height)
8786 XRectangle * rect; int x; int y; int width; int height;
8790 rect->width = width;
8791 rect->height = height;
8794 /* Test if two frames overlap. If they do, return
8795 intersection rect within old and location of
8796 that rect within new. */
8799 Intersect(old, new, size, area, pt)
8800 XPoint * old; XPoint * new;
8801 int size; XRectangle * area; XPoint * pt;
8803 if (old->x > new->x + size || new->x > old->x + size ||
8804 old->y > new->y + size || new->y > old->y + size) {
8807 SetRect(area, Max(new->x - old->x, 0), Max(new->y - old->y, 0),
8808 size - abs(old->x - new->x), size - abs(old->y - new->y));
8809 pt->x = Max(old->x - new->x, 0);
8810 pt->y = Max(old->y - new->y, 0);
8815 /* For two overlapping frames, return the rect(s)
8816 in the old that do not intersect with the new. */
8819 CalcUpdateRects(old, new, size, update, nUpdates)
8820 XPoint * old; XPoint * new; int size;
8821 XRectangle update[]; int * nUpdates;
8825 /* If old = new (shouldn't happen) then nothing to draw */
8826 if (old->x == new->x && old->y == new->y) {
8830 /* Work out what bits overlap. Since we know the rects
8831 are the same size we don't need a full intersect calc. */
8833 /* Top or bottom edge? */
8834 if (new->y > old->y) {
8835 SetRect(&(update[count]), old->x, old->y, size, new->y - old->y);
8837 } else if (old->y > new->y) {
8838 SetRect(&(update[count]), old->x, old->y + size - (old->y - new->y),
8839 size, old->y - new->y);
8842 /* Left or right edge - don't overlap any update calculated above. */
8843 if (new->x > old->x) {
8844 SetRect(&(update[count]), old->x, Max(new->y, old->y),
8845 new->x - old->x, size - abs(new->y - old->y));
8847 } else if (old->x > new->x) {
8848 SetRect(&(update[count]), new->x + size, Max(new->y, old->y),
8849 old->x - new->x, size - abs(new->y - old->y));
8856 /* Generate a series of frame coords from start->mid->finish.
8857 The movement rate doubles until the half way point is
8858 reached, then halves back down to the final destination,
8859 which gives a nice slow in/out effect. The algorithmn
8860 may seem to generate too many intermediates for short
8861 moves, but remember that the purpose is to attract the
8862 viewers attention to the piece about to be moved and
8863 then to where it ends up. Too few frames would be less
8867 Tween(start, mid, finish, factor, frames, nFrames)
8868 XPoint * start; XPoint * mid;
8869 XPoint * finish; int factor;
8870 XPoint frames[]; int * nFrames;
8872 int fraction, n, count;
8876 /* Slow in, stepping 1/16th, then 1/8th, ... */
8878 for (n = 0; n < factor; n++)
8880 for (n = 0; n < factor; n++) {
8881 frames[count].x = start->x + (mid->x - start->x) / fraction;
8882 frames[count].y = start->y + (mid->y - start->y) / fraction;
8884 fraction = fraction / 2;
8888 frames[count] = *mid;
8891 /* Slow out, stepping 1/2, then 1/4, ... */
8893 for (n = 0; n < factor; n++) {
8894 frames[count].x = finish->x - (finish->x - mid->x) / fraction;
8895 frames[count].y = finish->y - (finish->y - mid->y) / fraction;
8897 fraction = fraction * 2;
8902 /* Draw a piece on the screen without disturbing what's there */
8905 SelectGCMask(piece, clip, outline, mask)
8906 ChessSquare piece; GC * clip; GC * outline; Pixmap * mask;
8910 /* Bitmap for piece being moved. */
8911 if (appData.monoMode) {
8912 *mask = *pieceToSolid(piece);
8913 } else if (useImages) {
8915 *mask = xpmMask[piece];
8917 *mask = ximMaskPm[piece%(int)BlackPawn];
8920 *mask = *pieceToSolid(piece);
8923 /* GC for piece being moved. Square color doesn't matter, but
8924 since it gets modified we make a copy of the original. */
8926 if (appData.monoMode)
8931 if (appData.monoMode)
8936 XCopyGC(xDisplay, source, 0xFFFFFFFF, *clip);
8938 /* Outline only used in mono mode and is not modified */
8940 *outline = bwPieceGC;
8942 *outline = wbPieceGC;
8946 OverlayPiece(piece, clip, outline, dest)
8947 ChessSquare piece; GC clip; GC outline; Drawable dest;
8952 /* Draw solid rectangle which will be clipped to shape of piece */
8953 XFillRectangle(xDisplay, dest, clip,
8954 0, 0, squareSize, squareSize);
8955 if (appData.monoMode)
8956 /* Also draw outline in contrasting color for black
8957 on black / white on white cases */
8958 XCopyPlane(xDisplay, *pieceToOutline(piece), dest, outline,
8959 0, 0, squareSize, squareSize, 0, 0, 1);
8961 /* Copy the piece */
8966 XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % (int)BlackPawn],
8968 0, 0, squareSize, squareSize,
8973 /* Animate the movement of a single piece */
8976 BeginAnimation(anim, piece, startColor, start)
8984 /* The old buffer is initialised with the start square (empty) */
8985 BlankSquare(0, 0, startColor, EmptySquare, anim->saveBuf);
8986 anim->prevFrame = *start;
8988 /* The piece will be drawn using its own bitmap as a matte */
8989 SelectGCMask(piece, &anim->pieceGC, &anim->outlineGC, &mask);
8990 XSetClipMask(xDisplay, anim->pieceGC, mask);
8994 AnimationFrame(anim, frame, piece)
8999 XRectangle updates[4];
9004 /* Save what we are about to draw into the new buffer */
9005 XCopyArea(xDisplay, xBoardWindow, anim->newBuf, anim->blitGC,
9006 frame->x, frame->y, squareSize, squareSize,
9009 /* Erase bits of the previous frame */
9010 if (Intersect(&anim->prevFrame, frame, squareSize, &overlap, &pt)) {
9011 /* Where the new frame overlapped the previous,
9012 the contents in newBuf are wrong. */
9013 XCopyArea(xDisplay, anim->saveBuf, anim->newBuf, anim->blitGC,
9014 overlap.x, overlap.y,
9015 overlap.width, overlap.height,
9017 /* Repaint the areas in the old that don't overlap new */
9018 CalcUpdateRects(&anim->prevFrame, frame, squareSize, updates, &count);
9019 for (i = 0; i < count; i++)
9020 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9021 updates[i].x - anim->prevFrame.x,
9022 updates[i].y - anim->prevFrame.y,
9023 updates[i].width, updates[i].height,
9024 updates[i].x, updates[i].y);
9026 /* Easy when no overlap */
9027 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9028 0, 0, squareSize, squareSize,
9029 anim->prevFrame.x, anim->prevFrame.y);
9032 /* Save this frame for next time round */
9033 XCopyArea(xDisplay, anim->newBuf, anim->saveBuf, anim->blitGC,
9034 0, 0, squareSize, squareSize,
9036 anim->prevFrame = *frame;
9038 /* Draw piece over original screen contents, not current,
9039 and copy entire rect. Wipes out overlapping piece images. */
9040 OverlayPiece(piece, anim->pieceGC, anim->outlineGC, anim->newBuf);
9041 XCopyArea(xDisplay, anim->newBuf, xBoardWindow, anim->blitGC,
9042 0, 0, squareSize, squareSize,
9043 frame->x, frame->y);
9047 EndAnimation (anim, finish)
9051 XRectangle updates[4];
9056 /* The main code will redraw the final square, so we
9057 only need to erase the bits that don't overlap. */
9058 if (Intersect(&anim->prevFrame, finish, squareSize, &overlap, &pt)) {
9059 CalcUpdateRects(&anim->prevFrame, finish, squareSize, updates, &count);
9060 for (i = 0; i < count; i++)
9061 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9062 updates[i].x - anim->prevFrame.x,
9063 updates[i].y - anim->prevFrame.y,
9064 updates[i].width, updates[i].height,
9065 updates[i].x, updates[i].y);
9067 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9068 0, 0, squareSize, squareSize,
9069 anim->prevFrame.x, anim->prevFrame.y);
9074 FrameSequence(anim, piece, startColor, start, finish, frames, nFrames)
9076 ChessSquare piece; int startColor;
9077 XPoint * start; XPoint * finish;
9078 XPoint frames[]; int nFrames;
9082 BeginAnimation(anim, piece, startColor, start);
9083 for (n = 0; n < nFrames; n++) {
9084 AnimationFrame(anim, &(frames[n]), piece);
9085 FrameDelay(appData.animSpeed);
9087 EndAnimation(anim, finish);
9090 /* Main control logic for deciding what to animate and how */
9093 AnimateMove(board, fromX, fromY, toX, toY)
9102 XPoint start, finish, mid;
9103 XPoint frames[kFactor * 2 + 1];
9104 int nFrames, startColor, endColor;
9106 /* Are we animating? */
9107 if (!appData.animate || appData.blindfold)
9110 if (fromY < 0 || fromX < 0 || toX < 0 || toY < 0) return;
9111 piece = board[fromY][fromX];
9112 if (piece >= EmptySquare) return;
9117 hop = (piece == WhiteKnight || piece == BlackKnight);
9120 if (appData.debugMode) {
9121 fprintf(debugFP, hop ? _("AnimateMove: piece %d hops from %d,%d to %d,%d \n") :
9122 _("AnimateMove: piece %d slides from %d,%d to %d,%d \n"),
9123 piece, fromX, fromY, toX, toY); }
9125 ScreenSquare(fromX, fromY, &start, &startColor);
9126 ScreenSquare(toX, toY, &finish, &endColor);
9129 /* Knight: make diagonal movement then straight */
9130 if (abs(toY - fromY) < abs(toX - fromX)) {
9131 mid.x = start.x + (finish.x - start.x) / 2;
9135 mid.y = start.y + (finish.y - start.y) / 2;
9138 mid.x = start.x + (finish.x - start.x) / 2;
9139 mid.y = start.y + (finish.y - start.y) / 2;
9142 /* Don't use as many frames for very short moves */
9143 if (abs(toY - fromY) + abs(toX - fromX) <= 2)
9144 Tween(&start, &mid, &finish, kFactor - 1, frames, &nFrames);
9146 Tween(&start, &mid, &finish, kFactor, frames, &nFrames);
9147 FrameSequence(&game, piece, startColor, &start, &finish, frames, nFrames);
9149 /* Be sure end square is redrawn */
9150 damage[toY][toX] = True;
9154 DragPieceBegin(x, y)
9157 int boardX, boardY, color;
9160 /* Are we animating? */
9161 if (!appData.animateDragging || appData.blindfold)
9164 /* Figure out which square we start in and the
9165 mouse position relative to top left corner. */
9166 BoardSquare(x, y, &boardX, &boardY);
9167 player.startBoardX = boardX;
9168 player.startBoardY = boardY;
9169 ScreenSquare(boardX, boardY, &corner, &color);
9170 player.startSquare = corner;
9171 player.startColor = color;
9173 /* Start from exactly where the piece is. This can be confusing
9174 if you start dragging far from the center of the square; most
9175 or all of the piece can be over a different square from the one
9176 the mouse pointer is in. */
9177 player.mouseDelta.x = x - corner.x;
9178 player.mouseDelta.y = y - corner.y;
9180 /* As soon as we start dragging, the piece will jump slightly to
9181 be centered over the mouse pointer. */
9182 player.mouseDelta.x = squareSize/2;
9183 player.mouseDelta.y = squareSize/2;
9185 /* Initialise animation */
9186 player.dragPiece = PieceForSquare(boardX, boardY);
9188 if (player.dragPiece >= 0 && player.dragPiece < EmptySquare) {
9189 player.dragActive = True;
9190 BeginAnimation(&player, player.dragPiece, color, &corner);
9191 /* Mark this square as needing to be redrawn. Note that
9192 we don't remove the piece though, since logically (ie
9193 as seen by opponent) the move hasn't been made yet. */
9194 if(boardX == BOARD_RGHT+1 && PieceForSquare(boardX-1, boardY) > 1 ||
9195 boardX == BOARD_LEFT-2 && PieceForSquare(boardX+1, boardY) > 1)
9196 XCopyArea(xDisplay, xBoardWindow, player.saveBuf, player.blitGC,
9197 corner.x, corner.y, squareSize, squareSize,
9198 0, 0); // [HGM] zh: unstack in stead of grab
9199 damage[boardY][boardX] = True;
9201 player.dragActive = False;
9211 /* Are we animating? */
9212 if (!appData.animateDragging || appData.blindfold)
9216 if (! player.dragActive)
9218 /* Move piece, maintaining same relative position
9219 of mouse within square */
9220 corner.x = x - player.mouseDelta.x;
9221 corner.y = y - player.mouseDelta.y;
9222 AnimationFrame(&player, &corner, player.dragPiece);
9224 if (appData.highlightDragging) {
9226 BoardSquare(x, y, &boardX, &boardY);
9227 SetHighlights(fromX, fromY, boardX, boardY);
9236 int boardX, boardY, color;
9239 /* Are we animating? */
9240 if (!appData.animateDragging || appData.blindfold)
9244 if (! player.dragActive)
9246 /* Last frame in sequence is square piece is
9247 placed on, which may not match mouse exactly. */
9248 BoardSquare(x, y, &boardX, &boardY);
9249 ScreenSquare(boardX, boardY, &corner, &color);
9250 EndAnimation(&player, &corner);
9252 /* Be sure end square is redrawn */
9253 damage[boardY][boardX] = True;
9255 /* This prevents weird things happening with fast successive
9256 clicks which on my Sun at least can cause motion events
9257 without corresponding press/release. */
9258 player.dragActive = False;
9261 /* Handle expose event while piece being dragged */
9266 if (!player.dragActive || appData.blindfold)
9269 /* What we're doing: logically, the move hasn't been made yet,
9270 so the piece is still in it's original square. But visually
9271 it's being dragged around the board. So we erase the square
9272 that the piece is on and draw it at the last known drag point. */
9273 BlankSquare(player.startSquare.x, player.startSquare.y,
9274 player.startColor, EmptySquare, xBoardWindow);
9275 AnimationFrame(&player, &player.prevFrame, player.dragPiece);
9276 damage[player.startBoardY][player.startBoardX] = TRUE;
9280 SetProgramStats( FrontEndProgramStats * stats )
9283 // [HGM] done, but perhaps backend should call this directly?
9284 EngineOutputUpdate( stats );