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},
1220 // [HGM] 4.3.xx options
1221 { "boardWidth", "boardWidth", XtRInt,
1222 sizeof(int), XtOffset(AppDataPtr, NrFiles),
1223 XtRImmediate, (XtPointer) -1},
1224 { "boardHeight", "boardHeight", XtRInt,
1225 sizeof(int), XtOffset(AppDataPtr, NrRanks),
1226 XtRImmediate, (XtPointer) -1},
1227 { "matchPause", "matchPause", XtRInt,
1228 sizeof(int), XtOffset(AppDataPtr, matchPause),
1229 XtRImmediate, (XtPointer) 10000},
1230 { "holdingsSize", "holdingsSize", XtRInt,
1231 sizeof(int), XtOffset(AppDataPtr, holdingsSize),
1232 XtRImmediate, (XtPointer) -1},
1233 { "flipBlack", "flipBlack", XtRBoolean,
1234 sizeof(Boolean), XtOffset(AppDataPtr, upsideDown),
1235 XtRImmediate, (XtPointer) False},
1236 { "allWhite", "allWhite", XtRBoolean,
1237 sizeof(Boolean), XtOffset(AppDataPtr, allWhite),
1238 XtRImmediate, (XtPointer) False},
1239 { "pieceToCharTable", "pieceToCharTable", XtRString,
1240 sizeof(String), XtOffset(AppDataPtr, pieceToCharTable),
1241 XtRImmediate, (XtPointer) 0},
1242 { "alphaRank", "alphaRank", XtRBoolean,
1243 sizeof(Boolean), XtOffset(AppDataPtr, alphaRank),
1244 XtRImmediate, (XtPointer) False},
1245 { "testClaims", "testClaims", XtRBoolean,
1246 sizeof(Boolean), XtOffset(AppDataPtr, testClaims),
1247 XtRImmediate, (XtPointer) True},
1248 { "checkMates", "checkMates", XtRBoolean,
1249 sizeof(Boolean), XtOffset(AppDataPtr, checkMates),
1250 XtRImmediate, (XtPointer) True},
1251 { "materialDraws", "materialDraws", XtRBoolean,
1252 sizeof(Boolean), XtOffset(AppDataPtr, materialDraws),
1253 XtRImmediate, (XtPointer) True},
1254 { "trivialDraws", "trivialDraws", XtRBoolean,
1255 sizeof(Boolean), XtOffset(AppDataPtr, trivialDraws),
1256 XtRImmediate, (XtPointer) False},
1257 { "ruleMoves", "ruleMoves", XtRInt,
1258 sizeof(int), XtOffset(AppDataPtr, ruleMoves),
1259 XtRImmediate, (XtPointer) 51},
1260 { "repeatsToDraw", "repeatsToDraw", XtRInt,
1261 sizeof(int), XtOffset(AppDataPtr, drawRepeats),
1262 XtRImmediate, (XtPointer) 6},
1263 { "engineDebugOutput", "engineDebugOutput", XtRInt,
1264 sizeof(int), XtOffset(AppDataPtr, engineComments),
1265 XtRImmediate, (XtPointer) 1},
1266 { "userName", "userName", XtRString,
1267 sizeof(int), XtOffset(AppDataPtr, userName),
1268 XtRImmediate, (XtPointer) 0},
1269 { "autoKibitz", "autoKibitz", XtRBoolean,
1270 sizeof(Boolean), XtOffset(AppDataPtr, autoKibitz),
1271 XtRImmediate, (XtPointer) False},
1272 { "firstTimeOdds", "firstTimeOdds", XtRInt,
1273 sizeof(int), XtOffset(AppDataPtr, firstTimeOdds),
1274 XtRImmediate, (XtPointer) 1},
1275 { "secondTimeOdds", "secondTimeOdds", XtRInt,
1276 sizeof(int), XtOffset(AppDataPtr, secondTimeOdds),
1277 XtRImmediate, (XtPointer) 1},
1278 { "timeOddsMode", "timeOddsMode", XtRInt,
1279 sizeof(int), XtOffset(AppDataPtr, timeOddsMode),
1280 XtRImmediate, (XtPointer) 0},
1281 { "firstAccumulateTC", "firstAccumulateTC", XtRInt,
1282 sizeof(int), XtOffset(AppDataPtr, firstAccumulateTC),
1283 XtRImmediate, (XtPointer) 1},
1284 { "secondAccumulateTC", "secondAccumulateTC", XtRInt,
1285 sizeof(int), XtOffset(AppDataPtr, secondAccumulateTC),
1286 XtRImmediate, (XtPointer) 1},
1287 { "firstNPS", "firstNPS", XtRInt,
1288 sizeof(int), XtOffset(AppDataPtr, firstNPS),
1289 XtRImmediate, (XtPointer) -1},
1290 { "secondNPS", "secondNPS", XtRInt,
1291 sizeof(int), XtOffset(AppDataPtr, secondNPS),
1292 XtRImmediate, (XtPointer) -1},
1293 { "serverMoves", "serverMoves", XtRString,
1294 sizeof(String), XtOffset(AppDataPtr, serverMovesName),
1295 XtRImmediate, (XtPointer) 0},
1296 { "serverPause", "serverPause", XtRInt,
1297 sizeof(int), XtOffset(AppDataPtr, serverPause),
1298 XtRImmediate, (XtPointer) 0},
1299 { "suppressLoadMoves", "suppressLoadMoves", XtRBoolean,
1300 sizeof(Boolean), XtOffset(AppDataPtr, suppressLoadMoves),
1301 XtRImmediate, (XtPointer) False},
1302 { "userName", "userName", XtRString,
1303 sizeof(String), XtOffset(AppDataPtr, userName),
1304 XtRImmediate, (XtPointer) 0},
1305 { "egtFormats", "egtFormats", XtRString,
1306 sizeof(String), XtOffset(AppDataPtr, egtFormats),
1307 XtRImmediate, (XtPointer) 0},
1308 { "rewindIndex", "rewindIndex", XtRInt,
1309 sizeof(int), XtOffset(AppDataPtr, rewindIndex),
1310 XtRImmediate, (XtPointer) 0},
1311 { "sameColorGames", "sameColorGames", XtRInt,
1312 sizeof(int), XtOffset(AppDataPtr, sameColorGames),
1313 XtRImmediate, (XtPointer) 0},
1314 { "smpCores", "smpCores", XtRInt,
1315 sizeof(int), XtOffset(AppDataPtr, smpCores),
1316 XtRImmediate, (XtPointer) 1},
1317 { "niceEngines", "niceEngines", XtRInt,
1318 sizeof(int), XtOffset(AppDataPtr, niceEngines),
1319 XtRImmediate, (XtPointer) 0},
1320 { "nameOfDebugFile", "nameOfDebugFile", XtRString,
1321 sizeof(String), XtOffset(AppDataPtr, nameOfDebugFile),
1322 XtRImmediate, (XtPointer) "xboard.debug"},
1323 { "engineDebugOutput", "engineDebugOutput", XtRInt,
1324 sizeof(int), XtOffset(AppDataPtr, engineComments),
1325 XtRImmediate, (XtPointer) 0},
1326 { "noGUI", "noGUI", XtRBoolean,
1327 sizeof(Boolean), XtOffset(AppDataPtr, noGUI),
1328 XtRImmediate, (XtPointer) 0},
1329 { "firstOptions", "firstOptions", XtRString,
1330 sizeof(String), XtOffset(AppDataPtr, firstOptions),
1331 XtRImmediate, (XtPointer) "" },
1332 { "secondOptions", "secondOptions", XtRString,
1333 sizeof(String), XtOffset(AppDataPtr, secondOptions),
1334 XtRImmediate, (XtPointer) "" },
1336 // [HGM] Winboard_x UCI options
1337 { "firstIsUCI", "firstIsUCI", XtRBoolean,
1338 sizeof(Boolean), XtOffset(AppDataPtr, firstIsUCI),
1339 XtRImmediate, (XtPointer) False},
1340 { "secondIsUCI", "secondIsUCI", XtRBoolean,
1341 sizeof(Boolean), XtOffset(AppDataPtr, secondIsUCI),
1342 XtRImmediate, (XtPointer) False},
1343 { "firstHasOwnBookUCI", "firstHasOwnBookUCI", XtRBoolean,
1344 sizeof(Boolean), XtOffset(AppDataPtr, firstHasOwnBookUCI),
1345 XtRImmediate, (XtPointer) True},
1346 { "secondHasOwnBookUCI", "secondHasOwnBookUCI", XtRBoolean,
1347 sizeof(Boolean), XtOffset(AppDataPtr, secondHasOwnBookUCI),
1348 XtRImmediate, (XtPointer) True},
1349 { "usePolyglotBook", "usePolyglotBook", XtRBoolean,
1350 sizeof(Boolean), XtOffset(AppDataPtr, usePolyglotBook),
1351 XtRImmediate, (XtPointer) False},
1352 { "defaultHashSize", "defaultHashSize", XtRInt,
1353 sizeof(int), XtOffset(AppDataPtr, defaultHashSize),
1354 XtRImmediate, (XtPointer) 64},
1355 { "defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XtRInt,
1356 sizeof(int), XtOffset(AppDataPtr, defaultCacheSizeEGTB),
1357 XtRImmediate, (XtPointer) 4},
1358 { "polyglotDir", "polyglotDir", XtRString,
1359 sizeof(String), XtOffset(AppDataPtr, polyglotDir),
1360 XtRImmediate, (XtPointer) "." },
1361 { "polyglotBook", "polyglotBook", XtRString,
1362 sizeof(String), XtOffset(AppDataPtr, polyglotBook),
1363 XtRImmediate, (XtPointer) "" },
1364 { "defaultPathEGTB", "defaultPathEGTB", XtRString,
1365 sizeof(String), XtOffset(AppDataPtr, defaultPathEGTB),
1366 XtRImmediate, (XtPointer) "/usr/local/share/egtb"},
1367 { "delayBeforeQuit", "delayBeforeQuit", XtRInt,
1368 sizeof(int), XtOffset(AppDataPtr, delayBeforeQuit),
1369 XtRImmediate, (XtPointer) 0},
1370 { "delayAfterQuit", "delayAfterQuit", XtRInt,
1371 sizeof(int), XtOffset(AppDataPtr, delayAfterQuit),
1372 XtRImmediate, (XtPointer) 0},
1375 XrmOptionDescRec shellOptions[] = {
1376 { "-whitePieceColor", "whitePieceColor", XrmoptionSepArg, NULL },
1377 { "-blackPieceColor", "blackPieceColor", XrmoptionSepArg, NULL },
1378 { "-lightSquareColor", "lightSquareColor", XrmoptionSepArg, NULL },
1379 { "-darkSquareColor", "darkSquareColor", XrmoptionSepArg, NULL },
1380 { "-highlightSquareColor", "highlightSquareColor", XrmoptionSepArg, NULL },
1381 { "-premoveHighlightColor", "premoveHighlightColor", XrmoptionSepArg,NULL},
1382 { "-movesPerSession", "movesPerSession", XrmoptionSepArg, NULL },
1383 { "-mps", "movesPerSession", XrmoptionSepArg, NULL },
1384 { "-timeIncrement", "timeIncrement", XrmoptionSepArg, NULL },
1385 { "-inc", "timeIncrement", XrmoptionSepArg, NULL },
1386 { "-initString", "initString", XrmoptionSepArg, NULL },
1387 { "-firstInitString", "initString", XrmoptionSepArg, NULL },
1388 { "-secondInitString", "secondInitString", XrmoptionSepArg, NULL },
1389 { "-firstComputerString", "firstComputerString", XrmoptionSepArg, NULL },
1390 { "-secondComputerString", "secondComputerString", XrmoptionSepArg, NULL },
1391 { "-firstChessProgram", "firstChessProgram", XrmoptionSepArg, NULL },
1392 { "-fcp", "firstChessProgram", XrmoptionSepArg, NULL },
1393 { "-secondChessProgram", "secondChessProgram", XrmoptionSepArg, NULL },
1394 { "-scp", "secondChessProgram", XrmoptionSepArg, NULL },
1395 { "-firstPlaysBlack", "firstPlaysBlack", XrmoptionSepArg, NULL },
1396 { "-fb", "firstPlaysBlack", XrmoptionNoArg, "True" },
1397 { "-xfb", "firstPlaysBlack", XrmoptionNoArg, "False" },
1398 { "-noChessProgram", "noChessProgram", XrmoptionSepArg, NULL },
1399 { "-ncp", "noChessProgram", XrmoptionNoArg, "True" },
1400 { "-xncp", "noChessProgram", XrmoptionNoArg, "False" },
1401 { "-firstHost", "firstHost", XrmoptionSepArg, NULL },
1402 { "-fh", "firstHost", XrmoptionSepArg, NULL },
1403 { "-secondHost", "secondHost", XrmoptionSepArg, NULL },
1404 { "-sh", "secondHost", XrmoptionSepArg, NULL },
1405 { "-firstDirectory", "firstDirectory", XrmoptionSepArg, NULL },
1406 { "-fd", "firstDirectory", XrmoptionSepArg, NULL },
1407 { "-secondDirectory", "secondDirectory", XrmoptionSepArg, NULL },
1408 { "-sd", "secondDirectory", XrmoptionSepArg, NULL },
1409 { "-bitmapDirectory", "bitmapDirectory", XrmoptionSepArg, NULL },
1410 { "-bm", "bitmapDirectory", XrmoptionSepArg, NULL },
1411 { "-remoteShell", "remoteShell", XrmoptionSepArg, NULL },
1412 { "-rsh", "remoteShell", XrmoptionSepArg, NULL },
1413 { "-remoteUser", "remoteUser", XrmoptionSepArg, NULL },
1414 { "-ruser", "remoteUser", XrmoptionSepArg, NULL },
1415 { "-timeDelay", "timeDelay", XrmoptionSepArg, NULL },
1416 { "-td", "timeDelay", XrmoptionSepArg, NULL },
1417 { "-timeControl", "timeControl", XrmoptionSepArg, NULL },
1418 { "-tc", "timeControl", XrmoptionSepArg, NULL },
1419 { "-internetChessServerMode", "internetChessServerMode",
1420 XrmoptionSepArg, NULL },
1421 { "-ics", "internetChessServerMode", XrmoptionNoArg, "True" },
1422 { "-xics", "internetChessServerMode", XrmoptionNoArg, "False" },
1423 { "-internetChessServerHost", "internetChessServerHost",
1424 XrmoptionSepArg, NULL },
1425 { "-icshost", "internetChessServerHost", XrmoptionSepArg, NULL },
1426 { "-internetChessServerPort", "internetChessServerPort",
1427 XrmoptionSepArg, NULL },
1428 { "-icsport", "internetChessServerPort", XrmoptionSepArg, NULL },
1429 { "-internetChessServerCommPort", "internetChessServerCommPort",
1430 XrmoptionSepArg, NULL },
1431 { "-icscomm", "internetChessServerCommPort", XrmoptionSepArg, NULL },
1432 { "-internetChessServerLogonScript", "internetChessServerLogonScript",
1433 XrmoptionSepArg, NULL },
1434 { "-icslogon", "internetChessServerLogonScript", XrmoptionSepArg, NULL },
1435 { "-internetChessServerHelper", "internetChessServerHelper",
1436 XrmoptionSepArg, NULL },
1437 { "-icshelper", "internetChessServerHelper", XrmoptionSepArg, NULL },
1438 { "-internetChessServerInputBox", "internetChessServerInputBox",
1439 XrmoptionSepArg, NULL },
1440 { "-icsinput", "internetChessServerInputBox", XrmoptionNoArg, "True" },
1441 { "-xicsinput", "internetChessServerInputBox", XrmoptionNoArg, "False" },
1442 { "-icsAlarm", "icsAlarm", XrmoptionSepArg, NULL },
1443 { "-alarm", "icsAlarm", XrmoptionNoArg, "True" },
1444 { "-xalarm", "icsAlarm", XrmoptionNoArg, "False" },
1445 { "-icsAlarmTime", "icsAlarmTime", XrmoptionSepArg, NULL },
1446 { "-useTelnet", "useTelnet", XrmoptionSepArg, NULL },
1447 { "-telnet", "useTelnet", XrmoptionNoArg, "True" },
1448 { "-xtelnet", "useTelnet", XrmoptionNoArg, "False" },
1449 { "-telnetProgram", "telnetProgram", XrmoptionSepArg, NULL },
1450 { "-gateway", "gateway", XrmoptionSepArg, NULL },
1451 { "-loadGameFile", "loadGameFile", XrmoptionSepArg, NULL },
1452 { "-lgf", "loadGameFile", XrmoptionSepArg, NULL },
1453 { "-loadGameIndex", "loadGameIndex", XrmoptionSepArg, NULL },
1454 { "-lgi", "loadGameIndex", XrmoptionSepArg, NULL },
1455 { "-saveGameFile", "saveGameFile", XrmoptionSepArg, NULL },
1456 { "-sgf", "saveGameFile", XrmoptionSepArg, NULL },
1457 { "-autoSaveGames", "autoSaveGames", XrmoptionSepArg, NULL },
1458 { "-autosave", "autoSaveGames", XrmoptionNoArg, "True" },
1459 { "-xautosave", "autoSaveGames", XrmoptionNoArg, "False" },
1460 { "-autoRaiseBoard", "autoRaiseBoard", XrmoptionSepArg, NULL },
1461 { "-autoraise", "autoRaiseBoard", XrmoptionNoArg, "True" },
1462 { "-xautoraise", "autoRaiseBoard", XrmoptionNoArg, "False" },
1463 { "-blindfold", "blindfold", XrmoptionSepArg, NULL },
1464 { "-blind", "blindfold", XrmoptionNoArg, "True" },
1465 { "-xblind", "blindfold", XrmoptionNoArg, "False" },
1466 { "-loadPositionFile", "loadPositionFile", XrmoptionSepArg, NULL },
1467 { "-lpf", "loadPositionFile", XrmoptionSepArg, NULL },
1468 { "-loadPositionIndex", "loadPositionIndex", XrmoptionSepArg, NULL },
1469 { "-lpi", "loadPositionIndex", XrmoptionSepArg, NULL },
1470 { "-savePositionFile", "savePositionFile", XrmoptionSepArg, NULL },
1471 { "-spf", "savePositionFile", XrmoptionSepArg, NULL },
1472 { "-matchMode", "matchMode", XrmoptionSepArg, NULL },
1473 { "-mm", "matchMode", XrmoptionNoArg, "True" },
1474 { "-xmm", "matchMode", XrmoptionNoArg, "False" },
1475 { "-matchGames", "matchGames", XrmoptionSepArg, NULL },
1476 { "-mg", "matchGames", XrmoptionSepArg, NULL },
1477 { "-monoMode", "monoMode", XrmoptionSepArg, NULL },
1478 { "-mono", "monoMode", XrmoptionNoArg, "True" },
1479 { "-xmono", "monoMode", XrmoptionNoArg, "False" },
1480 { "-debugMode", "debugMode", XrmoptionSepArg, NULL },
1481 { "-debug", "debugMode", XrmoptionNoArg, "True" },
1482 { "-xdebug", "debugMode", XrmoptionNoArg, "False" },
1483 { "-clockMode", "clockMode", XrmoptionSepArg, NULL },
1484 { "-clock", "clockMode", XrmoptionNoArg, "True" },
1485 { "-xclock", "clockMode", XrmoptionNoArg, "False" },
1486 { "-boardSize", "boardSize", XrmoptionSepArg, NULL },
1487 { "-size", "boardSize", XrmoptionSepArg, NULL },
1488 { "-searchTime", "searchTime", XrmoptionSepArg, NULL },
1489 { "-st", "searchTime", XrmoptionSepArg, NULL },
1490 { "-searchDepth", "searchDepth", XrmoptionSepArg, NULL },
1491 { "-depth", "searchDepth", XrmoptionSepArg, NULL },
1492 { "-showCoords", "showCoords", XrmoptionSepArg, NULL },
1493 { "-coords", "showCoords", XrmoptionNoArg, "True" },
1494 { "-xcoords", "showCoords", XrmoptionNoArg, "False" },
1496 { "-showJail", "showJail", XrmoptionSepArg, NULL },
1497 { "-jail", "showJail", XrmoptionNoArg, "1" },
1498 { "-sidejail", "showJail", XrmoptionNoArg, "2" },
1499 { "-xjail", "showJail", XrmoptionNoArg, "0" },
1501 { "-showThinking", "showThinking", XrmoptionSepArg, NULL },
1502 { "-thinking", "showThinking", XrmoptionNoArg, "True" },
1503 { "-xthinking", "showThinking", XrmoptionNoArg, "False" },
1504 { "-ponderNextMove", "ponderNextMove", XrmoptionSepArg, NULL },
1505 { "-ponder", "ponderNextMove", XrmoptionNoArg, "True" },
1506 { "-xponder", "ponderNextMove", XrmoptionNoArg, "False" },
1507 { "-periodicUpdates", "periodicUpdates", XrmoptionSepArg, NULL },
1508 { "-periodic", "periodicUpdates", XrmoptionNoArg, "True" },
1509 { "-xperiodic", "periodicUpdates", XrmoptionNoArg, "False" },
1510 { "-clockFont", "clockFont", XrmoptionSepArg, NULL },
1511 { "-coordFont", "coordFont", XrmoptionSepArg, NULL },
1512 { "-font", "font", XrmoptionSepArg, NULL },
1513 { "-ringBellAfterMoves", "ringBellAfterMoves", XrmoptionSepArg, NULL },
1514 { "-bell", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1515 { "-xbell", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1516 { "-movesound", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1517 { "-xmovesound", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1518 { "-autoCallFlag", "autoCallFlag", XrmoptionSepArg, NULL },
1519 { "-autoflag", "autoCallFlag", XrmoptionNoArg, "True" },
1520 { "-xautoflag", "autoCallFlag", XrmoptionNoArg, "False" },
1521 { "-autoFlipView", "autoFlipView", XrmoptionSepArg, NULL },
1522 { "-autoflip", "autoFlipView", XrmoptionNoArg, "True" },
1523 { "-xautoflip", "autoFlipView", XrmoptionNoArg, "False" },
1524 { "-autoObserve", "autoObserve", XrmoptionSepArg, NULL },
1525 { "-autobs", "autoObserve", XrmoptionNoArg, "True" },
1526 { "-xautobs", "autoObserve", XrmoptionNoArg, "False" },
1527 { "-autoComment", "autoComment", XrmoptionSepArg, NULL },
1528 { "-autocomm", "autoComment", XrmoptionNoArg, "True" },
1529 { "-xautocomm", "autoComment", XrmoptionNoArg, "False" },
1530 { "-getMoveList", "getMoveList", XrmoptionSepArg, NULL },
1531 { "-moves", "getMoveList", XrmoptionNoArg, "True" },
1532 { "-xmoves", "getMoveList", XrmoptionNoArg, "False" },
1534 { "-highlightDragging", "highlightDragging", XrmoptionSepArg, NULL },
1535 { "-highdrag", "highlightDragging", XrmoptionNoArg, "True" },
1536 { "-xhighdrag", "highlightDragging", XrmoptionNoArg, "False" },
1538 { "-highlightLastMove", "highlightLastMove", XrmoptionSepArg, NULL },
1539 { "-highlight", "highlightLastMove", XrmoptionNoArg, "True" },
1540 { "-xhighlight", "highlightLastMove", XrmoptionNoArg, "False" },
1541 { "-premove", "premove", XrmoptionSepArg, NULL },
1542 { "-pre", "premove", XrmoptionNoArg, "True" },
1543 { "-xpre", "premove", XrmoptionNoArg, "False" },
1544 { "-testLegality", "testLegality", XrmoptionSepArg, NULL },
1545 { "-legal", "testLegality", XrmoptionNoArg, "True" },
1546 { "-xlegal", "testLegality", XrmoptionNoArg, "False" },
1547 { "-flipView", "flipView", XrmoptionSepArg, NULL },
1548 { "-flip", "flipView", XrmoptionNoArg, "True" },
1549 { "-xflip", "flipView", XrmoptionNoArg, "False" },
1550 { "-cmail", "cmailGameName", XrmoptionSepArg, NULL },
1551 { "-alwaysPromoteToQueen", "alwaysPromoteToQueen",
1552 XrmoptionSepArg, NULL },
1553 { "-queen", "alwaysPromoteToQueen", XrmoptionNoArg, "True" },
1554 { "-xqueen", "alwaysPromoteToQueen", XrmoptionNoArg, "False" },
1555 { "-oldSaveStyle", "oldSaveStyle", XrmoptionSepArg, NULL },
1556 { "-oldsave", "oldSaveStyle", XrmoptionNoArg, "True" },
1557 { "-xoldsave", "oldSaveStyle", XrmoptionNoArg, "False" },
1558 { "-quietPlay", "quietPlay", XrmoptionSepArg, NULL },
1559 { "-quiet", "quietPlay", XrmoptionNoArg, "True" },
1560 { "-xquiet", "quietPlay", XrmoptionNoArg, "False" },
1561 { "-titleInWindow", "titleInWindow", XrmoptionSepArg, NULL },
1562 { "-title", "titleInWindow", XrmoptionNoArg, "True" },
1563 { "-xtitle", "titleInWindow", XrmoptionNoArg, "False" },
1565 { "-zippyTalk", "zippyTalk", XrmoptionSepArg, NULL },
1566 { "-zt", "zippyTalk", XrmoptionNoArg, "True" },
1567 { "-xzt", "zippyTalk", XrmoptionNoArg, "False" },
1568 { "-zippyPlay", "zippyPlay", XrmoptionSepArg, NULL },
1569 { "-zp", "zippyPlay", XrmoptionNoArg, "True" },
1570 { "-xzp", "zippyPlay", XrmoptionNoArg, "False" },
1571 { "-zippyLines", "zippyLines", XrmoptionSepArg, NULL },
1572 { "-zippyPinhead", "zippyPinhead", XrmoptionSepArg, NULL },
1573 { "-zippyPassword", "zippyPassword", XrmoptionSepArg, NULL },
1574 { "-zippyPassword2", "zippyPassword2", XrmoptionSepArg, NULL },
1575 { "-zippyWrongPassword", "zippyWrongPassword", XrmoptionSepArg, NULL },
1576 { "-zippyAcceptOnly", "zippyAcceptOnly", XrmoptionSepArg, NULL },
1577 { "-zippyUseI", "zippyUseI", XrmoptionSepArg, NULL },
1578 { "-zui", "zippyUseI", XrmoptionNoArg, "True" },
1579 { "-xzui", "zippyUseI", XrmoptionNoArg, "False" },
1580 { "-zippyBughouse", "zippyBughouse", XrmoptionSepArg, NULL },
1581 { "-zippyNoplayCrafty", "zippyNoplayCrafty", XrmoptionSepArg, NULL },
1582 { "-znc", "zippyNoplayCrafty", XrmoptionNoArg, "True" },
1583 { "-xznc", "zippyNoplayCrafty", XrmoptionNoArg, "False" },
1584 { "-zippyGameEnd", "zippyGameEnd", XrmoptionSepArg, NULL },
1585 { "-zippyGameStart", "zippyGameStart", XrmoptionSepArg, NULL },
1586 { "-zippyAdjourn", "zippyAdjourn", XrmoptionSepArg, NULL },
1587 { "-zadj", "zippyAdjourn", XrmoptionNoArg, "True" },
1588 { "-xzadj", "zippyAdjourn", XrmoptionNoArg, "False" },
1589 { "-zippyAbort", "zippyAbort", XrmoptionSepArg, NULL },
1590 { "-zab", "zippyAbort", XrmoptionNoArg, "True" },
1591 { "-xzab", "zippyAbort", XrmoptionNoArg, "False" },
1592 { "-zippyVariants", "zippyVariants", XrmoptionSepArg, NULL },
1593 { "-zippyMaxGames", "zippyMaxGames", XrmoptionSepArg, NULL },
1594 { "-zippyReplayTimeout", "zippyReplayTimeout", XrmoptionSepArg, NULL },
1596 { "-flashCount", "flashCount", XrmoptionSepArg, NULL },
1597 { "-flash", "flashCount", XrmoptionNoArg, "3" },
1598 { "-xflash", "flashCount", XrmoptionNoArg, "0" },
1599 { "-flashRate", "flashRate", XrmoptionSepArg, NULL },
1600 { "-pixmapDirectory", "pixmapDirectory", XrmoptionSepArg, NULL },
1601 { "-msLoginDelay", "msLoginDelay", XrmoptionSepArg, NULL },
1602 { "-pixmap", "pixmapDirectory", XrmoptionSepArg, NULL },
1603 { "-colorizeMessages", "colorizeMessages", XrmoptionSepArg, NULL },
1604 { "-colorize", "colorizeMessages", XrmoptionNoArg, "True" },
1605 { "-xcolorize", "colorizeMessages", XrmoptionNoArg, "False" },
1606 { "-colorShout", "colorShout", XrmoptionSepArg, NULL },
1607 { "-colorSShout", "colorSShout", XrmoptionSepArg, NULL },
1608 { "-colorCShout", "colorSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1609 { "-colorChannel1", "colorChannel1", XrmoptionSepArg, NULL },
1610 { "-colorChannel", "colorChannel", XrmoptionSepArg, NULL },
1611 { "-colorKibitz", "colorKibitz", XrmoptionSepArg, NULL },
1612 { "-colorTell", "colorTell", XrmoptionSepArg, NULL },
1613 { "-colorChallenge", "colorChallenge", XrmoptionSepArg, NULL },
1614 { "-colorRequest", "colorRequest", XrmoptionSepArg, NULL },
1615 { "-colorSeek", "colorSeek", XrmoptionSepArg, NULL },
1616 { "-colorNormal", "colorNormal", XrmoptionSepArg, NULL },
1617 { "-soundProgram", "soundProgram", XrmoptionSepArg, NULL },
1618 { "-soundShout", "soundShout", XrmoptionSepArg, NULL },
1619 { "-soundSShout", "soundSShout", XrmoptionSepArg, NULL },
1620 { "-soundCShout", "soundSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1621 { "-soundChannel1", "soundChannel1", XrmoptionSepArg, NULL },
1622 { "-soundChannel", "soundChannel", XrmoptionSepArg, NULL },
1623 { "-soundKibitz", "soundKibitz", XrmoptionSepArg, NULL },
1624 { "-soundTell", "soundTell", XrmoptionSepArg, NULL },
1625 { "-soundChallenge", "soundChallenge", XrmoptionSepArg, NULL },
1626 { "-soundRequest", "soundRequest", XrmoptionSepArg, NULL },
1627 { "-soundSeek", "soundSeek", XrmoptionSepArg, NULL },
1628 { "-soundMove", "soundMove", XrmoptionSepArg, NULL },
1629 { "-soundIcsWin", "soundIcsWin", XrmoptionSepArg, NULL },
1630 { "-soundIcsLoss", "soundIcsLoss", XrmoptionSepArg, NULL },
1631 { "-soundIcsDraw", "soundIcsDraw", XrmoptionSepArg, NULL },
1632 { "-soundIcsUnfinished", "soundIcsUnfinished", XrmoptionSepArg, NULL },
1633 { "-soundIcsAlarm", "soundIcsAlarm", XrmoptionSepArg, NULL },
1634 { "-reuseFirst", "reuseFirst", XrmoptionSepArg, NULL },
1635 { "-reuseChessPrograms", "reuseFirst", XrmoptionSepArg, NULL }, /*compat*/
1636 { "-reuse", "reuseFirst", XrmoptionNoArg, "True" },
1637 { "-xreuse", "reuseFirst", XrmoptionNoArg, "False" },
1638 { "-reuseSecond", "reuseSecond", XrmoptionSepArg, NULL },
1639 { "-reuse2", "reuseSecond", XrmoptionNoArg, "True" },
1640 { "-xreuse2", "reuseSecond", XrmoptionNoArg, "False" },
1641 { "-animateMoving", "animateMoving", XrmoptionSepArg, NULL },
1642 { "-animate", "animateMoving", XrmoptionNoArg, "True" },
1643 { "-xanimate", "animateMoving", XrmoptionNoArg, "False" },
1644 { "-animateDragging", "animateDragging", XrmoptionSepArg, NULL },
1645 { "-drag", "animateDragging", XrmoptionNoArg, "True" },
1646 { "-xdrag", "animateDragging", XrmoptionNoArg, "False" },
1647 { "-animateSpeed", "animateSpeed", XrmoptionSepArg, NULL },
1648 { "-popupExitMessage", "popupExitMessage", XrmoptionSepArg, NULL },
1649 { "-exit", "popupExitMessage", XrmoptionNoArg, "True" },
1650 { "-xexit", "popupExitMessage", XrmoptionNoArg, "False" },
1651 { "-popupMoveErrors", "popupMoveErrors", XrmoptionSepArg, NULL },
1652 { "-popup", "popupMoveErrors", XrmoptionNoArg, "True" },
1653 { "-xpopup", "popupMoveErrors", XrmoptionNoArg, "False" },
1654 { "-fontSizeTolerance", "fontSizeTolerance", XrmoptionSepArg, NULL },
1655 { "-initialMode", "initialMode", XrmoptionSepArg, NULL },
1656 { "-mode", "initialMode", XrmoptionSepArg, NULL },
1657 { "-variant", "variant", XrmoptionSepArg, NULL },
1658 { "-firstProtocolVersion", "firstProtocolVersion", XrmoptionSepArg, NULL },
1659 { "-secondProtocolVersion","secondProtocolVersion",XrmoptionSepArg, NULL },
1660 { "-showButtonBar", "showButtonBar", XrmoptionSepArg, NULL },
1661 { "-buttons", "showButtonBar", XrmoptionNoArg, "True" },
1662 { "-xbuttons", "showButtonBar", XrmoptionNoArg, "False" },
1663 /* [AS,HR] New features */
1664 { "-firstScoreAbs", "firstScoreAbs", XrmoptionSepArg, NULL },
1665 { "-secondScoreAbs", "secondScoreAbs", XrmoptionSepArg, NULL },
1666 { "-pgnExtendedInfo", "pgnExtendedInfo", XrmoptionSepArg, NULL },
1667 { "-hideThinkingFromHuman", "hideThinkingFromHuman", XrmoptionSepArg, NULL },
1668 { "-adjudicateLossThreshold", "adjudicateLossThreshold", XrmoptionSepArg, NULL },
1669 { "-pgnEventHeader", "pgnEventHeader", XrmoptionSepArg, NULL },
1670 { "-firstIsUCI", "firstIsUCI", XrmoptionSepArg, NULL },
1671 { "-secondIsUCI", "secondIsUCI", XrmoptionSepArg, NULL },
1672 { "-fUCI", "firstIsUCI", XrmoptionNoArg, "True" },
1673 { "-sUCI", "secondIsUCI", XrmoptionNoArg, "True" },
1674 { "-firstHasOwnBookUCI", "firstHasOwnBookUCI", XrmoptionSepArg, NULL },
1675 { "-secondHasOwnBookUCI", "secondHasOwnBookUCI", XrmoptionSepArg, NULL },
1676 { "-fNoOwnBookUCI", "firstHasOwnBookUCI", XrmoptionNoArg, "False" },
1677 { "-sNoOwnBookUCI", "secondHasOwnBookUCI", XrmoptionNoArg, "False" },
1678 { "-firstXBook", "firstHasOwnBookUCI", XrmoptionNoArg, "False" },
1679 { "-secondXBook", "secondHasOwnBookUCI", XrmoptionNoArg, "False" },
1680 { "-polyglotDir", "polyglotDir", XrmoptionSepArg, NULL },
1681 { "-usePolyglotBook", "usePolyglotBook", XrmoptionSepArg, NULL },
1682 { "-polyglotBook", "polyglotBook", XrmoptionSepArg, NULL },
1683 { "-defaultHashSize", "defaultHashSize", XrmoptionSepArg, NULL },
1684 { "-defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XrmoptionSepArg, NULL },
1685 { "-defaultPathEGTB", "defaultPathEGTB", XrmoptionSepArg, NULL },
1686 { "-defaultFrcPosition", "defaultFrcPosition", XrmoptionSepArg, NULL },
1687 // [HGM] I am sure AS added many more options, but we have to fish them out, from the list in winboard.c
1689 /* [HGM,HR] User-selectable board size */
1690 { "-boardWidth", "boardWidth", XrmoptionSepArg, NULL },
1691 { "-boardHeight", "boardHeight", XrmoptionSepArg, NULL },
1692 { "-matchPause", "matchPause", XrmoptionSepArg, NULL },
1694 /* [HGM] new arguments of 4.3.xx. All except first three are back-end options, which should work immediately */
1695 { "-holdingsSize", "holdingsSize", XrmoptionSepArg, NULL }, // requires extensive front-end changes to work
1696 { "-flipBlack", "flipBlack", XrmoptionSepArg, NULL }, // requires front-end changes to work
1697 { "-allWhite", "allWhite", XrmoptionSepArg, NULL }, // requires front-end changes to work
1698 { "-pieceToCharTable", "pieceToCharTable", XrmoptionSepArg, NULL },
1699 { "-alphaRank", "alphaRank", XrmoptionSepArg, NULL },
1700 { "-testClaims", "testClaims", XrmoptionSepArg, NULL },
1701 { "-checkMates", "checkMates", XrmoptionSepArg, NULL },
1702 { "-materialDraws", "materialDraws", XrmoptionSepArg, NULL },
1703 { "-trivialDraws", "trivialDraws", XrmoptionSepArg, NULL },
1704 { "-ruleMoves", "ruleMoves", XrmoptionSepArg, NULL },
1705 { "-repeatsToDraw", "repeatsToDraw", XrmoptionSepArg, NULL },
1706 { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL },
1707 { "-userName", "userName", XrmoptionSepArg, NULL },
1708 { "-autoKibitz", "autoKibitz", XrmoptionNoArg, "True" },
1709 { "-firstTimeOdds", "firstTimeOdds", XrmoptionSepArg, NULL },
1710 { "-secondTimeOdds", "secondTimeOdds", XrmoptionSepArg, NULL },
1711 { "-timeOddsMode", "timeOddsMode", XrmoptionSepArg, NULL },
1712 { "-firstAccumulateTC", "firstAccumulateTC", XrmoptionSepArg, NULL },
1713 { "-secondAccumulateTC", "secondAccumulateTC", XrmoptionSepArg, NULL },
1714 { "-firstNPS", "firstNPS", XrmoptionSepArg, NULL },
1715 { "-secondNPS", "secondNPS", XrmoptionSepArg, NULL },
1716 { "-serverMoves", "serverMoves", XrmoptionSepArg, NULL },
1717 { "-serverPause", "serverPause", XrmoptionSepArg, NULL },
1718 { "-suppressLoadMoves", "suppressLoadMoves", XrmoptionSepArg, NULL },
1719 { "-egtFormats", "egtFormats", XrmoptionSepArg, NULL },
1720 { "-userName", "userName", XrmoptionSepArg, NULL },
1721 { "-smpCores", "smpCores", XrmoptionSepArg, NULL },
1722 { "-sameColorGames", "sameColorGames", XrmoptionSepArg, NULL },
1723 { "-rewindIndex", "rewindIndex", XrmoptionSepArg, NULL },
1724 { "-niceEngines", "niceEngines", XrmoptionSepArg, NULL },
1725 { "-delayBeforeQuit", "delayBeforeQuit", XrmoptionSepArg, NULL },
1726 { "-delayAfterQuit", "delayAfterQuit", XrmoptionSepArg, NULL },
1727 { "-nameOfDebugFile", "nameOfDebugFile", XrmoptionSepArg, NULL },
1728 { "-debugFile", "nameOfDebugFile", XrmoptionSepArg, NULL },
1729 { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL },
1730 { "-noGUI", "noGUI", XrmoptionNoArg, "True" },
1731 { "-firstOptions", "firstOptions", XrmoptionSepArg, NULL },
1732 { "-secondOptions", "secondOptions", XrmoptionSepArg, NULL },
1736 XtActionsRec boardActions[] = {
1737 { "DrawPosition", DrawPositionProc },
1738 { "HandleUserMove", HandleUserMove },
1739 { "AnimateUserMove", AnimateUserMove },
1740 { "FileNameAction", FileNameAction },
1741 { "AskQuestionProc", AskQuestionProc },
1742 { "AskQuestionReplyAction", AskQuestionReplyAction },
1743 { "PieceMenuPopup", PieceMenuPopup },
1744 { "WhiteClock", WhiteClock },
1745 { "BlackClock", BlackClock },
1746 { "Iconify", Iconify },
1747 { "ResetProc", ResetProc },
1748 { "LoadGameProc", LoadGameProc },
1749 { "LoadNextGameProc", LoadNextGameProc },
1750 { "LoadPrevGameProc", LoadPrevGameProc },
1751 { "LoadSelectedProc", LoadSelectedProc },
1752 { "ReloadGameProc", ReloadGameProc },
1753 { "LoadPositionProc", LoadPositionProc },
1754 { "LoadNextPositionProc", LoadNextPositionProc },
1755 { "LoadPrevPositionProc", LoadPrevPositionProc },
1756 { "ReloadPositionProc", ReloadPositionProc },
1757 { "CopyPositionProc", CopyPositionProc },
1758 { "PastePositionProc", PastePositionProc },
1759 { "CopyGameProc", CopyGameProc },
1760 { "PasteGameProc", PasteGameProc },
1761 { "SaveGameProc", SaveGameProc },
1762 { "SavePositionProc", SavePositionProc },
1763 { "MailMoveProc", MailMoveProc },
1764 { "ReloadCmailMsgProc", ReloadCmailMsgProc },
1765 { "QuitProc", QuitProc },
1766 { "MachineWhiteProc", MachineWhiteProc },
1767 { "MachineBlackProc", MachineBlackProc },
1768 { "AnalysisModeProc", AnalyzeModeProc },
1769 { "AnalyzeFileProc", AnalyzeFileProc },
1770 { "TwoMachinesProc", TwoMachinesProc },
1771 { "IcsClientProc", IcsClientProc },
1772 { "EditGameProc", EditGameProc },
1773 { "EditPositionProc", EditPositionProc },
1774 { "TrainingProc", EditPositionProc },
1775 { "EngineOutputProc", EngineOutputProc}, // [HGM] Winboard_x engine-output window
1776 { "ShowGameListProc", ShowGameListProc },
1777 { "ShowMoveListProc", HistoryShowProc},
1778 { "EditTagsProc", EditCommentProc },
1779 { "EditCommentProc", EditCommentProc },
1780 { "IcsAlarmProc", IcsAlarmProc },
1781 { "IcsInputBoxProc", IcsInputBoxProc },
1782 { "PauseProc", PauseProc },
1783 { "AcceptProc", AcceptProc },
1784 { "DeclineProc", DeclineProc },
1785 { "RematchProc", RematchProc },
1786 { "CallFlagProc", CallFlagProc },
1787 { "DrawProc", DrawProc },
1788 { "AdjournProc", AdjournProc },
1789 { "AbortProc", AbortProc },
1790 { "ResignProc", ResignProc },
1791 { "AdjuWhiteProc", AdjuWhiteProc },
1792 { "AdjuBlackProc", AdjuBlackProc },
1793 { "AdjuDrawProc", AdjuDrawProc },
1794 { "EnterKeyProc", EnterKeyProc },
1795 { "StopObservingProc", StopObservingProc },
1796 { "StopExaminingProc", StopExaminingProc },
1797 { "BackwardProc", BackwardProc },
1798 { "ForwardProc", ForwardProc },
1799 { "ToStartProc", ToStartProc },
1800 { "ToEndProc", ToEndProc },
1801 { "RevertProc", RevertProc },
1802 { "TruncateGameProc", TruncateGameProc },
1803 { "MoveNowProc", MoveNowProc },
1804 { "RetractMoveProc", RetractMoveProc },
1805 { "AlwaysQueenProc", AlwaysQueenProc },
1806 { "AnimateDraggingProc", AnimateDraggingProc },
1807 { "AnimateMovingProc", AnimateMovingProc },
1808 { "AutoflagProc", AutoflagProc },
1809 { "AutoflipProc", AutoflipProc },
1810 { "AutobsProc", AutobsProc },
1811 { "AutoraiseProc", AutoraiseProc },
1812 { "AutosaveProc", AutosaveProc },
1813 { "BlindfoldProc", BlindfoldProc },
1814 { "FlashMovesProc", FlashMovesProc },
1815 { "FlipViewProc", FlipViewProc },
1816 { "GetMoveListProc", GetMoveListProc },
1818 { "HighlightDraggingProc", HighlightDraggingProc },
1820 { "HighlightLastMoveProc", HighlightLastMoveProc },
1821 { "IcsAlarmProc", IcsAlarmProc },
1822 { "MoveSoundProc", MoveSoundProc },
1823 { "OldSaveStyleProc", OldSaveStyleProc },
1824 { "PeriodicUpdatesProc", PeriodicUpdatesProc },
1825 { "PonderNextMoveProc", PonderNextMoveProc },
1826 { "PopupExitMessageProc", PopupExitMessageProc },
1827 { "PopupMoveErrorsProc", PopupMoveErrorsProc },
1828 { "PremoveProc", PremoveProc },
1829 { "QuietPlayProc", QuietPlayProc },
1830 { "ShowCoordsProc", ShowCoordsProc },
1831 { "ShowThinkingProc", ShowThinkingProc },
1832 { "HideThinkingProc", HideThinkingProc },
1833 { "TestLegalityProc", TestLegalityProc },
1834 { "InfoProc", InfoProc },
1835 { "ManProc", ManProc },
1836 { "HintProc", HintProc },
1837 { "BookProc", BookProc },
1838 { "AboutGameProc", AboutGameProc },
1839 { "AboutProc", AboutProc },
1840 { "DebugProc", DebugProc },
1841 { "NothingProc", NothingProc },
1842 { "CommentPopDown", (XtActionProc) CommentPopDown },
1843 { "EditCommentPopDown", (XtActionProc) EditCommentPopDown },
1844 { "TagsPopDown", (XtActionProc) TagsPopDown },
1845 { "ErrorPopDown", (XtActionProc) ErrorPopDown },
1846 { "ICSInputBoxPopDown", (XtActionProc) ICSInputBoxPopDown },
1847 { "AnalysisPopDown", (XtActionProc) AnalysisPopDown },
1848 { "FileNamePopDown", (XtActionProc) FileNamePopDown },
1849 { "AskQuestionPopDown", (XtActionProc) AskQuestionPopDown },
1850 { "GameListPopDown", (XtActionProc) GameListPopDown },
1851 { "PromotionPopDown", (XtActionProc) PromotionPopDown },
1852 { "HistoryPopDown", (XtActionProc) HistoryPopDown },
1853 { "EngineOutputPopDown", (XtActionProc) EngineOutputPopDown },
1854 { "ShufflePopDown", (XtActionProc) ShufflePopDown },
1855 { "EnginePopDown", (XtActionProc) EnginePopDown },
1856 { "UciPopDown", (XtActionProc) UciPopDown },
1857 { "TimeControlPopDown", (XtActionProc) TimeControlPopDown },
1858 { "NewVariantPopDown", (XtActionProc) NewVariantPopDown },
1859 { "SettingsPopDown", (XtActionProc) SettingsPopDown },
1862 char globalTranslations[] =
1863 ":<Key>R: ResignProc() \n \
1864 :<Key>r: ResetProc() \n \
1865 :<Key>g: LoadGameProc() \n \
1866 :<Key>N: LoadNextGameProc() \n \
1867 :<Key>P: LoadPrevGameProc() \n \
1868 :<Key>Q: QuitProc() \n \
1869 :<Key>F: ToEndProc() \n \
1870 :<Key>f: ForwardProc() \n \
1871 :<Key>B: ToStartProc() \n \
1872 :<Key>b: BackwardProc() \n \
1873 :<Key>p: PauseProc() \n \
1874 :<Key>d: DrawProc() \n \
1875 :<Key>t: CallFlagProc() \n \
1876 :<Key>i: Iconify() \n \
1877 :<Key>c: Iconify() \n \
1878 :<Key>v: FlipViewProc() \n \
1879 <KeyDown>Control_L: BackwardProc() \n \
1880 <KeyUp>Control_L: ForwardProc() \n \
1881 <KeyDown>Control_R: BackwardProc() \n \
1882 <KeyUp>Control_R: ForwardProc() \n \
1883 Shift<Key>1: AskQuestionProc(\"Direct command\",\
1884 \"Send to chess program:\",,1) \n \
1885 Shift<Key>2: AskQuestionProc(\"Direct command\",\
1886 \"Send to second chess program:\",,2) \n";
1888 char boardTranslations[] =
1889 "<Btn1Down>: HandleUserMove() \n \
1890 <Btn1Up>: HandleUserMove() \n \
1891 <Btn1Motion>: AnimateUserMove() \n \
1892 Shift<Btn2Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD)\
1893 PieceMenuPopup(menuB) \n \
1894 Any<Btn2Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD) \
1895 PieceMenuPopup(menuW) \n \
1896 Shift<Btn3Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD)\
1897 PieceMenuPopup(menuW) \n \
1898 Any<Btn3Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD) \
1899 PieceMenuPopup(menuB) \n";
1901 char whiteTranslations[] = "<BtnDown>: WhiteClock()\n";
1902 char blackTranslations[] = "<BtnDown>: BlackClock()\n";
1904 char ICSInputTranslations[] =
1905 "<Key>Return: EnterKeyProc() \n";
1907 String xboardResources[] = {
1908 "*fileName*value.translations: #override\\n <Key>Return: FileNameAction()",
1909 "*question*value.translations: #override\\n <Key>Return: AskQuestionReplyAction()",
1910 "*errorpopup*translations: #override\\n <Key>Return: ErrorPopDown()",
1915 /* Max possible square size */
1916 #define MAXSQSIZE 256
1918 static int xpm_avail[MAXSQSIZE];
1920 #ifdef HAVE_DIR_STRUCT
1922 /* Extract piece size from filename */
1924 xpm_getsize(name, len, ext)
1935 if ((p=strchr(name, '.')) == NULL ||
1936 StrCaseCmp(p+1, ext) != 0)
1942 while (*p && isdigit(*p))
1949 /* Setup xpm_avail */
1951 xpm_getavail(dirname, ext)
1959 for (i=0; i<MAXSQSIZE; ++i)
1962 if (appData.debugMode)
1963 fprintf(stderr, "XPM dir:%s:ext:%s:\n", dirname, ext);
1965 dir = opendir(dirname);
1968 fprintf(stderr, _("%s: Can't access XPM directory %s\n"),
1969 programName, dirname);
1973 while ((ent=readdir(dir)) != NULL) {
1974 i = xpm_getsize(ent->d_name, NAMLEN(ent), ext);
1975 if (i > 0 && i < MAXSQSIZE)
1985 xpm_print_avail(fp, ext)
1991 fprintf(fp, _("Available `%s' sizes:\n"), ext);
1992 for (i=1; i<MAXSQSIZE; ++i) {
1998 /* Return XPM piecesize closest to size */
2000 xpm_closest_to(dirname, size, ext)
2006 int sm_diff = MAXSQSIZE;
2010 xpm_getavail(dirname, ext);
2012 if (appData.debugMode)
2013 xpm_print_avail(stderr, ext);
2015 for (i=1; i<MAXSQSIZE; ++i) {
2018 diff = (diff<0) ? -diff : diff;
2019 if (diff < sm_diff) {
2027 fprintf(stderr, _("Error: No `%s' files!\n"), ext);
2033 #else /* !HAVE_DIR_STRUCT */
2034 /* If we are on a system without a DIR struct, we can't
2035 read the directory, so we can't collect a list of
2036 filenames, etc., so we can't do any size-fitting. */
2038 xpm_closest_to(dirname, size, ext)
2043 fprintf(stderr, _("\
2044 Warning: No DIR structure found on this system --\n\
2045 Unable to autosize for XPM/XIM pieces.\n\
2046 Please report this error to frankm@hiwaay.net.\n\
2047 Include system type & operating system in message.\n"));
2050 #endif /* HAVE_DIR_STRUCT */
2052 static char *cnames[9] = { "black", "red", "green", "yellow", "blue",
2053 "magenta", "cyan", "white" };
2057 TextColors textColors[(int)NColorClasses];
2059 /* String is: "fg, bg, attr". Which is 0, 1, 2 */
2061 parse_color(str, which)
2065 char *p, buf[100], *d;
2068 if (strlen(str) > 99) /* watch bounds on buf */
2073 for (i=0; i<which; ++i) {
2080 /* Could be looking at something like:
2082 .. in which case we want to stop on a comma also */
2083 while (*p && *p != ',' && !isalpha(*p) && !isdigit(*p))
2087 return -1; /* Use default for empty field */
2090 if (which == 2 || isdigit(*p))
2093 while (*p && isalpha(*p))
2098 for (i=0; i<8; ++i) {
2099 if (!StrCaseCmp(buf, cnames[i]))
2100 return which? (i+40) : (i+30);
2102 if (!StrCaseCmp(buf, "default")) return -1;
2104 fprintf(stderr, _("%s: unrecognized color %s\n"), programName, buf);
2109 parse_cpair(cc, str)
2113 if ((textColors[(int)cc].fg=parse_color(str, 0)) == -2) {
2114 fprintf(stderr, _("%s: can't parse foreground color in `%s'\n"),
2119 /* bg and attr are optional */
2120 textColors[(int)cc].bg = parse_color(str, 1);
2121 if ((textColors[(int)cc].attr = parse_color(str, 2)) < 0) {
2122 textColors[(int)cc].attr = 0;
2128 /* Arrange to catch delete-window events */
2129 Atom wm_delete_window;
2131 CatchDeleteWindow(Widget w, String procname)
2134 XSetWMProtocols(xDisplay, XtWindow(w), &wm_delete_window, 1);
2135 sprintf(buf, "<Message>WM_PROTOCOLS: %s() \n", procname);
2136 XtAugmentTranslations(w, XtParseTranslationTable(buf));
2143 XtSetArg(args[0], XtNiconic, False);
2144 XtSetValues(shellWidget, args, 1);
2146 XtPopup(shellWidget, XtGrabNone); /* Raise if lowered */
2150 // eventually, all layout determining code should go into a subroutine, but until then IDSIZE remains undefined
2152 #define BoardSize int
2153 void InitDrawingSizes(BoardSize boardSize, int flags)
2154 { // [HGM] resize is functional now, but for board format changes only (nr of ranks, files)
2155 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
2157 XtGeometryResult gres;
2160 if(!formWidget) return;
2163 * Enable shell resizing.
2165 shellArgs[0].value = (XtArgVal) &w;
2166 shellArgs[1].value = (XtArgVal) &h;
2167 XtGetValues(shellWidget, shellArgs, 2);
2169 shellArgs[4].value = 2*w; shellArgs[2].value = 10;
2170 shellArgs[5].value = 2*h; shellArgs[3].value = 10;
2171 XtSetValues(shellWidget, &shellArgs[2], 4);
2173 XtSetArg(args[0], XtNdefaultDistance, &sep);
2174 XtGetValues(formWidget, args, 1);
2176 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2177 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2180 XtSetArg(args[0], XtNwidth, boardWidth);
2181 XtSetArg(args[1], XtNheight, boardHeight);
2182 XtSetValues(boardWidget, args, 2);
2184 timerWidth = (boardWidth - sep) / 2;
2185 XtSetArg(args[0], XtNwidth, timerWidth);
2186 XtSetValues(whiteTimerWidget, args, 1);
2187 XtSetValues(blackTimerWidget, args, 1);
2189 XawFormDoLayout(formWidget, False);
2191 if (appData.titleInWindow) {
2193 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2194 XtSetArg(args[i], XtNheight, &h); i++;
2195 XtGetValues(titleWidget, args, i);
2197 w = boardWidth - 2*bor;
2199 XtSetArg(args[0], XtNwidth, &w);
2200 XtGetValues(menuBarWidget, args, 1);
2201 w = boardWidth - w - sep - 2*bor - 2; // WIDTH_FUDGE
2204 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
2205 if (gres != XtGeometryYes && appData.debugMode) {
2207 _("%s: titleWidget geometry error %d %d %d %d %d\n"),
2208 programName, gres, w, h, wr, hr);
2212 XawFormDoLayout(formWidget, True);
2215 * Inhibit shell resizing.
2217 shellArgs[0].value = w = (XtArgVal) boardWidth + marginW;
2218 shellArgs[1].value = h = (XtArgVal) boardHeight + marginH;
2219 shellArgs[4].value = shellArgs[2].value = w;
2220 shellArgs[5].value = shellArgs[3].value = h;
2221 XtSetValues(shellWidget, &shellArgs[0], 6);
2230 int i, j, clockFontPxlSize, coordFontPxlSize, fontPxlSize;
2231 XSetWindowAttributes window_attributes;
2233 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
2234 XrmValue vFrom, vTo;
2235 XtGeometryResult gres;
2238 int forceMono = False;
2241 // [HGM] before anything else, expand any indirection files amongst options
2242 char *argvCopy[1000]; // 1000 seems enough
2243 char newArgs[10000]; // holds actual characters
2246 srandom(time(0)); // [HGM] book: make random truly random
2249 for(i=0; i<argc; i++) {
2250 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2251 //fprintf(stderr, "arg %s\n", argv[i]);
2252 if(argv[i][0] != '@') argvCopy[j++] = argv[i]; else {
2254 FILE *f = fopen(argv[i]+1, "rb");
2255 if(f == NULL) { fprintf(stderr, _("ignore %s\n"), argv[i]); continue; } // do not expand non-existing
2256 argvCopy[j++] = newArgs + k; // get ready for first argument from file
2257 while((c = fgetc(f)) != EOF) { // each line of file inserts 1 argument in the list
2259 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2260 newArgs[k++] = 0; // terminate current arg
2261 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2262 argvCopy[j++] = newArgs + k; // get ready for next
2264 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2277 if(appData.debugMode,1) { // OK, appData is not initialized here yet...
2278 for(i=0; i<argc; i++) fprintf(stderr, "argv[%2d] = '%s'\n", i, argv[i]);
2284 setbuf(stdout, NULL);
2285 setbuf(stderr, NULL);
2288 programName = strrchr(argv[0], '/');
2289 if (programName == NULL)
2290 programName = argv[0];
2295 XtSetLanguageProc(NULL, NULL, NULL);
2296 bindtextdomain(PRODUCT, LOCALEDIR);
2297 textdomain(PRODUCT);
2301 XtAppInitialize(&appContext, "XBoard", shellOptions,
2302 XtNumber(shellOptions),
2303 &argc, argv, xboardResources, NULL, 0);
2305 fprintf(stderr, _("%s: unrecognized argument %s\n"),
2306 programName, argv[1]);
2310 if ((chessDir = (char *) getenv("CHESSDIR")) == NULL) {
2313 if (chdir(chessDir) != 0) {
2314 fprintf(stderr, _("%s: can't cd to CHESSDIR: "), programName);
2321 if (p == NULL) p = "/tmp";
2322 i = strlen(p) + strlen("/.xboardXXXXXx.pgn") + 1;
2323 gameCopyFilename = (char*) malloc(i);
2324 gamePasteFilename = (char*) malloc(i);
2325 sprintf(gameCopyFilename, "%s/.xboard%05uc.pgn", p, getpid());
2326 sprintf(gamePasteFilename, "%s/.xboard%05up.pgn", p, getpid());
2328 XtGetApplicationResources(shellWidget, (XtPointer) &appData,
2329 clientResources, XtNumber(clientResources),
2332 if (appData.debugMode && appData.nameOfDebugFile && strcmp(appData.nameOfDebugFile, "stderr")) {
2333 /* [DM] debug info to file [HGM] make the filename a command-line option, and allow it to remain stderr */
2334 if ((debugFP = fopen(appData.nameOfDebugFile, "w")) == NULL) {
2335 printf(_("Failed to open file '%s'\n"), appData.nameOfDebugFile);
2338 setbuf(debugFP, NULL);
2341 /* [HGM,HR] make sure board size is acceptable */
2342 if(appData.NrFiles > BOARD_SIZE ||
2343 appData.NrRanks > BOARD_SIZE )
2344 DisplayFatalError(_("Recompile with BOARD_SIZE > 12, to support this size"), 0, 2);
2347 /* This feature does not work; animation needs a rewrite */
2348 appData.highlightDragging = FALSE;
2352 xDisplay = XtDisplay(shellWidget);
2353 xScreen = DefaultScreen(xDisplay);
2354 wm_delete_window = XInternAtom(xDisplay, "WM_DELETE_WINDOW", True);
2356 gameInfo.variant = StringToVariant(appData.variant);
2357 InitPosition(FALSE);
2360 * Determine boardSize
2362 gameInfo.boardWidth = gameInfo.boardHeight = 8; // [HGM] boardsize: make sure we start as 8x8
2365 // [HGM] as long as we have not created the possibility to change size while running, start with requested size
2366 gameInfo.boardWidth = appData.NrFiles > 0 ? appData.NrFiles : 8;
2367 gameInfo.boardHeight = appData.NrRanks > 0 ? appData.NrRanks : 8;
2368 gameInfo.holdingsWidth = appData.holdingsSize > 0 ? 2 : 0;
2373 InitDrawingSizes(-1, 0); // [HGM] initsize: make this into a subroutine
2375 if (isdigit(appData.boardSize[0])) {
2376 i = sscanf(appData.boardSize, "%d,%d,%d,%d,%d,%d,%d", &squareSize,
2377 &lineGap, &clockFontPxlSize, &coordFontPxlSize,
2378 &fontPxlSize, &smallLayout, &tinyLayout);
2380 fprintf(stderr, _("%s: bad boardSize syntax %s\n"),
2381 programName, appData.boardSize);
2385 /* Find some defaults; use the nearest known size */
2386 SizeDefaults *szd, *nearest;
2387 int distance = 99999;
2388 nearest = szd = sizeDefaults;
2389 while (szd->name != NULL) {
2390 if (abs(szd->squareSize - squareSize) < distance) {
2392 distance = abs(szd->squareSize - squareSize);
2393 if (distance == 0) break;
2397 if (i < 2) lineGap = nearest->lineGap;
2398 if (i < 3) clockFontPxlSize = nearest->clockFontPxlSize;
2399 if (i < 4) coordFontPxlSize = nearest->coordFontPxlSize;
2400 if (i < 5) fontPxlSize = nearest->fontPxlSize;
2401 if (i < 6) smallLayout = nearest->smallLayout;
2402 if (i < 7) tinyLayout = nearest->tinyLayout;
2405 SizeDefaults *szd = sizeDefaults;
2406 if (*appData.boardSize == NULLCHAR) {
2407 while (DisplayWidth(xDisplay, xScreen) < szd->minScreenSize ||
2408 DisplayHeight(xDisplay, xScreen) < szd->minScreenSize) {
2411 if (szd->name == NULL) szd--;
2413 while (szd->name != NULL &&
2414 StrCaseCmp(szd->name, appData.boardSize) != 0) szd++;
2415 if (szd->name == NULL) {
2416 fprintf(stderr, _("%s: unrecognized boardSize name %s\n"),
2417 programName, appData.boardSize);
2421 squareSize = szd->squareSize;
2422 lineGap = szd->lineGap;
2423 clockFontPxlSize = szd->clockFontPxlSize;
2424 coordFontPxlSize = szd->coordFontPxlSize;
2425 fontPxlSize = szd->fontPxlSize;
2426 smallLayout = szd->smallLayout;
2427 tinyLayout = szd->tinyLayout;
2430 /* Now, using squareSize as a hint, find a good XPM/XIM set size */
2431 if (strlen(appData.pixmapDirectory) > 0) {
2432 p = ExpandPathName(appData.pixmapDirectory);
2434 fprintf(stderr, _("Error expanding path name \"%s\"\n"),
2435 appData.pixmapDirectory);
2438 if (appData.debugMode) {
2439 fprintf(stderr, _("\
2440 XBoard square size (hint): %d\n\
2441 %s fulldir:%s:\n"), squareSize, IMAGE_EXT, p);
2443 squareSize = xpm_closest_to(p, squareSize, IMAGE_EXT);
2444 if (appData.debugMode) {
2445 fprintf(stderr, _("Closest %s size: %d\n"), IMAGE_EXT, squareSize);
2449 /* [HR] height treated separately (hacked) */
2450 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2451 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2452 if (appData.showJail == 1) {
2453 /* Jail on top and bottom */
2454 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2455 XtSetArg(boardArgs[2], XtNheight,
2456 boardHeight + 2*(lineGap + squareSize));
2457 } else if (appData.showJail == 2) {
2459 XtSetArg(boardArgs[1], XtNwidth,
2460 boardWidth + 2*(lineGap + squareSize));
2461 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2464 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2465 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2469 * Determine what fonts to use.
2471 appData.clockFont = FindFont(appData.clockFont, clockFontPxlSize);
2472 clockFontID = XLoadFont(xDisplay, appData.clockFont);
2473 clockFontStruct = XQueryFont(xDisplay, clockFontID);
2474 appData.coordFont = FindFont(appData.coordFont, coordFontPxlSize);
2475 coordFontID = XLoadFont(xDisplay, appData.coordFont);
2476 coordFontStruct = XQueryFont(xDisplay, coordFontID);
2477 appData.font = FindFont(appData.font, fontPxlSize);
2478 countFontID = XLoadFont(xDisplay, appData.coordFont); // [HGM] holdings
2479 countFontStruct = XQueryFont(xDisplay, countFontID);
2480 // appData.font = FindFont(appData.font, fontPxlSize);
2482 xdb = XtDatabase(xDisplay);
2483 XrmPutStringResource(&xdb, "*font", appData.font);
2486 * Detect if there are not enough colors available and adapt.
2488 if (DefaultDepth(xDisplay, xScreen) <= 2) {
2489 appData.monoMode = True;
2492 if (!appData.monoMode) {
2493 vFrom.addr = (caddr_t) appData.lightSquareColor;
2494 vFrom.size = strlen(appData.lightSquareColor);
2495 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2496 if (vTo.addr == NULL) {
2497 appData.monoMode = True;
2500 lightSquareColor = *(Pixel *) vTo.addr;
2503 if (!appData.monoMode) {
2504 vFrom.addr = (caddr_t) appData.darkSquareColor;
2505 vFrom.size = strlen(appData.darkSquareColor);
2506 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2507 if (vTo.addr == NULL) {
2508 appData.monoMode = True;
2511 darkSquareColor = *(Pixel *) vTo.addr;
2514 if (!appData.monoMode) {
2515 vFrom.addr = (caddr_t) appData.whitePieceColor;
2516 vFrom.size = strlen(appData.whitePieceColor);
2517 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2518 if (vTo.addr == NULL) {
2519 appData.monoMode = True;
2522 whitePieceColor = *(Pixel *) vTo.addr;
2525 if (!appData.monoMode) {
2526 vFrom.addr = (caddr_t) appData.blackPieceColor;
2527 vFrom.size = strlen(appData.blackPieceColor);
2528 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2529 if (vTo.addr == NULL) {
2530 appData.monoMode = True;
2533 blackPieceColor = *(Pixel *) vTo.addr;
2537 if (!appData.monoMode) {
2538 vFrom.addr = (caddr_t) appData.highlightSquareColor;
2539 vFrom.size = strlen(appData.highlightSquareColor);
2540 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2541 if (vTo.addr == NULL) {
2542 appData.monoMode = True;
2545 highlightSquareColor = *(Pixel *) vTo.addr;
2549 if (!appData.monoMode) {
2550 vFrom.addr = (caddr_t) appData.premoveHighlightColor;
2551 vFrom.size = strlen(appData.premoveHighlightColor);
2552 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2553 if (vTo.addr == NULL) {
2554 appData.monoMode = True;
2557 premoveHighlightColor = *(Pixel *) vTo.addr;
2562 fprintf(stderr, _("%s: too few colors available; trying monochrome mode\n"),
2566 if (appData.monoMode && appData.debugMode) {
2567 fprintf(stderr, _("white pixel = 0x%lx, black pixel = 0x%lx\n"),
2568 (unsigned long) XWhitePixel(xDisplay, xScreen),
2569 (unsigned long) XBlackPixel(xDisplay, xScreen));
2572 if (parse_cpair(ColorShout, appData.colorShout) < 0 ||
2573 parse_cpair(ColorSShout, appData.colorSShout) < 0 ||
2574 parse_cpair(ColorChannel1, appData.colorChannel1) < 0 ||
2575 parse_cpair(ColorChannel, appData.colorChannel) < 0 ||
2576 parse_cpair(ColorKibitz, appData.colorKibitz) < 0 ||
2577 parse_cpair(ColorTell, appData.colorTell) < 0 ||
2578 parse_cpair(ColorChallenge, appData.colorChallenge) < 0 ||
2579 parse_cpair(ColorRequest, appData.colorRequest) < 0 ||
2580 parse_cpair(ColorSeek, appData.colorSeek) < 0 ||
2581 parse_cpair(ColorNormal, appData.colorNormal) < 0)
2583 if (appData.colorize) {
2585 _("%s: can't parse color names; disabling colorization\n"),
2588 appData.colorize = FALSE;
2590 textColors[ColorNone].fg = textColors[ColorNone].bg = -1;
2591 textColors[ColorNone].attr = 0;
2593 XtAppAddActions(appContext, boardActions, XtNumber(boardActions));
2599 layoutName = "tinyLayout";
2600 } else if (smallLayout) {
2601 layoutName = "smallLayout";
2603 layoutName = "normalLayout";
2605 /* Outer layoutWidget is there only to provide a name for use in
2606 resources that depend on the layout style */
2608 XtCreateManagedWidget(layoutName, formWidgetClass, shellWidget,
2609 layoutArgs, XtNumber(layoutArgs));
2611 XtCreateManagedWidget("form", formWidgetClass, layoutWidget,
2612 formArgs, XtNumber(formArgs));
2613 XtSetArg(args[0], XtNdefaultDistance, &sep);
2614 XtGetValues(formWidget, args, 1);
2617 widgetList[j++] = menuBarWidget = CreateMenuBar(menuBar);
2618 XtSetArg(args[0], XtNtop, XtChainTop);
2619 XtSetArg(args[1], XtNbottom, XtChainTop);
2620 XtSetValues(menuBarWidget, args, 2);
2622 widgetList[j++] = whiteTimerWidget =
2623 XtCreateWidget("whiteTime", labelWidgetClass,
2624 formWidget, timerArgs, XtNumber(timerArgs));
2625 XtSetArg(args[0], XtNfont, clockFontStruct);
2626 XtSetArg(args[1], XtNtop, XtChainTop);
2627 XtSetArg(args[2], XtNbottom, XtChainTop);
2628 XtSetValues(whiteTimerWidget, args, 3);
2630 widgetList[j++] = blackTimerWidget =
2631 XtCreateWidget("blackTime", labelWidgetClass,
2632 formWidget, timerArgs, XtNumber(timerArgs));
2633 XtSetArg(args[0], XtNfont, clockFontStruct);
2634 XtSetArg(args[1], XtNtop, XtChainTop);
2635 XtSetArg(args[2], XtNbottom, XtChainTop);
2636 XtSetValues(blackTimerWidget, args, 3);
2638 if (appData.titleInWindow) {
2639 widgetList[j++] = titleWidget =
2640 XtCreateWidget("title", labelWidgetClass, formWidget,
2641 titleArgs, XtNumber(titleArgs));
2642 XtSetArg(args[0], XtNtop, XtChainTop);
2643 XtSetArg(args[1], XtNbottom, XtChainTop);
2644 XtSetValues(titleWidget, args, 2);
2647 if (appData.showButtonBar) {
2648 widgetList[j++] = buttonBarWidget = CreateButtonBar(buttonBar);
2649 XtSetArg(args[0], XtNleft, XtChainRight); // [HGM] glue to right window edge
2650 XtSetArg(args[1], XtNright, XtChainRight); // for good run-time sizing
2651 XtSetArg(args[2], XtNtop, XtChainTop);
2652 XtSetArg(args[3], XtNbottom, XtChainTop);
2653 XtSetValues(buttonBarWidget, args, 4);
2656 widgetList[j++] = messageWidget =
2657 XtCreateWidget("message", labelWidgetClass, formWidget,
2658 messageArgs, XtNumber(messageArgs));
2659 XtSetArg(args[0], XtNtop, XtChainTop);
2660 XtSetArg(args[1], XtNbottom, XtChainTop);
2661 XtSetValues(messageWidget, args, 2);
2663 widgetList[j++] = boardWidget =
2664 XtCreateWidget("board", widgetClass, formWidget, boardArgs,
2665 XtNumber(boardArgs));
2667 XtManageChildren(widgetList, j);
2669 timerWidth = (boardWidth - sep) / 2;
2670 XtSetArg(args[0], XtNwidth, timerWidth);
2671 XtSetValues(whiteTimerWidget, args, 1);
2672 XtSetValues(blackTimerWidget, args, 1);
2674 XtSetArg(args[0], XtNbackground, &timerBackgroundPixel);
2675 XtSetArg(args[1], XtNforeground, &timerForegroundPixel);
2676 XtGetValues(whiteTimerWidget, args, 2);
2678 if (appData.showButtonBar) {
2679 XtSetArg(args[0], XtNbackground, &buttonBackgroundPixel);
2680 XtSetArg(args[1], XtNforeground, &buttonForegroundPixel);
2681 XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
2685 * formWidget uses these constraints but they are stored
2689 XtSetArg(args[i], XtNfromHoriz, 0); i++;
2690 XtSetValues(menuBarWidget, args, i);
2691 if (appData.titleInWindow) {
2694 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2695 XtSetValues(whiteTimerWidget, args, i);
2697 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2698 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2699 XtSetValues(blackTimerWidget, args, i);
2701 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2702 XtSetArg(args[i], XtNjustify, XtJustifyLeft); i++;
2703 XtSetValues(titleWidget, args, i);
2705 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2706 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2707 XtSetValues(messageWidget, args, i);
2708 if (appData.showButtonBar) {
2710 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2711 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2712 XtSetValues(buttonBarWidget, args, i);
2716 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2717 XtSetValues(whiteTimerWidget, args, i);
2719 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2720 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2721 XtSetValues(blackTimerWidget, args, i);
2723 XtSetArg(args[i], XtNfromHoriz, menuBarWidget); i++;
2724 XtSetValues(titleWidget, args, i);
2726 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2727 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2728 XtSetValues(messageWidget, args, i);
2729 if (appData.showButtonBar) {
2731 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2732 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2733 XtSetValues(buttonBarWidget, args, i);
2738 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2739 XtSetValues(whiteTimerWidget, args, i);
2741 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2742 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2743 XtSetValues(blackTimerWidget, args, i);
2745 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2746 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2747 XtSetValues(messageWidget, args, i);
2748 if (appData.showButtonBar) {
2750 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2751 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2752 XtSetValues(buttonBarWidget, args, i);
2756 XtSetArg(args[0], XtNfromVert, messageWidget);
2757 XtSetArg(args[1], XtNtop, XtChainTop);
2758 XtSetArg(args[2], XtNbottom, XtChainBottom);
2759 XtSetArg(args[3], XtNleft, XtChainLeft);
2760 XtSetArg(args[4], XtNright, XtChainRight);
2761 XtSetValues(boardWidget, args, 5);
2763 XtRealizeWidget(shellWidget);
2766 * Correct the width of the message and title widgets.
2767 * It is not known why some systems need the extra fudge term.
2768 * The value "2" is probably larger than needed.
2770 XawFormDoLayout(formWidget, False);
2772 #define WIDTH_FUDGE 2
2774 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2775 XtSetArg(args[i], XtNheight, &h); i++;
2776 XtGetValues(messageWidget, args, i);
2777 if (appData.showButtonBar) {
2779 XtSetArg(args[i], XtNwidth, &w); i++;
2780 XtGetValues(buttonBarWidget, args, i);
2781 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2783 w = boardWidth - 2*bor + 1; /*!! +1 compensates for kludge below */
2786 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2787 if (gres != XtGeometryYes && appData.debugMode) {
2788 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2789 programName, gres, w, h, wr, hr);
2792 /* !! Horrible hack to work around bug in XFree86 4.0.1 (X11R6.4.3) */
2793 /* The size used for the child widget in layout lags one resize behind
2794 its true size, so we resize a second time, 1 pixel smaller. Yeech! */
2796 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2797 if (gres != XtGeometryYes && appData.debugMode) {
2798 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2799 programName, gres, w, h, wr, hr);
2802 XtSetArg(args[0], XtNleft, XtChainLeft); // [HGM] glue ends for good run-time sizing
2803 XtSetArg(args[1], XtNright, XtChainRight);
2804 XtSetValues(messageWidget, args, 2);
2806 if (appData.titleInWindow) {
2808 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2809 XtSetArg(args[i], XtNheight, &h); i++;
2810 XtGetValues(titleWidget, args, i);
2812 w = boardWidth - 2*bor;
2814 XtSetArg(args[0], XtNwidth, &w);
2815 XtGetValues(menuBarWidget, args, 1);
2816 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2819 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
2820 if (gres != XtGeometryYes && appData.debugMode) {
2822 _("%s: titleWidget geometry error %d %d %d %d %d\n"),
2823 programName, gres, w, h, wr, hr);
2826 XawFormDoLayout(formWidget, True);
2828 xBoardWindow = XtWindow(boardWidget);
2830 // [HGM] it seems the layout code ends here, but perhaps the color stuff is size independent and would
2831 // not need to go into InitDrawingSizes().
2835 * Create X checkmark bitmap and initialize option menu checks.
2837 ReadBitmap(&xMarkPixmap, "checkmark.bm",
2838 checkmark_bits, checkmark_width, checkmark_height);
2839 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
2840 if (appData.alwaysPromoteToQueen) {
2841 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
2844 if (appData.animateDragging) {
2845 XtSetValues(XtNameToWidget(menuBarWidget,
2846 "menuOptions.Animate Dragging"),
2849 if (appData.animate) {
2850 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
2853 if (appData.autoComment) {
2854 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
2857 if (appData.autoCallFlag) {
2858 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
2861 if (appData.autoFlipView) {
2862 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Auto Flip View"),
2865 if (appData.autoObserve) {
2866 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
2869 if (appData.autoRaiseBoard) {
2870 XtSetValues(XtNameToWidget(menuBarWidget,
2871 "menuOptions.Auto Raise Board"), args, 1);
2873 if (appData.autoSaveGames) {
2874 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
2877 if (appData.saveGameFile[0] != NULLCHAR) {
2878 /* Can't turn this off from menu */
2879 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
2881 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
2885 if (appData.blindfold) {
2886 XtSetValues(XtNameToWidget(menuBarWidget,
2887 "menuOptions.Blindfold"), args, 1);
2889 if (appData.flashCount > 0) {
2890 XtSetValues(XtNameToWidget(menuBarWidget,
2891 "menuOptions.Flash Moves"),
2894 if (appData.getMoveList) {
2895 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
2899 if (appData.highlightDragging) {
2900 XtSetValues(XtNameToWidget(menuBarWidget,
2901 "menuOptions.Highlight Dragging"),
2905 if (appData.highlightLastMove) {
2906 XtSetValues(XtNameToWidget(menuBarWidget,
2907 "menuOptions.Highlight Last Move"),
2910 if (appData.icsAlarm) {
2911 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.ICS Alarm"),
2914 if (appData.ringBellAfterMoves) {
2915 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
2918 if (appData.oldSaveStyle) {
2919 XtSetValues(XtNameToWidget(menuBarWidget,
2920 "menuOptions.Old Save Style"), args, 1);
2922 if (appData.periodicUpdates) {
2923 XtSetValues(XtNameToWidget(menuBarWidget,
2924 "menuOptions.Periodic Updates"), args, 1);
2926 if (appData.ponderNextMove) {
2927 XtSetValues(XtNameToWidget(menuBarWidget,
2928 "menuOptions.Ponder Next Move"), args, 1);
2930 if (appData.popupExitMessage) {
2931 XtSetValues(XtNameToWidget(menuBarWidget,
2932 "menuOptions.Popup Exit Message"), args, 1);
2934 if (appData.popupMoveErrors) {
2935 XtSetValues(XtNameToWidget(menuBarWidget,
2936 "menuOptions.Popup Move Errors"), args, 1);
2938 if (appData.premove) {
2939 XtSetValues(XtNameToWidget(menuBarWidget,
2940 "menuOptions.Premove"), args, 1);
2942 if (appData.quietPlay) {
2943 XtSetValues(XtNameToWidget(menuBarWidget,
2944 "menuOptions.Quiet Play"), args, 1);
2946 if (appData.showCoords) {
2947 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
2950 if (appData.hideThinkingFromHuman) {
2951 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
2954 if (appData.testLegality) {
2955 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Test Legality"),
2962 ReadBitmap(&wIconPixmap, "icon_white.bm",
2963 icon_white_bits, icon_white_width, icon_white_height);
2964 ReadBitmap(&bIconPixmap, "icon_black.bm",
2965 icon_black_bits, icon_black_width, icon_black_height);
2966 iconPixmap = wIconPixmap;
2968 XtSetArg(args[i], XtNiconPixmap, iconPixmap); i++;
2969 XtSetValues(shellWidget, args, i);
2972 * Create a cursor for the board widget.
2974 window_attributes.cursor = XCreateFontCursor(xDisplay, XC_hand2);
2975 XChangeWindowAttributes(xDisplay, xBoardWindow,
2976 CWCursor, &window_attributes);
2979 * Inhibit shell resizing.
2981 shellArgs[0].value = (XtArgVal) &w;
2982 shellArgs[1].value = (XtArgVal) &h;
2983 XtGetValues(shellWidget, shellArgs, 2);
2984 shellArgs[4].value = shellArgs[2].value = w;
2985 shellArgs[5].value = shellArgs[3].value = h;
2986 XtSetValues(shellWidget, &shellArgs[2], 4);
2987 marginW = w - boardWidth; // [HGM] needed to set new shellWidget size when we resize board
2988 marginH = h - boardHeight;
2990 CatchDeleteWindow(shellWidget, "QuitProc");
2995 if (appData.bitmapDirectory[0] != NULLCHAR) {
3002 /* Create regular pieces */
3003 if (!useImages) CreatePieces();
3008 if (appData.animate || appData.animateDragging)
3011 XtAugmentTranslations(formWidget,
3012 XtParseTranslationTable(globalTranslations));
3013 XtAugmentTranslations(boardWidget,
3014 XtParseTranslationTable(boardTranslations));
3015 XtAugmentTranslations(whiteTimerWidget,
3016 XtParseTranslationTable(whiteTranslations));
3017 XtAugmentTranslations(blackTimerWidget,
3018 XtParseTranslationTable(blackTranslations));
3020 /* Why is the following needed on some versions of X instead
3021 * of a translation? */
3022 XtAddEventHandler(boardWidget, ExposureMask, False,
3023 (XtEventHandler) EventProc, NULL);
3028 if (errorExitStatus == -1) {
3029 if (appData.icsActive) {
3030 /* We now wait until we see "login:" from the ICS before
3031 sending the logon script (problems with timestamp otherwise) */
3032 /*ICSInitScript();*/
3033 if (appData.icsInputBox) ICSInputBoxPopUp();
3036 signal(SIGINT, IntSigHandler);
3037 signal(SIGTERM, IntSigHandler);
3038 if (*appData.cmailGameName != NULLCHAR) {
3039 signal(SIGUSR1, CmailSigHandler);
3044 XtAppMainLoop(appContext);
3045 if (appData.debugMode) fclose(debugFP); // [DM] debug
3052 if (appData.icsActive && oldICSInteractionTitle != NULL) {
3053 DisplayIcsInteractionTitle(oldICSInteractionTitle);
3055 unlink(gameCopyFilename);
3056 unlink(gamePasteFilename);
3067 CmailSigHandler(sig)
3073 signal(SIGUSR1, SIG_IGN); /* suspend handler */
3075 /* Activate call-back function CmailSigHandlerCallBack() */
3076 OutputToProcess(cmailPR, (char *)(&dummy), sizeof(int), &error);
3078 signal(SIGUSR1, CmailSigHandler); /* re-activate handler */
3082 CmailSigHandlerCallBack(isr, closure, message, count, error)
3090 ReloadCmailMsgEvent(TRUE); /* Reload cmail msg */
3092 /**** end signal code ****/
3102 f = fopen(appData.icsLogon, "r");
3108 strcat(buf, appData.icsLogon);
3109 f = fopen(buf, "r");
3113 ProcessICSInitScript(f);
3120 EditCommentPopDown();
3131 SetMenuEnables(enab)
3135 if (!menuBarWidget) return;
3136 while (enab->name != NULL) {
3137 w = XtNameToWidget(menuBarWidget, enab->name);
3139 DisplayError(enab->name, 0);
3141 XtSetSensitive(w, enab->value);
3147 Enables icsEnables[] = {
3148 { "menuFile.Mail Move", False },
3149 { "menuFile.Reload CMail Message", False },
3150 { "menuMode.Machine Black", False },
3151 { "menuMode.Machine White", False },
3152 { "menuMode.Analysis Mode", False },
3153 { "menuMode.Analyze File", False },
3154 { "menuMode.Two Machines", False },
3156 { "menuHelp.Hint", False },
3157 { "menuHelp.Book", False },
3158 { "menuStep.Move Now", False },
3159 { "menuOptions.Periodic Updates", False },
3160 { "menuOptions.Hide Thinking", False },
3161 { "menuOptions.Ponder Next Move", False },
3166 Enables ncpEnables[] = {
3167 { "menuFile.Mail Move", False },
3168 { "menuFile.Reload CMail Message", False },
3169 { "menuMode.Machine White", False },
3170 { "menuMode.Machine Black", False },
3171 { "menuMode.Analysis Mode", False },
3172 { "menuMode.Analyze File", False },
3173 { "menuMode.Two Machines", False },
3174 { "menuMode.ICS Client", False },
3175 { "menuMode.ICS Input Box", False },
3176 { "Action", False },
3177 { "menuStep.Revert", False },
3178 { "menuStep.Move Now", False },
3179 { "menuStep.Retract Move", False },
3180 { "menuOptions.Auto Comment", False },
3181 { "menuOptions.Auto Flag", False },
3182 { "menuOptions.Auto Flip View", False },
3183 { "menuOptions.Auto Observe", False },
3184 { "menuOptions.Auto Raise Board", False },
3185 { "menuOptions.Get Move List", False },
3186 { "menuOptions.ICS Alarm", False },
3187 { "menuOptions.Move Sound", False },
3188 { "menuOptions.Quiet Play", False },
3189 { "menuOptions.Hide Thinking", False },
3190 { "menuOptions.Periodic Updates", False },
3191 { "menuOptions.Ponder Next Move", False },
3192 { "menuHelp.Hint", False },
3193 { "menuHelp.Book", False },
3197 Enables gnuEnables[] = {
3198 { "menuMode.ICS Client", False },
3199 { "menuMode.ICS Input Box", False },
3200 { "menuAction.Accept", False },
3201 { "menuAction.Decline", False },
3202 { "menuAction.Rematch", False },
3203 { "menuAction.Adjourn", False },
3204 { "menuAction.Stop Examining", False },
3205 { "menuAction.Stop Observing", False },
3206 { "menuStep.Revert", False },
3207 { "menuOptions.Auto Comment", False },
3208 { "menuOptions.Auto Observe", False },
3209 { "menuOptions.Auto Raise Board", False },
3210 { "menuOptions.Get Move List", False },
3211 { "menuOptions.Premove", False },
3212 { "menuOptions.Quiet Play", False },
3214 /* The next two options rely on SetCmailMode being called *after* */
3215 /* SetGNUMode so that when GNU is being used to give hints these */
3216 /* menu options are still available */
3218 { "menuFile.Mail Move", False },
3219 { "menuFile.Reload CMail Message", False },
3223 Enables cmailEnables[] = {
3225 { "menuAction.Call Flag", False },
3226 { "menuAction.Draw", True },
3227 { "menuAction.Adjourn", False },
3228 { "menuAction.Abort", False },
3229 { "menuAction.Stop Observing", False },
3230 { "menuAction.Stop Examining", False },
3231 { "menuFile.Mail Move", True },
3232 { "menuFile.Reload CMail Message", True },
3236 Enables trainingOnEnables[] = {
3237 { "menuMode.Edit Comment", False },
3238 { "menuMode.Pause", False },
3239 { "menuStep.Forward", False },
3240 { "menuStep.Backward", False },
3241 { "menuStep.Forward to End", False },
3242 { "menuStep.Back to Start", False },
3243 { "menuStep.Move Now", False },
3244 { "menuStep.Truncate Game", False },
3248 Enables trainingOffEnables[] = {
3249 { "menuMode.Edit Comment", True },
3250 { "menuMode.Pause", True },
3251 { "menuStep.Forward", True },
3252 { "menuStep.Backward", True },
3253 { "menuStep.Forward to End", True },
3254 { "menuStep.Back to Start", True },
3255 { "menuStep.Move Now", True },
3256 { "menuStep.Truncate Game", True },
3260 Enables machineThinkingEnables[] = {
3261 { "menuFile.Load Game", False },
3262 { "menuFile.Load Next Game", False },
3263 { "menuFile.Load Previous Game", False },
3264 { "menuFile.Reload Same Game", False },
3265 { "menuFile.Paste Game", False },
3266 { "menuFile.Load Position", False },
3267 { "menuFile.Load Next Position", False },
3268 { "menuFile.Load Previous Position", False },
3269 { "menuFile.Reload Same Position", False },
3270 { "menuFile.Paste Position", False },
3271 { "menuMode.Machine White", False },
3272 { "menuMode.Machine Black", False },
3273 { "menuMode.Two Machines", False },
3274 { "menuStep.Retract Move", False },
3278 Enables userThinkingEnables[] = {
3279 { "menuFile.Load Game", True },
3280 { "menuFile.Load Next Game", True },
3281 { "menuFile.Load Previous Game", True },
3282 { "menuFile.Reload Same Game", True },
3283 { "menuFile.Paste Game", True },
3284 { "menuFile.Load Position", True },
3285 { "menuFile.Load Next Position", True },
3286 { "menuFile.Load Previous Position", True },
3287 { "menuFile.Reload Same Position", True },
3288 { "menuFile.Paste Position", True },
3289 { "menuMode.Machine White", True },
3290 { "menuMode.Machine Black", True },
3291 { "menuMode.Two Machines", True },
3292 { "menuStep.Retract Move", True },
3298 SetMenuEnables(icsEnables);
3301 if (appData.zippyPlay && !appData.noChessProgram) /* [DM] icsEngineAnalyze */
3302 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Analysis Mode"), True);
3309 SetMenuEnables(ncpEnables);
3315 SetMenuEnables(gnuEnables);
3321 SetMenuEnables(cmailEnables);
3327 SetMenuEnables(trainingOnEnables);
3328 if (appData.showButtonBar) {
3329 XtSetSensitive(buttonBarWidget, False);
3335 SetTrainingModeOff()
3337 SetMenuEnables(trainingOffEnables);
3338 if (appData.showButtonBar) {
3339 XtSetSensitive(buttonBarWidget, True);
3344 SetUserThinkingEnables()
3346 if (appData.noChessProgram) return;
3347 SetMenuEnables(userThinkingEnables);
3351 SetMachineThinkingEnables()
3353 if (appData.noChessProgram) return;
3354 SetMenuEnables(machineThinkingEnables);
3356 case MachinePlaysBlack:
3357 case MachinePlaysWhite:
3358 case TwoMachinesPlay:
3359 XtSetSensitive(XtNameToWidget(menuBarWidget,
3360 ModeToWidgetName(gameMode)), True);
3367 #define Abs(n) ((n)<0 ? -(n) : (n))
3370 * Find a font that matches "pattern" that is as close as
3371 * possible to the targetPxlSize. Prefer fonts that are k
3372 * pixels smaller to fonts that are k pixels larger. The
3373 * pattern must be in the X Consortium standard format,
3374 * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".
3375 * The return value should be freed with XtFree when no
3378 char *FindFont(pattern, targetPxlSize)
3382 char **fonts, *p, *best, *scalable, *scalableTail;
3383 int i, j, nfonts, minerr, err, pxlSize;
3386 char **missing_list;
3388 char *def_string, *base_fnt_lst, strInt[3];
3390 XFontStruct **fnt_list;
3392 base_fnt_lst = calloc(1, strlen(pattern) + 3);
3393 sprintf(strInt, "%d", targetPxlSize);
3394 p = strstr(pattern, "--");
3395 strncpy(base_fnt_lst, pattern, p - pattern + 2);
3396 strcat(base_fnt_lst, strInt);
3397 strcat(base_fnt_lst, strchr(p + 2, '-'));
3399 if ((fntSet = XCreateFontSet(xDisplay,
3403 &def_string)) == NULL) {
3405 fprintf(stderr, _("Unable to create font set.\n"));
3409 nfonts = XFontsOfFontSet(fntSet, &fnt_list, &fonts);
3411 fonts = XListFonts(xDisplay, pattern, 999999, &nfonts);
3413 fprintf(stderr, _("%s: no fonts match pattern %s\n"),
3414 programName, pattern);
3422 for (i=0; i<nfonts; i++) {
3425 if (*p != '-') continue;
3427 if (*p == NULLCHAR) break;
3428 if (*p++ == '-') j++;
3430 if (j < 7) continue;
3433 scalable = fonts[i];
3436 err = pxlSize - targetPxlSize;
3437 if (Abs(err) < Abs(minerr) ||
3438 (minerr > 0 && err < 0 && -err == minerr)) {
3444 if (scalable && Abs(minerr) > appData.fontSizeTolerance) {
3445 /* If the error is too big and there is a scalable font,
3446 use the scalable font. */
3447 int headlen = scalableTail - scalable;
3448 p = (char *) XtMalloc(strlen(scalable) + 10);
3449 while (isdigit(*scalableTail)) scalableTail++;
3450 sprintf(p, "%.*s%d%s", headlen, scalable, targetPxlSize, scalableTail);
3452 p = (char *) XtMalloc(strlen(best) + 1);
3455 if (appData.debugMode) {
3456 fprintf(debugFP, _("resolved %s at pixel size %d\n to %s\n"),
3457 pattern, targetPxlSize, p);
3460 if (missing_count > 0)
3461 XFreeStringList(missing_list);
3462 XFreeFontSet(xDisplay, fntSet);
3464 XFreeFontNames(fonts);
3471 XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
3472 | GCBackground | GCFunction | GCPlaneMask;
3473 XGCValues gc_values;
3476 gc_values.plane_mask = AllPlanes;
3477 gc_values.line_width = lineGap;
3478 gc_values.line_style = LineSolid;
3479 gc_values.function = GXcopy;
3481 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3482 gc_values.background = XBlackPixel(xDisplay, xScreen);
3483 lineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3485 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3486 gc_values.background = XWhitePixel(xDisplay, xScreen);
3487 coordGC = XtGetGC(shellWidget, value_mask, &gc_values);
3488 XSetFont(xDisplay, coordGC, coordFontID);
3490 // [HGM] make font for holdings counts (white on black0
3491 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3492 gc_values.background = XBlackPixel(xDisplay, xScreen);
3493 countGC = XtGetGC(shellWidget, value_mask, &gc_values);
3494 XSetFont(xDisplay, countGC, countFontID);
3496 if (appData.monoMode) {
3497 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3498 gc_values.background = XWhitePixel(xDisplay, xScreen);
3499 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3501 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3502 gc_values.background = XBlackPixel(xDisplay, xScreen);
3503 lightSquareGC = wbPieceGC
3504 = XtGetGC(shellWidget, value_mask, &gc_values);
3506 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3507 gc_values.background = XWhitePixel(xDisplay, xScreen);
3508 darkSquareGC = bwPieceGC
3509 = XtGetGC(shellWidget, value_mask, &gc_values);
3511 if (DefaultDepth(xDisplay, xScreen) == 1) {
3512 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
3513 gc_values.function = GXcopyInverted;
3514 copyInvertedGC = XtGetGC(shellWidget, value_mask, &gc_values);
3515 gc_values.function = GXcopy;
3516 if (XBlackPixel(xDisplay, xScreen) == 1) {
3517 bwPieceGC = darkSquareGC;
3518 wbPieceGC = copyInvertedGC;
3520 bwPieceGC = copyInvertedGC;
3521 wbPieceGC = lightSquareGC;
3525 gc_values.foreground = highlightSquareColor;
3526 gc_values.background = highlightSquareColor;
3527 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3529 gc_values.foreground = premoveHighlightColor;
3530 gc_values.background = premoveHighlightColor;
3531 prelineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3533 gc_values.foreground = lightSquareColor;
3534 gc_values.background = darkSquareColor;
3535 lightSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3537 gc_values.foreground = darkSquareColor;
3538 gc_values.background = lightSquareColor;
3539 darkSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3541 gc_values.foreground = jailSquareColor;
3542 gc_values.background = jailSquareColor;
3543 jailSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3545 gc_values.foreground = whitePieceColor;
3546 gc_values.background = darkSquareColor;
3547 wdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3549 gc_values.foreground = whitePieceColor;
3550 gc_values.background = lightSquareColor;
3551 wlPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3553 gc_values.foreground = whitePieceColor;
3554 gc_values.background = jailSquareColor;
3555 wjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3557 gc_values.foreground = blackPieceColor;
3558 gc_values.background = darkSquareColor;
3559 bdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3561 gc_values.foreground = blackPieceColor;
3562 gc_values.background = lightSquareColor;
3563 blPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3565 gc_values.foreground = blackPieceColor;
3566 gc_values.background = jailSquareColor;
3567 bjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3571 void loadXIM(xim, xmask, filename, dest, mask)
3584 fp = fopen(filename, "rb");
3586 fprintf(stderr, _("%s: error loading XIM!\n"), programName);
3593 for (y=0; y<h; ++y) {
3594 for (x=0; x<h; ++x) {
3599 XPutPixel(xim, x, y, blackPieceColor);
3601 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3604 XPutPixel(xim, x, y, darkSquareColor);
3606 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3609 XPutPixel(xim, x, y, whitePieceColor);
3611 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3614 XPutPixel(xim, x, y, lightSquareColor);
3616 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3622 /* create Pixmap of piece */
3623 *dest = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3625 XPutImage(xDisplay, *dest, lightSquareGC, xim,
3628 /* create Pixmap of clipmask
3629 Note: We assume the white/black pieces have the same
3630 outline, so we make only 6 masks. This is okay
3631 since the XPM clipmask routines do the same. */
3633 temp = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3635 XPutImage(xDisplay, temp, lightSquareGC, xmask,
3638 /* now create the 1-bit version */
3639 *mask = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3642 values.foreground = 1;
3643 values.background = 0;
3645 /* Don't use XtGetGC, not read only */
3646 maskGC = XCreateGC(xDisplay, *mask,
3647 GCForeground | GCBackground, &values);
3648 XCopyPlane(xDisplay, temp, *mask, maskGC,
3649 0, 0, squareSize, squareSize, 0, 0, 1);
3650 XFreePixmap(xDisplay, temp);
3654 void CreateXIMPieces()
3659 static char *ximkind[] = { "ll", "ld", "dl", "dd" };
3664 /* The XSynchronize calls were copied from CreatePieces.
3665 Not sure if needed, but can't hurt */
3666 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3669 /* temp needed by loadXIM() */
3670 ximtemp = XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3671 0, 0, ss, ss, AllPlanes, XYPixmap);
3673 if (strlen(appData.pixmapDirectory) == 0) {
3677 if (appData.monoMode) {
3678 DisplayFatalError(_("XIM pieces cannot be used in monochrome mode"),
3682 fprintf(stderr, _("\nLoading XIMs...\n"));
3684 for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
3685 fprintf(stderr, "%d", piece+1);
3686 for (kind=0; kind<4; kind++) {
3687 fprintf(stderr, ".");
3688 sprintf(buf, "%s/%c%s%u.xim",
3689 ExpandPathName(appData.pixmapDirectory),
3690 ToLower(PieceToChar((ChessSquare)piece)),
3692 ximPieceBitmap[kind][piece] =
3693 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3694 0, 0, ss, ss, AllPlanes, XYPixmap);
3695 if (appData.debugMode)
3696 fprintf(stderr, _("(File:%s:) "), buf);
3697 loadXIM(ximPieceBitmap[kind][piece],
3699 &(xpmPieceBitmap[kind][piece]),
3700 &(ximMaskPm[piece%(int)BlackPawn]));
3702 fprintf(stderr," ");
3704 /* Load light and dark squares */
3705 /* If the LSQ and DSQ pieces don't exist, we will
3706 draw them with solid squares. */
3707 sprintf(buf, "%s/lsq%u.xim", ExpandPathName(appData.pixmapDirectory), ss);
3708 if (access(buf, 0) != 0) {
3712 fprintf(stderr, _("light square "));
3714 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3715 0, 0, ss, ss, AllPlanes, XYPixmap);
3716 if (appData.debugMode)
3717 fprintf(stderr, _("(File:%s:) "), buf);
3719 loadXIM(ximLightSquare, NULL, buf, &xpmLightSquare, NULL);
3720 fprintf(stderr, _("dark square "));
3721 sprintf(buf, "%s/dsq%u.xim",
3722 ExpandPathName(appData.pixmapDirectory), ss);
3723 if (appData.debugMode)
3724 fprintf(stderr, _("(File:%s:) "), buf);
3726 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3727 0, 0, ss, ss, AllPlanes, XYPixmap);
3728 loadXIM(ximDarkSquare, NULL, buf, &xpmDarkSquare, NULL);
3729 xpmJailSquare = xpmLightSquare;
3731 fprintf(stderr, _("Done.\n"));
3733 XSynchronize(xDisplay, False); /* Work-around for xlib/xt buffering bug */
3737 void CreateXPMPieces()
3741 u_int ss = squareSize;
3743 static char *xpmkind[] = { "ll", "ld", "dl", "dd" };
3744 XpmColorSymbol symbols[4];
3747 /* Apparently some versions of Xpm don't define XpmFormat at all --tpm */
3748 if (appData.debugMode) {
3749 fprintf(stderr, "XPM Library Version: %d.%d%c\n",
3750 XpmFormat, XpmVersion, (char)('a' + XpmRevision - 1));
3754 /* The XSynchronize calls were copied from CreatePieces.
3755 Not sure if needed, but can't hurt */
3756 XSynchronize(xDisplay, True); /* Work-around for xlib/xt buffering bug */
3758 /* Setup translations so piece colors match square colors */
3759 symbols[0].name = "light_piece";
3760 symbols[0].value = appData.whitePieceColor;
3761 symbols[1].name = "dark_piece";
3762 symbols[1].value = appData.blackPieceColor;
3763 symbols[2].name = "light_square";
3764 symbols[2].value = appData.lightSquareColor;
3765 symbols[3].name = "dark_square";
3766 symbols[3].value = appData.darkSquareColor;
3768 attr.valuemask = XpmColorSymbols;
3769 attr.colorsymbols = symbols;
3770 attr.numsymbols = 4;
3772 if (appData.monoMode) {
3773 DisplayFatalError(_("XPM pieces cannot be used in monochrome mode"),
3777 if (strlen(appData.pixmapDirectory) == 0) {
3778 XpmPieces* pieces = builtInXpms;
3781 while (pieces->size != squareSize && pieces->size) pieces++;
3782 if (!pieces->size) {
3783 fprintf(stderr, _("No builtin XPM pieces of size %d\n"), squareSize);
3786 for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
3787 for (kind=0; kind<4; kind++) {
3789 if ((r=XpmCreatePixmapFromData(xDisplay, xBoardWindow,
3790 pieces->xpm[piece][kind],
3791 &(xpmPieceBitmap[kind][piece]),
3792 NULL, &attr)) != 0) {
3793 fprintf(stderr, _("Error %d loading XPM image \"%s\"\n"),
3800 xpmJailSquare = xpmLightSquare;
3804 fprintf(stderr, _("\nLoading XPMs...\n"));
3807 for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
3808 fprintf(stderr, "%d ", piece+1);
3809 for (kind=0; kind<4; kind++) {
3810 sprintf(buf, "%s/%c%s%u.xpm",
3811 ExpandPathName(appData.pixmapDirectory),
3812 ToLower(PieceToChar((ChessSquare)piece)),
3814 if (appData.debugMode) {
3815 fprintf(stderr, _("(File:%s:) "), buf);
3817 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3818 &(xpmPieceBitmap[kind][piece]),
3819 NULL, &attr)) != 0) {
3820 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"),
3826 /* Load light and dark squares */
3827 /* If the LSQ and DSQ pieces don't exist, we will
3828 draw them with solid squares. */
3829 fprintf(stderr, _("light square "));
3830 sprintf(buf, "%s/lsq%u.xpm", ExpandPathName(appData.pixmapDirectory), ss);
3831 if (access(buf, 0) != 0) {
3835 if (appData.debugMode)
3836 fprintf(stderr, _("(File:%s:) "), buf);
3838 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3839 &xpmLightSquare, NULL, &attr)) != 0) {
3840 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
3843 fprintf(stderr, _("dark square "));
3844 sprintf(buf, "%s/dsq%u.xpm",
3845 ExpandPathName(appData.pixmapDirectory), ss);
3846 if (appData.debugMode) {
3847 fprintf(stderr, _("(File:%s:) "), buf);
3849 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3850 &xpmDarkSquare, NULL, &attr)) != 0) {
3851 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
3855 xpmJailSquare = xpmLightSquare;
3856 fprintf(stderr, _("Done.\n"));
3858 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3861 #endif /* HAVE_LIBXPM */
3864 /* No built-in bitmaps */
3869 u_int ss = squareSize;
3871 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3874 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
3875 for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
3876 sprintf(buf, "%c%u%c.bm", ToLower(PieceToChar((ChessSquare)piece)),
3877 ss, kind == SOLID ? 's' : 'o');
3878 ReadBitmap(&pieceBitmap[kind][piece], buf, NULL, ss, ss);
3882 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3886 /* With built-in bitmaps */
3889 BuiltInBits* bib = builtInBits;
3892 u_int ss = squareSize;
3894 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3897 while (bib->squareSize != ss && bib->squareSize != 0) bib++;
3899 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
3900 for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
3901 sprintf(buf, "%c%u%c.bm", ToLower(PieceToChar((ChessSquare)piece)),
3902 ss, kind == SOLID ? 's' : 'o');
3903 ReadBitmap(&pieceBitmap[kind][piece], buf,
3904 bib->bits[kind][piece], ss, ss);
3908 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3913 void ReadBitmap(pm, name, bits, wreq, hreq)
3916 unsigned char bits[];
3922 char msg[MSG_SIZ], fullname[MSG_SIZ];
3924 if (*appData.bitmapDirectory != NULLCHAR) {
3925 strcpy(fullname, appData.bitmapDirectory);
3926 strcat(fullname, "/");
3927 strcat(fullname, name);
3928 errcode = XReadBitmapFile(xDisplay, xBoardWindow, fullname,
3929 &w, &h, pm, &x_hot, &y_hot);
3930 if (errcode != BitmapSuccess) {
3932 case BitmapOpenFailed:
3933 sprintf(msg, _("Can't open bitmap file %s"), fullname);
3935 case BitmapFileInvalid:
3936 sprintf(msg, _("Invalid bitmap in file %s"), fullname);
3938 case BitmapNoMemory:
3939 sprintf(msg, _("Ran out of memory reading bitmap file %s"),
3943 sprintf(msg, _("Unknown XReadBitmapFile error %d on file %s"),
3947 fprintf(stderr, _("%s: %s...using built-in\n"),
3949 } else if (w != wreq || h != hreq) {
3951 _("%s: Bitmap %s is %dx%d, not %dx%d...using built-in\n"),
3952 programName, fullname, w, h, wreq, hreq);
3959 fprintf(stderr, _("%s: No built-in bitmap for %s; giving up\n"),
3963 ; // [HGM] bitmaps: make it non-fatal if we have no bitmap;
3965 *pm = XCreateBitmapFromData(xDisplay, xBoardWindow, (char *) bits,
3974 if (lineGap == 0) return;
3976 /* [HR] Split this into 2 loops for non-square boards. */
3978 for (i = 0; i < BOARD_HEIGHT + 1; i++) {
3979 gridSegments[i].x1 = 0;
3980 gridSegments[i].x2 =
3981 lineGap + BOARD_WIDTH * (squareSize + lineGap);
3982 gridSegments[i].y1 = gridSegments[i].y2
3983 = lineGap / 2 + (i * (squareSize + lineGap));
3986 for (j = 0; j < BOARD_WIDTH + 1; j++) {
3987 gridSegments[j + i].y1 = 0;
3988 gridSegments[j + i].y2 =
3989 lineGap + BOARD_HEIGHT * (squareSize + lineGap);
3990 gridSegments[j + i].x1 = gridSegments[j + i].x2
3991 = lineGap / 2 + (j * (squareSize + lineGap));
3995 static void MenuBarSelect(w, addr, index)
4000 XtActionProc proc = (XtActionProc) addr;
4002 (proc)(NULL, NULL, NULL, NULL);
4005 void CreateMenuBarPopup(parent, name, mb)
4015 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
4018 XtSetArg(args[j], XtNleftMargin, 20); j++;
4019 XtSetArg(args[j], XtNrightMargin, 20); j++;
4021 while (mi->string != NULL) {
4022 if (strcmp(mi->string, "----") == 0) {
4023 entry = XtCreateManagedWidget(mi->string, smeLineObjectClass,
4026 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string)));
4027 entry = XtCreateManagedWidget(mi->string, smeBSBObjectClass,
4029 XtAddCallback(entry, XtNcallback,
4030 (XtCallbackProc) MenuBarSelect,
4031 (caddr_t) mi->proc);
4037 Widget CreateMenuBar(mb)
4041 Widget anchor, menuBar;
4043 char menuName[MSG_SIZ];
4046 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
4047 XtSetArg(args[j], XtNvSpace, 0); j++;
4048 XtSetArg(args[j], XtNborderWidth, 0); j++;
4049 menuBar = XtCreateWidget("menuBar", boxWidgetClass,
4050 formWidget, args, j);
4052 while (mb->name != NULL) {
4053 strcpy(menuName, "menu");
4054 strcat(menuName, mb->name);
4056 XtSetArg(args[j], XtNmenuName, XtNewString(menuName)); j++;
4059 shortName[0] = _(mb->name)[0];
4060 shortName[1] = NULLCHAR;
4061 XtSetArg(args[j], XtNlabel, XtNewString(shortName)); j++;
4064 XtSetArg(args[j], XtNlabel, XtNewString(_(mb->name))); j++;
4067 XtSetArg(args[j], XtNborderWidth, 0); j++;
4068 anchor = XtCreateManagedWidget(mb->name, menuButtonWidgetClass,
4070 CreateMenuBarPopup(menuBar, menuName, mb);
4076 Widget CreateButtonBar(mi)
4080 Widget button, buttonBar;
4084 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
4086 XtSetArg(args[j], XtNhSpace, 0); j++;
4088 XtSetArg(args[j], XtNborderWidth, 0); j++;
4089 XtSetArg(args[j], XtNvSpace, 0); j++;
4090 buttonBar = XtCreateWidget("buttonBar", boxWidgetClass,
4091 formWidget, args, j);
4093 while (mi->string != NULL) {
4096 XtSetArg(args[j], XtNinternalWidth, 2); j++;
4097 XtSetArg(args[j], XtNborderWidth, 0); j++;
4099 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string))); j++;
4100 button = XtCreateManagedWidget(mi->string, commandWidgetClass,
4101 buttonBar, args, j);
4102 XtAddCallback(button, XtNcallback,
4103 (XtCallbackProc) MenuBarSelect,
4104 (caddr_t) mi->proc);
4111 CreatePieceMenu(name, color)
4118 ChessSquare selection;
4120 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
4121 boardWidget, args, 0);
4123 for (i = 0; i < PIECE_MENU_SIZE; i++) {
4124 String item = pieceMenuStrings[color][i];
4126 if (strcmp(item, "----") == 0) {
4127 entry = XtCreateManagedWidget(item, smeLineObjectClass,
4130 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
4131 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
4133 selection = pieceMenuTranslation[color][i];
4134 XtAddCallback(entry, XtNcallback,
4135 (XtCallbackProc) PieceMenuSelect,
4136 (caddr_t) selection);
4137 if (selection == WhitePawn || selection == BlackPawn) {
4138 XtSetArg(args[0], XtNpopupOnEntry, entry);
4139 XtSetValues(menu, args, 1);
4152 ChessSquare selection;
4154 whitePieceMenu = CreatePieceMenu("menuW", 0);
4155 blackPieceMenu = CreatePieceMenu("menuB", 1);
4157 XtRegisterGrabAction(PieceMenuPopup, True,
4158 (unsigned)(ButtonPressMask|ButtonReleaseMask),
4159 GrabModeAsync, GrabModeAsync);
4161 XtSetArg(args[0], XtNlabel, _("Drop"));
4162 dropMenu = XtCreatePopupShell("menuD", simpleMenuWidgetClass,
4163 boardWidget, args, 1);
4164 for (i = 0; i < DROP_MENU_SIZE; i++) {
4165 String item = dropMenuStrings[i];
4167 if (strcmp(item, "----") == 0) {
4168 entry = XtCreateManagedWidget(item, smeLineObjectClass,
4171 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
4172 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
4174 selection = dropMenuTranslation[i];
4175 XtAddCallback(entry, XtNcallback,
4176 (XtCallbackProc) DropMenuSelect,
4177 (caddr_t) selection);
4182 void SetupDropMenu()
4190 for (i=0; i<sizeof(dmEnables)/sizeof(DropMenuEnables); i++) {
4191 entry = XtNameToWidget(dropMenu, dmEnables[i].widget);
4192 p = strchr(gameMode == IcsPlayingWhite ? white_holding : black_holding,
4193 dmEnables[i].piece);
4194 XtSetSensitive(entry, p != NULL || !appData.testLegality
4195 /*!!temp:*/ || (gameInfo.variant == VariantCrazyhouse
4196 && !appData.icsActive));
4198 while (p && *p++ == dmEnables[i].piece) count++;
4199 sprintf(label, "%s %d", dmEnables[i].widget, count);
4201 XtSetArg(args[j], XtNlabel, label); j++;
4202 XtSetValues(entry, args, j);
4206 void PieceMenuPopup(w, event, params, num_params)
4210 Cardinal *num_params;
4213 if (event->type != ButtonPress) return;
4214 if (errorUp) ErrorPopDown();
4218 whichMenu = params[0];
4220 case IcsPlayingWhite:
4221 case IcsPlayingBlack:
4223 case MachinePlaysWhite:
4224 case MachinePlaysBlack:
4225 if (appData.testLegality &&
4226 gameInfo.variant != VariantBughouse &&
4227 gameInfo.variant != VariantCrazyhouse) return;
4229 whichMenu = "menuD";
4235 if (((pmFromX = EventToSquare(event->xbutton.x, BOARD_WIDTH)) < 0) ||
4236 ((pmFromY = EventToSquare(event->xbutton.y, BOARD_HEIGHT)) < 0)) {
4237 pmFromX = pmFromY = -1;
4241 pmFromX = BOARD_WIDTH - 1 - pmFromX;
4243 pmFromY = BOARD_HEIGHT - 1 - pmFromY;
4245 XtPopupSpringLoaded(XtNameToWidget(boardWidget, whichMenu));
4248 static void PieceMenuSelect(w, piece, junk)
4253 if (pmFromX < 0 || pmFromY < 0) return;
4254 EditPositionMenuEvent(piece, pmFromX, pmFromY);
4257 static void DropMenuSelect(w, piece, junk)
4262 if (pmFromX < 0 || pmFromY < 0) return;
4263 DropMenuEvent(piece, pmFromX, pmFromY);
4266 void WhiteClock(w, event, prms, nprms)
4272 if (gameMode == EditPosition || gameMode == IcsExamining) {
4273 SetWhiteToPlayEvent();
4274 } else if (gameMode == IcsPlayingBlack || gameMode == MachinePlaysWhite) {
4279 void BlackClock(w, event, prms, nprms)
4285 if (gameMode == EditPosition || gameMode == IcsExamining) {
4286 SetBlackToPlayEvent();
4287 } else if (gameMode == IcsPlayingWhite || gameMode == MachinePlaysBlack) {
4294 * If the user selects on a border boundary, return -1; if off the board,
4295 * return -2. Otherwise map the event coordinate to the square.
4297 int EventToSquare(x, limit)
4305 if ((x % (squareSize + lineGap)) >= squareSize)
4307 x /= (squareSize + lineGap);
4313 static void do_flash_delay(msec)
4319 static void drawHighlight(file, rank, gc)
4325 if (lineGap == 0 || appData.blindfold) return;
4328 x = lineGap/2 + ((BOARD_WIDTH-1)-file) *
4329 (squareSize + lineGap);
4330 y = lineGap/2 + rank * (squareSize + lineGap);
4332 x = lineGap/2 + file * (squareSize + lineGap);
4333 y = lineGap/2 + ((BOARD_HEIGHT-1)-rank) *
4334 (squareSize + lineGap);
4337 XDrawRectangle(xDisplay, xBoardWindow, gc, x, y,
4338 squareSize+lineGap, squareSize+lineGap);
4341 int hi1X = -1, hi1Y = -1, hi2X = -1, hi2Y = -1;
4342 int pm1X = -1, pm1Y = -1, pm2X = -1, pm2Y = -1;
4345 SetHighlights(fromX, fromY, toX, toY)
4346 int fromX, fromY, toX, toY;
4348 if (hi1X != fromX || hi1Y != fromY) {
4349 if (hi1X >= 0 && hi1Y >= 0) {
4350 drawHighlight(hi1X, hi1Y, lineGC);
4352 if (fromX >= 0 && fromY >= 0) {
4353 drawHighlight(fromX, fromY, highlineGC);
4356 if (hi2X != toX || hi2Y != toY) {
4357 if (hi2X >= 0 && hi2Y >= 0) {
4358 drawHighlight(hi2X, hi2Y, lineGC);
4360 if (toX >= 0 && toY >= 0) {
4361 drawHighlight(toX, toY, highlineGC);
4373 SetHighlights(-1, -1, -1, -1);
4378 SetPremoveHighlights(fromX, fromY, toX, toY)
4379 int fromX, fromY, toX, toY;
4381 if (pm1X != fromX || pm1Y != fromY) {
4382 if (pm1X >= 0 && pm1Y >= 0) {
4383 drawHighlight(pm1X, pm1Y, lineGC);
4385 if (fromX >= 0 && fromY >= 0) {
4386 drawHighlight(fromX, fromY, prelineGC);
4389 if (pm2X != toX || pm2Y != toY) {
4390 if (pm2X >= 0 && pm2Y >= 0) {
4391 drawHighlight(pm2X, pm2Y, lineGC);
4393 if (toX >= 0 && toY >= 0) {
4394 drawHighlight(toX, toY, prelineGC);
4404 ClearPremoveHighlights()
4406 SetPremoveHighlights(-1, -1, -1, -1);
4409 static void BlankSquare(x, y, color, piece, dest)
4414 if (useImages && useImageSqs) {
4418 pm = xpmLightSquare;
4423 case 2: /* neutral */
4428 XCopyArea(xDisplay, pm, dest, wlPieceGC, 0, 0,
4429 squareSize, squareSize, x, y);
4439 case 2: /* neutral */
4444 XFillRectangle(xDisplay, dest, gc, x, y, squareSize, squareSize);
4449 I split out the routines to draw a piece so that I could
4450 make a generic flash routine.
4452 static void monoDrawPiece_1bit(piece, square_color, x, y, dest)
4454 int square_color, x, y;
4457 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
4458 switch (square_color) {
4460 case 2: /* neutral */
4462 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
4463 ? *pieceToOutline(piece)
4464 : *pieceToSolid(piece),
4465 dest, bwPieceGC, 0, 0,
4466 squareSize, squareSize, x, y);
4469 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
4470 ? *pieceToSolid(piece)
4471 : *pieceToOutline(piece),
4472 dest, wbPieceGC, 0, 0,
4473 squareSize, squareSize, x, y);
4478 static void monoDrawPiece(piece, square_color, x, y, dest)
4480 int square_color, x, y;
4483 switch (square_color) {
4485 case 2: /* neutral */
4487 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
4488 ? *pieceToOutline(piece)
4489 : *pieceToSolid(piece),
4490 dest, bwPieceGC, 0, 0,
4491 squareSize, squareSize, x, y, 1);
4494 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
4495 ? *pieceToSolid(piece)
4496 : *pieceToOutline(piece),
4497 dest, wbPieceGC, 0, 0,
4498 squareSize, squareSize, x, y, 1);
4503 static void colorDrawPiece(piece, square_color, x, y, dest)
4505 int square_color, x, y;
4508 if(pieceToSolid(piece) == NULL) return; // [HGM] bitmaps: make it non-fatal if we have no bitmap;
4509 switch (square_color) {
4511 XCopyPlane(xDisplay, *pieceToSolid(piece),
4512 dest, (int) piece < (int) BlackPawn
4513 ? wlPieceGC : blPieceGC, 0, 0,
4514 squareSize, squareSize, x, y, 1);
4517 XCopyPlane(xDisplay, *pieceToSolid(piece),
4518 dest, (int) piece < (int) BlackPawn
4519 ? wdPieceGC : bdPieceGC, 0, 0,
4520 squareSize, squareSize, x, y, 1);
4522 case 2: /* neutral */
4524 XCopyPlane(xDisplay, *pieceToSolid(piece),
4525 dest, (int) piece < (int) BlackPawn
4526 ? wjPieceGC : bjPieceGC, 0, 0,
4527 squareSize, squareSize, x, y, 1);
4532 static void colorDrawPieceImage(piece, square_color, x, y, dest)
4534 int square_color, x, y;
4539 switch (square_color) {
4541 case 2: /* neutral */
4543 if ((int)piece < (int) BlackPawn) {
4551 if ((int)piece < (int) BlackPawn) {
4559 XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
4560 dest, wlPieceGC, 0, 0,
4561 squareSize, squareSize, x, y);
4564 typedef void (*DrawFunc)();
4566 DrawFunc ChooseDrawFunc()
4568 if (appData.monoMode) {
4569 if (DefaultDepth(xDisplay, xScreen) == 1) {
4570 return monoDrawPiece_1bit;
4572 return monoDrawPiece;
4576 return colorDrawPieceImage;
4578 return colorDrawPiece;
4582 /* [HR] determine square color depending on chess variant. */
4583 static int SquareColor(row, column)
4588 if (gameInfo.variant == VariantXiangqi) {
4589 if (column >= 3 && column <= 5 && row >= 0 && row <= 2) {
4591 } else if (column >= 3 && column <= 5 && row >= 7 && row <= 9) {
4593 } else if (row <= 4) {
4599 square_color = ((column + row) % 2) == 1;
4602 /* [hgm] holdings: next line makes all holdings squares light */
4603 if(column < BOARD_LEFT || column >= BOARD_RGHT) square_color = 1;
4605 return square_color;
4608 void DrawSquare(row, column, piece, do_flash)
4609 int row, column, do_flash;
4612 int square_color, x, y, direction, font_ascent, font_descent;
4615 XCharStruct overall;
4619 if(gameInfo.variant == VariantShogi) { // [HGM] shogi: in shogi Q is used for Lance
4620 if(piece == WhiteQueen) piece = WhiteLance; else
4621 if(piece == BlackQueen) piece = BlackLance;
4624 else if(gameInfo.variant == VariantGothic) { // [HGM] shogi: in Gothic Chancelor has alternative look
4625 if(piece == WhiteMarshall) piece = WhiteSilver; else
4626 if(piece == BlackMarshall) piece = BlackSilver;
4630 /* Calculate delay in milliseconds (2-delays per complete flash) */
4631 flash_delay = 500 / appData.flashRate;
4634 x = lineGap + ((BOARD_WIDTH-1)-column) *
4635 (squareSize + lineGap);
4636 y = lineGap + row * (squareSize + lineGap);
4638 x = lineGap + column * (squareSize + lineGap);
4639 y = lineGap + ((BOARD_HEIGHT-1)-row) *
4640 (squareSize + lineGap);
4643 square_color = SquareColor(row, column);
4645 if ( // [HGM] holdings: blank out area between board and holdings
4646 column == BOARD_LEFT-1 || column == BOARD_RGHT
4647 || (column == BOARD_LEFT-2 && row < BOARD_HEIGHT-gameInfo.holdingsSize)
4648 || (column == BOARD_RGHT+1 && row >= gameInfo.holdingsSize) ) {
4649 BlankSquare(x, y, 2, EmptySquare, xBoardWindow);
4651 // [HGM] print piece counts next to holdings
4652 string[1] = NULLCHAR;
4653 if (column == (flipView ? BOARD_LEFT-1 : BOARD_RGHT) && piece > 1 ) {
4654 string[0] = '0' + piece;
4655 XTextExtents(countFontStruct, string, 1, &direction,
4656 &font_ascent, &font_descent, &overall);
4657 if (appData.monoMode) {
4658 XDrawImageString(xDisplay, xBoardWindow, countGC,
4659 x + squareSize - overall.width - 2,
4660 y + font_ascent + 1, string, 1);
4662 XDrawString(xDisplay, xBoardWindow, countGC,
4663 x + squareSize - overall.width - 2,
4664 y + font_ascent + 1, string, 1);
4667 if (column == (flipView ? BOARD_RGHT : BOARD_LEFT-1) && piece > 1) {
4668 string[0] = '0' + piece;
4669 XTextExtents(countFontStruct, string, 1, &direction,
4670 &font_ascent, &font_descent, &overall);
4671 if (appData.monoMode) {
4672 XDrawImageString(xDisplay, xBoardWindow, countGC,
4673 x + 2, y + font_ascent + 1, string, 1);
4675 XDrawString(xDisplay, xBoardWindow, countGC,
4676 x + 2, y + font_ascent + 1, string, 1);
4680 if (piece == EmptySquare || appData.blindfold) {
4681 BlankSquare(x, y, square_color, piece, xBoardWindow);
4683 drawfunc = ChooseDrawFunc();
4684 if (do_flash && appData.flashCount > 0) {
4685 for (i=0; i<appData.flashCount; ++i) {
4687 drawfunc(piece, square_color, x, y, xBoardWindow);
4688 XSync(xDisplay, False);
4689 do_flash_delay(flash_delay);
4691 BlankSquare(x, y, square_color, piece, xBoardWindow);
4692 XSync(xDisplay, False);
4693 do_flash_delay(flash_delay);
4696 drawfunc(piece, square_color, x, y, xBoardWindow);
4700 string[1] = NULLCHAR;
4701 if (appData.showCoords && row == (flipView ? BOARD_HEIGHT-1 : 0)
4702 && column >= BOARD_LEFT && column < BOARD_RGHT) {
4703 string[0] = 'a' + column - BOARD_LEFT;
4704 XTextExtents(coordFontStruct, string, 1, &direction,
4705 &font_ascent, &font_descent, &overall);
4706 if (appData.monoMode) {
4707 XDrawImageString(xDisplay, xBoardWindow, coordGC,
4708 x + squareSize - overall.width - 2,
4709 y + squareSize - font_descent - 1, string, 1);
4711 XDrawString(xDisplay, xBoardWindow, coordGC,
4712 x + squareSize - overall.width - 2,
4713 y + squareSize - font_descent - 1, string, 1);
4716 if (appData.showCoords && column == (flipView ? BOARD_RGHT-1 : BOARD_LEFT)) {
4717 string[0] = ONE + row;
4718 XTextExtents(coordFontStruct, string, 1, &direction,
4719 &font_ascent, &font_descent, &overall);
4720 if (appData.monoMode) {
4721 XDrawImageString(xDisplay, xBoardWindow, coordGC,
4722 x + 2, y + font_ascent + 1, string, 1);
4724 XDrawString(xDisplay, xBoardWindow, coordGC,
4725 x + 2, y + font_ascent + 1, string, 1);
4731 /* Why is this needed on some versions of X? */
4732 void EventProc(widget, unused, event)
4737 if (!XtIsRealized(widget))
4740 switch (event->type) {
4742 if (event->xexpose.count > 0) return; /* no clipping is done */
4743 XDrawPosition(widget, True, NULL);
4751 void DrawPosition(fullRedraw, board)
4752 /*Boolean*/int fullRedraw;
4755 XDrawPosition(boardWidget, fullRedraw, board);
4758 /* Returns 1 if there are "too many" differences between b1 and b2
4759 (i.e. more than 1 move was made) */
4760 static int too_many_diffs(b1, b2)
4766 for (i=0; i<BOARD_HEIGHT; ++i) {
4767 for (j=0; j<BOARD_WIDTH; ++j) {
4768 if (b1[i][j] != b2[i][j]) {
4769 if (++c > 4) /* Castling causes 4 diffs */
4778 /* Matrix describing castling maneuvers */
4779 /* Row, ColRookFrom, ColKingFrom, ColRookTo, ColKingTo */
4780 static int castling_matrix[4][5] = {
4781 { 0, 0, 4, 3, 2 }, /* 0-0-0, white */
4782 { 0, 7, 4, 5, 6 }, /* 0-0, white */
4783 { 7, 0, 4, 3, 2 }, /* 0-0-0, black */
4784 { 7, 7, 4, 5, 6 } /* 0-0, black */
4787 /* Checks whether castling occurred. If it did, *rrow and *rcol
4788 are set to the destination (row,col) of the rook that moved.
4790 Returns 1 if castling occurred, 0 if not.
4792 Note: Only handles a max of 1 castling move, so be sure
4793 to call too_many_diffs() first.
4795 static int check_castle_draw(newb, oldb, rrow, rcol)
4802 /* For each type of castling... */
4803 for (i=0; i<4; ++i) {
4804 r = castling_matrix[i];
4806 /* Check the 4 squares involved in the castling move */
4808 for (j=1; j<=4; ++j) {
4809 if (newb[r[0]][r[j]] == oldb[r[0]][r[j]]) {
4816 /* All 4 changed, so it must be a castling move */
4825 static int damage[BOARD_SIZE][BOARD_SIZE];
4828 * event handler for redrawing the board
4830 void XDrawPosition(w, repaint, board)
4832 /*Boolean*/int repaint;
4836 static int lastFlipView = 0;
4837 static int lastBoardValid = 0;
4838 static Board lastBoard;
4842 if (board == NULL) {
4843 if (!lastBoardValid) return;
4846 if (!lastBoardValid || lastFlipView != flipView) {
4847 XtSetArg(args[0], XtNleftBitmap, (flipView ? xMarkPixmap : None));
4848 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flip View"),
4853 * It would be simpler to clear the window with XClearWindow()
4854 * but this causes a very distracting flicker.
4857 if (!repaint && lastBoardValid && lastFlipView == flipView) {
4859 /* If too much changes (begin observing new game, etc.), don't
4861 do_flash = too_many_diffs(board, lastBoard) ? 0 : 1;
4863 /* Special check for castling so we don't flash both the king
4864 and the rook (just flash the king). */
4866 if (check_castle_draw(board, lastBoard, &rrow, &rcol)) {
4867 /* Draw rook with NO flashing. King will be drawn flashing later */
4868 DrawSquare(rrow, rcol, board[rrow][rcol], 0);
4869 lastBoard[rrow][rcol] = board[rrow][rcol];
4873 /* First pass -- Draw (newly) empty squares and repair damage.
4874 This prevents you from having a piece show up twice while it
4875 is flashing on its new square */
4876 for (i = 0; i < BOARD_HEIGHT; i++)
4877 for (j = 0; j < BOARD_WIDTH; j++)
4878 if ((board[i][j] != lastBoard[i][j] && board[i][j] == EmptySquare)
4880 DrawSquare(i, j, board[i][j], 0);
4881 damage[i][j] = False;
4884 /* Second pass -- Draw piece(s) in new position and flash them */
4885 for (i = 0; i < BOARD_HEIGHT; i++)
4886 for (j = 0; j < BOARD_WIDTH; j++)
4887 if (board[i][j] != lastBoard[i][j]) {
4888 DrawSquare(i, j, board[i][j], do_flash);
4892 XDrawSegments(xDisplay, xBoardWindow, lineGC,
4893 gridSegments, BOARD_HEIGHT + BOARD_WIDTH + 2);
4895 for (i = 0; i < BOARD_HEIGHT; i++)
4896 for (j = 0; j < BOARD_WIDTH; j++) {
4897 DrawSquare(i, j, board[i][j], 0);
4898 damage[i][j] = False;
4902 CopyBoard(lastBoard, board);
4904 lastFlipView = flipView;
4906 /* Draw highlights */
4907 if (pm1X >= 0 && pm1Y >= 0) {
4908 drawHighlight(pm1X, pm1Y, prelineGC);
4910 if (pm2X >= 0 && pm2Y >= 0) {
4911 drawHighlight(pm2X, pm2Y, prelineGC);
4913 if (hi1X >= 0 && hi1Y >= 0) {
4914 drawHighlight(hi1X, hi1Y, highlineGC);
4916 if (hi2X >= 0 && hi2Y >= 0) {
4917 drawHighlight(hi2X, hi2Y, highlineGC);
4920 /* If piece being dragged around board, must redraw that too */
4923 XSync(xDisplay, False);
4928 * event handler for redrawing the board
4930 void DrawPositionProc(w, event, prms, nprms)
4936 XDrawPosition(w, True, NULL);
4941 * event handler for parsing user moves
4943 // [HGM] This routine will need quite some reworking. Although the backend still supports the old
4944 // way of doing things, by calling UserMoveEvent() to test the legality of the move and then perform
4945 // it at the end, and doing all kind of preliminary tests here (e.g. to weed out self-captures), it
4946 // should be made to use the new way, of calling UserMoveTest early to determine the legality of the
4947 // move, (which will weed out the illegal selfcaptures and moves into the holdings, and flag promotions),
4948 // and at the end FinishMove() to perform the move after optional promotion popups.
4949 // For now I patched it to allow self-capture with King, and suppress clicks between board and holdings.
4950 void HandleUserMove(w, event, prms, nprms)
4957 Boolean saveAnimate;
4958 static int second = 0;
4960 if (w != boardWidget || errorExitStatus != -1) return;
4962 if (event->type == ButtonPress) ErrorPopDown();
4965 if (event->type == ButtonPress) {
4966 XtPopdown(promotionShell);
4967 XtDestroyWidget(promotionShell);
4968 promotionUp = False;
4976 x = EventToSquare(event->xbutton.x, BOARD_WIDTH);
4977 y = EventToSquare(event->xbutton.y, BOARD_HEIGHT);
4978 if (!flipView && y >= 0) {
4979 y = BOARD_HEIGHT - 1 - y;
4981 if (flipView && x >= 0) {
4982 x = BOARD_WIDTH - 1 - x;
4985 /* [HGM] holdings: next 5 lines: ignore all clicks between board and holdings */
4986 if(event->type == ButtonPress
4987 && ( x == BOARD_LEFT-1 || x == BOARD_RGHT
4988 || x == BOARD_LEFT-2 && y < BOARD_HEIGHT-gameInfo.holdingsSize
4989 || x == BOARD_RGHT+1 && y >= gameInfo.holdingsSize) )
4993 if (event->type == ButtonPress) {
4995 if (OKToStartUserMove(x, y)) {
4999 DragPieceBegin(event->xbutton.x, event->xbutton.y);
5000 if (appData.highlightDragging) {
5001 SetHighlights(x, y, -1, -1);
5009 if (event->type == ButtonPress && gameMode != EditPosition &&
5014 /* Check if clicking again on the same color piece */
5015 fromP = boards[currentMove][fromY][fromX];
5016 toP = boards[currentMove][y][x];
5017 if ((WhitePawn <= fromP && fromP < WhiteKing && // [HGM] this test should go, as UserMoveTest now does it.
5018 WhitePawn <= toP && toP <= WhiteKing) || // For now I made it less critical by exempting King
5019 (BlackPawn <= fromP && fromP < BlackKing && // moves, to not interfere with FRC castlings.
5020 BlackPawn <= toP && toP <= BlackKing)) {
5021 /* Clicked again on same color piece -- changed his mind */
5022 second = (x == fromX && y == fromY);
5023 if (appData.highlightDragging) {
5024 SetHighlights(x, y, -1, -1);
5028 if (OKToStartUserMove(x, y)) {
5031 DragPieceBegin(event->xbutton.x, event->xbutton.y);
5037 if (event->type == ButtonRelease && x == fromX && y == fromY) {
5038 DragPieceEnd(event->xbutton.x, event->xbutton.y);
5039 if (appData.animateDragging) {
5040 /* Undo animation damage if any */
5041 DrawPosition(FALSE, NULL);
5044 /* Second up/down in same square; just abort move */
5049 ClearPremoveHighlights();
5051 /* First upclick in same square; start click-click mode */
5052 SetHighlights(x, y, -1, -1);
5057 /* Completed move */
5060 saveAnimate = appData.animate;
5061 if (event->type == ButtonPress) {
5062 /* Finish clickclick move */
5063 if (appData.animate || appData.highlightLastMove) {
5064 SetHighlights(fromX, fromY, toX, toY);
5069 /* Finish drag move */
5070 if (appData.highlightLastMove) {
5071 SetHighlights(fromX, fromY, toX, toY);
5075 DragPieceEnd(event->xbutton.x, event->xbutton.y);
5076 /* Don't animate move and drag both */
5077 appData.animate = FALSE;
5079 if (IsPromotion(fromX, fromY, toX, toY)) {
5080 if (appData.alwaysPromoteToQueen) {
5081 UserMoveEvent(fromX, fromY, toX, toY, 'q');
5082 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
5083 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
5086 SetHighlights(fromX, fromY, toX, toY);
5090 UserMoveEvent(fromX, fromY, toX, toY, NULLCHAR);
5091 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
5092 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
5095 appData.animate = saveAnimate;
5096 if (appData.animate || appData.animateDragging) {
5097 /* Undo animation damage if needed */
5098 DrawPosition(FALSE, NULL);
5102 void AnimateUserMove (Widget w, XEvent * event,
5103 String * params, Cardinal * nParams)
5105 DragPieceMove(event->xmotion.x, event->xmotion.y);
5108 Widget CommentCreate(name, text, mutable, callback, lines)
5110 int /*Boolean*/ mutable;
5111 XtCallbackProc callback;
5115 Widget shell, layout, form, edit, b_ok, b_cancel, b_clear, b_close, b_edit;
5120 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5121 XtGetValues(boardWidget, args, j);
5124 XtSetArg(args[j], XtNresizable, True); j++;
5127 XtCreatePopupShell(name, topLevelShellWidgetClass,
5128 shellWidget, args, j);
5131 XtCreatePopupShell(name, transientShellWidgetClass,
5132 shellWidget, args, j);
5135 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
5136 layoutArgs, XtNumber(layoutArgs));
5138 XtCreateManagedWidget("form", formWidgetClass, layout,
5139 formArgs, XtNumber(formArgs));
5143 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
5144 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
5146 XtSetArg(args[j], XtNstring, text); j++;
5147 XtSetArg(args[j], XtNtop, XtChainTop); j++;
5148 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5149 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5150 XtSetArg(args[j], XtNright, XtChainRight); j++;
5151 XtSetArg(args[j], XtNresizable, True); j++;
5152 XtSetArg(args[j], XtNwidth, bw_width); j++; /*force wider than buttons*/
5154 XtSetArg(args[j], XtNscrollVertical, XawtextScrollWhenNeeded); j++;
5156 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
5157 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
5159 XtSetArg(args[j], XtNautoFill, True); j++;
5160 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
5162 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
5166 XtSetArg(args[j], XtNfromVert, edit); j++;
5167 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5168 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5169 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5170 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5172 XtCreateManagedWidget(_("ok"), commandWidgetClass, form, args, j);
5173 XtAddCallback(b_ok, XtNcallback, callback, (XtPointer) 0);
5176 XtSetArg(args[j], XtNfromVert, edit); j++;
5177 XtSetArg(args[j], XtNfromHoriz, b_ok); j++;
5178 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5179 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5180 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5181 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5183 XtCreateManagedWidget(_("cancel"), commandWidgetClass, form, args, j);
5184 XtAddCallback(b_cancel, XtNcallback, callback, (XtPointer) 0);
5187 XtSetArg(args[j], XtNfromVert, edit); j++;
5188 XtSetArg(args[j], XtNfromHoriz, b_cancel); j++;
5189 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5190 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5191 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5192 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5194 XtCreateManagedWidget(_("clear"), commandWidgetClass, form, args, j);
5195 XtAddCallback(b_clear, XtNcallback, callback, (XtPointer) 0);
5198 XtSetArg(args[j], XtNfromVert, edit); j++;
5199 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5200 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5201 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5202 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5204 XtCreateManagedWidget(_("close"), commandWidgetClass, form, args, j);
5205 XtAddCallback(b_close, XtNcallback, callback, (XtPointer) 0);
5208 XtSetArg(args[j], XtNfromVert, edit); j++;
5209 XtSetArg(args[j], XtNfromHoriz, b_close); j++;
5210 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5211 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5212 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5213 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5215 XtCreateManagedWidget(_("edit"), commandWidgetClass, form, args, j);
5216 XtAddCallback(b_edit, XtNcallback, callback, (XtPointer) 0);
5219 XtRealizeWidget(shell);
5221 if (commentX == -1) {
5224 Dimension pw_height;
5225 Dimension ew_height;
5228 XtSetArg(args[j], XtNheight, &ew_height); j++;
5229 XtGetValues(edit, args, j);
5232 XtSetArg(args[j], XtNheight, &pw_height); j++;
5233 XtGetValues(shell, args, j);
5234 commentH = pw_height + (lines - 1) * ew_height;
5235 commentW = bw_width - 16;
5237 XSync(xDisplay, False);
5239 /* This code seems to tickle an X bug if it is executed too soon
5240 after xboard starts up. The coordinates get transformed as if
5241 the main window was positioned at (0, 0).
5243 XtTranslateCoords(shellWidget,
5244 (bw_width - commentW) / 2, 0 - commentH / 2,
5245 &commentX, &commentY);
5247 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
5248 RootWindowOfScreen(XtScreen(shellWidget)),
5249 (bw_width - commentW) / 2, 0 - commentH / 2,
5254 if (commentY < 0) commentY = 0; /*avoid positioning top offscreen*/
5257 XtSetArg(args[j], XtNheight, commentH); j++;
5258 XtSetArg(args[j], XtNwidth, commentW); j++;
5259 XtSetArg(args[j], XtNx, commentX); j++;
5260 XtSetArg(args[j], XtNy, commentY); j++;
5261 XtSetValues(shell, args, j);
5262 XtSetKeyboardFocus(shell, edit);
5267 /* Used for analysis window and ICS input window */
5268 Widget MiscCreate(name, text, mutable, callback, lines)
5270 int /*Boolean*/ mutable;
5271 XtCallbackProc callback;
5275 Widget shell, layout, form, edit;
5277 Dimension bw_width, pw_height, ew_height, w, h;
5283 XtSetArg(args[j], XtNresizable, True); j++;
5286 XtCreatePopupShell(name, topLevelShellWidgetClass,
5287 shellWidget, args, j);
5290 XtCreatePopupShell(name, transientShellWidgetClass,
5291 shellWidget, args, j);
5294 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
5295 layoutArgs, XtNumber(layoutArgs));
5297 XtCreateManagedWidget("form", formWidgetClass, layout,
5298 formArgs, XtNumber(formArgs));
5302 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
5303 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
5305 XtSetArg(args[j], XtNstring, text); j++;
5306 XtSetArg(args[j], XtNtop, XtChainTop); j++;
5307 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5308 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5309 XtSetArg(args[j], XtNright, XtChainRight); j++;
5310 XtSetArg(args[j], XtNresizable, True); j++;
5312 XtSetArg(args[j], XtNscrollVertical, XawtextScrollWhenNeeded); j++;
5314 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
5315 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
5317 XtSetArg(args[j], XtNautoFill, True); j++;
5318 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
5320 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
5322 XtRealizeWidget(shell);
5325 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5326 XtGetValues(boardWidget, args, j);
5329 XtSetArg(args[j], XtNheight, &ew_height); j++;
5330 XtGetValues(edit, args, j);
5333 XtSetArg(args[j], XtNheight, &pw_height); j++;
5334 XtGetValues(shell, args, j);
5335 h = pw_height + (lines - 1) * ew_height;
5338 XSync(xDisplay, False);
5340 /* This code seems to tickle an X bug if it is executed too soon
5341 after xboard starts up. The coordinates get transformed as if
5342 the main window was positioned at (0, 0).
5344 XtTranslateCoords(shellWidget, (bw_width - w) / 2, 0 - h / 2, &x, &y);
5346 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
5347 RootWindowOfScreen(XtScreen(shellWidget)),
5348 (bw_width - w) / 2, 0 - h / 2, &xx, &yy, &junk);
5352 if (y < 0) y = 0; /*avoid positioning top offscreen*/
5355 XtSetArg(args[j], XtNheight, h); j++;
5356 XtSetArg(args[j], XtNwidth, w); j++;
5357 XtSetArg(args[j], XtNx, x); j++;
5358 XtSetArg(args[j], XtNy, y); j++;
5359 XtSetValues(shell, args, j);
5365 static int savedIndex; /* gross that this is global */
5367 void EditCommentPopUp(index, title, text)
5376 if (text == NULL) text = "";
5378 if (editShell == NULL) {
5380 CommentCreate(title, text, True, EditCommentCallback, 4);
5381 XtRealizeWidget(editShell);
5382 CatchDeleteWindow(editShell, "EditCommentPopDown");
5384 edit = XtNameToWidget(editShell, "*form.text");
5386 XtSetArg(args[j], XtNstring, text); j++;
5387 XtSetValues(edit, args, j);
5389 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5390 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5391 XtSetValues(editShell, args, j);
5394 XtPopup(editShell, XtGrabNone);
5398 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
5399 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
5403 void EditCommentCallback(w, client_data, call_data)
5405 XtPointer client_data, call_data;
5413 XtSetArg(args[j], XtNlabel, &name); j++;
5414 XtGetValues(w, args, j);
5416 if (strcmp(name, _("ok")) == 0) {
5417 edit = XtNameToWidget(editShell, "*form.text");
5419 XtSetArg(args[j], XtNstring, &val); j++;
5420 XtGetValues(edit, args, j);
5421 ReplaceComment(savedIndex, val);
5422 EditCommentPopDown();
5423 } else if (strcmp(name, _("cancel")) == 0) {
5424 EditCommentPopDown();
5425 } else if (strcmp(name, _("clear")) == 0) {
5426 edit = XtNameToWidget(editShell, "*form.text");
5427 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
5428 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
5432 void EditCommentPopDown()
5437 if (!editUp) return;
5439 XtSetArg(args[j], XtNx, &commentX); j++;
5440 XtSetArg(args[j], XtNy, &commentY); j++;
5441 XtSetArg(args[j], XtNheight, &commentH); j++;
5442 XtSetArg(args[j], XtNwidth, &commentW); j++;
5443 XtGetValues(editShell, args, j);
5444 XtPopdown(editShell);
5447 XtSetArg(args[j], XtNleftBitmap, None); j++;
5448 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
5452 void ICSInputBoxPopUp()
5457 char *title = _("ICS Input");
5460 if (ICSInputShell == NULL) {
5461 ICSInputShell = MiscCreate(title, "", True, NULL, 1);
5462 tr = XtParseTranslationTable(ICSInputTranslations);
5463 edit = XtNameToWidget(ICSInputShell, "*form.text");
5464 XtOverrideTranslations(edit, tr);
5465 XtRealizeWidget(ICSInputShell);
5466 CatchDeleteWindow(ICSInputShell, "ICSInputBoxPopDown");
5469 edit = XtNameToWidget(ICSInputShell, "*form.text");
5471 XtSetArg(args[j], XtNstring, ""); j++;
5472 XtSetValues(edit, args, j);
5474 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5475 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5476 XtSetValues(ICSInputShell, args, j);
5479 XtPopup(ICSInputShell, XtGrabNone);
5480 XtSetKeyboardFocus(ICSInputShell, edit);
5482 ICSInputBoxUp = True;
5484 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
5485 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
5489 void ICSInputSendText()
5496 edit = XtNameToWidget(ICSInputShell, "*form.text");
5498 XtSetArg(args[j], XtNstring, &val); j++;
5499 XtGetValues(edit, args, j);
5500 SendMultiLineToICS(val);
5501 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
5502 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
5505 void ICSInputBoxPopDown()
5510 if (!ICSInputBoxUp) return;
5512 XtPopdown(ICSInputShell);
5513 ICSInputBoxUp = False;
5515 XtSetArg(args[j], XtNleftBitmap, None); j++;
5516 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
5520 void CommentPopUp(title, text)
5527 if (commentShell == NULL) {
5529 CommentCreate(title, text, False, CommentCallback, 4);
5530 XtRealizeWidget(commentShell);
5531 CatchDeleteWindow(commentShell, "CommentPopDown");
5533 edit = XtNameToWidget(commentShell, "*form.text");
5535 XtSetArg(args[j], XtNstring, text); j++;
5536 XtSetValues(edit, args, j);
5538 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5539 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5540 XtSetValues(commentShell, args, j);
5543 XtPopup(commentShell, XtGrabNone);
5544 XSync(xDisplay, False);
5549 void AnalysisPopUp(title, text)
5556 if (analysisShell == NULL) {
5557 analysisShell = MiscCreate(title, text, False, NULL, 4);
5558 XtRealizeWidget(analysisShell);
5559 CatchDeleteWindow(analysisShell, "AnalysisPopDown");
5562 edit = XtNameToWidget(analysisShell, "*form.text");
5564 XtSetArg(args[j], XtNstring, text); j++;
5565 XtSetValues(edit, args, j);
5567 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5568 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5569 XtSetValues(analysisShell, args, j);
5573 XtPopup(analysisShell, XtGrabNone);
5575 XSync(xDisplay, False);
5580 void CommentCallback(w, client_data, call_data)
5582 XtPointer client_data, call_data;
5589 XtSetArg(args[j], XtNlabel, &name); j++;
5590 XtGetValues(w, args, j);
5592 if (strcmp(name, _("close")) == 0) {
5594 } else if (strcmp(name, _("edit")) == 0) {
5601 void CommentPopDown()
5606 if (!commentUp) return;
5608 XtSetArg(args[j], XtNx, &commentX); j++;
5609 XtSetArg(args[j], XtNy, &commentY); j++;
5610 XtSetArg(args[j], XtNwidth, &commentW); j++;
5611 XtSetArg(args[j], XtNheight, &commentH); j++;
5612 XtGetValues(commentShell, args, j);
5613 XtPopdown(commentShell);
5614 XSync(xDisplay, False);
5618 void AnalysisPopDown()
5620 if (!analysisUp) return;
5621 XtPopdown(analysisShell);
5622 XSync(xDisplay, False);
5624 if (appData.icsEngineAnalyze) ExitAnalyzeMode(); /* [DM] icsEngineAnalyze */
5628 void FileNamePopUp(label, def, proc, openMode)
5635 Widget popup, layout, dialog, edit;
5641 fileProc = proc; /* I can't see a way not */
5642 fileOpenMode = openMode; /* to use globals here */
5645 XtSetArg(args[i], XtNresizable, True); i++;
5646 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
5647 XtSetArg(args[i], XtNtitle, XtNewString(_("File name prompt"))); i++;
5648 fileNameShell = popup =
5649 XtCreatePopupShell("File name prompt", transientShellWidgetClass,
5650 shellWidget, args, i);
5653 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
5654 layoutArgs, XtNumber(layoutArgs));
5657 XtSetArg(args[i], XtNlabel, label); i++;
5658 XtSetArg(args[i], XtNvalue, def); i++;
5659 XtSetArg(args[i], XtNborderWidth, 0); i++;
5660 dialog = XtCreateManagedWidget("fileName", dialogWidgetClass,
5663 XawDialogAddButton(dialog, _("ok"), FileNameCallback, (XtPointer) dialog);
5664 XawDialogAddButton(dialog, _("cancel"), FileNameCallback,
5665 (XtPointer) dialog);
5667 XtRealizeWidget(popup);
5668 CatchDeleteWindow(popup, "FileNamePopDown");
5670 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
5671 &x, &y, &win_x, &win_y, &mask);
5673 XtSetArg(args[0], XtNx, x - 10);
5674 XtSetArg(args[1], XtNy, y - 30);
5675 XtSetValues(popup, args, 2);
5677 XtPopup(popup, XtGrabExclusive);
5680 edit = XtNameToWidget(dialog, "*value");
5681 XtSetKeyboardFocus(popup, edit);
5684 void FileNamePopDown()
5686 if (!filenameUp) return;
5687 XtPopdown(fileNameShell);
5688 XtDestroyWidget(fileNameShell);
5693 void FileNameCallback(w, client_data, call_data)
5695 XtPointer client_data, call_data;
5700 XtSetArg(args[0], XtNlabel, &name);
5701 XtGetValues(w, args, 1);
5703 if (strcmp(name, _("cancel")) == 0) {
5708 FileNameAction(w, NULL, NULL, NULL);
5711 void FileNameAction(w, event, prms, nprms)
5723 name = XawDialogGetValueString(w = XtParent(w));
5725 if ((name != NULL) && (*name != NULLCHAR)) {
5727 XtPopdown(w = XtParent(XtParent(w)));
5731 p = strrchr(buf, ' ');
5738 fullname = ExpandPathName(buf);
5740 ErrorPopUp(_("Error"), _("Can't open file"), FALSE);
5743 f = fopen(fullname, fileOpenMode);
5745 DisplayError(_("Failed to open file"), errno);
5747 (void) (*fileProc)(f, index, buf);
5754 XtPopdown(w = XtParent(XtParent(w)));
5760 void PromotionPopUp()
5763 Widget dialog, layout;
5765 Dimension bw_width, pw_width;
5769 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5770 XtGetValues(boardWidget, args, j);
5773 XtSetArg(args[j], XtNresizable, True); j++;
5774 XtSetArg(args[j], XtNtitle, XtNewString(_("Promotion"))); j++;
5776 XtCreatePopupShell("Promotion", transientShellWidgetClass,
5777 shellWidget, args, j);
5779 XtCreateManagedWidget(layoutName, formWidgetClass, promotionShell,
5780 layoutArgs, XtNumber(layoutArgs));
5783 XtSetArg(args[j], XtNlabel, _("Promote pawn to what?")); j++;
5784 XtSetArg(args[j], XtNborderWidth, 0); j++;
5785 dialog = XtCreateManagedWidget("promotion", dialogWidgetClass,
5788 XawDialogAddButton(dialog, _("Queen"), PromotionCallback,
5789 (XtPointer) dialog);
5790 XawDialogAddButton(dialog, _("Rook"), PromotionCallback,
5791 (XtPointer) dialog);
5792 XawDialogAddButton(dialog, _("Bishop"), PromotionCallback,
5793 (XtPointer) dialog);
5794 XawDialogAddButton(dialog, _("Knight"), PromotionCallback,
5795 (XtPointer) dialog);
5796 if (!appData.testLegality || gameInfo.variant == VariantSuicide ||
5797 gameInfo.variant == VariantGiveaway) {
5798 XawDialogAddButton(dialog, _("King"), PromotionCallback,
5799 (XtPointer) dialog);
5801 XawDialogAddButton(dialog, _("cancel"), PromotionCallback,
5802 (XtPointer) dialog);
5804 XtRealizeWidget(promotionShell);
5805 CatchDeleteWindow(promotionShell, "PromotionPopDown");
5808 XtSetArg(args[j], XtNwidth, &pw_width); j++;
5809 XtGetValues(promotionShell, args, j);
5811 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
5812 lineGap + squareSize/3 +
5813 ((toY == BOARD_HEIGHT-1) ^ (flipView) ?
5814 0 : 6*(squareSize + lineGap)), &x, &y);
5817 XtSetArg(args[j], XtNx, x); j++;
5818 XtSetArg(args[j], XtNy, y); j++;
5819 XtSetValues(promotionShell, args, j);
5821 XtPopup(promotionShell, XtGrabNone);
5826 void PromotionPopDown()
5828 if (!promotionUp) return;
5829 XtPopdown(promotionShell);
5830 XtDestroyWidget(promotionShell);
5831 promotionUp = False;
5834 void PromotionCallback(w, client_data, call_data)
5836 XtPointer client_data, call_data;
5842 XtSetArg(args[0], XtNlabel, &name);
5843 XtGetValues(w, args, 1);
5847 if (fromX == -1) return;
5849 if (strcmp(name, _("cancel")) == 0) {
5853 } else if (strcmp(name, _("Knight")) == 0) {
5856 promoChar = ToLower(name[0]);
5859 UserMoveEvent(fromX, fromY, toX, toY, promoChar);
5861 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
5862 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
5867 void ErrorCallback(w, client_data, call_data)
5869 XtPointer client_data, call_data;
5872 XtPopdown(w = XtParent(XtParent(XtParent(w))));
5874 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
5880 if (!errorUp) return;
5882 XtPopdown(errorShell);
5883 XtDestroyWidget(errorShell);
5884 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
5887 void ErrorPopUp(title, label, modal)
5888 char *title, *label;
5892 Widget dialog, layout;
5896 Dimension bw_width, pw_width;
5897 Dimension pw_height;
5901 XtSetArg(args[i], XtNresizable, True); i++;
5902 XtSetArg(args[i], XtNtitle, title); i++;
5904 XtCreatePopupShell("errorpopup", transientShellWidgetClass,
5905 shellWidget, args, i);
5907 XtCreateManagedWidget(layoutName, formWidgetClass, errorShell,
5908 layoutArgs, XtNumber(layoutArgs));
5911 XtSetArg(args[i], XtNlabel, label); i++;
5912 XtSetArg(args[i], XtNborderWidth, 0); i++;
5913 dialog = XtCreateManagedWidget("dialog", dialogWidgetClass,
5916 XawDialogAddButton(dialog, _("ok"), ErrorCallback, (XtPointer) dialog);
5918 XtRealizeWidget(errorShell);
5919 CatchDeleteWindow(errorShell, "ErrorPopDown");
5922 XtSetArg(args[i], XtNwidth, &bw_width); i++;
5923 XtGetValues(boardWidget, args, i);
5925 XtSetArg(args[i], XtNwidth, &pw_width); i++;
5926 XtSetArg(args[i], XtNheight, &pw_height); i++;
5927 XtGetValues(errorShell, args, i);
5930 /* This code seems to tickle an X bug if it is executed too soon
5931 after xboard starts up. The coordinates get transformed as if
5932 the main window was positioned at (0, 0).
5934 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
5935 0 - pw_height + squareSize / 3, &x, &y);
5937 XTranslateCoordinates(xDisplay, XtWindow(boardWidget),
5938 RootWindowOfScreen(XtScreen(boardWidget)),
5939 (bw_width - pw_width) / 2,
5940 0 - pw_height + squareSize / 3, &xx, &yy, &junk);
5944 if (y < 0) y = 0; /*avoid positioning top offscreen*/
5947 XtSetArg(args[i], XtNx, x); i++;
5948 XtSetArg(args[i], XtNy, y); i++;
5949 XtSetValues(errorShell, args, i);
5952 XtPopup(errorShell, modal ? XtGrabExclusive : XtGrabNone);
5955 /* Disable all user input other than deleting the window */
5956 static int frozen = 0;
5960 /* Grab by a widget that doesn't accept input */
5961 XtAddGrab(messageWidget, TRUE, FALSE);
5965 /* Undo a FreezeUI */
5968 if (!frozen) return;
5969 XtRemoveGrab(messageWidget);
5973 char *ModeToWidgetName(mode)
5977 case BeginningOfGame:
5978 if (appData.icsActive)
5979 return "menuMode.ICS Client";
5980 else if (appData.noChessProgram ||
5981 *appData.cmailGameName != NULLCHAR)
5982 return "menuMode.Edit Game";
5984 return "menuMode.Machine Black";
5985 case MachinePlaysBlack:
5986 return "menuMode.Machine Black";
5987 case MachinePlaysWhite:
5988 return "menuMode.Machine White";
5990 return "menuMode.Analysis Mode";
5992 return "menuMode.Analyze File";
5993 case TwoMachinesPlay:
5994 return "menuMode.Two Machines";
5996 return "menuMode.Edit Game";
5997 case PlayFromGameFile:
5998 return "menuFile.Load Game";
6000 return "menuMode.Edit Position";
6002 return "menuMode.Training";
6003 case IcsPlayingWhite:
6004 case IcsPlayingBlack:
6008 return "menuMode.ICS Client";
6015 void ModeHighlight()
6018 static int oldPausing = FALSE;
6019 static GameMode oldmode = (GameMode) -1;
6022 if (!boardWidget || !XtIsRealized(boardWidget)) return;
6024 if (pausing != oldPausing) {
6025 oldPausing = pausing;
6027 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6029 XtSetArg(args[0], XtNleftBitmap, None);
6031 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Pause"),
6034 if (appData.showButtonBar) {
6037 XtSetArg(args[0], XtNbackground, buttonForegroundPixel);
6038 XtSetArg(args[1], XtNforeground, buttonBackgroundPixel);
6040 XtSetArg(args[0], XtNbackground, buttonBackgroundPixel);
6041 XtSetArg(args[1], XtNforeground, buttonForegroundPixel);
6044 /* Always toggle, don't set. Previous code messes up when
6045 invoked while the button is pressed, as releasing it
6046 toggles the state again. */
6049 XtSetArg(args[0], XtNbackground, &oldbg);
6050 XtSetArg(args[1], XtNforeground, &oldfg);
6051 XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON),
6053 XtSetArg(args[0], XtNbackground, oldfg);
6054 XtSetArg(args[1], XtNforeground, oldbg);
6057 XtSetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
6061 wname = ModeToWidgetName(oldmode);
6062 if (wname != NULL) {
6063 XtSetArg(args[0], XtNleftBitmap, None);
6064 XtSetValues(XtNameToWidget(menuBarWidget, wname), args, 1);
6066 wname = ModeToWidgetName(gameMode);
6067 if (wname != NULL) {
6068 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6069 XtSetValues(XtNameToWidget(menuBarWidget, wname), args, 1);
6073 /* Maybe all the enables should be handled here, not just this one */
6074 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Training"),
6075 gameMode == Training || gameMode == PlayFromGameFile);
6080 * Button/menu procedures
6082 void ResetProc(w, event, prms, nprms)
6092 int LoadGamePopUp(f, gameNumber, title)
6097 cmailMsgLoaded = FALSE;
6098 if (gameNumber == 0) {
6099 int error = GameListBuild(f);
6101 DisplayError(_("Cannot build game list"), error);
6102 } else if (!ListEmpty(&gameList) &&
6103 ((ListGame *) gameList.tailPred)->number > 1) {
6104 GameListPopUp(f, title);
6110 return LoadGame(f, gameNumber, title, FALSE);
6113 void LoadGameProc(w, event, prms, nprms)
6119 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
6122 FileNamePopUp(_("Load game file name?"), "", LoadGamePopUp, "rb");
6125 void LoadNextGameProc(w, event, prms, nprms)
6134 void LoadPrevGameProc(w, event, prms, nprms)
6143 void ReloadGameProc(w, event, prms, nprms)
6152 void LoadNextPositionProc(w, event, prms, nprms)
6161 void LoadPrevPositionProc(w, event, prms, nprms)
6170 void ReloadPositionProc(w, event, prms, nprms)
6179 void LoadPositionProc(w, event, prms, nprms)
6185 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
6188 FileNamePopUp(_("Load position file name?"), "", LoadPosition, "rb");
6191 void SaveGameProc(w, event, prms, nprms)
6197 FileNamePopUp(_("Save game file name?"),
6198 DefaultFileName(appData.oldSaveStyle ? "game" : "pgn"),
6202 void SavePositionProc(w, event, prms, nprms)
6208 FileNamePopUp(_("Save position file name?"),
6209 DefaultFileName(appData.oldSaveStyle ? "pos" : "fen"),
6213 void ReloadCmailMsgProc(w, event, prms, nprms)
6219 ReloadCmailMsgEvent(FALSE);
6222 void MailMoveProc(w, event, prms, nprms)
6231 /* this variable is shared between CopyPositionProc and SendPositionSelection */
6232 static char *selected_fen_position=NULL;
6235 SendPositionSelection(Widget w, Atom *selection, Atom *target,
6236 Atom *type_return, XtPointer *value_return,
6237 unsigned long *length_return, int *format_return)
6239 char *selection_tmp;
6241 if (!selected_fen_position) return False; /* should never happen */
6242 if (*target == XA_STRING){
6243 /* note: since no XtSelectionDoneProc was registered, Xt will
6244 * automatically call XtFree on the value returned. So have to
6245 * make a copy of it allocated with XtMalloc */
6246 selection_tmp= XtMalloc(strlen(selected_fen_position)+16);
6247 strcpy(selection_tmp, selected_fen_position);
6249 *value_return=selection_tmp;
6250 *length_return=strlen(selection_tmp);
6251 *type_return=XA_STRING;
6252 *format_return = 8; /* bits per byte */
6259 /* note: when called from menu all parameters are NULL, so no clue what the
6260 * Widget which was clicked on was, or what the click event was
6262 void CopyPositionProc(w, event, prms, nprms)
6270 if (selected_fen_position) free(selected_fen_position);
6271 selected_fen_position = (char *)PositionToFEN(currentMove,1);
6272 if (!selected_fen_position) return;
6273 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
6275 SendPositionSelection,
6276 NULL/* lose_ownership_proc */ ,
6277 NULL/* transfer_done_proc */);
6279 free(selected_fen_position);
6280 selected_fen_position=NULL;
6284 /* function called when the data to Paste is ready */
6286 PastePositionCB(Widget w, XtPointer client_data, Atom *selection,
6287 Atom *type, XtPointer value, unsigned long *len, int *format)
6290 if (value==NULL || *len==0) return; /* nothing had been selected to copy */
6291 fenstr[*len]='\0'; /* normally this string is terminated, but be safe */
6292 EditPositionPasteFEN(fenstr);
6296 /* called when Paste Position button is pressed,
6297 * all parameters will be NULL */
6298 void PastePositionProc(w, event, prms, nprms)
6304 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
6305 /* (XtSelectionCallbackProc) */ PastePositionCB,
6306 NULL, /* client_data passed to PastePositionCB */
6308 /* better to use the time field from the event that triggered the
6309 * call to this function, but that isn't trivial to get
6317 SendGameSelection(Widget w, Atom *selection, Atom *target,
6318 Atom *type_return, XtPointer *value_return,
6319 unsigned long *length_return, int *format_return)
6321 char *selection_tmp;
6323 if (*target == XA_STRING){
6324 FILE* f = fopen(gameCopyFilename, "r");
6327 if (f == NULL) return False;
6331 selection_tmp = XtMalloc(len + 1);
6332 count = fread(selection_tmp, 1, len, f);
6334 XtFree(selection_tmp);
6337 selection_tmp[len] = NULLCHAR;
6338 *value_return = selection_tmp;
6339 *length_return = len;
6340 *type_return = XA_STRING;
6341 *format_return = 8; /* bits per byte */
6348 /* note: when called from menu all parameters are NULL, so no clue what the
6349 * Widget which was clicked on was, or what the click event was
6351 void CopyGameProc(w, event, prms, nprms)
6359 ret = SaveGameToFile(gameCopyFilename, FALSE);
6362 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
6365 NULL/* lose_ownership_proc */ ,
6366 NULL/* transfer_done_proc */);
6369 /* function called when the data to Paste is ready */
6371 PasteGameCB(Widget w, XtPointer client_data, Atom *selection,
6372 Atom *type, XtPointer value, unsigned long *len, int *format)
6375 if (value == NULL || *len == 0) {
6376 return; /* nothing had been selected to copy */
6378 f = fopen(gamePasteFilename, "w");
6380 DisplayError(_("Can't open temp file"), errno);
6383 fwrite(value, 1, *len, f);
6386 LoadGameFromFile(gamePasteFilename, 0, gamePasteFilename, TRUE);
6389 /* called when Paste Game button is pressed,
6390 * all parameters will be NULL */
6391 void PasteGameProc(w, event, prms, nprms)
6397 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
6398 /* (XtSelectionCallbackProc) */ PasteGameCB,
6399 NULL, /* client_data passed to PasteGameCB */
6401 /* better to use the time field from the event that triggered the
6402 * call to this function, but that isn't trivial to get
6412 SaveGameProc(NULL, NULL, NULL, NULL);
6416 void QuitProc(w, event, prms, nprms)
6425 void PauseProc(w, event, prms, nprms)
6435 void MachineBlackProc(w, event, prms, nprms)
6441 MachineBlackEvent();
6444 void MachineWhiteProc(w, event, prms, nprms)
6450 MachineWhiteEvent();
6453 void AnalyzeModeProc(w, event, prms, nprms)
6461 if (!first.analysisSupport) {
6462 sprintf(buf, _("%s does not support analysis"), first.tidy);
6463 DisplayError(buf, 0);
6466 /* [DM] icsEngineAnalyze [HGM] This is horrible code; reverse the gameMode and isEngineAnalyze tests! */
6467 if (appData.icsActive) {
6468 if (gameMode != IcsObserving) {
6469 sprintf(buf,_("You are not observing a game"));
6470 DisplayError(buf, 0);
6472 if (appData.icsEngineAnalyze) {
6473 if (appData.debugMode)
6474 fprintf(debugFP, _("Found unexpected active ICS engine analyze \n"));
6480 /* if enable, use want disable icsEngineAnalyze */
6481 if (appData.icsEngineAnalyze) {
6486 appData.icsEngineAnalyze = TRUE;
6487 if (appData.debugMode)
6488 fprintf(debugFP, _("ICS engine analyze starting... \n"));
6490 if (!appData.showThinking)
6491 ShowThinkingProc(w,event,prms,nprms);
6496 void AnalyzeFileProc(w, event, prms, nprms)
6502 if (!first.analysisSupport) {
6504 sprintf(buf, _("%s does not support analysis"), first.tidy);
6505 DisplayError(buf, 0);
6510 if (!appData.showThinking)
6511 ShowThinkingProc(w,event,prms,nprms);
6514 FileNamePopUp(_("File to analyze"), "", LoadGamePopUp, "rb");
6515 AnalysisPeriodicEvent(1);
6518 void TwoMachinesProc(w, event, prms, nprms)
6527 void IcsClientProc(w, event, prms, nprms)
6536 void EditGameProc(w, event, prms, nprms)
6545 void EditPositionProc(w, event, prms, nprms)
6551 EditPositionEvent();
6554 void TrainingProc(w, event, prms, nprms)
6563 void EditCommentProc(w, event, prms, nprms)
6570 EditCommentPopDown();
6576 void IcsInputBoxProc(w, event, prms, nprms)
6582 if (ICSInputBoxUp) {
6583 ICSInputBoxPopDown();
6589 void AcceptProc(w, event, prms, nprms)
6598 void DeclineProc(w, event, prms, nprms)
6607 void RematchProc(w, event, prms, nprms)
6616 void CallFlagProc(w, event, prms, nprms)
6625 void DrawProc(w, event, prms, nprms)
6634 void AbortProc(w, event, prms, nprms)
6643 void AdjournProc(w, event, prms, nprms)
6652 void ResignProc(w, event, prms, nprms)
6661 void AdjuWhiteProc(w, event, prms, nprms)
6667 UserAdjudicationEvent(+1);
6670 void AdjuBlackProc(w, event, prms, nprms)
6676 UserAdjudicationEvent(-1);
6679 void AdjuDrawProc(w, event, prms, nprms)
6685 UserAdjudicationEvent(0);
6688 void EnterKeyProc(w, event, prms, nprms)
6694 if (ICSInputBoxUp == True)
6698 void StopObservingProc(w, event, prms, nprms)
6704 StopObservingEvent();
6707 void StopExaminingProc(w, event, prms, nprms)
6713 StopExaminingEvent();
6717 void ForwardProc(w, event, prms, nprms)
6727 void BackwardProc(w, event, prms, nprms)
6736 void ToStartProc(w, event, prms, nprms)
6745 void ToEndProc(w, event, prms, nprms)
6754 void RevertProc(w, event, prms, nprms)
6763 void TruncateGameProc(w, event, prms, nprms)
6769 TruncateGameEvent();
6771 void RetractMoveProc(w, event, prms, nprms)
6780 void MoveNowProc(w, event, prms, nprms)
6790 void AlwaysQueenProc(w, event, prms, nprms)
6798 appData.alwaysPromoteToQueen = !appData.alwaysPromoteToQueen;
6800 if (appData.alwaysPromoteToQueen) {
6801 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6803 XtSetArg(args[0], XtNleftBitmap, None);
6805 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
6809 void AnimateDraggingProc(w, event, prms, nprms)
6817 appData.animateDragging = !appData.animateDragging;
6819 if (appData.animateDragging) {
6820 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6823 XtSetArg(args[0], XtNleftBitmap, None);
6825 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Dragging"),
6829 void AnimateMovingProc(w, event, prms, nprms)
6837 appData.animate = !appData.animate;
6839 if (appData.animate) {
6840 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6843 XtSetArg(args[0], XtNleftBitmap, None);
6845 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
6849 void AutocommProc(w, event, prms, nprms)
6857 appData.autoComment = !appData.autoComment;
6859 if (appData.autoComment) {
6860 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6862 XtSetArg(args[0], XtNleftBitmap, None);
6864 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
6869 void AutoflagProc(w, event, prms, nprms)
6877 appData.autoCallFlag = !appData.autoCallFlag;
6879 if (appData.autoCallFlag) {
6880 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6882 XtSetArg(args[0], XtNleftBitmap, None);
6884 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
6888 void AutoflipProc(w, event, prms, nprms)
6896 appData.autoFlipView = !appData.autoFlipView;
6898 if (appData.autoFlipView) {
6899 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6901 XtSetArg(args[0], XtNleftBitmap, None);
6903 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flip View"),
6907 void AutobsProc(w, event, prms, nprms)
6915 appData.autoObserve = !appData.autoObserve;
6917 if (appData.autoObserve) {
6918 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6920 XtSetArg(args[0], XtNleftBitmap, None);
6922 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
6926 void AutoraiseProc(w, event, prms, nprms)
6934 appData.autoRaiseBoard = !appData.autoRaiseBoard;
6936 if (appData.autoRaiseBoard) {
6937 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6939 XtSetArg(args[0], XtNleftBitmap, None);
6941 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Raise Board"),
6945 void AutosaveProc(w, event, prms, nprms)
6953 appData.autoSaveGames = !appData.autoSaveGames;
6955 if (appData.autoSaveGames) {
6956 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6958 XtSetArg(args[0], XtNleftBitmap, None);
6960 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
6964 void BlindfoldProc(w, event, prms, nprms)
6972 appData.blindfold = !appData.blindfold;
6974 if (appData.blindfold) {
6975 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6977 XtSetArg(args[0], XtNleftBitmap, None);
6979 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Blindfold"),
6982 DrawPosition(True, NULL);
6985 void TestLegalityProc(w, event, prms, nprms)
6993 appData.testLegality = !appData.testLegality;
6995 if (appData.testLegality) {
6996 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6998 XtSetArg(args[0], XtNleftBitmap, None);
7000 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Test Legality"),
7005 void FlashMovesProc(w, event, prms, nprms)
7013 if (appData.flashCount == 0) {
7014 appData.flashCount = 3;
7016 appData.flashCount = -appData.flashCount;
7019 if (appData.flashCount > 0) {
7020 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7022 XtSetArg(args[0], XtNleftBitmap, None);
7024 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flash Moves"),
7028 void FlipViewProc(w, event, prms, nprms)
7034 flipView = !flipView;
7035 DrawPosition(True, NULL);
7038 void GetMoveListProc(w, event, prms, nprms)
7046 appData.getMoveList = !appData.getMoveList;
7048 if (appData.getMoveList) {
7049 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7052 XtSetArg(args[0], XtNleftBitmap, None);
7054 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
7059 void HighlightDraggingProc(w, event, prms, nprms)
7067 appData.highlightDragging = !appData.highlightDragging;
7069 if (appData.highlightDragging) {
7070 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7072 XtSetArg(args[0], XtNleftBitmap, None);
7074 XtSetValues(XtNameToWidget(menuBarWidget,
7075 "menuOptions.Highlight Dragging"), args, 1);
7079 void HighlightLastMoveProc(w, event, prms, nprms)
7087 appData.highlightLastMove = !appData.highlightLastMove;
7089 if (appData.highlightLastMove) {
7090 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7092 XtSetArg(args[0], XtNleftBitmap, None);
7094 XtSetValues(XtNameToWidget(menuBarWidget,
7095 "menuOptions.Highlight Last Move"), args, 1);
7098 void IcsAlarmProc(w, event, prms, nprms)
7106 appData.icsAlarm = !appData.icsAlarm;
7108 if (appData.icsAlarm) {
7109 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7111 XtSetArg(args[0], XtNleftBitmap, None);
7113 XtSetValues(XtNameToWidget(menuBarWidget,
7114 "menuOptions.ICS Alarm"), args, 1);
7117 void MoveSoundProc(w, event, prms, nprms)
7125 appData.ringBellAfterMoves = !appData.ringBellAfterMoves;
7127 if (appData.ringBellAfterMoves) {
7128 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7130 XtSetArg(args[0], XtNleftBitmap, None);
7132 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
7137 void OldSaveStyleProc(w, event, prms, nprms)
7145 appData.oldSaveStyle = !appData.oldSaveStyle;
7147 if (appData.oldSaveStyle) {
7148 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7150 XtSetArg(args[0], XtNleftBitmap, None);
7152 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Old Save Style"),
7156 void PeriodicUpdatesProc(w, event, prms, nprms)
7164 PeriodicUpdatesEvent(!appData.periodicUpdates);
7166 if (appData.periodicUpdates) {
7167 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7169 XtSetArg(args[0], XtNleftBitmap, None);
7171 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Periodic Updates"),
7175 void PonderNextMoveProc(w, event, prms, nprms)
7183 PonderNextMoveEvent(!appData.ponderNextMove);
7185 if (appData.ponderNextMove) {
7186 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7188 XtSetArg(args[0], XtNleftBitmap, None);
7190 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Ponder Next Move"),
7194 void PopupExitMessageProc(w, event, prms, nprms)
7202 appData.popupExitMessage = !appData.popupExitMessage;
7204 if (appData.popupExitMessage) {
7205 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7207 XtSetArg(args[0], XtNleftBitmap, None);
7209 XtSetValues(XtNameToWidget(menuBarWidget,
7210 "menuOptions.Popup Exit Message"), args, 1);
7213 void PopupMoveErrorsProc(w, event, prms, nprms)
7221 appData.popupMoveErrors = !appData.popupMoveErrors;
7223 if (appData.popupMoveErrors) {
7224 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7226 XtSetArg(args[0], XtNleftBitmap, None);
7228 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Popup Move Errors"),
7232 void PremoveProc(w, event, prms, nprms)
7240 appData.premove = !appData.premove;
7242 if (appData.premove) {
7243 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7245 XtSetArg(args[0], XtNleftBitmap, None);
7247 XtSetValues(XtNameToWidget(menuBarWidget,
7248 "menuOptions.Premove"), args, 1);
7251 void QuietPlayProc(w, event, prms, nprms)
7259 appData.quietPlay = !appData.quietPlay;
7261 if (appData.quietPlay) {
7262 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7264 XtSetArg(args[0], XtNleftBitmap, None);
7266 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Quiet Play"),
7270 void ShowCoordsProc(w, event, prms, nprms)
7278 appData.showCoords = !appData.showCoords;
7280 if (appData.showCoords) {
7281 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7283 XtSetArg(args[0], XtNleftBitmap, None);
7285 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
7288 DrawPosition(True, NULL);
7291 void ShowThinkingProc(w, event, prms, nprms)
7299 appData.showThinking = !appData.showThinking; // [HGM] thinking: tken out of ShowThinkingEvent
7300 ShowThinkingEvent();
7302 // [HGM] thinking: currently no suc menu item; replaced by Hide Thinking (From Human)
7303 if (appData.showThinking) {
7304 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7306 XtSetArg(args[0], XtNleftBitmap, None);
7308 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Thinking"),
7313 void HideThinkingProc(w, event, prms, nprms)
7321 appData.hideThinkingFromHuman = !appData.hideThinkingFromHuman; // [HGM] thinking: tken out of ShowThinkingEvent
7322 ShowThinkingEvent();
7324 if (appData.hideThinkingFromHuman) {
7325 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7327 XtSetArg(args[0], XtNleftBitmap, None);
7329 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
7333 void InfoProc(w, event, prms, nprms)
7340 sprintf(buf, "xterm -e info --directory %s --directory . -f %s &",
7345 void ManProc(w, event, prms, nprms)
7353 if (nprms && *nprms > 0)
7357 sprintf(buf, "xterm -e man %s &", name);
7361 void HintProc(w, event, prms, nprms)
7370 void BookProc(w, event, prms, nprms)
7379 void AboutProc(w, event, prms, nprms)
7387 char *zippy = " (with Zippy code)";
7391 sprintf(buf, "%s%s\n\n%s\n%s\n%s\n%s\n\n%s%s\n%s",
7392 programVersion, zippy,
7393 "Copyright 1991 Digital Equipment Corporation",
7394 "Enhancements Copyright 1992-2001 Free Software Foundation",
7395 "Enhancements Copyright 2005 Alessandro Scotti",
7396 "Enhancements Copyright 2007-2008 H.G.Muller",
7397 PRODUCT, " is free software and carries NO WARRANTY;",
7398 "see the file COPYING for more information.");
7399 ErrorPopUp(_("About XBoard"), buf, FALSE);
7402 void DebugProc(w, event, prms, nprms)
7408 appData.debugMode = !appData.debugMode;
7411 void AboutGameProc(w, event, prms, nprms)
7420 void NothingProc(w, event, prms, nprms)
7429 void Iconify(w, event, prms, nprms)
7438 XtSetArg(args[0], XtNiconic, True);
7439 XtSetValues(shellWidget, args, 1);
7442 void DisplayMessage(message, extMessage)
7443 char *message, *extMessage;
7450 sprintf(buf, "%s %s", message, extMessage);
7453 message = extMessage;
7456 XtSetArg(arg, XtNlabel, message);
7457 XtSetValues(messageWidget, &arg, 1);
7460 void DisplayTitle(text)
7465 char title[MSG_SIZ];
7468 if (text == NULL) text = "";
7470 if (appData.titleInWindow) {
7472 XtSetArg(args[i], XtNlabel, text); i++;
7473 XtSetValues(titleWidget, args, i);
7476 if (*text != NULLCHAR) {
7478 strcpy(title, text);
7479 } else if (appData.icsActive) {
7480 sprintf(icon, "%s", appData.icsHost);
7481 sprintf(title, "%s: %s", programName, appData.icsHost);
7482 } else if (appData.cmailGameName[0] != NULLCHAR) {
7483 sprintf(icon, "%s", "CMail");
7484 sprintf(title, "%s: %s", programName, "CMail");
7486 // [HGM] license: This stuff should really be done in back-end, but WinBoard already had a pop-up for it
7487 } else if (gameInfo.variant == VariantGothic) {
7488 strcpy(icon, programName);
7489 strcpy(title, GOTHIC);
7492 } else if (gameInfo.variant == VariantFalcon) {
7493 strcpy(icon, programName);
7494 strcpy(title, FALCON);
7496 } else if (appData.noChessProgram) {
7497 strcpy(icon, programName);
7498 strcpy(title, programName);
7500 strcpy(icon, first.tidy);
7501 sprintf(title, "%s: %s", programName, first.tidy);
7504 XtSetArg(args[i], XtNiconName, (XtArgVal) icon); i++;
7505 XtSetArg(args[i], XtNtitle, (XtArgVal) title); i++;
7506 XtSetValues(shellWidget, args, i);
7510 void DisplayError(message, error)
7517 if (appData.debugMode || appData.matchMode) {
7518 fprintf(stderr, "%s: %s\n", programName, message);
7521 if (appData.debugMode || appData.matchMode) {
7522 fprintf(stderr, "%s: %s: %s\n",
7523 programName, message, strerror(error));
7525 sprintf(buf, "%s: %s", message, strerror(error));
7528 ErrorPopUp(_("Error"), message, FALSE);
7532 void DisplayMoveError(message)
7537 DrawPosition(FALSE, NULL);
7538 if (appData.debugMode || appData.matchMode) {
7539 fprintf(stderr, "%s: %s\n", programName, message);
7541 if (appData.popupMoveErrors) {
7542 ErrorPopUp(_("Error"), message, FALSE);
7544 DisplayMessage(message, "");
7549 void DisplayFatalError(message, error, status)
7555 errorExitStatus = status;
7557 fprintf(stderr, "%s: %s\n", programName, message);
7559 fprintf(stderr, "%s: %s: %s\n",
7560 programName, message, strerror(error));
7561 sprintf(buf, "%s: %s", message, strerror(error));
7564 if (appData.popupExitMessage && boardWidget && XtIsRealized(boardWidget)) {
7565 ErrorPopUp(status ? _("Fatal Error") : _("Exiting"), message, TRUE);
7571 void DisplayInformation(message)
7575 ErrorPopUp(_("Information"), message, TRUE);
7578 void DisplayNote(message)
7582 ErrorPopUp(_("Note"), message, FALSE);
7586 NullXErrorCheck(dpy, error_event)
7588 XErrorEvent *error_event;
7593 void DisplayIcsInteractionTitle(message)
7596 if (oldICSInteractionTitle == NULL) {
7597 /* Magic to find the old window title, adapted from vim */
7598 char *wina = getenv("WINDOWID");
7600 Window win = (Window) atoi(wina);
7601 Window root, parent, *children;
7602 unsigned int nchildren;
7603 int (*oldHandler)() = XSetErrorHandler(NullXErrorCheck);
7605 if (XFetchName(xDisplay, win, &oldICSInteractionTitle)) break;
7606 if (!XQueryTree(xDisplay, win, &root, &parent,
7607 &children, &nchildren)) break;
7608 if (children) XFree((void *)children);
7609 if (parent == root || parent == 0) break;
7612 XSetErrorHandler(oldHandler);
7614 if (oldICSInteractionTitle == NULL) {
7615 oldICSInteractionTitle = "xterm";
7618 printf("\033]0;%s\007", message);
7622 char pendingReplyPrefix[MSG_SIZ];
7623 ProcRef pendingReplyPR;
7625 void AskQuestionProc(w, event, prms, nprms)
7632 fprintf(stderr, _("AskQuestionProc needed 4 parameters, got %d\n"),
7636 AskQuestionEvent(prms[0], prms[1], prms[2], prms[3]);
7639 void AskQuestionPopDown()
7641 if (!askQuestionUp) return;
7642 XtPopdown(askQuestionShell);
7643 XtDestroyWidget(askQuestionShell);
7644 askQuestionUp = False;
7647 void AskQuestionReplyAction(w, event, prms, nprms)
7657 reply = XawDialogGetValueString(w = XtParent(w));
7658 strcpy(buf, pendingReplyPrefix);
7659 if (*buf) strcat(buf, " ");
7662 OutputToProcess(pendingReplyPR, buf, strlen(buf), &err);
7663 AskQuestionPopDown();
7665 if (err) DisplayFatalError(_("Error writing to chess program"), err, 0);
7668 void AskQuestionCallback(w, client_data, call_data)
7670 XtPointer client_data, call_data;
7675 XtSetArg(args[0], XtNlabel, &name);
7676 XtGetValues(w, args, 1);
7678 if (strcmp(name, _("cancel")) == 0) {
7679 AskQuestionPopDown();
7681 AskQuestionReplyAction(w, NULL, NULL, NULL);
7685 void AskQuestion(title, question, replyPrefix, pr)
7686 char *title, *question, *replyPrefix;
7690 Widget popup, layout, dialog, edit;
7696 strcpy(pendingReplyPrefix, replyPrefix);
7697 pendingReplyPR = pr;
7700 XtSetArg(args[i], XtNresizable, True); i++;
7701 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
7702 askQuestionShell = popup =
7703 XtCreatePopupShell(title, transientShellWidgetClass,
7704 shellWidget, args, i);
7707 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
7708 layoutArgs, XtNumber(layoutArgs));
7711 XtSetArg(args[i], XtNlabel, question); i++;
7712 XtSetArg(args[i], XtNvalue, ""); i++;
7713 XtSetArg(args[i], XtNborderWidth, 0); i++;
7714 dialog = XtCreateManagedWidget("question", dialogWidgetClass,
7717 XawDialogAddButton(dialog, _("enter"), AskQuestionCallback,
7718 (XtPointer) dialog);
7719 XawDialogAddButton(dialog, _("cancel"), AskQuestionCallback,
7720 (XtPointer) dialog);
7722 XtRealizeWidget(popup);
7723 CatchDeleteWindow(popup, "AskQuestionPopDown");
7725 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
7726 &x, &y, &win_x, &win_y, &mask);
7728 XtSetArg(args[0], XtNx, x - 10);
7729 XtSetArg(args[1], XtNy, y - 30);
7730 XtSetValues(popup, args, 2);
7732 XtPopup(popup, XtGrabExclusive);
7733 askQuestionUp = True;
7735 edit = XtNameToWidget(dialog, "*value");
7736 XtSetKeyboardFocus(popup, edit);
7744 if (*name == NULLCHAR) {
7746 } else if (strcmp(name, "$") == 0) {
7747 putc(BELLCHAR, stderr);
7750 sprintf(buf, "%s '%s' &", appData.soundProgram, name);
7758 PlaySound(appData.soundMove);
7764 PlaySound(appData.soundIcsWin);
7770 PlaySound(appData.soundIcsLoss);
7776 PlaySound(appData.soundIcsDraw);
7780 PlayIcsUnfinishedSound()
7782 PlaySound(appData.soundIcsUnfinished);
7788 PlaySound(appData.soundIcsAlarm);
7794 system("stty echo");
7800 system("stty -echo");
7804 Colorize(cc, continuation)
7809 int count, outCount, error;
7811 if (textColors[(int)cc].bg > 0) {
7812 if (textColors[(int)cc].fg > 0) {
7813 sprintf(buf, "\033[0;%d;%d;%dm", textColors[(int)cc].attr,
7814 textColors[(int)cc].fg, textColors[(int)cc].bg);
7816 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
7817 textColors[(int)cc].bg);
7820 if (textColors[(int)cc].fg > 0) {
7821 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
7822 textColors[(int)cc].fg);
7824 sprintf(buf, "\033[0;%dm", textColors[(int)cc].attr);
7827 count = strlen(buf);
7828 outCount = OutputToProcess(NoProc, buf, count, &error);
7829 if (outCount < count) {
7830 DisplayFatalError(_("Error writing to display"), error, 1);
7833 if (continuation) return;
7836 PlaySound(appData.soundShout);
7839 PlaySound(appData.soundSShout);
7842 PlaySound(appData.soundChannel1);
7845 PlaySound(appData.soundChannel);
7848 PlaySound(appData.soundKibitz);
7851 PlaySound(appData.soundTell);
7853 case ColorChallenge:
7854 PlaySound(appData.soundChallenge);
7857 PlaySound(appData.soundRequest);
7860 PlaySound(appData.soundSeek);
7871 return getpwuid(getuid())->pw_name;
7874 static char *ExpandPathName(path)
7877 static char static_buf[2000];
7878 char *d, *s, buf[2000];
7884 while (*s && isspace(*s))
7893 if (*(s+1) == '/') {
7894 strcpy(d, getpwuid(getuid())->pw_dir);
7899 *strchr(buf, '/') = 0;
7900 pwd = getpwnam(buf);
7903 fprintf(stderr, _("ERROR: Unknown user %s (in path %s)\n"),
7907 strcpy(d, pwd->pw_dir);
7908 strcat(d, strchr(s+1, '/'));
7919 static char host_name[MSG_SIZ];
7921 #if HAVE_GETHOSTNAME
7922 gethostname(host_name, MSG_SIZ);
7924 #else /* not HAVE_GETHOSTNAME */
7925 # if HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H
7926 sysinfo(SI_HOSTNAME, host_name, MSG_SIZ);
7928 # else /* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
7930 # endif/* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
7931 #endif /* not HAVE_GETHOSTNAME */
7934 XtIntervalId delayedEventTimerXID = 0;
7935 DelayedEventCallback delayedEventCallback = 0;
7940 delayedEventTimerXID = 0;
7941 delayedEventCallback();
7945 ScheduleDelayedEvent(cb, millisec)
7946 DelayedEventCallback cb; long millisec;
7948 delayedEventCallback = cb;
7949 delayedEventTimerXID =
7950 XtAppAddTimeOut(appContext, millisec,
7951 (XtTimerCallbackProc) FireDelayedEvent, (XtPointer) 0);
7954 DelayedEventCallback
7957 if (delayedEventTimerXID) {
7958 return delayedEventCallback;
7965 CancelDelayedEvent()
7967 if (delayedEventTimerXID) {
7968 XtRemoveTimeOut(delayedEventTimerXID);
7969 delayedEventTimerXID = 0;
7973 XtIntervalId loadGameTimerXID = 0;
7975 int LoadGameTimerRunning()
7977 return loadGameTimerXID != 0;
7980 int StopLoadGameTimer()
7982 if (loadGameTimerXID != 0) {
7983 XtRemoveTimeOut(loadGameTimerXID);
7984 loadGameTimerXID = 0;
7992 LoadGameTimerCallback(arg, id)
7996 loadGameTimerXID = 0;
8001 StartLoadGameTimer(millisec)
8005 XtAppAddTimeOut(appContext, millisec,
8006 (XtTimerCallbackProc) LoadGameTimerCallback,
8010 XtIntervalId analysisClockXID = 0;
8013 AnalysisClockCallback(arg, id)
8017 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile
8018 || appData.icsEngineAnalyze) { // [DM]
8019 AnalysisPeriodicEvent(0);
8020 StartAnalysisClock();
8025 StartAnalysisClock()
8028 XtAppAddTimeOut(appContext, 2000,
8029 (XtTimerCallbackProc) AnalysisClockCallback,
8033 XtIntervalId clockTimerXID = 0;
8035 int ClockTimerRunning()
8037 return clockTimerXID != 0;
8040 int StopClockTimer()
8042 if (clockTimerXID != 0) {
8043 XtRemoveTimeOut(clockTimerXID);
8052 ClockTimerCallback(arg, id)
8061 StartClockTimer(millisec)
8065 XtAppAddTimeOut(appContext, millisec,
8066 (XtTimerCallbackProc) ClockTimerCallback,
8071 DisplayTimerLabel(w, color, timer, highlight)
8080 if (appData.clockMode) {
8081 sprintf(buf, "%s: %s", color, TimeString(timer));
8082 XtSetArg(args[0], XtNlabel, buf);
8084 sprintf(buf, "%s ", color);
8085 XtSetArg(args[0], XtNlabel, buf);
8089 XtSetArg(args[1], XtNbackground, timerForegroundPixel);
8090 XtSetArg(args[2], XtNforeground, timerBackgroundPixel);
8092 XtSetArg(args[1], XtNbackground, timerBackgroundPixel);
8093 XtSetArg(args[2], XtNforeground, timerForegroundPixel);
8096 XtSetValues(w, args, 3);
8100 DisplayWhiteClock(timeRemaining, highlight)
8106 if(appData.noGUI) return;
8107 DisplayTimerLabel(whiteTimerWidget, _("White"), timeRemaining, highlight);
8108 if (highlight && iconPixmap == bIconPixmap) {
8109 iconPixmap = wIconPixmap;
8110 XtSetArg(args[0], XtNiconPixmap, iconPixmap);
8111 XtSetValues(shellWidget, args, 1);
8116 DisplayBlackClock(timeRemaining, highlight)
8122 if(appData.noGUI) return;
8123 DisplayTimerLabel(blackTimerWidget, _("Black"), timeRemaining, highlight);
8124 if (highlight && iconPixmap == wIconPixmap) {
8125 iconPixmap = bIconPixmap;
8126 XtSetArg(args[0], XtNiconPixmap, iconPixmap);
8127 XtSetValues(shellWidget, args, 1);
8145 int StartChildProcess(cmdLine, dir, pr)
8152 int to_prog[2], from_prog[2];
8156 if (appData.debugMode) {
8157 fprintf(stderr, "StartChildProcess (dir=\"%s\") %s\n",dir, cmdLine);
8160 /* We do NOT feed the cmdLine to the shell; we just
8161 parse it into blank-separated arguments in the
8162 most simple-minded way possible.
8165 strcpy(buf, cmdLine);
8170 if (p == NULL) break;
8175 SetUpChildIO(to_prog, from_prog);
8177 if ((pid = fork()) == 0) {
8179 // [HGM] PSWBTM: made order resistant against case where fd of created pipe was 0 or 1
8180 close(to_prog[1]); // first close the unused pipe ends
8181 close(from_prog[0]);
8182 dup2(to_prog[0], 0); // to_prog was created first, nd is the only one to use 0 or 1
8183 dup2(from_prog[1], 1);
8184 if(to_prog[0] >= 2) close(to_prog[0]); // if 0 or 1, the dup2 already cosed the original
8185 close(from_prog[1]); // and closing again loses one of the pipes!
8186 if(fileno(stderr) >= 2) // better safe than sorry...
8187 dup2(1, fileno(stderr)); /* force stderr to the pipe */
8189 if (dir[0] != NULLCHAR && chdir(dir) != 0) {
8194 nice(appData.niceEngines); // [HGM] nice: adjust priority of engine proc
8196 execvp(argv[0], argv);
8198 /* If we get here, exec failed */
8203 /* Parent process */
8205 close(from_prog[1]);
8207 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8210 cp->fdFrom = from_prog[0];
8211 cp->fdTo = to_prog[1];
8216 // [HGM] kill: implement the 'hard killing' of AS's Winboard_x
8217 static RETSIGTYPE AlarmCallBack(int n)
8223 DestroyChildProcess(pr, signalType)
8227 ChildProc *cp = (ChildProc *) pr;
8229 if (cp->kind != CPReal) return;
8231 if (signalType == 10) { // [HGM] kill: if it does not terminate in 3 sec, kill
8232 signal(SIGALRM, AlarmCallBack);
8234 if(wait((int *) 0) == -1) { // process does not terminate on its own accord
8235 kill(cp->pid, SIGKILL); // kill it forcefully
8236 wait((int *) 0); // and wait again
8240 kill(cp->pid, signalType == 9 ? SIGKILL : SIGTERM); // [HGM] kill: use hard kill if so requested
8242 /* Process is exiting either because of the kill or because of
8243 a quit command sent by the backend; either way, wait for it to die.
8252 InterruptChildProcess(pr)
8255 ChildProc *cp = (ChildProc *) pr;
8257 if (cp->kind != CPReal) return;
8258 (void) kill(cp->pid, SIGINT); /* stop it thinking */
8261 int OpenTelnet(host, port, pr)
8266 char cmdLine[MSG_SIZ];
8268 if (port[0] == NULLCHAR) {
8269 sprintf(cmdLine, "%s %s", appData.telnetProgram, host);
8271 sprintf(cmdLine, "%s %s %s", appData.telnetProgram, host, port);
8273 return StartChildProcess(cmdLine, "", pr);
8276 int OpenTCP(host, port, pr)
8282 DisplayFatalError(_("Socket support is not configured in"), 0, 2);
8283 #else /* !OMIT_SOCKETS */
8285 struct sockaddr_in sa;
8287 unsigned short uport;
8290 if ((s = socket(AF_INET, SOCK_STREAM, 6)) < 0) {
8294 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
8295 sa.sin_family = AF_INET;
8296 sa.sin_addr.s_addr = INADDR_ANY;
8297 uport = (unsigned short) 0;
8298 sa.sin_port = htons(uport);
8299 if (bind(s, (struct sockaddr *) &sa, sizeof(struct sockaddr_in)) < 0) {
8303 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
8304 if (!(hp = gethostbyname(host))) {
8306 if (sscanf(host, "%d.%d.%d.%d", &b0, &b1, &b2, &b3) == 4) {
8307 hp = (struct hostent *) calloc(1, sizeof(struct hostent));
8308 hp->h_addrtype = AF_INET;
8310 hp->h_addr_list = (char **) calloc(2, sizeof(char *));
8311 hp->h_addr_list[0] = (char *) malloc(4);
8312 hp->h_addr_list[0][0] = b0;
8313 hp->h_addr_list[0][1] = b1;
8314 hp->h_addr_list[0][2] = b2;
8315 hp->h_addr_list[0][3] = b3;
8320 sa.sin_family = hp->h_addrtype;
8321 uport = (unsigned short) atoi(port);
8322 sa.sin_port = htons(uport);
8323 memcpy((char *) &sa.sin_addr, hp->h_addr, hp->h_length);
8325 if (connect(s, (struct sockaddr *) &sa,
8326 sizeof(struct sockaddr_in)) < 0) {
8330 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8337 #endif /* !OMIT_SOCKETS */
8342 int OpenCommPort(name, pr)
8349 fd = open(name, 2, 0);
8350 if (fd < 0) return errno;
8352 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8362 int OpenLoopback(pr)
8368 SetUpChildIO(to, from);
8370 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8373 cp->fdFrom = to[0]; /* note not from[0]; we are doing a loopback */
8380 int OpenRcmd(host, user, cmd, pr)
8381 char *host, *user, *cmd;
8384 DisplayFatalError(_("internal rcmd not implemented for Unix"), 0, 1);
8388 #define INPUT_SOURCE_BUF_SIZE 8192
8397 char buf[INPUT_SOURCE_BUF_SIZE];
8402 DoInputCallback(closure, source, xid)
8407 InputSource *is = (InputSource *) closure;
8412 if (is->lineByLine) {
8413 count = read(is->fd, is->unused,
8414 INPUT_SOURCE_BUF_SIZE - (is->unused - is->buf));
8416 (is->func)(is, is->closure, is->buf, count, count ? errno : 0);
8419 is->unused += count;
8421 while (p < is->unused) {
8422 q = memchr(p, '\n', is->unused - p);
8423 if (q == NULL) break;
8425 (is->func)(is, is->closure, p, q - p, 0);
8429 while (p < is->unused) {
8434 count = read(is->fd, is->buf, INPUT_SOURCE_BUF_SIZE);
8439 (is->func)(is, is->closure, is->buf, count, error);
8443 InputSourceRef AddInputSource(pr, lineByLine, func, closure)
8450 ChildProc *cp = (ChildProc *) pr;
8452 is = (InputSource *) calloc(1, sizeof(InputSource));
8453 is->lineByLine = lineByLine;
8457 is->fd = fileno(stdin);
8459 is->kind = cp->kind;
8460 is->fd = cp->fdFrom;
8463 is->unused = is->buf;
8466 is->xid = XtAppAddInput(appContext, is->fd,
8467 (XtPointer) (XtInputReadMask),
8468 (XtInputCallbackProc) DoInputCallback,
8470 is->closure = closure;
8471 return (InputSourceRef) is;
8475 RemoveInputSource(isr)
8478 InputSource *is = (InputSource *) isr;
8480 if (is->xid == 0) return;
8481 XtRemoveInput(is->xid);
8485 int OutputToProcess(pr, message, count, outError)
8491 ChildProc *cp = (ChildProc *) pr;
8495 outCount = fwrite(message, 1, count, stdout);
8497 outCount = write(cp->fdTo, message, count);
8507 /* Output message to process, with "ms" milliseconds of delay
8508 between each character. This is needed when sending the logon
8509 script to ICC, which for some reason doesn't like the
8510 instantaneous send. */
8511 int OutputToProcessDelayed(pr, message, count, outError, msdelay)
8518 ChildProc *cp = (ChildProc *) pr;
8523 r = write(cp->fdTo, message++, 1);
8536 /**** Animation code by Hugh Fisher, DCS, ANU.
8538 Known problem: if a window overlapping the board is
8539 moved away while a piece is being animated underneath,
8540 the newly exposed area won't be updated properly.
8541 I can live with this.
8543 Known problem: if you look carefully at the animation
8544 of pieces in mono mode, they are being drawn as solid
8545 shapes without interior detail while moving. Fixing
8546 this would be a major complication for minimal return.
8549 /* Masks for XPM pieces. Black and white pieces can have
8550 different shapes, but in the interest of retaining my
8551 sanity pieces must have the same outline on both light
8552 and dark squares, and all pieces must use the same
8553 background square colors/images. */
8556 CreateAnimMasks (pieceDepth)
8563 unsigned long plane;
8566 /* Need a bitmap just to get a GC with right depth */
8567 buf = XCreatePixmap(xDisplay, xBoardWindow,
8569 values.foreground = 1;
8570 values.background = 0;
8571 /* Don't use XtGetGC, not read only */
8572 maskGC = XCreateGC(xDisplay, buf,
8573 GCForeground | GCBackground, &values);
8574 XFreePixmap(xDisplay, buf);
8576 buf = XCreatePixmap(xDisplay, xBoardWindow,
8577 squareSize, squareSize, pieceDepth);
8578 values.foreground = XBlackPixel(xDisplay, xScreen);
8579 values.background = XWhitePixel(xDisplay, xScreen);
8580 bufGC = XCreateGC(xDisplay, buf,
8581 GCForeground | GCBackground, &values);
8583 for (piece = WhitePawn; piece <= BlackKing; piece++) {
8584 /* Begin with empty mask */
8585 xpmMask[piece] = XCreatePixmap(xDisplay, xBoardWindow,
8586 squareSize, squareSize, 1);
8587 XSetFunction(xDisplay, maskGC, GXclear);
8588 XFillRectangle(xDisplay, xpmMask[piece], maskGC,
8589 0, 0, squareSize, squareSize);
8591 /* Take a copy of the piece */
8596 XSetFunction(xDisplay, bufGC, GXcopy);
8597 XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % (int)BlackPawn],
8599 0, 0, squareSize, squareSize, 0, 0);
8601 /* XOR the background (light) over the piece */
8602 XSetFunction(xDisplay, bufGC, GXxor);
8604 XCopyArea(xDisplay, xpmLightSquare, buf, bufGC,
8605 0, 0, squareSize, squareSize, 0, 0);
8607 XSetForeground(xDisplay, bufGC, lightSquareColor);
8608 XFillRectangle(xDisplay, buf, bufGC, 0, 0, squareSize, squareSize);
8611 /* We now have an inverted piece image with the background
8612 erased. Construct mask by just selecting all the non-zero
8613 pixels - no need to reconstruct the original image. */
8614 XSetFunction(xDisplay, maskGC, GXor);
8616 /* Might be quicker to download an XImage and create bitmap
8617 data from it rather than this N copies per piece, but it
8618 only takes a fraction of a second and there is a much
8619 longer delay for loading the pieces. */
8620 for (n = 0; n < pieceDepth; n ++) {
8621 XCopyPlane(xDisplay, buf, xpmMask[piece], maskGC,
8622 0, 0, squareSize, squareSize,
8628 XFreePixmap(xDisplay, buf);
8629 XFreeGC(xDisplay, bufGC);
8630 XFreeGC(xDisplay, maskGC);
8634 InitAnimState (anim, info)
8636 XWindowAttributes * info;
8641 /* Each buffer is square size, same depth as window */
8642 anim->saveBuf = XCreatePixmap(xDisplay, xBoardWindow,
8643 squareSize, squareSize, info->depth);
8644 anim->newBuf = XCreatePixmap(xDisplay, xBoardWindow,
8645 squareSize, squareSize, info->depth);
8647 /* Create a plain GC for blitting */
8648 mask = GCForeground | GCBackground | GCFunction |
8649 GCPlaneMask | GCGraphicsExposures;
8650 values.foreground = XBlackPixel(xDisplay, xScreen);
8651 values.background = XWhitePixel(xDisplay, xScreen);
8652 values.function = GXcopy;
8653 values.plane_mask = AllPlanes;
8654 values.graphics_exposures = False;
8655 anim->blitGC = XCreateGC(xDisplay, xBoardWindow, mask, &values);
8657 /* Piece will be copied from an existing context at
8658 the start of each new animation/drag. */
8659 anim->pieceGC = XCreateGC(xDisplay, xBoardWindow, 0, &values);
8661 /* Outline will be a read-only copy of an existing */
8662 anim->outlineGC = None;
8668 static int done = 0;
8669 XWindowAttributes info;
8673 XGetWindowAttributes(xDisplay, xBoardWindow, &info);
8675 InitAnimState(&game, &info);
8676 InitAnimState(&player, &info);
8678 /* For XPM pieces, we need bitmaps to use as masks. */
8680 CreateAnimMasks(info.depth);
8685 static Boolean frameWaiting;
8687 static RETSIGTYPE FrameAlarm (sig)
8690 frameWaiting = False;
8691 /* In case System-V style signals. Needed?? */
8692 signal(SIGALRM, FrameAlarm);
8699 struct itimerval delay;
8701 XSync(xDisplay, False);
8704 frameWaiting = True;
8705 signal(SIGALRM, FrameAlarm);
8706 delay.it_interval.tv_sec =
8707 delay.it_value.tv_sec = time / 1000;
8708 delay.it_interval.tv_usec =
8709 delay.it_value.tv_usec = (time % 1000) * 1000;
8710 setitimer(ITIMER_REAL, &delay, NULL);
8712 /* Ugh -- busy-wait! --tpm */
8713 while (frameWaiting);
8715 while (frameWaiting) pause();
8717 delay.it_interval.tv_sec = delay.it_value.tv_sec = 0;
8718 delay.it_interval.tv_usec = delay.it_value.tv_usec = 0;
8719 setitimer(ITIMER_REAL, &delay, NULL);
8729 XSync(xDisplay, False);
8731 usleep(time * 1000);
8736 /* Convert board position to corner of screen rect and color */
8739 ScreenSquare(column, row, pt, color)
8740 int column; int row; XPoint * pt; int * color;
8743 pt->x = lineGap + ((BOARD_WIDTH-1)-column) * (squareSize + lineGap);
8744 pt->y = lineGap + row * (squareSize + lineGap);
8746 pt->x = lineGap + column * (squareSize + lineGap);
8747 pt->y = lineGap + ((BOARD_HEIGHT-1)-row) * (squareSize + lineGap);
8749 *color = SquareColor(row, column);
8752 /* Convert window coords to square */
8755 BoardSquare(x, y, column, row)
8756 int x; int y; int * column; int * row;
8758 *column = EventToSquare(x, BOARD_WIDTH);
8759 if (flipView && *column >= 0)
8760 *column = BOARD_WIDTH - 1 - *column;
8761 *row = EventToSquare(y, BOARD_HEIGHT);
8762 if (!flipView && *row >= 0)
8763 *row = BOARD_HEIGHT - 1 - *row;
8768 #undef Max /* just in case */
8770 #define Max(a, b) ((a) > (b) ? (a) : (b))
8771 #define Min(a, b) ((a) < (b) ? (a) : (b))
8774 SetRect(rect, x, y, width, height)
8775 XRectangle * rect; int x; int y; int width; int height;
8779 rect->width = width;
8780 rect->height = height;
8783 /* Test if two frames overlap. If they do, return
8784 intersection rect within old and location of
8785 that rect within new. */
8788 Intersect(old, new, size, area, pt)
8789 XPoint * old; XPoint * new;
8790 int size; XRectangle * area; XPoint * pt;
8792 if (old->x > new->x + size || new->x > old->x + size ||
8793 old->y > new->y + size || new->y > old->y + size) {
8796 SetRect(area, Max(new->x - old->x, 0), Max(new->y - old->y, 0),
8797 size - abs(old->x - new->x), size - abs(old->y - new->y));
8798 pt->x = Max(old->x - new->x, 0);
8799 pt->y = Max(old->y - new->y, 0);
8804 /* For two overlapping frames, return the rect(s)
8805 in the old that do not intersect with the new. */
8808 CalcUpdateRects(old, new, size, update, nUpdates)
8809 XPoint * old; XPoint * new; int size;
8810 XRectangle update[]; int * nUpdates;
8814 /* If old = new (shouldn't happen) then nothing to draw */
8815 if (old->x == new->x && old->y == new->y) {
8819 /* Work out what bits overlap. Since we know the rects
8820 are the same size we don't need a full intersect calc. */
8822 /* Top or bottom edge? */
8823 if (new->y > old->y) {
8824 SetRect(&(update[count]), old->x, old->y, size, new->y - old->y);
8826 } else if (old->y > new->y) {
8827 SetRect(&(update[count]), old->x, old->y + size - (old->y - new->y),
8828 size, old->y - new->y);
8831 /* Left or right edge - don't overlap any update calculated above. */
8832 if (new->x > old->x) {
8833 SetRect(&(update[count]), old->x, Max(new->y, old->y),
8834 new->x - old->x, size - abs(new->y - old->y));
8836 } else if (old->x > new->x) {
8837 SetRect(&(update[count]), new->x + size, Max(new->y, old->y),
8838 old->x - new->x, size - abs(new->y - old->y));
8845 /* Generate a series of frame coords from start->mid->finish.
8846 The movement rate doubles until the half way point is
8847 reached, then halves back down to the final destination,
8848 which gives a nice slow in/out effect. The algorithmn
8849 may seem to generate too many intermediates for short
8850 moves, but remember that the purpose is to attract the
8851 viewers attention to the piece about to be moved and
8852 then to where it ends up. Too few frames would be less
8856 Tween(start, mid, finish, factor, frames, nFrames)
8857 XPoint * start; XPoint * mid;
8858 XPoint * finish; int factor;
8859 XPoint frames[]; int * nFrames;
8861 int fraction, n, count;
8865 /* Slow in, stepping 1/16th, then 1/8th, ... */
8867 for (n = 0; n < factor; n++)
8869 for (n = 0; n < factor; n++) {
8870 frames[count].x = start->x + (mid->x - start->x) / fraction;
8871 frames[count].y = start->y + (mid->y - start->y) / fraction;
8873 fraction = fraction / 2;
8877 frames[count] = *mid;
8880 /* Slow out, stepping 1/2, then 1/4, ... */
8882 for (n = 0; n < factor; n++) {
8883 frames[count].x = finish->x - (finish->x - mid->x) / fraction;
8884 frames[count].y = finish->y - (finish->y - mid->y) / fraction;
8886 fraction = fraction * 2;
8891 /* Draw a piece on the screen without disturbing what's there */
8894 SelectGCMask(piece, clip, outline, mask)
8895 ChessSquare piece; GC * clip; GC * outline; Pixmap * mask;
8899 /* Bitmap for piece being moved. */
8900 if (appData.monoMode) {
8901 *mask = *pieceToSolid(piece);
8902 } else if (useImages) {
8904 *mask = xpmMask[piece];
8906 *mask = ximMaskPm[piece%(int)BlackPawn];
8909 *mask = *pieceToSolid(piece);
8912 /* GC for piece being moved. Square color doesn't matter, but
8913 since it gets modified we make a copy of the original. */
8915 if (appData.monoMode)
8920 if (appData.monoMode)
8925 XCopyGC(xDisplay, source, 0xFFFFFFFF, *clip);
8927 /* Outline only used in mono mode and is not modified */
8929 *outline = bwPieceGC;
8931 *outline = wbPieceGC;
8935 OverlayPiece(piece, clip, outline, dest)
8936 ChessSquare piece; GC clip; GC outline; Drawable dest;
8941 /* Draw solid rectangle which will be clipped to shape of piece */
8942 XFillRectangle(xDisplay, dest, clip,
8943 0, 0, squareSize, squareSize);
8944 if (appData.monoMode)
8945 /* Also draw outline in contrasting color for black
8946 on black / white on white cases */
8947 XCopyPlane(xDisplay, *pieceToOutline(piece), dest, outline,
8948 0, 0, squareSize, squareSize, 0, 0, 1);
8950 /* Copy the piece */
8955 XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % (int)BlackPawn],
8957 0, 0, squareSize, squareSize,
8962 /* Animate the movement of a single piece */
8965 BeginAnimation(anim, piece, startColor, start)
8973 /* The old buffer is initialised with the start square (empty) */
8974 BlankSquare(0, 0, startColor, EmptySquare, anim->saveBuf);
8975 anim->prevFrame = *start;
8977 /* The piece will be drawn using its own bitmap as a matte */
8978 SelectGCMask(piece, &anim->pieceGC, &anim->outlineGC, &mask);
8979 XSetClipMask(xDisplay, anim->pieceGC, mask);
8983 AnimationFrame(anim, frame, piece)
8988 XRectangle updates[4];
8993 /* Save what we are about to draw into the new buffer */
8994 XCopyArea(xDisplay, xBoardWindow, anim->newBuf, anim->blitGC,
8995 frame->x, frame->y, squareSize, squareSize,
8998 /* Erase bits of the previous frame */
8999 if (Intersect(&anim->prevFrame, frame, squareSize, &overlap, &pt)) {
9000 /* Where the new frame overlapped the previous,
9001 the contents in newBuf are wrong. */
9002 XCopyArea(xDisplay, anim->saveBuf, anim->newBuf, anim->blitGC,
9003 overlap.x, overlap.y,
9004 overlap.width, overlap.height,
9006 /* Repaint the areas in the old that don't overlap new */
9007 CalcUpdateRects(&anim->prevFrame, frame, squareSize, updates, &count);
9008 for (i = 0; i < count; i++)
9009 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9010 updates[i].x - anim->prevFrame.x,
9011 updates[i].y - anim->prevFrame.y,
9012 updates[i].width, updates[i].height,
9013 updates[i].x, updates[i].y);
9015 /* Easy when no overlap */
9016 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9017 0, 0, squareSize, squareSize,
9018 anim->prevFrame.x, anim->prevFrame.y);
9021 /* Save this frame for next time round */
9022 XCopyArea(xDisplay, anim->newBuf, anim->saveBuf, anim->blitGC,
9023 0, 0, squareSize, squareSize,
9025 anim->prevFrame = *frame;
9027 /* Draw piece over original screen contents, not current,
9028 and copy entire rect. Wipes out overlapping piece images. */
9029 OverlayPiece(piece, anim->pieceGC, anim->outlineGC, anim->newBuf);
9030 XCopyArea(xDisplay, anim->newBuf, xBoardWindow, anim->blitGC,
9031 0, 0, squareSize, squareSize,
9032 frame->x, frame->y);
9036 EndAnimation (anim, finish)
9040 XRectangle updates[4];
9045 /* The main code will redraw the final square, so we
9046 only need to erase the bits that don't overlap. */
9047 if (Intersect(&anim->prevFrame, finish, squareSize, &overlap, &pt)) {
9048 CalcUpdateRects(&anim->prevFrame, finish, squareSize, updates, &count);
9049 for (i = 0; i < count; i++)
9050 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9051 updates[i].x - anim->prevFrame.x,
9052 updates[i].y - anim->prevFrame.y,
9053 updates[i].width, updates[i].height,
9054 updates[i].x, updates[i].y);
9056 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9057 0, 0, squareSize, squareSize,
9058 anim->prevFrame.x, anim->prevFrame.y);
9063 FrameSequence(anim, piece, startColor, start, finish, frames, nFrames)
9065 ChessSquare piece; int startColor;
9066 XPoint * start; XPoint * finish;
9067 XPoint frames[]; int nFrames;
9071 BeginAnimation(anim, piece, startColor, start);
9072 for (n = 0; n < nFrames; n++) {
9073 AnimationFrame(anim, &(frames[n]), piece);
9074 FrameDelay(appData.animSpeed);
9076 EndAnimation(anim, finish);
9079 /* Main control logic for deciding what to animate and how */
9082 AnimateMove(board, fromX, fromY, toX, toY)
9091 XPoint start, finish, mid;
9092 XPoint frames[kFactor * 2 + 1];
9093 int nFrames, startColor, endColor;
9095 /* Are we animating? */
9096 if (!appData.animate || appData.blindfold)
9099 if (fromY < 0 || fromX < 0 || toX < 0 || toY < 0) return;
9100 piece = board[fromY][fromX];
9101 if (piece >= EmptySquare) return;
9106 hop = (piece == WhiteKnight || piece == BlackKnight);
9109 if (appData.debugMode) {
9110 fprintf(debugFP, hop ? _("AnimateMove: piece %d hops from %d,%d to %d,%d \n") :
9111 _("AnimateMove: piece %d slides from %d,%d to %d,%d \n"),
9112 piece, fromX, fromY, toX, toY); }
9114 ScreenSquare(fromX, fromY, &start, &startColor);
9115 ScreenSquare(toX, toY, &finish, &endColor);
9118 /* Knight: make diagonal movement then straight */
9119 if (abs(toY - fromY) < abs(toX - fromX)) {
9120 mid.x = start.x + (finish.x - start.x) / 2;
9124 mid.y = start.y + (finish.y - start.y) / 2;
9127 mid.x = start.x + (finish.x - start.x) / 2;
9128 mid.y = start.y + (finish.y - start.y) / 2;
9131 /* Don't use as many frames for very short moves */
9132 if (abs(toY - fromY) + abs(toX - fromX) <= 2)
9133 Tween(&start, &mid, &finish, kFactor - 1, frames, &nFrames);
9135 Tween(&start, &mid, &finish, kFactor, frames, &nFrames);
9136 FrameSequence(&game, piece, startColor, &start, &finish, frames, nFrames);
9138 /* Be sure end square is redrawn */
9139 damage[toY][toX] = True;
9143 DragPieceBegin(x, y)
9146 int boardX, boardY, color;
9149 /* Are we animating? */
9150 if (!appData.animateDragging || appData.blindfold)
9153 /* Figure out which square we start in and the
9154 mouse position relative to top left corner. */
9155 BoardSquare(x, y, &boardX, &boardY);
9156 player.startBoardX = boardX;
9157 player.startBoardY = boardY;
9158 ScreenSquare(boardX, boardY, &corner, &color);
9159 player.startSquare = corner;
9160 player.startColor = color;
9162 /* Start from exactly where the piece is. This can be confusing
9163 if you start dragging far from the center of the square; most
9164 or all of the piece can be over a different square from the one
9165 the mouse pointer is in. */
9166 player.mouseDelta.x = x - corner.x;
9167 player.mouseDelta.y = y - corner.y;
9169 /* As soon as we start dragging, the piece will jump slightly to
9170 be centered over the mouse pointer. */
9171 player.mouseDelta.x = squareSize/2;
9172 player.mouseDelta.y = squareSize/2;
9174 /* Initialise animation */
9175 player.dragPiece = PieceForSquare(boardX, boardY);
9177 if (player.dragPiece >= 0 && player.dragPiece < EmptySquare) {
9178 player.dragActive = True;
9179 BeginAnimation(&player, player.dragPiece, color, &corner);
9180 /* Mark this square as needing to be redrawn. Note that
9181 we don't remove the piece though, since logically (ie
9182 as seen by opponent) the move hasn't been made yet. */
9183 if(boardX == BOARD_RGHT+1 && PieceForSquare(boardX-1, boardY) > 1 ||
9184 boardX == BOARD_LEFT-2 && PieceForSquare(boardX+1, boardY) > 1)
9185 XCopyArea(xDisplay, xBoardWindow, player.saveBuf, player.blitGC,
9186 corner.x, corner.y, squareSize, squareSize,
9187 0, 0); // [HGM] zh: unstack in stead of grab
9188 damage[boardY][boardX] = True;
9190 player.dragActive = False;
9200 /* Are we animating? */
9201 if (!appData.animateDragging || appData.blindfold)
9205 if (! player.dragActive)
9207 /* Move piece, maintaining same relative position
9208 of mouse within square */
9209 corner.x = x - player.mouseDelta.x;
9210 corner.y = y - player.mouseDelta.y;
9211 AnimationFrame(&player, &corner, player.dragPiece);
9213 if (appData.highlightDragging) {
9215 BoardSquare(x, y, &boardX, &boardY);
9216 SetHighlights(fromX, fromY, boardX, boardY);
9225 int boardX, boardY, color;
9228 /* Are we animating? */
9229 if (!appData.animateDragging || appData.blindfold)
9233 if (! player.dragActive)
9235 /* Last frame in sequence is square piece is
9236 placed on, which may not match mouse exactly. */
9237 BoardSquare(x, y, &boardX, &boardY);
9238 ScreenSquare(boardX, boardY, &corner, &color);
9239 EndAnimation(&player, &corner);
9241 /* Be sure end square is redrawn */
9242 damage[boardY][boardX] = True;
9244 /* This prevents weird things happening with fast successive
9245 clicks which on my Sun at least can cause motion events
9246 without corresponding press/release. */
9247 player.dragActive = False;
9250 /* Handle expose event while piece being dragged */
9255 if (!player.dragActive || appData.blindfold)
9258 /* What we're doing: logically, the move hasn't been made yet,
9259 so the piece is still in it's original square. But visually
9260 it's being dragged around the board. So we erase the square
9261 that the piece is on and draw it at the last known drag point. */
9262 BlankSquare(player.startSquare.x, player.startSquare.y,
9263 player.startColor, EmptySquare, xBoardWindow);
9264 AnimationFrame(&player, &player.prevFrame, player.dragPiece);
9265 damage[player.startBoardY][player.startBoardX] = TRUE;
9269 SetProgramStats( FrontEndProgramStats * stats )
9272 // [HGM] done, but perhaps backend should call this directly?
9273 EngineOutputUpdate( stats );