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) "" },
1339 // [HGM] Winboard_x UCI options
1340 { "firstIsUCI", "firstIsUCI", XtRBoolean,
1341 sizeof(Boolean), XtOffset(AppDataPtr, firstIsUCI),
1342 XtRImmediate, (XtPointer) False},
1343 { "secondIsUCI", "secondIsUCI", XtRBoolean,
1344 sizeof(Boolean), XtOffset(AppDataPtr, secondIsUCI),
1345 XtRImmediate, (XtPointer) False},
1346 { "firstHasOwnBookUCI", "firstHasOwnBookUCI", XtRBoolean,
1347 sizeof(Boolean), XtOffset(AppDataPtr, firstHasOwnBookUCI),
1348 XtRImmediate, (XtPointer) True},
1349 { "secondHasOwnBookUCI", "secondHasOwnBookUCI", XtRBoolean,
1350 sizeof(Boolean), XtOffset(AppDataPtr, secondHasOwnBookUCI),
1351 XtRImmediate, (XtPointer) True},
1352 { "usePolyglotBook", "usePolyglotBook", XtRBoolean,
1353 sizeof(Boolean), XtOffset(AppDataPtr, usePolyglotBook),
1354 XtRImmediate, (XtPointer) False},
1355 { "defaultHashSize", "defaultHashSize", XtRInt,
1356 sizeof(int), XtOffset(AppDataPtr, defaultHashSize),
1357 XtRImmediate, (XtPointer) 64},
1358 { "defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XtRInt,
1359 sizeof(int), XtOffset(AppDataPtr, defaultCacheSizeEGTB),
1360 XtRImmediate, (XtPointer) 4},
1361 { "polyglotDir", "polyglotDir", XtRString,
1362 sizeof(String), XtOffset(AppDataPtr, polyglotDir),
1363 XtRImmediate, (XtPointer) "." },
1364 { "polyglotBook", "polyglotBook", XtRString,
1365 sizeof(String), XtOffset(AppDataPtr, polyglotBook),
1366 XtRImmediate, (XtPointer) "" },
1367 { "defaultPathEGTB", "defaultPathEGTB", XtRString,
1368 sizeof(String), XtOffset(AppDataPtr, defaultPathEGTB),
1369 XtRImmediate, (XtPointer) "/usr/local/share/egtb"},
1370 { "delayBeforeQuit", "delayBeforeQuit", XtRInt,
1371 sizeof(int), XtOffset(AppDataPtr, delayBeforeQuit),
1372 XtRImmediate, (XtPointer) 0},
1373 { "delayAfterQuit", "delayAfterQuit", XtRInt,
1374 sizeof(int), XtOffset(AppDataPtr, delayAfterQuit),
1375 XtRImmediate, (XtPointer) 0},
1378 XrmOptionDescRec shellOptions[] = {
1379 { "-whitePieceColor", "whitePieceColor", XrmoptionSepArg, NULL },
1380 { "-blackPieceColor", "blackPieceColor", XrmoptionSepArg, NULL },
1381 { "-lightSquareColor", "lightSquareColor", XrmoptionSepArg, NULL },
1382 { "-darkSquareColor", "darkSquareColor", XrmoptionSepArg, NULL },
1383 { "-highlightSquareColor", "highlightSquareColor", XrmoptionSepArg, NULL },
1384 { "-premoveHighlightColor", "premoveHighlightColor", XrmoptionSepArg,NULL},
1385 { "-movesPerSession", "movesPerSession", XrmoptionSepArg, NULL },
1386 { "-mps", "movesPerSession", XrmoptionSepArg, NULL },
1387 { "-timeIncrement", "timeIncrement", XrmoptionSepArg, NULL },
1388 { "-inc", "timeIncrement", XrmoptionSepArg, NULL },
1389 { "-initString", "initString", XrmoptionSepArg, NULL },
1390 { "-firstInitString", "initString", XrmoptionSepArg, NULL },
1391 { "-secondInitString", "secondInitString", XrmoptionSepArg, NULL },
1392 { "-firstComputerString", "firstComputerString", XrmoptionSepArg, NULL },
1393 { "-secondComputerString", "secondComputerString", XrmoptionSepArg, NULL },
1394 { "-firstChessProgram", "firstChessProgram", XrmoptionSepArg, NULL },
1395 { "-fcp", "firstChessProgram", XrmoptionSepArg, NULL },
1396 { "-secondChessProgram", "secondChessProgram", XrmoptionSepArg, NULL },
1397 { "-scp", "secondChessProgram", XrmoptionSepArg, NULL },
1398 { "-firstPlaysBlack", "firstPlaysBlack", XrmoptionSepArg, NULL },
1399 { "-fb", "firstPlaysBlack", XrmoptionNoArg, "True" },
1400 { "-xfb", "firstPlaysBlack", XrmoptionNoArg, "False" },
1401 { "-noChessProgram", "noChessProgram", XrmoptionSepArg, NULL },
1402 { "-ncp", "noChessProgram", XrmoptionNoArg, "True" },
1403 { "-xncp", "noChessProgram", XrmoptionNoArg, "False" },
1404 { "-firstHost", "firstHost", XrmoptionSepArg, NULL },
1405 { "-fh", "firstHost", XrmoptionSepArg, NULL },
1406 { "-secondHost", "secondHost", XrmoptionSepArg, NULL },
1407 { "-sh", "secondHost", XrmoptionSepArg, NULL },
1408 { "-firstDirectory", "firstDirectory", XrmoptionSepArg, NULL },
1409 { "-fd", "firstDirectory", XrmoptionSepArg, NULL },
1410 { "-secondDirectory", "secondDirectory", XrmoptionSepArg, NULL },
1411 { "-sd", "secondDirectory", XrmoptionSepArg, NULL },
1412 { "-bitmapDirectory", "bitmapDirectory", XrmoptionSepArg, NULL },
1413 { "-bm", "bitmapDirectory", XrmoptionSepArg, NULL },
1414 { "-remoteShell", "remoteShell", XrmoptionSepArg, NULL },
1415 { "-rsh", "remoteShell", XrmoptionSepArg, NULL },
1416 { "-remoteUser", "remoteUser", XrmoptionSepArg, NULL },
1417 { "-ruser", "remoteUser", XrmoptionSepArg, NULL },
1418 { "-timeDelay", "timeDelay", XrmoptionSepArg, NULL },
1419 { "-td", "timeDelay", XrmoptionSepArg, NULL },
1420 { "-timeControl", "timeControl", XrmoptionSepArg, NULL },
1421 { "-tc", "timeControl", XrmoptionSepArg, NULL },
1422 { "-internetChessServerMode", "internetChessServerMode",
1423 XrmoptionSepArg, NULL },
1424 { "-ics", "internetChessServerMode", XrmoptionNoArg, "True" },
1425 { "-xics", "internetChessServerMode", XrmoptionNoArg, "False" },
1426 { "-internetChessServerHost", "internetChessServerHost",
1427 XrmoptionSepArg, NULL },
1428 { "-icshost", "internetChessServerHost", XrmoptionSepArg, NULL },
1429 { "-internetChessServerPort", "internetChessServerPort",
1430 XrmoptionSepArg, NULL },
1431 { "-icsport", "internetChessServerPort", XrmoptionSepArg, NULL },
1432 { "-internetChessServerCommPort", "internetChessServerCommPort",
1433 XrmoptionSepArg, NULL },
1434 { "-icscomm", "internetChessServerCommPort", XrmoptionSepArg, NULL },
1435 { "-internetChessServerLogonScript", "internetChessServerLogonScript",
1436 XrmoptionSepArg, NULL },
1437 { "-icslogon", "internetChessServerLogonScript", XrmoptionSepArg, NULL },
1438 { "-internetChessServerHelper", "internetChessServerHelper",
1439 XrmoptionSepArg, NULL },
1440 { "-icshelper", "internetChessServerHelper", XrmoptionSepArg, NULL },
1441 { "-internetChessServerInputBox", "internetChessServerInputBox",
1442 XrmoptionSepArg, NULL },
1443 { "-icsinput", "internetChessServerInputBox", XrmoptionNoArg, "True" },
1444 { "-xicsinput", "internetChessServerInputBox", XrmoptionNoArg, "False" },
1445 { "-icsAlarm", "icsAlarm", XrmoptionSepArg, NULL },
1446 { "-alarm", "icsAlarm", XrmoptionNoArg, "True" },
1447 { "-xalarm", "icsAlarm", XrmoptionNoArg, "False" },
1448 { "-icsAlarmTime", "icsAlarmTime", XrmoptionSepArg, NULL },
1449 { "-useTelnet", "useTelnet", XrmoptionSepArg, NULL },
1450 { "-telnet", "useTelnet", XrmoptionNoArg, "True" },
1451 { "-xtelnet", "useTelnet", XrmoptionNoArg, "False" },
1452 { "-telnetProgram", "telnetProgram", XrmoptionSepArg, NULL },
1453 { "-gateway", "gateway", XrmoptionSepArg, NULL },
1454 { "-loadGameFile", "loadGameFile", XrmoptionSepArg, NULL },
1455 { "-lgf", "loadGameFile", XrmoptionSepArg, NULL },
1456 { "-loadGameIndex", "loadGameIndex", XrmoptionSepArg, NULL },
1457 { "-lgi", "loadGameIndex", XrmoptionSepArg, NULL },
1458 { "-saveGameFile", "saveGameFile", XrmoptionSepArg, NULL },
1459 { "-sgf", "saveGameFile", XrmoptionSepArg, NULL },
1460 { "-autoSaveGames", "autoSaveGames", XrmoptionSepArg, NULL },
1461 { "-autosave", "autoSaveGames", XrmoptionNoArg, "True" },
1462 { "-xautosave", "autoSaveGames", XrmoptionNoArg, "False" },
1463 { "-autoRaiseBoard", "autoRaiseBoard", XrmoptionSepArg, NULL },
1464 { "-autoraise", "autoRaiseBoard", XrmoptionNoArg, "True" },
1465 { "-xautoraise", "autoRaiseBoard", XrmoptionNoArg, "False" },
1466 { "-blindfold", "blindfold", XrmoptionSepArg, NULL },
1467 { "-blind", "blindfold", XrmoptionNoArg, "True" },
1468 { "-xblind", "blindfold", XrmoptionNoArg, "False" },
1469 { "-loadPositionFile", "loadPositionFile", XrmoptionSepArg, NULL },
1470 { "-lpf", "loadPositionFile", XrmoptionSepArg, NULL },
1471 { "-loadPositionIndex", "loadPositionIndex", XrmoptionSepArg, NULL },
1472 { "-lpi", "loadPositionIndex", XrmoptionSepArg, NULL },
1473 { "-savePositionFile", "savePositionFile", XrmoptionSepArg, NULL },
1474 { "-spf", "savePositionFile", XrmoptionSepArg, NULL },
1475 { "-matchMode", "matchMode", XrmoptionSepArg, NULL },
1476 { "-mm", "matchMode", XrmoptionNoArg, "True" },
1477 { "-xmm", "matchMode", XrmoptionNoArg, "False" },
1478 { "-matchGames", "matchGames", XrmoptionSepArg, NULL },
1479 { "-mg", "matchGames", XrmoptionSepArg, NULL },
1480 { "-monoMode", "monoMode", XrmoptionSepArg, NULL },
1481 { "-mono", "monoMode", XrmoptionNoArg, "True" },
1482 { "-xmono", "monoMode", XrmoptionNoArg, "False" },
1483 { "-debugMode", "debugMode", XrmoptionSepArg, NULL },
1484 { "-debug", "debugMode", XrmoptionNoArg, "True" },
1485 { "-xdebug", "debugMode", XrmoptionNoArg, "False" },
1486 { "-clockMode", "clockMode", XrmoptionSepArg, NULL },
1487 { "-clock", "clockMode", XrmoptionNoArg, "True" },
1488 { "-xclock", "clockMode", XrmoptionNoArg, "False" },
1489 { "-boardSize", "boardSize", XrmoptionSepArg, NULL },
1490 { "-size", "boardSize", XrmoptionSepArg, NULL },
1491 { "-searchTime", "searchTime", XrmoptionSepArg, NULL },
1492 { "-st", "searchTime", XrmoptionSepArg, NULL },
1493 { "-searchDepth", "searchDepth", XrmoptionSepArg, NULL },
1494 { "-depth", "searchDepth", XrmoptionSepArg, NULL },
1495 { "-showCoords", "showCoords", XrmoptionSepArg, NULL },
1496 { "-coords", "showCoords", XrmoptionNoArg, "True" },
1497 { "-xcoords", "showCoords", XrmoptionNoArg, "False" },
1499 { "-showJail", "showJail", XrmoptionSepArg, NULL },
1500 { "-jail", "showJail", XrmoptionNoArg, "1" },
1501 { "-sidejail", "showJail", XrmoptionNoArg, "2" },
1502 { "-xjail", "showJail", XrmoptionNoArg, "0" },
1504 { "-showThinking", "showThinking", XrmoptionSepArg, NULL },
1505 { "-thinking", "showThinking", XrmoptionNoArg, "True" },
1506 { "-xthinking", "showThinking", XrmoptionNoArg, "False" },
1507 { "-ponderNextMove", "ponderNextMove", XrmoptionSepArg, NULL },
1508 { "-ponder", "ponderNextMove", XrmoptionNoArg, "True" },
1509 { "-xponder", "ponderNextMove", XrmoptionNoArg, "False" },
1510 { "-periodicUpdates", "periodicUpdates", XrmoptionSepArg, NULL },
1511 { "-periodic", "periodicUpdates", XrmoptionNoArg, "True" },
1512 { "-xperiodic", "periodicUpdates", XrmoptionNoArg, "False" },
1513 { "-clockFont", "clockFont", XrmoptionSepArg, NULL },
1514 { "-coordFont", "coordFont", XrmoptionSepArg, NULL },
1515 { "-font", "font", XrmoptionSepArg, NULL },
1516 { "-ringBellAfterMoves", "ringBellAfterMoves", XrmoptionSepArg, NULL },
1517 { "-bell", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1518 { "-xbell", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1519 { "-movesound", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1520 { "-xmovesound", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1521 { "-autoCallFlag", "autoCallFlag", XrmoptionSepArg, NULL },
1522 { "-autoflag", "autoCallFlag", XrmoptionNoArg, "True" },
1523 { "-xautoflag", "autoCallFlag", XrmoptionNoArg, "False" },
1524 { "-autoFlipView", "autoFlipView", XrmoptionSepArg, NULL },
1525 { "-autoflip", "autoFlipView", XrmoptionNoArg, "True" },
1526 { "-xautoflip", "autoFlipView", XrmoptionNoArg, "False" },
1527 { "-autoObserve", "autoObserve", XrmoptionSepArg, NULL },
1528 { "-autobs", "autoObserve", XrmoptionNoArg, "True" },
1529 { "-xautobs", "autoObserve", XrmoptionNoArg, "False" },
1530 { "-autoComment", "autoComment", XrmoptionSepArg, NULL },
1531 { "-autocomm", "autoComment", XrmoptionNoArg, "True" },
1532 { "-xautocomm", "autoComment", XrmoptionNoArg, "False" },
1533 { "-getMoveList", "getMoveList", XrmoptionSepArg, NULL },
1534 { "-moves", "getMoveList", XrmoptionNoArg, "True" },
1535 { "-xmoves", "getMoveList", XrmoptionNoArg, "False" },
1537 { "-highlightDragging", "highlightDragging", XrmoptionSepArg, NULL },
1538 { "-highdrag", "highlightDragging", XrmoptionNoArg, "True" },
1539 { "-xhighdrag", "highlightDragging", XrmoptionNoArg, "False" },
1541 { "-highlightLastMove", "highlightLastMove", XrmoptionSepArg, NULL },
1542 { "-highlight", "highlightLastMove", XrmoptionNoArg, "True" },
1543 { "-xhighlight", "highlightLastMove", XrmoptionNoArg, "False" },
1544 { "-premove", "premove", XrmoptionSepArg, NULL },
1545 { "-pre", "premove", XrmoptionNoArg, "True" },
1546 { "-xpre", "premove", XrmoptionNoArg, "False" },
1547 { "-testLegality", "testLegality", XrmoptionSepArg, NULL },
1548 { "-legal", "testLegality", XrmoptionNoArg, "True" },
1549 { "-xlegal", "testLegality", XrmoptionNoArg, "False" },
1550 { "-flipView", "flipView", XrmoptionSepArg, NULL },
1551 { "-flip", "flipView", XrmoptionNoArg, "True" },
1552 { "-xflip", "flipView", XrmoptionNoArg, "False" },
1553 { "-cmail", "cmailGameName", XrmoptionSepArg, NULL },
1554 { "-alwaysPromoteToQueen", "alwaysPromoteToQueen",
1555 XrmoptionSepArg, NULL },
1556 { "-queen", "alwaysPromoteToQueen", XrmoptionNoArg, "True" },
1557 { "-xqueen", "alwaysPromoteToQueen", XrmoptionNoArg, "False" },
1558 { "-oldSaveStyle", "oldSaveStyle", XrmoptionSepArg, NULL },
1559 { "-oldsave", "oldSaveStyle", XrmoptionNoArg, "True" },
1560 { "-xoldsave", "oldSaveStyle", XrmoptionNoArg, "False" },
1561 { "-quietPlay", "quietPlay", XrmoptionSepArg, NULL },
1562 { "-quiet", "quietPlay", XrmoptionNoArg, "True" },
1563 { "-xquiet", "quietPlay", XrmoptionNoArg, "False" },
1564 { "-titleInWindow", "titleInWindow", XrmoptionSepArg, NULL },
1565 { "-title", "titleInWindow", XrmoptionNoArg, "True" },
1566 { "-xtitle", "titleInWindow", XrmoptionNoArg, "False" },
1568 { "-zippyTalk", "zippyTalk", XrmoptionSepArg, NULL },
1569 { "-zt", "zippyTalk", XrmoptionNoArg, "True" },
1570 { "-xzt", "zippyTalk", XrmoptionNoArg, "False" },
1571 { "-zippyPlay", "zippyPlay", XrmoptionSepArg, NULL },
1572 { "-zp", "zippyPlay", XrmoptionNoArg, "True" },
1573 { "-xzp", "zippyPlay", XrmoptionNoArg, "False" },
1574 { "-zippyLines", "zippyLines", XrmoptionSepArg, NULL },
1575 { "-zippyPinhead", "zippyPinhead", XrmoptionSepArg, NULL },
1576 { "-zippyPassword", "zippyPassword", XrmoptionSepArg, NULL },
1577 { "-zippyPassword2", "zippyPassword2", XrmoptionSepArg, NULL },
1578 { "-zippyWrongPassword", "zippyWrongPassword", XrmoptionSepArg, NULL },
1579 { "-zippyAcceptOnly", "zippyAcceptOnly", XrmoptionSepArg, NULL },
1580 { "-zippyUseI", "zippyUseI", XrmoptionSepArg, NULL },
1581 { "-zui", "zippyUseI", XrmoptionNoArg, "True" },
1582 { "-xzui", "zippyUseI", XrmoptionNoArg, "False" },
1583 { "-zippyBughouse", "zippyBughouse", XrmoptionSepArg, NULL },
1584 { "-zippyNoplayCrafty", "zippyNoplayCrafty", XrmoptionSepArg, NULL },
1585 { "-znc", "zippyNoplayCrafty", XrmoptionNoArg, "True" },
1586 { "-xznc", "zippyNoplayCrafty", XrmoptionNoArg, "False" },
1587 { "-zippyGameEnd", "zippyGameEnd", XrmoptionSepArg, NULL },
1588 { "-zippyGameStart", "zippyGameStart", XrmoptionSepArg, NULL },
1589 { "-zippyAdjourn", "zippyAdjourn", XrmoptionSepArg, NULL },
1590 { "-zadj", "zippyAdjourn", XrmoptionNoArg, "True" },
1591 { "-xzadj", "zippyAdjourn", XrmoptionNoArg, "False" },
1592 { "-zippyAbort", "zippyAbort", XrmoptionSepArg, NULL },
1593 { "-zab", "zippyAbort", XrmoptionNoArg, "True" },
1594 { "-xzab", "zippyAbort", XrmoptionNoArg, "False" },
1595 { "-zippyVariants", "zippyVariants", XrmoptionSepArg, NULL },
1596 { "-zippyMaxGames", "zippyMaxGames", XrmoptionSepArg, NULL },
1597 { "-zippyReplayTimeout", "zippyReplayTimeout", XrmoptionSepArg, NULL },
1599 { "-flashCount", "flashCount", XrmoptionSepArg, NULL },
1600 { "-flash", "flashCount", XrmoptionNoArg, "3" },
1601 { "-xflash", "flashCount", XrmoptionNoArg, "0" },
1602 { "-flashRate", "flashRate", XrmoptionSepArg, NULL },
1603 { "-pixmapDirectory", "pixmapDirectory", XrmoptionSepArg, NULL },
1604 { "-msLoginDelay", "msLoginDelay", XrmoptionSepArg, NULL },
1605 { "-pixmap", "pixmapDirectory", XrmoptionSepArg, NULL },
1606 { "-colorizeMessages", "colorizeMessages", XrmoptionSepArg, NULL },
1607 { "-colorize", "colorizeMessages", XrmoptionNoArg, "True" },
1608 { "-xcolorize", "colorizeMessages", XrmoptionNoArg, "False" },
1609 { "-colorShout", "colorShout", XrmoptionSepArg, NULL },
1610 { "-colorSShout", "colorSShout", XrmoptionSepArg, NULL },
1611 { "-colorCShout", "colorSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1612 { "-colorChannel1", "colorChannel1", XrmoptionSepArg, NULL },
1613 { "-colorChannel", "colorChannel", XrmoptionSepArg, NULL },
1614 { "-colorKibitz", "colorKibitz", XrmoptionSepArg, NULL },
1615 { "-colorTell", "colorTell", XrmoptionSepArg, NULL },
1616 { "-colorChallenge", "colorChallenge", XrmoptionSepArg, NULL },
1617 { "-colorRequest", "colorRequest", XrmoptionSepArg, NULL },
1618 { "-colorSeek", "colorSeek", XrmoptionSepArg, NULL },
1619 { "-colorNormal", "colorNormal", XrmoptionSepArg, NULL },
1620 { "-soundProgram", "soundProgram", XrmoptionSepArg, NULL },
1621 { "-soundShout", "soundShout", XrmoptionSepArg, NULL },
1622 { "-soundSShout", "soundSShout", XrmoptionSepArg, NULL },
1623 { "-soundCShout", "soundSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1624 { "-soundChannel1", "soundChannel1", XrmoptionSepArg, NULL },
1625 { "-soundChannel", "soundChannel", XrmoptionSepArg, NULL },
1626 { "-soundKibitz", "soundKibitz", XrmoptionSepArg, NULL },
1627 { "-soundTell", "soundTell", XrmoptionSepArg, NULL },
1628 { "-soundChallenge", "soundChallenge", XrmoptionSepArg, NULL },
1629 { "-soundRequest", "soundRequest", XrmoptionSepArg, NULL },
1630 { "-soundSeek", "soundSeek", XrmoptionSepArg, NULL },
1631 { "-soundMove", "soundMove", XrmoptionSepArg, NULL },
1632 { "-soundIcsWin", "soundIcsWin", XrmoptionSepArg, NULL },
1633 { "-soundIcsLoss", "soundIcsLoss", XrmoptionSepArg, NULL },
1634 { "-soundIcsDraw", "soundIcsDraw", XrmoptionSepArg, NULL },
1635 { "-soundIcsUnfinished", "soundIcsUnfinished", XrmoptionSepArg, NULL },
1636 { "-soundIcsAlarm", "soundIcsAlarm", XrmoptionSepArg, NULL },
1637 { "-reuseFirst", "reuseFirst", XrmoptionSepArg, NULL },
1638 { "-reuseChessPrograms", "reuseFirst", XrmoptionSepArg, NULL }, /*compat*/
1639 { "-reuse", "reuseFirst", XrmoptionNoArg, "True" },
1640 { "-xreuse", "reuseFirst", XrmoptionNoArg, "False" },
1641 { "-reuseSecond", "reuseSecond", XrmoptionSepArg, NULL },
1642 { "-reuse2", "reuseSecond", XrmoptionNoArg, "True" },
1643 { "-xreuse2", "reuseSecond", XrmoptionNoArg, "False" },
1644 { "-animateMoving", "animateMoving", XrmoptionSepArg, NULL },
1645 { "-animate", "animateMoving", XrmoptionNoArg, "True" },
1646 { "-xanimate", "animateMoving", XrmoptionNoArg, "False" },
1647 { "-animateDragging", "animateDragging", XrmoptionSepArg, NULL },
1648 { "-drag", "animateDragging", XrmoptionNoArg, "True" },
1649 { "-xdrag", "animateDragging", XrmoptionNoArg, "False" },
1650 { "-animateSpeed", "animateSpeed", XrmoptionSepArg, NULL },
1651 { "-popupExitMessage", "popupExitMessage", XrmoptionSepArg, NULL },
1652 { "-exit", "popupExitMessage", XrmoptionNoArg, "True" },
1653 { "-xexit", "popupExitMessage", XrmoptionNoArg, "False" },
1654 { "-popupMoveErrors", "popupMoveErrors", XrmoptionSepArg, NULL },
1655 { "-popup", "popupMoveErrors", XrmoptionNoArg, "True" },
1656 { "-xpopup", "popupMoveErrors", XrmoptionNoArg, "False" },
1657 { "-fontSizeTolerance", "fontSizeTolerance", XrmoptionSepArg, NULL },
1658 { "-initialMode", "initialMode", XrmoptionSepArg, NULL },
1659 { "-mode", "initialMode", XrmoptionSepArg, NULL },
1660 { "-variant", "variant", XrmoptionSepArg, NULL },
1661 { "-firstProtocolVersion", "firstProtocolVersion", XrmoptionSepArg, NULL },
1662 { "-secondProtocolVersion","secondProtocolVersion",XrmoptionSepArg, NULL },
1663 { "-showButtonBar", "showButtonBar", XrmoptionSepArg, NULL },
1664 { "-buttons", "showButtonBar", XrmoptionNoArg, "True" },
1665 { "-xbuttons", "showButtonBar", XrmoptionNoArg, "False" },
1666 /* [AS,HR] New features */
1667 { "-firstScoreAbs", "firstScoreAbs", XrmoptionSepArg, NULL },
1668 { "-secondScoreAbs", "secondScoreAbs", XrmoptionSepArg, NULL },
1669 { "-pgnExtendedInfo", "pgnExtendedInfo", XrmoptionSepArg, NULL },
1670 { "-hideThinkingFromHuman", "hideThinkingFromHuman", XrmoptionSepArg, NULL },
1671 { "-adjudicateLossThreshold", "adjudicateLossThreshold", XrmoptionSepArg, NULL },
1672 { "-pgnEventHeader", "pgnEventHeader", XrmoptionSepArg, NULL },
1673 { "-firstIsUCI", "firstIsUCI", XrmoptionSepArg, NULL },
1674 { "-secondIsUCI", "secondIsUCI", XrmoptionSepArg, NULL },
1675 { "-fUCI", "firstIsUCI", XrmoptionNoArg, "True" },
1676 { "-sUCI", "secondIsUCI", XrmoptionNoArg, "True" },
1677 { "-firstHasOwnBookUCI", "firstHasOwnBookUCI", XrmoptionSepArg, NULL },
1678 { "-secondHasOwnBookUCI", "secondHasOwnBookUCI", XrmoptionSepArg, NULL },
1679 { "-fNoOwnBookUCI", "firstHasOwnBookUCI", XrmoptionNoArg, "False" },
1680 { "-sNoOwnBookUCI", "secondHasOwnBookUCI", XrmoptionNoArg, "False" },
1681 { "-firstXBook", "firstHasOwnBookUCI", XrmoptionNoArg, "False" },
1682 { "-secondXBook", "secondHasOwnBookUCI", XrmoptionNoArg, "False" },
1683 { "-polyglotDir", "polyglotDir", XrmoptionSepArg, NULL },
1684 { "-usePolyglotBook", "usePolyglotBook", XrmoptionSepArg, NULL },
1685 { "-polyglotBook", "polyglotBook", XrmoptionSepArg, NULL },
1686 { "-defaultHashSize", "defaultHashSize", XrmoptionSepArg, NULL },
1687 { "-defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XrmoptionSepArg, NULL },
1688 { "-defaultPathEGTB", "defaultPathEGTB", XrmoptionSepArg, NULL },
1689 { "-defaultFrcPosition", "defaultFrcPosition", XrmoptionSepArg, NULL },
1690 { "-gameListTags", "gameListTags", XrmoptionSepArg, NULL },
1691 // [HGM] I am sure AS added many more options, but we have to fish them out, from the list in winboard.c
1693 /* [HGM,HR] User-selectable board size */
1694 { "-boardWidth", "boardWidth", XrmoptionSepArg, NULL },
1695 { "-boardHeight", "boardHeight", XrmoptionSepArg, NULL },
1696 { "-matchPause", "matchPause", XrmoptionSepArg, NULL },
1698 /* [HGM] new arguments of 4.3.xx. All except first three are back-end options, which should work immediately */
1699 { "-holdingsSize", "holdingsSize", XrmoptionSepArg, NULL }, // requires extensive front-end changes to work
1700 { "-flipBlack", "flipBlack", XrmoptionSepArg, NULL }, // requires front-end changes to work
1701 { "-allWhite", "allWhite", XrmoptionSepArg, NULL }, // requires front-end changes to work
1702 { "-pieceToCharTable", "pieceToCharTable", XrmoptionSepArg, NULL },
1703 { "-alphaRank", "alphaRank", XrmoptionSepArg, NULL },
1704 { "-testClaims", "testClaims", XrmoptionSepArg, NULL },
1705 { "-checkMates", "checkMates", XrmoptionSepArg, NULL },
1706 { "-materialDraws", "materialDraws", XrmoptionSepArg, NULL },
1707 { "-trivialDraws", "trivialDraws", XrmoptionSepArg, NULL },
1708 { "-ruleMoves", "ruleMoves", XrmoptionSepArg, NULL },
1709 { "-repeatsToDraw", "repeatsToDraw", XrmoptionSepArg, NULL },
1710 { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL },
1711 { "-userName", "userName", XrmoptionSepArg, NULL },
1712 { "-autoKibitz", "autoKibitz", XrmoptionNoArg, "True" },
1713 { "-firstTimeOdds", "firstTimeOdds", XrmoptionSepArg, NULL },
1714 { "-secondTimeOdds", "secondTimeOdds", XrmoptionSepArg, NULL },
1715 { "-timeOddsMode", "timeOddsMode", XrmoptionSepArg, NULL },
1716 { "-firstAccumulateTC", "firstAccumulateTC", XrmoptionSepArg, NULL },
1717 { "-secondAccumulateTC", "secondAccumulateTC", XrmoptionSepArg, NULL },
1718 { "-firstNPS", "firstNPS", XrmoptionSepArg, NULL },
1719 { "-secondNPS", "secondNPS", XrmoptionSepArg, NULL },
1720 { "-serverMoves", "serverMoves", XrmoptionSepArg, NULL },
1721 { "-serverPause", "serverPause", XrmoptionSepArg, NULL },
1722 { "-suppressLoadMoves", "suppressLoadMoves", XrmoptionSepArg, NULL },
1723 { "-egtFormats", "egtFormats", XrmoptionSepArg, NULL },
1724 { "-userName", "userName", XrmoptionSepArg, NULL },
1725 { "-smpCores", "smpCores", XrmoptionSepArg, NULL },
1726 { "-sameColorGames", "sameColorGames", XrmoptionSepArg, NULL },
1727 { "-rewindIndex", "rewindIndex", XrmoptionSepArg, NULL },
1728 { "-niceEngines", "niceEngines", XrmoptionSepArg, NULL },
1729 { "-delayBeforeQuit", "delayBeforeQuit", XrmoptionSepArg, NULL },
1730 { "-delayAfterQuit", "delayAfterQuit", XrmoptionSepArg, NULL },
1731 { "-nameOfDebugFile", "nameOfDebugFile", XrmoptionSepArg, NULL },
1732 { "-debugFile", "nameOfDebugFile", XrmoptionSepArg, NULL },
1733 { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL },
1734 { "-noGUI", "noGUI", XrmoptionNoArg, "True" },
1735 { "-firstOptions", "firstOptions", XrmoptionSepArg, NULL },
1736 { "-secondOptions", "secondOptions", XrmoptionSepArg, NULL },
1740 XtActionsRec boardActions[] = {
1741 { "DrawPosition", DrawPositionProc },
1742 { "HandleUserMove", HandleUserMove },
1743 { "AnimateUserMove", AnimateUserMove },
1744 { "FileNameAction", FileNameAction },
1745 { "AskQuestionProc", AskQuestionProc },
1746 { "AskQuestionReplyAction", AskQuestionReplyAction },
1747 { "PieceMenuPopup", PieceMenuPopup },
1748 { "WhiteClock", WhiteClock },
1749 { "BlackClock", BlackClock },
1750 { "Iconify", Iconify },
1751 { "ResetProc", ResetProc },
1752 { "LoadGameProc", LoadGameProc },
1753 { "LoadNextGameProc", LoadNextGameProc },
1754 { "LoadPrevGameProc", LoadPrevGameProc },
1755 { "LoadSelectedProc", LoadSelectedProc },
1756 { "ReloadGameProc", ReloadGameProc },
1757 { "LoadPositionProc", LoadPositionProc },
1758 { "LoadNextPositionProc", LoadNextPositionProc },
1759 { "LoadPrevPositionProc", LoadPrevPositionProc },
1760 { "ReloadPositionProc", ReloadPositionProc },
1761 { "CopyPositionProc", CopyPositionProc },
1762 { "PastePositionProc", PastePositionProc },
1763 { "CopyGameProc", CopyGameProc },
1764 { "PasteGameProc", PasteGameProc },
1765 { "SaveGameProc", SaveGameProc },
1766 { "SavePositionProc", SavePositionProc },
1767 { "MailMoveProc", MailMoveProc },
1768 { "ReloadCmailMsgProc", ReloadCmailMsgProc },
1769 { "QuitProc", QuitProc },
1770 { "MachineWhiteProc", MachineWhiteProc },
1771 { "MachineBlackProc", MachineBlackProc },
1772 { "AnalysisModeProc", AnalyzeModeProc },
1773 { "AnalyzeFileProc", AnalyzeFileProc },
1774 { "TwoMachinesProc", TwoMachinesProc },
1775 { "IcsClientProc", IcsClientProc },
1776 { "EditGameProc", EditGameProc },
1777 { "EditPositionProc", EditPositionProc },
1778 { "TrainingProc", EditPositionProc },
1779 { "EngineOutputProc", EngineOutputProc}, // [HGM] Winboard_x engine-output window
1780 { "ShowGameListProc", ShowGameListProc },
1781 { "ShowMoveListProc", HistoryShowProc},
1782 { "EditTagsProc", EditCommentProc },
1783 { "EditCommentProc", EditCommentProc },
1784 { "IcsAlarmProc", IcsAlarmProc },
1785 { "IcsInputBoxProc", IcsInputBoxProc },
1786 { "PauseProc", PauseProc },
1787 { "AcceptProc", AcceptProc },
1788 { "DeclineProc", DeclineProc },
1789 { "RematchProc", RematchProc },
1790 { "CallFlagProc", CallFlagProc },
1791 { "DrawProc", DrawProc },
1792 { "AdjournProc", AdjournProc },
1793 { "AbortProc", AbortProc },
1794 { "ResignProc", ResignProc },
1795 { "AdjuWhiteProc", AdjuWhiteProc },
1796 { "AdjuBlackProc", AdjuBlackProc },
1797 { "AdjuDrawProc", AdjuDrawProc },
1798 { "EnterKeyProc", EnterKeyProc },
1799 { "StopObservingProc", StopObservingProc },
1800 { "StopExaminingProc", StopExaminingProc },
1801 { "BackwardProc", BackwardProc },
1802 { "ForwardProc", ForwardProc },
1803 { "ToStartProc", ToStartProc },
1804 { "ToEndProc", ToEndProc },
1805 { "RevertProc", RevertProc },
1806 { "TruncateGameProc", TruncateGameProc },
1807 { "MoveNowProc", MoveNowProc },
1808 { "RetractMoveProc", RetractMoveProc },
1809 { "AlwaysQueenProc", AlwaysQueenProc },
1810 { "AnimateDraggingProc", AnimateDraggingProc },
1811 { "AnimateMovingProc", AnimateMovingProc },
1812 { "AutoflagProc", AutoflagProc },
1813 { "AutoflipProc", AutoflipProc },
1814 { "AutobsProc", AutobsProc },
1815 { "AutoraiseProc", AutoraiseProc },
1816 { "AutosaveProc", AutosaveProc },
1817 { "BlindfoldProc", BlindfoldProc },
1818 { "FlashMovesProc", FlashMovesProc },
1819 { "FlipViewProc", FlipViewProc },
1820 { "GetMoveListProc", GetMoveListProc },
1822 { "HighlightDraggingProc", HighlightDraggingProc },
1824 { "HighlightLastMoveProc", HighlightLastMoveProc },
1825 { "IcsAlarmProc", IcsAlarmProc },
1826 { "MoveSoundProc", MoveSoundProc },
1827 { "OldSaveStyleProc", OldSaveStyleProc },
1828 { "PeriodicUpdatesProc", PeriodicUpdatesProc },
1829 { "PonderNextMoveProc", PonderNextMoveProc },
1830 { "PopupExitMessageProc", PopupExitMessageProc },
1831 { "PopupMoveErrorsProc", PopupMoveErrorsProc },
1832 { "PremoveProc", PremoveProc },
1833 { "QuietPlayProc", QuietPlayProc },
1834 { "ShowCoordsProc", ShowCoordsProc },
1835 { "ShowThinkingProc", ShowThinkingProc },
1836 { "HideThinkingProc", HideThinkingProc },
1837 { "TestLegalityProc", TestLegalityProc },
1838 { "InfoProc", InfoProc },
1839 { "ManProc", ManProc },
1840 { "HintProc", HintProc },
1841 { "BookProc", BookProc },
1842 { "AboutGameProc", AboutGameProc },
1843 { "AboutProc", AboutProc },
1844 { "DebugProc", DebugProc },
1845 { "NothingProc", NothingProc },
1846 { "CommentPopDown", (XtActionProc) CommentPopDown },
1847 { "EditCommentPopDown", (XtActionProc) EditCommentPopDown },
1848 { "TagsPopDown", (XtActionProc) TagsPopDown },
1849 { "ErrorPopDown", (XtActionProc) ErrorPopDown },
1850 { "ICSInputBoxPopDown", (XtActionProc) ICSInputBoxPopDown },
1851 { "AnalysisPopDown", (XtActionProc) AnalysisPopDown },
1852 { "FileNamePopDown", (XtActionProc) FileNamePopDown },
1853 { "AskQuestionPopDown", (XtActionProc) AskQuestionPopDown },
1854 { "GameListPopDown", (XtActionProc) GameListPopDown },
1855 { "PromotionPopDown", (XtActionProc) PromotionPopDown },
1856 { "HistoryPopDown", (XtActionProc) HistoryPopDown },
1857 { "EngineOutputPopDown", (XtActionProc) EngineOutputPopDown },
1858 { "ShufflePopDown", (XtActionProc) ShufflePopDown },
1859 { "EnginePopDown", (XtActionProc) EnginePopDown },
1860 { "UciPopDown", (XtActionProc) UciPopDown },
1861 { "TimeControlPopDown", (XtActionProc) TimeControlPopDown },
1862 { "NewVariantPopDown", (XtActionProc) NewVariantPopDown },
1863 { "SettingsPopDown", (XtActionProc) SettingsPopDown },
1866 char globalTranslations[] =
1867 ":<Key>R: ResignProc() \n \
1868 :<Key>r: ResetProc() \n \
1869 :<Key>g: LoadGameProc() \n \
1870 :<Key>N: LoadNextGameProc() \n \
1871 :<Key>P: LoadPrevGameProc() \n \
1872 :<Key>Q: QuitProc() \n \
1873 :<Key>F: ToEndProc() \n \
1874 :<Key>f: ForwardProc() \n \
1875 :<Key>B: ToStartProc() \n \
1876 :<Key>b: BackwardProc() \n \
1877 :<Key>p: PauseProc() \n \
1878 :<Key>d: DrawProc() \n \
1879 :<Key>t: CallFlagProc() \n \
1880 :<Key>i: Iconify() \n \
1881 :<Key>c: Iconify() \n \
1882 :<Key>v: FlipViewProc() \n \
1883 <KeyDown>Control_L: BackwardProc() \n \
1884 <KeyUp>Control_L: ForwardProc() \n \
1885 <KeyDown>Control_R: BackwardProc() \n \
1886 <KeyUp>Control_R: ForwardProc() \n \
1887 Shift<Key>1: AskQuestionProc(\"Direct command\",\
1888 \"Send to chess program:\",,1) \n \
1889 Shift<Key>2: AskQuestionProc(\"Direct command\",\
1890 \"Send to second chess program:\",,2) \n";
1892 char boardTranslations[] =
1893 "<Btn1Down>: HandleUserMove() \n \
1894 <Btn1Up>: HandleUserMove() \n \
1895 <Btn1Motion>: AnimateUserMove() \n \
1896 Shift<Btn2Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD)\
1897 PieceMenuPopup(menuB) \n \
1898 Any<Btn2Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD) \
1899 PieceMenuPopup(menuW) \n \
1900 Shift<Btn3Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD)\
1901 PieceMenuPopup(menuW) \n \
1902 Any<Btn3Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD) \
1903 PieceMenuPopup(menuB) \n";
1905 char whiteTranslations[] = "<BtnDown>: WhiteClock()\n";
1906 char blackTranslations[] = "<BtnDown>: BlackClock()\n";
1908 char ICSInputTranslations[] =
1909 "<Key>Return: EnterKeyProc() \n";
1911 String xboardResources[] = {
1912 "*fileName*value.translations: #override\\n <Key>Return: FileNameAction()",
1913 "*question*value.translations: #override\\n <Key>Return: AskQuestionReplyAction()",
1914 "*errorpopup*translations: #override\\n <Key>Return: ErrorPopDown()",
1919 /* Max possible square size */
1920 #define MAXSQSIZE 256
1922 static int xpm_avail[MAXSQSIZE];
1924 #ifdef HAVE_DIR_STRUCT
1926 /* Extract piece size from filename */
1928 xpm_getsize(name, len, ext)
1939 if ((p=strchr(name, '.')) == NULL ||
1940 StrCaseCmp(p+1, ext) != 0)
1946 while (*p && isdigit(*p))
1953 /* Setup xpm_avail */
1955 xpm_getavail(dirname, ext)
1963 for (i=0; i<MAXSQSIZE; ++i)
1966 if (appData.debugMode)
1967 fprintf(stderr, "XPM dir:%s:ext:%s:\n", dirname, ext);
1969 dir = opendir(dirname);
1972 fprintf(stderr, _("%s: Can't access XPM directory %s\n"),
1973 programName, dirname);
1977 while ((ent=readdir(dir)) != NULL) {
1978 i = xpm_getsize(ent->d_name, NAMLEN(ent), ext);
1979 if (i > 0 && i < MAXSQSIZE)
1989 xpm_print_avail(fp, ext)
1995 fprintf(fp, _("Available `%s' sizes:\n"), ext);
1996 for (i=1; i<MAXSQSIZE; ++i) {
2002 /* Return XPM piecesize closest to size */
2004 xpm_closest_to(dirname, size, ext)
2010 int sm_diff = MAXSQSIZE;
2014 xpm_getavail(dirname, ext);
2016 if (appData.debugMode)
2017 xpm_print_avail(stderr, ext);
2019 for (i=1; i<MAXSQSIZE; ++i) {
2022 diff = (diff<0) ? -diff : diff;
2023 if (diff < sm_diff) {
2031 fprintf(stderr, _("Error: No `%s' files!\n"), ext);
2037 #else /* !HAVE_DIR_STRUCT */
2038 /* If we are on a system without a DIR struct, we can't
2039 read the directory, so we can't collect a list of
2040 filenames, etc., so we can't do any size-fitting. */
2042 xpm_closest_to(dirname, size, ext)
2047 fprintf(stderr, _("\
2048 Warning: No DIR structure found on this system --\n\
2049 Unable to autosize for XPM/XIM pieces.\n\
2050 Please report this error to frankm@hiwaay.net.\n\
2051 Include system type & operating system in message.\n"));
2054 #endif /* HAVE_DIR_STRUCT */
2056 static char *cnames[9] = { "black", "red", "green", "yellow", "blue",
2057 "magenta", "cyan", "white" };
2061 TextColors textColors[(int)NColorClasses];
2063 /* String is: "fg, bg, attr". Which is 0, 1, 2 */
2065 parse_color(str, which)
2069 char *p, buf[100], *d;
2072 if (strlen(str) > 99) /* watch bounds on buf */
2077 for (i=0; i<which; ++i) {
2084 /* Could be looking at something like:
2086 .. in which case we want to stop on a comma also */
2087 while (*p && *p != ',' && !isalpha(*p) && !isdigit(*p))
2091 return -1; /* Use default for empty field */
2094 if (which == 2 || isdigit(*p))
2097 while (*p && isalpha(*p))
2102 for (i=0; i<8; ++i) {
2103 if (!StrCaseCmp(buf, cnames[i]))
2104 return which? (i+40) : (i+30);
2106 if (!StrCaseCmp(buf, "default")) return -1;
2108 fprintf(stderr, _("%s: unrecognized color %s\n"), programName, buf);
2113 parse_cpair(cc, str)
2117 if ((textColors[(int)cc].fg=parse_color(str, 0)) == -2) {
2118 fprintf(stderr, _("%s: can't parse foreground color in `%s'\n"),
2123 /* bg and attr are optional */
2124 textColors[(int)cc].bg = parse_color(str, 1);
2125 if ((textColors[(int)cc].attr = parse_color(str, 2)) < 0) {
2126 textColors[(int)cc].attr = 0;
2132 /* Arrange to catch delete-window events */
2133 Atom wm_delete_window;
2135 CatchDeleteWindow(Widget w, String procname)
2138 XSetWMProtocols(xDisplay, XtWindow(w), &wm_delete_window, 1);
2139 sprintf(buf, "<Message>WM_PROTOCOLS: %s() \n", procname);
2140 XtAugmentTranslations(w, XtParseTranslationTable(buf));
2147 XtSetArg(args[0], XtNiconic, False);
2148 XtSetValues(shellWidget, args, 1);
2150 XtPopup(shellWidget, XtGrabNone); /* Raise if lowered */
2154 // eventually, all layout determining code should go into a subroutine, but until then IDSIZE remains undefined
2156 #define BoardSize int
2157 void InitDrawingSizes(BoardSize boardSize, int flags)
2158 { // [HGM] resize is functional now, but for board format changes only (nr of ranks, files)
2159 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
2161 XtGeometryResult gres;
2164 if(!formWidget) return;
2167 * Enable shell resizing.
2169 shellArgs[0].value = (XtArgVal) &w;
2170 shellArgs[1].value = (XtArgVal) &h;
2171 XtGetValues(shellWidget, shellArgs, 2);
2173 shellArgs[4].value = 2*w; shellArgs[2].value = 10;
2174 shellArgs[5].value = 2*h; shellArgs[3].value = 10;
2175 XtSetValues(shellWidget, &shellArgs[2], 4);
2177 XtSetArg(args[0], XtNdefaultDistance, &sep);
2178 XtGetValues(formWidget, args, 1);
2180 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2181 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2184 XtSetArg(args[0], XtNwidth, boardWidth);
2185 XtSetArg(args[1], XtNheight, boardHeight);
2186 XtSetValues(boardWidget, args, 2);
2188 timerWidth = (boardWidth - sep) / 2;
2189 XtSetArg(args[0], XtNwidth, timerWidth);
2190 XtSetValues(whiteTimerWidget, args, 1);
2191 XtSetValues(blackTimerWidget, args, 1);
2193 XawFormDoLayout(formWidget, False);
2195 if (appData.titleInWindow) {
2197 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2198 XtSetArg(args[i], XtNheight, &h); i++;
2199 XtGetValues(titleWidget, args, i);
2201 w = boardWidth - 2*bor;
2203 XtSetArg(args[0], XtNwidth, &w);
2204 XtGetValues(menuBarWidget, args, 1);
2205 w = boardWidth - w - sep - 2*bor - 2; // WIDTH_FUDGE
2208 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
2209 if (gres != XtGeometryYes && appData.debugMode) {
2211 _("%s: titleWidget geometry error %d %d %d %d %d\n"),
2212 programName, gres, w, h, wr, hr);
2216 XawFormDoLayout(formWidget, True);
2219 * Inhibit shell resizing.
2221 shellArgs[0].value = w = (XtArgVal) boardWidth + marginW;
2222 shellArgs[1].value = h = (XtArgVal) boardHeight + marginH;
2223 shellArgs[4].value = shellArgs[2].value = w;
2224 shellArgs[5].value = shellArgs[3].value = h;
2225 XtSetValues(shellWidget, &shellArgs[0], 6);
2234 int i, j, clockFontPxlSize, coordFontPxlSize, fontPxlSize;
2235 XSetWindowAttributes window_attributes;
2237 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
2238 XrmValue vFrom, vTo;
2239 XtGeometryResult gres;
2242 int forceMono = False;
2245 // [HGM] before anything else, expand any indirection files amongst options
2246 char *argvCopy[1000]; // 1000 seems enough
2247 char newArgs[10000]; // holds actual characters
2250 srandom(time(0)); // [HGM] book: make random truly random
2253 for(i=0; i<argc; i++) {
2254 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2255 //fprintf(stderr, "arg %s\n", argv[i]);
2256 if(argv[i][0] != '@') argvCopy[j++] = argv[i]; else {
2258 FILE *f = fopen(argv[i]+1, "rb");
2259 if(f == NULL) { fprintf(stderr, _("ignore %s\n"), argv[i]); continue; } // do not expand non-existing
2260 argvCopy[j++] = newArgs + k; // get ready for first argument from file
2261 while((c = fgetc(f)) != EOF) { // each line of file inserts 1 argument in the list
2263 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2264 newArgs[k++] = 0; // terminate current arg
2265 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2266 argvCopy[j++] = newArgs + k; // get ready for next
2268 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2281 if(appData.debugMode,1) { // OK, appData is not initialized here yet...
2282 for(i=0; i<argc; i++) fprintf(stderr, "argv[%2d] = '%s'\n", i, argv[i]);
2288 setbuf(stdout, NULL);
2289 setbuf(stderr, NULL);
2292 programName = strrchr(argv[0], '/');
2293 if (programName == NULL)
2294 programName = argv[0];
2299 XtSetLanguageProc(NULL, NULL, NULL);
2300 bindtextdomain(PRODUCT, LOCALEDIR);
2301 textdomain(PRODUCT);
2305 XtAppInitialize(&appContext, "XBoard", shellOptions,
2306 XtNumber(shellOptions),
2307 &argc, argv, xboardResources, NULL, 0);
2309 fprintf(stderr, _("%s: unrecognized argument %s\n"),
2310 programName, argv[1]);
2314 if ((chessDir = (char *) getenv("CHESSDIR")) == NULL) {
2317 if (chdir(chessDir) != 0) {
2318 fprintf(stderr, _("%s: can't cd to CHESSDIR: "), programName);
2325 if (p == NULL) p = "/tmp";
2326 i = strlen(p) + strlen("/.xboardXXXXXx.pgn") + 1;
2327 gameCopyFilename = (char*) malloc(i);
2328 gamePasteFilename = (char*) malloc(i);
2329 sprintf(gameCopyFilename, "%s/.xboard%05uc.pgn", p, getpid());
2330 sprintf(gamePasteFilename, "%s/.xboard%05up.pgn", p, getpid());
2332 XtGetApplicationResources(shellWidget, (XtPointer) &appData,
2333 clientResources, XtNumber(clientResources),
2336 if (appData.debugMode && appData.nameOfDebugFile && strcmp(appData.nameOfDebugFile, "stderr")) {
2337 /* [DM] debug info to file [HGM] make the filename a command-line option, and allow it to remain stderr */
2338 if ((debugFP = fopen(appData.nameOfDebugFile, "w")) == NULL) {
2339 printf(_("Failed to open file '%s'\n"), appData.nameOfDebugFile);
2342 setbuf(debugFP, NULL);
2345 /* [HGM,HR] make sure board size is acceptable */
2346 if(appData.NrFiles > BOARD_SIZE ||
2347 appData.NrRanks > BOARD_SIZE )
2348 DisplayFatalError(_("Recompile with BOARD_SIZE > 12, to support this size"), 0, 2);
2351 /* This feature does not work; animation needs a rewrite */
2352 appData.highlightDragging = FALSE;
2356 xDisplay = XtDisplay(shellWidget);
2357 xScreen = DefaultScreen(xDisplay);
2358 wm_delete_window = XInternAtom(xDisplay, "WM_DELETE_WINDOW", True);
2360 gameInfo.variant = StringToVariant(appData.variant);
2361 InitPosition(FALSE);
2364 * Determine boardSize
2366 gameInfo.boardWidth = gameInfo.boardHeight = 8; // [HGM] boardsize: make sure we start as 8x8
2369 // [HGM] as long as we have not created the possibility to change size while running, start with requested size
2370 gameInfo.boardWidth = appData.NrFiles > 0 ? appData.NrFiles : 8;
2371 gameInfo.boardHeight = appData.NrRanks > 0 ? appData.NrRanks : 8;
2372 gameInfo.holdingsWidth = appData.holdingsSize > 0 ? 2 : 0;
2377 InitDrawingSizes(-1, 0); // [HGM] initsize: make this into a subroutine
2379 if (isdigit(appData.boardSize[0])) {
2380 i = sscanf(appData.boardSize, "%d,%d,%d,%d,%d,%d,%d", &squareSize,
2381 &lineGap, &clockFontPxlSize, &coordFontPxlSize,
2382 &fontPxlSize, &smallLayout, &tinyLayout);
2384 fprintf(stderr, _("%s: bad boardSize syntax %s\n"),
2385 programName, appData.boardSize);
2389 /* Find some defaults; use the nearest known size */
2390 SizeDefaults *szd, *nearest;
2391 int distance = 99999;
2392 nearest = szd = sizeDefaults;
2393 while (szd->name != NULL) {
2394 if (abs(szd->squareSize - squareSize) < distance) {
2396 distance = abs(szd->squareSize - squareSize);
2397 if (distance == 0) break;
2401 if (i < 2) lineGap = nearest->lineGap;
2402 if (i < 3) clockFontPxlSize = nearest->clockFontPxlSize;
2403 if (i < 4) coordFontPxlSize = nearest->coordFontPxlSize;
2404 if (i < 5) fontPxlSize = nearest->fontPxlSize;
2405 if (i < 6) smallLayout = nearest->smallLayout;
2406 if (i < 7) tinyLayout = nearest->tinyLayout;
2409 SizeDefaults *szd = sizeDefaults;
2410 if (*appData.boardSize == NULLCHAR) {
2411 while (DisplayWidth(xDisplay, xScreen) < szd->minScreenSize ||
2412 DisplayHeight(xDisplay, xScreen) < szd->minScreenSize) {
2415 if (szd->name == NULL) szd--;
2417 while (szd->name != NULL &&
2418 StrCaseCmp(szd->name, appData.boardSize) != 0) szd++;
2419 if (szd->name == NULL) {
2420 fprintf(stderr, _("%s: unrecognized boardSize name %s\n"),
2421 programName, appData.boardSize);
2425 squareSize = szd->squareSize;
2426 lineGap = szd->lineGap;
2427 clockFontPxlSize = szd->clockFontPxlSize;
2428 coordFontPxlSize = szd->coordFontPxlSize;
2429 fontPxlSize = szd->fontPxlSize;
2430 smallLayout = szd->smallLayout;
2431 tinyLayout = szd->tinyLayout;
2434 /* Now, using squareSize as a hint, find a good XPM/XIM set size */
2435 if (strlen(appData.pixmapDirectory) > 0) {
2436 p = ExpandPathName(appData.pixmapDirectory);
2438 fprintf(stderr, _("Error expanding path name \"%s\"\n"),
2439 appData.pixmapDirectory);
2442 if (appData.debugMode) {
2443 fprintf(stderr, _("\
2444 XBoard square size (hint): %d\n\
2445 %s fulldir:%s:\n"), squareSize, IMAGE_EXT, p);
2447 squareSize = xpm_closest_to(p, squareSize, IMAGE_EXT);
2448 if (appData.debugMode) {
2449 fprintf(stderr, _("Closest %s size: %d\n"), IMAGE_EXT, squareSize);
2453 /* [HR] height treated separately (hacked) */
2454 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2455 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2456 if (appData.showJail == 1) {
2457 /* Jail on top and bottom */
2458 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2459 XtSetArg(boardArgs[2], XtNheight,
2460 boardHeight + 2*(lineGap + squareSize));
2461 } else if (appData.showJail == 2) {
2463 XtSetArg(boardArgs[1], XtNwidth,
2464 boardWidth + 2*(lineGap + squareSize));
2465 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2468 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2469 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2473 * Determine what fonts to use.
2475 appData.clockFont = FindFont(appData.clockFont, clockFontPxlSize);
2476 clockFontID = XLoadFont(xDisplay, appData.clockFont);
2477 clockFontStruct = XQueryFont(xDisplay, clockFontID);
2478 appData.coordFont = FindFont(appData.coordFont, coordFontPxlSize);
2479 coordFontID = XLoadFont(xDisplay, appData.coordFont);
2480 coordFontStruct = XQueryFont(xDisplay, coordFontID);
2481 appData.font = FindFont(appData.font, fontPxlSize);
2482 countFontID = XLoadFont(xDisplay, appData.coordFont); // [HGM] holdings
2483 countFontStruct = XQueryFont(xDisplay, countFontID);
2484 // appData.font = FindFont(appData.font, fontPxlSize);
2486 xdb = XtDatabase(xDisplay);
2487 XrmPutStringResource(&xdb, "*font", appData.font);
2490 * Detect if there are not enough colors available and adapt.
2492 if (DefaultDepth(xDisplay, xScreen) <= 2) {
2493 appData.monoMode = True;
2496 if (!appData.monoMode) {
2497 vFrom.addr = (caddr_t) appData.lightSquareColor;
2498 vFrom.size = strlen(appData.lightSquareColor);
2499 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2500 if (vTo.addr == NULL) {
2501 appData.monoMode = True;
2504 lightSquareColor = *(Pixel *) vTo.addr;
2507 if (!appData.monoMode) {
2508 vFrom.addr = (caddr_t) appData.darkSquareColor;
2509 vFrom.size = strlen(appData.darkSquareColor);
2510 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2511 if (vTo.addr == NULL) {
2512 appData.monoMode = True;
2515 darkSquareColor = *(Pixel *) vTo.addr;
2518 if (!appData.monoMode) {
2519 vFrom.addr = (caddr_t) appData.whitePieceColor;
2520 vFrom.size = strlen(appData.whitePieceColor);
2521 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2522 if (vTo.addr == NULL) {
2523 appData.monoMode = True;
2526 whitePieceColor = *(Pixel *) vTo.addr;
2529 if (!appData.monoMode) {
2530 vFrom.addr = (caddr_t) appData.blackPieceColor;
2531 vFrom.size = strlen(appData.blackPieceColor);
2532 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2533 if (vTo.addr == NULL) {
2534 appData.monoMode = True;
2537 blackPieceColor = *(Pixel *) vTo.addr;
2541 if (!appData.monoMode) {
2542 vFrom.addr = (caddr_t) appData.highlightSquareColor;
2543 vFrom.size = strlen(appData.highlightSquareColor);
2544 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2545 if (vTo.addr == NULL) {
2546 appData.monoMode = True;
2549 highlightSquareColor = *(Pixel *) vTo.addr;
2553 if (!appData.monoMode) {
2554 vFrom.addr = (caddr_t) appData.premoveHighlightColor;
2555 vFrom.size = strlen(appData.premoveHighlightColor);
2556 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2557 if (vTo.addr == NULL) {
2558 appData.monoMode = True;
2561 premoveHighlightColor = *(Pixel *) vTo.addr;
2566 fprintf(stderr, _("%s: too few colors available; trying monochrome mode\n"),
2570 if (appData.monoMode && appData.debugMode) {
2571 fprintf(stderr, _("white pixel = 0x%lx, black pixel = 0x%lx\n"),
2572 (unsigned long) XWhitePixel(xDisplay, xScreen),
2573 (unsigned long) XBlackPixel(xDisplay, xScreen));
2576 if (parse_cpair(ColorShout, appData.colorShout) < 0 ||
2577 parse_cpair(ColorSShout, appData.colorSShout) < 0 ||
2578 parse_cpair(ColorChannel1, appData.colorChannel1) < 0 ||
2579 parse_cpair(ColorChannel, appData.colorChannel) < 0 ||
2580 parse_cpair(ColorKibitz, appData.colorKibitz) < 0 ||
2581 parse_cpair(ColorTell, appData.colorTell) < 0 ||
2582 parse_cpair(ColorChallenge, appData.colorChallenge) < 0 ||
2583 parse_cpair(ColorRequest, appData.colorRequest) < 0 ||
2584 parse_cpair(ColorSeek, appData.colorSeek) < 0 ||
2585 parse_cpair(ColorNormal, appData.colorNormal) < 0)
2587 if (appData.colorize) {
2589 _("%s: can't parse color names; disabling colorization\n"),
2592 appData.colorize = FALSE;
2594 textColors[ColorNone].fg = textColors[ColorNone].bg = -1;
2595 textColors[ColorNone].attr = 0;
2597 XtAppAddActions(appContext, boardActions, XtNumber(boardActions));
2603 layoutName = "tinyLayout";
2604 } else if (smallLayout) {
2605 layoutName = "smallLayout";
2607 layoutName = "normalLayout";
2609 /* Outer layoutWidget is there only to provide a name for use in
2610 resources that depend on the layout style */
2612 XtCreateManagedWidget(layoutName, formWidgetClass, shellWidget,
2613 layoutArgs, XtNumber(layoutArgs));
2615 XtCreateManagedWidget("form", formWidgetClass, layoutWidget,
2616 formArgs, XtNumber(formArgs));
2617 XtSetArg(args[0], XtNdefaultDistance, &sep);
2618 XtGetValues(formWidget, args, 1);
2621 widgetList[j++] = menuBarWidget = CreateMenuBar(menuBar);
2622 XtSetArg(args[0], XtNtop, XtChainTop);
2623 XtSetArg(args[1], XtNbottom, XtChainTop);
2624 XtSetValues(menuBarWidget, args, 2);
2626 widgetList[j++] = whiteTimerWidget =
2627 XtCreateWidget("whiteTime", labelWidgetClass,
2628 formWidget, timerArgs, XtNumber(timerArgs));
2629 XtSetArg(args[0], XtNfont, clockFontStruct);
2630 XtSetArg(args[1], XtNtop, XtChainTop);
2631 XtSetArg(args[2], XtNbottom, XtChainTop);
2632 XtSetValues(whiteTimerWidget, args, 3);
2634 widgetList[j++] = blackTimerWidget =
2635 XtCreateWidget("blackTime", 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(blackTimerWidget, args, 3);
2642 if (appData.titleInWindow) {
2643 widgetList[j++] = titleWidget =
2644 XtCreateWidget("title", labelWidgetClass, formWidget,
2645 titleArgs, XtNumber(titleArgs));
2646 XtSetArg(args[0], XtNtop, XtChainTop);
2647 XtSetArg(args[1], XtNbottom, XtChainTop);
2648 XtSetValues(titleWidget, args, 2);
2651 if (appData.showButtonBar) {
2652 widgetList[j++] = buttonBarWidget = CreateButtonBar(buttonBar);
2653 XtSetArg(args[0], XtNleft, XtChainRight); // [HGM] glue to right window edge
2654 XtSetArg(args[1], XtNright, XtChainRight); // for good run-time sizing
2655 XtSetArg(args[2], XtNtop, XtChainTop);
2656 XtSetArg(args[3], XtNbottom, XtChainTop);
2657 XtSetValues(buttonBarWidget, args, 4);
2660 widgetList[j++] = messageWidget =
2661 XtCreateWidget("message", labelWidgetClass, formWidget,
2662 messageArgs, XtNumber(messageArgs));
2663 XtSetArg(args[0], XtNtop, XtChainTop);
2664 XtSetArg(args[1], XtNbottom, XtChainTop);
2665 XtSetValues(messageWidget, args, 2);
2667 widgetList[j++] = boardWidget =
2668 XtCreateWidget("board", widgetClass, formWidget, boardArgs,
2669 XtNumber(boardArgs));
2671 XtManageChildren(widgetList, j);
2673 timerWidth = (boardWidth - sep) / 2;
2674 XtSetArg(args[0], XtNwidth, timerWidth);
2675 XtSetValues(whiteTimerWidget, args, 1);
2676 XtSetValues(blackTimerWidget, args, 1);
2678 XtSetArg(args[0], XtNbackground, &timerBackgroundPixel);
2679 XtSetArg(args[1], XtNforeground, &timerForegroundPixel);
2680 XtGetValues(whiteTimerWidget, args, 2);
2682 if (appData.showButtonBar) {
2683 XtSetArg(args[0], XtNbackground, &buttonBackgroundPixel);
2684 XtSetArg(args[1], XtNforeground, &buttonForegroundPixel);
2685 XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
2689 * formWidget uses these constraints but they are stored
2693 XtSetArg(args[i], XtNfromHoriz, 0); i++;
2694 XtSetValues(menuBarWidget, args, i);
2695 if (appData.titleInWindow) {
2698 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2699 XtSetValues(whiteTimerWidget, args, i);
2701 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2702 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2703 XtSetValues(blackTimerWidget, args, i);
2705 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2706 XtSetArg(args[i], XtNjustify, XtJustifyLeft); i++;
2707 XtSetValues(titleWidget, args, i);
2709 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2710 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2711 XtSetValues(messageWidget, args, i);
2712 if (appData.showButtonBar) {
2714 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2715 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2716 XtSetValues(buttonBarWidget, args, i);
2720 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2721 XtSetValues(whiteTimerWidget, args, i);
2723 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2724 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2725 XtSetValues(blackTimerWidget, args, i);
2727 XtSetArg(args[i], XtNfromHoriz, menuBarWidget); i++;
2728 XtSetValues(titleWidget, args, i);
2730 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2731 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2732 XtSetValues(messageWidget, args, i);
2733 if (appData.showButtonBar) {
2735 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2736 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2737 XtSetValues(buttonBarWidget, args, i);
2742 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2743 XtSetValues(whiteTimerWidget, args, i);
2745 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2746 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2747 XtSetValues(blackTimerWidget, args, i);
2749 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2750 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2751 XtSetValues(messageWidget, args, i);
2752 if (appData.showButtonBar) {
2754 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2755 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2756 XtSetValues(buttonBarWidget, args, i);
2760 XtSetArg(args[0], XtNfromVert, messageWidget);
2761 XtSetArg(args[1], XtNtop, XtChainTop);
2762 XtSetArg(args[2], XtNbottom, XtChainBottom);
2763 XtSetArg(args[3], XtNleft, XtChainLeft);
2764 XtSetArg(args[4], XtNright, XtChainRight);
2765 XtSetValues(boardWidget, args, 5);
2767 XtRealizeWidget(shellWidget);
2770 * Correct the width of the message and title widgets.
2771 * It is not known why some systems need the extra fudge term.
2772 * The value "2" is probably larger than needed.
2774 XawFormDoLayout(formWidget, False);
2776 #define WIDTH_FUDGE 2
2778 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2779 XtSetArg(args[i], XtNheight, &h); i++;
2780 XtGetValues(messageWidget, args, i);
2781 if (appData.showButtonBar) {
2783 XtSetArg(args[i], XtNwidth, &w); i++;
2784 XtGetValues(buttonBarWidget, args, i);
2785 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2787 w = boardWidth - 2*bor + 1; /*!! +1 compensates for kludge below */
2790 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2791 if (gres != XtGeometryYes && appData.debugMode) {
2792 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2793 programName, gres, w, h, wr, hr);
2796 /* !! Horrible hack to work around bug in XFree86 4.0.1 (X11R6.4.3) */
2797 /* The size used for the child widget in layout lags one resize behind
2798 its true size, so we resize a second time, 1 pixel smaller. Yeech! */
2800 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2801 if (gres != XtGeometryYes && appData.debugMode) {
2802 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2803 programName, gres, w, h, wr, hr);
2806 XtSetArg(args[0], XtNleft, XtChainLeft); // [HGM] glue ends for good run-time sizing
2807 XtSetArg(args[1], XtNright, XtChainRight);
2808 XtSetValues(messageWidget, args, 2);
2810 if (appData.titleInWindow) {
2812 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2813 XtSetArg(args[i], XtNheight, &h); i++;
2814 XtGetValues(titleWidget, args, i);
2816 w = boardWidth - 2*bor;
2818 XtSetArg(args[0], XtNwidth, &w);
2819 XtGetValues(menuBarWidget, args, 1);
2820 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2823 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
2824 if (gres != XtGeometryYes && appData.debugMode) {
2826 _("%s: titleWidget geometry error %d %d %d %d %d\n"),
2827 programName, gres, w, h, wr, hr);
2830 XawFormDoLayout(formWidget, True);
2832 xBoardWindow = XtWindow(boardWidget);
2834 // [HGM] it seems the layout code ends here, but perhaps the color stuff is size independent and would
2835 // not need to go into InitDrawingSizes().
2839 * Create X checkmark bitmap and initialize option menu checks.
2841 ReadBitmap(&xMarkPixmap, "checkmark.bm",
2842 checkmark_bits, checkmark_width, checkmark_height);
2843 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
2844 if (appData.alwaysPromoteToQueen) {
2845 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
2848 if (appData.animateDragging) {
2849 XtSetValues(XtNameToWidget(menuBarWidget,
2850 "menuOptions.Animate Dragging"),
2853 if (appData.animate) {
2854 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
2857 if (appData.autoComment) {
2858 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
2861 if (appData.autoCallFlag) {
2862 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
2865 if (appData.autoFlipView) {
2866 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Auto Flip View"),
2869 if (appData.autoObserve) {
2870 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
2873 if (appData.autoRaiseBoard) {
2874 XtSetValues(XtNameToWidget(menuBarWidget,
2875 "menuOptions.Auto Raise Board"), args, 1);
2877 if (appData.autoSaveGames) {
2878 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
2881 if (appData.saveGameFile[0] != NULLCHAR) {
2882 /* Can't turn this off from menu */
2883 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
2885 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
2889 if (appData.blindfold) {
2890 XtSetValues(XtNameToWidget(menuBarWidget,
2891 "menuOptions.Blindfold"), args, 1);
2893 if (appData.flashCount > 0) {
2894 XtSetValues(XtNameToWidget(menuBarWidget,
2895 "menuOptions.Flash Moves"),
2898 if (appData.getMoveList) {
2899 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
2903 if (appData.highlightDragging) {
2904 XtSetValues(XtNameToWidget(menuBarWidget,
2905 "menuOptions.Highlight Dragging"),
2909 if (appData.highlightLastMove) {
2910 XtSetValues(XtNameToWidget(menuBarWidget,
2911 "menuOptions.Highlight Last Move"),
2914 if (appData.icsAlarm) {
2915 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.ICS Alarm"),
2918 if (appData.ringBellAfterMoves) {
2919 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
2922 if (appData.oldSaveStyle) {
2923 XtSetValues(XtNameToWidget(menuBarWidget,
2924 "menuOptions.Old Save Style"), args, 1);
2926 if (appData.periodicUpdates) {
2927 XtSetValues(XtNameToWidget(menuBarWidget,
2928 "menuOptions.Periodic Updates"), args, 1);
2930 if (appData.ponderNextMove) {
2931 XtSetValues(XtNameToWidget(menuBarWidget,
2932 "menuOptions.Ponder Next Move"), args, 1);
2934 if (appData.popupExitMessage) {
2935 XtSetValues(XtNameToWidget(menuBarWidget,
2936 "menuOptions.Popup Exit Message"), args, 1);
2938 if (appData.popupMoveErrors) {
2939 XtSetValues(XtNameToWidget(menuBarWidget,
2940 "menuOptions.Popup Move Errors"), args, 1);
2942 if (appData.premove) {
2943 XtSetValues(XtNameToWidget(menuBarWidget,
2944 "menuOptions.Premove"), args, 1);
2946 if (appData.quietPlay) {
2947 XtSetValues(XtNameToWidget(menuBarWidget,
2948 "menuOptions.Quiet Play"), args, 1);
2950 if (appData.showCoords) {
2951 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
2954 if (appData.hideThinkingFromHuman) {
2955 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
2958 if (appData.testLegality) {
2959 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Test Legality"),
2966 ReadBitmap(&wIconPixmap, "icon_white.bm",
2967 icon_white_bits, icon_white_width, icon_white_height);
2968 ReadBitmap(&bIconPixmap, "icon_black.bm",
2969 icon_black_bits, icon_black_width, icon_black_height);
2970 iconPixmap = wIconPixmap;
2972 XtSetArg(args[i], XtNiconPixmap, iconPixmap); i++;
2973 XtSetValues(shellWidget, args, i);
2976 * Create a cursor for the board widget.
2978 window_attributes.cursor = XCreateFontCursor(xDisplay, XC_hand2);
2979 XChangeWindowAttributes(xDisplay, xBoardWindow,
2980 CWCursor, &window_attributes);
2983 * Inhibit shell resizing.
2985 shellArgs[0].value = (XtArgVal) &w;
2986 shellArgs[1].value = (XtArgVal) &h;
2987 XtGetValues(shellWidget, shellArgs, 2);
2988 shellArgs[4].value = shellArgs[2].value = w;
2989 shellArgs[5].value = shellArgs[3].value = h;
2990 XtSetValues(shellWidget, &shellArgs[2], 4);
2991 marginW = w - boardWidth; // [HGM] needed to set new shellWidget size when we resize board
2992 marginH = h - boardHeight;
2994 CatchDeleteWindow(shellWidget, "QuitProc");
2999 if (appData.bitmapDirectory[0] != NULLCHAR) {
3006 /* Create regular pieces */
3007 if (!useImages) CreatePieces();
3012 if (appData.animate || appData.animateDragging)
3015 XtAugmentTranslations(formWidget,
3016 XtParseTranslationTable(globalTranslations));
3017 XtAugmentTranslations(boardWidget,
3018 XtParseTranslationTable(boardTranslations));
3019 XtAugmentTranslations(whiteTimerWidget,
3020 XtParseTranslationTable(whiteTranslations));
3021 XtAugmentTranslations(blackTimerWidget,
3022 XtParseTranslationTable(blackTranslations));
3024 /* Why is the following needed on some versions of X instead
3025 * of a translation? */
3026 XtAddEventHandler(boardWidget, ExposureMask, False,
3027 (XtEventHandler) EventProc, NULL);
3032 if (errorExitStatus == -1) {
3033 if (appData.icsActive) {
3034 /* We now wait until we see "login:" from the ICS before
3035 sending the logon script (problems with timestamp otherwise) */
3036 /*ICSInitScript();*/
3037 if (appData.icsInputBox) ICSInputBoxPopUp();
3040 signal(SIGINT, IntSigHandler);
3041 signal(SIGTERM, IntSigHandler);
3042 if (*appData.cmailGameName != NULLCHAR) {
3043 signal(SIGUSR1, CmailSigHandler);
3048 XtAppMainLoop(appContext);
3049 if (appData.debugMode) fclose(debugFP); // [DM] debug
3056 if (appData.icsActive && oldICSInteractionTitle != NULL) {
3057 DisplayIcsInteractionTitle(oldICSInteractionTitle);
3059 unlink(gameCopyFilename);
3060 unlink(gamePasteFilename);
3071 CmailSigHandler(sig)
3077 signal(SIGUSR1, SIG_IGN); /* suspend handler */
3079 /* Activate call-back function CmailSigHandlerCallBack() */
3080 OutputToProcess(cmailPR, (char *)(&dummy), sizeof(int), &error);
3082 signal(SIGUSR1, CmailSigHandler); /* re-activate handler */
3086 CmailSigHandlerCallBack(isr, closure, message, count, error)
3094 ReloadCmailMsgEvent(TRUE); /* Reload cmail msg */
3096 /**** end signal code ****/
3106 f = fopen(appData.icsLogon, "r");
3112 strcat(buf, appData.icsLogon);
3113 f = fopen(buf, "r");
3117 ProcessICSInitScript(f);
3124 EditCommentPopDown();
3135 SetMenuEnables(enab)
3139 if (!menuBarWidget) return;
3140 while (enab->name != NULL) {
3141 w = XtNameToWidget(menuBarWidget, enab->name);
3143 DisplayError(enab->name, 0);
3145 XtSetSensitive(w, enab->value);
3151 Enables icsEnables[] = {
3152 { "menuFile.Mail Move", False },
3153 { "menuFile.Reload CMail Message", False },
3154 { "menuMode.Machine Black", False },
3155 { "menuMode.Machine White", False },
3156 { "menuMode.Analysis Mode", False },
3157 { "menuMode.Analyze File", False },
3158 { "menuMode.Two Machines", False },
3160 { "menuHelp.Hint", False },
3161 { "menuHelp.Book", False },
3162 { "menuStep.Move Now", False },
3163 { "menuOptions.Periodic Updates", False },
3164 { "menuOptions.Hide Thinking", False },
3165 { "menuOptions.Ponder Next Move", False },
3170 Enables ncpEnables[] = {
3171 { "menuFile.Mail Move", False },
3172 { "menuFile.Reload CMail Message", False },
3173 { "menuMode.Machine White", False },
3174 { "menuMode.Machine Black", False },
3175 { "menuMode.Analysis Mode", False },
3176 { "menuMode.Analyze File", False },
3177 { "menuMode.Two Machines", False },
3178 { "menuMode.ICS Client", False },
3179 { "menuMode.ICS Input Box", False },
3180 { "Action", False },
3181 { "menuStep.Revert", False },
3182 { "menuStep.Move Now", False },
3183 { "menuStep.Retract Move", False },
3184 { "menuOptions.Auto Comment", False },
3185 { "menuOptions.Auto Flag", False },
3186 { "menuOptions.Auto Flip View", False },
3187 { "menuOptions.Auto Observe", False },
3188 { "menuOptions.Auto Raise Board", False },
3189 { "menuOptions.Get Move List", False },
3190 { "menuOptions.ICS Alarm", False },
3191 { "menuOptions.Move Sound", False },
3192 { "menuOptions.Quiet Play", False },
3193 { "menuOptions.Hide Thinking", False },
3194 { "menuOptions.Periodic Updates", False },
3195 { "menuOptions.Ponder Next Move", False },
3196 { "menuHelp.Hint", False },
3197 { "menuHelp.Book", False },
3201 Enables gnuEnables[] = {
3202 { "menuMode.ICS Client", False },
3203 { "menuMode.ICS Input Box", False },
3204 { "menuAction.Accept", False },
3205 { "menuAction.Decline", False },
3206 { "menuAction.Rematch", False },
3207 { "menuAction.Adjourn", False },
3208 { "menuAction.Stop Examining", False },
3209 { "menuAction.Stop Observing", False },
3210 { "menuStep.Revert", False },
3211 { "menuOptions.Auto Comment", False },
3212 { "menuOptions.Auto Observe", False },
3213 { "menuOptions.Auto Raise Board", False },
3214 { "menuOptions.Get Move List", False },
3215 { "menuOptions.Premove", False },
3216 { "menuOptions.Quiet Play", False },
3218 /* The next two options rely on SetCmailMode being called *after* */
3219 /* SetGNUMode so that when GNU is being used to give hints these */
3220 /* menu options are still available */
3222 { "menuFile.Mail Move", False },
3223 { "menuFile.Reload CMail Message", False },
3227 Enables cmailEnables[] = {
3229 { "menuAction.Call Flag", False },
3230 { "menuAction.Draw", True },
3231 { "menuAction.Adjourn", False },
3232 { "menuAction.Abort", False },
3233 { "menuAction.Stop Observing", False },
3234 { "menuAction.Stop Examining", False },
3235 { "menuFile.Mail Move", True },
3236 { "menuFile.Reload CMail Message", True },
3240 Enables trainingOnEnables[] = {
3241 { "menuMode.Edit Comment", False },
3242 { "menuMode.Pause", False },
3243 { "menuStep.Forward", False },
3244 { "menuStep.Backward", False },
3245 { "menuStep.Forward to End", False },
3246 { "menuStep.Back to Start", False },
3247 { "menuStep.Move Now", False },
3248 { "menuStep.Truncate Game", False },
3252 Enables trainingOffEnables[] = {
3253 { "menuMode.Edit Comment", True },
3254 { "menuMode.Pause", True },
3255 { "menuStep.Forward", True },
3256 { "menuStep.Backward", True },
3257 { "menuStep.Forward to End", True },
3258 { "menuStep.Back to Start", True },
3259 { "menuStep.Move Now", True },
3260 { "menuStep.Truncate Game", True },
3264 Enables machineThinkingEnables[] = {
3265 { "menuFile.Load Game", False },
3266 { "menuFile.Load Next Game", False },
3267 { "menuFile.Load Previous Game", False },
3268 { "menuFile.Reload Same Game", False },
3269 { "menuFile.Paste Game", False },
3270 { "menuFile.Load Position", False },
3271 { "menuFile.Load Next Position", False },
3272 { "menuFile.Load Previous Position", False },
3273 { "menuFile.Reload Same Position", False },
3274 { "menuFile.Paste Position", False },
3275 { "menuMode.Machine White", False },
3276 { "menuMode.Machine Black", False },
3277 { "menuMode.Two Machines", False },
3278 { "menuStep.Retract Move", False },
3282 Enables userThinkingEnables[] = {
3283 { "menuFile.Load Game", True },
3284 { "menuFile.Load Next Game", True },
3285 { "menuFile.Load Previous Game", True },
3286 { "menuFile.Reload Same Game", True },
3287 { "menuFile.Paste Game", True },
3288 { "menuFile.Load Position", True },
3289 { "menuFile.Load Next Position", True },
3290 { "menuFile.Load Previous Position", True },
3291 { "menuFile.Reload Same Position", True },
3292 { "menuFile.Paste Position", True },
3293 { "menuMode.Machine White", True },
3294 { "menuMode.Machine Black", True },
3295 { "menuMode.Two Machines", True },
3296 { "menuStep.Retract Move", True },
3302 SetMenuEnables(icsEnables);
3305 if (appData.zippyPlay && !appData.noChessProgram) /* [DM] icsEngineAnalyze */
3306 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Analysis Mode"), True);
3313 SetMenuEnables(ncpEnables);
3319 SetMenuEnables(gnuEnables);
3325 SetMenuEnables(cmailEnables);
3331 SetMenuEnables(trainingOnEnables);
3332 if (appData.showButtonBar) {
3333 XtSetSensitive(buttonBarWidget, False);
3339 SetTrainingModeOff()
3341 SetMenuEnables(trainingOffEnables);
3342 if (appData.showButtonBar) {
3343 XtSetSensitive(buttonBarWidget, True);
3348 SetUserThinkingEnables()
3350 if (appData.noChessProgram) return;
3351 SetMenuEnables(userThinkingEnables);
3355 SetMachineThinkingEnables()
3357 if (appData.noChessProgram) return;
3358 SetMenuEnables(machineThinkingEnables);
3360 case MachinePlaysBlack:
3361 case MachinePlaysWhite:
3362 case TwoMachinesPlay:
3363 XtSetSensitive(XtNameToWidget(menuBarWidget,
3364 ModeToWidgetName(gameMode)), True);
3371 #define Abs(n) ((n)<0 ? -(n) : (n))
3374 * Find a font that matches "pattern" that is as close as
3375 * possible to the targetPxlSize. Prefer fonts that are k
3376 * pixels smaller to fonts that are k pixels larger. The
3377 * pattern must be in the X Consortium standard format,
3378 * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".
3379 * The return value should be freed with XtFree when no
3382 char *FindFont(pattern, targetPxlSize)
3386 char **fonts, *p, *best, *scalable, *scalableTail;
3387 int i, j, nfonts, minerr, err, pxlSize;
3390 char **missing_list;
3392 char *def_string, *base_fnt_lst, strInt[3];
3394 XFontStruct **fnt_list;
3396 base_fnt_lst = calloc(1, strlen(pattern) + 3);
3397 sprintf(strInt, "%d", targetPxlSize);
3398 p = strstr(pattern, "--");
3399 strncpy(base_fnt_lst, pattern, p - pattern + 2);
3400 strcat(base_fnt_lst, strInt);
3401 strcat(base_fnt_lst, strchr(p + 2, '-'));
3403 if ((fntSet = XCreateFontSet(xDisplay,
3407 &def_string)) == NULL) {
3409 fprintf(stderr, _("Unable to create font set.\n"));
3413 nfonts = XFontsOfFontSet(fntSet, &fnt_list, &fonts);
3415 fonts = XListFonts(xDisplay, pattern, 999999, &nfonts);
3417 fprintf(stderr, _("%s: no fonts match pattern %s\n"),
3418 programName, pattern);
3426 for (i=0; i<nfonts; i++) {
3429 if (*p != '-') continue;
3431 if (*p == NULLCHAR) break;
3432 if (*p++ == '-') j++;
3434 if (j < 7) continue;
3437 scalable = fonts[i];
3440 err = pxlSize - targetPxlSize;
3441 if (Abs(err) < Abs(minerr) ||
3442 (minerr > 0 && err < 0 && -err == minerr)) {
3448 if (scalable && Abs(minerr) > appData.fontSizeTolerance) {
3449 /* If the error is too big and there is a scalable font,
3450 use the scalable font. */
3451 int headlen = scalableTail - scalable;
3452 p = (char *) XtMalloc(strlen(scalable) + 10);
3453 while (isdigit(*scalableTail)) scalableTail++;
3454 sprintf(p, "%.*s%d%s", headlen, scalable, targetPxlSize, scalableTail);
3456 p = (char *) XtMalloc(strlen(best) + 1);
3459 if (appData.debugMode) {
3460 fprintf(debugFP, _("resolved %s at pixel size %d\n to %s\n"),
3461 pattern, targetPxlSize, p);
3464 if (missing_count > 0)
3465 XFreeStringList(missing_list);
3466 XFreeFontSet(xDisplay, fntSet);
3468 XFreeFontNames(fonts);
3475 XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
3476 | GCBackground | GCFunction | GCPlaneMask;
3477 XGCValues gc_values;
3480 gc_values.plane_mask = AllPlanes;
3481 gc_values.line_width = lineGap;
3482 gc_values.line_style = LineSolid;
3483 gc_values.function = GXcopy;
3485 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3486 gc_values.background = XBlackPixel(xDisplay, xScreen);
3487 lineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3489 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3490 gc_values.background = XWhitePixel(xDisplay, xScreen);
3491 coordGC = XtGetGC(shellWidget, value_mask, &gc_values);
3492 XSetFont(xDisplay, coordGC, coordFontID);
3494 // [HGM] make font for holdings counts (white on black0
3495 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3496 gc_values.background = XBlackPixel(xDisplay, xScreen);
3497 countGC = XtGetGC(shellWidget, value_mask, &gc_values);
3498 XSetFont(xDisplay, countGC, countFontID);
3500 if (appData.monoMode) {
3501 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3502 gc_values.background = XWhitePixel(xDisplay, xScreen);
3503 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3505 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3506 gc_values.background = XBlackPixel(xDisplay, xScreen);
3507 lightSquareGC = wbPieceGC
3508 = XtGetGC(shellWidget, value_mask, &gc_values);
3510 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3511 gc_values.background = XWhitePixel(xDisplay, xScreen);
3512 darkSquareGC = bwPieceGC
3513 = XtGetGC(shellWidget, value_mask, &gc_values);
3515 if (DefaultDepth(xDisplay, xScreen) == 1) {
3516 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
3517 gc_values.function = GXcopyInverted;
3518 copyInvertedGC = XtGetGC(shellWidget, value_mask, &gc_values);
3519 gc_values.function = GXcopy;
3520 if (XBlackPixel(xDisplay, xScreen) == 1) {
3521 bwPieceGC = darkSquareGC;
3522 wbPieceGC = copyInvertedGC;
3524 bwPieceGC = copyInvertedGC;
3525 wbPieceGC = lightSquareGC;
3529 gc_values.foreground = highlightSquareColor;
3530 gc_values.background = highlightSquareColor;
3531 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3533 gc_values.foreground = premoveHighlightColor;
3534 gc_values.background = premoveHighlightColor;
3535 prelineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3537 gc_values.foreground = lightSquareColor;
3538 gc_values.background = darkSquareColor;
3539 lightSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3541 gc_values.foreground = darkSquareColor;
3542 gc_values.background = lightSquareColor;
3543 darkSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3545 gc_values.foreground = jailSquareColor;
3546 gc_values.background = jailSquareColor;
3547 jailSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3549 gc_values.foreground = whitePieceColor;
3550 gc_values.background = darkSquareColor;
3551 wdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3553 gc_values.foreground = whitePieceColor;
3554 gc_values.background = lightSquareColor;
3555 wlPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3557 gc_values.foreground = whitePieceColor;
3558 gc_values.background = jailSquareColor;
3559 wjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3561 gc_values.foreground = blackPieceColor;
3562 gc_values.background = darkSquareColor;
3563 bdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3565 gc_values.foreground = blackPieceColor;
3566 gc_values.background = lightSquareColor;
3567 blPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3569 gc_values.foreground = blackPieceColor;
3570 gc_values.background = jailSquareColor;
3571 bjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3575 void loadXIM(xim, xmask, filename, dest, mask)
3588 fp = fopen(filename, "rb");
3590 fprintf(stderr, _("%s: error loading XIM!\n"), programName);
3597 for (y=0; y<h; ++y) {
3598 for (x=0; x<h; ++x) {
3603 XPutPixel(xim, x, y, blackPieceColor);
3605 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3608 XPutPixel(xim, x, y, darkSquareColor);
3610 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3613 XPutPixel(xim, x, y, whitePieceColor);
3615 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3618 XPutPixel(xim, x, y, lightSquareColor);
3620 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3626 /* create Pixmap of piece */
3627 *dest = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3629 XPutImage(xDisplay, *dest, lightSquareGC, xim,
3632 /* create Pixmap of clipmask
3633 Note: We assume the white/black pieces have the same
3634 outline, so we make only 6 masks. This is okay
3635 since the XPM clipmask routines do the same. */
3637 temp = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3639 XPutImage(xDisplay, temp, lightSquareGC, xmask,
3642 /* now create the 1-bit version */
3643 *mask = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3646 values.foreground = 1;
3647 values.background = 0;
3649 /* Don't use XtGetGC, not read only */
3650 maskGC = XCreateGC(xDisplay, *mask,
3651 GCForeground | GCBackground, &values);
3652 XCopyPlane(xDisplay, temp, *mask, maskGC,
3653 0, 0, squareSize, squareSize, 0, 0, 1);
3654 XFreePixmap(xDisplay, temp);
3658 void CreateXIMPieces()
3663 static char *ximkind[] = { "ll", "ld", "dl", "dd" };
3668 /* The XSynchronize calls were copied from CreatePieces.
3669 Not sure if needed, but can't hurt */
3670 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3673 /* temp needed by loadXIM() */
3674 ximtemp = XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3675 0, 0, ss, ss, AllPlanes, XYPixmap);
3677 if (strlen(appData.pixmapDirectory) == 0) {
3681 if (appData.monoMode) {
3682 DisplayFatalError(_("XIM pieces cannot be used in monochrome mode"),
3686 fprintf(stderr, _("\nLoading XIMs...\n"));
3688 for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
3689 fprintf(stderr, "%d", piece+1);
3690 for (kind=0; kind<4; kind++) {
3691 fprintf(stderr, ".");
3692 sprintf(buf, "%s/%c%s%u.xim",
3693 ExpandPathName(appData.pixmapDirectory),
3694 ToLower(PieceToChar((ChessSquare)piece)),
3696 ximPieceBitmap[kind][piece] =
3697 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3698 0, 0, ss, ss, AllPlanes, XYPixmap);
3699 if (appData.debugMode)
3700 fprintf(stderr, _("(File:%s:) "), buf);
3701 loadXIM(ximPieceBitmap[kind][piece],
3703 &(xpmPieceBitmap[kind][piece]),
3704 &(ximMaskPm[piece%(int)BlackPawn]));
3706 fprintf(stderr," ");
3708 /* Load light and dark squares */
3709 /* If the LSQ and DSQ pieces don't exist, we will
3710 draw them with solid squares. */
3711 sprintf(buf, "%s/lsq%u.xim", ExpandPathName(appData.pixmapDirectory), ss);
3712 if (access(buf, 0) != 0) {
3716 fprintf(stderr, _("light square "));
3718 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3719 0, 0, ss, ss, AllPlanes, XYPixmap);
3720 if (appData.debugMode)
3721 fprintf(stderr, _("(File:%s:) "), buf);
3723 loadXIM(ximLightSquare, NULL, buf, &xpmLightSquare, NULL);
3724 fprintf(stderr, _("dark square "));
3725 sprintf(buf, "%s/dsq%u.xim",
3726 ExpandPathName(appData.pixmapDirectory), ss);
3727 if (appData.debugMode)
3728 fprintf(stderr, _("(File:%s:) "), buf);
3730 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3731 0, 0, ss, ss, AllPlanes, XYPixmap);
3732 loadXIM(ximDarkSquare, NULL, buf, &xpmDarkSquare, NULL);
3733 xpmJailSquare = xpmLightSquare;
3735 fprintf(stderr, _("Done.\n"));
3737 XSynchronize(xDisplay, False); /* Work-around for xlib/xt buffering bug */
3741 void CreateXPMPieces()
3745 u_int ss = squareSize;
3747 static char *xpmkind[] = { "ll", "ld", "dl", "dd" };
3748 XpmColorSymbol symbols[4];
3751 /* Apparently some versions of Xpm don't define XpmFormat at all --tpm */
3752 if (appData.debugMode) {
3753 fprintf(stderr, "XPM Library Version: %d.%d%c\n",
3754 XpmFormat, XpmVersion, (char)('a' + XpmRevision - 1));
3758 /* The XSynchronize calls were copied from CreatePieces.
3759 Not sure if needed, but can't hurt */
3760 XSynchronize(xDisplay, True); /* Work-around for xlib/xt buffering bug */
3762 /* Setup translations so piece colors match square colors */
3763 symbols[0].name = "light_piece";
3764 symbols[0].value = appData.whitePieceColor;
3765 symbols[1].name = "dark_piece";
3766 symbols[1].value = appData.blackPieceColor;
3767 symbols[2].name = "light_square";
3768 symbols[2].value = appData.lightSquareColor;
3769 symbols[3].name = "dark_square";
3770 symbols[3].value = appData.darkSquareColor;
3772 attr.valuemask = XpmColorSymbols;
3773 attr.colorsymbols = symbols;
3774 attr.numsymbols = 4;
3776 if (appData.monoMode) {
3777 DisplayFatalError(_("XPM pieces cannot be used in monochrome mode"),
3781 if (strlen(appData.pixmapDirectory) == 0) {
3782 XpmPieces* pieces = builtInXpms;
3785 while (pieces->size != squareSize && pieces->size) pieces++;
3786 if (!pieces->size) {
3787 fprintf(stderr, _("No builtin XPM pieces of size %d\n"), squareSize);
3790 for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
3791 for (kind=0; kind<4; kind++) {
3793 if ((r=XpmCreatePixmapFromData(xDisplay, xBoardWindow,
3794 pieces->xpm[piece][kind],
3795 &(xpmPieceBitmap[kind][piece]),
3796 NULL, &attr)) != 0) {
3797 fprintf(stderr, _("Error %d loading XPM image \"%s\"\n"),
3804 xpmJailSquare = xpmLightSquare;
3808 fprintf(stderr, _("\nLoading XPMs...\n"));
3811 for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
3812 fprintf(stderr, "%d ", piece+1);
3813 for (kind=0; kind<4; kind++) {
3814 sprintf(buf, "%s/%c%s%u.xpm",
3815 ExpandPathName(appData.pixmapDirectory),
3816 ToLower(PieceToChar((ChessSquare)piece)),
3818 if (appData.debugMode) {
3819 fprintf(stderr, _("(File:%s:) "), buf);
3821 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3822 &(xpmPieceBitmap[kind][piece]),
3823 NULL, &attr)) != 0) {
3824 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"),
3830 /* Load light and dark squares */
3831 /* If the LSQ and DSQ pieces don't exist, we will
3832 draw them with solid squares. */
3833 fprintf(stderr, _("light square "));
3834 sprintf(buf, "%s/lsq%u.xpm", ExpandPathName(appData.pixmapDirectory), ss);
3835 if (access(buf, 0) != 0) {
3839 if (appData.debugMode)
3840 fprintf(stderr, _("(File:%s:) "), buf);
3842 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3843 &xpmLightSquare, NULL, &attr)) != 0) {
3844 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
3847 fprintf(stderr, _("dark square "));
3848 sprintf(buf, "%s/dsq%u.xpm",
3849 ExpandPathName(appData.pixmapDirectory), ss);
3850 if (appData.debugMode) {
3851 fprintf(stderr, _("(File:%s:) "), buf);
3853 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3854 &xpmDarkSquare, NULL, &attr)) != 0) {
3855 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
3859 xpmJailSquare = xpmLightSquare;
3860 fprintf(stderr, _("Done.\n"));
3862 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3865 #endif /* HAVE_LIBXPM */
3868 /* No built-in bitmaps */
3873 u_int ss = squareSize;
3875 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3878 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
3879 for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
3880 sprintf(buf, "%c%u%c.bm", ToLower(PieceToChar((ChessSquare)piece)),
3881 ss, kind == SOLID ? 's' : 'o');
3882 ReadBitmap(&pieceBitmap[kind][piece], buf, NULL, ss, ss);
3886 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3890 /* With built-in bitmaps */
3893 BuiltInBits* bib = builtInBits;
3896 u_int ss = squareSize;
3898 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3901 while (bib->squareSize != ss && bib->squareSize != 0) bib++;
3903 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
3904 for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
3905 sprintf(buf, "%c%u%c.bm", ToLower(PieceToChar((ChessSquare)piece)),
3906 ss, kind == SOLID ? 's' : 'o');
3907 ReadBitmap(&pieceBitmap[kind][piece], buf,
3908 bib->bits[kind][piece], ss, ss);
3912 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3917 void ReadBitmap(pm, name, bits, wreq, hreq)
3920 unsigned char bits[];
3926 char msg[MSG_SIZ], fullname[MSG_SIZ];
3928 if (*appData.bitmapDirectory != NULLCHAR) {
3929 strcpy(fullname, appData.bitmapDirectory);
3930 strcat(fullname, "/");
3931 strcat(fullname, name);
3932 errcode = XReadBitmapFile(xDisplay, xBoardWindow, fullname,
3933 &w, &h, pm, &x_hot, &y_hot);
3934 if (errcode != BitmapSuccess) {
3936 case BitmapOpenFailed:
3937 sprintf(msg, _("Can't open bitmap file %s"), fullname);
3939 case BitmapFileInvalid:
3940 sprintf(msg, _("Invalid bitmap in file %s"), fullname);
3942 case BitmapNoMemory:
3943 sprintf(msg, _("Ran out of memory reading bitmap file %s"),
3947 sprintf(msg, _("Unknown XReadBitmapFile error %d on file %s"),
3951 fprintf(stderr, _("%s: %s...using built-in\n"),
3953 } else if (w != wreq || h != hreq) {
3955 _("%s: Bitmap %s is %dx%d, not %dx%d...using built-in\n"),
3956 programName, fullname, w, h, wreq, hreq);
3963 fprintf(stderr, _("%s: No built-in bitmap for %s; giving up\n"),
3967 ; // [HGM] bitmaps: make it non-fatal if we have no bitmap;
3969 *pm = XCreateBitmapFromData(xDisplay, xBoardWindow, (char *) bits,
3978 if (lineGap == 0) return;
3980 /* [HR] Split this into 2 loops for non-square boards. */
3982 for (i = 0; i < BOARD_HEIGHT + 1; i++) {
3983 gridSegments[i].x1 = 0;
3984 gridSegments[i].x2 =
3985 lineGap + BOARD_WIDTH * (squareSize + lineGap);
3986 gridSegments[i].y1 = gridSegments[i].y2
3987 = lineGap / 2 + (i * (squareSize + lineGap));
3990 for (j = 0; j < BOARD_WIDTH + 1; j++) {
3991 gridSegments[j + i].y1 = 0;
3992 gridSegments[j + i].y2 =
3993 lineGap + BOARD_HEIGHT * (squareSize + lineGap);
3994 gridSegments[j + i].x1 = gridSegments[j + i].x2
3995 = lineGap / 2 + (j * (squareSize + lineGap));
3999 static void MenuBarSelect(w, addr, index)
4004 XtActionProc proc = (XtActionProc) addr;
4006 (proc)(NULL, NULL, NULL, NULL);
4009 void CreateMenuBarPopup(parent, name, mb)
4019 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
4022 XtSetArg(args[j], XtNleftMargin, 20); j++;
4023 XtSetArg(args[j], XtNrightMargin, 20); j++;
4025 while (mi->string != NULL) {
4026 if (strcmp(mi->string, "----") == 0) {
4027 entry = XtCreateManagedWidget(mi->string, smeLineObjectClass,
4030 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string)));
4031 entry = XtCreateManagedWidget(mi->string, smeBSBObjectClass,
4033 XtAddCallback(entry, XtNcallback,
4034 (XtCallbackProc) MenuBarSelect,
4035 (caddr_t) mi->proc);
4041 Widget CreateMenuBar(mb)
4045 Widget anchor, menuBar;
4047 char menuName[MSG_SIZ];
4050 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
4051 XtSetArg(args[j], XtNvSpace, 0); j++;
4052 XtSetArg(args[j], XtNborderWidth, 0); j++;
4053 menuBar = XtCreateWidget("menuBar", boxWidgetClass,
4054 formWidget, args, j);
4056 while (mb->name != NULL) {
4057 strcpy(menuName, "menu");
4058 strcat(menuName, mb->name);
4060 XtSetArg(args[j], XtNmenuName, XtNewString(menuName)); j++;
4063 shortName[0] = _(mb->name)[0];
4064 shortName[1] = NULLCHAR;
4065 XtSetArg(args[j], XtNlabel, XtNewString(shortName)); j++;
4068 XtSetArg(args[j], XtNlabel, XtNewString(_(mb->name))); j++;
4071 XtSetArg(args[j], XtNborderWidth, 0); j++;
4072 anchor = XtCreateManagedWidget(mb->name, menuButtonWidgetClass,
4074 CreateMenuBarPopup(menuBar, menuName, mb);
4080 Widget CreateButtonBar(mi)
4084 Widget button, buttonBar;
4088 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
4090 XtSetArg(args[j], XtNhSpace, 0); j++;
4092 XtSetArg(args[j], XtNborderWidth, 0); j++;
4093 XtSetArg(args[j], XtNvSpace, 0); j++;
4094 buttonBar = XtCreateWidget("buttonBar", boxWidgetClass,
4095 formWidget, args, j);
4097 while (mi->string != NULL) {
4100 XtSetArg(args[j], XtNinternalWidth, 2); j++;
4101 XtSetArg(args[j], XtNborderWidth, 0); j++;
4103 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string))); j++;
4104 button = XtCreateManagedWidget(mi->string, commandWidgetClass,
4105 buttonBar, args, j);
4106 XtAddCallback(button, XtNcallback,
4107 (XtCallbackProc) MenuBarSelect,
4108 (caddr_t) mi->proc);
4115 CreatePieceMenu(name, color)
4122 ChessSquare selection;
4124 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
4125 boardWidget, args, 0);
4127 for (i = 0; i < PIECE_MENU_SIZE; i++) {
4128 String item = pieceMenuStrings[color][i];
4130 if (strcmp(item, "----") == 0) {
4131 entry = XtCreateManagedWidget(item, smeLineObjectClass,
4134 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
4135 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
4137 selection = pieceMenuTranslation[color][i];
4138 XtAddCallback(entry, XtNcallback,
4139 (XtCallbackProc) PieceMenuSelect,
4140 (caddr_t) selection);
4141 if (selection == WhitePawn || selection == BlackPawn) {
4142 XtSetArg(args[0], XtNpopupOnEntry, entry);
4143 XtSetValues(menu, args, 1);
4156 ChessSquare selection;
4158 whitePieceMenu = CreatePieceMenu("menuW", 0);
4159 blackPieceMenu = CreatePieceMenu("menuB", 1);
4161 XtRegisterGrabAction(PieceMenuPopup, True,
4162 (unsigned)(ButtonPressMask|ButtonReleaseMask),
4163 GrabModeAsync, GrabModeAsync);
4165 XtSetArg(args[0], XtNlabel, _("Drop"));
4166 dropMenu = XtCreatePopupShell("menuD", simpleMenuWidgetClass,
4167 boardWidget, args, 1);
4168 for (i = 0; i < DROP_MENU_SIZE; i++) {
4169 String item = dropMenuStrings[i];
4171 if (strcmp(item, "----") == 0) {
4172 entry = XtCreateManagedWidget(item, smeLineObjectClass,
4175 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
4176 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
4178 selection = dropMenuTranslation[i];
4179 XtAddCallback(entry, XtNcallback,
4180 (XtCallbackProc) DropMenuSelect,
4181 (caddr_t) selection);
4186 void SetupDropMenu()
4194 for (i=0; i<sizeof(dmEnables)/sizeof(DropMenuEnables); i++) {
4195 entry = XtNameToWidget(dropMenu, dmEnables[i].widget);
4196 p = strchr(gameMode == IcsPlayingWhite ? white_holding : black_holding,
4197 dmEnables[i].piece);
4198 XtSetSensitive(entry, p != NULL || !appData.testLegality
4199 /*!!temp:*/ || (gameInfo.variant == VariantCrazyhouse
4200 && !appData.icsActive));
4202 while (p && *p++ == dmEnables[i].piece) count++;
4203 sprintf(label, "%s %d", dmEnables[i].widget, count);
4205 XtSetArg(args[j], XtNlabel, label); j++;
4206 XtSetValues(entry, args, j);
4210 void PieceMenuPopup(w, event, params, num_params)
4214 Cardinal *num_params;
4217 if (event->type != ButtonPress) return;
4218 if (errorUp) ErrorPopDown();
4222 whichMenu = params[0];
4224 case IcsPlayingWhite:
4225 case IcsPlayingBlack:
4227 case MachinePlaysWhite:
4228 case MachinePlaysBlack:
4229 if (appData.testLegality &&
4230 gameInfo.variant != VariantBughouse &&
4231 gameInfo.variant != VariantCrazyhouse) return;
4233 whichMenu = "menuD";
4239 if (((pmFromX = EventToSquare(event->xbutton.x, BOARD_WIDTH)) < 0) ||
4240 ((pmFromY = EventToSquare(event->xbutton.y, BOARD_HEIGHT)) < 0)) {
4241 pmFromX = pmFromY = -1;
4245 pmFromX = BOARD_WIDTH - 1 - pmFromX;
4247 pmFromY = BOARD_HEIGHT - 1 - pmFromY;
4249 XtPopupSpringLoaded(XtNameToWidget(boardWidget, whichMenu));
4252 static void PieceMenuSelect(w, piece, junk)
4257 if (pmFromX < 0 || pmFromY < 0) return;
4258 EditPositionMenuEvent(piece, pmFromX, pmFromY);
4261 static void DropMenuSelect(w, piece, junk)
4266 if (pmFromX < 0 || pmFromY < 0) return;
4267 DropMenuEvent(piece, pmFromX, pmFromY);
4270 void WhiteClock(w, event, prms, nprms)
4276 if (gameMode == EditPosition || gameMode == IcsExamining) {
4277 SetWhiteToPlayEvent();
4278 } else if (gameMode == IcsPlayingBlack || gameMode == MachinePlaysWhite) {
4283 void BlackClock(w, event, prms, nprms)
4289 if (gameMode == EditPosition || gameMode == IcsExamining) {
4290 SetBlackToPlayEvent();
4291 } else if (gameMode == IcsPlayingWhite || gameMode == MachinePlaysBlack) {
4298 * If the user selects on a border boundary, return -1; if off the board,
4299 * return -2. Otherwise map the event coordinate to the square.
4301 int EventToSquare(x, limit)
4309 if ((x % (squareSize + lineGap)) >= squareSize)
4311 x /= (squareSize + lineGap);
4317 static void do_flash_delay(msec)
4323 static void drawHighlight(file, rank, gc)
4329 if (lineGap == 0 || appData.blindfold) return;
4332 x = lineGap/2 + ((BOARD_WIDTH-1)-file) *
4333 (squareSize + lineGap);
4334 y = lineGap/2 + rank * (squareSize + lineGap);
4336 x = lineGap/2 + file * (squareSize + lineGap);
4337 y = lineGap/2 + ((BOARD_HEIGHT-1)-rank) *
4338 (squareSize + lineGap);
4341 XDrawRectangle(xDisplay, xBoardWindow, gc, x, y,
4342 squareSize+lineGap, squareSize+lineGap);
4345 int hi1X = -1, hi1Y = -1, hi2X = -1, hi2Y = -1;
4346 int pm1X = -1, pm1Y = -1, pm2X = -1, pm2Y = -1;
4349 SetHighlights(fromX, fromY, toX, toY)
4350 int fromX, fromY, toX, toY;
4352 if (hi1X != fromX || hi1Y != fromY) {
4353 if (hi1X >= 0 && hi1Y >= 0) {
4354 drawHighlight(hi1X, hi1Y, lineGC);
4356 if (fromX >= 0 && fromY >= 0) {
4357 drawHighlight(fromX, fromY, highlineGC);
4360 if (hi2X != toX || hi2Y != toY) {
4361 if (hi2X >= 0 && hi2Y >= 0) {
4362 drawHighlight(hi2X, hi2Y, lineGC);
4364 if (toX >= 0 && toY >= 0) {
4365 drawHighlight(toX, toY, highlineGC);
4377 SetHighlights(-1, -1, -1, -1);
4382 SetPremoveHighlights(fromX, fromY, toX, toY)
4383 int fromX, fromY, toX, toY;
4385 if (pm1X != fromX || pm1Y != fromY) {
4386 if (pm1X >= 0 && pm1Y >= 0) {
4387 drawHighlight(pm1X, pm1Y, lineGC);
4389 if (fromX >= 0 && fromY >= 0) {
4390 drawHighlight(fromX, fromY, prelineGC);
4393 if (pm2X != toX || pm2Y != toY) {
4394 if (pm2X >= 0 && pm2Y >= 0) {
4395 drawHighlight(pm2X, pm2Y, lineGC);
4397 if (toX >= 0 && toY >= 0) {
4398 drawHighlight(toX, toY, prelineGC);
4408 ClearPremoveHighlights()
4410 SetPremoveHighlights(-1, -1, -1, -1);
4413 static void BlankSquare(x, y, color, piece, dest)
4418 if (useImages && useImageSqs) {
4422 pm = xpmLightSquare;
4427 case 2: /* neutral */
4432 XCopyArea(xDisplay, pm, dest, wlPieceGC, 0, 0,
4433 squareSize, squareSize, x, y);
4443 case 2: /* neutral */
4448 XFillRectangle(xDisplay, dest, gc, x, y, squareSize, squareSize);
4453 I split out the routines to draw a piece so that I could
4454 make a generic flash routine.
4456 static void monoDrawPiece_1bit(piece, square_color, x, y, dest)
4458 int square_color, x, y;
4461 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
4462 switch (square_color) {
4464 case 2: /* neutral */
4466 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
4467 ? *pieceToOutline(piece)
4468 : *pieceToSolid(piece),
4469 dest, bwPieceGC, 0, 0,
4470 squareSize, squareSize, x, y);
4473 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
4474 ? *pieceToSolid(piece)
4475 : *pieceToOutline(piece),
4476 dest, wbPieceGC, 0, 0,
4477 squareSize, squareSize, x, y);
4482 static void monoDrawPiece(piece, square_color, x, y, dest)
4484 int square_color, x, y;
4487 switch (square_color) {
4489 case 2: /* neutral */
4491 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
4492 ? *pieceToOutline(piece)
4493 : *pieceToSolid(piece),
4494 dest, bwPieceGC, 0, 0,
4495 squareSize, squareSize, x, y, 1);
4498 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
4499 ? *pieceToSolid(piece)
4500 : *pieceToOutline(piece),
4501 dest, wbPieceGC, 0, 0,
4502 squareSize, squareSize, x, y, 1);
4507 static void colorDrawPiece(piece, square_color, x, y, dest)
4509 int square_color, x, y;
4512 if(pieceToSolid(piece) == NULL) return; // [HGM] bitmaps: make it non-fatal if we have no bitmap;
4513 switch (square_color) {
4515 XCopyPlane(xDisplay, *pieceToSolid(piece),
4516 dest, (int) piece < (int) BlackPawn
4517 ? wlPieceGC : blPieceGC, 0, 0,
4518 squareSize, squareSize, x, y, 1);
4521 XCopyPlane(xDisplay, *pieceToSolid(piece),
4522 dest, (int) piece < (int) BlackPawn
4523 ? wdPieceGC : bdPieceGC, 0, 0,
4524 squareSize, squareSize, x, y, 1);
4526 case 2: /* neutral */
4528 XCopyPlane(xDisplay, *pieceToSolid(piece),
4529 dest, (int) piece < (int) BlackPawn
4530 ? wjPieceGC : bjPieceGC, 0, 0,
4531 squareSize, squareSize, x, y, 1);
4536 static void colorDrawPieceImage(piece, square_color, x, y, dest)
4538 int square_color, x, y;
4543 switch (square_color) {
4545 case 2: /* neutral */
4547 if ((int)piece < (int) BlackPawn) {
4555 if ((int)piece < (int) BlackPawn) {
4563 XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
4564 dest, wlPieceGC, 0, 0,
4565 squareSize, squareSize, x, y);
4568 typedef void (*DrawFunc)();
4570 DrawFunc ChooseDrawFunc()
4572 if (appData.monoMode) {
4573 if (DefaultDepth(xDisplay, xScreen) == 1) {
4574 return monoDrawPiece_1bit;
4576 return monoDrawPiece;
4580 return colorDrawPieceImage;
4582 return colorDrawPiece;
4586 /* [HR] determine square color depending on chess variant. */
4587 static int SquareColor(row, column)
4592 if (gameInfo.variant == VariantXiangqi) {
4593 if (column >= 3 && column <= 5 && row >= 0 && row <= 2) {
4595 } else if (column >= 3 && column <= 5 && row >= 7 && row <= 9) {
4597 } else if (row <= 4) {
4603 square_color = ((column + row) % 2) == 1;
4606 /* [hgm] holdings: next line makes all holdings squares light */
4607 if(column < BOARD_LEFT || column >= BOARD_RGHT) square_color = 1;
4609 return square_color;
4612 void DrawSquare(row, column, piece, do_flash)
4613 int row, column, do_flash;
4616 int square_color, x, y, direction, font_ascent, font_descent;
4619 XCharStruct overall;
4623 if(gameInfo.variant == VariantShogi) { // [HGM] shogi: in shogi Q is used for Lance
4624 if(piece == WhiteQueen) piece = WhiteLance; else
4625 if(piece == BlackQueen) piece = BlackLance;
4628 else if(gameInfo.variant == VariantGothic) { // [HGM] shogi: in Gothic Chancelor has alternative look
4629 if(piece == WhiteMarshall) piece = WhiteSilver; else
4630 if(piece == BlackMarshall) piece = BlackSilver;
4634 /* Calculate delay in milliseconds (2-delays per complete flash) */
4635 flash_delay = 500 / appData.flashRate;
4638 x = lineGap + ((BOARD_WIDTH-1)-column) *
4639 (squareSize + lineGap);
4640 y = lineGap + row * (squareSize + lineGap);
4642 x = lineGap + column * (squareSize + lineGap);
4643 y = lineGap + ((BOARD_HEIGHT-1)-row) *
4644 (squareSize + lineGap);
4647 square_color = SquareColor(row, column);
4649 if ( // [HGM] holdings: blank out area between board and holdings
4650 column == BOARD_LEFT-1 || column == BOARD_RGHT
4651 || (column == BOARD_LEFT-2 && row < BOARD_HEIGHT-gameInfo.holdingsSize)
4652 || (column == BOARD_RGHT+1 && row >= gameInfo.holdingsSize) ) {
4653 BlankSquare(x, y, 2, EmptySquare, xBoardWindow);
4655 // [HGM] print piece counts next to holdings
4656 string[1] = NULLCHAR;
4657 if (column == (flipView ? BOARD_LEFT-1 : BOARD_RGHT) && piece > 1 ) {
4658 string[0] = '0' + piece;
4659 XTextExtents(countFontStruct, string, 1, &direction,
4660 &font_ascent, &font_descent, &overall);
4661 if (appData.monoMode) {
4662 XDrawImageString(xDisplay, xBoardWindow, countGC,
4663 x + squareSize - overall.width - 2,
4664 y + font_ascent + 1, string, 1);
4666 XDrawString(xDisplay, xBoardWindow, countGC,
4667 x + squareSize - overall.width - 2,
4668 y + font_ascent + 1, string, 1);
4671 if (column == (flipView ? BOARD_RGHT : BOARD_LEFT-1) && piece > 1) {
4672 string[0] = '0' + piece;
4673 XTextExtents(countFontStruct, string, 1, &direction,
4674 &font_ascent, &font_descent, &overall);
4675 if (appData.monoMode) {
4676 XDrawImageString(xDisplay, xBoardWindow, countGC,
4677 x + 2, y + font_ascent + 1, string, 1);
4679 XDrawString(xDisplay, xBoardWindow, countGC,
4680 x + 2, y + font_ascent + 1, string, 1);
4684 if (piece == EmptySquare || appData.blindfold) {
4685 BlankSquare(x, y, square_color, piece, xBoardWindow);
4687 drawfunc = ChooseDrawFunc();
4688 if (do_flash && appData.flashCount > 0) {
4689 for (i=0; i<appData.flashCount; ++i) {
4691 drawfunc(piece, square_color, x, y, xBoardWindow);
4692 XSync(xDisplay, False);
4693 do_flash_delay(flash_delay);
4695 BlankSquare(x, y, square_color, piece, xBoardWindow);
4696 XSync(xDisplay, False);
4697 do_flash_delay(flash_delay);
4700 drawfunc(piece, square_color, x, y, xBoardWindow);
4704 string[1] = NULLCHAR;
4705 if (appData.showCoords && row == (flipView ? BOARD_HEIGHT-1 : 0)
4706 && column >= BOARD_LEFT && column < BOARD_RGHT) {
4707 string[0] = 'a' + column - BOARD_LEFT;
4708 XTextExtents(coordFontStruct, string, 1, &direction,
4709 &font_ascent, &font_descent, &overall);
4710 if (appData.monoMode) {
4711 XDrawImageString(xDisplay, xBoardWindow, coordGC,
4712 x + squareSize - overall.width - 2,
4713 y + squareSize - font_descent - 1, string, 1);
4715 XDrawString(xDisplay, xBoardWindow, coordGC,
4716 x + squareSize - overall.width - 2,
4717 y + squareSize - font_descent - 1, string, 1);
4720 if (appData.showCoords && column == (flipView ? BOARD_RGHT-1 : BOARD_LEFT)) {
4721 string[0] = ONE + row;
4722 XTextExtents(coordFontStruct, string, 1, &direction,
4723 &font_ascent, &font_descent, &overall);
4724 if (appData.monoMode) {
4725 XDrawImageString(xDisplay, xBoardWindow, coordGC,
4726 x + 2, y + font_ascent + 1, string, 1);
4728 XDrawString(xDisplay, xBoardWindow, coordGC,
4729 x + 2, y + font_ascent + 1, string, 1);
4735 /* Why is this needed on some versions of X? */
4736 void EventProc(widget, unused, event)
4741 if (!XtIsRealized(widget))
4744 switch (event->type) {
4746 if (event->xexpose.count > 0) return; /* no clipping is done */
4747 XDrawPosition(widget, True, NULL);
4755 void DrawPosition(fullRedraw, board)
4756 /*Boolean*/int fullRedraw;
4759 XDrawPosition(boardWidget, fullRedraw, board);
4762 /* Returns 1 if there are "too many" differences between b1 and b2
4763 (i.e. more than 1 move was made) */
4764 static int too_many_diffs(b1, b2)
4770 for (i=0; i<BOARD_HEIGHT; ++i) {
4771 for (j=0; j<BOARD_WIDTH; ++j) {
4772 if (b1[i][j] != b2[i][j]) {
4773 if (++c > 4) /* Castling causes 4 diffs */
4782 /* Matrix describing castling maneuvers */
4783 /* Row, ColRookFrom, ColKingFrom, ColRookTo, ColKingTo */
4784 static int castling_matrix[4][5] = {
4785 { 0, 0, 4, 3, 2 }, /* 0-0-0, white */
4786 { 0, 7, 4, 5, 6 }, /* 0-0, white */
4787 { 7, 0, 4, 3, 2 }, /* 0-0-0, black */
4788 { 7, 7, 4, 5, 6 } /* 0-0, black */
4791 /* Checks whether castling occurred. If it did, *rrow and *rcol
4792 are set to the destination (row,col) of the rook that moved.
4794 Returns 1 if castling occurred, 0 if not.
4796 Note: Only handles a max of 1 castling move, so be sure
4797 to call too_many_diffs() first.
4799 static int check_castle_draw(newb, oldb, rrow, rcol)
4806 /* For each type of castling... */
4807 for (i=0; i<4; ++i) {
4808 r = castling_matrix[i];
4810 /* Check the 4 squares involved in the castling move */
4812 for (j=1; j<=4; ++j) {
4813 if (newb[r[0]][r[j]] == oldb[r[0]][r[j]]) {
4820 /* All 4 changed, so it must be a castling move */
4829 static int damage[BOARD_SIZE][BOARD_SIZE];
4832 * event handler for redrawing the board
4834 void XDrawPosition(w, repaint, board)
4836 /*Boolean*/int repaint;
4840 static int lastFlipView = 0;
4841 static int lastBoardValid = 0;
4842 static Board lastBoard;
4846 if (board == NULL) {
4847 if (!lastBoardValid) return;
4850 if (!lastBoardValid || lastFlipView != flipView) {
4851 XtSetArg(args[0], XtNleftBitmap, (flipView ? xMarkPixmap : None));
4852 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flip View"),
4857 * It would be simpler to clear the window with XClearWindow()
4858 * but this causes a very distracting flicker.
4861 if (!repaint && lastBoardValid && lastFlipView == flipView) {
4863 /* If too much changes (begin observing new game, etc.), don't
4865 do_flash = too_many_diffs(board, lastBoard) ? 0 : 1;
4867 /* Special check for castling so we don't flash both the king
4868 and the rook (just flash the king). */
4870 if (check_castle_draw(board, lastBoard, &rrow, &rcol)) {
4871 /* Draw rook with NO flashing. King will be drawn flashing later */
4872 DrawSquare(rrow, rcol, board[rrow][rcol], 0);
4873 lastBoard[rrow][rcol] = board[rrow][rcol];
4877 /* First pass -- Draw (newly) empty squares and repair damage.
4878 This prevents you from having a piece show up twice while it
4879 is flashing on its new square */
4880 for (i = 0; i < BOARD_HEIGHT; i++)
4881 for (j = 0; j < BOARD_WIDTH; j++)
4882 if ((board[i][j] != lastBoard[i][j] && board[i][j] == EmptySquare)
4884 DrawSquare(i, j, board[i][j], 0);
4885 damage[i][j] = False;
4888 /* Second pass -- Draw piece(s) in new position and flash them */
4889 for (i = 0; i < BOARD_HEIGHT; i++)
4890 for (j = 0; j < BOARD_WIDTH; j++)
4891 if (board[i][j] != lastBoard[i][j]) {
4892 DrawSquare(i, j, board[i][j], do_flash);
4896 XDrawSegments(xDisplay, xBoardWindow, lineGC,
4897 gridSegments, BOARD_HEIGHT + BOARD_WIDTH + 2);
4899 for (i = 0; i < BOARD_HEIGHT; i++)
4900 for (j = 0; j < BOARD_WIDTH; j++) {
4901 DrawSquare(i, j, board[i][j], 0);
4902 damage[i][j] = False;
4906 CopyBoard(lastBoard, board);
4908 lastFlipView = flipView;
4910 /* Draw highlights */
4911 if (pm1X >= 0 && pm1Y >= 0) {
4912 drawHighlight(pm1X, pm1Y, prelineGC);
4914 if (pm2X >= 0 && pm2Y >= 0) {
4915 drawHighlight(pm2X, pm2Y, prelineGC);
4917 if (hi1X >= 0 && hi1Y >= 0) {
4918 drawHighlight(hi1X, hi1Y, highlineGC);
4920 if (hi2X >= 0 && hi2Y >= 0) {
4921 drawHighlight(hi2X, hi2Y, highlineGC);
4924 /* If piece being dragged around board, must redraw that too */
4927 XSync(xDisplay, False);
4932 * event handler for redrawing the board
4934 void DrawPositionProc(w, event, prms, nprms)
4940 XDrawPosition(w, True, NULL);
4945 * event handler for parsing user moves
4947 // [HGM] This routine will need quite some reworking. Although the backend still supports the old
4948 // way of doing things, by calling UserMoveEvent() to test the legality of the move and then perform
4949 // it at the end, and doing all kind of preliminary tests here (e.g. to weed out self-captures), it
4950 // should be made to use the new way, of calling UserMoveTest early to determine the legality of the
4951 // move, (which will weed out the illegal selfcaptures and moves into the holdings, and flag promotions),
4952 // and at the end FinishMove() to perform the move after optional promotion popups.
4953 // For now I patched it to allow self-capture with King, and suppress clicks between board and holdings.
4954 void HandleUserMove(w, event, prms, nprms)
4961 Boolean saveAnimate;
4962 static int second = 0;
4964 if (w != boardWidget || errorExitStatus != -1) return;
4966 if (event->type == ButtonPress) ErrorPopDown();
4969 if (event->type == ButtonPress) {
4970 XtPopdown(promotionShell);
4971 XtDestroyWidget(promotionShell);
4972 promotionUp = False;
4980 x = EventToSquare(event->xbutton.x, BOARD_WIDTH);
4981 y = EventToSquare(event->xbutton.y, BOARD_HEIGHT);
4982 if (!flipView && y >= 0) {
4983 y = BOARD_HEIGHT - 1 - y;
4985 if (flipView && x >= 0) {
4986 x = BOARD_WIDTH - 1 - x;
4989 /* [HGM] holdings: next 5 lines: ignore all clicks between board and holdings */
4990 if(event->type == ButtonPress
4991 && ( x == BOARD_LEFT-1 || x == BOARD_RGHT
4992 || x == BOARD_LEFT-2 && y < BOARD_HEIGHT-gameInfo.holdingsSize
4993 || x == BOARD_RGHT+1 && y >= gameInfo.holdingsSize) )
4997 if (event->type == ButtonPress) {
4999 if (OKToStartUserMove(x, y)) {
5003 DragPieceBegin(event->xbutton.x, event->xbutton.y);
5004 if (appData.highlightDragging) {
5005 SetHighlights(x, y, -1, -1);
5013 if (event->type == ButtonPress && gameMode != EditPosition &&
5018 /* Check if clicking again on the same color piece */
5019 fromP = boards[currentMove][fromY][fromX];
5020 toP = boards[currentMove][y][x];
5021 if ((WhitePawn <= fromP && fromP < WhiteKing && // [HGM] this test should go, as UserMoveTest now does it.
5022 WhitePawn <= toP && toP <= WhiteKing) || // For now I made it less critical by exempting King
5023 (BlackPawn <= fromP && fromP < BlackKing && // moves, to not interfere with FRC castlings.
5024 BlackPawn <= toP && toP <= BlackKing)) {
5025 /* Clicked again on same color piece -- changed his mind */
5026 second = (x == fromX && y == fromY);
5027 if (appData.highlightDragging) {
5028 SetHighlights(x, y, -1, -1);
5032 if (OKToStartUserMove(x, y)) {
5035 DragPieceBegin(event->xbutton.x, event->xbutton.y);
5041 if (event->type == ButtonRelease && x == fromX && y == fromY) {
5042 DragPieceEnd(event->xbutton.x, event->xbutton.y);
5043 if (appData.animateDragging) {
5044 /* Undo animation damage if any */
5045 DrawPosition(FALSE, NULL);
5048 /* Second up/down in same square; just abort move */
5053 ClearPremoveHighlights();
5055 /* First upclick in same square; start click-click mode */
5056 SetHighlights(x, y, -1, -1);
5061 /* Completed move */
5064 saveAnimate = appData.animate;
5065 if (event->type == ButtonPress) {
5066 /* Finish clickclick move */
5067 if (appData.animate || appData.highlightLastMove) {
5068 SetHighlights(fromX, fromY, toX, toY);
5073 /* Finish drag move */
5074 if (appData.highlightLastMove) {
5075 SetHighlights(fromX, fromY, toX, toY);
5079 DragPieceEnd(event->xbutton.x, event->xbutton.y);
5080 /* Don't animate move and drag both */
5081 appData.animate = FALSE;
5083 if (IsPromotion(fromX, fromY, toX, toY)) {
5084 if (appData.alwaysPromoteToQueen) {
5085 UserMoveEvent(fromX, fromY, toX, toY, 'q');
5086 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
5087 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
5090 SetHighlights(fromX, fromY, toX, toY);
5094 UserMoveEvent(fromX, fromY, toX, toY, NULLCHAR);
5095 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
5096 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
5099 appData.animate = saveAnimate;
5100 if (appData.animate || appData.animateDragging) {
5101 /* Undo animation damage if needed */
5102 DrawPosition(FALSE, NULL);
5106 void AnimateUserMove (Widget w, XEvent * event,
5107 String * params, Cardinal * nParams)
5109 DragPieceMove(event->xmotion.x, event->xmotion.y);
5112 Widget CommentCreate(name, text, mutable, callback, lines)
5114 int /*Boolean*/ mutable;
5115 XtCallbackProc callback;
5119 Widget shell, layout, form, edit, b_ok, b_cancel, b_clear, b_close, b_edit;
5124 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5125 XtGetValues(boardWidget, args, j);
5128 XtSetArg(args[j], XtNresizable, True); j++;
5131 XtCreatePopupShell(name, topLevelShellWidgetClass,
5132 shellWidget, args, j);
5135 XtCreatePopupShell(name, transientShellWidgetClass,
5136 shellWidget, args, j);
5139 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
5140 layoutArgs, XtNumber(layoutArgs));
5142 XtCreateManagedWidget("form", formWidgetClass, layout,
5143 formArgs, XtNumber(formArgs));
5147 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
5148 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
5150 XtSetArg(args[j], XtNstring, text); j++;
5151 XtSetArg(args[j], XtNtop, XtChainTop); j++;
5152 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5153 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5154 XtSetArg(args[j], XtNright, XtChainRight); j++;
5155 XtSetArg(args[j], XtNresizable, True); j++;
5156 XtSetArg(args[j], XtNwidth, bw_width); j++; /*force wider than buttons*/
5158 XtSetArg(args[j], XtNscrollVertical, XawtextScrollWhenNeeded); j++;
5160 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
5161 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
5163 XtSetArg(args[j], XtNautoFill, True); j++;
5164 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
5166 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
5170 XtSetArg(args[j], XtNfromVert, edit); j++;
5171 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5172 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5173 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5174 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5176 XtCreateManagedWidget(_("ok"), commandWidgetClass, form, args, j);
5177 XtAddCallback(b_ok, XtNcallback, callback, (XtPointer) 0);
5180 XtSetArg(args[j], XtNfromVert, edit); j++;
5181 XtSetArg(args[j], XtNfromHoriz, b_ok); j++;
5182 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5183 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5184 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5185 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5187 XtCreateManagedWidget(_("cancel"), commandWidgetClass, form, args, j);
5188 XtAddCallback(b_cancel, XtNcallback, callback, (XtPointer) 0);
5191 XtSetArg(args[j], XtNfromVert, edit); j++;
5192 XtSetArg(args[j], XtNfromHoriz, b_cancel); j++;
5193 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5194 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5195 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5196 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5198 XtCreateManagedWidget(_("clear"), commandWidgetClass, form, args, j);
5199 XtAddCallback(b_clear, XtNcallback, callback, (XtPointer) 0);
5202 XtSetArg(args[j], XtNfromVert, edit); j++;
5203 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5204 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5205 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5206 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5208 XtCreateManagedWidget(_("close"), commandWidgetClass, form, args, j);
5209 XtAddCallback(b_close, XtNcallback, callback, (XtPointer) 0);
5212 XtSetArg(args[j], XtNfromVert, edit); j++;
5213 XtSetArg(args[j], XtNfromHoriz, b_close); j++;
5214 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5215 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5216 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5217 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5219 XtCreateManagedWidget(_("edit"), commandWidgetClass, form, args, j);
5220 XtAddCallback(b_edit, XtNcallback, callback, (XtPointer) 0);
5223 XtRealizeWidget(shell);
5225 if (commentX == -1) {
5228 Dimension pw_height;
5229 Dimension ew_height;
5232 XtSetArg(args[j], XtNheight, &ew_height); j++;
5233 XtGetValues(edit, args, j);
5236 XtSetArg(args[j], XtNheight, &pw_height); j++;
5237 XtGetValues(shell, args, j);
5238 commentH = pw_height + (lines - 1) * ew_height;
5239 commentW = bw_width - 16;
5241 XSync(xDisplay, False);
5243 /* This code seems to tickle an X bug if it is executed too soon
5244 after xboard starts up. The coordinates get transformed as if
5245 the main window was positioned at (0, 0).
5247 XtTranslateCoords(shellWidget,
5248 (bw_width - commentW) / 2, 0 - commentH / 2,
5249 &commentX, &commentY);
5251 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
5252 RootWindowOfScreen(XtScreen(shellWidget)),
5253 (bw_width - commentW) / 2, 0 - commentH / 2,
5258 if (commentY < 0) commentY = 0; /*avoid positioning top offscreen*/
5261 XtSetArg(args[j], XtNheight, commentH); j++;
5262 XtSetArg(args[j], XtNwidth, commentW); j++;
5263 XtSetArg(args[j], XtNx, commentX); j++;
5264 XtSetArg(args[j], XtNy, commentY); j++;
5265 XtSetValues(shell, args, j);
5266 XtSetKeyboardFocus(shell, edit);
5271 /* Used for analysis window and ICS input window */
5272 Widget MiscCreate(name, text, mutable, callback, lines)
5274 int /*Boolean*/ mutable;
5275 XtCallbackProc callback;
5279 Widget shell, layout, form, edit;
5281 Dimension bw_width, pw_height, ew_height, w, h;
5287 XtSetArg(args[j], XtNresizable, True); j++;
5290 XtCreatePopupShell(name, topLevelShellWidgetClass,
5291 shellWidget, args, j);
5294 XtCreatePopupShell(name, transientShellWidgetClass,
5295 shellWidget, args, j);
5298 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
5299 layoutArgs, XtNumber(layoutArgs));
5301 XtCreateManagedWidget("form", formWidgetClass, layout,
5302 formArgs, XtNumber(formArgs));
5306 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
5307 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
5309 XtSetArg(args[j], XtNstring, text); j++;
5310 XtSetArg(args[j], XtNtop, XtChainTop); j++;
5311 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5312 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5313 XtSetArg(args[j], XtNright, XtChainRight); j++;
5314 XtSetArg(args[j], XtNresizable, True); j++;
5316 XtSetArg(args[j], XtNscrollVertical, XawtextScrollWhenNeeded); j++;
5318 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
5319 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
5321 XtSetArg(args[j], XtNautoFill, True); j++;
5322 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
5324 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
5326 XtRealizeWidget(shell);
5329 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5330 XtGetValues(boardWidget, args, j);
5333 XtSetArg(args[j], XtNheight, &ew_height); j++;
5334 XtGetValues(edit, args, j);
5337 XtSetArg(args[j], XtNheight, &pw_height); j++;
5338 XtGetValues(shell, args, j);
5339 h = pw_height + (lines - 1) * ew_height;
5342 XSync(xDisplay, False);
5344 /* This code seems to tickle an X bug if it is executed too soon
5345 after xboard starts up. The coordinates get transformed as if
5346 the main window was positioned at (0, 0).
5348 XtTranslateCoords(shellWidget, (bw_width - w) / 2, 0 - h / 2, &x, &y);
5350 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
5351 RootWindowOfScreen(XtScreen(shellWidget)),
5352 (bw_width - w) / 2, 0 - h / 2, &xx, &yy, &junk);
5356 if (y < 0) y = 0; /*avoid positioning top offscreen*/
5359 XtSetArg(args[j], XtNheight, h); j++;
5360 XtSetArg(args[j], XtNwidth, w); j++;
5361 XtSetArg(args[j], XtNx, x); j++;
5362 XtSetArg(args[j], XtNy, y); j++;
5363 XtSetValues(shell, args, j);
5369 static int savedIndex; /* gross that this is global */
5371 void EditCommentPopUp(index, title, text)
5380 if (text == NULL) text = "";
5382 if (editShell == NULL) {
5384 CommentCreate(title, text, True, EditCommentCallback, 4);
5385 XtRealizeWidget(editShell);
5386 CatchDeleteWindow(editShell, "EditCommentPopDown");
5388 edit = XtNameToWidget(editShell, "*form.text");
5390 XtSetArg(args[j], XtNstring, text); j++;
5391 XtSetValues(edit, args, j);
5393 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5394 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5395 XtSetValues(editShell, args, j);
5398 XtPopup(editShell, XtGrabNone);
5402 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
5403 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
5407 void EditCommentCallback(w, client_data, call_data)
5409 XtPointer client_data, call_data;
5417 XtSetArg(args[j], XtNlabel, &name); j++;
5418 XtGetValues(w, args, j);
5420 if (strcmp(name, _("ok")) == 0) {
5421 edit = XtNameToWidget(editShell, "*form.text");
5423 XtSetArg(args[j], XtNstring, &val); j++;
5424 XtGetValues(edit, args, j);
5425 ReplaceComment(savedIndex, val);
5426 EditCommentPopDown();
5427 } else if (strcmp(name, _("cancel")) == 0) {
5428 EditCommentPopDown();
5429 } else if (strcmp(name, _("clear")) == 0) {
5430 edit = XtNameToWidget(editShell, "*form.text");
5431 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
5432 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
5436 void EditCommentPopDown()
5441 if (!editUp) return;
5443 XtSetArg(args[j], XtNx, &commentX); j++;
5444 XtSetArg(args[j], XtNy, &commentY); j++;
5445 XtSetArg(args[j], XtNheight, &commentH); j++;
5446 XtSetArg(args[j], XtNwidth, &commentW); j++;
5447 XtGetValues(editShell, args, j);
5448 XtPopdown(editShell);
5451 XtSetArg(args[j], XtNleftBitmap, None); j++;
5452 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
5456 void ICSInputBoxPopUp()
5461 char *title = _("ICS Input");
5464 if (ICSInputShell == NULL) {
5465 ICSInputShell = MiscCreate(title, "", True, NULL, 1);
5466 tr = XtParseTranslationTable(ICSInputTranslations);
5467 edit = XtNameToWidget(ICSInputShell, "*form.text");
5468 XtOverrideTranslations(edit, tr);
5469 XtRealizeWidget(ICSInputShell);
5470 CatchDeleteWindow(ICSInputShell, "ICSInputBoxPopDown");
5473 edit = XtNameToWidget(ICSInputShell, "*form.text");
5475 XtSetArg(args[j], XtNstring, ""); j++;
5476 XtSetValues(edit, args, j);
5478 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5479 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5480 XtSetValues(ICSInputShell, args, j);
5483 XtPopup(ICSInputShell, XtGrabNone);
5484 XtSetKeyboardFocus(ICSInputShell, edit);
5486 ICSInputBoxUp = True;
5488 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
5489 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
5493 void ICSInputSendText()
5500 edit = XtNameToWidget(ICSInputShell, "*form.text");
5502 XtSetArg(args[j], XtNstring, &val); j++;
5503 XtGetValues(edit, args, j);
5504 SendMultiLineToICS(val);
5505 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
5506 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
5509 void ICSInputBoxPopDown()
5514 if (!ICSInputBoxUp) return;
5516 XtPopdown(ICSInputShell);
5517 ICSInputBoxUp = False;
5519 XtSetArg(args[j], XtNleftBitmap, None); j++;
5520 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
5524 void CommentPopUp(title, text)
5531 if (commentShell == NULL) {
5533 CommentCreate(title, text, False, CommentCallback, 4);
5534 XtRealizeWidget(commentShell);
5535 CatchDeleteWindow(commentShell, "CommentPopDown");
5537 edit = XtNameToWidget(commentShell, "*form.text");
5539 XtSetArg(args[j], XtNstring, text); j++;
5540 XtSetValues(edit, args, j);
5542 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5543 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5544 XtSetValues(commentShell, args, j);
5547 XtPopup(commentShell, XtGrabNone);
5548 XSync(xDisplay, False);
5553 void AnalysisPopUp(title, text)
5560 if (analysisShell == NULL) {
5561 analysisShell = MiscCreate(title, text, False, NULL, 4);
5562 XtRealizeWidget(analysisShell);
5563 CatchDeleteWindow(analysisShell, "AnalysisPopDown");
5566 edit = XtNameToWidget(analysisShell, "*form.text");
5568 XtSetArg(args[j], XtNstring, text); j++;
5569 XtSetValues(edit, args, j);
5571 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5572 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5573 XtSetValues(analysisShell, args, j);
5577 XtPopup(analysisShell, XtGrabNone);
5579 XSync(xDisplay, False);
5584 void CommentCallback(w, client_data, call_data)
5586 XtPointer client_data, call_data;
5593 XtSetArg(args[j], XtNlabel, &name); j++;
5594 XtGetValues(w, args, j);
5596 if (strcmp(name, _("close")) == 0) {
5598 } else if (strcmp(name, _("edit")) == 0) {
5605 void CommentPopDown()
5610 if (!commentUp) return;
5612 XtSetArg(args[j], XtNx, &commentX); j++;
5613 XtSetArg(args[j], XtNy, &commentY); j++;
5614 XtSetArg(args[j], XtNwidth, &commentW); j++;
5615 XtSetArg(args[j], XtNheight, &commentH); j++;
5616 XtGetValues(commentShell, args, j);
5617 XtPopdown(commentShell);
5618 XSync(xDisplay, False);
5622 void AnalysisPopDown()
5624 if (!analysisUp) return;
5625 XtPopdown(analysisShell);
5626 XSync(xDisplay, False);
5628 if (appData.icsEngineAnalyze) ExitAnalyzeMode(); /* [DM] icsEngineAnalyze */
5632 void FileNamePopUp(label, def, proc, openMode)
5639 Widget popup, layout, dialog, edit;
5645 fileProc = proc; /* I can't see a way not */
5646 fileOpenMode = openMode; /* to use globals here */
5649 XtSetArg(args[i], XtNresizable, True); i++;
5650 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
5651 XtSetArg(args[i], XtNtitle, XtNewString(_("File name prompt"))); i++;
5652 fileNameShell = popup =
5653 XtCreatePopupShell("File name prompt", transientShellWidgetClass,
5654 shellWidget, args, i);
5657 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
5658 layoutArgs, XtNumber(layoutArgs));
5661 XtSetArg(args[i], XtNlabel, label); i++;
5662 XtSetArg(args[i], XtNvalue, def); i++;
5663 XtSetArg(args[i], XtNborderWidth, 0); i++;
5664 dialog = XtCreateManagedWidget("fileName", dialogWidgetClass,
5667 XawDialogAddButton(dialog, _("ok"), FileNameCallback, (XtPointer) dialog);
5668 XawDialogAddButton(dialog, _("cancel"), FileNameCallback,
5669 (XtPointer) dialog);
5671 XtRealizeWidget(popup);
5672 CatchDeleteWindow(popup, "FileNamePopDown");
5674 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
5675 &x, &y, &win_x, &win_y, &mask);
5677 XtSetArg(args[0], XtNx, x - 10);
5678 XtSetArg(args[1], XtNy, y - 30);
5679 XtSetValues(popup, args, 2);
5681 XtPopup(popup, XtGrabExclusive);
5684 edit = XtNameToWidget(dialog, "*value");
5685 XtSetKeyboardFocus(popup, edit);
5688 void FileNamePopDown()
5690 if (!filenameUp) return;
5691 XtPopdown(fileNameShell);
5692 XtDestroyWidget(fileNameShell);
5697 void FileNameCallback(w, client_data, call_data)
5699 XtPointer client_data, call_data;
5704 XtSetArg(args[0], XtNlabel, &name);
5705 XtGetValues(w, args, 1);
5707 if (strcmp(name, _("cancel")) == 0) {
5712 FileNameAction(w, NULL, NULL, NULL);
5715 void FileNameAction(w, event, prms, nprms)
5727 name = XawDialogGetValueString(w = XtParent(w));
5729 if ((name != NULL) && (*name != NULLCHAR)) {
5731 XtPopdown(w = XtParent(XtParent(w)));
5735 p = strrchr(buf, ' ');
5742 fullname = ExpandPathName(buf);
5744 ErrorPopUp(_("Error"), _("Can't open file"), FALSE);
5747 f = fopen(fullname, fileOpenMode);
5749 DisplayError(_("Failed to open file"), errno);
5751 (void) (*fileProc)(f, index, buf);
5758 XtPopdown(w = XtParent(XtParent(w)));
5764 void PromotionPopUp()
5767 Widget dialog, layout;
5769 Dimension bw_width, pw_width;
5773 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5774 XtGetValues(boardWidget, args, j);
5777 XtSetArg(args[j], XtNresizable, True); j++;
5778 XtSetArg(args[j], XtNtitle, XtNewString(_("Promotion"))); j++;
5780 XtCreatePopupShell("Promotion", transientShellWidgetClass,
5781 shellWidget, args, j);
5783 XtCreateManagedWidget(layoutName, formWidgetClass, promotionShell,
5784 layoutArgs, XtNumber(layoutArgs));
5787 XtSetArg(args[j], XtNlabel, _("Promote pawn to what?")); j++;
5788 XtSetArg(args[j], XtNborderWidth, 0); j++;
5789 dialog = XtCreateManagedWidget("promotion", dialogWidgetClass,
5792 XawDialogAddButton(dialog, _("Queen"), PromotionCallback,
5793 (XtPointer) dialog);
5794 XawDialogAddButton(dialog, _("Rook"), PromotionCallback,
5795 (XtPointer) dialog);
5796 XawDialogAddButton(dialog, _("Bishop"), PromotionCallback,
5797 (XtPointer) dialog);
5798 XawDialogAddButton(dialog, _("Knight"), PromotionCallback,
5799 (XtPointer) dialog);
5800 if (!appData.testLegality || gameInfo.variant == VariantSuicide ||
5801 gameInfo.variant == VariantGiveaway) {
5802 XawDialogAddButton(dialog, _("King"), PromotionCallback,
5803 (XtPointer) dialog);
5805 XawDialogAddButton(dialog, _("cancel"), PromotionCallback,
5806 (XtPointer) dialog);
5808 XtRealizeWidget(promotionShell);
5809 CatchDeleteWindow(promotionShell, "PromotionPopDown");
5812 XtSetArg(args[j], XtNwidth, &pw_width); j++;
5813 XtGetValues(promotionShell, args, j);
5815 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
5816 lineGap + squareSize/3 +
5817 ((toY == BOARD_HEIGHT-1) ^ (flipView) ?
5818 0 : 6*(squareSize + lineGap)), &x, &y);
5821 XtSetArg(args[j], XtNx, x); j++;
5822 XtSetArg(args[j], XtNy, y); j++;
5823 XtSetValues(promotionShell, args, j);
5825 XtPopup(promotionShell, XtGrabNone);
5830 void PromotionPopDown()
5832 if (!promotionUp) return;
5833 XtPopdown(promotionShell);
5834 XtDestroyWidget(promotionShell);
5835 promotionUp = False;
5838 void PromotionCallback(w, client_data, call_data)
5840 XtPointer client_data, call_data;
5846 XtSetArg(args[0], XtNlabel, &name);
5847 XtGetValues(w, args, 1);
5851 if (fromX == -1) return;
5853 if (strcmp(name, _("cancel")) == 0) {
5857 } else if (strcmp(name, _("Knight")) == 0) {
5860 promoChar = ToLower(name[0]);
5863 UserMoveEvent(fromX, fromY, toX, toY, promoChar);
5865 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
5866 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
5871 void ErrorCallback(w, client_data, call_data)
5873 XtPointer client_data, call_data;
5876 XtPopdown(w = XtParent(XtParent(XtParent(w))));
5878 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
5884 if (!errorUp) return;
5886 XtPopdown(errorShell);
5887 XtDestroyWidget(errorShell);
5888 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
5891 void ErrorPopUp(title, label, modal)
5892 char *title, *label;
5896 Widget dialog, layout;
5900 Dimension bw_width, pw_width;
5901 Dimension pw_height;
5905 XtSetArg(args[i], XtNresizable, True); i++;
5906 XtSetArg(args[i], XtNtitle, title); i++;
5908 XtCreatePopupShell("errorpopup", transientShellWidgetClass,
5909 shellWidget, args, i);
5911 XtCreateManagedWidget(layoutName, formWidgetClass, errorShell,
5912 layoutArgs, XtNumber(layoutArgs));
5915 XtSetArg(args[i], XtNlabel, label); i++;
5916 XtSetArg(args[i], XtNborderWidth, 0); i++;
5917 dialog = XtCreateManagedWidget("dialog", dialogWidgetClass,
5920 XawDialogAddButton(dialog, _("ok"), ErrorCallback, (XtPointer) dialog);
5922 XtRealizeWidget(errorShell);
5923 CatchDeleteWindow(errorShell, "ErrorPopDown");
5926 XtSetArg(args[i], XtNwidth, &bw_width); i++;
5927 XtGetValues(boardWidget, args, i);
5929 XtSetArg(args[i], XtNwidth, &pw_width); i++;
5930 XtSetArg(args[i], XtNheight, &pw_height); i++;
5931 XtGetValues(errorShell, args, i);
5934 /* This code seems to tickle an X bug if it is executed too soon
5935 after xboard starts up. The coordinates get transformed as if
5936 the main window was positioned at (0, 0).
5938 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
5939 0 - pw_height + squareSize / 3, &x, &y);
5941 XTranslateCoordinates(xDisplay, XtWindow(boardWidget),
5942 RootWindowOfScreen(XtScreen(boardWidget)),
5943 (bw_width - pw_width) / 2,
5944 0 - pw_height + squareSize / 3, &xx, &yy, &junk);
5948 if (y < 0) y = 0; /*avoid positioning top offscreen*/
5951 XtSetArg(args[i], XtNx, x); i++;
5952 XtSetArg(args[i], XtNy, y); i++;
5953 XtSetValues(errorShell, args, i);
5956 XtPopup(errorShell, modal ? XtGrabExclusive : XtGrabNone);
5959 /* Disable all user input other than deleting the window */
5960 static int frozen = 0;
5964 /* Grab by a widget that doesn't accept input */
5965 XtAddGrab(messageWidget, TRUE, FALSE);
5969 /* Undo a FreezeUI */
5972 if (!frozen) return;
5973 XtRemoveGrab(messageWidget);
5977 char *ModeToWidgetName(mode)
5981 case BeginningOfGame:
5982 if (appData.icsActive)
5983 return "menuMode.ICS Client";
5984 else if (appData.noChessProgram ||
5985 *appData.cmailGameName != NULLCHAR)
5986 return "menuMode.Edit Game";
5988 return "menuMode.Machine Black";
5989 case MachinePlaysBlack:
5990 return "menuMode.Machine Black";
5991 case MachinePlaysWhite:
5992 return "menuMode.Machine White";
5994 return "menuMode.Analysis Mode";
5996 return "menuMode.Analyze File";
5997 case TwoMachinesPlay:
5998 return "menuMode.Two Machines";
6000 return "menuMode.Edit Game";
6001 case PlayFromGameFile:
6002 return "menuFile.Load Game";
6004 return "menuMode.Edit Position";
6006 return "menuMode.Training";
6007 case IcsPlayingWhite:
6008 case IcsPlayingBlack:
6012 return "menuMode.ICS Client";
6019 void ModeHighlight()
6022 static int oldPausing = FALSE;
6023 static GameMode oldmode = (GameMode) -1;
6026 if (!boardWidget || !XtIsRealized(boardWidget)) return;
6028 if (pausing != oldPausing) {
6029 oldPausing = pausing;
6031 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6033 XtSetArg(args[0], XtNleftBitmap, None);
6035 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Pause"),
6038 if (appData.showButtonBar) {
6041 XtSetArg(args[0], XtNbackground, buttonForegroundPixel);
6042 XtSetArg(args[1], XtNforeground, buttonBackgroundPixel);
6044 XtSetArg(args[0], XtNbackground, buttonBackgroundPixel);
6045 XtSetArg(args[1], XtNforeground, buttonForegroundPixel);
6048 /* Always toggle, don't set. Previous code messes up when
6049 invoked while the button is pressed, as releasing it
6050 toggles the state again. */
6053 XtSetArg(args[0], XtNbackground, &oldbg);
6054 XtSetArg(args[1], XtNforeground, &oldfg);
6055 XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON),
6057 XtSetArg(args[0], XtNbackground, oldfg);
6058 XtSetArg(args[1], XtNforeground, oldbg);
6061 XtSetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
6065 wname = ModeToWidgetName(oldmode);
6066 if (wname != NULL) {
6067 XtSetArg(args[0], XtNleftBitmap, None);
6068 XtSetValues(XtNameToWidget(menuBarWidget, wname), args, 1);
6070 wname = ModeToWidgetName(gameMode);
6071 if (wname != NULL) {
6072 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6073 XtSetValues(XtNameToWidget(menuBarWidget, wname), args, 1);
6077 /* Maybe all the enables should be handled here, not just this one */
6078 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Training"),
6079 gameMode == Training || gameMode == PlayFromGameFile);
6084 * Button/menu procedures
6086 void ResetProc(w, event, prms, nprms)
6096 int LoadGamePopUp(f, gameNumber, title)
6101 cmailMsgLoaded = FALSE;
6102 if (gameNumber == 0) {
6103 int error = GameListBuild(f);
6105 DisplayError(_("Cannot build game list"), error);
6106 } else if (!ListEmpty(&gameList) &&
6107 ((ListGame *) gameList.tailPred)->number > 1) {
6108 GameListPopUp(f, title);
6114 return LoadGame(f, gameNumber, title, FALSE);
6117 void LoadGameProc(w, event, prms, nprms)
6123 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
6126 FileNamePopUp(_("Load game file name?"), "", LoadGamePopUp, "rb");
6129 void LoadNextGameProc(w, event, prms, nprms)
6138 void LoadPrevGameProc(w, event, prms, nprms)
6147 void ReloadGameProc(w, event, prms, nprms)
6156 void LoadNextPositionProc(w, event, prms, nprms)
6165 void LoadPrevPositionProc(w, event, prms, nprms)
6174 void ReloadPositionProc(w, event, prms, nprms)
6183 void LoadPositionProc(w, event, prms, nprms)
6189 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
6192 FileNamePopUp(_("Load position file name?"), "", LoadPosition, "rb");
6195 void SaveGameProc(w, event, prms, nprms)
6201 FileNamePopUp(_("Save game file name?"),
6202 DefaultFileName(appData.oldSaveStyle ? "game" : "pgn"),
6206 void SavePositionProc(w, event, prms, nprms)
6212 FileNamePopUp(_("Save position file name?"),
6213 DefaultFileName(appData.oldSaveStyle ? "pos" : "fen"),
6217 void ReloadCmailMsgProc(w, event, prms, nprms)
6223 ReloadCmailMsgEvent(FALSE);
6226 void MailMoveProc(w, event, prms, nprms)
6235 /* this variable is shared between CopyPositionProc and SendPositionSelection */
6236 static char *selected_fen_position=NULL;
6239 SendPositionSelection(Widget w, Atom *selection, Atom *target,
6240 Atom *type_return, XtPointer *value_return,
6241 unsigned long *length_return, int *format_return)
6243 char *selection_tmp;
6245 if (!selected_fen_position) return False; /* should never happen */
6246 if (*target == XA_STRING){
6247 /* note: since no XtSelectionDoneProc was registered, Xt will
6248 * automatically call XtFree on the value returned. So have to
6249 * make a copy of it allocated with XtMalloc */
6250 selection_tmp= XtMalloc(strlen(selected_fen_position)+16);
6251 strcpy(selection_tmp, selected_fen_position);
6253 *value_return=selection_tmp;
6254 *length_return=strlen(selection_tmp);
6255 *type_return=XA_STRING;
6256 *format_return = 8; /* bits per byte */
6263 /* note: when called from menu all parameters are NULL, so no clue what the
6264 * Widget which was clicked on was, or what the click event was
6266 void CopyPositionProc(w, event, prms, nprms)
6274 if (selected_fen_position) free(selected_fen_position);
6275 selected_fen_position = (char *)PositionToFEN(currentMove,1);
6276 if (!selected_fen_position) return;
6277 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
6279 SendPositionSelection,
6280 NULL/* lose_ownership_proc */ ,
6281 NULL/* transfer_done_proc */);
6283 free(selected_fen_position);
6284 selected_fen_position=NULL;
6288 /* function called when the data to Paste is ready */
6290 PastePositionCB(Widget w, XtPointer client_data, Atom *selection,
6291 Atom *type, XtPointer value, unsigned long *len, int *format)
6294 if (value==NULL || *len==0) return; /* nothing had been selected to copy */
6295 fenstr[*len]='\0'; /* normally this string is terminated, but be safe */
6296 EditPositionPasteFEN(fenstr);
6300 /* called when Paste Position button is pressed,
6301 * all parameters will be NULL */
6302 void PastePositionProc(w, event, prms, nprms)
6308 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
6309 /* (XtSelectionCallbackProc) */ PastePositionCB,
6310 NULL, /* client_data passed to PastePositionCB */
6312 /* better to use the time field from the event that triggered the
6313 * call to this function, but that isn't trivial to get
6321 SendGameSelection(Widget w, Atom *selection, Atom *target,
6322 Atom *type_return, XtPointer *value_return,
6323 unsigned long *length_return, int *format_return)
6325 char *selection_tmp;
6327 if (*target == XA_STRING){
6328 FILE* f = fopen(gameCopyFilename, "r");
6331 if (f == NULL) return False;
6335 selection_tmp = XtMalloc(len + 1);
6336 count = fread(selection_tmp, 1, len, f);
6338 XtFree(selection_tmp);
6341 selection_tmp[len] = NULLCHAR;
6342 *value_return = selection_tmp;
6343 *length_return = len;
6344 *type_return = XA_STRING;
6345 *format_return = 8; /* bits per byte */
6352 /* note: when called from menu all parameters are NULL, so no clue what the
6353 * Widget which was clicked on was, or what the click event was
6355 void CopyGameProc(w, event, prms, nprms)
6363 ret = SaveGameToFile(gameCopyFilename, FALSE);
6366 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
6369 NULL/* lose_ownership_proc */ ,
6370 NULL/* transfer_done_proc */);
6373 /* function called when the data to Paste is ready */
6375 PasteGameCB(Widget w, XtPointer client_data, Atom *selection,
6376 Atom *type, XtPointer value, unsigned long *len, int *format)
6379 if (value == NULL || *len == 0) {
6380 return; /* nothing had been selected to copy */
6382 f = fopen(gamePasteFilename, "w");
6384 DisplayError(_("Can't open temp file"), errno);
6387 fwrite(value, 1, *len, f);
6390 LoadGameFromFile(gamePasteFilename, 0, gamePasteFilename, TRUE);
6393 /* called when Paste Game button is pressed,
6394 * all parameters will be NULL */
6395 void PasteGameProc(w, event, prms, nprms)
6401 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
6402 /* (XtSelectionCallbackProc) */ PasteGameCB,
6403 NULL, /* client_data passed to PasteGameCB */
6405 /* better to use the time field from the event that triggered the
6406 * call to this function, but that isn't trivial to get
6416 SaveGameProc(NULL, NULL, NULL, NULL);
6420 void QuitProc(w, event, prms, nprms)
6429 void PauseProc(w, event, prms, nprms)
6439 void MachineBlackProc(w, event, prms, nprms)
6445 MachineBlackEvent();
6448 void MachineWhiteProc(w, event, prms, nprms)
6454 MachineWhiteEvent();
6457 void AnalyzeModeProc(w, event, prms, nprms)
6465 if (!first.analysisSupport) {
6466 sprintf(buf, _("%s does not support analysis"), first.tidy);
6467 DisplayError(buf, 0);
6470 /* [DM] icsEngineAnalyze [HGM] This is horrible code; reverse the gameMode and isEngineAnalyze tests! */
6471 if (appData.icsActive) {
6472 if (gameMode != IcsObserving) {
6473 sprintf(buf,_("You are not observing a game"));
6474 DisplayError(buf, 0);
6476 if (appData.icsEngineAnalyze) {
6477 if (appData.debugMode)
6478 fprintf(debugFP, _("Found unexpected active ICS engine analyze \n"));
6484 /* if enable, use want disable icsEngineAnalyze */
6485 if (appData.icsEngineAnalyze) {
6490 appData.icsEngineAnalyze = TRUE;
6491 if (appData.debugMode)
6492 fprintf(debugFP, _("ICS engine analyze starting... \n"));
6494 if (!appData.showThinking)
6495 ShowThinkingProc(w,event,prms,nprms);
6500 void AnalyzeFileProc(w, event, prms, nprms)
6506 if (!first.analysisSupport) {
6508 sprintf(buf, _("%s does not support analysis"), first.tidy);
6509 DisplayError(buf, 0);
6514 if (!appData.showThinking)
6515 ShowThinkingProc(w,event,prms,nprms);
6518 FileNamePopUp(_("File to analyze"), "", LoadGamePopUp, "rb");
6519 AnalysisPeriodicEvent(1);
6522 void TwoMachinesProc(w, event, prms, nprms)
6531 void IcsClientProc(w, event, prms, nprms)
6540 void EditGameProc(w, event, prms, nprms)
6549 void EditPositionProc(w, event, prms, nprms)
6555 EditPositionEvent();
6558 void TrainingProc(w, event, prms, nprms)
6567 void EditCommentProc(w, event, prms, nprms)
6574 EditCommentPopDown();
6580 void IcsInputBoxProc(w, event, prms, nprms)
6586 if (ICSInputBoxUp) {
6587 ICSInputBoxPopDown();
6593 void AcceptProc(w, event, prms, nprms)
6602 void DeclineProc(w, event, prms, nprms)
6611 void RematchProc(w, event, prms, nprms)
6620 void CallFlagProc(w, event, prms, nprms)
6629 void DrawProc(w, event, prms, nprms)
6638 void AbortProc(w, event, prms, nprms)
6647 void AdjournProc(w, event, prms, nprms)
6656 void ResignProc(w, event, prms, nprms)
6665 void AdjuWhiteProc(w, event, prms, nprms)
6671 UserAdjudicationEvent(+1);
6674 void AdjuBlackProc(w, event, prms, nprms)
6680 UserAdjudicationEvent(-1);
6683 void AdjuDrawProc(w, event, prms, nprms)
6689 UserAdjudicationEvent(0);
6692 void EnterKeyProc(w, event, prms, nprms)
6698 if (ICSInputBoxUp == True)
6702 void StopObservingProc(w, event, prms, nprms)
6708 StopObservingEvent();
6711 void StopExaminingProc(w, event, prms, nprms)
6717 StopExaminingEvent();
6721 void ForwardProc(w, event, prms, nprms)
6731 void BackwardProc(w, event, prms, nprms)
6740 void ToStartProc(w, event, prms, nprms)
6749 void ToEndProc(w, event, prms, nprms)
6758 void RevertProc(w, event, prms, nprms)
6767 void TruncateGameProc(w, event, prms, nprms)
6773 TruncateGameEvent();
6775 void RetractMoveProc(w, event, prms, nprms)
6784 void MoveNowProc(w, event, prms, nprms)
6794 void AlwaysQueenProc(w, event, prms, nprms)
6802 appData.alwaysPromoteToQueen = !appData.alwaysPromoteToQueen;
6804 if (appData.alwaysPromoteToQueen) {
6805 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6807 XtSetArg(args[0], XtNleftBitmap, None);
6809 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
6813 void AnimateDraggingProc(w, event, prms, nprms)
6821 appData.animateDragging = !appData.animateDragging;
6823 if (appData.animateDragging) {
6824 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6827 XtSetArg(args[0], XtNleftBitmap, None);
6829 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Dragging"),
6833 void AnimateMovingProc(w, event, prms, nprms)
6841 appData.animate = !appData.animate;
6843 if (appData.animate) {
6844 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6847 XtSetArg(args[0], XtNleftBitmap, None);
6849 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
6853 void AutocommProc(w, event, prms, nprms)
6861 appData.autoComment = !appData.autoComment;
6863 if (appData.autoComment) {
6864 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6866 XtSetArg(args[0], XtNleftBitmap, None);
6868 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
6873 void AutoflagProc(w, event, prms, nprms)
6881 appData.autoCallFlag = !appData.autoCallFlag;
6883 if (appData.autoCallFlag) {
6884 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6886 XtSetArg(args[0], XtNleftBitmap, None);
6888 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
6892 void AutoflipProc(w, event, prms, nprms)
6900 appData.autoFlipView = !appData.autoFlipView;
6902 if (appData.autoFlipView) {
6903 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6905 XtSetArg(args[0], XtNleftBitmap, None);
6907 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flip View"),
6911 void AutobsProc(w, event, prms, nprms)
6919 appData.autoObserve = !appData.autoObserve;
6921 if (appData.autoObserve) {
6922 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6924 XtSetArg(args[0], XtNleftBitmap, None);
6926 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
6930 void AutoraiseProc(w, event, prms, nprms)
6938 appData.autoRaiseBoard = !appData.autoRaiseBoard;
6940 if (appData.autoRaiseBoard) {
6941 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6943 XtSetArg(args[0], XtNleftBitmap, None);
6945 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Raise Board"),
6949 void AutosaveProc(w, event, prms, nprms)
6957 appData.autoSaveGames = !appData.autoSaveGames;
6959 if (appData.autoSaveGames) {
6960 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6962 XtSetArg(args[0], XtNleftBitmap, None);
6964 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
6968 void BlindfoldProc(w, event, prms, nprms)
6976 appData.blindfold = !appData.blindfold;
6978 if (appData.blindfold) {
6979 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6981 XtSetArg(args[0], XtNleftBitmap, None);
6983 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Blindfold"),
6986 DrawPosition(True, NULL);
6989 void TestLegalityProc(w, event, prms, nprms)
6997 appData.testLegality = !appData.testLegality;
6999 if (appData.testLegality) {
7000 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7002 XtSetArg(args[0], XtNleftBitmap, None);
7004 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Test Legality"),
7009 void FlashMovesProc(w, event, prms, nprms)
7017 if (appData.flashCount == 0) {
7018 appData.flashCount = 3;
7020 appData.flashCount = -appData.flashCount;
7023 if (appData.flashCount > 0) {
7024 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7026 XtSetArg(args[0], XtNleftBitmap, None);
7028 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flash Moves"),
7032 void FlipViewProc(w, event, prms, nprms)
7038 flipView = !flipView;
7039 DrawPosition(True, NULL);
7042 void GetMoveListProc(w, event, prms, nprms)
7050 appData.getMoveList = !appData.getMoveList;
7052 if (appData.getMoveList) {
7053 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7056 XtSetArg(args[0], XtNleftBitmap, None);
7058 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
7063 void HighlightDraggingProc(w, event, prms, nprms)
7071 appData.highlightDragging = !appData.highlightDragging;
7073 if (appData.highlightDragging) {
7074 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7076 XtSetArg(args[0], XtNleftBitmap, None);
7078 XtSetValues(XtNameToWidget(menuBarWidget,
7079 "menuOptions.Highlight Dragging"), args, 1);
7083 void HighlightLastMoveProc(w, event, prms, nprms)
7091 appData.highlightLastMove = !appData.highlightLastMove;
7093 if (appData.highlightLastMove) {
7094 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7096 XtSetArg(args[0], XtNleftBitmap, None);
7098 XtSetValues(XtNameToWidget(menuBarWidget,
7099 "menuOptions.Highlight Last Move"), args, 1);
7102 void IcsAlarmProc(w, event, prms, nprms)
7110 appData.icsAlarm = !appData.icsAlarm;
7112 if (appData.icsAlarm) {
7113 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7115 XtSetArg(args[0], XtNleftBitmap, None);
7117 XtSetValues(XtNameToWidget(menuBarWidget,
7118 "menuOptions.ICS Alarm"), args, 1);
7121 void MoveSoundProc(w, event, prms, nprms)
7129 appData.ringBellAfterMoves = !appData.ringBellAfterMoves;
7131 if (appData.ringBellAfterMoves) {
7132 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7134 XtSetArg(args[0], XtNleftBitmap, None);
7136 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
7141 void OldSaveStyleProc(w, event, prms, nprms)
7149 appData.oldSaveStyle = !appData.oldSaveStyle;
7151 if (appData.oldSaveStyle) {
7152 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7154 XtSetArg(args[0], XtNleftBitmap, None);
7156 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Old Save Style"),
7160 void PeriodicUpdatesProc(w, event, prms, nprms)
7168 PeriodicUpdatesEvent(!appData.periodicUpdates);
7170 if (appData.periodicUpdates) {
7171 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7173 XtSetArg(args[0], XtNleftBitmap, None);
7175 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Periodic Updates"),
7179 void PonderNextMoveProc(w, event, prms, nprms)
7187 PonderNextMoveEvent(!appData.ponderNextMove);
7189 if (appData.ponderNextMove) {
7190 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7192 XtSetArg(args[0], XtNleftBitmap, None);
7194 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Ponder Next Move"),
7198 void PopupExitMessageProc(w, event, prms, nprms)
7206 appData.popupExitMessage = !appData.popupExitMessage;
7208 if (appData.popupExitMessage) {
7209 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7211 XtSetArg(args[0], XtNleftBitmap, None);
7213 XtSetValues(XtNameToWidget(menuBarWidget,
7214 "menuOptions.Popup Exit Message"), args, 1);
7217 void PopupMoveErrorsProc(w, event, prms, nprms)
7225 appData.popupMoveErrors = !appData.popupMoveErrors;
7227 if (appData.popupMoveErrors) {
7228 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7230 XtSetArg(args[0], XtNleftBitmap, None);
7232 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Popup Move Errors"),
7236 void PremoveProc(w, event, prms, nprms)
7244 appData.premove = !appData.premove;
7246 if (appData.premove) {
7247 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7249 XtSetArg(args[0], XtNleftBitmap, None);
7251 XtSetValues(XtNameToWidget(menuBarWidget,
7252 "menuOptions.Premove"), args, 1);
7255 void QuietPlayProc(w, event, prms, nprms)
7263 appData.quietPlay = !appData.quietPlay;
7265 if (appData.quietPlay) {
7266 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7268 XtSetArg(args[0], XtNleftBitmap, None);
7270 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Quiet Play"),
7274 void ShowCoordsProc(w, event, prms, nprms)
7282 appData.showCoords = !appData.showCoords;
7284 if (appData.showCoords) {
7285 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7287 XtSetArg(args[0], XtNleftBitmap, None);
7289 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
7292 DrawPosition(True, NULL);
7295 void ShowThinkingProc(w, event, prms, nprms)
7303 appData.showThinking = !appData.showThinking; // [HGM] thinking: tken out of ShowThinkingEvent
7304 ShowThinkingEvent();
7306 // [HGM] thinking: currently no suc menu item; replaced by Hide Thinking (From Human)
7307 if (appData.showThinking) {
7308 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7310 XtSetArg(args[0], XtNleftBitmap, None);
7312 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Thinking"),
7317 void HideThinkingProc(w, event, prms, nprms)
7325 appData.hideThinkingFromHuman = !appData.hideThinkingFromHuman; // [HGM] thinking: tken out of ShowThinkingEvent
7326 ShowThinkingEvent();
7328 if (appData.hideThinkingFromHuman) {
7329 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7331 XtSetArg(args[0], XtNleftBitmap, None);
7333 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
7337 void InfoProc(w, event, prms, nprms)
7344 sprintf(buf, "xterm -e info --directory %s --directory . -f %s &",
7349 void ManProc(w, event, prms, nprms)
7357 if (nprms && *nprms > 0)
7361 sprintf(buf, "xterm -e man %s &", name);
7365 void HintProc(w, event, prms, nprms)
7374 void BookProc(w, event, prms, nprms)
7383 void AboutProc(w, event, prms, nprms)
7391 char *zippy = " (with Zippy code)";
7395 sprintf(buf, "%s%s\n\n%s\n%s\n%s\n%s\n\n%s%s\n%s",
7396 programVersion, zippy,
7397 "Copyright 1991 Digital Equipment Corporation",
7398 "Enhancements Copyright 1992-2001 Free Software Foundation",
7399 "Enhancements Copyright 2005 Alessandro Scotti",
7400 "Enhancements Copyright 2007-2008 H.G.Muller",
7401 PRODUCT, " is free software and carries NO WARRANTY;",
7402 "see the file COPYING for more information.");
7403 ErrorPopUp(_("About XBoard"), buf, FALSE);
7406 void DebugProc(w, event, prms, nprms)
7412 appData.debugMode = !appData.debugMode;
7415 void AboutGameProc(w, event, prms, nprms)
7424 void NothingProc(w, event, prms, nprms)
7433 void Iconify(w, event, prms, nprms)
7442 XtSetArg(args[0], XtNiconic, True);
7443 XtSetValues(shellWidget, args, 1);
7446 void DisplayMessage(message, extMessage)
7447 char *message, *extMessage;
7454 sprintf(buf, "%s %s", message, extMessage);
7457 message = extMessage;
7460 XtSetArg(arg, XtNlabel, message);
7461 XtSetValues(messageWidget, &arg, 1);
7464 void DisplayTitle(text)
7469 char title[MSG_SIZ];
7472 if (text == NULL) text = "";
7474 if (appData.titleInWindow) {
7476 XtSetArg(args[i], XtNlabel, text); i++;
7477 XtSetValues(titleWidget, args, i);
7480 if (*text != NULLCHAR) {
7482 strcpy(title, text);
7483 } else if (appData.icsActive) {
7484 sprintf(icon, "%s", appData.icsHost);
7485 sprintf(title, "%s: %s", programName, appData.icsHost);
7486 } else if (appData.cmailGameName[0] != NULLCHAR) {
7487 sprintf(icon, "%s", "CMail");
7488 sprintf(title, "%s: %s", programName, "CMail");
7490 // [HGM] license: This stuff should really be done in back-end, but WinBoard already had a pop-up for it
7491 } else if (gameInfo.variant == VariantGothic) {
7492 strcpy(icon, programName);
7493 strcpy(title, GOTHIC);
7496 } else if (gameInfo.variant == VariantFalcon) {
7497 strcpy(icon, programName);
7498 strcpy(title, FALCON);
7500 } else if (appData.noChessProgram) {
7501 strcpy(icon, programName);
7502 strcpy(title, programName);
7504 strcpy(icon, first.tidy);
7505 sprintf(title, "%s: %s", programName, first.tidy);
7508 XtSetArg(args[i], XtNiconName, (XtArgVal) icon); i++;
7509 XtSetArg(args[i], XtNtitle, (XtArgVal) title); i++;
7510 XtSetValues(shellWidget, args, i);
7514 void DisplayError(message, error)
7521 if (appData.debugMode || appData.matchMode) {
7522 fprintf(stderr, "%s: %s\n", programName, message);
7525 if (appData.debugMode || appData.matchMode) {
7526 fprintf(stderr, "%s: %s: %s\n",
7527 programName, message, strerror(error));
7529 sprintf(buf, "%s: %s", message, strerror(error));
7532 ErrorPopUp(_("Error"), message, FALSE);
7536 void DisplayMoveError(message)
7541 DrawPosition(FALSE, NULL);
7542 if (appData.debugMode || appData.matchMode) {
7543 fprintf(stderr, "%s: %s\n", programName, message);
7545 if (appData.popupMoveErrors) {
7546 ErrorPopUp(_("Error"), message, FALSE);
7548 DisplayMessage(message, "");
7553 void DisplayFatalError(message, error, status)
7559 errorExitStatus = status;
7561 fprintf(stderr, "%s: %s\n", programName, message);
7563 fprintf(stderr, "%s: %s: %s\n",
7564 programName, message, strerror(error));
7565 sprintf(buf, "%s: %s", message, strerror(error));
7568 if (appData.popupExitMessage && boardWidget && XtIsRealized(boardWidget)) {
7569 ErrorPopUp(status ? _("Fatal Error") : _("Exiting"), message, TRUE);
7575 void DisplayInformation(message)
7579 ErrorPopUp(_("Information"), message, TRUE);
7582 void DisplayNote(message)
7586 ErrorPopUp(_("Note"), message, FALSE);
7590 NullXErrorCheck(dpy, error_event)
7592 XErrorEvent *error_event;
7597 void DisplayIcsInteractionTitle(message)
7600 if (oldICSInteractionTitle == NULL) {
7601 /* Magic to find the old window title, adapted from vim */
7602 char *wina = getenv("WINDOWID");
7604 Window win = (Window) atoi(wina);
7605 Window root, parent, *children;
7606 unsigned int nchildren;
7607 int (*oldHandler)() = XSetErrorHandler(NullXErrorCheck);
7609 if (XFetchName(xDisplay, win, &oldICSInteractionTitle)) break;
7610 if (!XQueryTree(xDisplay, win, &root, &parent,
7611 &children, &nchildren)) break;
7612 if (children) XFree((void *)children);
7613 if (parent == root || parent == 0) break;
7616 XSetErrorHandler(oldHandler);
7618 if (oldICSInteractionTitle == NULL) {
7619 oldICSInteractionTitle = "xterm";
7622 printf("\033]0;%s\007", message);
7626 char pendingReplyPrefix[MSG_SIZ];
7627 ProcRef pendingReplyPR;
7629 void AskQuestionProc(w, event, prms, nprms)
7636 fprintf(stderr, _("AskQuestionProc needed 4 parameters, got %d\n"),
7640 AskQuestionEvent(prms[0], prms[1], prms[2], prms[3]);
7643 void AskQuestionPopDown()
7645 if (!askQuestionUp) return;
7646 XtPopdown(askQuestionShell);
7647 XtDestroyWidget(askQuestionShell);
7648 askQuestionUp = False;
7651 void AskQuestionReplyAction(w, event, prms, nprms)
7661 reply = XawDialogGetValueString(w = XtParent(w));
7662 strcpy(buf, pendingReplyPrefix);
7663 if (*buf) strcat(buf, " ");
7666 OutputToProcess(pendingReplyPR, buf, strlen(buf), &err);
7667 AskQuestionPopDown();
7669 if (err) DisplayFatalError(_("Error writing to chess program"), err, 0);
7672 void AskQuestionCallback(w, client_data, call_data)
7674 XtPointer client_data, call_data;
7679 XtSetArg(args[0], XtNlabel, &name);
7680 XtGetValues(w, args, 1);
7682 if (strcmp(name, _("cancel")) == 0) {
7683 AskQuestionPopDown();
7685 AskQuestionReplyAction(w, NULL, NULL, NULL);
7689 void AskQuestion(title, question, replyPrefix, pr)
7690 char *title, *question, *replyPrefix;
7694 Widget popup, layout, dialog, edit;
7700 strcpy(pendingReplyPrefix, replyPrefix);
7701 pendingReplyPR = pr;
7704 XtSetArg(args[i], XtNresizable, True); i++;
7705 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
7706 askQuestionShell = popup =
7707 XtCreatePopupShell(title, transientShellWidgetClass,
7708 shellWidget, args, i);
7711 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
7712 layoutArgs, XtNumber(layoutArgs));
7715 XtSetArg(args[i], XtNlabel, question); i++;
7716 XtSetArg(args[i], XtNvalue, ""); i++;
7717 XtSetArg(args[i], XtNborderWidth, 0); i++;
7718 dialog = XtCreateManagedWidget("question", dialogWidgetClass,
7721 XawDialogAddButton(dialog, _("enter"), AskQuestionCallback,
7722 (XtPointer) dialog);
7723 XawDialogAddButton(dialog, _("cancel"), AskQuestionCallback,
7724 (XtPointer) dialog);
7726 XtRealizeWidget(popup);
7727 CatchDeleteWindow(popup, "AskQuestionPopDown");
7729 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
7730 &x, &y, &win_x, &win_y, &mask);
7732 XtSetArg(args[0], XtNx, x - 10);
7733 XtSetArg(args[1], XtNy, y - 30);
7734 XtSetValues(popup, args, 2);
7736 XtPopup(popup, XtGrabExclusive);
7737 askQuestionUp = True;
7739 edit = XtNameToWidget(dialog, "*value");
7740 XtSetKeyboardFocus(popup, edit);
7748 if (*name == NULLCHAR) {
7750 } else if (strcmp(name, "$") == 0) {
7751 putc(BELLCHAR, stderr);
7754 sprintf(buf, "%s '%s' &", appData.soundProgram, name);
7762 PlaySound(appData.soundMove);
7768 PlaySound(appData.soundIcsWin);
7774 PlaySound(appData.soundIcsLoss);
7780 PlaySound(appData.soundIcsDraw);
7784 PlayIcsUnfinishedSound()
7786 PlaySound(appData.soundIcsUnfinished);
7792 PlaySound(appData.soundIcsAlarm);
7798 system("stty echo");
7804 system("stty -echo");
7808 Colorize(cc, continuation)
7813 int count, outCount, error;
7815 if (textColors[(int)cc].bg > 0) {
7816 if (textColors[(int)cc].fg > 0) {
7817 sprintf(buf, "\033[0;%d;%d;%dm", textColors[(int)cc].attr,
7818 textColors[(int)cc].fg, textColors[(int)cc].bg);
7820 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
7821 textColors[(int)cc].bg);
7824 if (textColors[(int)cc].fg > 0) {
7825 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
7826 textColors[(int)cc].fg);
7828 sprintf(buf, "\033[0;%dm", textColors[(int)cc].attr);
7831 count = strlen(buf);
7832 outCount = OutputToProcess(NoProc, buf, count, &error);
7833 if (outCount < count) {
7834 DisplayFatalError(_("Error writing to display"), error, 1);
7837 if (continuation) return;
7840 PlaySound(appData.soundShout);
7843 PlaySound(appData.soundSShout);
7846 PlaySound(appData.soundChannel1);
7849 PlaySound(appData.soundChannel);
7852 PlaySound(appData.soundKibitz);
7855 PlaySound(appData.soundTell);
7857 case ColorChallenge:
7858 PlaySound(appData.soundChallenge);
7861 PlaySound(appData.soundRequest);
7864 PlaySound(appData.soundSeek);
7875 return getpwuid(getuid())->pw_name;
7878 static char *ExpandPathName(path)
7881 static char static_buf[2000];
7882 char *d, *s, buf[2000];
7888 while (*s && isspace(*s))
7897 if (*(s+1) == '/') {
7898 strcpy(d, getpwuid(getuid())->pw_dir);
7903 *strchr(buf, '/') = 0;
7904 pwd = getpwnam(buf);
7907 fprintf(stderr, _("ERROR: Unknown user %s (in path %s)\n"),
7911 strcpy(d, pwd->pw_dir);
7912 strcat(d, strchr(s+1, '/'));
7923 static char host_name[MSG_SIZ];
7925 #if HAVE_GETHOSTNAME
7926 gethostname(host_name, MSG_SIZ);
7928 #else /* not HAVE_GETHOSTNAME */
7929 # if HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H
7930 sysinfo(SI_HOSTNAME, host_name, MSG_SIZ);
7932 # else /* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
7934 # endif/* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
7935 #endif /* not HAVE_GETHOSTNAME */
7938 XtIntervalId delayedEventTimerXID = 0;
7939 DelayedEventCallback delayedEventCallback = 0;
7944 delayedEventTimerXID = 0;
7945 delayedEventCallback();
7949 ScheduleDelayedEvent(cb, millisec)
7950 DelayedEventCallback cb; long millisec;
7952 delayedEventCallback = cb;
7953 delayedEventTimerXID =
7954 XtAppAddTimeOut(appContext, millisec,
7955 (XtTimerCallbackProc) FireDelayedEvent, (XtPointer) 0);
7958 DelayedEventCallback
7961 if (delayedEventTimerXID) {
7962 return delayedEventCallback;
7969 CancelDelayedEvent()
7971 if (delayedEventTimerXID) {
7972 XtRemoveTimeOut(delayedEventTimerXID);
7973 delayedEventTimerXID = 0;
7977 XtIntervalId loadGameTimerXID = 0;
7979 int LoadGameTimerRunning()
7981 return loadGameTimerXID != 0;
7984 int StopLoadGameTimer()
7986 if (loadGameTimerXID != 0) {
7987 XtRemoveTimeOut(loadGameTimerXID);
7988 loadGameTimerXID = 0;
7996 LoadGameTimerCallback(arg, id)
8000 loadGameTimerXID = 0;
8005 StartLoadGameTimer(millisec)
8009 XtAppAddTimeOut(appContext, millisec,
8010 (XtTimerCallbackProc) LoadGameTimerCallback,
8014 XtIntervalId analysisClockXID = 0;
8017 AnalysisClockCallback(arg, id)
8021 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile
8022 || appData.icsEngineAnalyze) { // [DM]
8023 AnalysisPeriodicEvent(0);
8024 StartAnalysisClock();
8029 StartAnalysisClock()
8032 XtAppAddTimeOut(appContext, 2000,
8033 (XtTimerCallbackProc) AnalysisClockCallback,
8037 XtIntervalId clockTimerXID = 0;
8039 int ClockTimerRunning()
8041 return clockTimerXID != 0;
8044 int StopClockTimer()
8046 if (clockTimerXID != 0) {
8047 XtRemoveTimeOut(clockTimerXID);
8056 ClockTimerCallback(arg, id)
8065 StartClockTimer(millisec)
8069 XtAppAddTimeOut(appContext, millisec,
8070 (XtTimerCallbackProc) ClockTimerCallback,
8075 DisplayTimerLabel(w, color, timer, highlight)
8084 if (appData.clockMode) {
8085 sprintf(buf, "%s: %s", color, TimeString(timer));
8086 XtSetArg(args[0], XtNlabel, buf);
8088 sprintf(buf, "%s ", color);
8089 XtSetArg(args[0], XtNlabel, buf);
8093 XtSetArg(args[1], XtNbackground, timerForegroundPixel);
8094 XtSetArg(args[2], XtNforeground, timerBackgroundPixel);
8096 XtSetArg(args[1], XtNbackground, timerBackgroundPixel);
8097 XtSetArg(args[2], XtNforeground, timerForegroundPixel);
8100 XtSetValues(w, args, 3);
8104 DisplayWhiteClock(timeRemaining, highlight)
8110 if(appData.noGUI) return;
8111 DisplayTimerLabel(whiteTimerWidget, _("White"), timeRemaining, highlight);
8112 if (highlight && iconPixmap == bIconPixmap) {
8113 iconPixmap = wIconPixmap;
8114 XtSetArg(args[0], XtNiconPixmap, iconPixmap);
8115 XtSetValues(shellWidget, args, 1);
8120 DisplayBlackClock(timeRemaining, highlight)
8126 if(appData.noGUI) return;
8127 DisplayTimerLabel(blackTimerWidget, _("Black"), timeRemaining, highlight);
8128 if (highlight && iconPixmap == wIconPixmap) {
8129 iconPixmap = bIconPixmap;
8130 XtSetArg(args[0], XtNiconPixmap, iconPixmap);
8131 XtSetValues(shellWidget, args, 1);
8149 int StartChildProcess(cmdLine, dir, pr)
8156 int to_prog[2], from_prog[2];
8160 if (appData.debugMode) {
8161 fprintf(stderr, "StartChildProcess (dir=\"%s\") %s\n",dir, cmdLine);
8164 /* We do NOT feed the cmdLine to the shell; we just
8165 parse it into blank-separated arguments in the
8166 most simple-minded way possible.
8169 strcpy(buf, cmdLine);
8174 if (p == NULL) break;
8179 SetUpChildIO(to_prog, from_prog);
8181 if ((pid = fork()) == 0) {
8183 // [HGM] PSWBTM: made order resistant against case where fd of created pipe was 0 or 1
8184 close(to_prog[1]); // first close the unused pipe ends
8185 close(from_prog[0]);
8186 dup2(to_prog[0], 0); // to_prog was created first, nd is the only one to use 0 or 1
8187 dup2(from_prog[1], 1);
8188 if(to_prog[0] >= 2) close(to_prog[0]); // if 0 or 1, the dup2 already cosed the original
8189 close(from_prog[1]); // and closing again loses one of the pipes!
8190 if(fileno(stderr) >= 2) // better safe than sorry...
8191 dup2(1, fileno(stderr)); /* force stderr to the pipe */
8193 if (dir[0] != NULLCHAR && chdir(dir) != 0) {
8198 nice(appData.niceEngines); // [HGM] nice: adjust priority of engine proc
8200 execvp(argv[0], argv);
8202 /* If we get here, exec failed */
8207 /* Parent process */
8209 close(from_prog[1]);
8211 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8214 cp->fdFrom = from_prog[0];
8215 cp->fdTo = to_prog[1];
8220 // [HGM] kill: implement the 'hard killing' of AS's Winboard_x
8221 static RETSIGTYPE AlarmCallBack(int n)
8227 DestroyChildProcess(pr, signalType)
8231 ChildProc *cp = (ChildProc *) pr;
8233 if (cp->kind != CPReal) return;
8235 if (signalType == 10) { // [HGM] kill: if it does not terminate in 3 sec, kill
8236 signal(SIGALRM, AlarmCallBack);
8238 if(wait((int *) 0) == -1) { // process does not terminate on its own accord
8239 kill(cp->pid, SIGKILL); // kill it forcefully
8240 wait((int *) 0); // and wait again
8244 kill(cp->pid, signalType == 9 ? SIGKILL : SIGTERM); // [HGM] kill: use hard kill if so requested
8246 /* Process is exiting either because of the kill or because of
8247 a quit command sent by the backend; either way, wait for it to die.
8256 InterruptChildProcess(pr)
8259 ChildProc *cp = (ChildProc *) pr;
8261 if (cp->kind != CPReal) return;
8262 (void) kill(cp->pid, SIGINT); /* stop it thinking */
8265 int OpenTelnet(host, port, pr)
8270 char cmdLine[MSG_SIZ];
8272 if (port[0] == NULLCHAR) {
8273 sprintf(cmdLine, "%s %s", appData.telnetProgram, host);
8275 sprintf(cmdLine, "%s %s %s", appData.telnetProgram, host, port);
8277 return StartChildProcess(cmdLine, "", pr);
8280 int OpenTCP(host, port, pr)
8286 DisplayFatalError(_("Socket support is not configured in"), 0, 2);
8287 #else /* !OMIT_SOCKETS */
8289 struct sockaddr_in sa;
8291 unsigned short uport;
8294 if ((s = socket(AF_INET, SOCK_STREAM, 6)) < 0) {
8298 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
8299 sa.sin_family = AF_INET;
8300 sa.sin_addr.s_addr = INADDR_ANY;
8301 uport = (unsigned short) 0;
8302 sa.sin_port = htons(uport);
8303 if (bind(s, (struct sockaddr *) &sa, sizeof(struct sockaddr_in)) < 0) {
8307 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
8308 if (!(hp = gethostbyname(host))) {
8310 if (sscanf(host, "%d.%d.%d.%d", &b0, &b1, &b2, &b3) == 4) {
8311 hp = (struct hostent *) calloc(1, sizeof(struct hostent));
8312 hp->h_addrtype = AF_INET;
8314 hp->h_addr_list = (char **) calloc(2, sizeof(char *));
8315 hp->h_addr_list[0] = (char *) malloc(4);
8316 hp->h_addr_list[0][0] = b0;
8317 hp->h_addr_list[0][1] = b1;
8318 hp->h_addr_list[0][2] = b2;
8319 hp->h_addr_list[0][3] = b3;
8324 sa.sin_family = hp->h_addrtype;
8325 uport = (unsigned short) atoi(port);
8326 sa.sin_port = htons(uport);
8327 memcpy((char *) &sa.sin_addr, hp->h_addr, hp->h_length);
8329 if (connect(s, (struct sockaddr *) &sa,
8330 sizeof(struct sockaddr_in)) < 0) {
8334 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8341 #endif /* !OMIT_SOCKETS */
8346 int OpenCommPort(name, pr)
8353 fd = open(name, 2, 0);
8354 if (fd < 0) return errno;
8356 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8366 int OpenLoopback(pr)
8372 SetUpChildIO(to, from);
8374 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8377 cp->fdFrom = to[0]; /* note not from[0]; we are doing a loopback */
8384 int OpenRcmd(host, user, cmd, pr)
8385 char *host, *user, *cmd;
8388 DisplayFatalError(_("internal rcmd not implemented for Unix"), 0, 1);
8392 #define INPUT_SOURCE_BUF_SIZE 8192
8401 char buf[INPUT_SOURCE_BUF_SIZE];
8406 DoInputCallback(closure, source, xid)
8411 InputSource *is = (InputSource *) closure;
8416 if (is->lineByLine) {
8417 count = read(is->fd, is->unused,
8418 INPUT_SOURCE_BUF_SIZE - (is->unused - is->buf));
8420 (is->func)(is, is->closure, is->buf, count, count ? errno : 0);
8423 is->unused += count;
8425 while (p < is->unused) {
8426 q = memchr(p, '\n', is->unused - p);
8427 if (q == NULL) break;
8429 (is->func)(is, is->closure, p, q - p, 0);
8433 while (p < is->unused) {
8438 count = read(is->fd, is->buf, INPUT_SOURCE_BUF_SIZE);
8443 (is->func)(is, is->closure, is->buf, count, error);
8447 InputSourceRef AddInputSource(pr, lineByLine, func, closure)
8454 ChildProc *cp = (ChildProc *) pr;
8456 is = (InputSource *) calloc(1, sizeof(InputSource));
8457 is->lineByLine = lineByLine;
8461 is->fd = fileno(stdin);
8463 is->kind = cp->kind;
8464 is->fd = cp->fdFrom;
8467 is->unused = is->buf;
8470 is->xid = XtAppAddInput(appContext, is->fd,
8471 (XtPointer) (XtInputReadMask),
8472 (XtInputCallbackProc) DoInputCallback,
8474 is->closure = closure;
8475 return (InputSourceRef) is;
8479 RemoveInputSource(isr)
8482 InputSource *is = (InputSource *) isr;
8484 if (is->xid == 0) return;
8485 XtRemoveInput(is->xid);
8489 int OutputToProcess(pr, message, count, outError)
8495 ChildProc *cp = (ChildProc *) pr;
8499 outCount = fwrite(message, 1, count, stdout);
8501 outCount = write(cp->fdTo, message, count);
8511 /* Output message to process, with "ms" milliseconds of delay
8512 between each character. This is needed when sending the logon
8513 script to ICC, which for some reason doesn't like the
8514 instantaneous send. */
8515 int OutputToProcessDelayed(pr, message, count, outError, msdelay)
8522 ChildProc *cp = (ChildProc *) pr;
8527 r = write(cp->fdTo, message++, 1);
8540 /**** Animation code by Hugh Fisher, DCS, ANU.
8542 Known problem: if a window overlapping the board is
8543 moved away while a piece is being animated underneath,
8544 the newly exposed area won't be updated properly.
8545 I can live with this.
8547 Known problem: if you look carefully at the animation
8548 of pieces in mono mode, they are being drawn as solid
8549 shapes without interior detail while moving. Fixing
8550 this would be a major complication for minimal return.
8553 /* Masks for XPM pieces. Black and white pieces can have
8554 different shapes, but in the interest of retaining my
8555 sanity pieces must have the same outline on both light
8556 and dark squares, and all pieces must use the same
8557 background square colors/images. */
8560 CreateAnimMasks (pieceDepth)
8567 unsigned long plane;
8570 /* Need a bitmap just to get a GC with right depth */
8571 buf = XCreatePixmap(xDisplay, xBoardWindow,
8573 values.foreground = 1;
8574 values.background = 0;
8575 /* Don't use XtGetGC, not read only */
8576 maskGC = XCreateGC(xDisplay, buf,
8577 GCForeground | GCBackground, &values);
8578 XFreePixmap(xDisplay, buf);
8580 buf = XCreatePixmap(xDisplay, xBoardWindow,
8581 squareSize, squareSize, pieceDepth);
8582 values.foreground = XBlackPixel(xDisplay, xScreen);
8583 values.background = XWhitePixel(xDisplay, xScreen);
8584 bufGC = XCreateGC(xDisplay, buf,
8585 GCForeground | GCBackground, &values);
8587 for (piece = WhitePawn; piece <= BlackKing; piece++) {
8588 /* Begin with empty mask */
8589 xpmMask[piece] = XCreatePixmap(xDisplay, xBoardWindow,
8590 squareSize, squareSize, 1);
8591 XSetFunction(xDisplay, maskGC, GXclear);
8592 XFillRectangle(xDisplay, xpmMask[piece], maskGC,
8593 0, 0, squareSize, squareSize);
8595 /* Take a copy of the piece */
8600 XSetFunction(xDisplay, bufGC, GXcopy);
8601 XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % (int)BlackPawn],
8603 0, 0, squareSize, squareSize, 0, 0);
8605 /* XOR the background (light) over the piece */
8606 XSetFunction(xDisplay, bufGC, GXxor);
8608 XCopyArea(xDisplay, xpmLightSquare, buf, bufGC,
8609 0, 0, squareSize, squareSize, 0, 0);
8611 XSetForeground(xDisplay, bufGC, lightSquareColor);
8612 XFillRectangle(xDisplay, buf, bufGC, 0, 0, squareSize, squareSize);
8615 /* We now have an inverted piece image with the background
8616 erased. Construct mask by just selecting all the non-zero
8617 pixels - no need to reconstruct the original image. */
8618 XSetFunction(xDisplay, maskGC, GXor);
8620 /* Might be quicker to download an XImage and create bitmap
8621 data from it rather than this N copies per piece, but it
8622 only takes a fraction of a second and there is a much
8623 longer delay for loading the pieces. */
8624 for (n = 0; n < pieceDepth; n ++) {
8625 XCopyPlane(xDisplay, buf, xpmMask[piece], maskGC,
8626 0, 0, squareSize, squareSize,
8632 XFreePixmap(xDisplay, buf);
8633 XFreeGC(xDisplay, bufGC);
8634 XFreeGC(xDisplay, maskGC);
8638 InitAnimState (anim, info)
8640 XWindowAttributes * info;
8645 /* Each buffer is square size, same depth as window */
8646 anim->saveBuf = XCreatePixmap(xDisplay, xBoardWindow,
8647 squareSize, squareSize, info->depth);
8648 anim->newBuf = XCreatePixmap(xDisplay, xBoardWindow,
8649 squareSize, squareSize, info->depth);
8651 /* Create a plain GC for blitting */
8652 mask = GCForeground | GCBackground | GCFunction |
8653 GCPlaneMask | GCGraphicsExposures;
8654 values.foreground = XBlackPixel(xDisplay, xScreen);
8655 values.background = XWhitePixel(xDisplay, xScreen);
8656 values.function = GXcopy;
8657 values.plane_mask = AllPlanes;
8658 values.graphics_exposures = False;
8659 anim->blitGC = XCreateGC(xDisplay, xBoardWindow, mask, &values);
8661 /* Piece will be copied from an existing context at
8662 the start of each new animation/drag. */
8663 anim->pieceGC = XCreateGC(xDisplay, xBoardWindow, 0, &values);
8665 /* Outline will be a read-only copy of an existing */
8666 anim->outlineGC = None;
8672 static int done = 0;
8673 XWindowAttributes info;
8677 XGetWindowAttributes(xDisplay, xBoardWindow, &info);
8679 InitAnimState(&game, &info);
8680 InitAnimState(&player, &info);
8682 /* For XPM pieces, we need bitmaps to use as masks. */
8684 CreateAnimMasks(info.depth);
8689 static Boolean frameWaiting;
8691 static RETSIGTYPE FrameAlarm (sig)
8694 frameWaiting = False;
8695 /* In case System-V style signals. Needed?? */
8696 signal(SIGALRM, FrameAlarm);
8703 struct itimerval delay;
8705 XSync(xDisplay, False);
8708 frameWaiting = True;
8709 signal(SIGALRM, FrameAlarm);
8710 delay.it_interval.tv_sec =
8711 delay.it_value.tv_sec = time / 1000;
8712 delay.it_interval.tv_usec =
8713 delay.it_value.tv_usec = (time % 1000) * 1000;
8714 setitimer(ITIMER_REAL, &delay, NULL);
8716 /* Ugh -- busy-wait! --tpm */
8717 while (frameWaiting);
8719 while (frameWaiting) pause();
8721 delay.it_interval.tv_sec = delay.it_value.tv_sec = 0;
8722 delay.it_interval.tv_usec = delay.it_value.tv_usec = 0;
8723 setitimer(ITIMER_REAL, &delay, NULL);
8733 XSync(xDisplay, False);
8735 usleep(time * 1000);
8740 /* Convert board position to corner of screen rect and color */
8743 ScreenSquare(column, row, pt, color)
8744 int column; int row; XPoint * pt; int * color;
8747 pt->x = lineGap + ((BOARD_WIDTH-1)-column) * (squareSize + lineGap);
8748 pt->y = lineGap + row * (squareSize + lineGap);
8750 pt->x = lineGap + column * (squareSize + lineGap);
8751 pt->y = lineGap + ((BOARD_HEIGHT-1)-row) * (squareSize + lineGap);
8753 *color = SquareColor(row, column);
8756 /* Convert window coords to square */
8759 BoardSquare(x, y, column, row)
8760 int x; int y; int * column; int * row;
8762 *column = EventToSquare(x, BOARD_WIDTH);
8763 if (flipView && *column >= 0)
8764 *column = BOARD_WIDTH - 1 - *column;
8765 *row = EventToSquare(y, BOARD_HEIGHT);
8766 if (!flipView && *row >= 0)
8767 *row = BOARD_HEIGHT - 1 - *row;
8772 #undef Max /* just in case */
8774 #define Max(a, b) ((a) > (b) ? (a) : (b))
8775 #define Min(a, b) ((a) < (b) ? (a) : (b))
8778 SetRect(rect, x, y, width, height)
8779 XRectangle * rect; int x; int y; int width; int height;
8783 rect->width = width;
8784 rect->height = height;
8787 /* Test if two frames overlap. If they do, return
8788 intersection rect within old and location of
8789 that rect within new. */
8792 Intersect(old, new, size, area, pt)
8793 XPoint * old; XPoint * new;
8794 int size; XRectangle * area; XPoint * pt;
8796 if (old->x > new->x + size || new->x > old->x + size ||
8797 old->y > new->y + size || new->y > old->y + size) {
8800 SetRect(area, Max(new->x - old->x, 0), Max(new->y - old->y, 0),
8801 size - abs(old->x - new->x), size - abs(old->y - new->y));
8802 pt->x = Max(old->x - new->x, 0);
8803 pt->y = Max(old->y - new->y, 0);
8808 /* For two overlapping frames, return the rect(s)
8809 in the old that do not intersect with the new. */
8812 CalcUpdateRects(old, new, size, update, nUpdates)
8813 XPoint * old; XPoint * new; int size;
8814 XRectangle update[]; int * nUpdates;
8818 /* If old = new (shouldn't happen) then nothing to draw */
8819 if (old->x == new->x && old->y == new->y) {
8823 /* Work out what bits overlap. Since we know the rects
8824 are the same size we don't need a full intersect calc. */
8826 /* Top or bottom edge? */
8827 if (new->y > old->y) {
8828 SetRect(&(update[count]), old->x, old->y, size, new->y - old->y);
8830 } else if (old->y > new->y) {
8831 SetRect(&(update[count]), old->x, old->y + size - (old->y - new->y),
8832 size, old->y - new->y);
8835 /* Left or right edge - don't overlap any update calculated above. */
8836 if (new->x > old->x) {
8837 SetRect(&(update[count]), old->x, Max(new->y, old->y),
8838 new->x - old->x, size - abs(new->y - old->y));
8840 } else if (old->x > new->x) {
8841 SetRect(&(update[count]), new->x + size, Max(new->y, old->y),
8842 old->x - new->x, size - abs(new->y - old->y));
8849 /* Generate a series of frame coords from start->mid->finish.
8850 The movement rate doubles until the half way point is
8851 reached, then halves back down to the final destination,
8852 which gives a nice slow in/out effect. The algorithmn
8853 may seem to generate too many intermediates for short
8854 moves, but remember that the purpose is to attract the
8855 viewers attention to the piece about to be moved and
8856 then to where it ends up. Too few frames would be less
8860 Tween(start, mid, finish, factor, frames, nFrames)
8861 XPoint * start; XPoint * mid;
8862 XPoint * finish; int factor;
8863 XPoint frames[]; int * nFrames;
8865 int fraction, n, count;
8869 /* Slow in, stepping 1/16th, then 1/8th, ... */
8871 for (n = 0; n < factor; n++)
8873 for (n = 0; n < factor; n++) {
8874 frames[count].x = start->x + (mid->x - start->x) / fraction;
8875 frames[count].y = start->y + (mid->y - start->y) / fraction;
8877 fraction = fraction / 2;
8881 frames[count] = *mid;
8884 /* Slow out, stepping 1/2, then 1/4, ... */
8886 for (n = 0; n < factor; n++) {
8887 frames[count].x = finish->x - (finish->x - mid->x) / fraction;
8888 frames[count].y = finish->y - (finish->y - mid->y) / fraction;
8890 fraction = fraction * 2;
8895 /* Draw a piece on the screen without disturbing what's there */
8898 SelectGCMask(piece, clip, outline, mask)
8899 ChessSquare piece; GC * clip; GC * outline; Pixmap * mask;
8903 /* Bitmap for piece being moved. */
8904 if (appData.monoMode) {
8905 *mask = *pieceToSolid(piece);
8906 } else if (useImages) {
8908 *mask = xpmMask[piece];
8910 *mask = ximMaskPm[piece%(int)BlackPawn];
8913 *mask = *pieceToSolid(piece);
8916 /* GC for piece being moved. Square color doesn't matter, but
8917 since it gets modified we make a copy of the original. */
8919 if (appData.monoMode)
8924 if (appData.monoMode)
8929 XCopyGC(xDisplay, source, 0xFFFFFFFF, *clip);
8931 /* Outline only used in mono mode and is not modified */
8933 *outline = bwPieceGC;
8935 *outline = wbPieceGC;
8939 OverlayPiece(piece, clip, outline, dest)
8940 ChessSquare piece; GC clip; GC outline; Drawable dest;
8945 /* Draw solid rectangle which will be clipped to shape of piece */
8946 XFillRectangle(xDisplay, dest, clip,
8947 0, 0, squareSize, squareSize);
8948 if (appData.monoMode)
8949 /* Also draw outline in contrasting color for black
8950 on black / white on white cases */
8951 XCopyPlane(xDisplay, *pieceToOutline(piece), dest, outline,
8952 0, 0, squareSize, squareSize, 0, 0, 1);
8954 /* Copy the piece */
8959 XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % (int)BlackPawn],
8961 0, 0, squareSize, squareSize,
8966 /* Animate the movement of a single piece */
8969 BeginAnimation(anim, piece, startColor, start)
8977 /* The old buffer is initialised with the start square (empty) */
8978 BlankSquare(0, 0, startColor, EmptySquare, anim->saveBuf);
8979 anim->prevFrame = *start;
8981 /* The piece will be drawn using its own bitmap as a matte */
8982 SelectGCMask(piece, &anim->pieceGC, &anim->outlineGC, &mask);
8983 XSetClipMask(xDisplay, anim->pieceGC, mask);
8987 AnimationFrame(anim, frame, piece)
8992 XRectangle updates[4];
8997 /* Save what we are about to draw into the new buffer */
8998 XCopyArea(xDisplay, xBoardWindow, anim->newBuf, anim->blitGC,
8999 frame->x, frame->y, squareSize, squareSize,
9002 /* Erase bits of the previous frame */
9003 if (Intersect(&anim->prevFrame, frame, squareSize, &overlap, &pt)) {
9004 /* Where the new frame overlapped the previous,
9005 the contents in newBuf are wrong. */
9006 XCopyArea(xDisplay, anim->saveBuf, anim->newBuf, anim->blitGC,
9007 overlap.x, overlap.y,
9008 overlap.width, overlap.height,
9010 /* Repaint the areas in the old that don't overlap new */
9011 CalcUpdateRects(&anim->prevFrame, frame, squareSize, updates, &count);
9012 for (i = 0; i < count; i++)
9013 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9014 updates[i].x - anim->prevFrame.x,
9015 updates[i].y - anim->prevFrame.y,
9016 updates[i].width, updates[i].height,
9017 updates[i].x, updates[i].y);
9019 /* Easy when no overlap */
9020 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9021 0, 0, squareSize, squareSize,
9022 anim->prevFrame.x, anim->prevFrame.y);
9025 /* Save this frame for next time round */
9026 XCopyArea(xDisplay, anim->newBuf, anim->saveBuf, anim->blitGC,
9027 0, 0, squareSize, squareSize,
9029 anim->prevFrame = *frame;
9031 /* Draw piece over original screen contents, not current,
9032 and copy entire rect. Wipes out overlapping piece images. */
9033 OverlayPiece(piece, anim->pieceGC, anim->outlineGC, anim->newBuf);
9034 XCopyArea(xDisplay, anim->newBuf, xBoardWindow, anim->blitGC,
9035 0, 0, squareSize, squareSize,
9036 frame->x, frame->y);
9040 EndAnimation (anim, finish)
9044 XRectangle updates[4];
9049 /* The main code will redraw the final square, so we
9050 only need to erase the bits that don't overlap. */
9051 if (Intersect(&anim->prevFrame, finish, squareSize, &overlap, &pt)) {
9052 CalcUpdateRects(&anim->prevFrame, finish, squareSize, updates, &count);
9053 for (i = 0; i < count; i++)
9054 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9055 updates[i].x - anim->prevFrame.x,
9056 updates[i].y - anim->prevFrame.y,
9057 updates[i].width, updates[i].height,
9058 updates[i].x, updates[i].y);
9060 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9061 0, 0, squareSize, squareSize,
9062 anim->prevFrame.x, anim->prevFrame.y);
9067 FrameSequence(anim, piece, startColor, start, finish, frames, nFrames)
9069 ChessSquare piece; int startColor;
9070 XPoint * start; XPoint * finish;
9071 XPoint frames[]; int nFrames;
9075 BeginAnimation(anim, piece, startColor, start);
9076 for (n = 0; n < nFrames; n++) {
9077 AnimationFrame(anim, &(frames[n]), piece);
9078 FrameDelay(appData.animSpeed);
9080 EndAnimation(anim, finish);
9083 /* Main control logic for deciding what to animate and how */
9086 AnimateMove(board, fromX, fromY, toX, toY)
9095 XPoint start, finish, mid;
9096 XPoint frames[kFactor * 2 + 1];
9097 int nFrames, startColor, endColor;
9099 /* Are we animating? */
9100 if (!appData.animate || appData.blindfold)
9103 if (fromY < 0 || fromX < 0 || toX < 0 || toY < 0) return;
9104 piece = board[fromY][fromX];
9105 if (piece >= EmptySquare) return;
9110 hop = (piece == WhiteKnight || piece == BlackKnight);
9113 if (appData.debugMode) {
9114 fprintf(debugFP, hop ? _("AnimateMove: piece %d hops from %d,%d to %d,%d \n") :
9115 _("AnimateMove: piece %d slides from %d,%d to %d,%d \n"),
9116 piece, fromX, fromY, toX, toY); }
9118 ScreenSquare(fromX, fromY, &start, &startColor);
9119 ScreenSquare(toX, toY, &finish, &endColor);
9122 /* Knight: make diagonal movement then straight */
9123 if (abs(toY - fromY) < abs(toX - fromX)) {
9124 mid.x = start.x + (finish.x - start.x) / 2;
9128 mid.y = start.y + (finish.y - start.y) / 2;
9131 mid.x = start.x + (finish.x - start.x) / 2;
9132 mid.y = start.y + (finish.y - start.y) / 2;
9135 /* Don't use as many frames for very short moves */
9136 if (abs(toY - fromY) + abs(toX - fromX) <= 2)
9137 Tween(&start, &mid, &finish, kFactor - 1, frames, &nFrames);
9139 Tween(&start, &mid, &finish, kFactor, frames, &nFrames);
9140 FrameSequence(&game, piece, startColor, &start, &finish, frames, nFrames);
9142 /* Be sure end square is redrawn */
9143 damage[toY][toX] = True;
9147 DragPieceBegin(x, y)
9150 int boardX, boardY, color;
9153 /* Are we animating? */
9154 if (!appData.animateDragging || appData.blindfold)
9157 /* Figure out which square we start in and the
9158 mouse position relative to top left corner. */
9159 BoardSquare(x, y, &boardX, &boardY);
9160 player.startBoardX = boardX;
9161 player.startBoardY = boardY;
9162 ScreenSquare(boardX, boardY, &corner, &color);
9163 player.startSquare = corner;
9164 player.startColor = color;
9166 /* Start from exactly where the piece is. This can be confusing
9167 if you start dragging far from the center of the square; most
9168 or all of the piece can be over a different square from the one
9169 the mouse pointer is in. */
9170 player.mouseDelta.x = x - corner.x;
9171 player.mouseDelta.y = y - corner.y;
9173 /* As soon as we start dragging, the piece will jump slightly to
9174 be centered over the mouse pointer. */
9175 player.mouseDelta.x = squareSize/2;
9176 player.mouseDelta.y = squareSize/2;
9178 /* Initialise animation */
9179 player.dragPiece = PieceForSquare(boardX, boardY);
9181 if (player.dragPiece >= 0 && player.dragPiece < EmptySquare) {
9182 player.dragActive = True;
9183 BeginAnimation(&player, player.dragPiece, color, &corner);
9184 /* Mark this square as needing to be redrawn. Note that
9185 we don't remove the piece though, since logically (ie
9186 as seen by opponent) the move hasn't been made yet. */
9187 if(boardX == BOARD_RGHT+1 && PieceForSquare(boardX-1, boardY) > 1 ||
9188 boardX == BOARD_LEFT-2 && PieceForSquare(boardX+1, boardY) > 1)
9189 XCopyArea(xDisplay, xBoardWindow, player.saveBuf, player.blitGC,
9190 corner.x, corner.y, squareSize, squareSize,
9191 0, 0); // [HGM] zh: unstack in stead of grab
9192 damage[boardY][boardX] = True;
9194 player.dragActive = False;
9204 /* Are we animating? */
9205 if (!appData.animateDragging || appData.blindfold)
9209 if (! player.dragActive)
9211 /* Move piece, maintaining same relative position
9212 of mouse within square */
9213 corner.x = x - player.mouseDelta.x;
9214 corner.y = y - player.mouseDelta.y;
9215 AnimationFrame(&player, &corner, player.dragPiece);
9217 if (appData.highlightDragging) {
9219 BoardSquare(x, y, &boardX, &boardY);
9220 SetHighlights(fromX, fromY, boardX, boardY);
9229 int boardX, boardY, color;
9232 /* Are we animating? */
9233 if (!appData.animateDragging || appData.blindfold)
9237 if (! player.dragActive)
9239 /* Last frame in sequence is square piece is
9240 placed on, which may not match mouse exactly. */
9241 BoardSquare(x, y, &boardX, &boardY);
9242 ScreenSquare(boardX, boardY, &corner, &color);
9243 EndAnimation(&player, &corner);
9245 /* Be sure end square is redrawn */
9246 damage[boardY][boardX] = True;
9248 /* This prevents weird things happening with fast successive
9249 clicks which on my Sun at least can cause motion events
9250 without corresponding press/release. */
9251 player.dragActive = False;
9254 /* Handle expose event while piece being dragged */
9259 if (!player.dragActive || appData.blindfold)
9262 /* What we're doing: logically, the move hasn't been made yet,
9263 so the piece is still in it's original square. But visually
9264 it's being dragged around the board. So we erase the square
9265 that the piece is on and draw it at the last known drag point. */
9266 BlankSquare(player.startSquare.x, player.startSquare.y,
9267 player.startColor, EmptySquare, xBoardWindow);
9268 AnimationFrame(&player, &player.prevFrame, player.dragPiece);
9269 damage[player.startBoardY][player.startBoardX] = TRUE;
9273 SetProgramStats( FrontEndProgramStats * stats )
9276 // [HGM] done, but perhaps backend should call this directly?
9277 EngineOutputUpdate( stats );