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 EnterKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
350 void StopObservingProc P((Widget w, XEvent *event, String *prms,
352 void StopExaminingProc P((Widget w, XEvent *event, String *prms,
354 void BackwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
355 void ForwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
356 void ToStartProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
357 void ToEndProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
358 void RevertProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
359 void TruncateGameProc P((Widget w, XEvent *event, String *prms,
361 void RetractMoveProc P((Widget w, XEvent *event, String *prms,
363 void MoveNowProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
364 void AlwaysQueenProc P((Widget w, XEvent *event, String *prms,
366 void AnimateDraggingProc P((Widget w, XEvent *event, String *prms,
368 void AnimateMovingProc P((Widget w, XEvent *event, String *prms,
370 void AutocommProc P((Widget w, XEvent *event, String *prms,
372 void AutoflagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
373 void AutoflipProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
374 void AutobsProc P((Widget w, XEvent *event, String *prms,
376 void AutoraiseProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
377 void AutosaveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
378 void BlindfoldProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
379 void FlashMovesProc P((Widget w, XEvent *event, String *prms,
381 void FlipViewProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
382 void GetMoveListProc P((Widget w, XEvent *event, String *prms,
384 void HighlightDraggingProc P((Widget w, XEvent *event, String *prms,
386 void HighlightLastMoveProc P((Widget w, XEvent *event, String *prms,
388 void MoveSoundProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
389 void IcsAlarmProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
390 void OldSaveStyleProc P((Widget w, XEvent *event, String *prms,
392 void PeriodicUpdatesProc P((Widget w, XEvent *event, String *prms,
394 void PonderNextMoveProc P((Widget w, XEvent *event, String *prms,
396 void PopupMoveErrorsProc P((Widget w, XEvent *event, String *prms,
398 void PopupExitMessageProc P((Widget w, XEvent *event, String *prms,
400 void PremoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
401 void QuietPlayProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
402 void ShowCoordsProc P((Widget w, XEvent *event, String *prms,
404 void ShowThinkingProc P((Widget w, XEvent *event, String *prms,
406 void HideThinkingProc P((Widget w, XEvent *event, String *prms,
408 void TestLegalityProc P((Widget w, XEvent *event, String *prms,
410 void InfoProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
411 void ManProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
412 void HintProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
413 void BookProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
414 void AboutGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
415 void AboutProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
416 void DebugProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
417 void NothingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
418 void Iconify P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
419 void DisplayMove P((int moveNumber));
420 void DisplayTitle P((char *title));
421 void ICSInitScript P((void));
422 int LoadGamePopUp P((FILE *f, int gameNumber, char *title));
423 void ErrorPopUp P((char *title, char *text, int modal));
424 void ErrorPopDown P((void));
425 static char *ExpandPathName P((char *path));
426 static void CreateAnimVars P((void));
427 static void DragPieceBegin P((int x, int y));
428 static void DragPieceMove P((int x, int y));
429 static void DragPieceEnd P((int x, int y));
430 static void DrawDragPiece P((void));
431 char *ModeToWidgetName P((GameMode mode));
432 void EngineOutputUpdate( FrontEndProgramStats * stats );
433 void ShuffleMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
434 void EngineMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
435 void UciMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
436 void TimeControlProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
437 void NewVariantProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
438 void FirstSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
439 void SecondSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
440 void ShufflePopDown P(());
441 void EnginePopDown P(());
442 void UciPopDown P(());
443 void TimeControlPopDown P(());
444 void NewVariantPopDown P(());
445 void SettingsPopDown P(());
447 * XBoard depends on Xt R4 or higher
449 int xtVersion = XtSpecificationRelease;
454 Pixel lightSquareColor, darkSquareColor, whitePieceColor, blackPieceColor,
455 jailSquareColor, highlightSquareColor, premoveHighlightColor;
456 GC lightSquareGC, darkSquareGC, jailSquareGC, lineGC, wdPieceGC, wlPieceGC,
457 bdPieceGC, blPieceGC, wbPieceGC, bwPieceGC, coordGC, highlineGC,
458 wjPieceGC, bjPieceGC, prelineGC, countGC;
459 Pixmap iconPixmap, wIconPixmap, bIconPixmap, xMarkPixmap;
460 Widget shellWidget, layoutWidget, formWidget, boardWidget, messageWidget,
461 whiteTimerWidget, blackTimerWidget, titleWidget, widgetList[16],
462 commentShell, promotionShell, whitePieceMenu, blackPieceMenu, dropMenu,
463 menuBarWidget, buttonBarWidget, editShell, errorShell, analysisShell,
464 ICSInputShell, fileNameShell, askQuestionShell;
465 XSegment gridSegments[(BOARD_SIZE + 1) * 2];
466 XSegment jailGridSegments[(BOARD_SIZE + 3) * 2];
467 Font clockFontID, coordFontID, countFontID;
468 XFontStruct *clockFontStruct, *coordFontStruct, *countFontStruct;
469 XtAppContext appContext;
471 char *oldICSInteractionTitle;
475 char installDir[] = "."; // [HGM] UCI: needed for UCI; probably needs run-time initializtion
477 Position commentX = -1, commentY = -1;
478 Dimension commentW, commentH;
480 int squareSize, smallLayout = 0, tinyLayout = 0,
481 marginW, marginH, // [HGM] for run-time resizing
482 fromX = -1, fromY = -1, toX, toY, commentUp = False, analysisUp = False,
483 ICSInputBoxUp = False, askQuestionUp = False,
484 filenameUp = False, promotionUp = False, pmFromX = -1, pmFromY = -1,
485 editUp = False, errorUp = False, errorExitStatus = -1, lineGap;
486 Pixel timerForegroundPixel, timerBackgroundPixel;
487 Pixel buttonForegroundPixel, buttonBackgroundPixel;
488 char *chessDir, *programName, *programVersion,
489 *gameCopyFilename, *gamePasteFilename;
493 Pixmap pieceBitmap[2][(int)BlackPawn];
494 Pixmap xpmPieceBitmap[4][(int)BlackPawn]; /* LL, LD, DL, DD */
495 Pixmap xpmLightSquare, xpmDarkSquare, xpmJailSquare;
496 int useImages, useImageSqs;
497 XImage *ximPieceBitmap[4][(int)BlackPawn]; /* LL, LD, DL, DD */
498 Pixmap ximMaskPm[(int)BlackPawn]; /* clipmasks, used for XIM pieces */
499 XImage *ximLightSquare, *ximDarkSquare;
502 #define pieceToSolid(piece) &pieceBitmap[SOLID][((int)(piece)) % (int)BlackPawn]
503 #define pieceToOutline(piece) &pieceBitmap[OUTLINE][((int)(piece)) % (int)BlackPawn]
505 #define White(piece) ((int)(piece) < (int)BlackPawn)
507 /* Variables for doing smooth animation. This whole thing
508 would be much easier if the board was double-buffered,
509 but that would require a fairly major rewrite. */
514 GC blitGC, pieceGC, outlineGC;
515 XPoint startSquare, prevFrame, mouseDelta;
519 int startBoardX, startBoardY;
522 /* There can be two pieces being animated at once: a player
523 can begin dragging a piece before the remote opponent has moved. */
525 static AnimState game, player;
527 /* Bitmaps for use as masks when drawing XPM pieces.
528 Need one for each black and white piece. */
529 static Pixmap xpmMask[BlackKing + 1];
531 /* This magic number is the number of intermediate frames used
532 in each half of the animation. For short moves it's reduced
533 by 1. The total number of frames will be factor * 2 + 1. */
536 SizeDefaults sizeDefaults[] = SIZE_DEFAULTS;
538 MenuItem fileMenu[] = {
539 {N_("New Game"), ResetProc},
540 {N_("New Shuffle Game ..."), ShuffleMenuProc},
541 {N_("New Variant ..."), NewVariantProc}, // [HGM] variant: not functional yet
542 {"----", NothingProc},
543 {N_("Load Game"), LoadGameProc},
544 {N_("Load Next Game"), LoadNextGameProc},
545 {N_("Load Previous Game"), LoadPrevGameProc},
546 {N_("Reload Same Game"), ReloadGameProc},
547 {N_("Save Game"), SaveGameProc},
548 {"----", NothingProc},
549 {N_("Copy Game"), CopyGameProc},
550 {N_("Paste Game"), PasteGameProc},
551 {"----", NothingProc},
552 {N_("Load Position"), LoadPositionProc},
553 {N_("Load Next Position"), LoadNextPositionProc},
554 {N_("Load Previous Position"), LoadPrevPositionProc},
555 {N_("Reload Same Position"), ReloadPositionProc},
556 {N_("Save Position"), SavePositionProc},
557 {"----", NothingProc},
558 {N_("Copy Position"), CopyPositionProc},
559 {N_("Paste Position"), PastePositionProc},
560 {"----", NothingProc},
561 {N_("Mail Move"), MailMoveProc},
562 {N_("Reload CMail Message"), ReloadCmailMsgProc},
563 {"----", NothingProc},
564 {N_("Exit"), QuitProc},
568 MenuItem modeMenu[] = {
569 {N_("Machine White"), MachineWhiteProc},
570 {N_("Machine Black"), MachineBlackProc},
571 {N_("Two Machines"), TwoMachinesProc},
572 {N_("Analysis Mode"), AnalyzeModeProc},
573 {N_("Analyze File"), AnalyzeFileProc },
574 {N_("ICS Client"), IcsClientProc},
575 {N_("Edit Game"), EditGameProc},
576 {N_("Edit Position"), EditPositionProc},
577 {N_("Training"), TrainingProc},
578 {"----", NothingProc},
579 {N_("Show Engine Output"), EngineOutputProc},
580 {N_("Show Evaluation Graph"), NothingProc}, // [HGM] evalgr: not functional yet
581 {N_("Show Game List"), ShowGameListProc},
582 {"Show Move History", HistoryShowProc}, // [HGM] hist: activate 4.2.7 code
583 {"----", NothingProc},
584 {N_("Edit Tags"), EditTagsProc},
585 {N_("Edit Comment"), EditCommentProc},
586 {N_("ICS Input Box"), IcsInputBoxProc},
587 {N_("Pause"), PauseProc},
591 MenuItem actionMenu[] = {
592 {N_("Accept"), AcceptProc},
593 {N_("Decline"), DeclineProc},
594 {N_("Rematch"), RematchProc},
595 {"----", NothingProc},
596 {N_("Call Flag"), CallFlagProc},
597 {N_("Draw"), DrawProc},
598 {N_("Adjourn"), AdjournProc},
599 {N_("Abort"), AbortProc},
600 {N_("Resign"), ResignProc},
601 {"----", NothingProc},
602 {N_("Stop Observing"), StopObservingProc},
603 {N_("Stop Examining"), StopExaminingProc},
607 MenuItem stepMenu[] = {
608 {N_("Backward"), BackwardProc},
609 {N_("Forward"), ForwardProc},
610 {N_("Back to Start"), ToStartProc},
611 {N_("Forward to End"), ToEndProc},
612 {N_("Revert"), RevertProc},
613 {N_("Truncate Game"), TruncateGameProc},
614 {"----", NothingProc},
615 {N_("Move Now"), MoveNowProc},
616 {N_("Retract Move"), RetractMoveProc},
620 MenuItem optionsMenu[] = {
621 {N_("Flip View"), FlipViewProc},
622 {"----", NothingProc},
623 {N_("Adjudications ..."), EngineMenuProc},
624 {N_("General Settings ..."), UciMenuProc},
625 {N_("Engine #1 Settings ..."), FirstSettingsProc},
626 {N_("Engine #2 Settings ..."), SecondSettingsProc},
627 {N_("Time Control ..."), TimeControlProc},
628 {"----", NothingProc},
629 {N_("Always Queen"), AlwaysQueenProc},
630 {N_("Animate Dragging"), AnimateDraggingProc},
631 {N_("Animate Moving"), AnimateMovingProc},
632 {N_("Auto Comment"), AutocommProc},
633 {N_("Auto Flag"), AutoflagProc},
634 {N_("Auto Flip View"), AutoflipProc},
635 {N_("Auto Observe"), AutobsProc},
636 {N_("Auto Raise Board"), AutoraiseProc},
637 {N_("Auto Save"), AutosaveProc},
638 {N_("Blindfold"), BlindfoldProc},
639 {N_("Flash Moves"), FlashMovesProc},
640 {N_("Get Move List"), GetMoveListProc},
642 {N_("Highlight Dragging"), HighlightDraggingProc},
644 {N_("Highlight Last Move"), HighlightLastMoveProc},
645 {N_("Move Sound"), MoveSoundProc},
646 {N_("ICS Alarm"), IcsAlarmProc},
647 {N_("Old Save Style"), OldSaveStyleProc},
648 {N_("Periodic Updates"), PeriodicUpdatesProc},
649 {N_("Ponder Next Move"), PonderNextMoveProc},
650 {N_("Popup Exit Message"), PopupExitMessageProc},
651 {N_("Popup Move Errors"), PopupMoveErrorsProc},
652 {N_("Premove"), PremoveProc},
653 {N_("Quiet Play"), QuietPlayProc},
654 {N_("Show Coords"), ShowCoordsProc},
655 {N_("Hide Thinking"), HideThinkingProc},
656 {N_("Test Legality"), TestLegalityProc},
660 MenuItem helpMenu[] = {
661 {N_("Info XBoard"), InfoProc},
662 {N_("Man XBoard"), ManProc},
663 {"----", NothingProc},
664 {N_("Hint"), HintProc},
665 {N_("Book"), BookProc},
666 {"----", NothingProc},
667 {N_("About XBoard"), AboutProc},
672 {N_("File"), fileMenu},
673 {N_("Mode"), modeMenu},
674 {N_("Action"), actionMenu},
675 {N_("Step"), stepMenu},
676 {N_("Options"), optionsMenu},
677 {N_("Help"), helpMenu},
681 #define PAUSE_BUTTON N_("P")
682 MenuItem buttonBar[] = {
685 {PAUSE_BUTTON, PauseProc},
691 #define PIECE_MENU_SIZE 11
692 String pieceMenuStrings[2][PIECE_MENU_SIZE] = {
693 { N_("White"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
694 N_("Queen"), N_("King"), "----", N_("Empty square"), N_("Clear board") },
695 { N_("Black"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
696 N_("Queen"), N_("King"), "----", N_("Empty square"), N_("Clear board") },
698 /* must be in same order as PieceMenuStrings! */
699 ChessSquare pieceMenuTranslation[2][PIECE_MENU_SIZE] = {
700 { WhitePlay, (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
701 WhiteRook, WhiteQueen, WhiteKing,
702 (ChessSquare) 0, EmptySquare, ClearBoard },
703 { BlackPlay, (ChessSquare) 0, BlackPawn, BlackKnight, BlackBishop,
704 BlackRook, BlackQueen, BlackKing,
705 (ChessSquare) 0, EmptySquare, ClearBoard },
708 #define DROP_MENU_SIZE 6
709 String dropMenuStrings[DROP_MENU_SIZE] = {
710 "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"), N_("Queen")
712 /* must be in same order as PieceMenuStrings! */
713 ChessSquare dropMenuTranslation[DROP_MENU_SIZE] = {
714 (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
715 WhiteRook, WhiteQueen
723 DropMenuEnables dmEnables[] = {
741 { XtNborderWidth, 0 },
742 { XtNdefaultDistance, 0 },
746 { XtNborderWidth, 0 },
747 { XtNresizable, (XtArgVal) True },
751 { XtNborderWidth, 0 },
757 { XtNjustify, (XtArgVal) XtJustifyRight },
758 { XtNlabel, (XtArgVal) "..." },
759 { XtNresizable, (XtArgVal) True },
760 { XtNresize, (XtArgVal) False }
763 Arg messageArgs[] = {
764 { XtNjustify, (XtArgVal) XtJustifyLeft },
765 { XtNlabel, (XtArgVal) "..." },
766 { XtNresizable, (XtArgVal) True },
767 { XtNresize, (XtArgVal) False }
771 { XtNborderWidth, 0 },
772 { XtNjustify, (XtArgVal) XtJustifyLeft }
775 XtResource clientResources[] = {
776 { "whitePieceColor", "whitePieceColor", XtRString, sizeof(String),
777 XtOffset(AppDataPtr, whitePieceColor), XtRString,
779 { "blackPieceColor", "blackPieceColor", XtRString, sizeof(String),
780 XtOffset(AppDataPtr, blackPieceColor), XtRString,
782 { "lightSquareColor", "lightSquareColor", XtRString,
783 sizeof(String), XtOffset(AppDataPtr, lightSquareColor),
784 XtRString, LIGHT_SQUARE_COLOR },
785 { "darkSquareColor", "darkSquareColor", XtRString, sizeof(String),
786 XtOffset(AppDataPtr, darkSquareColor), XtRString,
788 { "highlightSquareColor", "highlightSquareColor", XtRString,
789 sizeof(String), XtOffset(AppDataPtr, highlightSquareColor),
790 XtRString, HIGHLIGHT_SQUARE_COLOR },
791 { "premoveHighlightColor", "premoveHighlightColor", XtRString,
792 sizeof(String), XtOffset(AppDataPtr, premoveHighlightColor),
793 XtRString, PREMOVE_HIGHLIGHT_COLOR },
794 { "movesPerSession", "movesPerSession", XtRInt, sizeof(int),
795 XtOffset(AppDataPtr, movesPerSession), XtRImmediate,
796 (XtPointer) MOVES_PER_SESSION },
797 { "timeIncrement", "timeIncrement", XtRInt, sizeof(int),
798 XtOffset(AppDataPtr, timeIncrement), XtRImmediate,
799 (XtPointer) TIME_INCREMENT },
800 { "initString", "initString", XtRString, sizeof(String),
801 XtOffset(AppDataPtr, initString), XtRString, INIT_STRING },
802 { "secondInitString", "secondInitString", XtRString, sizeof(String),
803 XtOffset(AppDataPtr, secondInitString), XtRString, INIT_STRING },
804 { "firstComputerString", "firstComputerString", XtRString,
805 sizeof(String), XtOffset(AppDataPtr, firstComputerString), XtRString,
807 { "secondComputerString", "secondComputerString", XtRString,
808 sizeof(String), XtOffset(AppDataPtr, secondComputerString), XtRString,
810 { "firstChessProgram", "firstChessProgram", XtRString,
811 sizeof(String), XtOffset(AppDataPtr, firstChessProgram),
812 XtRString, FIRST_CHESS_PROGRAM },
813 { "secondChessProgram", "secondChessProgram", XtRString,
814 sizeof(String), XtOffset(AppDataPtr, secondChessProgram),
815 XtRString, SECOND_CHESS_PROGRAM },
816 { "firstPlaysBlack", "firstPlaysBlack", XtRBoolean,
817 sizeof(Boolean), XtOffset(AppDataPtr, firstPlaysBlack),
818 XtRImmediate, (XtPointer) False },
819 { "noChessProgram", "noChessProgram", XtRBoolean,
820 sizeof(Boolean), XtOffset(AppDataPtr, noChessProgram),
821 XtRImmediate, (XtPointer) False },
822 { "firstHost", "firstHost", XtRString, sizeof(String),
823 XtOffset(AppDataPtr, firstHost), XtRString, FIRST_HOST },
824 { "secondHost", "secondHost", XtRString, sizeof(String),
825 XtOffset(AppDataPtr, secondHost), XtRString, SECOND_HOST },
826 { "firstDirectory", "firstDirectory", XtRString, sizeof(String),
827 XtOffset(AppDataPtr, firstDirectory), XtRString, "." },
828 { "secondDirectory", "secondDirectory", XtRString, sizeof(String),
829 XtOffset(AppDataPtr, secondDirectory), XtRString, "." },
830 { "bitmapDirectory", "bitmapDirectory", XtRString,
831 sizeof(String), XtOffset(AppDataPtr, bitmapDirectory),
833 { "remoteShell", "remoteShell", XtRString, sizeof(String),
834 XtOffset(AppDataPtr, remoteShell), XtRString, REMOTE_SHELL },
835 { "remoteUser", "remoteUser", XtRString, sizeof(String),
836 XtOffset(AppDataPtr, remoteUser), XtRString, "" },
837 { "timeDelay", "timeDelay", XtRFloat, sizeof(float),
838 XtOffset(AppDataPtr, timeDelay), XtRString,
839 (XtPointer) TIME_DELAY_QUOTE },
840 { "timeControl", "timeControl", XtRString, sizeof(String),
841 XtOffset(AppDataPtr, timeControl), XtRString,
842 (XtPointer) TIME_CONTROL },
843 { "internetChessServerMode", "internetChessServerMode",
844 XtRBoolean, sizeof(Boolean),
845 XtOffset(AppDataPtr, icsActive), XtRImmediate,
847 { "internetChessServerHost", "internetChessServerHost",
848 XtRString, sizeof(String),
849 XtOffset(AppDataPtr, icsHost),
850 XtRString, (XtPointer) ICS_HOST },
851 { "internetChessServerPort", "internetChessServerPort",
852 XtRString, sizeof(String),
853 XtOffset(AppDataPtr, icsPort), XtRString,
854 (XtPointer) ICS_PORT },
855 { "internetChessServerCommPort", "internetChessServerCommPort",
856 XtRString, sizeof(String),
857 XtOffset(AppDataPtr, icsCommPort), XtRString,
859 { "internetChessServerLogonScript", "internetChessServerLogonScript",
860 XtRString, sizeof(String),
861 XtOffset(AppDataPtr, icsLogon), XtRString,
863 { "internetChessServerHelper", "internetChessServerHelper",
864 XtRString, sizeof(String),
865 XtOffset(AppDataPtr, icsHelper), XtRString, "" },
866 { "internetChessServerInputBox", "internetChessServerInputBox",
867 XtRBoolean, sizeof(Boolean),
868 XtOffset(AppDataPtr, icsInputBox), XtRImmediate,
870 { "icsAlarm", "icsAlarm",
871 XtRBoolean, sizeof(Boolean),
872 XtOffset(AppDataPtr, icsAlarm), XtRImmediate,
874 { "icsAlarmTime", "icsAlarmTime",
876 XtOffset(AppDataPtr, icsAlarmTime), XtRImmediate,
878 { "useTelnet", "useTelnet", XtRBoolean, sizeof(Boolean),
879 XtOffset(AppDataPtr, useTelnet), XtRImmediate,
881 { "telnetProgram", "telnetProgram", XtRString, sizeof(String),
882 XtOffset(AppDataPtr, telnetProgram), XtRString, TELNET_PROGRAM },
883 { "gateway", "gateway", XtRString, sizeof(String),
884 XtOffset(AppDataPtr, gateway), XtRString, "" },
885 { "loadGameFile", "loadGameFile", XtRString, sizeof(String),
886 XtOffset(AppDataPtr, loadGameFile), XtRString, "" },
887 { "loadGameIndex", "loadGameIndex",
889 XtOffset(AppDataPtr, loadGameIndex), XtRImmediate,
891 { "saveGameFile", "saveGameFile", XtRString, sizeof(String),
892 XtOffset(AppDataPtr, saveGameFile), XtRString, "" },
893 { "autoRaiseBoard", "autoRaiseBoard", XtRBoolean,
894 sizeof(Boolean), XtOffset(AppDataPtr, autoRaiseBoard),
895 XtRImmediate, (XtPointer) True },
896 { "autoSaveGames", "autoSaveGames", XtRBoolean,
897 sizeof(Boolean), XtOffset(AppDataPtr, autoSaveGames),
898 XtRImmediate, (XtPointer) False },
899 { "blindfold", "blindfold", XtRBoolean,
900 sizeof(Boolean), XtOffset(AppDataPtr, blindfold),
901 XtRImmediate, (XtPointer) False },
902 { "loadPositionFile", "loadPositionFile", XtRString,
903 sizeof(String), XtOffset(AppDataPtr, loadPositionFile),
905 { "loadPositionIndex", "loadPositionIndex",
907 XtOffset(AppDataPtr, loadPositionIndex), XtRImmediate,
909 { "savePositionFile", "savePositionFile", XtRString,
910 sizeof(String), XtOffset(AppDataPtr, savePositionFile),
912 { "matchMode", "matchMode", XtRBoolean, sizeof(Boolean),
913 XtOffset(AppDataPtr, matchMode), XtRImmediate, (XtPointer) False },
914 { "matchGames", "matchGames", XtRInt, sizeof(int),
915 XtOffset(AppDataPtr, matchGames), XtRImmediate,
917 { "monoMode", "monoMode", XtRBoolean, sizeof(Boolean),
918 XtOffset(AppDataPtr, monoMode), XtRImmediate,
920 { "debugMode", "debugMode", XtRBoolean, sizeof(Boolean),
921 XtOffset(AppDataPtr, debugMode), XtRImmediate,
923 { "clockMode", "clockMode", XtRBoolean, sizeof(Boolean),
924 XtOffset(AppDataPtr, clockMode), XtRImmediate,
926 { "boardSize", "boardSize", XtRString, sizeof(String),
927 XtOffset(AppDataPtr, boardSize), XtRString, "" },
928 { "searchTime", "searchTime", XtRString, sizeof(String),
929 XtOffset(AppDataPtr, searchTime), XtRString,
931 { "searchDepth", "searchDepth", XtRInt, sizeof(int),
932 XtOffset(AppDataPtr, searchDepth), XtRImmediate,
934 { "showCoords", "showCoords", XtRBoolean, sizeof(Boolean),
935 XtOffset(AppDataPtr, showCoords), XtRImmediate,
937 { "showJail", "showJail", XtRInt, sizeof(int),
938 XtOffset(AppDataPtr, showJail), XtRImmediate,
940 { "showThinking", "showThinking", XtRBoolean, sizeof(Boolean),
941 XtOffset(AppDataPtr, showThinking), XtRImmediate,
943 { "ponderNextMove", "ponderNextMove", XtRBoolean, sizeof(Boolean),
944 XtOffset(AppDataPtr, ponderNextMove), XtRImmediate,
946 { "periodicUpdates", "periodicUpdates", XtRBoolean, sizeof(Boolean),
947 XtOffset(AppDataPtr, periodicUpdates), XtRImmediate,
949 { "clockFont", "clockFont", XtRString, sizeof(String),
950 XtOffset(AppDataPtr, clockFont), XtRString, CLOCK_FONT },
951 { "coordFont", "coordFont", XtRString, sizeof(String),
952 XtOffset(AppDataPtr, coordFont), XtRString, COORD_FONT },
953 { "font", "font", XtRString, sizeof(String),
954 XtOffset(AppDataPtr, font), XtRString, DEFAULT_FONT },
955 { "ringBellAfterMoves", "ringBellAfterMoves",
956 XtRBoolean, sizeof(Boolean),
957 XtOffset(AppDataPtr, ringBellAfterMoves),
958 XtRImmediate, (XtPointer) False },
959 { "autoCallFlag", "autoCallFlag", XtRBoolean,
960 sizeof(Boolean), XtOffset(AppDataPtr, autoCallFlag),
961 XtRImmediate, (XtPointer) False },
962 { "autoFlipView", "autoFlipView", XtRBoolean,
963 sizeof(Boolean), XtOffset(AppDataPtr, autoFlipView),
964 XtRImmediate, (XtPointer) True },
965 { "autoObserve", "autoObserve", XtRBoolean,
966 sizeof(Boolean), XtOffset(AppDataPtr, autoObserve),
967 XtRImmediate, (XtPointer) False },
968 { "autoComment", "autoComment", XtRBoolean,
969 sizeof(Boolean), XtOffset(AppDataPtr, autoComment),
970 XtRImmediate, (XtPointer) False },
971 { "getMoveList", "getMoveList", XtRBoolean,
972 sizeof(Boolean), XtOffset(AppDataPtr, getMoveList),
973 XtRImmediate, (XtPointer) True },
975 { "highlightDragging", "highlightDragging", XtRBoolean,
976 sizeof(Boolean), XtOffset(AppDataPtr, highlightDragging),
977 XtRImmediate, (XtPointer) False },
979 { "highlightLastMove", "highlightLastMove", XtRBoolean,
980 sizeof(Boolean), XtOffset(AppDataPtr, highlightLastMove),
981 XtRImmediate, (XtPointer) False },
982 { "premove", "premove", XtRBoolean,
983 sizeof(Boolean), XtOffset(AppDataPtr, premove),
984 XtRImmediate, (XtPointer) True },
985 { "testLegality", "testLegality", XtRBoolean,
986 sizeof(Boolean), XtOffset(AppDataPtr, testLegality),
987 XtRImmediate, (XtPointer) True },
988 { "flipView", "flipView", XtRBoolean,
989 sizeof(Boolean), XtOffset(AppDataPtr, flipView),
990 XtRImmediate, (XtPointer) False },
991 { "cmail", "cmailGameName", XtRString, sizeof(String),
992 XtOffset(AppDataPtr, cmailGameName), XtRString, "" },
993 { "alwaysPromoteToQueen", "alwaysPromoteToQueen", XtRBoolean,
994 sizeof(Boolean), XtOffset(AppDataPtr, alwaysPromoteToQueen),
995 XtRImmediate, (XtPointer) False },
996 { "oldSaveStyle", "oldSaveStyle", XtRBoolean,
997 sizeof(Boolean), XtOffset(AppDataPtr, oldSaveStyle),
998 XtRImmediate, (XtPointer) False },
999 { "quietPlay", "quietPlay", XtRBoolean,
1000 sizeof(Boolean), XtOffset(AppDataPtr, quietPlay),
1001 XtRImmediate, (XtPointer) False },
1002 { "titleInWindow", "titleInWindow", XtRBoolean,
1003 sizeof(Boolean), XtOffset(AppDataPtr, titleInWindow),
1004 XtRImmediate, (XtPointer) False },
1005 { "localLineEditing", "localLineEditing", XtRBoolean,
1006 sizeof(Boolean), XtOffset(AppDataPtr, localLineEditing),
1007 XtRImmediate, (XtPointer) True }, /* not implemented, must be True */
1009 { "zippyTalk", "zippyTalk", XtRBoolean,
1010 sizeof(Boolean), XtOffset(AppDataPtr, zippyTalk),
1011 XtRImmediate, (XtPointer) ZIPPY_TALK },
1012 { "zippyPlay", "zippyPlay", XtRBoolean,
1013 sizeof(Boolean), XtOffset(AppDataPtr, zippyPlay),
1014 XtRImmediate, (XtPointer) ZIPPY_PLAY },
1015 { "zippyLines", "zippyLines", XtRString, sizeof(String),
1016 XtOffset(AppDataPtr, zippyLines), XtRString, ZIPPY_LINES },
1017 { "zippyPinhead", "zippyPinhead", XtRString, sizeof(String),
1018 XtOffset(AppDataPtr, zippyPinhead), XtRString, ZIPPY_PINHEAD },
1019 { "zippyPassword", "zippyPassword", XtRString, sizeof(String),
1020 XtOffset(AppDataPtr, zippyPassword), XtRString, ZIPPY_PASSWORD },
1021 { "zippyPassword2", "zippyPassword2", XtRString, sizeof(String),
1022 XtOffset(AppDataPtr, zippyPassword2), XtRString, ZIPPY_PASSWORD2 },
1023 { "zippyWrongPassword", "zippyWrongPassword", XtRString, sizeof(String),
1024 XtOffset(AppDataPtr, zippyWrongPassword), XtRString,
1025 ZIPPY_WRONG_PASSWORD },
1026 { "zippyAcceptOnly", "zippyAcceptOnly", XtRString, sizeof(String),
1027 XtOffset(AppDataPtr, zippyAcceptOnly), XtRString, ZIPPY_ACCEPT_ONLY },
1028 { "zippyUseI", "zippyUseI", XtRBoolean,
1029 sizeof(Boolean), XtOffset(AppDataPtr, zippyUseI),
1030 XtRImmediate, (XtPointer) ZIPPY_USE_I },
1031 { "zippyBughouse", "zippyBughouse", XtRInt,
1032 sizeof(int), XtOffset(AppDataPtr, zippyBughouse),
1033 XtRImmediate, (XtPointer) ZIPPY_BUGHOUSE },
1034 { "zippyNoplayCrafty", "zippyNoplayCrafty", XtRBoolean,
1035 sizeof(Boolean), XtOffset(AppDataPtr, zippyNoplayCrafty),
1036 XtRImmediate, (XtPointer) ZIPPY_NOPLAY_CRAFTY },
1037 { "zippyGameEnd", "zippyGameEnd", XtRString, sizeof(String),
1038 XtOffset(AppDataPtr, zippyGameEnd), XtRString, ZIPPY_GAME_END },
1039 { "zippyGameStart", "zippyGameStart", XtRString, sizeof(String),
1040 XtOffset(AppDataPtr, zippyGameStart), XtRString, ZIPPY_GAME_START },
1041 { "zippyAdjourn", "zippyAdjourn", XtRBoolean,
1042 sizeof(Boolean), XtOffset(AppDataPtr, zippyAdjourn),
1043 XtRImmediate, (XtPointer) ZIPPY_ADJOURN },
1044 { "zippyAbort", "zippyAbort", XtRBoolean,
1045 sizeof(Boolean), XtOffset(AppDataPtr, zippyAbort),
1046 XtRImmediate, (XtPointer) ZIPPY_ABORT },
1047 { "zippyVariants", "zippyVariants", XtRString, sizeof(String),
1048 XtOffset(AppDataPtr, zippyVariants), XtRString, ZIPPY_VARIANTS },
1049 { "zippyMaxGames", "zippyMaxGames", XtRInt, sizeof(int),
1050 XtOffset(AppDataPtr, zippyMaxGames), XtRImmediate,
1051 (XtPointer) ZIPPY_MAX_GAMES },
1052 { "zippyReplayTimeout", "zippyReplayTimeout", XtRInt, sizeof(int),
1053 XtOffset(AppDataPtr, zippyReplayTimeout), XtRImmediate,
1054 (XtPointer) ZIPPY_REPLAY_TIMEOUT },
1056 { "flashCount", "flashCount", XtRInt, sizeof(int),
1057 XtOffset(AppDataPtr, flashCount), XtRImmediate,
1058 (XtPointer) FLASH_COUNT },
1059 { "flashRate", "flashRate", XtRInt, sizeof(int),
1060 XtOffset(AppDataPtr, flashRate), XtRImmediate,
1061 (XtPointer) FLASH_RATE },
1062 { "pixmapDirectory", "pixmapDirectory", XtRString,
1063 sizeof(String), XtOffset(AppDataPtr, pixmapDirectory),
1065 { "msLoginDelay", "msLoginDelay", XtRInt, sizeof(int),
1066 XtOffset(AppDataPtr, msLoginDelay), XtRImmediate,
1067 (XtPointer) MS_LOGIN_DELAY },
1068 { "colorizeMessages", "colorizeMessages", XtRBoolean,
1069 sizeof(Boolean), XtOffset(AppDataPtr, colorize),
1070 XtRImmediate, (XtPointer) False },
1071 { "colorShout", "colorShout", XtRString,
1072 sizeof(String), XtOffset(AppDataPtr, colorShout),
1073 XtRString, COLOR_SHOUT },
1074 { "colorSShout", "colorSShout", XtRString,
1075 sizeof(String), XtOffset(AppDataPtr, colorSShout),
1076 XtRString, COLOR_SSHOUT },
1077 { "colorChannel1", "colorChannel1", XtRString,
1078 sizeof(String), XtOffset(AppDataPtr, colorChannel1),
1079 XtRString, COLOR_CHANNEL1 },
1080 { "colorChannel", "colorChannel", XtRString,
1081 sizeof(String), XtOffset(AppDataPtr, colorChannel),
1082 XtRString, COLOR_CHANNEL },
1083 { "colorKibitz", "colorKibitz", XtRString,
1084 sizeof(String), XtOffset(AppDataPtr, colorKibitz),
1085 XtRString, COLOR_KIBITZ },
1086 { "colorTell", "colorTell", XtRString,
1087 sizeof(String), XtOffset(AppDataPtr, colorTell),
1088 XtRString, COLOR_TELL },
1089 { "colorChallenge", "colorChallenge", XtRString,
1090 sizeof(String), XtOffset(AppDataPtr, colorChallenge),
1091 XtRString, COLOR_CHALLENGE },
1092 { "colorRequest", "colorRequest", XtRString,
1093 sizeof(String), XtOffset(AppDataPtr, colorRequest),
1094 XtRString, COLOR_REQUEST },
1095 { "colorSeek", "colorSeek", XtRString,
1096 sizeof(String), XtOffset(AppDataPtr, colorSeek),
1097 XtRString, COLOR_SEEK },
1098 { "colorNormal", "colorNormal", XtRString,
1099 sizeof(String), XtOffset(AppDataPtr, colorNormal),
1100 XtRString, COLOR_NORMAL },
1101 { "soundProgram", "soundProgram", XtRString,
1102 sizeof(String), XtOffset(AppDataPtr, soundProgram),
1103 XtRString, "play" },
1104 { "soundShout", "soundShout", XtRString,
1105 sizeof(String), XtOffset(AppDataPtr, soundShout),
1107 { "soundSShout", "soundSShout", XtRString,
1108 sizeof(String), XtOffset(AppDataPtr, soundSShout),
1110 { "soundChannel1", "soundChannel1", XtRString,
1111 sizeof(String), XtOffset(AppDataPtr, soundChannel1),
1113 { "soundChannel", "soundChannel", XtRString,
1114 sizeof(String), XtOffset(AppDataPtr, soundChannel),
1116 { "soundKibitz", "soundKibitz", XtRString,
1117 sizeof(String), XtOffset(AppDataPtr, soundKibitz),
1119 { "soundTell", "soundTell", XtRString,
1120 sizeof(String), XtOffset(AppDataPtr, soundTell),
1122 { "soundChallenge", "soundChallenge", XtRString,
1123 sizeof(String), XtOffset(AppDataPtr, soundChallenge),
1125 { "soundRequest", "soundRequest", XtRString,
1126 sizeof(String), XtOffset(AppDataPtr, soundRequest),
1128 { "soundSeek", "soundSeek", XtRString,
1129 sizeof(String), XtOffset(AppDataPtr, soundSeek),
1131 { "soundMove", "soundMove", XtRString,
1132 sizeof(String), XtOffset(AppDataPtr, soundMove),
1134 { "soundIcsWin", "soundIcsWin", XtRString,
1135 sizeof(String), XtOffset(AppDataPtr, soundIcsWin),
1137 { "soundIcsLoss", "soundIcsLoss", XtRString,
1138 sizeof(String), XtOffset(AppDataPtr, soundIcsLoss),
1140 { "soundIcsDraw", "soundIcsDraw", XtRString,
1141 sizeof(String), XtOffset(AppDataPtr, soundIcsDraw),
1143 { "soundIcsUnfinished", "soundIcsUnfinished", XtRString,
1144 sizeof(String), XtOffset(AppDataPtr, soundIcsUnfinished),
1146 { "soundIcsAlarm", "soundIcsAlarm", XtRString,
1147 sizeof(String), XtOffset(AppDataPtr, soundIcsAlarm),
1149 { "reuseFirst", "reuseFirst", XtRBoolean,
1150 sizeof(Boolean), XtOffset(AppDataPtr, reuseFirst),
1151 XtRImmediate, (XtPointer) True },
1152 { "reuseSecond", "reuseSecond", XtRBoolean,
1153 sizeof(Boolean), XtOffset(AppDataPtr, reuseSecond),
1154 XtRImmediate, (XtPointer) True },
1155 { "animateDragging", "animateDragging", XtRBoolean,
1156 sizeof(Boolean), XtOffset(AppDataPtr, animateDragging),
1157 XtRImmediate, (XtPointer) True },
1158 { "animateMoving", "animateMoving", XtRBoolean,
1159 sizeof(Boolean), XtOffset(AppDataPtr, animate),
1160 XtRImmediate, (XtPointer) True },
1161 { "animateSpeed", "animateSpeed", XtRInt,
1162 sizeof(int), XtOffset(AppDataPtr, animSpeed),
1163 XtRImmediate, (XtPointer)10 },
1164 { "popupExitMessage", "popupExitMessage", XtRBoolean,
1165 sizeof(Boolean), XtOffset(AppDataPtr, popupExitMessage),
1166 XtRImmediate, (XtPointer) True },
1167 { "popupMoveErrors", "popupMoveErrors", XtRBoolean,
1168 sizeof(Boolean), XtOffset(AppDataPtr, popupMoveErrors),
1169 XtRImmediate, (XtPointer) False },
1170 { "fontSizeTolerance", "fontSizeTolerance", XtRInt,
1171 sizeof(int), XtOffset(AppDataPtr, fontSizeTolerance),
1172 XtRImmediate, (XtPointer)4 },
1173 { "initialMode", "initialMode", XtRString,
1174 sizeof(String), XtOffset(AppDataPtr, initialMode),
1175 XtRImmediate, (XtPointer) "" },
1176 { "variant", "variant", XtRString,
1177 sizeof(String), XtOffset(AppDataPtr, variant),
1178 XtRImmediate, (XtPointer) "normal" },
1179 { "firstProtocolVersion", "firstProtocolVersion", XtRInt,
1180 sizeof(int), XtOffset(AppDataPtr, firstProtocolVersion),
1181 XtRImmediate, (XtPointer)PROTOVER },
1182 { "secondProtocolVersion", "secondProtocolVersion", XtRInt,
1183 sizeof(int), XtOffset(AppDataPtr, secondProtocolVersion),
1184 XtRImmediate, (XtPointer)PROTOVER },
1185 { "showButtonBar", "showButtonBar", XtRBoolean,
1186 sizeof(Boolean), XtOffset(AppDataPtr, showButtonBar),
1187 XtRImmediate, (XtPointer) True },
1188 {"icsEngineAnalyze", "icsEngineAnalyze", XtRBoolean, /* [DM] icsEngineAnalyze */
1189 sizeof(Boolean), XtOffset(AppDataPtr, icsEngineAnalyze),
1190 XtRImmediate, (XtPointer) False },
1191 { "firstScoreAbs", "firstScoreAbs", XtRBoolean,
1192 sizeof(Boolean), XtOffset(AppDataPtr, firstScoreIsAbsolute),
1193 XtRImmediate, (XtPointer) False },
1194 { "secondScoreAbs", "secondScoreAbs", XtRBoolean,
1195 sizeof(Boolean), XtOffset(AppDataPtr, secondScoreIsAbsolute),
1196 XtRImmediate, (XtPointer) False },
1197 { "pgnExtendedInfo", "pgnExtendedInfo", XtRBoolean,
1198 sizeof(Boolean), XtOffset(AppDataPtr, saveExtendedInfoInPGN),
1199 XtRImmediate, (XtPointer) False },
1200 { "hideThinkingFromHuman", "hideThinkingFromHuman", XtRBoolean,
1201 sizeof(Boolean), XtOffset(AppDataPtr, hideThinkingFromHuman),
1202 XtRImmediate, (XtPointer) True },
1203 { "adjudicateLossThreshold", "adjudicateLossThreshold", XtRInt,
1204 sizeof(int), XtOffset(AppDataPtr, adjudicateLossThreshold),
1205 XtRImmediate, (XtPointer) 0},
1206 { "pgnEventHeader", "pgnEventHeader", XtRString,
1207 sizeof(String), XtOffset(AppDataPtr, pgnEventHeader),
1208 XtRImmediate, (XtPointer) "Computer Chess Game" },
1209 { "defaultFrcPosition", "defaultFrcPositon", XtRInt,
1210 sizeof(int), XtOffset(AppDataPtr, defaultFrcPosition),
1211 XtRImmediate, (XtPointer) -1},
1213 // [HGM] 4.3.xx options
1214 { "boardWidth", "boardWidth", XtRInt,
1215 sizeof(int), XtOffset(AppDataPtr, NrFiles),
1216 XtRImmediate, (XtPointer) -1},
1217 { "boardHeight", "boardHeight", XtRInt,
1218 sizeof(int), XtOffset(AppDataPtr, NrRanks),
1219 XtRImmediate, (XtPointer) -1},
1220 { "matchPause", "matchPause", XtRInt,
1221 sizeof(int), XtOffset(AppDataPtr, matchPause),
1222 XtRImmediate, (XtPointer) 10000},
1223 { "holdingsSize", "holdingsSize", XtRInt,
1224 sizeof(int), XtOffset(AppDataPtr, holdingsSize),
1225 XtRImmediate, (XtPointer) -1},
1226 { "flipBlack", "flipBlack", XtRBoolean,
1227 sizeof(Boolean), XtOffset(AppDataPtr, upsideDown),
1228 XtRImmediate, (XtPointer) False},
1229 { "allWhite", "allWhite", XtRBoolean,
1230 sizeof(Boolean), XtOffset(AppDataPtr, allWhite),
1231 XtRImmediate, (XtPointer) False},
1232 { "pieceToCharTable", "pieceToCharTable", XtRString,
1233 sizeof(String), XtOffset(AppDataPtr, pieceToCharTable),
1234 XtRImmediate, (XtPointer) 0},
1235 { "alphaRank", "alphaRank", XtRBoolean,
1236 sizeof(Boolean), XtOffset(AppDataPtr, alphaRank),
1237 XtRImmediate, (XtPointer) False},
1238 { "testClaims", "testClaims", XtRBoolean,
1239 sizeof(Boolean), XtOffset(AppDataPtr, testClaims),
1240 XtRImmediate, (XtPointer) True},
1241 { "checkMates", "checkMates", XtRBoolean,
1242 sizeof(Boolean), XtOffset(AppDataPtr, checkMates),
1243 XtRImmediate, (XtPointer) True},
1244 { "materialDraws", "materialDraws", XtRBoolean,
1245 sizeof(Boolean), XtOffset(AppDataPtr, materialDraws),
1246 XtRImmediate, (XtPointer) True},
1247 { "trivialDraws", "trivialDraws", XtRBoolean,
1248 sizeof(Boolean), XtOffset(AppDataPtr, trivialDraws),
1249 XtRImmediate, (XtPointer) False},
1250 { "ruleMoves", "ruleMoves", XtRInt,
1251 sizeof(int), XtOffset(AppDataPtr, ruleMoves),
1252 XtRImmediate, (XtPointer) 51},
1253 { "repeatsToDraw", "repeatsToDraw", XtRInt,
1254 sizeof(int), XtOffset(AppDataPtr, drawRepeats),
1255 XtRImmediate, (XtPointer) 6},
1256 { "engineDebugOutput", "engineDebugOutput", XtRInt,
1257 sizeof(int), XtOffset(AppDataPtr, engineComments),
1258 XtRImmediate, (XtPointer) 1},
1259 { "userName", "userName", XtRString,
1260 sizeof(int), XtOffset(AppDataPtr, userName),
1261 XtRImmediate, (XtPointer) 0},
1262 { "autoKibitz", "autoKibitz", XtRBoolean,
1263 sizeof(Boolean), XtOffset(AppDataPtr, autoKibitz),
1264 XtRImmediate, (XtPointer) False},
1265 { "firstTimeOdds", "firstTimeOdds", XtRInt,
1266 sizeof(int), XtOffset(AppDataPtr, firstTimeOdds),
1267 XtRImmediate, (XtPointer) 1},
1268 { "secondTimeOdds", "secondTimeOdds", XtRInt,
1269 sizeof(int), XtOffset(AppDataPtr, secondTimeOdds),
1270 XtRImmediate, (XtPointer) 1},
1271 { "timeOddsMode", "timeOddsMode", XtRInt,
1272 sizeof(int), XtOffset(AppDataPtr, timeOddsMode),
1273 XtRImmediate, (XtPointer) 0},
1274 { "firstAccumulateTC", "firstAccumulateTC", XtRInt,
1275 sizeof(int), XtOffset(AppDataPtr, firstAccumulateTC),
1276 XtRImmediate, (XtPointer) 1},
1277 { "secondAccumulateTC", "secondAccumulateTC", XtRInt,
1278 sizeof(int), XtOffset(AppDataPtr, secondAccumulateTC),
1279 XtRImmediate, (XtPointer) 1},
1280 { "firstNPS", "firstNPS", XtRInt,
1281 sizeof(int), XtOffset(AppDataPtr, firstNPS),
1282 XtRImmediate, (XtPointer) -1},
1283 { "secondNPS", "secondNPS", XtRInt,
1284 sizeof(int), XtOffset(AppDataPtr, secondNPS),
1285 XtRImmediate, (XtPointer) -1},
1286 { "serverMoves", "serverMoves", XtRString,
1287 sizeof(String), XtOffset(AppDataPtr, serverMovesName),
1288 XtRImmediate, (XtPointer) 0},
1289 { "serverPause", "serverPause", XtRInt,
1290 sizeof(int), XtOffset(AppDataPtr, serverPause),
1291 XtRImmediate, (XtPointer) 0},
1292 { "suppressLoadMoves", "suppressLoadMoves", XtRBoolean,
1293 sizeof(Boolean), XtOffset(AppDataPtr, suppressLoadMoves),
1294 XtRImmediate, (XtPointer) False},
1295 { "userName", "userName", XtRString,
1296 sizeof(String), XtOffset(AppDataPtr, userName),
1297 XtRImmediate, (XtPointer) 0},
1298 { "egtFormats", "egtFormats", XtRString,
1299 sizeof(String), XtOffset(AppDataPtr, egtFormats),
1300 XtRImmediate, (XtPointer) 0},
1301 { "rewindIndex", "rewindIndex", XtRInt,
1302 sizeof(int), XtOffset(AppDataPtr, rewindIndex),
1303 XtRImmediate, (XtPointer) 0},
1304 { "sameColorGames", "sameColorGames", XtRInt,
1305 sizeof(int), XtOffset(AppDataPtr, sameColorGames),
1306 XtRImmediate, (XtPointer) 0},
1307 { "smpCores", "smpCores", XtRInt,
1308 sizeof(int), XtOffset(AppDataPtr, smpCores),
1309 XtRImmediate, (XtPointer) 1},
1310 { "niceEngines", "niceEngines", XtRInt,
1311 sizeof(int), XtOffset(AppDataPtr, niceEngines),
1312 XtRImmediate, (XtPointer) 0},
1313 { "nameOfDebugFile", "nameOfDebugFile", XtRString,
1314 sizeof(String), XtOffset(AppDataPtr, nameOfDebugFile),
1315 XtRImmediate, (XtPointer) "xboard.debug"},
1316 { "engineDebugOutput", "engineDebugOutput", XtRInt,
1317 sizeof(int), XtOffset(AppDataPtr, engineComments),
1318 XtRImmediate, (XtPointer) 0},
1319 { "noGUI", "noGUI", XtRBoolean,
1320 sizeof(Boolean), XtOffset(AppDataPtr, noGUI),
1321 XtRImmediate, (XtPointer) 0},
1322 { "firstOptions", "firstOptions", XtRString,
1323 sizeof(String), XtOffset(AppDataPtr, firstOptions),
1324 XtRImmediate, (XtPointer) "" },
1325 { "secondOptions", "secondOptions", XtRString,
1326 sizeof(String), XtOffset(AppDataPtr, secondOptions),
1327 XtRImmediate, (XtPointer) "" },
1329 // [HGM] Winboard_x UCI options
1330 { "firstIsUCI", "firstIsUCI", XtRBoolean,
1331 sizeof(Boolean), XtOffset(AppDataPtr, firstIsUCI),
1332 XtRImmediate, (XtPointer) False},
1333 { "secondIsUCI", "secondIsUCI", XtRBoolean,
1334 sizeof(Boolean), XtOffset(AppDataPtr, secondIsUCI),
1335 XtRImmediate, (XtPointer) False},
1336 { "firstHasOwnBookUCI", "firstHasOwnBookUCI", XtRBoolean,
1337 sizeof(Boolean), XtOffset(AppDataPtr, firstHasOwnBookUCI),
1338 XtRImmediate, (XtPointer) True},
1339 { "secondHasOwnBookUCI", "secondHasOwnBookUCI", XtRBoolean,
1340 sizeof(Boolean), XtOffset(AppDataPtr, secondHasOwnBookUCI),
1341 XtRImmediate, (XtPointer) True},
1342 { "usePolyglotBook", "usePolyglotBook", XtRBoolean,
1343 sizeof(Boolean), XtOffset(AppDataPtr, usePolyglotBook),
1344 XtRImmediate, (XtPointer) False},
1345 { "defaultHashSize", "defaultHashSize", XtRInt,
1346 sizeof(int), XtOffset(AppDataPtr, defaultHashSize),
1347 XtRImmediate, (XtPointer) 64},
1348 { "defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XtRInt,
1349 sizeof(int), XtOffset(AppDataPtr, defaultCacheSizeEGTB),
1350 XtRImmediate, (XtPointer) 4},
1351 { "polyglotDir", "polyglotDir", XtRString,
1352 sizeof(String), XtOffset(AppDataPtr, polyglotDir),
1353 XtRImmediate, (XtPointer) "." },
1354 { "polyglotBook", "polyglotBook", XtRString,
1355 sizeof(String), XtOffset(AppDataPtr, polyglotBook),
1356 XtRImmediate, (XtPointer) "" },
1357 { "defaultPathEGTB", "defaultPathEGTB", XtRString,
1358 sizeof(String), XtOffset(AppDataPtr, defaultPathEGTB),
1359 XtRImmediate, (XtPointer) "/usr/local/share/egtb"},
1360 { "delayBeforeQuit", "delayBeforeQuit", XtRInt,
1361 sizeof(int), XtOffset(AppDataPtr, delayBeforeQuit),
1362 XtRImmediate, (XtPointer) 0},
1363 { "delayAfterQuit", "delayAfterQuit", XtRInt,
1364 sizeof(int), XtOffset(AppDataPtr, delayAfterQuit),
1365 XtRImmediate, (XtPointer) 0},
1368 XrmOptionDescRec shellOptions[] = {
1369 { "-whitePieceColor", "whitePieceColor", XrmoptionSepArg, NULL },
1370 { "-blackPieceColor", "blackPieceColor", XrmoptionSepArg, NULL },
1371 { "-lightSquareColor", "lightSquareColor", XrmoptionSepArg, NULL },
1372 { "-darkSquareColor", "darkSquareColor", XrmoptionSepArg, NULL },
1373 { "-highlightSquareColor", "highlightSquareColor", XrmoptionSepArg, NULL },
1374 { "-premoveHighlightColor", "premoveHighlightColor", XrmoptionSepArg,NULL},
1375 { "-movesPerSession", "movesPerSession", XrmoptionSepArg, NULL },
1376 { "-mps", "movesPerSession", XrmoptionSepArg, NULL },
1377 { "-timeIncrement", "timeIncrement", XrmoptionSepArg, NULL },
1378 { "-inc", "timeIncrement", XrmoptionSepArg, NULL },
1379 { "-initString", "initString", XrmoptionSepArg, NULL },
1380 { "-firstInitString", "initString", XrmoptionSepArg, NULL },
1381 { "-secondInitString", "secondInitString", XrmoptionSepArg, NULL },
1382 { "-firstComputerString", "firstComputerString", XrmoptionSepArg, NULL },
1383 { "-secondComputerString", "secondComputerString", XrmoptionSepArg, NULL },
1384 { "-firstChessProgram", "firstChessProgram", XrmoptionSepArg, NULL },
1385 { "-fcp", "firstChessProgram", XrmoptionSepArg, NULL },
1386 { "-secondChessProgram", "secondChessProgram", XrmoptionSepArg, NULL },
1387 { "-scp", "secondChessProgram", XrmoptionSepArg, NULL },
1388 { "-firstPlaysBlack", "firstPlaysBlack", XrmoptionSepArg, NULL },
1389 { "-fb", "firstPlaysBlack", XrmoptionNoArg, "True" },
1390 { "-xfb", "firstPlaysBlack", XrmoptionNoArg, "False" },
1391 { "-noChessProgram", "noChessProgram", XrmoptionSepArg, NULL },
1392 { "-ncp", "noChessProgram", XrmoptionNoArg, "True" },
1393 { "-xncp", "noChessProgram", XrmoptionNoArg, "False" },
1394 { "-firstHost", "firstHost", XrmoptionSepArg, NULL },
1395 { "-fh", "firstHost", XrmoptionSepArg, NULL },
1396 { "-secondHost", "secondHost", XrmoptionSepArg, NULL },
1397 { "-sh", "secondHost", XrmoptionSepArg, NULL },
1398 { "-firstDirectory", "firstDirectory", XrmoptionSepArg, NULL },
1399 { "-fd", "firstDirectory", XrmoptionSepArg, NULL },
1400 { "-secondDirectory", "secondDirectory", XrmoptionSepArg, NULL },
1401 { "-sd", "secondDirectory", XrmoptionSepArg, NULL },
1402 { "-bitmapDirectory", "bitmapDirectory", XrmoptionSepArg, NULL },
1403 { "-bm", "bitmapDirectory", XrmoptionSepArg, NULL },
1404 { "-remoteShell", "remoteShell", XrmoptionSepArg, NULL },
1405 { "-rsh", "remoteShell", XrmoptionSepArg, NULL },
1406 { "-remoteUser", "remoteUser", XrmoptionSepArg, NULL },
1407 { "-ruser", "remoteUser", XrmoptionSepArg, NULL },
1408 { "-timeDelay", "timeDelay", XrmoptionSepArg, NULL },
1409 { "-td", "timeDelay", XrmoptionSepArg, NULL },
1410 { "-timeControl", "timeControl", XrmoptionSepArg, NULL },
1411 { "-tc", "timeControl", XrmoptionSepArg, NULL },
1412 { "-internetChessServerMode", "internetChessServerMode",
1413 XrmoptionSepArg, NULL },
1414 { "-ics", "internetChessServerMode", XrmoptionNoArg, "True" },
1415 { "-xics", "internetChessServerMode", XrmoptionNoArg, "False" },
1416 { "-internetChessServerHost", "internetChessServerHost",
1417 XrmoptionSepArg, NULL },
1418 { "-icshost", "internetChessServerHost", XrmoptionSepArg, NULL },
1419 { "-internetChessServerPort", "internetChessServerPort",
1420 XrmoptionSepArg, NULL },
1421 { "-icsport", "internetChessServerPort", XrmoptionSepArg, NULL },
1422 { "-internetChessServerCommPort", "internetChessServerCommPort",
1423 XrmoptionSepArg, NULL },
1424 { "-icscomm", "internetChessServerCommPort", XrmoptionSepArg, NULL },
1425 { "-internetChessServerLogonScript", "internetChessServerLogonScript",
1426 XrmoptionSepArg, NULL },
1427 { "-icslogon", "internetChessServerLogonScript", XrmoptionSepArg, NULL },
1428 { "-internetChessServerHelper", "internetChessServerHelper",
1429 XrmoptionSepArg, NULL },
1430 { "-icshelper", "internetChessServerHelper", XrmoptionSepArg, NULL },
1431 { "-internetChessServerInputBox", "internetChessServerInputBox",
1432 XrmoptionSepArg, NULL },
1433 { "-icsinput", "internetChessServerInputBox", XrmoptionNoArg, "True" },
1434 { "-xicsinput", "internetChessServerInputBox", XrmoptionNoArg, "False" },
1435 { "-icsAlarm", "icsAlarm", XrmoptionSepArg, NULL },
1436 { "-alarm", "icsAlarm", XrmoptionNoArg, "True" },
1437 { "-xalarm", "icsAlarm", XrmoptionNoArg, "False" },
1438 { "-icsAlarmTime", "icsAlarmTime", XrmoptionSepArg, NULL },
1439 { "-useTelnet", "useTelnet", XrmoptionSepArg, NULL },
1440 { "-telnet", "useTelnet", XrmoptionNoArg, "True" },
1441 { "-xtelnet", "useTelnet", XrmoptionNoArg, "False" },
1442 { "-telnetProgram", "telnetProgram", XrmoptionSepArg, NULL },
1443 { "-gateway", "gateway", XrmoptionSepArg, NULL },
1444 { "-loadGameFile", "loadGameFile", XrmoptionSepArg, NULL },
1445 { "-lgf", "loadGameFile", XrmoptionSepArg, NULL },
1446 { "-loadGameIndex", "loadGameIndex", XrmoptionSepArg, NULL },
1447 { "-lgi", "loadGameIndex", XrmoptionSepArg, NULL },
1448 { "-saveGameFile", "saveGameFile", XrmoptionSepArg, NULL },
1449 { "-sgf", "saveGameFile", XrmoptionSepArg, NULL },
1450 { "-autoSaveGames", "autoSaveGames", XrmoptionSepArg, NULL },
1451 { "-autosave", "autoSaveGames", XrmoptionNoArg, "True" },
1452 { "-xautosave", "autoSaveGames", XrmoptionNoArg, "False" },
1453 { "-autoRaiseBoard", "autoRaiseBoard", XrmoptionSepArg, NULL },
1454 { "-autoraise", "autoRaiseBoard", XrmoptionNoArg, "True" },
1455 { "-xautoraise", "autoRaiseBoard", XrmoptionNoArg, "False" },
1456 { "-blindfold", "blindfold", XrmoptionSepArg, NULL },
1457 { "-blind", "blindfold", XrmoptionNoArg, "True" },
1458 { "-xblind", "blindfold", XrmoptionNoArg, "False" },
1459 { "-loadPositionFile", "loadPositionFile", XrmoptionSepArg, NULL },
1460 { "-lpf", "loadPositionFile", XrmoptionSepArg, NULL },
1461 { "-loadPositionIndex", "loadPositionIndex", XrmoptionSepArg, NULL },
1462 { "-lpi", "loadPositionIndex", XrmoptionSepArg, NULL },
1463 { "-savePositionFile", "savePositionFile", XrmoptionSepArg, NULL },
1464 { "-spf", "savePositionFile", XrmoptionSepArg, NULL },
1465 { "-matchMode", "matchMode", XrmoptionSepArg, NULL },
1466 { "-mm", "matchMode", XrmoptionNoArg, "True" },
1467 { "-xmm", "matchMode", XrmoptionNoArg, "False" },
1468 { "-matchGames", "matchGames", XrmoptionSepArg, NULL },
1469 { "-mg", "matchGames", XrmoptionSepArg, NULL },
1470 { "-monoMode", "monoMode", XrmoptionSepArg, NULL },
1471 { "-mono", "monoMode", XrmoptionNoArg, "True" },
1472 { "-xmono", "monoMode", XrmoptionNoArg, "False" },
1473 { "-debugMode", "debugMode", XrmoptionSepArg, NULL },
1474 { "-debug", "debugMode", XrmoptionNoArg, "True" },
1475 { "-xdebug", "debugMode", XrmoptionNoArg, "False" },
1476 { "-clockMode", "clockMode", XrmoptionSepArg, NULL },
1477 { "-clock", "clockMode", XrmoptionNoArg, "True" },
1478 { "-xclock", "clockMode", XrmoptionNoArg, "False" },
1479 { "-boardSize", "boardSize", XrmoptionSepArg, NULL },
1480 { "-size", "boardSize", XrmoptionSepArg, NULL },
1481 { "-searchTime", "searchTime", XrmoptionSepArg, NULL },
1482 { "-st", "searchTime", XrmoptionSepArg, NULL },
1483 { "-searchDepth", "searchDepth", XrmoptionSepArg, NULL },
1484 { "-depth", "searchDepth", XrmoptionSepArg, NULL },
1485 { "-showCoords", "showCoords", XrmoptionSepArg, NULL },
1486 { "-coords", "showCoords", XrmoptionNoArg, "True" },
1487 { "-xcoords", "showCoords", XrmoptionNoArg, "False" },
1489 { "-showJail", "showJail", XrmoptionSepArg, NULL },
1490 { "-jail", "showJail", XrmoptionNoArg, "1" },
1491 { "-sidejail", "showJail", XrmoptionNoArg, "2" },
1492 { "-xjail", "showJail", XrmoptionNoArg, "0" },
1494 { "-showThinking", "showThinking", XrmoptionSepArg, NULL },
1495 { "-thinking", "showThinking", XrmoptionNoArg, "True" },
1496 { "-xthinking", "showThinking", XrmoptionNoArg, "False" },
1497 { "-ponderNextMove", "ponderNextMove", XrmoptionSepArg, NULL },
1498 { "-ponder", "ponderNextMove", XrmoptionNoArg, "True" },
1499 { "-xponder", "ponderNextMove", XrmoptionNoArg, "False" },
1500 { "-periodicUpdates", "periodicUpdates", XrmoptionSepArg, NULL },
1501 { "-periodic", "periodicUpdates", XrmoptionNoArg, "True" },
1502 { "-xperiodic", "periodicUpdates", XrmoptionNoArg, "False" },
1503 { "-clockFont", "clockFont", XrmoptionSepArg, NULL },
1504 { "-coordFont", "coordFont", XrmoptionSepArg, NULL },
1505 { "-font", "font", XrmoptionSepArg, NULL },
1506 { "-ringBellAfterMoves", "ringBellAfterMoves", XrmoptionSepArg, NULL },
1507 { "-bell", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1508 { "-xbell", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1509 { "-movesound", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1510 { "-xmovesound", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1511 { "-autoCallFlag", "autoCallFlag", XrmoptionSepArg, NULL },
1512 { "-autoflag", "autoCallFlag", XrmoptionNoArg, "True" },
1513 { "-xautoflag", "autoCallFlag", XrmoptionNoArg, "False" },
1514 { "-autoFlipView", "autoFlipView", XrmoptionSepArg, NULL },
1515 { "-autoflip", "autoFlipView", XrmoptionNoArg, "True" },
1516 { "-xautoflip", "autoFlipView", XrmoptionNoArg, "False" },
1517 { "-autoObserve", "autoObserve", XrmoptionSepArg, NULL },
1518 { "-autobs", "autoObserve", XrmoptionNoArg, "True" },
1519 { "-xautobs", "autoObserve", XrmoptionNoArg, "False" },
1520 { "-autoComment", "autoComment", XrmoptionSepArg, NULL },
1521 { "-autocomm", "autoComment", XrmoptionNoArg, "True" },
1522 { "-xautocomm", "autoComment", XrmoptionNoArg, "False" },
1523 { "-getMoveList", "getMoveList", XrmoptionSepArg, NULL },
1524 { "-moves", "getMoveList", XrmoptionNoArg, "True" },
1525 { "-xmoves", "getMoveList", XrmoptionNoArg, "False" },
1527 { "-highlightDragging", "highlightDragging", XrmoptionSepArg, NULL },
1528 { "-highdrag", "highlightDragging", XrmoptionNoArg, "True" },
1529 { "-xhighdrag", "highlightDragging", XrmoptionNoArg, "False" },
1531 { "-highlightLastMove", "highlightLastMove", XrmoptionSepArg, NULL },
1532 { "-highlight", "highlightLastMove", XrmoptionNoArg, "True" },
1533 { "-xhighlight", "highlightLastMove", XrmoptionNoArg, "False" },
1534 { "-premove", "premove", XrmoptionSepArg, NULL },
1535 { "-pre", "premove", XrmoptionNoArg, "True" },
1536 { "-xpre", "premove", XrmoptionNoArg, "False" },
1537 { "-testLegality", "testLegality", XrmoptionSepArg, NULL },
1538 { "-legal", "testLegality", XrmoptionNoArg, "True" },
1539 { "-xlegal", "testLegality", XrmoptionNoArg, "False" },
1540 { "-flipView", "flipView", XrmoptionSepArg, NULL },
1541 { "-flip", "flipView", XrmoptionNoArg, "True" },
1542 { "-xflip", "flipView", XrmoptionNoArg, "False" },
1543 { "-cmail", "cmailGameName", XrmoptionSepArg, NULL },
1544 { "-alwaysPromoteToQueen", "alwaysPromoteToQueen",
1545 XrmoptionSepArg, NULL },
1546 { "-queen", "alwaysPromoteToQueen", XrmoptionNoArg, "True" },
1547 { "-xqueen", "alwaysPromoteToQueen", XrmoptionNoArg, "False" },
1548 { "-oldSaveStyle", "oldSaveStyle", XrmoptionSepArg, NULL },
1549 { "-oldsave", "oldSaveStyle", XrmoptionNoArg, "True" },
1550 { "-xoldsave", "oldSaveStyle", XrmoptionNoArg, "False" },
1551 { "-quietPlay", "quietPlay", XrmoptionSepArg, NULL },
1552 { "-quiet", "quietPlay", XrmoptionNoArg, "True" },
1553 { "-xquiet", "quietPlay", XrmoptionNoArg, "False" },
1554 { "-titleInWindow", "titleInWindow", XrmoptionSepArg, NULL },
1555 { "-title", "titleInWindow", XrmoptionNoArg, "True" },
1556 { "-xtitle", "titleInWindow", XrmoptionNoArg, "False" },
1558 { "-zippyTalk", "zippyTalk", XrmoptionSepArg, NULL },
1559 { "-zt", "zippyTalk", XrmoptionNoArg, "True" },
1560 { "-xzt", "zippyTalk", XrmoptionNoArg, "False" },
1561 { "-zippyPlay", "zippyPlay", XrmoptionSepArg, NULL },
1562 { "-zp", "zippyPlay", XrmoptionNoArg, "True" },
1563 { "-xzp", "zippyPlay", XrmoptionNoArg, "False" },
1564 { "-zippyLines", "zippyLines", XrmoptionSepArg, NULL },
1565 { "-zippyPinhead", "zippyPinhead", XrmoptionSepArg, NULL },
1566 { "-zippyPassword", "zippyPassword", XrmoptionSepArg, NULL },
1567 { "-zippyPassword2", "zippyPassword2", XrmoptionSepArg, NULL },
1568 { "-zippyWrongPassword", "zippyWrongPassword", XrmoptionSepArg, NULL },
1569 { "-zippyAcceptOnly", "zippyAcceptOnly", XrmoptionSepArg, NULL },
1570 { "-zippyUseI", "zippyUseI", XrmoptionSepArg, NULL },
1571 { "-zui", "zippyUseI", XrmoptionNoArg, "True" },
1572 { "-xzui", "zippyUseI", XrmoptionNoArg, "False" },
1573 { "-zippyBughouse", "zippyBughouse", XrmoptionSepArg, NULL },
1574 { "-zippyNoplayCrafty", "zippyNoplayCrafty", XrmoptionSepArg, NULL },
1575 { "-znc", "zippyNoplayCrafty", XrmoptionNoArg, "True" },
1576 { "-xznc", "zippyNoplayCrafty", XrmoptionNoArg, "False" },
1577 { "-zippyGameEnd", "zippyGameEnd", XrmoptionSepArg, NULL },
1578 { "-zippyGameStart", "zippyGameStart", XrmoptionSepArg, NULL },
1579 { "-zippyAdjourn", "zippyAdjourn", XrmoptionSepArg, NULL },
1580 { "-zadj", "zippyAdjourn", XrmoptionNoArg, "True" },
1581 { "-xzadj", "zippyAdjourn", XrmoptionNoArg, "False" },
1582 { "-zippyAbort", "zippyAbort", XrmoptionSepArg, NULL },
1583 { "-zab", "zippyAbort", XrmoptionNoArg, "True" },
1584 { "-xzab", "zippyAbort", XrmoptionNoArg, "False" },
1585 { "-zippyVariants", "zippyVariants", XrmoptionSepArg, NULL },
1586 { "-zippyMaxGames", "zippyMaxGames", XrmoptionSepArg, NULL },
1587 { "-zippyReplayTimeout", "zippyReplayTimeout", XrmoptionSepArg, NULL },
1589 { "-flashCount", "flashCount", XrmoptionSepArg, NULL },
1590 { "-flash", "flashCount", XrmoptionNoArg, "3" },
1591 { "-xflash", "flashCount", XrmoptionNoArg, "0" },
1592 { "-flashRate", "flashRate", XrmoptionSepArg, NULL },
1593 { "-pixmapDirectory", "pixmapDirectory", XrmoptionSepArg, NULL },
1594 { "-msLoginDelay", "msLoginDelay", XrmoptionSepArg, NULL },
1595 { "-pixmap", "pixmapDirectory", XrmoptionSepArg, NULL },
1596 { "-colorizeMessages", "colorizeMessages", XrmoptionSepArg, NULL },
1597 { "-colorize", "colorizeMessages", XrmoptionNoArg, "True" },
1598 { "-xcolorize", "colorizeMessages", XrmoptionNoArg, "False" },
1599 { "-colorShout", "colorShout", XrmoptionSepArg, NULL },
1600 { "-colorSShout", "colorSShout", XrmoptionSepArg, NULL },
1601 { "-colorCShout", "colorSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1602 { "-colorChannel1", "colorChannel1", XrmoptionSepArg, NULL },
1603 { "-colorChannel", "colorChannel", XrmoptionSepArg, NULL },
1604 { "-colorKibitz", "colorKibitz", XrmoptionSepArg, NULL },
1605 { "-colorTell", "colorTell", XrmoptionSepArg, NULL },
1606 { "-colorChallenge", "colorChallenge", XrmoptionSepArg, NULL },
1607 { "-colorRequest", "colorRequest", XrmoptionSepArg, NULL },
1608 { "-colorSeek", "colorSeek", XrmoptionSepArg, NULL },
1609 { "-colorNormal", "colorNormal", XrmoptionSepArg, NULL },
1610 { "-soundProgram", "soundProgram", XrmoptionSepArg, NULL },
1611 { "-soundShout", "soundShout", XrmoptionSepArg, NULL },
1612 { "-soundSShout", "soundSShout", XrmoptionSepArg, NULL },
1613 { "-soundCShout", "soundSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1614 { "-soundChannel1", "soundChannel1", XrmoptionSepArg, NULL },
1615 { "-soundChannel", "soundChannel", XrmoptionSepArg, NULL },
1616 { "-soundKibitz", "soundKibitz", XrmoptionSepArg, NULL },
1617 { "-soundTell", "soundTell", XrmoptionSepArg, NULL },
1618 { "-soundChallenge", "soundChallenge", XrmoptionSepArg, NULL },
1619 { "-soundRequest", "soundRequest", XrmoptionSepArg, NULL },
1620 { "-soundSeek", "soundSeek", XrmoptionSepArg, NULL },
1621 { "-soundMove", "soundMove", XrmoptionSepArg, NULL },
1622 { "-soundIcsWin", "soundIcsWin", XrmoptionSepArg, NULL },
1623 { "-soundIcsLoss", "soundIcsLoss", XrmoptionSepArg, NULL },
1624 { "-soundIcsDraw", "soundIcsDraw", XrmoptionSepArg, NULL },
1625 { "-soundIcsUnfinished", "soundIcsUnfinished", XrmoptionSepArg, NULL },
1626 { "-soundIcsAlarm", "soundIcsAlarm", XrmoptionSepArg, NULL },
1627 { "-reuseFirst", "reuseFirst", XrmoptionSepArg, NULL },
1628 { "-reuseChessPrograms", "reuseFirst", XrmoptionSepArg, NULL }, /*compat*/
1629 { "-reuse", "reuseFirst", XrmoptionNoArg, "True" },
1630 { "-xreuse", "reuseFirst", XrmoptionNoArg, "False" },
1631 { "-reuseSecond", "reuseSecond", XrmoptionSepArg, NULL },
1632 { "-reuse2", "reuseSecond", XrmoptionNoArg, "True" },
1633 { "-xreuse2", "reuseSecond", XrmoptionNoArg, "False" },
1634 { "-animateMoving", "animateMoving", XrmoptionSepArg, NULL },
1635 { "-animate", "animateMoving", XrmoptionNoArg, "True" },
1636 { "-xanimate", "animateMoving", XrmoptionNoArg, "False" },
1637 { "-animateDragging", "animateDragging", XrmoptionSepArg, NULL },
1638 { "-drag", "animateDragging", XrmoptionNoArg, "True" },
1639 { "-xdrag", "animateDragging", XrmoptionNoArg, "False" },
1640 { "-animateSpeed", "animateSpeed", XrmoptionSepArg, NULL },
1641 { "-popupExitMessage", "popupExitMessage", XrmoptionSepArg, NULL },
1642 { "-exit", "popupExitMessage", XrmoptionNoArg, "True" },
1643 { "-xexit", "popupExitMessage", XrmoptionNoArg, "False" },
1644 { "-popupMoveErrors", "popupMoveErrors", XrmoptionSepArg, NULL },
1645 { "-popup", "popupMoveErrors", XrmoptionNoArg, "True" },
1646 { "-xpopup", "popupMoveErrors", XrmoptionNoArg, "False" },
1647 { "-fontSizeTolerance", "fontSizeTolerance", XrmoptionSepArg, NULL },
1648 { "-initialMode", "initialMode", XrmoptionSepArg, NULL },
1649 { "-mode", "initialMode", XrmoptionSepArg, NULL },
1650 { "-variant", "variant", XrmoptionSepArg, NULL },
1651 { "-firstProtocolVersion", "firstProtocolVersion", XrmoptionSepArg, NULL },
1652 { "-secondProtocolVersion","secondProtocolVersion",XrmoptionSepArg, NULL },
1653 { "-showButtonBar", "showButtonBar", XrmoptionSepArg, NULL },
1654 { "-buttons", "showButtonBar", XrmoptionNoArg, "True" },
1655 { "-xbuttons", "showButtonBar", XrmoptionNoArg, "False" },
1656 /* [AS,HR] New features */
1657 { "-firstScoreAbs", "firstScoreAbs", XrmoptionSepArg, NULL },
1658 { "-secondScoreAbs", "secondScoreAbs", XrmoptionSepArg, NULL },
1659 { "-pgnExtendedInfo", "pgnExtendedInfo", XrmoptionSepArg, NULL },
1660 { "-hideThinkingFromHuman", "hideThinkingFromHuman", XrmoptionSepArg, NULL },
1661 { "-adjudicateLossThreshold", "adjudicateLossThreshold", XrmoptionSepArg, NULL },
1662 { "-pgnEventHeader", "pgnEventHeader", XrmoptionSepArg, NULL },
1663 { "-firstIsUCI", "firstIsUCI", XrmoptionSepArg, NULL },
1664 { "-secondIsUCI", "secondIsUCI", XrmoptionSepArg, NULL },
1665 { "-fUCI", "firstIsUCI", XrmoptionNoArg, "True" },
1666 { "-sUCI", "secondIsUCI", XrmoptionNoArg, "True" },
1667 { "-firstHasOwnBookUCI", "firstHasOwnBookUCI", XrmoptionSepArg, NULL },
1668 { "-secondHasOwnBookUCI", "secondHasOwnBookUCI", XrmoptionSepArg, NULL },
1669 { "-fNoOwnBookUCI", "firstHasOwnBookUCI", XrmoptionNoArg, "False" },
1670 { "-sNoOwnBookUCI", "secondHasOwnBookUCI", XrmoptionNoArg, "False" },
1671 { "-firstXBook", "firstHasOwnBookUCI", XrmoptionNoArg, "False" },
1672 { "-secondXBook", "secondHasOwnBookUCI", XrmoptionNoArg, "False" },
1673 { "-polyglotDir", "polyglotDir", XrmoptionSepArg, NULL },
1674 { "-usePolyglotBook", "usePolyglotBook", XrmoptionSepArg, NULL },
1675 { "-polyglotBook", "polyglotBook", XrmoptionSepArg, NULL },
1676 { "-defaultHashSize", "defaultHashSize", XrmoptionSepArg, NULL },
1677 { "-defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XrmoptionSepArg, NULL },
1678 { "-defaultPathEGTB", "defaultPathEGTB", XrmoptionSepArg, NULL },
1679 { "-defaultFrcPosition", "defaultFrcPosition", XrmoptionSepArg, NULL },
1680 // [HGM] I am sure AS added many more options, but we have to fish them out, from the list in winboard.c
1682 /* [HGM,HR] User-selectable board size */
1683 { "-boardWidth", "boardWidth", XrmoptionSepArg, NULL },
1684 { "-boardHeight", "boardHeight", XrmoptionSepArg, NULL },
1685 { "-matchPause", "matchPause", XrmoptionSepArg, NULL },
1687 /* [HGM] new arguments of 4.3.xx. All except first three are back-end options, which should work immediately */
1688 { "-holdingsSize", "holdingsSize", XrmoptionSepArg, NULL }, // requires extensive front-end changes to work
1689 { "-flipBlack", "flipBlack", XrmoptionSepArg, NULL }, // requires front-end changes to work
1690 { "-allWhite", "allWhite", XrmoptionSepArg, NULL }, // requires front-end changes to work
1691 { "-pieceToCharTable", "pieceToCharTable", XrmoptionSepArg, NULL },
1692 { "-alphaRank", "alphaRank", XrmoptionSepArg, NULL },
1693 { "-testClaims", "testClaims", XrmoptionSepArg, NULL },
1694 { "-checkMates", "checkMates", XrmoptionSepArg, NULL },
1695 { "-materialDraws", "materialDraws", XrmoptionSepArg, NULL },
1696 { "-trivialDraws", "trivialDraws", XrmoptionSepArg, NULL },
1697 { "-ruleMoves", "ruleMoves", XrmoptionSepArg, NULL },
1698 { "-repeatsToDraw", "repeatsToDraw", XrmoptionSepArg, NULL },
1699 { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL },
1700 { "-userName", "userName", XrmoptionSepArg, NULL },
1701 { "-autoKibitz", "autoKibitz", XrmoptionNoArg, "True" },
1702 { "-firstTimeOdds", "firstTimeOdds", XrmoptionSepArg, NULL },
1703 { "-secondTimeOdds", "secondTimeOdds", XrmoptionSepArg, NULL },
1704 { "-timeOddsMode", "timeOddsMode", XrmoptionSepArg, NULL },
1705 { "-firstAccumulateTC", "firstAccumulateTC", XrmoptionSepArg, NULL },
1706 { "-secondAccumulateTC", "secondAccumulateTC", XrmoptionSepArg, NULL },
1707 { "-firstNPS", "firstNPS", XrmoptionSepArg, NULL },
1708 { "-secondNPS", "secondNPS", XrmoptionSepArg, NULL },
1709 { "-serverMoves", "serverMoves", XrmoptionSepArg, NULL },
1710 { "-serverPause", "serverPause", XrmoptionSepArg, NULL },
1711 { "-suppressLoadMoves", "suppressLoadMoves", XrmoptionSepArg, NULL },
1712 { "-egtFormats", "egtFormats", XrmoptionSepArg, NULL },
1713 { "-userName", "userName", XrmoptionSepArg, NULL },
1714 { "-smpCores", "smpCores", XrmoptionSepArg, NULL },
1715 { "-sameColorGames", "sameColorGames", XrmoptionSepArg, NULL },
1716 { "-rewindIndex", "rewindIndex", XrmoptionSepArg, NULL },
1717 { "-niceEngines", "niceEngines", XrmoptionSepArg, NULL },
1718 { "-delayBeforeQuit", "delayBeforeQuit", XrmoptionSepArg, NULL },
1719 { "-delayAfterQuit", "delayAfterQuit", XrmoptionSepArg, NULL },
1720 { "-nameOfDebugFile", "nameOfDebugFile", XrmoptionSepArg, NULL },
1721 { "-debugFile", "nameOfDebugFile", XrmoptionSepArg, NULL },
1722 { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL },
1723 { "-noGUI", "noGUI", XrmoptionNoArg, "True" },
1724 { "-firstOptions", "firstOptions", XrmoptionSepArg, NULL },
1725 { "-secondOptions", "secondOptions", XrmoptionSepArg, NULL },
1729 XtActionsRec boardActions[] = {
1730 { "DrawPosition", DrawPositionProc },
1731 { "HandleUserMove", HandleUserMove },
1732 { "AnimateUserMove", AnimateUserMove },
1733 { "FileNameAction", FileNameAction },
1734 { "AskQuestionProc", AskQuestionProc },
1735 { "AskQuestionReplyAction", AskQuestionReplyAction },
1736 { "PieceMenuPopup", PieceMenuPopup },
1737 { "WhiteClock", WhiteClock },
1738 { "BlackClock", BlackClock },
1739 { "Iconify", Iconify },
1740 { "ResetProc", ResetProc },
1741 { "LoadGameProc", LoadGameProc },
1742 { "LoadNextGameProc", LoadNextGameProc },
1743 { "LoadPrevGameProc", LoadPrevGameProc },
1744 { "LoadSelectedProc", LoadSelectedProc },
1745 { "ReloadGameProc", ReloadGameProc },
1746 { "LoadPositionProc", LoadPositionProc },
1747 { "LoadNextPositionProc", LoadNextPositionProc },
1748 { "LoadPrevPositionProc", LoadPrevPositionProc },
1749 { "ReloadPositionProc", ReloadPositionProc },
1750 { "CopyPositionProc", CopyPositionProc },
1751 { "PastePositionProc", PastePositionProc },
1752 { "CopyGameProc", CopyGameProc },
1753 { "PasteGameProc", PasteGameProc },
1754 { "SaveGameProc", SaveGameProc },
1755 { "SavePositionProc", SavePositionProc },
1756 { "MailMoveProc", MailMoveProc },
1757 { "ReloadCmailMsgProc", ReloadCmailMsgProc },
1758 { "QuitProc", QuitProc },
1759 { "MachineWhiteProc", MachineWhiteProc },
1760 { "MachineBlackProc", MachineBlackProc },
1761 { "AnalysisModeProc", AnalyzeModeProc },
1762 { "AnalyzeFileProc", AnalyzeFileProc },
1763 { "TwoMachinesProc", TwoMachinesProc },
1764 { "IcsClientProc", IcsClientProc },
1765 { "EditGameProc", EditGameProc },
1766 { "EditPositionProc", EditPositionProc },
1767 { "TrainingProc", EditPositionProc },
1768 { "EngineOutputProc", EngineOutputProc}, // [HGM] Winboard_x engine-output window
1769 { "ShowGameListProc", ShowGameListProc },
1770 { "ShowMoveListProc", HistoryShowProc},
1771 { "EditTagsProc", EditCommentProc },
1772 { "EditCommentProc", EditCommentProc },
1773 { "IcsAlarmProc", IcsAlarmProc },
1774 { "IcsInputBoxProc", IcsInputBoxProc },
1775 { "PauseProc", PauseProc },
1776 { "AcceptProc", AcceptProc },
1777 { "DeclineProc", DeclineProc },
1778 { "RematchProc", RematchProc },
1779 { "CallFlagProc", CallFlagProc },
1780 { "DrawProc", DrawProc },
1781 { "AdjournProc", AdjournProc },
1782 { "AbortProc", AbortProc },
1783 { "ResignProc", ResignProc },
1784 { "EnterKeyProc", EnterKeyProc },
1785 { "StopObservingProc", StopObservingProc },
1786 { "StopExaminingProc", StopExaminingProc },
1787 { "BackwardProc", BackwardProc },
1788 { "ForwardProc", ForwardProc },
1789 { "ToStartProc", ToStartProc },
1790 { "ToEndProc", ToEndProc },
1791 { "RevertProc", RevertProc },
1792 { "TruncateGameProc", TruncateGameProc },
1793 { "MoveNowProc", MoveNowProc },
1794 { "RetractMoveProc", RetractMoveProc },
1795 { "AlwaysQueenProc", AlwaysQueenProc },
1796 { "AnimateDraggingProc", AnimateDraggingProc },
1797 { "AnimateMovingProc", AnimateMovingProc },
1798 { "AutoflagProc", AutoflagProc },
1799 { "AutoflipProc", AutoflipProc },
1800 { "AutobsProc", AutobsProc },
1801 { "AutoraiseProc", AutoraiseProc },
1802 { "AutosaveProc", AutosaveProc },
1803 { "BlindfoldProc", BlindfoldProc },
1804 { "FlashMovesProc", FlashMovesProc },
1805 { "FlipViewProc", FlipViewProc },
1806 { "GetMoveListProc", GetMoveListProc },
1808 { "HighlightDraggingProc", HighlightDraggingProc },
1810 { "HighlightLastMoveProc", HighlightLastMoveProc },
1811 { "IcsAlarmProc", IcsAlarmProc },
1812 { "MoveSoundProc", MoveSoundProc },
1813 { "OldSaveStyleProc", OldSaveStyleProc },
1814 { "PeriodicUpdatesProc", PeriodicUpdatesProc },
1815 { "PonderNextMoveProc", PonderNextMoveProc },
1816 { "PopupExitMessageProc", PopupExitMessageProc },
1817 { "PopupMoveErrorsProc", PopupMoveErrorsProc },
1818 { "PremoveProc", PremoveProc },
1819 { "QuietPlayProc", QuietPlayProc },
1820 { "ShowCoordsProc", ShowCoordsProc },
1821 { "ShowThinkingProc", ShowThinkingProc },
1822 { "HideThinkingProc", HideThinkingProc },
1823 { "TestLegalityProc", TestLegalityProc },
1824 { "InfoProc", InfoProc },
1825 { "ManProc", ManProc },
1826 { "HintProc", HintProc },
1827 { "BookProc", BookProc },
1828 { "AboutGameProc", AboutGameProc },
1829 { "AboutProc", AboutProc },
1830 { "DebugProc", DebugProc },
1831 { "NothingProc", NothingProc },
1832 { "CommentPopDown", (XtActionProc) CommentPopDown },
1833 { "EditCommentPopDown", (XtActionProc) EditCommentPopDown },
1834 { "TagsPopDown", (XtActionProc) TagsPopDown },
1835 { "ErrorPopDown", (XtActionProc) ErrorPopDown },
1836 { "ICSInputBoxPopDown", (XtActionProc) ICSInputBoxPopDown },
1837 { "AnalysisPopDown", (XtActionProc) AnalysisPopDown },
1838 { "FileNamePopDown", (XtActionProc) FileNamePopDown },
1839 { "AskQuestionPopDown", (XtActionProc) AskQuestionPopDown },
1840 { "GameListPopDown", (XtActionProc) GameListPopDown },
1841 { "PromotionPopDown", (XtActionProc) PromotionPopDown },
1842 { "HistoryPopDown", (XtActionProc) HistoryPopDown },
1843 { "EngineOutputPopDown", (XtActionProc) EngineOutputPopDown },
1844 { "ShufflePopDown", (XtActionProc) ShufflePopDown },
1845 { "EnginePopDown", (XtActionProc) EnginePopDown },
1846 { "UciPopDown", (XtActionProc) UciPopDown },
1847 { "TimeControlPopDown", (XtActionProc) TimeControlPopDown },
1848 { "NewVariantPopDown", (XtActionProc) NewVariantPopDown },
1849 { "SettingsPopDown", (XtActionProc) SettingsPopDown },
1852 char globalTranslations[] =
1853 ":<Key>R: ResignProc() \n \
1854 :<Key>r: ResetProc() \n \
1855 :<Key>g: LoadGameProc() \n \
1856 :<Key>N: LoadNextGameProc() \n \
1857 :<Key>P: LoadPrevGameProc() \n \
1858 :<Key>Q: QuitProc() \n \
1859 :<Key>F: ToEndProc() \n \
1860 :<Key>f: ForwardProc() \n \
1861 :<Key>B: ToStartProc() \n \
1862 :<Key>b: BackwardProc() \n \
1863 :<Key>p: PauseProc() \n \
1864 :<Key>d: DrawProc() \n \
1865 :<Key>t: CallFlagProc() \n \
1866 :<Key>i: Iconify() \n \
1867 :<Key>c: Iconify() \n \
1868 :<Key>v: FlipViewProc() \n \
1869 <KeyDown>Control_L: BackwardProc() \n \
1870 <KeyUp>Control_L: ForwardProc() \n \
1871 <KeyDown>Control_R: BackwardProc() \n \
1872 <KeyUp>Control_R: ForwardProc() \n \
1873 Shift<Key>1: AskQuestionProc(\"Direct command\",\
1874 \"Send to chess program:\",,1) \n \
1875 Shift<Key>2: AskQuestionProc(\"Direct command\",\
1876 \"Send to second chess program:\",,2) \n";
1878 char boardTranslations[] =
1879 "<Btn1Down>: HandleUserMove() \n \
1880 <Btn1Up>: HandleUserMove() \n \
1881 <Btn1Motion>: AnimateUserMove() \n \
1882 Shift<Btn2Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD)\
1883 PieceMenuPopup(menuB) \n \
1884 Any<Btn2Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD) \
1885 PieceMenuPopup(menuW) \n \
1886 Shift<Btn3Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD)\
1887 PieceMenuPopup(menuW) \n \
1888 Any<Btn3Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD) \
1889 PieceMenuPopup(menuB) \n";
1891 char whiteTranslations[] = "<BtnDown>: WhiteClock()\n";
1892 char blackTranslations[] = "<BtnDown>: BlackClock()\n";
1894 char ICSInputTranslations[] =
1895 "<Key>Return: EnterKeyProc() \n";
1897 String xboardResources[] = {
1898 "*fileName*value.translations: #override\\n <Key>Return: FileNameAction()",
1899 "*question*value.translations: #override\\n <Key>Return: AskQuestionReplyAction()",
1900 "*errorpopup*translations: #override\\n <Key>Return: ErrorPopDown()",
1905 /* Max possible square size */
1906 #define MAXSQSIZE 256
1908 static int xpm_avail[MAXSQSIZE];
1910 #ifdef HAVE_DIR_STRUCT
1912 /* Extract piece size from filename */
1914 xpm_getsize(name, len, ext)
1925 if ((p=strchr(name, '.')) == NULL ||
1926 StrCaseCmp(p+1, ext) != 0)
1932 while (*p && isdigit(*p))
1939 /* Setup xpm_avail */
1941 xpm_getavail(dirname, ext)
1949 for (i=0; i<MAXSQSIZE; ++i)
1952 if (appData.debugMode)
1953 fprintf(stderr, "XPM dir:%s:ext:%s:\n", dirname, ext);
1955 dir = opendir(dirname);
1958 fprintf(stderr, _("%s: Can't access XPM directory %s\n"),
1959 programName, dirname);
1963 while ((ent=readdir(dir)) != NULL) {
1964 i = xpm_getsize(ent->d_name, NAMLEN(ent), ext);
1965 if (i > 0 && i < MAXSQSIZE)
1975 xpm_print_avail(fp, ext)
1981 fprintf(fp, _("Available `%s' sizes:\n"), ext);
1982 for (i=1; i<MAXSQSIZE; ++i) {
1988 /* Return XPM piecesize closest to size */
1990 xpm_closest_to(dirname, size, ext)
1996 int sm_diff = MAXSQSIZE;
2000 xpm_getavail(dirname, ext);
2002 if (appData.debugMode)
2003 xpm_print_avail(stderr, ext);
2005 for (i=1; i<MAXSQSIZE; ++i) {
2008 diff = (diff<0) ? -diff : diff;
2009 if (diff < sm_diff) {
2017 fprintf(stderr, _("Error: No `%s' files!\n"), ext);
2023 #else /* !HAVE_DIR_STRUCT */
2024 /* If we are on a system without a DIR struct, we can't
2025 read the directory, so we can't collect a list of
2026 filenames, etc., so we can't do any size-fitting. */
2028 xpm_closest_to(dirname, size, ext)
2033 fprintf(stderr, _("\
2034 Warning: No DIR structure found on this system --\n\
2035 Unable to autosize for XPM/XIM pieces.\n\
2036 Please report this error to frankm@hiwaay.net.\n\
2037 Include system type & operating system in message.\n"));
2040 #endif /* HAVE_DIR_STRUCT */
2042 static char *cnames[9] = { "black", "red", "green", "yellow", "blue",
2043 "magenta", "cyan", "white" };
2047 TextColors textColors[(int)NColorClasses];
2049 /* String is: "fg, bg, attr". Which is 0, 1, 2 */
2051 parse_color(str, which)
2055 char *p, buf[100], *d;
2058 if (strlen(str) > 99) /* watch bounds on buf */
2063 for (i=0; i<which; ++i) {
2070 /* Could be looking at something like:
2072 .. in which case we want to stop on a comma also */
2073 while (*p && *p != ',' && !isalpha(*p) && !isdigit(*p))
2077 return -1; /* Use default for empty field */
2080 if (which == 2 || isdigit(*p))
2083 while (*p && isalpha(*p))
2088 for (i=0; i<8; ++i) {
2089 if (!StrCaseCmp(buf, cnames[i]))
2090 return which? (i+40) : (i+30);
2092 if (!StrCaseCmp(buf, "default")) return -1;
2094 fprintf(stderr, _("%s: unrecognized color %s\n"), programName, buf);
2099 parse_cpair(cc, str)
2103 if ((textColors[(int)cc].fg=parse_color(str, 0)) == -2) {
2104 fprintf(stderr, _("%s: can't parse foreground color in `%s'\n"),
2109 /* bg and attr are optional */
2110 textColors[(int)cc].bg = parse_color(str, 1);
2111 if ((textColors[(int)cc].attr = parse_color(str, 2)) < 0) {
2112 textColors[(int)cc].attr = 0;
2118 /* Arrange to catch delete-window events */
2119 Atom wm_delete_window;
2121 CatchDeleteWindow(Widget w, String procname)
2124 XSetWMProtocols(xDisplay, XtWindow(w), &wm_delete_window, 1);
2125 sprintf(buf, "<Message>WM_PROTOCOLS: %s() \n", procname);
2126 XtAugmentTranslations(w, XtParseTranslationTable(buf));
2133 XtSetArg(args[0], XtNiconic, False);
2134 XtSetValues(shellWidget, args, 1);
2136 XtPopup(shellWidget, XtGrabNone); /* Raise if lowered */
2140 // eventually, all layout determining code should go into a subroutine, but until then IDSIZE remains undefined
2142 #define BoardSize int
2143 void InitDrawingSizes(BoardSize boardSize, int flags)
2144 { // [HGM] resize is functional now, but for board format changes only (nr of ranks, files)
2145 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
2147 XtGeometryResult gres;
2150 if(!formWidget) return;
2153 * Enable shell resizing.
2155 shellArgs[0].value = (XtArgVal) &w;
2156 shellArgs[1].value = (XtArgVal) &h;
2157 XtGetValues(shellWidget, shellArgs, 2);
2159 shellArgs[4].value = 2*w; shellArgs[2].value = 10;
2160 shellArgs[5].value = 2*h; shellArgs[3].value = 10;
2161 XtSetValues(shellWidget, &shellArgs[2], 4);
2163 XtSetArg(args[0], XtNdefaultDistance, &sep);
2164 XtGetValues(formWidget, args, 1);
2166 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2167 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2170 XtSetArg(args[0], XtNwidth, boardWidth);
2171 XtSetArg(args[1], XtNheight, boardHeight);
2172 XtSetValues(boardWidget, args, 2);
2174 timerWidth = (boardWidth - sep) / 2;
2175 XtSetArg(args[0], XtNwidth, timerWidth);
2176 XtSetValues(whiteTimerWidget, args, 1);
2177 XtSetValues(blackTimerWidget, args, 1);
2179 XawFormDoLayout(formWidget, False);
2181 if (appData.titleInWindow) {
2183 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2184 XtSetArg(args[i], XtNheight, &h); i++;
2185 XtGetValues(titleWidget, args, i);
2187 w = boardWidth - 2*bor;
2189 XtSetArg(args[0], XtNwidth, &w);
2190 XtGetValues(menuBarWidget, args, 1);
2191 w = boardWidth - w - sep - 2*bor - 2; // WIDTH_FUDGE
2194 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
2195 if (gres != XtGeometryYes && appData.debugMode) {
2197 _("%s: titleWidget geometry error %d %d %d %d %d\n"),
2198 programName, gres, w, h, wr, hr);
2202 XawFormDoLayout(formWidget, True);
2205 * Inhibit shell resizing.
2207 shellArgs[0].value = w = (XtArgVal) boardWidth + marginW;
2208 shellArgs[1].value = h = (XtArgVal) boardHeight + marginH;
2209 shellArgs[4].value = shellArgs[2].value = w;
2210 shellArgs[5].value = shellArgs[3].value = h;
2211 XtSetValues(shellWidget, &shellArgs[0], 6);
2220 int i, j, clockFontPxlSize, coordFontPxlSize, fontPxlSize;
2221 XSetWindowAttributes window_attributes;
2223 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
2224 XrmValue vFrom, vTo;
2225 XtGeometryResult gres;
2228 int forceMono = False;
2231 // [HGM] before anything else, expand any indirection files amongst options
2232 char *argvCopy[1000]; // 1000 seems enough
2233 char newArgs[10000]; // holds actual characters
2236 srandom(time(0)); // [HGM] book: make random truly random
2239 for(i=0; i<argc; i++) {
2240 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2241 //fprintf(stderr, "arg %s\n", argv[i]);
2242 if(argv[i][0] != '@') argvCopy[j++] = argv[i]; else {
2244 FILE *f = fopen(argv[i]+1, "rb");
2245 if(f == NULL) { fprintf(stderr, _("ignore %s\n"), argv[i]); continue; } // do not expand non-existing
2246 argvCopy[j++] = newArgs + k; // get ready for first argument from file
2247 while((c = fgetc(f)) != EOF) { // each line of file inserts 1 argument in the list
2249 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2250 newArgs[k++] = 0; // terminate current arg
2251 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2252 argvCopy[j++] = newArgs + k; // get ready for next
2254 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2267 if(appData.debugMode,1) { // OK, appData is not initialized here yet...
2268 for(i=0; i<argc; i++) fprintf(stderr, "argv[%2d] = '%s'\n", i, argv[i]);
2274 setbuf(stdout, NULL);
2275 setbuf(stderr, NULL);
2278 programName = strrchr(argv[0], '/');
2279 if (programName == NULL)
2280 programName = argv[0];
2285 XtSetLanguageProc(NULL, NULL, NULL);
2286 bindtextdomain(PRODUCT, LOCALEDIR);
2287 textdomain(PRODUCT);
2291 XtAppInitialize(&appContext, "XBoard", shellOptions,
2292 XtNumber(shellOptions),
2293 &argc, argv, xboardResources, NULL, 0);
2295 fprintf(stderr, _("%s: unrecognized argument %s\n"),
2296 programName, argv[1]);
2300 if ((chessDir = (char *) getenv("CHESSDIR")) == NULL) {
2303 if (chdir(chessDir) != 0) {
2304 fprintf(stderr, _("%s: can't cd to CHESSDIR: "), programName);
2311 if (p == NULL) p = "/tmp";
2312 i = strlen(p) + strlen("/.xboardXXXXXx.pgn") + 1;
2313 gameCopyFilename = (char*) malloc(i);
2314 gamePasteFilename = (char*) malloc(i);
2315 sprintf(gameCopyFilename, "%s/.xboard%05uc.pgn", p, getpid());
2316 sprintf(gamePasteFilename, "%s/.xboard%05up.pgn", p, getpid());
2318 XtGetApplicationResources(shellWidget, (XtPointer) &appData,
2319 clientResources, XtNumber(clientResources),
2322 if (appData.debugMode && appData.nameOfDebugFile && strcmp(appData.nameOfDebugFile, "stderr")) {
2323 /* [DM] debug info to file [HGM] make the filename a command-line option, and allow it to remain stderr */
2324 if ((debugFP = fopen(appData.nameOfDebugFile, "w")) == NULL) {
2325 printf(_("Failed to open file '%s'\n"), appData.nameOfDebugFile);
2328 setbuf(debugFP, NULL);
2331 /* [HGM,HR] make sure board size is acceptable */
2332 if(appData.NrFiles > BOARD_SIZE ||
2333 appData.NrRanks > BOARD_SIZE )
2334 DisplayFatalError(_("Recompile with BOARD_SIZE > 12, to support this size"), 0, 2);
2337 /* This feature does not work; animation needs a rewrite */
2338 appData.highlightDragging = FALSE;
2342 xDisplay = XtDisplay(shellWidget);
2343 xScreen = DefaultScreen(xDisplay);
2344 wm_delete_window = XInternAtom(xDisplay, "WM_DELETE_WINDOW", True);
2346 gameInfo.variant = StringToVariant(appData.variant);
2347 InitPosition(FALSE);
2350 * Determine boardSize
2352 gameInfo.boardWidth = gameInfo.boardHeight = 8; // [HGM] boardsize: make sure we start as 8x8
2355 // [HGM] as long as we have not created the possibility to change size while running, start with requested size
2356 gameInfo.boardWidth = appData.NrFiles > 0 ? appData.NrFiles : 8;
2357 gameInfo.boardHeight = appData.NrRanks > 0 ? appData.NrRanks : 8;
2358 gameInfo.holdingsWidth = appData.holdingsSize > 0 ? 2 : 0;
2363 InitDrawingSizes(-1, 0); // [HGM] initsize: make this into a subroutine
2365 if (isdigit(appData.boardSize[0])) {
2366 i = sscanf(appData.boardSize, "%d,%d,%d,%d,%d,%d,%d", &squareSize,
2367 &lineGap, &clockFontPxlSize, &coordFontPxlSize,
2368 &fontPxlSize, &smallLayout, &tinyLayout);
2370 fprintf(stderr, _("%s: bad boardSize syntax %s\n"),
2371 programName, appData.boardSize);
2375 /* Find some defaults; use the nearest known size */
2376 SizeDefaults *szd, *nearest;
2377 int distance = 99999;
2378 nearest = szd = sizeDefaults;
2379 while (szd->name != NULL) {
2380 if (abs(szd->squareSize - squareSize) < distance) {
2382 distance = abs(szd->squareSize - squareSize);
2383 if (distance == 0) break;
2387 if (i < 2) lineGap = nearest->lineGap;
2388 if (i < 3) clockFontPxlSize = nearest->clockFontPxlSize;
2389 if (i < 4) coordFontPxlSize = nearest->coordFontPxlSize;
2390 if (i < 5) fontPxlSize = nearest->fontPxlSize;
2391 if (i < 6) smallLayout = nearest->smallLayout;
2392 if (i < 7) tinyLayout = nearest->tinyLayout;
2395 SizeDefaults *szd = sizeDefaults;
2396 if (*appData.boardSize == NULLCHAR) {
2397 while (DisplayWidth(xDisplay, xScreen) < szd->minScreenSize ||
2398 DisplayHeight(xDisplay, xScreen) < szd->minScreenSize) {
2401 if (szd->name == NULL) szd--;
2403 while (szd->name != NULL &&
2404 StrCaseCmp(szd->name, appData.boardSize) != 0) szd++;
2405 if (szd->name == NULL) {
2406 fprintf(stderr, _("%s: unrecognized boardSize name %s\n"),
2407 programName, appData.boardSize);
2411 squareSize = szd->squareSize;
2412 lineGap = szd->lineGap;
2413 clockFontPxlSize = szd->clockFontPxlSize;
2414 coordFontPxlSize = szd->coordFontPxlSize;
2415 fontPxlSize = szd->fontPxlSize;
2416 smallLayout = szd->smallLayout;
2417 tinyLayout = szd->tinyLayout;
2420 /* Now, using squareSize as a hint, find a good XPM/XIM set size */
2421 if (strlen(appData.pixmapDirectory) > 0) {
2422 p = ExpandPathName(appData.pixmapDirectory);
2424 fprintf(stderr, _("Error expanding path name \"%s\"\n"),
2425 appData.pixmapDirectory);
2428 if (appData.debugMode) {
2429 fprintf(stderr, _("\
2430 XBoard square size (hint): %d\n\
2431 %s fulldir:%s:\n"), squareSize, IMAGE_EXT, p);
2433 squareSize = xpm_closest_to(p, squareSize, IMAGE_EXT);
2434 if (appData.debugMode) {
2435 fprintf(stderr, _("Closest %s size: %d\n"), IMAGE_EXT, squareSize);
2439 /* [HR] height treated separately (hacked) */
2440 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2441 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2442 if (appData.showJail == 1) {
2443 /* Jail on top and bottom */
2444 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2445 XtSetArg(boardArgs[2], XtNheight,
2446 boardHeight + 2*(lineGap + squareSize));
2447 } else if (appData.showJail == 2) {
2449 XtSetArg(boardArgs[1], XtNwidth,
2450 boardWidth + 2*(lineGap + squareSize));
2451 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2454 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2455 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2459 * Determine what fonts to use.
2461 appData.clockFont = FindFont(appData.clockFont, clockFontPxlSize);
2462 clockFontID = XLoadFont(xDisplay, appData.clockFont);
2463 clockFontStruct = XQueryFont(xDisplay, clockFontID);
2464 appData.coordFont = FindFont(appData.coordFont, coordFontPxlSize);
2465 coordFontID = XLoadFont(xDisplay, appData.coordFont);
2466 coordFontStruct = XQueryFont(xDisplay, coordFontID);
2467 appData.font = FindFont(appData.font, fontPxlSize);
2468 countFontID = XLoadFont(xDisplay, appData.coordFont); // [HGM] holdings
2469 countFontStruct = XQueryFont(xDisplay, countFontID);
2470 // appData.font = FindFont(appData.font, fontPxlSize);
2472 xdb = XtDatabase(xDisplay);
2473 XrmPutStringResource(&xdb, "*font", appData.font);
2476 * Detect if there are not enough colors available and adapt.
2478 if (DefaultDepth(xDisplay, xScreen) <= 2) {
2479 appData.monoMode = True;
2482 if (!appData.monoMode) {
2483 vFrom.addr = (caddr_t) appData.lightSquareColor;
2484 vFrom.size = strlen(appData.lightSquareColor);
2485 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2486 if (vTo.addr == NULL) {
2487 appData.monoMode = True;
2490 lightSquareColor = *(Pixel *) vTo.addr;
2493 if (!appData.monoMode) {
2494 vFrom.addr = (caddr_t) appData.darkSquareColor;
2495 vFrom.size = strlen(appData.darkSquareColor);
2496 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2497 if (vTo.addr == NULL) {
2498 appData.monoMode = True;
2501 darkSquareColor = *(Pixel *) vTo.addr;
2504 if (!appData.monoMode) {
2505 vFrom.addr = (caddr_t) appData.whitePieceColor;
2506 vFrom.size = strlen(appData.whitePieceColor);
2507 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2508 if (vTo.addr == NULL) {
2509 appData.monoMode = True;
2512 whitePieceColor = *(Pixel *) vTo.addr;
2515 if (!appData.monoMode) {
2516 vFrom.addr = (caddr_t) appData.blackPieceColor;
2517 vFrom.size = strlen(appData.blackPieceColor);
2518 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2519 if (vTo.addr == NULL) {
2520 appData.monoMode = True;
2523 blackPieceColor = *(Pixel *) vTo.addr;
2527 if (!appData.monoMode) {
2528 vFrom.addr = (caddr_t) appData.highlightSquareColor;
2529 vFrom.size = strlen(appData.highlightSquareColor);
2530 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2531 if (vTo.addr == NULL) {
2532 appData.monoMode = True;
2535 highlightSquareColor = *(Pixel *) vTo.addr;
2539 if (!appData.monoMode) {
2540 vFrom.addr = (caddr_t) appData.premoveHighlightColor;
2541 vFrom.size = strlen(appData.premoveHighlightColor);
2542 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2543 if (vTo.addr == NULL) {
2544 appData.monoMode = True;
2547 premoveHighlightColor = *(Pixel *) vTo.addr;
2552 fprintf(stderr, _("%s: too few colors available; trying monochrome mode\n"),
2556 if (appData.monoMode && appData.debugMode) {
2557 fprintf(stderr, _("white pixel = 0x%lx, black pixel = 0x%lx\n"),
2558 (unsigned long) XWhitePixel(xDisplay, xScreen),
2559 (unsigned long) XBlackPixel(xDisplay, xScreen));
2562 if (parse_cpair(ColorShout, appData.colorShout) < 0 ||
2563 parse_cpair(ColorSShout, appData.colorSShout) < 0 ||
2564 parse_cpair(ColorChannel1, appData.colorChannel1) < 0 ||
2565 parse_cpair(ColorChannel, appData.colorChannel) < 0 ||
2566 parse_cpair(ColorKibitz, appData.colorKibitz) < 0 ||
2567 parse_cpair(ColorTell, appData.colorTell) < 0 ||
2568 parse_cpair(ColorChallenge, appData.colorChallenge) < 0 ||
2569 parse_cpair(ColorRequest, appData.colorRequest) < 0 ||
2570 parse_cpair(ColorSeek, appData.colorSeek) < 0 ||
2571 parse_cpair(ColorNormal, appData.colorNormal) < 0)
2573 if (appData.colorize) {
2575 _("%s: can't parse color names; disabling colorization\n"),
2578 appData.colorize = FALSE;
2580 textColors[ColorNone].fg = textColors[ColorNone].bg = -1;
2581 textColors[ColorNone].attr = 0;
2583 XtAppAddActions(appContext, boardActions, XtNumber(boardActions));
2589 layoutName = "tinyLayout";
2590 } else if (smallLayout) {
2591 layoutName = "smallLayout";
2593 layoutName = "normalLayout";
2595 /* Outer layoutWidget is there only to provide a name for use in
2596 resources that depend on the layout style */
2598 XtCreateManagedWidget(layoutName, formWidgetClass, shellWidget,
2599 layoutArgs, XtNumber(layoutArgs));
2601 XtCreateManagedWidget("form", formWidgetClass, layoutWidget,
2602 formArgs, XtNumber(formArgs));
2603 XtSetArg(args[0], XtNdefaultDistance, &sep);
2604 XtGetValues(formWidget, args, 1);
2607 widgetList[j++] = menuBarWidget = CreateMenuBar(menuBar);
2608 XtSetArg(args[0], XtNtop, XtChainTop);
2609 XtSetArg(args[1], XtNbottom, XtChainTop);
2610 XtSetValues(menuBarWidget, args, 2);
2612 widgetList[j++] = whiteTimerWidget =
2613 XtCreateWidget("whiteTime", labelWidgetClass,
2614 formWidget, timerArgs, XtNumber(timerArgs));
2615 XtSetArg(args[0], XtNfont, clockFontStruct);
2616 XtSetArg(args[1], XtNtop, XtChainTop);
2617 XtSetArg(args[2], XtNbottom, XtChainTop);
2618 XtSetValues(whiteTimerWidget, args, 3);
2620 widgetList[j++] = blackTimerWidget =
2621 XtCreateWidget("blackTime", labelWidgetClass,
2622 formWidget, timerArgs, XtNumber(timerArgs));
2623 XtSetArg(args[0], XtNfont, clockFontStruct);
2624 XtSetArg(args[1], XtNtop, XtChainTop);
2625 XtSetArg(args[2], XtNbottom, XtChainTop);
2626 XtSetValues(blackTimerWidget, args, 3);
2628 if (appData.titleInWindow) {
2629 widgetList[j++] = titleWidget =
2630 XtCreateWidget("title", labelWidgetClass, formWidget,
2631 titleArgs, XtNumber(titleArgs));
2632 XtSetArg(args[0], XtNtop, XtChainTop);
2633 XtSetArg(args[1], XtNbottom, XtChainTop);
2634 XtSetValues(titleWidget, args, 2);
2637 if (appData.showButtonBar) {
2638 widgetList[j++] = buttonBarWidget = CreateButtonBar(buttonBar);
2639 XtSetArg(args[0], XtNleft, XtChainRight); // [HGM] glue to right window edge
2640 XtSetArg(args[1], XtNright, XtChainRight); // for good run-time sizing
2641 XtSetArg(args[2], XtNtop, XtChainTop);
2642 XtSetArg(args[3], XtNbottom, XtChainTop);
2643 XtSetValues(buttonBarWidget, args, 4);
2646 widgetList[j++] = messageWidget =
2647 XtCreateWidget("message", labelWidgetClass, formWidget,
2648 messageArgs, XtNumber(messageArgs));
2649 XtSetArg(args[0], XtNtop, XtChainTop);
2650 XtSetArg(args[1], XtNbottom, XtChainTop);
2651 XtSetValues(messageWidget, args, 2);
2653 widgetList[j++] = boardWidget =
2654 XtCreateWidget("board", widgetClass, formWidget, boardArgs,
2655 XtNumber(boardArgs));
2657 XtManageChildren(widgetList, j);
2659 timerWidth = (boardWidth - sep) / 2;
2660 XtSetArg(args[0], XtNwidth, timerWidth);
2661 XtSetValues(whiteTimerWidget, args, 1);
2662 XtSetValues(blackTimerWidget, args, 1);
2664 XtSetArg(args[0], XtNbackground, &timerBackgroundPixel);
2665 XtSetArg(args[1], XtNforeground, &timerForegroundPixel);
2666 XtGetValues(whiteTimerWidget, args, 2);
2668 if (appData.showButtonBar) {
2669 XtSetArg(args[0], XtNbackground, &buttonBackgroundPixel);
2670 XtSetArg(args[1], XtNforeground, &buttonForegroundPixel);
2671 XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
2675 * formWidget uses these constraints but they are stored
2679 XtSetArg(args[i], XtNfromHoriz, 0); i++;
2680 XtSetValues(menuBarWidget, args, i);
2681 if (appData.titleInWindow) {
2684 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2685 XtSetValues(whiteTimerWidget, args, i);
2687 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2688 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2689 XtSetValues(blackTimerWidget, args, i);
2691 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2692 XtSetArg(args[i], XtNjustify, XtJustifyLeft); i++;
2693 XtSetValues(titleWidget, args, i);
2695 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2696 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2697 XtSetValues(messageWidget, args, i);
2698 if (appData.showButtonBar) {
2700 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2701 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2702 XtSetValues(buttonBarWidget, args, i);
2706 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2707 XtSetValues(whiteTimerWidget, args, i);
2709 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2710 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2711 XtSetValues(blackTimerWidget, args, i);
2713 XtSetArg(args[i], XtNfromHoriz, menuBarWidget); i++;
2714 XtSetValues(titleWidget, args, i);
2716 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2717 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2718 XtSetValues(messageWidget, args, i);
2719 if (appData.showButtonBar) {
2721 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2722 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2723 XtSetValues(buttonBarWidget, args, i);
2728 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2729 XtSetValues(whiteTimerWidget, args, i);
2731 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2732 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2733 XtSetValues(blackTimerWidget, args, i);
2735 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2736 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2737 XtSetValues(messageWidget, args, i);
2738 if (appData.showButtonBar) {
2740 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2741 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2742 XtSetValues(buttonBarWidget, args, i);
2746 XtSetArg(args[0], XtNfromVert, messageWidget);
2747 XtSetArg(args[1], XtNtop, XtChainTop);
2748 XtSetArg(args[2], XtNbottom, XtChainBottom);
2749 XtSetArg(args[3], XtNleft, XtChainLeft);
2750 XtSetArg(args[4], XtNright, XtChainRight);
2751 XtSetValues(boardWidget, args, 5);
2753 XtRealizeWidget(shellWidget);
2756 * Correct the width of the message and title widgets.
2757 * It is not known why some systems need the extra fudge term.
2758 * The value "2" is probably larger than needed.
2760 XawFormDoLayout(formWidget, False);
2762 #define WIDTH_FUDGE 2
2764 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2765 XtSetArg(args[i], XtNheight, &h); i++;
2766 XtGetValues(messageWidget, args, i);
2767 if (appData.showButtonBar) {
2769 XtSetArg(args[i], XtNwidth, &w); i++;
2770 XtGetValues(buttonBarWidget, args, i);
2771 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2773 w = boardWidth - 2*bor + 1; /*!! +1 compensates for kludge below */
2776 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2777 if (gres != XtGeometryYes && appData.debugMode) {
2778 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2779 programName, gres, w, h, wr, hr);
2782 /* !! Horrible hack to work around bug in XFree86 4.0.1 (X11R6.4.3) */
2783 /* The size used for the child widget in layout lags one resize behind
2784 its true size, so we resize a second time, 1 pixel smaller. Yeech! */
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 XtSetArg(args[0], XtNleft, XtChainLeft); // [HGM] glue ends for good run-time sizing
2793 XtSetArg(args[1], XtNright, XtChainRight);
2794 XtSetValues(messageWidget, args, 2);
2796 if (appData.titleInWindow) {
2798 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2799 XtSetArg(args[i], XtNheight, &h); i++;
2800 XtGetValues(titleWidget, args, i);
2802 w = boardWidth - 2*bor;
2804 XtSetArg(args[0], XtNwidth, &w);
2805 XtGetValues(menuBarWidget, args, 1);
2806 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2809 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
2810 if (gres != XtGeometryYes && appData.debugMode) {
2812 _("%s: titleWidget geometry error %d %d %d %d %d\n"),
2813 programName, gres, w, h, wr, hr);
2816 XawFormDoLayout(formWidget, True);
2818 xBoardWindow = XtWindow(boardWidget);
2820 // [HGM] it seems the layout code ends here, but perhaps the color stuff is size independent and would
2821 // not need to go into InitDrawingSizes().
2825 * Create X checkmark bitmap and initialize option menu checks.
2827 ReadBitmap(&xMarkPixmap, "checkmark.bm",
2828 checkmark_bits, checkmark_width, checkmark_height);
2829 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
2830 if (appData.alwaysPromoteToQueen) {
2831 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
2834 if (appData.animateDragging) {
2835 XtSetValues(XtNameToWidget(menuBarWidget,
2836 "menuOptions.Animate Dragging"),
2839 if (appData.animate) {
2840 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
2843 if (appData.autoComment) {
2844 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
2847 if (appData.autoCallFlag) {
2848 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
2851 if (appData.autoFlipView) {
2852 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Auto Flip View"),
2855 if (appData.autoObserve) {
2856 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
2859 if (appData.autoRaiseBoard) {
2860 XtSetValues(XtNameToWidget(menuBarWidget,
2861 "menuOptions.Auto Raise Board"), args, 1);
2863 if (appData.autoSaveGames) {
2864 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
2867 if (appData.saveGameFile[0] != NULLCHAR) {
2868 /* Can't turn this off from menu */
2869 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
2871 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
2875 if (appData.blindfold) {
2876 XtSetValues(XtNameToWidget(menuBarWidget,
2877 "menuOptions.Blindfold"), args, 1);
2879 if (appData.flashCount > 0) {
2880 XtSetValues(XtNameToWidget(menuBarWidget,
2881 "menuOptions.Flash Moves"),
2884 if (appData.getMoveList) {
2885 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
2889 if (appData.highlightDragging) {
2890 XtSetValues(XtNameToWidget(menuBarWidget,
2891 "menuOptions.Highlight Dragging"),
2895 if (appData.highlightLastMove) {
2896 XtSetValues(XtNameToWidget(menuBarWidget,
2897 "menuOptions.Highlight Last Move"),
2900 if (appData.icsAlarm) {
2901 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.ICS Alarm"),
2904 if (appData.ringBellAfterMoves) {
2905 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
2908 if (appData.oldSaveStyle) {
2909 XtSetValues(XtNameToWidget(menuBarWidget,
2910 "menuOptions.Old Save Style"), args, 1);
2912 if (appData.periodicUpdates) {
2913 XtSetValues(XtNameToWidget(menuBarWidget,
2914 "menuOptions.Periodic Updates"), args, 1);
2916 if (appData.ponderNextMove) {
2917 XtSetValues(XtNameToWidget(menuBarWidget,
2918 "menuOptions.Ponder Next Move"), args, 1);
2920 if (appData.popupExitMessage) {
2921 XtSetValues(XtNameToWidget(menuBarWidget,
2922 "menuOptions.Popup Exit Message"), args, 1);
2924 if (appData.popupMoveErrors) {
2925 XtSetValues(XtNameToWidget(menuBarWidget,
2926 "menuOptions.Popup Move Errors"), args, 1);
2928 if (appData.premove) {
2929 XtSetValues(XtNameToWidget(menuBarWidget,
2930 "menuOptions.Premove"), args, 1);
2932 if (appData.quietPlay) {
2933 XtSetValues(XtNameToWidget(menuBarWidget,
2934 "menuOptions.Quiet Play"), args, 1);
2936 if (appData.showCoords) {
2937 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
2940 if (appData.hideThinkingFromHuman) {
2941 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
2944 if (appData.testLegality) {
2945 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Test Legality"),
2952 ReadBitmap(&wIconPixmap, "icon_white.bm",
2953 icon_white_bits, icon_white_width, icon_white_height);
2954 ReadBitmap(&bIconPixmap, "icon_black.bm",
2955 icon_black_bits, icon_black_width, icon_black_height);
2956 iconPixmap = wIconPixmap;
2958 XtSetArg(args[i], XtNiconPixmap, iconPixmap); i++;
2959 XtSetValues(shellWidget, args, i);
2962 * Create a cursor for the board widget.
2964 window_attributes.cursor = XCreateFontCursor(xDisplay, XC_hand2);
2965 XChangeWindowAttributes(xDisplay, xBoardWindow,
2966 CWCursor, &window_attributes);
2969 * Inhibit shell resizing.
2971 shellArgs[0].value = (XtArgVal) &w;
2972 shellArgs[1].value = (XtArgVal) &h;
2973 XtGetValues(shellWidget, shellArgs, 2);
2974 shellArgs[4].value = shellArgs[2].value = w;
2975 shellArgs[5].value = shellArgs[3].value = h;
2976 XtSetValues(shellWidget, &shellArgs[2], 4);
2977 marginW = w - boardWidth; // [HGM] needed to set new shellWidget size when we resize board
2978 marginH = h - boardHeight;
2980 CatchDeleteWindow(shellWidget, "QuitProc");
2985 if (appData.bitmapDirectory[0] != NULLCHAR) {
2992 /* Create regular pieces */
2993 if (!useImages) CreatePieces();
2998 if (appData.animate || appData.animateDragging)
3001 XtAugmentTranslations(formWidget,
3002 XtParseTranslationTable(globalTranslations));
3003 XtAugmentTranslations(boardWidget,
3004 XtParseTranslationTable(boardTranslations));
3005 XtAugmentTranslations(whiteTimerWidget,
3006 XtParseTranslationTable(whiteTranslations));
3007 XtAugmentTranslations(blackTimerWidget,
3008 XtParseTranslationTable(blackTranslations));
3010 /* Why is the following needed on some versions of X instead
3011 * of a translation? */
3012 XtAddEventHandler(boardWidget, ExposureMask, False,
3013 (XtEventHandler) EventProc, NULL);
3018 if (errorExitStatus == -1) {
3019 if (appData.icsActive) {
3020 /* We now wait until we see "login:" from the ICS before
3021 sending the logon script (problems with timestamp otherwise) */
3022 /*ICSInitScript();*/
3023 if (appData.icsInputBox) ICSInputBoxPopUp();
3026 signal(SIGINT, IntSigHandler);
3027 signal(SIGTERM, IntSigHandler);
3028 if (*appData.cmailGameName != NULLCHAR) {
3029 signal(SIGUSR1, CmailSigHandler);
3034 XtAppMainLoop(appContext);
3035 if (appData.debugMode) fclose(debugFP); // [DM] debug
3042 if (appData.icsActive && oldICSInteractionTitle != NULL) {
3043 DisplayIcsInteractionTitle(oldICSInteractionTitle);
3045 unlink(gameCopyFilename);
3046 unlink(gamePasteFilename);
3057 CmailSigHandler(sig)
3063 signal(SIGUSR1, SIG_IGN); /* suspend handler */
3065 /* Activate call-back function CmailSigHandlerCallBack() */
3066 OutputToProcess(cmailPR, (char *)(&dummy), sizeof(int), &error);
3068 signal(SIGUSR1, CmailSigHandler); /* re-activate handler */
3072 CmailSigHandlerCallBack(isr, closure, message, count, error)
3080 ReloadCmailMsgEvent(TRUE); /* Reload cmail msg */
3082 /**** end signal code ****/
3092 f = fopen(appData.icsLogon, "r");
3098 strcat(buf, appData.icsLogon);
3099 f = fopen(buf, "r");
3103 ProcessICSInitScript(f);
3110 EditCommentPopDown();
3121 SetMenuEnables(enab)
3125 if (!menuBarWidget) return;
3126 while (enab->name != NULL) {
3127 w = XtNameToWidget(menuBarWidget, enab->name);
3129 DisplayError(enab->name, 0);
3131 XtSetSensitive(w, enab->value);
3137 Enables icsEnables[] = {
3138 { "menuFile.Mail Move", False },
3139 { "menuFile.Reload CMail Message", False },
3140 { "menuMode.Machine Black", False },
3141 { "menuMode.Machine White", False },
3142 { "menuMode.Analysis Mode", False },
3143 { "menuMode.Analyze File", False },
3144 { "menuMode.Two Machines", False },
3146 { "menuHelp.Hint", False },
3147 { "menuHelp.Book", False },
3148 { "menuStep.Move Now", False },
3149 { "menuOptions.Periodic Updates", False },
3150 { "menuOptions.Hide Thinking", False },
3151 { "menuOptions.Ponder Next Move", False },
3156 Enables ncpEnables[] = {
3157 { "menuFile.Mail Move", False },
3158 { "menuFile.Reload CMail Message", False },
3159 { "menuMode.Machine White", False },
3160 { "menuMode.Machine Black", False },
3161 { "menuMode.Analysis Mode", False },
3162 { "menuMode.Analyze File", False },
3163 { "menuMode.Two Machines", False },
3164 { "menuMode.ICS Client", False },
3165 { "menuMode.ICS Input Box", False },
3166 { "Action", False },
3167 { "menuStep.Revert", False },
3168 { "menuStep.Move Now", False },
3169 { "menuStep.Retract Move", False },
3170 { "menuOptions.Auto Comment", False },
3171 { "menuOptions.Auto Flag", False },
3172 { "menuOptions.Auto Flip View", False },
3173 { "menuOptions.Auto Observe", False },
3174 { "menuOptions.Auto Raise Board", False },
3175 { "menuOptions.Get Move List", False },
3176 { "menuOptions.ICS Alarm", False },
3177 { "menuOptions.Move Sound", False },
3178 { "menuOptions.Quiet Play", False },
3179 { "menuOptions.Hide Thinking", False },
3180 { "menuOptions.Periodic Updates", False },
3181 { "menuOptions.Ponder Next Move", False },
3182 { "menuHelp.Hint", False },
3183 { "menuHelp.Book", False },
3187 Enables gnuEnables[] = {
3188 { "menuMode.ICS Client", False },
3189 { "menuMode.ICS Input Box", False },
3190 { "menuAction.Accept", False },
3191 { "menuAction.Decline", False },
3192 { "menuAction.Rematch", False },
3193 { "menuAction.Adjourn", False },
3194 { "menuAction.Stop Examining", False },
3195 { "menuAction.Stop Observing", False },
3196 { "menuStep.Revert", False },
3197 { "menuOptions.Auto Comment", False },
3198 { "menuOptions.Auto Observe", False },
3199 { "menuOptions.Auto Raise Board", False },
3200 { "menuOptions.Get Move List", False },
3201 { "menuOptions.Premove", False },
3202 { "menuOptions.Quiet Play", False },
3204 /* The next two options rely on SetCmailMode being called *after* */
3205 /* SetGNUMode so that when GNU is being used to give hints these */
3206 /* menu options are still available */
3208 { "menuFile.Mail Move", False },
3209 { "menuFile.Reload CMail Message", False },
3213 Enables cmailEnables[] = {
3215 { "menuAction.Call Flag", False },
3216 { "menuAction.Draw", True },
3217 { "menuAction.Adjourn", False },
3218 { "menuAction.Abort", False },
3219 { "menuAction.Stop Observing", False },
3220 { "menuAction.Stop Examining", False },
3221 { "menuFile.Mail Move", True },
3222 { "menuFile.Reload CMail Message", True },
3226 Enables trainingOnEnables[] = {
3227 { "menuMode.Edit Comment", False },
3228 { "menuMode.Pause", False },
3229 { "menuStep.Forward", False },
3230 { "menuStep.Backward", False },
3231 { "menuStep.Forward to End", False },
3232 { "menuStep.Back to Start", False },
3233 { "menuStep.Move Now", False },
3234 { "menuStep.Truncate Game", False },
3238 Enables trainingOffEnables[] = {
3239 { "menuMode.Edit Comment", True },
3240 { "menuMode.Pause", True },
3241 { "menuStep.Forward", True },
3242 { "menuStep.Backward", True },
3243 { "menuStep.Forward to End", True },
3244 { "menuStep.Back to Start", True },
3245 { "menuStep.Move Now", True },
3246 { "menuStep.Truncate Game", True },
3250 Enables machineThinkingEnables[] = {
3251 { "menuFile.Load Game", False },
3252 { "menuFile.Load Next Game", False },
3253 { "menuFile.Load Previous Game", False },
3254 { "menuFile.Reload Same Game", False },
3255 { "menuFile.Paste Game", False },
3256 { "menuFile.Load Position", False },
3257 { "menuFile.Load Next Position", False },
3258 { "menuFile.Load Previous Position", False },
3259 { "menuFile.Reload Same Position", False },
3260 { "menuFile.Paste Position", False },
3261 { "menuMode.Machine White", False },
3262 { "menuMode.Machine Black", False },
3263 { "menuMode.Two Machines", False },
3264 { "menuStep.Retract Move", False },
3268 Enables userThinkingEnables[] = {
3269 { "menuFile.Load Game", True },
3270 { "menuFile.Load Next Game", True },
3271 { "menuFile.Load Previous Game", True },
3272 { "menuFile.Reload Same Game", True },
3273 { "menuFile.Paste Game", True },
3274 { "menuFile.Load Position", True },
3275 { "menuFile.Load Next Position", True },
3276 { "menuFile.Load Previous Position", True },
3277 { "menuFile.Reload Same Position", True },
3278 { "menuFile.Paste Position", True },
3279 { "menuMode.Machine White", True },
3280 { "menuMode.Machine Black", True },
3281 { "menuMode.Two Machines", True },
3282 { "menuStep.Retract Move", True },
3288 SetMenuEnables(icsEnables);
3291 if (appData.zippyPlay && !appData.noChessProgram) /* [DM] icsEngineAnalyze */
3292 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Analysis Mode"), True);
3299 SetMenuEnables(ncpEnables);
3305 SetMenuEnables(gnuEnables);
3311 SetMenuEnables(cmailEnables);
3317 SetMenuEnables(trainingOnEnables);
3318 if (appData.showButtonBar) {
3319 XtSetSensitive(buttonBarWidget, False);
3325 SetTrainingModeOff()
3327 SetMenuEnables(trainingOffEnables);
3328 if (appData.showButtonBar) {
3329 XtSetSensitive(buttonBarWidget, True);
3334 SetUserThinkingEnables()
3336 if (appData.noChessProgram) return;
3337 SetMenuEnables(userThinkingEnables);
3341 SetMachineThinkingEnables()
3343 if (appData.noChessProgram) return;
3344 SetMenuEnables(machineThinkingEnables);
3346 case MachinePlaysBlack:
3347 case MachinePlaysWhite:
3348 case TwoMachinesPlay:
3349 XtSetSensitive(XtNameToWidget(menuBarWidget,
3350 ModeToWidgetName(gameMode)), True);
3357 #define Abs(n) ((n)<0 ? -(n) : (n))
3360 * Find a font that matches "pattern" that is as close as
3361 * possible to the targetPxlSize. Prefer fonts that are k
3362 * pixels smaller to fonts that are k pixels larger. The
3363 * pattern must be in the X Consortium standard format,
3364 * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".
3365 * The return value should be freed with XtFree when no
3368 char *FindFont(pattern, targetPxlSize)
3372 char **fonts, *p, *best, *scalable, *scalableTail;
3373 int i, j, nfonts, minerr, err, pxlSize;
3376 char **missing_list;
3378 char *def_string, *base_fnt_lst, strInt[3];
3380 XFontStruct **fnt_list;
3382 base_fnt_lst = calloc(1, strlen(pattern) + 3);
3383 sprintf(strInt, "%d", targetPxlSize);
3384 p = strstr(pattern, "--");
3385 strncpy(base_fnt_lst, pattern, p - pattern + 2);
3386 strcat(base_fnt_lst, strInt);
3387 strcat(base_fnt_lst, strchr(p + 2, '-'));
3389 if ((fntSet = XCreateFontSet(xDisplay,
3393 &def_string)) == NULL) {
3395 fprintf(stderr, _("Unable to create font set.\n"));
3399 nfonts = XFontsOfFontSet(fntSet, &fnt_list, &fonts);
3401 fonts = XListFonts(xDisplay, pattern, 999999, &nfonts);
3403 fprintf(stderr, _("%s: no fonts match pattern %s\n"),
3404 programName, pattern);
3412 for (i=0; i<nfonts; i++) {
3415 if (*p != '-') continue;
3417 if (*p == NULLCHAR) break;
3418 if (*p++ == '-') j++;
3420 if (j < 7) continue;
3423 scalable = fonts[i];
3426 err = pxlSize - targetPxlSize;
3427 if (Abs(err) < Abs(minerr) ||
3428 (minerr > 0 && err < 0 && -err == minerr)) {
3434 if (scalable && Abs(minerr) > appData.fontSizeTolerance) {
3435 /* If the error is too big and there is a scalable font,
3436 use the scalable font. */
3437 int headlen = scalableTail - scalable;
3438 p = (char *) XtMalloc(strlen(scalable) + 10);
3439 while (isdigit(*scalableTail)) scalableTail++;
3440 sprintf(p, "%.*s%d%s", headlen, scalable, targetPxlSize, scalableTail);
3442 p = (char *) XtMalloc(strlen(best) + 1);
3445 if (appData.debugMode) {
3446 fprintf(debugFP, _("resolved %s at pixel size %d\n to %s\n"),
3447 pattern, targetPxlSize, p);
3450 if (missing_count > 0)
3451 XFreeStringList(missing_list);
3452 XFreeFontSet(xDisplay, fntSet);
3454 XFreeFontNames(fonts);
3461 XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
3462 | GCBackground | GCFunction | GCPlaneMask;
3463 XGCValues gc_values;
3466 gc_values.plane_mask = AllPlanes;
3467 gc_values.line_width = lineGap;
3468 gc_values.line_style = LineSolid;
3469 gc_values.function = GXcopy;
3471 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3472 gc_values.background = XBlackPixel(xDisplay, xScreen);
3473 lineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3475 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3476 gc_values.background = XWhitePixel(xDisplay, xScreen);
3477 coordGC = XtGetGC(shellWidget, value_mask, &gc_values);
3478 XSetFont(xDisplay, coordGC, coordFontID);
3480 // [HGM] make font for holdings counts (white on black0
3481 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3482 gc_values.background = XBlackPixel(xDisplay, xScreen);
3483 countGC = XtGetGC(shellWidget, value_mask, &gc_values);
3484 XSetFont(xDisplay, countGC, countFontID);
3486 if (appData.monoMode) {
3487 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3488 gc_values.background = XWhitePixel(xDisplay, xScreen);
3489 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3491 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3492 gc_values.background = XBlackPixel(xDisplay, xScreen);
3493 lightSquareGC = wbPieceGC
3494 = XtGetGC(shellWidget, value_mask, &gc_values);
3496 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3497 gc_values.background = XWhitePixel(xDisplay, xScreen);
3498 darkSquareGC = bwPieceGC
3499 = XtGetGC(shellWidget, value_mask, &gc_values);
3501 if (DefaultDepth(xDisplay, xScreen) == 1) {
3502 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
3503 gc_values.function = GXcopyInverted;
3504 copyInvertedGC = XtGetGC(shellWidget, value_mask, &gc_values);
3505 gc_values.function = GXcopy;
3506 if (XBlackPixel(xDisplay, xScreen) == 1) {
3507 bwPieceGC = darkSquareGC;
3508 wbPieceGC = copyInvertedGC;
3510 bwPieceGC = copyInvertedGC;
3511 wbPieceGC = lightSquareGC;
3515 gc_values.foreground = highlightSquareColor;
3516 gc_values.background = highlightSquareColor;
3517 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3519 gc_values.foreground = premoveHighlightColor;
3520 gc_values.background = premoveHighlightColor;
3521 prelineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3523 gc_values.foreground = lightSquareColor;
3524 gc_values.background = darkSquareColor;
3525 lightSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3527 gc_values.foreground = darkSquareColor;
3528 gc_values.background = lightSquareColor;
3529 darkSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3531 gc_values.foreground = jailSquareColor;
3532 gc_values.background = jailSquareColor;
3533 jailSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3535 gc_values.foreground = whitePieceColor;
3536 gc_values.background = darkSquareColor;
3537 wdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3539 gc_values.foreground = whitePieceColor;
3540 gc_values.background = lightSquareColor;
3541 wlPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3543 gc_values.foreground = whitePieceColor;
3544 gc_values.background = jailSquareColor;
3545 wjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3547 gc_values.foreground = blackPieceColor;
3548 gc_values.background = darkSquareColor;
3549 bdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3551 gc_values.foreground = blackPieceColor;
3552 gc_values.background = lightSquareColor;
3553 blPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3555 gc_values.foreground = blackPieceColor;
3556 gc_values.background = jailSquareColor;
3557 bjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3561 void loadXIM(xim, xmask, filename, dest, mask)
3574 fp = fopen(filename, "rb");
3576 fprintf(stderr, _("%s: error loading XIM!\n"), programName);
3583 for (y=0; y<h; ++y) {
3584 for (x=0; x<h; ++x) {
3589 XPutPixel(xim, x, y, blackPieceColor);
3591 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3594 XPutPixel(xim, x, y, darkSquareColor);
3596 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3599 XPutPixel(xim, x, y, whitePieceColor);
3601 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3604 XPutPixel(xim, x, y, lightSquareColor);
3606 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3612 /* create Pixmap of piece */
3613 *dest = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3615 XPutImage(xDisplay, *dest, lightSquareGC, xim,
3618 /* create Pixmap of clipmask
3619 Note: We assume the white/black pieces have the same
3620 outline, so we make only 6 masks. This is okay
3621 since the XPM clipmask routines do the same. */
3623 temp = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3625 XPutImage(xDisplay, temp, lightSquareGC, xmask,
3628 /* now create the 1-bit version */
3629 *mask = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3632 values.foreground = 1;
3633 values.background = 0;
3635 /* Don't use XtGetGC, not read only */
3636 maskGC = XCreateGC(xDisplay, *mask,
3637 GCForeground | GCBackground, &values);
3638 XCopyPlane(xDisplay, temp, *mask, maskGC,
3639 0, 0, squareSize, squareSize, 0, 0, 1);
3640 XFreePixmap(xDisplay, temp);
3644 void CreateXIMPieces()
3649 static char *ximkind[] = { "ll", "ld", "dl", "dd" };
3654 /* The XSynchronize calls were copied from CreatePieces.
3655 Not sure if needed, but can't hurt */
3656 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3659 /* temp needed by loadXIM() */
3660 ximtemp = XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3661 0, 0, ss, ss, AllPlanes, XYPixmap);
3663 if (strlen(appData.pixmapDirectory) == 0) {
3667 if (appData.monoMode) {
3668 DisplayFatalError(_("XIM pieces cannot be used in monochrome mode"),
3672 fprintf(stderr, _("\nLoading XIMs...\n"));
3674 for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
3675 fprintf(stderr, "%d", piece+1);
3676 for (kind=0; kind<4; kind++) {
3677 fprintf(stderr, ".");
3678 sprintf(buf, "%s/%c%s%u.xim",
3679 ExpandPathName(appData.pixmapDirectory),
3680 ToLower(PieceToChar((ChessSquare)piece)),
3682 ximPieceBitmap[kind][piece] =
3683 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3684 0, 0, ss, ss, AllPlanes, XYPixmap);
3685 if (appData.debugMode)
3686 fprintf(stderr, _("(File:%s:) "), buf);
3687 loadXIM(ximPieceBitmap[kind][piece],
3689 &(xpmPieceBitmap[kind][piece]),
3690 &(ximMaskPm[piece%(int)BlackPawn]));
3692 fprintf(stderr," ");
3694 /* Load light and dark squares */
3695 /* If the LSQ and DSQ pieces don't exist, we will
3696 draw them with solid squares. */
3697 sprintf(buf, "%s/lsq%u.xim", ExpandPathName(appData.pixmapDirectory), ss);
3698 if (access(buf, 0) != 0) {
3702 fprintf(stderr, _("light square "));
3704 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3705 0, 0, ss, ss, AllPlanes, XYPixmap);
3706 if (appData.debugMode)
3707 fprintf(stderr, _("(File:%s:) "), buf);
3709 loadXIM(ximLightSquare, NULL, buf, &xpmLightSquare, NULL);
3710 fprintf(stderr, _("dark square "));
3711 sprintf(buf, "%s/dsq%u.xim",
3712 ExpandPathName(appData.pixmapDirectory), ss);
3713 if (appData.debugMode)
3714 fprintf(stderr, _("(File:%s:) "), buf);
3716 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3717 0, 0, ss, ss, AllPlanes, XYPixmap);
3718 loadXIM(ximDarkSquare, NULL, buf, &xpmDarkSquare, NULL);
3719 xpmJailSquare = xpmLightSquare;
3721 fprintf(stderr, _("Done.\n"));
3723 XSynchronize(xDisplay, False); /* Work-around for xlib/xt buffering bug */
3727 void CreateXPMPieces()
3731 u_int ss = squareSize;
3733 static char *xpmkind[] = { "ll", "ld", "dl", "dd" };
3734 XpmColorSymbol symbols[4];
3737 /* Apparently some versions of Xpm don't define XpmFormat at all --tpm */
3738 if (appData.debugMode) {
3739 fprintf(stderr, "XPM Library Version: %d.%d%c\n",
3740 XpmFormat, XpmVersion, (char)('a' + XpmRevision - 1));
3744 /* The XSynchronize calls were copied from CreatePieces.
3745 Not sure if needed, but can't hurt */
3746 XSynchronize(xDisplay, True); /* Work-around for xlib/xt buffering bug */
3748 /* Setup translations so piece colors match square colors */
3749 symbols[0].name = "light_piece";
3750 symbols[0].value = appData.whitePieceColor;
3751 symbols[1].name = "dark_piece";
3752 symbols[1].value = appData.blackPieceColor;
3753 symbols[2].name = "light_square";
3754 symbols[2].value = appData.lightSquareColor;
3755 symbols[3].name = "dark_square";
3756 symbols[3].value = appData.darkSquareColor;
3758 attr.valuemask = XpmColorSymbols;
3759 attr.colorsymbols = symbols;
3760 attr.numsymbols = 4;
3762 if (appData.monoMode) {
3763 DisplayFatalError(_("XPM pieces cannot be used in monochrome mode"),
3767 if (strlen(appData.pixmapDirectory) == 0) {
3768 XpmPieces* pieces = builtInXpms;
3771 while (pieces->size != squareSize && pieces->size) pieces++;
3772 if (!pieces->size) {
3773 fprintf(stderr, _("No builtin XPM pieces of size %d\n"), squareSize);
3776 for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
3777 for (kind=0; kind<4; kind++) {
3779 if ((r=XpmCreatePixmapFromData(xDisplay, xBoardWindow,
3780 pieces->xpm[piece][kind],
3781 &(xpmPieceBitmap[kind][piece]),
3782 NULL, &attr)) != 0) {
3783 fprintf(stderr, _("Error %d loading XPM image \"%s\"\n"),
3790 xpmJailSquare = xpmLightSquare;
3794 fprintf(stderr, _("\nLoading XPMs...\n"));
3797 for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
3798 fprintf(stderr, "%d ", piece+1);
3799 for (kind=0; kind<4; kind++) {
3800 sprintf(buf, "%s/%c%s%u.xpm",
3801 ExpandPathName(appData.pixmapDirectory),
3802 ToLower(PieceToChar((ChessSquare)piece)),
3804 if (appData.debugMode) {
3805 fprintf(stderr, _("(File:%s:) "), buf);
3807 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3808 &(xpmPieceBitmap[kind][piece]),
3809 NULL, &attr)) != 0) {
3810 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"),
3816 /* Load light and dark squares */
3817 /* If the LSQ and DSQ pieces don't exist, we will
3818 draw them with solid squares. */
3819 fprintf(stderr, _("light square "));
3820 sprintf(buf, "%s/lsq%u.xpm", ExpandPathName(appData.pixmapDirectory), ss);
3821 if (access(buf, 0) != 0) {
3825 if (appData.debugMode)
3826 fprintf(stderr, _("(File:%s:) "), buf);
3828 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3829 &xpmLightSquare, NULL, &attr)) != 0) {
3830 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
3833 fprintf(stderr, _("dark square "));
3834 sprintf(buf, "%s/dsq%u.xpm",
3835 ExpandPathName(appData.pixmapDirectory), ss);
3836 if (appData.debugMode) {
3837 fprintf(stderr, _("(File:%s:) "), buf);
3839 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3840 &xpmDarkSquare, NULL, &attr)) != 0) {
3841 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
3845 xpmJailSquare = xpmLightSquare;
3846 fprintf(stderr, _("Done.\n"));
3848 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3851 #endif /* HAVE_LIBXPM */
3854 /* No built-in bitmaps */
3859 u_int ss = squareSize;
3861 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3864 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
3865 for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
3866 sprintf(buf, "%c%u%c.bm", ToLower(PieceToChar((ChessSquare)piece)),
3867 ss, kind == SOLID ? 's' : 'o');
3868 ReadBitmap(&pieceBitmap[kind][piece], buf, NULL, ss, ss);
3872 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3876 /* With built-in bitmaps */
3879 BuiltInBits* bib = builtInBits;
3882 u_int ss = squareSize;
3884 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3887 while (bib->squareSize != ss && bib->squareSize != 0) bib++;
3889 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
3890 for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
3891 sprintf(buf, "%c%u%c.bm", ToLower(PieceToChar((ChessSquare)piece)),
3892 ss, kind == SOLID ? 's' : 'o');
3893 ReadBitmap(&pieceBitmap[kind][piece], buf,
3894 bib->bits[kind][piece], ss, ss);
3898 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3903 void ReadBitmap(pm, name, bits, wreq, hreq)
3906 unsigned char bits[];
3912 char msg[MSG_SIZ], fullname[MSG_SIZ];
3914 if (*appData.bitmapDirectory != NULLCHAR) {
3915 strcpy(fullname, appData.bitmapDirectory);
3916 strcat(fullname, "/");
3917 strcat(fullname, name);
3918 errcode = XReadBitmapFile(xDisplay, xBoardWindow, fullname,
3919 &w, &h, pm, &x_hot, &y_hot);
3920 if (errcode != BitmapSuccess) {
3922 case BitmapOpenFailed:
3923 sprintf(msg, _("Can't open bitmap file %s"), fullname);
3925 case BitmapFileInvalid:
3926 sprintf(msg, _("Invalid bitmap in file %s"), fullname);
3928 case BitmapNoMemory:
3929 sprintf(msg, _("Ran out of memory reading bitmap file %s"),
3933 sprintf(msg, _("Unknown XReadBitmapFile error %d on file %s"),
3937 fprintf(stderr, _("%s: %s...using built-in\n"),
3939 } else if (w != wreq || h != hreq) {
3941 _("%s: Bitmap %s is %dx%d, not %dx%d...using built-in\n"),
3942 programName, fullname, w, h, wreq, hreq);
3949 fprintf(stderr, _("%s: No built-in bitmap for %s; giving up\n"),
3953 ; // [HGM] bitmaps: make it non-fatal if we have no bitmap;
3955 *pm = XCreateBitmapFromData(xDisplay, xBoardWindow, (char *) bits,
3964 if (lineGap == 0) return;
3966 /* [HR] Split this into 2 loops for non-square boards. */
3968 for (i = 0; i < BOARD_HEIGHT + 1; i++) {
3969 gridSegments[i].x1 = 0;
3970 gridSegments[i].x2 =
3971 lineGap + BOARD_WIDTH * (squareSize + lineGap);
3972 gridSegments[i].y1 = gridSegments[i].y2
3973 = lineGap / 2 + (i * (squareSize + lineGap));
3976 for (j = 0; j < BOARD_WIDTH + 1; j++) {
3977 gridSegments[j + i].y1 = 0;
3978 gridSegments[j + i].y2 =
3979 lineGap + BOARD_HEIGHT * (squareSize + lineGap);
3980 gridSegments[j + i].x1 = gridSegments[j + i].x2
3981 = lineGap / 2 + (j * (squareSize + lineGap));
3985 static void MenuBarSelect(w, addr, index)
3990 XtActionProc proc = (XtActionProc) addr;
3992 (proc)(NULL, NULL, NULL, NULL);
3995 void CreateMenuBarPopup(parent, name, mb)
4005 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
4008 XtSetArg(args[j], XtNleftMargin, 20); j++;
4009 XtSetArg(args[j], XtNrightMargin, 20); j++;
4011 while (mi->string != NULL) {
4012 if (strcmp(mi->string, "----") == 0) {
4013 entry = XtCreateManagedWidget(mi->string, smeLineObjectClass,
4016 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string)));
4017 entry = XtCreateManagedWidget(mi->string, smeBSBObjectClass,
4019 XtAddCallback(entry, XtNcallback,
4020 (XtCallbackProc) MenuBarSelect,
4021 (caddr_t) mi->proc);
4027 Widget CreateMenuBar(mb)
4031 Widget anchor, menuBar;
4033 char menuName[MSG_SIZ];
4036 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
4037 XtSetArg(args[j], XtNvSpace, 0); j++;
4038 XtSetArg(args[j], XtNborderWidth, 0); j++;
4039 menuBar = XtCreateWidget("menuBar", boxWidgetClass,
4040 formWidget, args, j);
4042 while (mb->name != NULL) {
4043 strcpy(menuName, "menu");
4044 strcat(menuName, mb->name);
4046 XtSetArg(args[j], XtNmenuName, XtNewString(menuName)); j++;
4049 shortName[0] = _(mb->name)[0];
4050 shortName[1] = NULLCHAR;
4051 XtSetArg(args[j], XtNlabel, XtNewString(shortName)); j++;
4054 XtSetArg(args[j], XtNlabel, XtNewString(_(mb->name))); j++;
4057 XtSetArg(args[j], XtNborderWidth, 0); j++;
4058 anchor = XtCreateManagedWidget(mb->name, menuButtonWidgetClass,
4060 CreateMenuBarPopup(menuBar, menuName, mb);
4066 Widget CreateButtonBar(mi)
4070 Widget button, buttonBar;
4074 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
4076 XtSetArg(args[j], XtNhSpace, 0); j++;
4078 XtSetArg(args[j], XtNborderWidth, 0); j++;
4079 XtSetArg(args[j], XtNvSpace, 0); j++;
4080 buttonBar = XtCreateWidget("buttonBar", boxWidgetClass,
4081 formWidget, args, j);
4083 while (mi->string != NULL) {
4086 XtSetArg(args[j], XtNinternalWidth, 2); j++;
4087 XtSetArg(args[j], XtNborderWidth, 0); j++;
4089 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string))); j++;
4090 button = XtCreateManagedWidget(mi->string, commandWidgetClass,
4091 buttonBar, args, j);
4092 XtAddCallback(button, XtNcallback,
4093 (XtCallbackProc) MenuBarSelect,
4094 (caddr_t) mi->proc);
4101 CreatePieceMenu(name, color)
4108 ChessSquare selection;
4110 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
4111 boardWidget, args, 0);
4113 for (i = 0; i < PIECE_MENU_SIZE; i++) {
4114 String item = pieceMenuStrings[color][i];
4116 if (strcmp(item, "----") == 0) {
4117 entry = XtCreateManagedWidget(item, smeLineObjectClass,
4120 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
4121 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
4123 selection = pieceMenuTranslation[color][i];
4124 XtAddCallback(entry, XtNcallback,
4125 (XtCallbackProc) PieceMenuSelect,
4126 (caddr_t) selection);
4127 if (selection == WhitePawn || selection == BlackPawn) {
4128 XtSetArg(args[0], XtNpopupOnEntry, entry);
4129 XtSetValues(menu, args, 1);
4142 ChessSquare selection;
4144 whitePieceMenu = CreatePieceMenu("menuW", 0);
4145 blackPieceMenu = CreatePieceMenu("menuB", 1);
4147 XtRegisterGrabAction(PieceMenuPopup, True,
4148 (unsigned)(ButtonPressMask|ButtonReleaseMask),
4149 GrabModeAsync, GrabModeAsync);
4151 XtSetArg(args[0], XtNlabel, _("Drop"));
4152 dropMenu = XtCreatePopupShell("menuD", simpleMenuWidgetClass,
4153 boardWidget, args, 1);
4154 for (i = 0; i < DROP_MENU_SIZE; i++) {
4155 String item = dropMenuStrings[i];
4157 if (strcmp(item, "----") == 0) {
4158 entry = XtCreateManagedWidget(item, smeLineObjectClass,
4161 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
4162 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
4164 selection = dropMenuTranslation[i];
4165 XtAddCallback(entry, XtNcallback,
4166 (XtCallbackProc) DropMenuSelect,
4167 (caddr_t) selection);
4172 void SetupDropMenu()
4180 for (i=0; i<sizeof(dmEnables)/sizeof(DropMenuEnables); i++) {
4181 entry = XtNameToWidget(dropMenu, dmEnables[i].widget);
4182 p = strchr(gameMode == IcsPlayingWhite ? white_holding : black_holding,
4183 dmEnables[i].piece);
4184 XtSetSensitive(entry, p != NULL || !appData.testLegality
4185 /*!!temp:*/ || (gameInfo.variant == VariantCrazyhouse
4186 && !appData.icsActive));
4188 while (p && *p++ == dmEnables[i].piece) count++;
4189 sprintf(label, "%s %d", dmEnables[i].widget, count);
4191 XtSetArg(args[j], XtNlabel, label); j++;
4192 XtSetValues(entry, args, j);
4196 void PieceMenuPopup(w, event, params, num_params)
4200 Cardinal *num_params;
4203 if (event->type != ButtonPress) return;
4204 if (errorUp) ErrorPopDown();
4208 whichMenu = params[0];
4210 case IcsPlayingWhite:
4211 case IcsPlayingBlack:
4213 case MachinePlaysWhite:
4214 case MachinePlaysBlack:
4215 if (appData.testLegality &&
4216 gameInfo.variant != VariantBughouse &&
4217 gameInfo.variant != VariantCrazyhouse) return;
4219 whichMenu = "menuD";
4225 if (((pmFromX = EventToSquare(event->xbutton.x, BOARD_WIDTH)) < 0) ||
4226 ((pmFromY = EventToSquare(event->xbutton.y, BOARD_HEIGHT)) < 0)) {
4227 pmFromX = pmFromY = -1;
4231 pmFromX = BOARD_WIDTH - 1 - pmFromX;
4233 pmFromY = BOARD_HEIGHT - 1 - pmFromY;
4235 XtPopupSpringLoaded(XtNameToWidget(boardWidget, whichMenu));
4238 static void PieceMenuSelect(w, piece, junk)
4243 if (pmFromX < 0 || pmFromY < 0) return;
4244 EditPositionMenuEvent(piece, pmFromX, pmFromY);
4247 static void DropMenuSelect(w, piece, junk)
4252 if (pmFromX < 0 || pmFromY < 0) return;
4253 DropMenuEvent(piece, pmFromX, pmFromY);
4256 void WhiteClock(w, event, prms, nprms)
4262 if (gameMode == EditPosition || gameMode == IcsExamining) {
4263 SetWhiteToPlayEvent();
4264 } else if (gameMode == IcsPlayingBlack || gameMode == MachinePlaysWhite) {
4269 void BlackClock(w, event, prms, nprms)
4275 if (gameMode == EditPosition || gameMode == IcsExamining) {
4276 SetBlackToPlayEvent();
4277 } else if (gameMode == IcsPlayingWhite || gameMode == MachinePlaysBlack) {
4284 * If the user selects on a border boundary, return -1; if off the board,
4285 * return -2. Otherwise map the event coordinate to the square.
4287 int EventToSquare(x, limit)
4295 if ((x % (squareSize + lineGap)) >= squareSize)
4297 x /= (squareSize + lineGap);
4303 static void do_flash_delay(msec)
4309 static void drawHighlight(file, rank, gc)
4315 if (lineGap == 0 || appData.blindfold) return;
4318 x = lineGap/2 + ((BOARD_WIDTH-1)-file) *
4319 (squareSize + lineGap);
4320 y = lineGap/2 + rank * (squareSize + lineGap);
4322 x = lineGap/2 + file * (squareSize + lineGap);
4323 y = lineGap/2 + ((BOARD_HEIGHT-1)-rank) *
4324 (squareSize + lineGap);
4327 XDrawRectangle(xDisplay, xBoardWindow, gc, x, y,
4328 squareSize+lineGap, squareSize+lineGap);
4331 int hi1X = -1, hi1Y = -1, hi2X = -1, hi2Y = -1;
4332 int pm1X = -1, pm1Y = -1, pm2X = -1, pm2Y = -1;
4335 SetHighlights(fromX, fromY, toX, toY)
4336 int fromX, fromY, toX, toY;
4338 if (hi1X != fromX || hi1Y != fromY) {
4339 if (hi1X >= 0 && hi1Y >= 0) {
4340 drawHighlight(hi1X, hi1Y, lineGC);
4342 if (fromX >= 0 && fromY >= 0) {
4343 drawHighlight(fromX, fromY, highlineGC);
4346 if (hi2X != toX || hi2Y != toY) {
4347 if (hi2X >= 0 && hi2Y >= 0) {
4348 drawHighlight(hi2X, hi2Y, lineGC);
4350 if (toX >= 0 && toY >= 0) {
4351 drawHighlight(toX, toY, highlineGC);
4363 SetHighlights(-1, -1, -1, -1);
4368 SetPremoveHighlights(fromX, fromY, toX, toY)
4369 int fromX, fromY, toX, toY;
4371 if (pm1X != fromX || pm1Y != fromY) {
4372 if (pm1X >= 0 && pm1Y >= 0) {
4373 drawHighlight(pm1X, pm1Y, lineGC);
4375 if (fromX >= 0 && fromY >= 0) {
4376 drawHighlight(fromX, fromY, prelineGC);
4379 if (pm2X != toX || pm2Y != toY) {
4380 if (pm2X >= 0 && pm2Y >= 0) {
4381 drawHighlight(pm2X, pm2Y, lineGC);
4383 if (toX >= 0 && toY >= 0) {
4384 drawHighlight(toX, toY, prelineGC);
4394 ClearPremoveHighlights()
4396 SetPremoveHighlights(-1, -1, -1, -1);
4399 static void BlankSquare(x, y, color, piece, dest)
4404 if (useImages && useImageSqs) {
4408 pm = xpmLightSquare;
4413 case 2: /* neutral */
4418 XCopyArea(xDisplay, pm, dest, wlPieceGC, 0, 0,
4419 squareSize, squareSize, x, y);
4429 case 2: /* neutral */
4434 XFillRectangle(xDisplay, dest, gc, x, y, squareSize, squareSize);
4439 I split out the routines to draw a piece so that I could
4440 make a generic flash routine.
4442 static void monoDrawPiece_1bit(piece, square_color, x, y, dest)
4444 int square_color, x, y;
4447 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
4448 switch (square_color) {
4450 case 2: /* neutral */
4452 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
4453 ? *pieceToOutline(piece)
4454 : *pieceToSolid(piece),
4455 dest, bwPieceGC, 0, 0,
4456 squareSize, squareSize, x, y);
4459 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
4460 ? *pieceToSolid(piece)
4461 : *pieceToOutline(piece),
4462 dest, wbPieceGC, 0, 0,
4463 squareSize, squareSize, x, y);
4468 static void monoDrawPiece(piece, square_color, x, y, dest)
4470 int square_color, x, y;
4473 switch (square_color) {
4475 case 2: /* neutral */
4477 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
4478 ? *pieceToOutline(piece)
4479 : *pieceToSolid(piece),
4480 dest, bwPieceGC, 0, 0,
4481 squareSize, squareSize, x, y, 1);
4484 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
4485 ? *pieceToSolid(piece)
4486 : *pieceToOutline(piece),
4487 dest, wbPieceGC, 0, 0,
4488 squareSize, squareSize, x, y, 1);
4493 static void colorDrawPiece(piece, square_color, x, y, dest)
4495 int square_color, x, y;
4498 if(pieceToSolid(piece) == NULL) return; // [HGM] bitmaps: make it non-fatal if we have no bitmap;
4499 switch (square_color) {
4501 XCopyPlane(xDisplay, *pieceToSolid(piece),
4502 dest, (int) piece < (int) BlackPawn
4503 ? wlPieceGC : blPieceGC, 0, 0,
4504 squareSize, squareSize, x, y, 1);
4507 XCopyPlane(xDisplay, *pieceToSolid(piece),
4508 dest, (int) piece < (int) BlackPawn
4509 ? wdPieceGC : bdPieceGC, 0, 0,
4510 squareSize, squareSize, x, y, 1);
4512 case 2: /* neutral */
4514 XCopyPlane(xDisplay, *pieceToSolid(piece),
4515 dest, (int) piece < (int) BlackPawn
4516 ? wjPieceGC : bjPieceGC, 0, 0,
4517 squareSize, squareSize, x, y, 1);
4522 static void colorDrawPieceImage(piece, square_color, x, y, dest)
4524 int square_color, x, y;
4529 switch (square_color) {
4531 case 2: /* neutral */
4533 if ((int)piece < (int) BlackPawn) {
4541 if ((int)piece < (int) BlackPawn) {
4549 XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
4550 dest, wlPieceGC, 0, 0,
4551 squareSize, squareSize, x, y);
4554 typedef void (*DrawFunc)();
4556 DrawFunc ChooseDrawFunc()
4558 if (appData.monoMode) {
4559 if (DefaultDepth(xDisplay, xScreen) == 1) {
4560 return monoDrawPiece_1bit;
4562 return monoDrawPiece;
4566 return colorDrawPieceImage;
4568 return colorDrawPiece;
4572 /* [HR] determine square color depending on chess variant. */
4573 static int SquareColor(row, column)
4578 if (gameInfo.variant == VariantXiangqi) {
4579 if (column >= 3 && column <= 5 && row >= 0 && row <= 2) {
4581 } else if (column >= 3 && column <= 5 && row >= 7 && row <= 9) {
4583 } else if (row <= 4) {
4589 square_color = ((column + row) % 2) == 1;
4592 /* [hgm] holdings: next line makes all holdings squares light */
4593 if(column < BOARD_LEFT || column >= BOARD_RGHT) square_color = 1;
4595 return square_color;
4598 void DrawSquare(row, column, piece, do_flash)
4599 int row, column, do_flash;
4602 int square_color, x, y, direction, font_ascent, font_descent;
4605 XCharStruct overall;
4609 if(gameInfo.variant == VariantShogi) { // [HGM] shogi: in shogi Q is used for Lance
4610 if(piece == WhiteQueen) piece = WhiteLance; else
4611 if(piece == BlackQueen) piece = BlackLance;
4614 else if(gameInfo.variant == VariantGothic) { // [HGM] shogi: in Gothic Chancelor has alternative look
4615 if(piece == WhiteMarshall) piece = WhiteSilver; else
4616 if(piece == BlackMarshall) piece = BlackSilver;
4620 /* Calculate delay in milliseconds (2-delays per complete flash) */
4621 flash_delay = 500 / appData.flashRate;
4624 x = lineGap + ((BOARD_WIDTH-1)-column) *
4625 (squareSize + lineGap);
4626 y = lineGap + row * (squareSize + lineGap);
4628 x = lineGap + column * (squareSize + lineGap);
4629 y = lineGap + ((BOARD_HEIGHT-1)-row) *
4630 (squareSize + lineGap);
4633 square_color = SquareColor(row, column);
4635 if ( // [HGM] holdings: blank out area between board and holdings
4636 column == BOARD_LEFT-1 || column == BOARD_RGHT
4637 || (column == BOARD_LEFT-2 && row < BOARD_HEIGHT-gameInfo.holdingsSize)
4638 || (column == BOARD_RGHT+1 && row >= gameInfo.holdingsSize) ) {
4639 BlankSquare(x, y, 2, EmptySquare, xBoardWindow);
4641 // [HGM] print piece counts next to holdings
4642 string[1] = NULLCHAR;
4643 if (column == (flipView ? BOARD_LEFT-1 : BOARD_RGHT) && piece > 1 ) {
4644 string[0] = '0' + piece;
4645 XTextExtents(countFontStruct, string, 1, &direction,
4646 &font_ascent, &font_descent, &overall);
4647 if (appData.monoMode) {
4648 XDrawImageString(xDisplay, xBoardWindow, countGC,
4649 x + squareSize - overall.width - 2,
4650 y + font_ascent + 1, string, 1);
4652 XDrawString(xDisplay, xBoardWindow, countGC,
4653 x + squareSize - overall.width - 2,
4654 y + font_ascent + 1, string, 1);
4657 if (column == (flipView ? BOARD_RGHT : BOARD_LEFT-1) && piece > 1) {
4658 string[0] = '0' + piece;
4659 XTextExtents(countFontStruct, string, 1, &direction,
4660 &font_ascent, &font_descent, &overall);
4661 if (appData.monoMode) {
4662 XDrawImageString(xDisplay, xBoardWindow, countGC,
4663 x + 2, y + font_ascent + 1, string, 1);
4665 XDrawString(xDisplay, xBoardWindow, countGC,
4666 x + 2, y + font_ascent + 1, string, 1);
4670 if (piece == EmptySquare || appData.blindfold) {
4671 BlankSquare(x, y, square_color, piece, xBoardWindow);
4673 drawfunc = ChooseDrawFunc();
4674 if (do_flash && appData.flashCount > 0) {
4675 for (i=0; i<appData.flashCount; ++i) {
4677 drawfunc(piece, square_color, x, y, xBoardWindow);
4678 XSync(xDisplay, False);
4679 do_flash_delay(flash_delay);
4681 BlankSquare(x, y, square_color, piece, xBoardWindow);
4682 XSync(xDisplay, False);
4683 do_flash_delay(flash_delay);
4686 drawfunc(piece, square_color, x, y, xBoardWindow);
4690 string[1] = NULLCHAR;
4691 if (appData.showCoords && row == (flipView ? BOARD_HEIGHT-1 : 0)
4692 && column >= BOARD_LEFT && column < BOARD_RGHT) {
4693 string[0] = 'a' + column - BOARD_LEFT;
4694 XTextExtents(coordFontStruct, string, 1, &direction,
4695 &font_ascent, &font_descent, &overall);
4696 if (appData.monoMode) {
4697 XDrawImageString(xDisplay, xBoardWindow, coordGC,
4698 x + squareSize - overall.width - 2,
4699 y + squareSize - font_descent - 1, string, 1);
4701 XDrawString(xDisplay, xBoardWindow, coordGC,
4702 x + squareSize - overall.width - 2,
4703 y + squareSize - font_descent - 1, string, 1);
4706 if (appData.showCoords && column == (flipView ? BOARD_RGHT-1 : BOARD_LEFT)) {
4707 string[0] = ONE + row;
4708 XTextExtents(coordFontStruct, string, 1, &direction,
4709 &font_ascent, &font_descent, &overall);
4710 if (appData.monoMode) {
4711 XDrawImageString(xDisplay, xBoardWindow, coordGC,
4712 x + 2, y + font_ascent + 1, string, 1);
4714 XDrawString(xDisplay, xBoardWindow, coordGC,
4715 x + 2, y + font_ascent + 1, string, 1);
4721 /* Why is this needed on some versions of X? */
4722 void EventProc(widget, unused, event)
4727 if (!XtIsRealized(widget))
4730 switch (event->type) {
4732 if (event->xexpose.count > 0) return; /* no clipping is done */
4733 XDrawPosition(widget, True, NULL);
4741 void DrawPosition(fullRedraw, board)
4742 /*Boolean*/int fullRedraw;
4745 XDrawPosition(boardWidget, fullRedraw, board);
4748 /* Returns 1 if there are "too many" differences between b1 and b2
4749 (i.e. more than 1 move was made) */
4750 static int too_many_diffs(b1, b2)
4756 for (i=0; i<BOARD_HEIGHT; ++i) {
4757 for (j=0; j<BOARD_WIDTH; ++j) {
4758 if (b1[i][j] != b2[i][j]) {
4759 if (++c > 4) /* Castling causes 4 diffs */
4768 /* Matrix describing castling maneuvers */
4769 /* Row, ColRookFrom, ColKingFrom, ColRookTo, ColKingTo */
4770 static int castling_matrix[4][5] = {
4771 { 0, 0, 4, 3, 2 }, /* 0-0-0, white */
4772 { 0, 7, 4, 5, 6 }, /* 0-0, white */
4773 { 7, 0, 4, 3, 2 }, /* 0-0-0, black */
4774 { 7, 7, 4, 5, 6 } /* 0-0, black */
4777 /* Checks whether castling occurred. If it did, *rrow and *rcol
4778 are set to the destination (row,col) of the rook that moved.
4780 Returns 1 if castling occurred, 0 if not.
4782 Note: Only handles a max of 1 castling move, so be sure
4783 to call too_many_diffs() first.
4785 static int check_castle_draw(newb, oldb, rrow, rcol)
4792 /* For each type of castling... */
4793 for (i=0; i<4; ++i) {
4794 r = castling_matrix[i];
4796 /* Check the 4 squares involved in the castling move */
4798 for (j=1; j<=4; ++j) {
4799 if (newb[r[0]][r[j]] == oldb[r[0]][r[j]]) {
4806 /* All 4 changed, so it must be a castling move */
4815 static int damage[BOARD_SIZE][BOARD_SIZE];
4818 * event handler for redrawing the board
4820 void XDrawPosition(w, repaint, board)
4822 /*Boolean*/int repaint;
4826 static int lastFlipView = 0;
4827 static int lastBoardValid = 0;
4828 static Board lastBoard;
4832 if (board == NULL) {
4833 if (!lastBoardValid) return;
4836 if (!lastBoardValid || lastFlipView != flipView) {
4837 XtSetArg(args[0], XtNleftBitmap, (flipView ? xMarkPixmap : None));
4838 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flip View"),
4843 * It would be simpler to clear the window with XClearWindow()
4844 * but this causes a very distracting flicker.
4847 if (!repaint && lastBoardValid && lastFlipView == flipView) {
4849 /* If too much changes (begin observing new game, etc.), don't
4851 do_flash = too_many_diffs(board, lastBoard) ? 0 : 1;
4853 /* Special check for castling so we don't flash both the king
4854 and the rook (just flash the king). */
4856 if (check_castle_draw(board, lastBoard, &rrow, &rcol)) {
4857 /* Draw rook with NO flashing. King will be drawn flashing later */
4858 DrawSquare(rrow, rcol, board[rrow][rcol], 0);
4859 lastBoard[rrow][rcol] = board[rrow][rcol];
4863 /* First pass -- Draw (newly) empty squares and repair damage.
4864 This prevents you from having a piece show up twice while it
4865 is flashing on its new square */
4866 for (i = 0; i < BOARD_HEIGHT; i++)
4867 for (j = 0; j < BOARD_WIDTH; j++)
4868 if ((board[i][j] != lastBoard[i][j] && board[i][j] == EmptySquare)
4870 DrawSquare(i, j, board[i][j], 0);
4871 damage[i][j] = False;
4874 /* Second pass -- Draw piece(s) in new position and flash them */
4875 for (i = 0; i < BOARD_HEIGHT; i++)
4876 for (j = 0; j < BOARD_WIDTH; j++)
4877 if (board[i][j] != lastBoard[i][j]) {
4878 DrawSquare(i, j, board[i][j], do_flash);
4882 XDrawSegments(xDisplay, xBoardWindow, lineGC,
4883 gridSegments, BOARD_HEIGHT + BOARD_WIDTH + 2);
4885 for (i = 0; i < BOARD_HEIGHT; i++)
4886 for (j = 0; j < BOARD_WIDTH; j++) {
4887 DrawSquare(i, j, board[i][j], 0);
4888 damage[i][j] = False;
4892 CopyBoard(lastBoard, board);
4894 lastFlipView = flipView;
4896 /* Draw highlights */
4897 if (pm1X >= 0 && pm1Y >= 0) {
4898 drawHighlight(pm1X, pm1Y, prelineGC);
4900 if (pm2X >= 0 && pm2Y >= 0) {
4901 drawHighlight(pm2X, pm2Y, prelineGC);
4903 if (hi1X >= 0 && hi1Y >= 0) {
4904 drawHighlight(hi1X, hi1Y, highlineGC);
4906 if (hi2X >= 0 && hi2Y >= 0) {
4907 drawHighlight(hi2X, hi2Y, highlineGC);
4910 /* If piece being dragged around board, must redraw that too */
4913 XSync(xDisplay, False);
4918 * event handler for redrawing the board
4920 void DrawPositionProc(w, event, prms, nprms)
4926 XDrawPosition(w, True, NULL);
4931 * event handler for parsing user moves
4933 // [HGM] This routine will need quite some reworking. Although the backend still supports the old
4934 // way of doing things, by calling UserMoveEvent() to test the legality of the move and then perform
4935 // it at the end, and doing all kind of preliminary tests here (e.g. to weed out self-captures), it
4936 // should be made to use the new way, of calling UserMoveTest early to determine the legality of the
4937 // move, (which will weed out the illegal selfcaptures and moves into the holdings, and flag promotions),
4938 // and at the end FinishMove() to perform the move after optional promotion popups.
4939 // For now I patched it to allow self-capture with King, and suppress clicks between board and holdings.
4940 void HandleUserMove(w, event, prms, nprms)
4947 Boolean saveAnimate;
4948 static int second = 0;
4950 if (w != boardWidget || errorExitStatus != -1) return;
4952 if (event->type == ButtonPress) ErrorPopDown();
4955 if (event->type == ButtonPress) {
4956 XtPopdown(promotionShell);
4957 XtDestroyWidget(promotionShell);
4958 promotionUp = False;
4966 x = EventToSquare(event->xbutton.x, BOARD_WIDTH);
4967 y = EventToSquare(event->xbutton.y, BOARD_HEIGHT);
4968 if (!flipView && y >= 0) {
4969 y = BOARD_HEIGHT - 1 - y;
4971 if (flipView && x >= 0) {
4972 x = BOARD_WIDTH - 1 - x;
4975 /* [HGM] holdings: next 5 lines: ignore all clicks between board and holdings */
4976 if(event->type == ButtonPress
4977 && ( x == BOARD_LEFT-1 || x == BOARD_RGHT
4978 || x == BOARD_LEFT-2 && y < BOARD_HEIGHT-gameInfo.holdingsSize
4979 || x == BOARD_RGHT+1 && y >= gameInfo.holdingsSize) )
4983 if (event->type == ButtonPress) {
4985 if (OKToStartUserMove(x, y)) {
4989 DragPieceBegin(event->xbutton.x, event->xbutton.y);
4990 if (appData.highlightDragging) {
4991 SetHighlights(x, y, -1, -1);
4999 if (event->type == ButtonPress && gameMode != EditPosition &&
5004 /* Check if clicking again on the same color piece */
5005 fromP = boards[currentMove][fromY][fromX];
5006 toP = boards[currentMove][y][x];
5007 if ((WhitePawn <= fromP && fromP < WhiteKing && // [HGM] this test should go, as UserMoveTest now does it.
5008 WhitePawn <= toP && toP <= WhiteKing) || // For now I made it less critical by exempting King
5009 (BlackPawn <= fromP && fromP < BlackKing && // moves, to not interfere with FRC castlings.
5010 BlackPawn <= toP && toP <= BlackKing)) {
5011 /* Clicked again on same color piece -- changed his mind */
5012 second = (x == fromX && y == fromY);
5013 if (appData.highlightDragging) {
5014 SetHighlights(x, y, -1, -1);
5018 if (OKToStartUserMove(x, y)) {
5021 DragPieceBegin(event->xbutton.x, event->xbutton.y);
5027 if (event->type == ButtonRelease && x == fromX && y == fromY) {
5028 DragPieceEnd(event->xbutton.x, event->xbutton.y);
5029 if (appData.animateDragging) {
5030 /* Undo animation damage if any */
5031 DrawPosition(FALSE, NULL);
5034 /* Second up/down in same square; just abort move */
5039 ClearPremoveHighlights();
5041 /* First upclick in same square; start click-click mode */
5042 SetHighlights(x, y, -1, -1);
5047 /* Completed move */
5050 saveAnimate = appData.animate;
5051 if (event->type == ButtonPress) {
5052 /* Finish clickclick move */
5053 if (appData.animate || appData.highlightLastMove) {
5054 SetHighlights(fromX, fromY, toX, toY);
5059 /* Finish drag move */
5060 if (appData.highlightLastMove) {
5061 SetHighlights(fromX, fromY, toX, toY);
5065 DragPieceEnd(event->xbutton.x, event->xbutton.y);
5066 /* Don't animate move and drag both */
5067 appData.animate = FALSE;
5069 if (IsPromotion(fromX, fromY, toX, toY)) {
5070 if (appData.alwaysPromoteToQueen) {
5071 UserMoveEvent(fromX, fromY, toX, toY, 'q');
5072 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
5073 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
5076 SetHighlights(fromX, fromY, toX, toY);
5080 UserMoveEvent(fromX, fromY, toX, toY, NULLCHAR);
5081 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
5082 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
5085 appData.animate = saveAnimate;
5086 if (appData.animate || appData.animateDragging) {
5087 /* Undo animation damage if needed */
5088 DrawPosition(FALSE, NULL);
5092 void AnimateUserMove (Widget w, XEvent * event,
5093 String * params, Cardinal * nParams)
5095 DragPieceMove(event->xmotion.x, event->xmotion.y);
5098 Widget CommentCreate(name, text, mutable, callback, lines)
5100 int /*Boolean*/ mutable;
5101 XtCallbackProc callback;
5105 Widget shell, layout, form, edit, b_ok, b_cancel, b_clear, b_close, b_edit;
5110 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5111 XtGetValues(boardWidget, args, j);
5114 XtSetArg(args[j], XtNresizable, True); j++;
5117 XtCreatePopupShell(name, topLevelShellWidgetClass,
5118 shellWidget, args, j);
5121 XtCreatePopupShell(name, transientShellWidgetClass,
5122 shellWidget, args, j);
5125 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
5126 layoutArgs, XtNumber(layoutArgs));
5128 XtCreateManagedWidget("form", formWidgetClass, layout,
5129 formArgs, XtNumber(formArgs));
5133 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
5134 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
5136 XtSetArg(args[j], XtNstring, text); j++;
5137 XtSetArg(args[j], XtNtop, XtChainTop); j++;
5138 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5139 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5140 XtSetArg(args[j], XtNright, XtChainRight); j++;
5141 XtSetArg(args[j], XtNresizable, True); j++;
5142 XtSetArg(args[j], XtNwidth, bw_width); j++; /*force wider than buttons*/
5144 XtSetArg(args[j], XtNscrollVertical, XawtextScrollWhenNeeded); j++;
5146 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
5147 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
5149 XtSetArg(args[j], XtNautoFill, True); j++;
5150 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
5152 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
5156 XtSetArg(args[j], XtNfromVert, edit); j++;
5157 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5158 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5159 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5160 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5162 XtCreateManagedWidget(_("ok"), commandWidgetClass, form, args, j);
5163 XtAddCallback(b_ok, XtNcallback, callback, (XtPointer) 0);
5166 XtSetArg(args[j], XtNfromVert, edit); j++;
5167 XtSetArg(args[j], XtNfromHoriz, b_ok); j++;
5168 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5169 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5170 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5171 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5173 XtCreateManagedWidget(_("cancel"), commandWidgetClass, form, args, j);
5174 XtAddCallback(b_cancel, XtNcallback, callback, (XtPointer) 0);
5177 XtSetArg(args[j], XtNfromVert, edit); j++;
5178 XtSetArg(args[j], XtNfromHoriz, b_cancel); j++;
5179 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5180 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5181 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5182 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5184 XtCreateManagedWidget(_("clear"), commandWidgetClass, form, args, j);
5185 XtAddCallback(b_clear, XtNcallback, callback, (XtPointer) 0);
5188 XtSetArg(args[j], XtNfromVert, edit); 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(_("close"), commandWidgetClass, form, args, j);
5195 XtAddCallback(b_close, XtNcallback, callback, (XtPointer) 0);
5198 XtSetArg(args[j], XtNfromVert, edit); j++;
5199 XtSetArg(args[j], XtNfromHoriz, b_close); j++;
5200 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5201 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5202 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5203 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5205 XtCreateManagedWidget(_("edit"), commandWidgetClass, form, args, j);
5206 XtAddCallback(b_edit, XtNcallback, callback, (XtPointer) 0);
5209 XtRealizeWidget(shell);
5211 if (commentX == -1) {
5214 Dimension pw_height;
5215 Dimension ew_height;
5218 XtSetArg(args[j], XtNheight, &ew_height); j++;
5219 XtGetValues(edit, args, j);
5222 XtSetArg(args[j], XtNheight, &pw_height); j++;
5223 XtGetValues(shell, args, j);
5224 commentH = pw_height + (lines - 1) * ew_height;
5225 commentW = bw_width - 16;
5227 XSync(xDisplay, False);
5229 /* This code seems to tickle an X bug if it is executed too soon
5230 after xboard starts up. The coordinates get transformed as if
5231 the main window was positioned at (0, 0).
5233 XtTranslateCoords(shellWidget,
5234 (bw_width - commentW) / 2, 0 - commentH / 2,
5235 &commentX, &commentY);
5237 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
5238 RootWindowOfScreen(XtScreen(shellWidget)),
5239 (bw_width - commentW) / 2, 0 - commentH / 2,
5244 if (commentY < 0) commentY = 0; /*avoid positioning top offscreen*/
5247 XtSetArg(args[j], XtNheight, commentH); j++;
5248 XtSetArg(args[j], XtNwidth, commentW); j++;
5249 XtSetArg(args[j], XtNx, commentX); j++;
5250 XtSetArg(args[j], XtNy, commentY); j++;
5251 XtSetValues(shell, args, j);
5252 XtSetKeyboardFocus(shell, edit);
5257 /* Used for analysis window and ICS input window */
5258 Widget MiscCreate(name, text, mutable, callback, lines)
5260 int /*Boolean*/ mutable;
5261 XtCallbackProc callback;
5265 Widget shell, layout, form, edit;
5267 Dimension bw_width, pw_height, ew_height, w, h;
5273 XtSetArg(args[j], XtNresizable, True); j++;
5276 XtCreatePopupShell(name, topLevelShellWidgetClass,
5277 shellWidget, args, j);
5280 XtCreatePopupShell(name, transientShellWidgetClass,
5281 shellWidget, args, j);
5284 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
5285 layoutArgs, XtNumber(layoutArgs));
5287 XtCreateManagedWidget("form", formWidgetClass, layout,
5288 formArgs, XtNumber(formArgs));
5292 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
5293 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
5295 XtSetArg(args[j], XtNstring, text); j++;
5296 XtSetArg(args[j], XtNtop, XtChainTop); j++;
5297 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5298 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5299 XtSetArg(args[j], XtNright, XtChainRight); j++;
5300 XtSetArg(args[j], XtNresizable, True); j++;
5302 XtSetArg(args[j], XtNscrollVertical, XawtextScrollWhenNeeded); j++;
5304 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
5305 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
5307 XtSetArg(args[j], XtNautoFill, True); j++;
5308 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
5310 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
5312 XtRealizeWidget(shell);
5315 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5316 XtGetValues(boardWidget, args, j);
5319 XtSetArg(args[j], XtNheight, &ew_height); j++;
5320 XtGetValues(edit, args, j);
5323 XtSetArg(args[j], XtNheight, &pw_height); j++;
5324 XtGetValues(shell, args, j);
5325 h = pw_height + (lines - 1) * ew_height;
5328 XSync(xDisplay, False);
5330 /* This code seems to tickle an X bug if it is executed too soon
5331 after xboard starts up. The coordinates get transformed as if
5332 the main window was positioned at (0, 0).
5334 XtTranslateCoords(shellWidget, (bw_width - w) / 2, 0 - h / 2, &x, &y);
5336 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
5337 RootWindowOfScreen(XtScreen(shellWidget)),
5338 (bw_width - w) / 2, 0 - h / 2, &xx, &yy, &junk);
5342 if (y < 0) y = 0; /*avoid positioning top offscreen*/
5345 XtSetArg(args[j], XtNheight, h); j++;
5346 XtSetArg(args[j], XtNwidth, w); j++;
5347 XtSetArg(args[j], XtNx, x); j++;
5348 XtSetArg(args[j], XtNy, y); j++;
5349 XtSetValues(shell, args, j);
5355 static int savedIndex; /* gross that this is global */
5357 void EditCommentPopUp(index, title, text)
5366 if (text == NULL) text = "";
5368 if (editShell == NULL) {
5370 CommentCreate(title, text, True, EditCommentCallback, 4);
5371 XtRealizeWidget(editShell);
5372 CatchDeleteWindow(editShell, "EditCommentPopDown");
5374 edit = XtNameToWidget(editShell, "*form.text");
5376 XtSetArg(args[j], XtNstring, text); j++;
5377 XtSetValues(edit, args, j);
5379 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5380 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5381 XtSetValues(editShell, args, j);
5384 XtPopup(editShell, XtGrabNone);
5388 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
5389 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
5393 void EditCommentCallback(w, client_data, call_data)
5395 XtPointer client_data, call_data;
5403 XtSetArg(args[j], XtNlabel, &name); j++;
5404 XtGetValues(w, args, j);
5406 if (strcmp(name, _("ok")) == 0) {
5407 edit = XtNameToWidget(editShell, "*form.text");
5409 XtSetArg(args[j], XtNstring, &val); j++;
5410 XtGetValues(edit, args, j);
5411 ReplaceComment(savedIndex, val);
5412 EditCommentPopDown();
5413 } else if (strcmp(name, _("cancel")) == 0) {
5414 EditCommentPopDown();
5415 } else if (strcmp(name, _("clear")) == 0) {
5416 edit = XtNameToWidget(editShell, "*form.text");
5417 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
5418 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
5422 void EditCommentPopDown()
5427 if (!editUp) return;
5429 XtSetArg(args[j], XtNx, &commentX); j++;
5430 XtSetArg(args[j], XtNy, &commentY); j++;
5431 XtSetArg(args[j], XtNheight, &commentH); j++;
5432 XtSetArg(args[j], XtNwidth, &commentW); j++;
5433 XtGetValues(editShell, args, j);
5434 XtPopdown(editShell);
5437 XtSetArg(args[j], XtNleftBitmap, None); j++;
5438 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
5442 void ICSInputBoxPopUp()
5447 char *title = _("ICS Input");
5450 if (ICSInputShell == NULL) {
5451 ICSInputShell = MiscCreate(title, "", True, NULL, 1);
5452 tr = XtParseTranslationTable(ICSInputTranslations);
5453 edit = XtNameToWidget(ICSInputShell, "*form.text");
5454 XtOverrideTranslations(edit, tr);
5455 XtRealizeWidget(ICSInputShell);
5456 CatchDeleteWindow(ICSInputShell, "ICSInputBoxPopDown");
5459 edit = XtNameToWidget(ICSInputShell, "*form.text");
5461 XtSetArg(args[j], XtNstring, ""); j++;
5462 XtSetValues(edit, args, j);
5464 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5465 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5466 XtSetValues(ICSInputShell, args, j);
5469 XtPopup(ICSInputShell, XtGrabNone);
5470 XtSetKeyboardFocus(ICSInputShell, edit);
5472 ICSInputBoxUp = True;
5474 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
5475 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
5479 void ICSInputSendText()
5486 edit = XtNameToWidget(ICSInputShell, "*form.text");
5488 XtSetArg(args[j], XtNstring, &val); j++;
5489 XtGetValues(edit, args, j);
5490 SendMultiLineToICS(val);
5491 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
5492 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
5495 void ICSInputBoxPopDown()
5500 if (!ICSInputBoxUp) return;
5502 XtPopdown(ICSInputShell);
5503 ICSInputBoxUp = False;
5505 XtSetArg(args[j], XtNleftBitmap, None); j++;
5506 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
5510 void CommentPopUp(title, text)
5517 if (commentShell == NULL) {
5519 CommentCreate(title, text, False, CommentCallback, 4);
5520 XtRealizeWidget(commentShell);
5521 CatchDeleteWindow(commentShell, "CommentPopDown");
5523 edit = XtNameToWidget(commentShell, "*form.text");
5525 XtSetArg(args[j], XtNstring, text); j++;
5526 XtSetValues(edit, args, j);
5528 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5529 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5530 XtSetValues(commentShell, args, j);
5533 XtPopup(commentShell, XtGrabNone);
5534 XSync(xDisplay, False);
5539 void AnalysisPopUp(title, text)
5546 if (analysisShell == NULL) {
5547 analysisShell = MiscCreate(title, text, False, NULL, 4);
5548 XtRealizeWidget(analysisShell);
5549 CatchDeleteWindow(analysisShell, "AnalysisPopDown");
5552 edit = XtNameToWidget(analysisShell, "*form.text");
5554 XtSetArg(args[j], XtNstring, text); j++;
5555 XtSetValues(edit, args, j);
5557 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5558 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5559 XtSetValues(analysisShell, args, j);
5563 XtPopup(analysisShell, XtGrabNone);
5565 XSync(xDisplay, False);
5570 void CommentCallback(w, client_data, call_data)
5572 XtPointer client_data, call_data;
5579 XtSetArg(args[j], XtNlabel, &name); j++;
5580 XtGetValues(w, args, j);
5582 if (strcmp(name, _("close")) == 0) {
5584 } else if (strcmp(name, _("edit")) == 0) {
5591 void CommentPopDown()
5596 if (!commentUp) return;
5598 XtSetArg(args[j], XtNx, &commentX); j++;
5599 XtSetArg(args[j], XtNy, &commentY); j++;
5600 XtSetArg(args[j], XtNwidth, &commentW); j++;
5601 XtSetArg(args[j], XtNheight, &commentH); j++;
5602 XtGetValues(commentShell, args, j);
5603 XtPopdown(commentShell);
5604 XSync(xDisplay, False);
5608 void AnalysisPopDown()
5610 if (!analysisUp) return;
5611 XtPopdown(analysisShell);
5612 XSync(xDisplay, False);
5614 if (appData.icsEngineAnalyze) ExitAnalyzeMode(); /* [DM] icsEngineAnalyze */
5618 void FileNamePopUp(label, def, proc, openMode)
5625 Widget popup, layout, dialog, edit;
5631 fileProc = proc; /* I can't see a way not */
5632 fileOpenMode = openMode; /* to use globals here */
5635 XtSetArg(args[i], XtNresizable, True); i++;
5636 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
5637 XtSetArg(args[i], XtNtitle, XtNewString(_("File name prompt"))); i++;
5638 fileNameShell = popup =
5639 XtCreatePopupShell("File name prompt", transientShellWidgetClass,
5640 shellWidget, args, i);
5643 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
5644 layoutArgs, XtNumber(layoutArgs));
5647 XtSetArg(args[i], XtNlabel, label); i++;
5648 XtSetArg(args[i], XtNvalue, def); i++;
5649 XtSetArg(args[i], XtNborderWidth, 0); i++;
5650 dialog = XtCreateManagedWidget("fileName", dialogWidgetClass,
5653 XawDialogAddButton(dialog, _("ok"), FileNameCallback, (XtPointer) dialog);
5654 XawDialogAddButton(dialog, _("cancel"), FileNameCallback,
5655 (XtPointer) dialog);
5657 XtRealizeWidget(popup);
5658 CatchDeleteWindow(popup, "FileNamePopDown");
5660 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
5661 &x, &y, &win_x, &win_y, &mask);
5663 XtSetArg(args[0], XtNx, x - 10);
5664 XtSetArg(args[1], XtNy, y - 30);
5665 XtSetValues(popup, args, 2);
5667 XtPopup(popup, XtGrabExclusive);
5670 edit = XtNameToWidget(dialog, "*value");
5671 XtSetKeyboardFocus(popup, edit);
5674 void FileNamePopDown()
5676 if (!filenameUp) return;
5677 XtPopdown(fileNameShell);
5678 XtDestroyWidget(fileNameShell);
5683 void FileNameCallback(w, client_data, call_data)
5685 XtPointer client_data, call_data;
5690 XtSetArg(args[0], XtNlabel, &name);
5691 XtGetValues(w, args, 1);
5693 if (strcmp(name, _("cancel")) == 0) {
5698 FileNameAction(w, NULL, NULL, NULL);
5701 void FileNameAction(w, event, prms, nprms)
5713 name = XawDialogGetValueString(w = XtParent(w));
5715 if ((name != NULL) && (*name != NULLCHAR)) {
5717 XtPopdown(w = XtParent(XtParent(w)));
5721 p = strrchr(buf, ' ');
5728 fullname = ExpandPathName(buf);
5730 ErrorPopUp(_("Error"), _("Can't open file"), FALSE);
5733 f = fopen(fullname, fileOpenMode);
5735 DisplayError(_("Failed to open file"), errno);
5737 (void) (*fileProc)(f, index, buf);
5744 XtPopdown(w = XtParent(XtParent(w)));
5750 void PromotionPopUp()
5753 Widget dialog, layout;
5755 Dimension bw_width, pw_width;
5759 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5760 XtGetValues(boardWidget, args, j);
5763 XtSetArg(args[j], XtNresizable, True); j++;
5764 XtSetArg(args[j], XtNtitle, XtNewString(_("Promotion"))); j++;
5766 XtCreatePopupShell("Promotion", transientShellWidgetClass,
5767 shellWidget, args, j);
5769 XtCreateManagedWidget(layoutName, formWidgetClass, promotionShell,
5770 layoutArgs, XtNumber(layoutArgs));
5773 XtSetArg(args[j], XtNlabel, _("Promote pawn to what?")); j++;
5774 XtSetArg(args[j], XtNborderWidth, 0); j++;
5775 dialog = XtCreateManagedWidget("promotion", dialogWidgetClass,
5778 XawDialogAddButton(dialog, _("Queen"), PromotionCallback,
5779 (XtPointer) dialog);
5780 XawDialogAddButton(dialog, _("Rook"), PromotionCallback,
5781 (XtPointer) dialog);
5782 XawDialogAddButton(dialog, _("Bishop"), PromotionCallback,
5783 (XtPointer) dialog);
5784 XawDialogAddButton(dialog, _("Knight"), PromotionCallback,
5785 (XtPointer) dialog);
5786 if (!appData.testLegality || gameInfo.variant == VariantSuicide ||
5787 gameInfo.variant == VariantGiveaway) {
5788 XawDialogAddButton(dialog, _("King"), PromotionCallback,
5789 (XtPointer) dialog);
5791 XawDialogAddButton(dialog, _("cancel"), PromotionCallback,
5792 (XtPointer) dialog);
5794 XtRealizeWidget(promotionShell);
5795 CatchDeleteWindow(promotionShell, "PromotionPopDown");
5798 XtSetArg(args[j], XtNwidth, &pw_width); j++;
5799 XtGetValues(promotionShell, args, j);
5801 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
5802 lineGap + squareSize/3 +
5803 ((toY == BOARD_HEIGHT-1) ^ (flipView) ?
5804 0 : 6*(squareSize + lineGap)), &x, &y);
5807 XtSetArg(args[j], XtNx, x); j++;
5808 XtSetArg(args[j], XtNy, y); j++;
5809 XtSetValues(promotionShell, args, j);
5811 XtPopup(promotionShell, XtGrabNone);
5816 void PromotionPopDown()
5818 if (!promotionUp) return;
5819 XtPopdown(promotionShell);
5820 XtDestroyWidget(promotionShell);
5821 promotionUp = False;
5824 void PromotionCallback(w, client_data, call_data)
5826 XtPointer client_data, call_data;
5832 XtSetArg(args[0], XtNlabel, &name);
5833 XtGetValues(w, args, 1);
5837 if (fromX == -1) return;
5839 if (strcmp(name, _("cancel")) == 0) {
5843 } else if (strcmp(name, _("Knight")) == 0) {
5846 promoChar = ToLower(name[0]);
5849 UserMoveEvent(fromX, fromY, toX, toY, promoChar);
5851 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
5852 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
5857 void ErrorCallback(w, client_data, call_data)
5859 XtPointer client_data, call_data;
5862 XtPopdown(w = XtParent(XtParent(XtParent(w))));
5864 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
5870 if (!errorUp) return;
5872 XtPopdown(errorShell);
5873 XtDestroyWidget(errorShell);
5874 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
5877 void ErrorPopUp(title, label, modal)
5878 char *title, *label;
5882 Widget dialog, layout;
5886 Dimension bw_width, pw_width;
5887 Dimension pw_height;
5891 XtSetArg(args[i], XtNresizable, True); i++;
5892 XtSetArg(args[i], XtNtitle, title); i++;
5894 XtCreatePopupShell("errorpopup", transientShellWidgetClass,
5895 shellWidget, args, i);
5897 XtCreateManagedWidget(layoutName, formWidgetClass, errorShell,
5898 layoutArgs, XtNumber(layoutArgs));
5901 XtSetArg(args[i], XtNlabel, label); i++;
5902 XtSetArg(args[i], XtNborderWidth, 0); i++;
5903 dialog = XtCreateManagedWidget("dialog", dialogWidgetClass,
5906 XawDialogAddButton(dialog, _("ok"), ErrorCallback, (XtPointer) dialog);
5908 XtRealizeWidget(errorShell);
5909 CatchDeleteWindow(errorShell, "ErrorPopDown");
5912 XtSetArg(args[i], XtNwidth, &bw_width); i++;
5913 XtGetValues(boardWidget, args, i);
5915 XtSetArg(args[i], XtNwidth, &pw_width); i++;
5916 XtSetArg(args[i], XtNheight, &pw_height); i++;
5917 XtGetValues(errorShell, args, i);
5920 /* This code seems to tickle an X bug if it is executed too soon
5921 after xboard starts up. The coordinates get transformed as if
5922 the main window was positioned at (0, 0).
5924 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
5925 0 - pw_height + squareSize / 3, &x, &y);
5927 XTranslateCoordinates(xDisplay, XtWindow(boardWidget),
5928 RootWindowOfScreen(XtScreen(boardWidget)),
5929 (bw_width - pw_width) / 2,
5930 0 - pw_height + squareSize / 3, &xx, &yy, &junk);
5934 if (y < 0) y = 0; /*avoid positioning top offscreen*/
5937 XtSetArg(args[i], XtNx, x); i++;
5938 XtSetArg(args[i], XtNy, y); i++;
5939 XtSetValues(errorShell, args, i);
5942 XtPopup(errorShell, modal ? XtGrabExclusive : XtGrabNone);
5945 /* Disable all user input other than deleting the window */
5946 static int frozen = 0;
5950 /* Grab by a widget that doesn't accept input */
5951 XtAddGrab(messageWidget, TRUE, FALSE);
5955 /* Undo a FreezeUI */
5958 if (!frozen) return;
5959 XtRemoveGrab(messageWidget);
5963 char *ModeToWidgetName(mode)
5967 case BeginningOfGame:
5968 if (appData.icsActive)
5969 return "menuMode.ICS Client";
5970 else if (appData.noChessProgram ||
5971 *appData.cmailGameName != NULLCHAR)
5972 return "menuMode.Edit Game";
5974 return "menuMode.Machine Black";
5975 case MachinePlaysBlack:
5976 return "menuMode.Machine Black";
5977 case MachinePlaysWhite:
5978 return "menuMode.Machine White";
5980 return "menuMode.Analysis Mode";
5982 return "menuMode.Analyze File";
5983 case TwoMachinesPlay:
5984 return "menuMode.Two Machines";
5986 return "menuMode.Edit Game";
5987 case PlayFromGameFile:
5988 return "menuFile.Load Game";
5990 return "menuMode.Edit Position";
5992 return "menuMode.Training";
5993 case IcsPlayingWhite:
5994 case IcsPlayingBlack:
5998 return "menuMode.ICS Client";
6005 void ModeHighlight()
6008 static int oldPausing = FALSE;
6009 static GameMode oldmode = (GameMode) -1;
6012 if (!boardWidget || !XtIsRealized(boardWidget)) return;
6014 if (pausing != oldPausing) {
6015 oldPausing = pausing;
6017 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6019 XtSetArg(args[0], XtNleftBitmap, None);
6021 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Pause"),
6024 if (appData.showButtonBar) {
6027 XtSetArg(args[0], XtNbackground, buttonForegroundPixel);
6028 XtSetArg(args[1], XtNforeground, buttonBackgroundPixel);
6030 XtSetArg(args[0], XtNbackground, buttonBackgroundPixel);
6031 XtSetArg(args[1], XtNforeground, buttonForegroundPixel);
6034 /* Always toggle, don't set. Previous code messes up when
6035 invoked while the button is pressed, as releasing it
6036 toggles the state again. */
6039 XtSetArg(args[0], XtNbackground, &oldbg);
6040 XtSetArg(args[1], XtNforeground, &oldfg);
6041 XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON),
6043 XtSetArg(args[0], XtNbackground, oldfg);
6044 XtSetArg(args[1], XtNforeground, oldbg);
6047 XtSetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
6051 wname = ModeToWidgetName(oldmode);
6052 if (wname != NULL) {
6053 XtSetArg(args[0], XtNleftBitmap, None);
6054 XtSetValues(XtNameToWidget(menuBarWidget, wname), args, 1);
6056 wname = ModeToWidgetName(gameMode);
6057 if (wname != NULL) {
6058 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6059 XtSetValues(XtNameToWidget(menuBarWidget, wname), args, 1);
6063 /* Maybe all the enables should be handled here, not just this one */
6064 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Training"),
6065 gameMode == Training || gameMode == PlayFromGameFile);
6070 * Button/menu procedures
6072 void ResetProc(w, event, prms, nprms)
6082 int LoadGamePopUp(f, gameNumber, title)
6087 cmailMsgLoaded = FALSE;
6088 if (gameNumber == 0) {
6089 int error = GameListBuild(f);
6091 DisplayError(_("Cannot build game list"), error);
6092 } else if (!ListEmpty(&gameList) &&
6093 ((ListGame *) gameList.tailPred)->number > 1) {
6094 GameListPopUp(f, title);
6100 return LoadGame(f, gameNumber, title, FALSE);
6103 void LoadGameProc(w, event, prms, nprms)
6109 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
6112 FileNamePopUp(_("Load game file name?"), "", LoadGamePopUp, "rb");
6115 void LoadNextGameProc(w, event, prms, nprms)
6124 void LoadPrevGameProc(w, event, prms, nprms)
6133 void ReloadGameProc(w, event, prms, nprms)
6142 void LoadNextPositionProc(w, event, prms, nprms)
6151 void LoadPrevPositionProc(w, event, prms, nprms)
6160 void ReloadPositionProc(w, event, prms, nprms)
6169 void LoadPositionProc(w, event, prms, nprms)
6175 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
6178 FileNamePopUp(_("Load position file name?"), "", LoadPosition, "rb");
6181 void SaveGameProc(w, event, prms, nprms)
6187 FileNamePopUp(_("Save game file name?"),
6188 DefaultFileName(appData.oldSaveStyle ? "game" : "pgn"),
6192 void SavePositionProc(w, event, prms, nprms)
6198 FileNamePopUp(_("Save position file name?"),
6199 DefaultFileName(appData.oldSaveStyle ? "pos" : "fen"),
6203 void ReloadCmailMsgProc(w, event, prms, nprms)
6209 ReloadCmailMsgEvent(FALSE);
6212 void MailMoveProc(w, event, prms, nprms)
6221 /* this variable is shared between CopyPositionProc and SendPositionSelection */
6222 static char *selected_fen_position=NULL;
6225 SendPositionSelection(Widget w, Atom *selection, Atom *target,
6226 Atom *type_return, XtPointer *value_return,
6227 unsigned long *length_return, int *format_return)
6229 char *selection_tmp;
6231 if (!selected_fen_position) return False; /* should never happen */
6232 if (*target == XA_STRING){
6233 /* note: since no XtSelectionDoneProc was registered, Xt will
6234 * automatically call XtFree on the value returned. So have to
6235 * make a copy of it allocated with XtMalloc */
6236 selection_tmp= XtMalloc(strlen(selected_fen_position)+16);
6237 strcpy(selection_tmp, selected_fen_position);
6239 *value_return=selection_tmp;
6240 *length_return=strlen(selection_tmp);
6241 *type_return=XA_STRING;
6242 *format_return = 8; /* bits per byte */
6249 /* note: when called from menu all parameters are NULL, so no clue what the
6250 * Widget which was clicked on was, or what the click event was
6252 void CopyPositionProc(w, event, prms, nprms)
6260 if (selected_fen_position) free(selected_fen_position);
6261 selected_fen_position = (char *)PositionToFEN(currentMove,1);
6262 if (!selected_fen_position) return;
6263 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
6265 SendPositionSelection,
6266 NULL/* lose_ownership_proc */ ,
6267 NULL/* transfer_done_proc */);
6269 free(selected_fen_position);
6270 selected_fen_position=NULL;
6274 /* function called when the data to Paste is ready */
6276 PastePositionCB(Widget w, XtPointer client_data, Atom *selection,
6277 Atom *type, XtPointer value, unsigned long *len, int *format)
6280 if (value==NULL || *len==0) return; /* nothing had been selected to copy */
6281 fenstr[*len]='\0'; /* normally this string is terminated, but be safe */
6282 EditPositionPasteFEN(fenstr);
6286 /* called when Paste Position button is pressed,
6287 * all parameters will be NULL */
6288 void PastePositionProc(w, event, prms, nprms)
6294 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
6295 /* (XtSelectionCallbackProc) */ PastePositionCB,
6296 NULL, /* client_data passed to PastePositionCB */
6298 /* better to use the time field from the event that triggered the
6299 * call to this function, but that isn't trivial to get
6307 SendGameSelection(Widget w, Atom *selection, Atom *target,
6308 Atom *type_return, XtPointer *value_return,
6309 unsigned long *length_return, int *format_return)
6311 char *selection_tmp;
6313 if (*target == XA_STRING){
6314 FILE* f = fopen(gameCopyFilename, "r");
6317 if (f == NULL) return False;
6321 selection_tmp = XtMalloc(len + 1);
6322 count = fread(selection_tmp, 1, len, f);
6324 XtFree(selection_tmp);
6327 selection_tmp[len] = NULLCHAR;
6328 *value_return = selection_tmp;
6329 *length_return = len;
6330 *type_return = XA_STRING;
6331 *format_return = 8; /* bits per byte */
6338 /* note: when called from menu all parameters are NULL, so no clue what the
6339 * Widget which was clicked on was, or what the click event was
6341 void CopyGameProc(w, event, prms, nprms)
6349 ret = SaveGameToFile(gameCopyFilename, FALSE);
6352 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
6355 NULL/* lose_ownership_proc */ ,
6356 NULL/* transfer_done_proc */);
6359 /* function called when the data to Paste is ready */
6361 PasteGameCB(Widget w, XtPointer client_data, Atom *selection,
6362 Atom *type, XtPointer value, unsigned long *len, int *format)
6365 if (value == NULL || *len == 0) {
6366 return; /* nothing had been selected to copy */
6368 f = fopen(gamePasteFilename, "w");
6370 DisplayError(_("Can't open temp file"), errno);
6373 fwrite(value, 1, *len, f);
6376 LoadGameFromFile(gamePasteFilename, 0, gamePasteFilename, TRUE);
6379 /* called when Paste Game button is pressed,
6380 * all parameters will be NULL */
6381 void PasteGameProc(w, event, prms, nprms)
6387 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
6388 /* (XtSelectionCallbackProc) */ PasteGameCB,
6389 NULL, /* client_data passed to PasteGameCB */
6391 /* better to use the time field from the event that triggered the
6392 * call to this function, but that isn't trivial to get
6402 SaveGameProc(NULL, NULL, NULL, NULL);
6406 void QuitProc(w, event, prms, nprms)
6415 void PauseProc(w, event, prms, nprms)
6425 void MachineBlackProc(w, event, prms, nprms)
6431 MachineBlackEvent();
6434 void MachineWhiteProc(w, event, prms, nprms)
6440 MachineWhiteEvent();
6443 void AnalyzeModeProc(w, event, prms, nprms)
6451 if (!first.analysisSupport) {
6452 sprintf(buf, _("%s does not support analysis"), first.tidy);
6453 DisplayError(buf, 0);
6456 /* [DM] icsEngineAnalyze [HGM] This is horrible code; reverse the gameMode and isEngineAnalyze tests! */
6457 if (appData.icsActive) {
6458 if (gameMode != IcsObserving) {
6459 sprintf(buf,_("You are not observing a game"));
6460 DisplayError(buf, 0);
6462 if (appData.icsEngineAnalyze) {
6463 if (appData.debugMode)
6464 fprintf(debugFP, _("Found unexpected active ICS engine analyze \n"));
6470 /* if enable, use want disable icsEngineAnalyze */
6471 if (appData.icsEngineAnalyze) {
6476 appData.icsEngineAnalyze = TRUE;
6477 if (appData.debugMode)
6478 fprintf(debugFP, _("ICS engine analyze starting... \n"));
6480 if (!appData.showThinking)
6481 ShowThinkingProc(w,event,prms,nprms);
6486 void AnalyzeFileProc(w, event, prms, nprms)
6492 if (!first.analysisSupport) {
6494 sprintf(buf, _("%s does not support analysis"), first.tidy);
6495 DisplayError(buf, 0);
6500 if (!appData.showThinking)
6501 ShowThinkingProc(w,event,prms,nprms);
6504 FileNamePopUp(_("File to analyze"), "", LoadGamePopUp, "rb");
6505 AnalysisPeriodicEvent(1);
6508 void TwoMachinesProc(w, event, prms, nprms)
6517 void IcsClientProc(w, event, prms, nprms)
6526 void EditGameProc(w, event, prms, nprms)
6535 void EditPositionProc(w, event, prms, nprms)
6541 EditPositionEvent();
6544 void TrainingProc(w, event, prms, nprms)
6553 void EditCommentProc(w, event, prms, nprms)
6560 EditCommentPopDown();
6566 void IcsInputBoxProc(w, event, prms, nprms)
6572 if (ICSInputBoxUp) {
6573 ICSInputBoxPopDown();
6579 void AcceptProc(w, event, prms, nprms)
6588 void DeclineProc(w, event, prms, nprms)
6597 void RematchProc(w, event, prms, nprms)
6606 void CallFlagProc(w, event, prms, nprms)
6615 void DrawProc(w, event, prms, nprms)
6624 void AbortProc(w, event, prms, nprms)
6633 void AdjournProc(w, event, prms, nprms)
6642 void ResignProc(w, event, prms, nprms)
6651 void EnterKeyProc(w, event, prms, nprms)
6657 if (ICSInputBoxUp == True)
6661 void StopObservingProc(w, event, prms, nprms)
6667 StopObservingEvent();
6670 void StopExaminingProc(w, event, prms, nprms)
6676 StopExaminingEvent();
6680 void ForwardProc(w, event, prms, nprms)
6690 void BackwardProc(w, event, prms, nprms)
6699 void ToStartProc(w, event, prms, nprms)
6708 void ToEndProc(w, event, prms, nprms)
6717 void RevertProc(w, event, prms, nprms)
6726 void TruncateGameProc(w, event, prms, nprms)
6732 TruncateGameEvent();
6734 void RetractMoveProc(w, event, prms, nprms)
6743 void MoveNowProc(w, event, prms, nprms)
6753 void AlwaysQueenProc(w, event, prms, nprms)
6761 appData.alwaysPromoteToQueen = !appData.alwaysPromoteToQueen;
6763 if (appData.alwaysPromoteToQueen) {
6764 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6766 XtSetArg(args[0], XtNleftBitmap, None);
6768 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
6772 void AnimateDraggingProc(w, event, prms, nprms)
6780 appData.animateDragging = !appData.animateDragging;
6782 if (appData.animateDragging) {
6783 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6786 XtSetArg(args[0], XtNleftBitmap, None);
6788 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Dragging"),
6792 void AnimateMovingProc(w, event, prms, nprms)
6800 appData.animate = !appData.animate;
6802 if (appData.animate) {
6803 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6806 XtSetArg(args[0], XtNleftBitmap, None);
6808 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
6812 void AutocommProc(w, event, prms, nprms)
6820 appData.autoComment = !appData.autoComment;
6822 if (appData.autoComment) {
6823 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6825 XtSetArg(args[0], XtNleftBitmap, None);
6827 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
6832 void AutoflagProc(w, event, prms, nprms)
6840 appData.autoCallFlag = !appData.autoCallFlag;
6842 if (appData.autoCallFlag) {
6843 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6845 XtSetArg(args[0], XtNleftBitmap, None);
6847 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
6851 void AutoflipProc(w, event, prms, nprms)
6859 appData.autoFlipView = !appData.autoFlipView;
6861 if (appData.autoFlipView) {
6862 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6864 XtSetArg(args[0], XtNleftBitmap, None);
6866 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flip View"),
6870 void AutobsProc(w, event, prms, nprms)
6878 appData.autoObserve = !appData.autoObserve;
6880 if (appData.autoObserve) {
6881 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6883 XtSetArg(args[0], XtNleftBitmap, None);
6885 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
6889 void AutoraiseProc(w, event, prms, nprms)
6897 appData.autoRaiseBoard = !appData.autoRaiseBoard;
6899 if (appData.autoRaiseBoard) {
6900 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6902 XtSetArg(args[0], XtNleftBitmap, None);
6904 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Raise Board"),
6908 void AutosaveProc(w, event, prms, nprms)
6916 appData.autoSaveGames = !appData.autoSaveGames;
6918 if (appData.autoSaveGames) {
6919 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6921 XtSetArg(args[0], XtNleftBitmap, None);
6923 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
6927 void BlindfoldProc(w, event, prms, nprms)
6935 appData.blindfold = !appData.blindfold;
6937 if (appData.blindfold) {
6938 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6940 XtSetArg(args[0], XtNleftBitmap, None);
6942 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Blindfold"),
6945 DrawPosition(True, NULL);
6948 void TestLegalityProc(w, event, prms, nprms)
6956 appData.testLegality = !appData.testLegality;
6958 if (appData.testLegality) {
6959 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6961 XtSetArg(args[0], XtNleftBitmap, None);
6963 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Test Legality"),
6968 void FlashMovesProc(w, event, prms, nprms)
6976 if (appData.flashCount == 0) {
6977 appData.flashCount = 3;
6979 appData.flashCount = -appData.flashCount;
6982 if (appData.flashCount > 0) {
6983 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6985 XtSetArg(args[0], XtNleftBitmap, None);
6987 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flash Moves"),
6991 void FlipViewProc(w, event, prms, nprms)
6997 flipView = !flipView;
6998 DrawPosition(True, NULL);
7001 void GetMoveListProc(w, event, prms, nprms)
7009 appData.getMoveList = !appData.getMoveList;
7011 if (appData.getMoveList) {
7012 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7015 XtSetArg(args[0], XtNleftBitmap, None);
7017 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
7022 void HighlightDraggingProc(w, event, prms, nprms)
7030 appData.highlightDragging = !appData.highlightDragging;
7032 if (appData.highlightDragging) {
7033 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7035 XtSetArg(args[0], XtNleftBitmap, None);
7037 XtSetValues(XtNameToWidget(menuBarWidget,
7038 "menuOptions.Highlight Dragging"), args, 1);
7042 void HighlightLastMoveProc(w, event, prms, nprms)
7050 appData.highlightLastMove = !appData.highlightLastMove;
7052 if (appData.highlightLastMove) {
7053 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7055 XtSetArg(args[0], XtNleftBitmap, None);
7057 XtSetValues(XtNameToWidget(menuBarWidget,
7058 "menuOptions.Highlight Last Move"), args, 1);
7061 void IcsAlarmProc(w, event, prms, nprms)
7069 appData.icsAlarm = !appData.icsAlarm;
7071 if (appData.icsAlarm) {
7072 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7074 XtSetArg(args[0], XtNleftBitmap, None);
7076 XtSetValues(XtNameToWidget(menuBarWidget,
7077 "menuOptions.ICS Alarm"), args, 1);
7080 void MoveSoundProc(w, event, prms, nprms)
7088 appData.ringBellAfterMoves = !appData.ringBellAfterMoves;
7090 if (appData.ringBellAfterMoves) {
7091 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7093 XtSetArg(args[0], XtNleftBitmap, None);
7095 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
7100 void OldSaveStyleProc(w, event, prms, nprms)
7108 appData.oldSaveStyle = !appData.oldSaveStyle;
7110 if (appData.oldSaveStyle) {
7111 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7113 XtSetArg(args[0], XtNleftBitmap, None);
7115 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Old Save Style"),
7119 void PeriodicUpdatesProc(w, event, prms, nprms)
7127 PeriodicUpdatesEvent(!appData.periodicUpdates);
7129 if (appData.periodicUpdates) {
7130 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7132 XtSetArg(args[0], XtNleftBitmap, None);
7134 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Periodic Updates"),
7138 void PonderNextMoveProc(w, event, prms, nprms)
7146 PonderNextMoveEvent(!appData.ponderNextMove);
7148 if (appData.ponderNextMove) {
7149 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7151 XtSetArg(args[0], XtNleftBitmap, None);
7153 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Ponder Next Move"),
7157 void PopupExitMessageProc(w, event, prms, nprms)
7165 appData.popupExitMessage = !appData.popupExitMessage;
7167 if (appData.popupExitMessage) {
7168 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7170 XtSetArg(args[0], XtNleftBitmap, None);
7172 XtSetValues(XtNameToWidget(menuBarWidget,
7173 "menuOptions.Popup Exit Message"), args, 1);
7176 void PopupMoveErrorsProc(w, event, prms, nprms)
7184 appData.popupMoveErrors = !appData.popupMoveErrors;
7186 if (appData.popupMoveErrors) {
7187 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7189 XtSetArg(args[0], XtNleftBitmap, None);
7191 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Popup Move Errors"),
7195 void PremoveProc(w, event, prms, nprms)
7203 appData.premove = !appData.premove;
7205 if (appData.premove) {
7206 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7208 XtSetArg(args[0], XtNleftBitmap, None);
7210 XtSetValues(XtNameToWidget(menuBarWidget,
7211 "menuOptions.Premove"), args, 1);
7214 void QuietPlayProc(w, event, prms, nprms)
7222 appData.quietPlay = !appData.quietPlay;
7224 if (appData.quietPlay) {
7225 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7227 XtSetArg(args[0], XtNleftBitmap, None);
7229 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Quiet Play"),
7233 void ShowCoordsProc(w, event, prms, nprms)
7241 appData.showCoords = !appData.showCoords;
7243 if (appData.showCoords) {
7244 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7246 XtSetArg(args[0], XtNleftBitmap, None);
7248 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
7251 DrawPosition(True, NULL);
7254 void ShowThinkingProc(w, event, prms, nprms)
7262 appData.showThinking = !appData.showThinking; // [HGM] thinking: tken out of ShowThinkingEvent
7263 ShowThinkingEvent();
7265 // [HGM] thinking: currently no suc menu item; replaced by Hide Thinking (From Human)
7266 if (appData.showThinking) {
7267 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7269 XtSetArg(args[0], XtNleftBitmap, None);
7271 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Thinking"),
7276 void HideThinkingProc(w, event, prms, nprms)
7284 appData.hideThinkingFromHuman = !appData.hideThinkingFromHuman; // [HGM] thinking: tken out of ShowThinkingEvent
7285 ShowThinkingEvent();
7287 if (appData.hideThinkingFromHuman) {
7288 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7290 XtSetArg(args[0], XtNleftBitmap, None);
7292 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
7296 void InfoProc(w, event, prms, nprms)
7303 sprintf(buf, "xterm -e info --directory %s --directory . -f %s &",
7308 void ManProc(w, event, prms, nprms)
7316 if (nprms && *nprms > 0)
7320 sprintf(buf, "xterm -e man %s &", name);
7324 void HintProc(w, event, prms, nprms)
7333 void BookProc(w, event, prms, nprms)
7342 void AboutProc(w, event, prms, nprms)
7350 char *zippy = " (with Zippy code)";
7354 sprintf(buf, "%s%s\n\n%s\n%s\n%s\n%s\n\n%s%s\n%s",
7355 programVersion, zippy,
7356 "Copyright 1991 Digital Equipment Corporation",
7357 "Enhancements Copyright 1992-2001 Free Software Foundation",
7358 "Enhancements Copyright 2005 Alessandro Scotti",
7359 "Enhancements Copyright 2007-2008 H.G.Muller",
7360 PRODUCT, " is free software and carries NO WARRANTY;",
7361 "see the file COPYING for more information.");
7362 ErrorPopUp(_("About XBoard"), buf, FALSE);
7365 void DebugProc(w, event, prms, nprms)
7371 appData.debugMode = !appData.debugMode;
7374 void AboutGameProc(w, event, prms, nprms)
7383 void NothingProc(w, event, prms, nprms)
7392 void Iconify(w, event, prms, nprms)
7401 XtSetArg(args[0], XtNiconic, True);
7402 XtSetValues(shellWidget, args, 1);
7405 void DisplayMessage(message, extMessage)
7406 char *message, *extMessage;
7413 sprintf(buf, "%s %s", message, extMessage);
7416 message = extMessage;
7419 XtSetArg(arg, XtNlabel, message);
7420 XtSetValues(messageWidget, &arg, 1);
7423 void DisplayTitle(text)
7428 char title[MSG_SIZ];
7431 if (text == NULL) text = "";
7433 if (appData.titleInWindow) {
7435 XtSetArg(args[i], XtNlabel, text); i++;
7436 XtSetValues(titleWidget, args, i);
7439 if (*text != NULLCHAR) {
7441 strcpy(title, text);
7442 } else if (appData.icsActive) {
7443 sprintf(icon, "%s", appData.icsHost);
7444 sprintf(title, "%s: %s", programName, appData.icsHost);
7445 } else if (appData.cmailGameName[0] != NULLCHAR) {
7446 sprintf(icon, "%s", "CMail");
7447 sprintf(title, "%s: %s", programName, "CMail");
7449 // [HGM] license: This stuff should really be done in back-end, but WinBoard already had a pop-up for it
7450 } else if (gameInfo.variant == VariantGothic) {
7451 strcpy(icon, programName);
7452 strcpy(title, GOTHIC);
7455 } else if (gameInfo.variant == VariantFalcon) {
7456 strcpy(icon, programName);
7457 strcpy(title, FALCON);
7459 } else if (appData.noChessProgram) {
7460 strcpy(icon, programName);
7461 strcpy(title, programName);
7463 strcpy(icon, first.tidy);
7464 sprintf(title, "%s: %s", programName, first.tidy);
7467 XtSetArg(args[i], XtNiconName, (XtArgVal) icon); i++;
7468 XtSetArg(args[i], XtNtitle, (XtArgVal) title); i++;
7469 XtSetValues(shellWidget, args, i);
7473 void DisplayError(message, error)
7480 if (appData.debugMode || appData.matchMode) {
7481 fprintf(stderr, "%s: %s\n", programName, message);
7484 if (appData.debugMode || appData.matchMode) {
7485 fprintf(stderr, "%s: %s: %s\n",
7486 programName, message, strerror(error));
7488 sprintf(buf, "%s: %s", message, strerror(error));
7491 ErrorPopUp(_("Error"), message, FALSE);
7495 void DisplayMoveError(message)
7500 DrawPosition(FALSE, NULL);
7501 if (appData.debugMode || appData.matchMode) {
7502 fprintf(stderr, "%s: %s\n", programName, message);
7504 if (appData.popupMoveErrors) {
7505 ErrorPopUp(_("Error"), message, FALSE);
7507 DisplayMessage(message, "");
7512 void DisplayFatalError(message, error, status)
7518 errorExitStatus = status;
7520 fprintf(stderr, "%s: %s\n", programName, message);
7522 fprintf(stderr, "%s: %s: %s\n",
7523 programName, message, strerror(error));
7524 sprintf(buf, "%s: %s", message, strerror(error));
7527 if (appData.popupExitMessage && boardWidget && XtIsRealized(boardWidget)) {
7528 ErrorPopUp(status ? _("Fatal Error") : _("Exiting"), message, TRUE);
7534 void DisplayInformation(message)
7538 ErrorPopUp(_("Information"), message, TRUE);
7541 void DisplayNote(message)
7545 ErrorPopUp(_("Note"), message, FALSE);
7549 NullXErrorCheck(dpy, error_event)
7551 XErrorEvent *error_event;
7556 void DisplayIcsInteractionTitle(message)
7559 if (oldICSInteractionTitle == NULL) {
7560 /* Magic to find the old window title, adapted from vim */
7561 char *wina = getenv("WINDOWID");
7563 Window win = (Window) atoi(wina);
7564 Window root, parent, *children;
7565 unsigned int nchildren;
7566 int (*oldHandler)() = XSetErrorHandler(NullXErrorCheck);
7568 if (XFetchName(xDisplay, win, &oldICSInteractionTitle)) break;
7569 if (!XQueryTree(xDisplay, win, &root, &parent,
7570 &children, &nchildren)) break;
7571 if (children) XFree((void *)children);
7572 if (parent == root || parent == 0) break;
7575 XSetErrorHandler(oldHandler);
7577 if (oldICSInteractionTitle == NULL) {
7578 oldICSInteractionTitle = "xterm";
7581 printf("\033]0;%s\007", message);
7585 char pendingReplyPrefix[MSG_SIZ];
7586 ProcRef pendingReplyPR;
7588 void AskQuestionProc(w, event, prms, nprms)
7595 fprintf(stderr, _("AskQuestionProc needed 4 parameters, got %d\n"),
7599 AskQuestionEvent(prms[0], prms[1], prms[2], prms[3]);
7602 void AskQuestionPopDown()
7604 if (!askQuestionUp) return;
7605 XtPopdown(askQuestionShell);
7606 XtDestroyWidget(askQuestionShell);
7607 askQuestionUp = False;
7610 void AskQuestionReplyAction(w, event, prms, nprms)
7620 reply = XawDialogGetValueString(w = XtParent(w));
7621 strcpy(buf, pendingReplyPrefix);
7622 if (*buf) strcat(buf, " ");
7625 OutputToProcess(pendingReplyPR, buf, strlen(buf), &err);
7626 AskQuestionPopDown();
7628 if (err) DisplayFatalError(_("Error writing to chess program"), err, 0);
7631 void AskQuestionCallback(w, client_data, call_data)
7633 XtPointer client_data, call_data;
7638 XtSetArg(args[0], XtNlabel, &name);
7639 XtGetValues(w, args, 1);
7641 if (strcmp(name, _("cancel")) == 0) {
7642 AskQuestionPopDown();
7644 AskQuestionReplyAction(w, NULL, NULL, NULL);
7648 void AskQuestion(title, question, replyPrefix, pr)
7649 char *title, *question, *replyPrefix;
7653 Widget popup, layout, dialog, edit;
7659 strcpy(pendingReplyPrefix, replyPrefix);
7660 pendingReplyPR = pr;
7663 XtSetArg(args[i], XtNresizable, True); i++;
7664 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
7665 askQuestionShell = popup =
7666 XtCreatePopupShell(title, transientShellWidgetClass,
7667 shellWidget, args, i);
7670 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
7671 layoutArgs, XtNumber(layoutArgs));
7674 XtSetArg(args[i], XtNlabel, question); i++;
7675 XtSetArg(args[i], XtNvalue, ""); i++;
7676 XtSetArg(args[i], XtNborderWidth, 0); i++;
7677 dialog = XtCreateManagedWidget("question", dialogWidgetClass,
7680 XawDialogAddButton(dialog, _("enter"), AskQuestionCallback,
7681 (XtPointer) dialog);
7682 XawDialogAddButton(dialog, _("cancel"), AskQuestionCallback,
7683 (XtPointer) dialog);
7685 XtRealizeWidget(popup);
7686 CatchDeleteWindow(popup, "AskQuestionPopDown");
7688 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
7689 &x, &y, &win_x, &win_y, &mask);
7691 XtSetArg(args[0], XtNx, x - 10);
7692 XtSetArg(args[1], XtNy, y - 30);
7693 XtSetValues(popup, args, 2);
7695 XtPopup(popup, XtGrabExclusive);
7696 askQuestionUp = True;
7698 edit = XtNameToWidget(dialog, "*value");
7699 XtSetKeyboardFocus(popup, edit);
7707 if (*name == NULLCHAR) {
7709 } else if (strcmp(name, "$") == 0) {
7710 putc(BELLCHAR, stderr);
7713 sprintf(buf, "%s '%s' &", appData.soundProgram, name);
7721 PlaySound(appData.soundMove);
7727 PlaySound(appData.soundIcsWin);
7733 PlaySound(appData.soundIcsLoss);
7739 PlaySound(appData.soundIcsDraw);
7743 PlayIcsUnfinishedSound()
7745 PlaySound(appData.soundIcsUnfinished);
7751 PlaySound(appData.soundIcsAlarm);
7757 system("stty echo");
7763 system("stty -echo");
7767 Colorize(cc, continuation)
7772 int count, outCount, error;
7774 if (textColors[(int)cc].bg > 0) {
7775 if (textColors[(int)cc].fg > 0) {
7776 sprintf(buf, "\033[0;%d;%d;%dm", textColors[(int)cc].attr,
7777 textColors[(int)cc].fg, textColors[(int)cc].bg);
7779 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
7780 textColors[(int)cc].bg);
7783 if (textColors[(int)cc].fg > 0) {
7784 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
7785 textColors[(int)cc].fg);
7787 sprintf(buf, "\033[0;%dm", textColors[(int)cc].attr);
7790 count = strlen(buf);
7791 outCount = OutputToProcess(NoProc, buf, count, &error);
7792 if (outCount < count) {
7793 DisplayFatalError(_("Error writing to display"), error, 1);
7796 if (continuation) return;
7799 PlaySound(appData.soundShout);
7802 PlaySound(appData.soundSShout);
7805 PlaySound(appData.soundChannel1);
7808 PlaySound(appData.soundChannel);
7811 PlaySound(appData.soundKibitz);
7814 PlaySound(appData.soundTell);
7816 case ColorChallenge:
7817 PlaySound(appData.soundChallenge);
7820 PlaySound(appData.soundRequest);
7823 PlaySound(appData.soundSeek);
7834 return getpwuid(getuid())->pw_name;
7837 static char *ExpandPathName(path)
7840 static char static_buf[2000];
7841 char *d, *s, buf[2000];
7847 while (*s && isspace(*s))
7856 if (*(s+1) == '/') {
7857 strcpy(d, getpwuid(getuid())->pw_dir);
7862 *strchr(buf, '/') = 0;
7863 pwd = getpwnam(buf);
7866 fprintf(stderr, _("ERROR: Unknown user %s (in path %s)\n"),
7870 strcpy(d, pwd->pw_dir);
7871 strcat(d, strchr(s+1, '/'));
7882 static char host_name[MSG_SIZ];
7884 #if HAVE_GETHOSTNAME
7885 gethostname(host_name, MSG_SIZ);
7887 #else /* not HAVE_GETHOSTNAME */
7888 # if HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H
7889 sysinfo(SI_HOSTNAME, host_name, MSG_SIZ);
7891 # else /* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
7893 # endif/* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
7894 #endif /* not HAVE_GETHOSTNAME */
7897 XtIntervalId delayedEventTimerXID = 0;
7898 DelayedEventCallback delayedEventCallback = 0;
7903 delayedEventTimerXID = 0;
7904 delayedEventCallback();
7908 ScheduleDelayedEvent(cb, millisec)
7909 DelayedEventCallback cb; long millisec;
7911 delayedEventCallback = cb;
7912 delayedEventTimerXID =
7913 XtAppAddTimeOut(appContext, millisec,
7914 (XtTimerCallbackProc) FireDelayedEvent, (XtPointer) 0);
7917 DelayedEventCallback
7920 if (delayedEventTimerXID) {
7921 return delayedEventCallback;
7928 CancelDelayedEvent()
7930 if (delayedEventTimerXID) {
7931 XtRemoveTimeOut(delayedEventTimerXID);
7932 delayedEventTimerXID = 0;
7936 XtIntervalId loadGameTimerXID = 0;
7938 int LoadGameTimerRunning()
7940 return loadGameTimerXID != 0;
7943 int StopLoadGameTimer()
7945 if (loadGameTimerXID != 0) {
7946 XtRemoveTimeOut(loadGameTimerXID);
7947 loadGameTimerXID = 0;
7955 LoadGameTimerCallback(arg, id)
7959 loadGameTimerXID = 0;
7964 StartLoadGameTimer(millisec)
7968 XtAppAddTimeOut(appContext, millisec,
7969 (XtTimerCallbackProc) LoadGameTimerCallback,
7973 XtIntervalId analysisClockXID = 0;
7976 AnalysisClockCallback(arg, id)
7980 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile
7981 || appData.icsEngineAnalyze) { // [DM]
7982 AnalysisPeriodicEvent(0);
7983 StartAnalysisClock();
7988 StartAnalysisClock()
7991 XtAppAddTimeOut(appContext, 2000,
7992 (XtTimerCallbackProc) AnalysisClockCallback,
7996 XtIntervalId clockTimerXID = 0;
7998 int ClockTimerRunning()
8000 return clockTimerXID != 0;
8003 int StopClockTimer()
8005 if (clockTimerXID != 0) {
8006 XtRemoveTimeOut(clockTimerXID);
8015 ClockTimerCallback(arg, id)
8024 StartClockTimer(millisec)
8028 XtAppAddTimeOut(appContext, millisec,
8029 (XtTimerCallbackProc) ClockTimerCallback,
8034 DisplayTimerLabel(w, color, timer, highlight)
8043 if (appData.clockMode) {
8044 sprintf(buf, "%s: %s", color, TimeString(timer));
8045 XtSetArg(args[0], XtNlabel, buf);
8047 sprintf(buf, "%s ", color);
8048 XtSetArg(args[0], XtNlabel, buf);
8052 XtSetArg(args[1], XtNbackground, timerForegroundPixel);
8053 XtSetArg(args[2], XtNforeground, timerBackgroundPixel);
8055 XtSetArg(args[1], XtNbackground, timerBackgroundPixel);
8056 XtSetArg(args[2], XtNforeground, timerForegroundPixel);
8059 XtSetValues(w, args, 3);
8063 DisplayWhiteClock(timeRemaining, highlight)
8069 if(appData.noGUI) return;
8070 DisplayTimerLabel(whiteTimerWidget, _("White"), timeRemaining, highlight);
8071 if (highlight && iconPixmap == bIconPixmap) {
8072 iconPixmap = wIconPixmap;
8073 XtSetArg(args[0], XtNiconPixmap, iconPixmap);
8074 XtSetValues(shellWidget, args, 1);
8079 DisplayBlackClock(timeRemaining, highlight)
8085 if(appData.noGUI) return;
8086 DisplayTimerLabel(blackTimerWidget, _("Black"), timeRemaining, highlight);
8087 if (highlight && iconPixmap == wIconPixmap) {
8088 iconPixmap = bIconPixmap;
8089 XtSetArg(args[0], XtNiconPixmap, iconPixmap);
8090 XtSetValues(shellWidget, args, 1);
8108 int StartChildProcess(cmdLine, dir, pr)
8115 int to_prog[2], from_prog[2];
8119 if (appData.debugMode) {
8120 fprintf(stderr, "StartChildProcess (dir=\"%s\") %s\n",dir, cmdLine);
8123 /* We do NOT feed the cmdLine to the shell; we just
8124 parse it into blank-separated arguments in the
8125 most simple-minded way possible.
8128 strcpy(buf, cmdLine);
8133 if (p == NULL) break;
8138 SetUpChildIO(to_prog, from_prog);
8140 if ((pid = fork()) == 0) {
8142 // [HGM] PSWBTM: made order resistant against case where fd of created pipe was 0 or 1
8143 close(to_prog[1]); // first close the unused pipe ends
8144 close(from_prog[0]);
8145 dup2(to_prog[0], 0); // to_prog was created first, nd is the only one to use 0 or 1
8146 dup2(from_prog[1], 1);
8147 if(to_prog[0] >= 2) close(to_prog[0]); // if 0 or 1, the dup2 already cosed the original
8148 close(from_prog[1]); // and closing again loses one of the pipes!
8149 if(fileno(stderr) >= 2) // better safe than sorry...
8150 dup2(1, fileno(stderr)); /* force stderr to the pipe */
8152 if (dir[0] != NULLCHAR && chdir(dir) != 0) {
8157 nice(appData.niceEngines); // [HGM] nice: adjust priority of engine proc
8159 execvp(argv[0], argv);
8161 /* If we get here, exec failed */
8166 /* Parent process */
8168 close(from_prog[1]);
8170 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8173 cp->fdFrom = from_prog[0];
8174 cp->fdTo = to_prog[1];
8179 // [HGM] kill: implement the 'hard killing' of AS's Winboard_x
8180 static RETSIGTYPE AlarmCallBack(int n)
8186 DestroyChildProcess(pr, signalType)
8190 ChildProc *cp = (ChildProc *) pr;
8192 if (cp->kind != CPReal) return;
8194 if (signalType == 10) { // [HGM] kill: if it does not terminate in 3 sec, kill
8195 signal(SIGALRM, AlarmCallBack);
8197 if(wait((int *) 0) == -1) { // process does not terminate on its own accord
8198 kill(cp->pid, SIGKILL); // kill it forcefully
8199 wait((int *) 0); // and wait again
8203 kill(cp->pid, signalType == 9 ? SIGKILL : SIGTERM); // [HGM] kill: use hard kill if so requested
8205 /* Process is exiting either because of the kill or because of
8206 a quit command sent by the backend; either way, wait for it to die.
8215 InterruptChildProcess(pr)
8218 ChildProc *cp = (ChildProc *) pr;
8220 if (cp->kind != CPReal) return;
8221 (void) kill(cp->pid, SIGINT); /* stop it thinking */
8224 int OpenTelnet(host, port, pr)
8229 char cmdLine[MSG_SIZ];
8231 if (port[0] == NULLCHAR) {
8232 sprintf(cmdLine, "%s %s", appData.telnetProgram, host);
8234 sprintf(cmdLine, "%s %s %s", appData.telnetProgram, host, port);
8236 return StartChildProcess(cmdLine, "", pr);
8239 int OpenTCP(host, port, pr)
8245 DisplayFatalError(_("Socket support is not configured in"), 0, 2);
8246 #else /* !OMIT_SOCKETS */
8248 struct sockaddr_in sa;
8250 unsigned short uport;
8253 if ((s = socket(AF_INET, SOCK_STREAM, 6)) < 0) {
8257 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
8258 sa.sin_family = AF_INET;
8259 sa.sin_addr.s_addr = INADDR_ANY;
8260 uport = (unsigned short) 0;
8261 sa.sin_port = htons(uport);
8262 if (bind(s, (struct sockaddr *) &sa, sizeof(struct sockaddr_in)) < 0) {
8266 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
8267 if (!(hp = gethostbyname(host))) {
8269 if (sscanf(host, "%d.%d.%d.%d", &b0, &b1, &b2, &b3) == 4) {
8270 hp = (struct hostent *) calloc(1, sizeof(struct hostent));
8271 hp->h_addrtype = AF_INET;
8273 hp->h_addr_list = (char **) calloc(2, sizeof(char *));
8274 hp->h_addr_list[0] = (char *) malloc(4);
8275 hp->h_addr_list[0][0] = b0;
8276 hp->h_addr_list[0][1] = b1;
8277 hp->h_addr_list[0][2] = b2;
8278 hp->h_addr_list[0][3] = b3;
8283 sa.sin_family = hp->h_addrtype;
8284 uport = (unsigned short) atoi(port);
8285 sa.sin_port = htons(uport);
8286 memcpy((char *) &sa.sin_addr, hp->h_addr, hp->h_length);
8288 if (connect(s, (struct sockaddr *) &sa,
8289 sizeof(struct sockaddr_in)) < 0) {
8293 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8300 #endif /* !OMIT_SOCKETS */
8305 int OpenCommPort(name, pr)
8312 fd = open(name, 2, 0);
8313 if (fd < 0) return errno;
8315 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8325 int OpenLoopback(pr)
8331 SetUpChildIO(to, from);
8333 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8336 cp->fdFrom = to[0]; /* note not from[0]; we are doing a loopback */
8343 int OpenRcmd(host, user, cmd, pr)
8344 char *host, *user, *cmd;
8347 DisplayFatalError(_("internal rcmd not implemented for Unix"), 0, 1);
8351 #define INPUT_SOURCE_BUF_SIZE 8192
8360 char buf[INPUT_SOURCE_BUF_SIZE];
8365 DoInputCallback(closure, source, xid)
8370 InputSource *is = (InputSource *) closure;
8375 if (is->lineByLine) {
8376 count = read(is->fd, is->unused,
8377 INPUT_SOURCE_BUF_SIZE - (is->unused - is->buf));
8379 (is->func)(is, is->closure, is->buf, count, count ? errno : 0);
8382 is->unused += count;
8384 while (p < is->unused) {
8385 q = memchr(p, '\n', is->unused - p);
8386 if (q == NULL) break;
8388 (is->func)(is, is->closure, p, q - p, 0);
8392 while (p < is->unused) {
8397 count = read(is->fd, is->buf, INPUT_SOURCE_BUF_SIZE);
8402 (is->func)(is, is->closure, is->buf, count, error);
8406 InputSourceRef AddInputSource(pr, lineByLine, func, closure)
8413 ChildProc *cp = (ChildProc *) pr;
8415 is = (InputSource *) calloc(1, sizeof(InputSource));
8416 is->lineByLine = lineByLine;
8420 is->fd = fileno(stdin);
8422 is->kind = cp->kind;
8423 is->fd = cp->fdFrom;
8426 is->unused = is->buf;
8429 is->xid = XtAppAddInput(appContext, is->fd,
8430 (XtPointer) (XtInputReadMask),
8431 (XtInputCallbackProc) DoInputCallback,
8433 is->closure = closure;
8434 return (InputSourceRef) is;
8438 RemoveInputSource(isr)
8441 InputSource *is = (InputSource *) isr;
8443 if (is->xid == 0) return;
8444 XtRemoveInput(is->xid);
8448 int OutputToProcess(pr, message, count, outError)
8454 ChildProc *cp = (ChildProc *) pr;
8458 outCount = fwrite(message, 1, count, stdout);
8460 outCount = write(cp->fdTo, message, count);
8470 /* Output message to process, with "ms" milliseconds of delay
8471 between each character. This is needed when sending the logon
8472 script to ICC, which for some reason doesn't like the
8473 instantaneous send. */
8474 int OutputToProcessDelayed(pr, message, count, outError, msdelay)
8481 ChildProc *cp = (ChildProc *) pr;
8486 r = write(cp->fdTo, message++, 1);
8499 /**** Animation code by Hugh Fisher, DCS, ANU.
8501 Known problem: if a window overlapping the board is
8502 moved away while a piece is being animated underneath,
8503 the newly exposed area won't be updated properly.
8504 I can live with this.
8506 Known problem: if you look carefully at the animation
8507 of pieces in mono mode, they are being drawn as solid
8508 shapes without interior detail while moving. Fixing
8509 this would be a major complication for minimal return.
8512 /* Masks for XPM pieces. Black and white pieces can have
8513 different shapes, but in the interest of retaining my
8514 sanity pieces must have the same outline on both light
8515 and dark squares, and all pieces must use the same
8516 background square colors/images. */
8519 CreateAnimMasks (pieceDepth)
8526 unsigned long plane;
8529 /* Need a bitmap just to get a GC with right depth */
8530 buf = XCreatePixmap(xDisplay, xBoardWindow,
8532 values.foreground = 1;
8533 values.background = 0;
8534 /* Don't use XtGetGC, not read only */
8535 maskGC = XCreateGC(xDisplay, buf,
8536 GCForeground | GCBackground, &values);
8537 XFreePixmap(xDisplay, buf);
8539 buf = XCreatePixmap(xDisplay, xBoardWindow,
8540 squareSize, squareSize, pieceDepth);
8541 values.foreground = XBlackPixel(xDisplay, xScreen);
8542 values.background = XWhitePixel(xDisplay, xScreen);
8543 bufGC = XCreateGC(xDisplay, buf,
8544 GCForeground | GCBackground, &values);
8546 for (piece = WhitePawn; piece <= BlackKing; piece++) {
8547 /* Begin with empty mask */
8548 xpmMask[piece] = XCreatePixmap(xDisplay, xBoardWindow,
8549 squareSize, squareSize, 1);
8550 XSetFunction(xDisplay, maskGC, GXclear);
8551 XFillRectangle(xDisplay, xpmMask[piece], maskGC,
8552 0, 0, squareSize, squareSize);
8554 /* Take a copy of the piece */
8559 XSetFunction(xDisplay, bufGC, GXcopy);
8560 XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % (int)BlackPawn],
8562 0, 0, squareSize, squareSize, 0, 0);
8564 /* XOR the background (light) over the piece */
8565 XSetFunction(xDisplay, bufGC, GXxor);
8567 XCopyArea(xDisplay, xpmLightSquare, buf, bufGC,
8568 0, 0, squareSize, squareSize, 0, 0);
8570 XSetForeground(xDisplay, bufGC, lightSquareColor);
8571 XFillRectangle(xDisplay, buf, bufGC, 0, 0, squareSize, squareSize);
8574 /* We now have an inverted piece image with the background
8575 erased. Construct mask by just selecting all the non-zero
8576 pixels - no need to reconstruct the original image. */
8577 XSetFunction(xDisplay, maskGC, GXor);
8579 /* Might be quicker to download an XImage and create bitmap
8580 data from it rather than this N copies per piece, but it
8581 only takes a fraction of a second and there is a much
8582 longer delay for loading the pieces. */
8583 for (n = 0; n < pieceDepth; n ++) {
8584 XCopyPlane(xDisplay, buf, xpmMask[piece], maskGC,
8585 0, 0, squareSize, squareSize,
8591 XFreePixmap(xDisplay, buf);
8592 XFreeGC(xDisplay, bufGC);
8593 XFreeGC(xDisplay, maskGC);
8597 InitAnimState (anim, info)
8599 XWindowAttributes * info;
8604 /* Each buffer is square size, same depth as window */
8605 anim->saveBuf = XCreatePixmap(xDisplay, xBoardWindow,
8606 squareSize, squareSize, info->depth);
8607 anim->newBuf = XCreatePixmap(xDisplay, xBoardWindow,
8608 squareSize, squareSize, info->depth);
8610 /* Create a plain GC for blitting */
8611 mask = GCForeground | GCBackground | GCFunction |
8612 GCPlaneMask | GCGraphicsExposures;
8613 values.foreground = XBlackPixel(xDisplay, xScreen);
8614 values.background = XWhitePixel(xDisplay, xScreen);
8615 values.function = GXcopy;
8616 values.plane_mask = AllPlanes;
8617 values.graphics_exposures = False;
8618 anim->blitGC = XCreateGC(xDisplay, xBoardWindow, mask, &values);
8620 /* Piece will be copied from an existing context at
8621 the start of each new animation/drag. */
8622 anim->pieceGC = XCreateGC(xDisplay, xBoardWindow, 0, &values);
8624 /* Outline will be a read-only copy of an existing */
8625 anim->outlineGC = None;
8631 static int done = 0;
8632 XWindowAttributes info;
8636 XGetWindowAttributes(xDisplay, xBoardWindow, &info);
8638 InitAnimState(&game, &info);
8639 InitAnimState(&player, &info);
8641 /* For XPM pieces, we need bitmaps to use as masks. */
8643 CreateAnimMasks(info.depth);
8648 static Boolean frameWaiting;
8650 static RETSIGTYPE FrameAlarm (sig)
8653 frameWaiting = False;
8654 /* In case System-V style signals. Needed?? */
8655 signal(SIGALRM, FrameAlarm);
8662 struct itimerval delay;
8664 XSync(xDisplay, False);
8667 frameWaiting = True;
8668 signal(SIGALRM, FrameAlarm);
8669 delay.it_interval.tv_sec =
8670 delay.it_value.tv_sec = time / 1000;
8671 delay.it_interval.tv_usec =
8672 delay.it_value.tv_usec = (time % 1000) * 1000;
8673 setitimer(ITIMER_REAL, &delay, NULL);
8675 /* Ugh -- busy-wait! --tpm */
8676 while (frameWaiting);
8678 while (frameWaiting) pause();
8680 delay.it_interval.tv_sec = delay.it_value.tv_sec = 0;
8681 delay.it_interval.tv_usec = delay.it_value.tv_usec = 0;
8682 setitimer(ITIMER_REAL, &delay, NULL);
8692 XSync(xDisplay, False);
8694 usleep(time * 1000);
8699 /* Convert board position to corner of screen rect and color */
8702 ScreenSquare(column, row, pt, color)
8703 int column; int row; XPoint * pt; int * color;
8706 pt->x = lineGap + ((BOARD_WIDTH-1)-column) * (squareSize + lineGap);
8707 pt->y = lineGap + row * (squareSize + lineGap);
8709 pt->x = lineGap + column * (squareSize + lineGap);
8710 pt->y = lineGap + ((BOARD_HEIGHT-1)-row) * (squareSize + lineGap);
8712 *color = SquareColor(row, column);
8715 /* Convert window coords to square */
8718 BoardSquare(x, y, column, row)
8719 int x; int y; int * column; int * row;
8721 *column = EventToSquare(x, BOARD_WIDTH);
8722 if (flipView && *column >= 0)
8723 *column = BOARD_WIDTH - 1 - *column;
8724 *row = EventToSquare(y, BOARD_HEIGHT);
8725 if (!flipView && *row >= 0)
8726 *row = BOARD_HEIGHT - 1 - *row;
8731 #undef Max /* just in case */
8733 #define Max(a, b) ((a) > (b) ? (a) : (b))
8734 #define Min(a, b) ((a) < (b) ? (a) : (b))
8737 SetRect(rect, x, y, width, height)
8738 XRectangle * rect; int x; int y; int width; int height;
8742 rect->width = width;
8743 rect->height = height;
8746 /* Test if two frames overlap. If they do, return
8747 intersection rect within old and location of
8748 that rect within new. */
8751 Intersect(old, new, size, area, pt)
8752 XPoint * old; XPoint * new;
8753 int size; XRectangle * area; XPoint * pt;
8755 if (old->x > new->x + size || new->x > old->x + size ||
8756 old->y > new->y + size || new->y > old->y + size) {
8759 SetRect(area, Max(new->x - old->x, 0), Max(new->y - old->y, 0),
8760 size - abs(old->x - new->x), size - abs(old->y - new->y));
8761 pt->x = Max(old->x - new->x, 0);
8762 pt->y = Max(old->y - new->y, 0);
8767 /* For two overlapping frames, return the rect(s)
8768 in the old that do not intersect with the new. */
8771 CalcUpdateRects(old, new, size, update, nUpdates)
8772 XPoint * old; XPoint * new; int size;
8773 XRectangle update[]; int * nUpdates;
8777 /* If old = new (shouldn't happen) then nothing to draw */
8778 if (old->x == new->x && old->y == new->y) {
8782 /* Work out what bits overlap. Since we know the rects
8783 are the same size we don't need a full intersect calc. */
8785 /* Top or bottom edge? */
8786 if (new->y > old->y) {
8787 SetRect(&(update[count]), old->x, old->y, size, new->y - old->y);
8789 } else if (old->y > new->y) {
8790 SetRect(&(update[count]), old->x, old->y + size - (old->y - new->y),
8791 size, old->y - new->y);
8794 /* Left or right edge - don't overlap any update calculated above. */
8795 if (new->x > old->x) {
8796 SetRect(&(update[count]), old->x, Max(new->y, old->y),
8797 new->x - old->x, size - abs(new->y - old->y));
8799 } else if (old->x > new->x) {
8800 SetRect(&(update[count]), new->x + size, Max(new->y, old->y),
8801 old->x - new->x, size - abs(new->y - old->y));
8808 /* Generate a series of frame coords from start->mid->finish.
8809 The movement rate doubles until the half way point is
8810 reached, then halves back down to the final destination,
8811 which gives a nice slow in/out effect. The algorithmn
8812 may seem to generate too many intermediates for short
8813 moves, but remember that the purpose is to attract the
8814 viewers attention to the piece about to be moved and
8815 then to where it ends up. Too few frames would be less
8819 Tween(start, mid, finish, factor, frames, nFrames)
8820 XPoint * start; XPoint * mid;
8821 XPoint * finish; int factor;
8822 XPoint frames[]; int * nFrames;
8824 int fraction, n, count;
8828 /* Slow in, stepping 1/16th, then 1/8th, ... */
8830 for (n = 0; n < factor; n++)
8832 for (n = 0; n < factor; n++) {
8833 frames[count].x = start->x + (mid->x - start->x) / fraction;
8834 frames[count].y = start->y + (mid->y - start->y) / fraction;
8836 fraction = fraction / 2;
8840 frames[count] = *mid;
8843 /* Slow out, stepping 1/2, then 1/4, ... */
8845 for (n = 0; n < factor; n++) {
8846 frames[count].x = finish->x - (finish->x - mid->x) / fraction;
8847 frames[count].y = finish->y - (finish->y - mid->y) / fraction;
8849 fraction = fraction * 2;
8854 /* Draw a piece on the screen without disturbing what's there */
8857 SelectGCMask(piece, clip, outline, mask)
8858 ChessSquare piece; GC * clip; GC * outline; Pixmap * mask;
8862 /* Bitmap for piece being moved. */
8863 if (appData.monoMode) {
8864 *mask = *pieceToSolid(piece);
8865 } else if (useImages) {
8867 *mask = xpmMask[piece];
8869 *mask = ximMaskPm[piece%(int)BlackPawn];
8872 *mask = *pieceToSolid(piece);
8875 /* GC for piece being moved. Square color doesn't matter, but
8876 since it gets modified we make a copy of the original. */
8878 if (appData.monoMode)
8883 if (appData.monoMode)
8888 XCopyGC(xDisplay, source, 0xFFFFFFFF, *clip);
8890 /* Outline only used in mono mode and is not modified */
8892 *outline = bwPieceGC;
8894 *outline = wbPieceGC;
8898 OverlayPiece(piece, clip, outline, dest)
8899 ChessSquare piece; GC clip; GC outline; Drawable dest;
8904 /* Draw solid rectangle which will be clipped to shape of piece */
8905 XFillRectangle(xDisplay, dest, clip,
8906 0, 0, squareSize, squareSize);
8907 if (appData.monoMode)
8908 /* Also draw outline in contrasting color for black
8909 on black / white on white cases */
8910 XCopyPlane(xDisplay, *pieceToOutline(piece), dest, outline,
8911 0, 0, squareSize, squareSize, 0, 0, 1);
8913 /* Copy the piece */
8918 XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % (int)BlackPawn],
8920 0, 0, squareSize, squareSize,
8925 /* Animate the movement of a single piece */
8928 BeginAnimation(anim, piece, startColor, start)
8936 /* The old buffer is initialised with the start square (empty) */
8937 BlankSquare(0, 0, startColor, EmptySquare, anim->saveBuf);
8938 anim->prevFrame = *start;
8940 /* The piece will be drawn using its own bitmap as a matte */
8941 SelectGCMask(piece, &anim->pieceGC, &anim->outlineGC, &mask);
8942 XSetClipMask(xDisplay, anim->pieceGC, mask);
8946 AnimationFrame(anim, frame, piece)
8951 XRectangle updates[4];
8956 /* Save what we are about to draw into the new buffer */
8957 XCopyArea(xDisplay, xBoardWindow, anim->newBuf, anim->blitGC,
8958 frame->x, frame->y, squareSize, squareSize,
8961 /* Erase bits of the previous frame */
8962 if (Intersect(&anim->prevFrame, frame, squareSize, &overlap, &pt)) {
8963 /* Where the new frame overlapped the previous,
8964 the contents in newBuf are wrong. */
8965 XCopyArea(xDisplay, anim->saveBuf, anim->newBuf, anim->blitGC,
8966 overlap.x, overlap.y,
8967 overlap.width, overlap.height,
8969 /* Repaint the areas in the old that don't overlap new */
8970 CalcUpdateRects(&anim->prevFrame, frame, squareSize, updates, &count);
8971 for (i = 0; i < count; i++)
8972 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
8973 updates[i].x - anim->prevFrame.x,
8974 updates[i].y - anim->prevFrame.y,
8975 updates[i].width, updates[i].height,
8976 updates[i].x, updates[i].y);
8978 /* Easy when no overlap */
8979 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
8980 0, 0, squareSize, squareSize,
8981 anim->prevFrame.x, anim->prevFrame.y);
8984 /* Save this frame for next time round */
8985 XCopyArea(xDisplay, anim->newBuf, anim->saveBuf, anim->blitGC,
8986 0, 0, squareSize, squareSize,
8988 anim->prevFrame = *frame;
8990 /* Draw piece over original screen contents, not current,
8991 and copy entire rect. Wipes out overlapping piece images. */
8992 OverlayPiece(piece, anim->pieceGC, anim->outlineGC, anim->newBuf);
8993 XCopyArea(xDisplay, anim->newBuf, xBoardWindow, anim->blitGC,
8994 0, 0, squareSize, squareSize,
8995 frame->x, frame->y);
8999 EndAnimation (anim, finish)
9003 XRectangle updates[4];
9008 /* The main code will redraw the final square, so we
9009 only need to erase the bits that don't overlap. */
9010 if (Intersect(&anim->prevFrame, finish, squareSize, &overlap, &pt)) {
9011 CalcUpdateRects(&anim->prevFrame, finish, squareSize, updates, &count);
9012 for (i = 0; i < count; i++)
9013 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9014 updates[i].x - anim->prevFrame.x,
9015 updates[i].y - anim->prevFrame.y,
9016 updates[i].width, updates[i].height,
9017 updates[i].x, updates[i].y);
9019 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9020 0, 0, squareSize, squareSize,
9021 anim->prevFrame.x, anim->prevFrame.y);
9026 FrameSequence(anim, piece, startColor, start, finish, frames, nFrames)
9028 ChessSquare piece; int startColor;
9029 XPoint * start; XPoint * finish;
9030 XPoint frames[]; int nFrames;
9034 BeginAnimation(anim, piece, startColor, start);
9035 for (n = 0; n < nFrames; n++) {
9036 AnimationFrame(anim, &(frames[n]), piece);
9037 FrameDelay(appData.animSpeed);
9039 EndAnimation(anim, finish);
9042 /* Main control logic for deciding what to animate and how */
9045 AnimateMove(board, fromX, fromY, toX, toY)
9054 XPoint start, finish, mid;
9055 XPoint frames[kFactor * 2 + 1];
9056 int nFrames, startColor, endColor;
9058 /* Are we animating? */
9059 if (!appData.animate || appData.blindfold)
9062 if (fromY < 0 || fromX < 0 || toX < 0 || toY < 0) return;
9063 piece = board[fromY][fromX];
9064 if (piece >= EmptySquare) return;
9069 hop = (piece == WhiteKnight || piece == BlackKnight);
9072 if (appData.debugMode) {
9073 fprintf(debugFP, hop ? _("AnimateMove: piece %d hops from %d,%d to %d,%d \n") :
9074 _("AnimateMove: piece %d slides from %d,%d to %d,%d \n"),
9075 piece, fromX, fromY, toX, toY); }
9077 ScreenSquare(fromX, fromY, &start, &startColor);
9078 ScreenSquare(toX, toY, &finish, &endColor);
9081 /* Knight: make diagonal movement then straight */
9082 if (abs(toY - fromY) < abs(toX - fromX)) {
9083 mid.x = start.x + (finish.x - start.x) / 2;
9087 mid.y = start.y + (finish.y - start.y) / 2;
9090 mid.x = start.x + (finish.x - start.x) / 2;
9091 mid.y = start.y + (finish.y - start.y) / 2;
9094 /* Don't use as many frames for very short moves */
9095 if (abs(toY - fromY) + abs(toX - fromX) <= 2)
9096 Tween(&start, &mid, &finish, kFactor - 1, frames, &nFrames);
9098 Tween(&start, &mid, &finish, kFactor, frames, &nFrames);
9099 FrameSequence(&game, piece, startColor, &start, &finish, frames, nFrames);
9101 /* Be sure end square is redrawn */
9102 damage[toY][toX] = True;
9106 DragPieceBegin(x, y)
9109 int boardX, boardY, color;
9112 /* Are we animating? */
9113 if (!appData.animateDragging || appData.blindfold)
9116 /* Figure out which square we start in and the
9117 mouse position relative to top left corner. */
9118 BoardSquare(x, y, &boardX, &boardY);
9119 player.startBoardX = boardX;
9120 player.startBoardY = boardY;
9121 ScreenSquare(boardX, boardY, &corner, &color);
9122 player.startSquare = corner;
9123 player.startColor = color;
9125 /* Start from exactly where the piece is. This can be confusing
9126 if you start dragging far from the center of the square; most
9127 or all of the piece can be over a different square from the one
9128 the mouse pointer is in. */
9129 player.mouseDelta.x = x - corner.x;
9130 player.mouseDelta.y = y - corner.y;
9132 /* As soon as we start dragging, the piece will jump slightly to
9133 be centered over the mouse pointer. */
9134 player.mouseDelta.x = squareSize/2;
9135 player.mouseDelta.y = squareSize/2;
9137 /* Initialise animation */
9138 player.dragPiece = PieceForSquare(boardX, boardY);
9140 if (player.dragPiece >= 0 && player.dragPiece < EmptySquare) {
9141 player.dragActive = True;
9142 BeginAnimation(&player, player.dragPiece, color, &corner);
9143 /* Mark this square as needing to be redrawn. Note that
9144 we don't remove the piece though, since logically (ie
9145 as seen by opponent) the move hasn't been made yet. */
9146 damage[boardY][boardX] = True;
9148 player.dragActive = False;
9158 /* Are we animating? */
9159 if (!appData.animateDragging || appData.blindfold)
9163 if (! player.dragActive)
9165 /* Move piece, maintaining same relative position
9166 of mouse within square */
9167 corner.x = x - player.mouseDelta.x;
9168 corner.y = y - player.mouseDelta.y;
9169 AnimationFrame(&player, &corner, player.dragPiece);
9171 if (appData.highlightDragging) {
9173 BoardSquare(x, y, &boardX, &boardY);
9174 SetHighlights(fromX, fromY, boardX, boardY);
9183 int boardX, boardY, color;
9186 /* Are we animating? */
9187 if (!appData.animateDragging || appData.blindfold)
9191 if (! player.dragActive)
9193 /* Last frame in sequence is square piece is
9194 placed on, which may not match mouse exactly. */
9195 BoardSquare(x, y, &boardX, &boardY);
9196 ScreenSquare(boardX, boardY, &corner, &color);
9197 EndAnimation(&player, &corner);
9199 /* Be sure end square is redrawn */
9200 damage[boardY][boardX] = True;
9202 /* This prevents weird things happening with fast successive
9203 clicks which on my Sun at least can cause motion events
9204 without corresponding press/release. */
9205 player.dragActive = False;
9208 /* Handle expose event while piece being dragged */
9213 if (!player.dragActive || appData.blindfold)
9216 /* What we're doing: logically, the move hasn't been made yet,
9217 so the piece is still in it's original square. But visually
9218 it's being dragged around the board. So we erase the square
9219 that the piece is on and draw it at the last known drag point. */
9220 BlankSquare(player.startSquare.x, player.startSquare.y,
9221 player.startColor, EmptySquare, xBoardWindow);
9222 AnimationFrame(&player, &player.prevFrame, player.dragPiece);
9223 damage[player.startBoardY][player.startBoardX] = TRUE;
9227 SetProgramStats( FrontEndProgramStats * stats )
9230 // [HGM] done, but perhaps backend should call this directly?
9231 EngineOutputUpdate( stats );