2 * xboard.c -- X front end for XBoard
4 * Copyright 1991 by Digital Equipment Corporation, Maynard,
7 * Enhancements Copyright 1992-2001, 2002, 2003, 2004, 2005, 2006,
8 * 2007, 2008, 2009 Free Software Foundation, Inc.
10 * The following terms apply to Digital Equipment Corporation's copyright
12 * ------------------------------------------------------------------------
15 * Permission to use, copy, modify, and distribute this software and its
16 * documentation for any purpose and without fee is hereby granted,
17 * provided that the above copyright notice appear in all copies and that
18 * both that copyright notice and this permission notice appear in
19 * supporting documentation, and that the name of Digital not be
20 * used in advertising or publicity pertaining to distribution of the
21 * software without specific, written prior permission.
23 * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
24 * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
25 * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
26 * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
27 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
28 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
30 * ------------------------------------------------------------------------
32 * The following terms apply to the enhanced version of XBoard
33 * distributed by the Free Software Foundation:
34 * ------------------------------------------------------------------------
36 * GNU XBoard is free software: you can redistribute it and/or modify
37 * it under the terms of the GNU General Public License as published by
38 * the Free Software Foundation, either version 3 of the License, or (at
39 * your option) any later version.
41 * GNU XBoard is distributed in the hope that it will be useful, but
42 * WITHOUT ANY WARRANTY; without even the implied warranty of
43 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
44 * General Public License for more details.
46 * You should have received a copy of the GNU General Public License
47 * along with this program. If not, see http://www.gnu.org/licenses/. *
49 *------------------------------------------------------------------------
50 ** See the file ChangeLog for a revision history. */
58 #include <sys/types.h>
63 # if HAVE_SYS_SOCKET_H
64 # include <sys/socket.h>
65 # include <netinet/in.h>
67 # else /* not HAVE_SYS_SOCKET_H */
68 # if HAVE_LAN_SOCKET_H
69 # include <lan/socket.h>
71 # include <lan/netdb.h>
72 # else /* not HAVE_LAN_SOCKET_H */
73 # define OMIT_SOCKETS 1
74 # endif /* not HAVE_LAN_SOCKET_H */
75 # endif /* not HAVE_SYS_SOCKET_H */
76 #endif /* !OMIT_SOCKETS */
81 #else /* not STDC_HEADERS */
82 extern char *getenv();
85 # else /* not HAVE_STRING_H */
87 # endif /* not HAVE_STRING_H */
88 #endif /* not STDC_HEADERS */
91 # include <sys/fcntl.h>
92 #else /* not HAVE_SYS_FCNTL_H */
95 # endif /* HAVE_FCNTL_H */
96 #endif /* not HAVE_SYS_FCNTL_H */
98 #if HAVE_SYS_SYSTEMINFO_H
99 # include <sys/systeminfo.h>
100 #endif /* HAVE_SYS_SYSTEMINFO_H */
102 #if TIME_WITH_SYS_TIME
103 # include <sys/time.h>
107 # include <sys/time.h>
118 # include <sys/wait.h>
123 # define NAMLEN(dirent) strlen((dirent)->d_name)
124 # define HAVE_DIR_STRUCT
126 # define dirent direct
127 # define NAMLEN(dirent) (dirent)->d_namlen
129 # include <sys/ndir.h>
130 # define HAVE_DIR_STRUCT
133 # include <sys/dir.h>
134 # define HAVE_DIR_STRUCT
138 # define HAVE_DIR_STRUCT
142 #include <X11/Intrinsic.h>
143 #include <X11/StringDefs.h>
144 #include <X11/Shell.h>
145 #include <X11/cursorfont.h>
146 #include <X11/Xatom.h>
148 #include <X11/Xaw3d/Dialog.h>
149 #include <X11/Xaw3d/Form.h>
150 #include <X11/Xaw3d/List.h>
151 #include <X11/Xaw3d/Label.h>
152 #include <X11/Xaw3d/SimpleMenu.h>
153 #include <X11/Xaw3d/SmeBSB.h>
154 #include <X11/Xaw3d/SmeLine.h>
155 #include <X11/Xaw3d/Box.h>
156 #include <X11/Xaw3d/MenuButton.h>
157 #include <X11/Xaw3d/Text.h>
158 #include <X11/Xaw3d/AsciiText.h>
160 #include <X11/Xaw/Dialog.h>
161 #include <X11/Xaw/Form.h>
162 #include <X11/Xaw/List.h>
163 #include <X11/Xaw/Label.h>
164 #include <X11/Xaw/SimpleMenu.h>
165 #include <X11/Xaw/SmeBSB.h>
166 #include <X11/Xaw/SmeLine.h>
167 #include <X11/Xaw/Box.h>
168 #include <X11/Xaw/MenuButton.h>
169 #include <X11/Xaw/Text.h>
170 #include <X11/Xaw/AsciiText.h>
173 // [HGM] bitmaps: put before incuding the bitmaps / pixmaps, to know how many piece types there are.
178 #include "pixmaps/pixmaps.h"
179 #define IMAGE_EXT "xpm"
181 #define IMAGE_EXT "xim"
182 #include "bitmaps/bitmaps.h"
185 #include "bitmaps/icon_white.bm"
186 #include "bitmaps/icon_black.bm"
187 #include "bitmaps/checkmark.bm"
189 #include "frontend.h"
194 #include "xgamelist.h"
195 #include "xhistory.h"
196 #include "xedittags.h"
199 // must be moved to xengineoutput.h
201 void EngineOutputProc P((Widget w, XEvent *event,
202 String *prms, Cardinal *nprms));
204 void EngineOutputPopDown();
211 #define usleep(t) _sleep2(((t)+500)/1000)
215 # define _(s) gettext (s)
216 # define N_(s) gettext_noop (s)
232 int main P((int argc, char **argv));
233 RETSIGTYPE CmailSigHandler P((int sig));
234 RETSIGTYPE IntSigHandler P((int sig));
235 void CreateGCs P((void));
236 void CreateXIMPieces P((void));
237 void CreateXPMPieces P((void));
238 void CreatePieces P((void));
239 void CreatePieceMenus P((void));
240 Widget CreateMenuBar P((Menu *mb));
241 Widget CreateButtonBar P ((MenuItem *mi));
242 char *FindFont P((char *pattern, int targetPxlSize));
243 void PieceMenuPopup P((Widget w, XEvent *event,
244 String *params, Cardinal *num_params));
245 static void PieceMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
246 static void DropMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
247 void ReadBitmap P((Pixmap *pm, String name, unsigned char bits[],
248 u_int wreq, u_int hreq));
249 void CreateGrid P((void));
250 int EventToSquare P((int x, int limit));
251 void DrawSquare P((int row, int column, ChessSquare piece, int do_flash));
252 void EventProc P((Widget widget, caddr_t unused, XEvent *event));
253 void HandleUserMove P((Widget w, XEvent *event,
254 String *prms, Cardinal *nprms));
255 void AnimateUserMove P((Widget w, XEvent * event,
256 String * params, Cardinal * nParams));
257 void WhiteClock P((Widget w, XEvent *event,
258 String *prms, Cardinal *nprms));
259 void BlackClock P((Widget w, XEvent *event,
260 String *prms, Cardinal *nprms));
261 void DrawPositionProc P((Widget w, XEvent *event,
262 String *prms, Cardinal *nprms));
263 void XDrawPosition P((Widget w, /*Boolean*/int repaint,
265 void CommentPopUp P((char *title, char *label));
266 void CommentPopDown P((void));
267 void CommentCallback P((Widget w, XtPointer client_data,
268 XtPointer call_data));
269 void ICSInputBoxPopUp P((void));
270 void ICSInputBoxPopDown P((void));
271 void FileNamePopUp P((char *label, char *def,
272 FileProc proc, char *openMode));
273 void FileNamePopDown P((void));
274 void FileNameCallback P((Widget w, XtPointer client_data,
275 XtPointer call_data));
276 void FileNameAction P((Widget w, XEvent *event,
277 String *prms, Cardinal *nprms));
278 void AskQuestionReplyAction P((Widget w, XEvent *event,
279 String *prms, Cardinal *nprms));
280 void AskQuestionProc P((Widget w, XEvent *event,
281 String *prms, Cardinal *nprms));
282 void AskQuestionPopDown P((void));
283 void PromotionPopUp P((void));
284 void PromotionPopDown P((void));
285 void PromotionCallback P((Widget w, XtPointer client_data,
286 XtPointer call_data));
287 void EditCommentPopDown P((void));
288 void EditCommentCallback P((Widget w, XtPointer client_data,
289 XtPointer call_data));
290 void SelectCommand P((Widget w, XtPointer client_data, XtPointer call_data));
291 void ResetProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
292 void LoadGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
293 void LoadNextGameProc P((Widget w, XEvent *event, String *prms,
295 void LoadPrevGameProc P((Widget w, XEvent *event, String *prms,
297 void ReloadGameProc P((Widget w, XEvent *event, String *prms,
299 void LoadPositionProc P((Widget w, XEvent *event,
300 String *prms, Cardinal *nprms));
301 void LoadNextPositionProc P((Widget w, XEvent *event, String *prms,
303 void LoadPrevPositionProc P((Widget w, XEvent *event, String *prms,
305 void ReloadPositionProc P((Widget w, XEvent *event, String *prms,
307 void CopyPositionProc P((Widget w, XEvent *event, String *prms,
309 void PastePositionProc P((Widget w, XEvent *event, String *prms,
311 void CopyGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
312 void PasteGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
313 void SaveGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
314 void SavePositionProc P((Widget w, XEvent *event,
315 String *prms, Cardinal *nprms));
316 void MailMoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
317 void ReloadCmailMsgProc P((Widget w, XEvent *event, String *prms,
319 void QuitProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
320 void PauseProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
321 void MachineBlackProc P((Widget w, XEvent *event, String *prms,
323 void MachineWhiteProc P((Widget w, XEvent *event,
324 String *prms, Cardinal *nprms));
325 void AnalyzeModeProc P((Widget w, XEvent *event,
326 String *prms, Cardinal *nprms));
327 void AnalyzeFileProc P((Widget w, XEvent *event,
328 String *prms, Cardinal *nprms));
329 void TwoMachinesProc P((Widget w, XEvent *event, String *prms,
331 void IcsClientProc P((Widget w, XEvent *event, String *prms,
333 void EditGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
334 void EditPositionProc P((Widget w, XEvent *event,
335 String *prms, Cardinal *nprms));
336 void TrainingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
337 void EditCommentProc P((Widget w, XEvent *event,
338 String *prms, Cardinal *nprms));
339 void IcsInputBoxProc P((Widget w, XEvent *event,
340 String *prms, Cardinal *nprms));
341 void AcceptProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
342 void DeclineProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
343 void RematchProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
344 void CallFlagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
345 void DrawProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
346 void AbortProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
347 void AdjournProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
348 void ResignProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
349 void AdjuWhiteProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
350 void AdjuBlackProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
351 void AdjuDrawProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
352 void EnterKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
353 void StopObservingProc P((Widget w, XEvent *event, String *prms,
355 void StopExaminingProc P((Widget w, XEvent *event, String *prms,
357 void BackwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
358 void ForwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
359 void ToStartProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
360 void ToEndProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
361 void RevertProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
362 void TruncateGameProc P((Widget w, XEvent *event, String *prms,
364 void RetractMoveProc P((Widget w, XEvent *event, String *prms,
366 void MoveNowProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
367 void AlwaysQueenProc P((Widget w, XEvent *event, String *prms,
369 void AnimateDraggingProc P((Widget w, XEvent *event, String *prms,
371 void AnimateMovingProc P((Widget w, XEvent *event, String *prms,
373 void AutocommProc P((Widget w, XEvent *event, String *prms,
375 void AutoflagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
376 void AutoflipProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
377 void AutobsProc P((Widget w, XEvent *event, String *prms,
379 void AutoraiseProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
380 void AutosaveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
381 void BlindfoldProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
382 void FlashMovesProc P((Widget w, XEvent *event, String *prms,
384 void FlipViewProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
385 void GetMoveListProc P((Widget w, XEvent *event, String *prms,
387 void HighlightDraggingProc P((Widget w, XEvent *event, String *prms,
389 void HighlightLastMoveProc P((Widget w, XEvent *event, String *prms,
391 void MoveSoundProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
392 void IcsAlarmProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
393 void OldSaveStyleProc P((Widget w, XEvent *event, String *prms,
395 void PeriodicUpdatesProc P((Widget w, XEvent *event, String *prms,
397 void PonderNextMoveProc P((Widget w, XEvent *event, String *prms,
399 void PopupMoveErrorsProc P((Widget w, XEvent *event, String *prms,
401 void PopupExitMessageProc P((Widget w, XEvent *event, String *prms,
403 void PremoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
404 void QuietPlayProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
405 void ShowCoordsProc P((Widget w, XEvent *event, String *prms,
407 void ShowThinkingProc P((Widget w, XEvent *event, String *prms,
409 void HideThinkingProc P((Widget w, XEvent *event, String *prms,
411 void TestLegalityProc P((Widget w, XEvent *event, String *prms,
413 void InfoProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
414 void ManProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
415 void HintProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
416 void BookProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
417 void AboutGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
418 void AboutProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
419 void DebugProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
420 void NothingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
421 void Iconify P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
422 void DisplayMove P((int moveNumber));
423 void DisplayTitle P((char *title));
424 void ICSInitScript P((void));
425 int LoadGamePopUp P((FILE *f, int gameNumber, char *title));
426 void ErrorPopUp P((char *title, char *text, int modal));
427 void ErrorPopDown P((void));
428 static char *ExpandPathName P((char *path));
429 static void CreateAnimVars P((void));
430 static void DragPieceBegin P((int x, int y));
431 static void DragPieceMove P((int x, int y));
432 static void DragPieceEnd P((int x, int y));
433 static void DrawDragPiece P((void));
434 char *ModeToWidgetName P((GameMode mode));
435 void EngineOutputUpdate( FrontEndProgramStats * stats );
436 void ShuffleMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
437 void EngineMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
438 void UciMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
439 void TimeControlProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
440 void NewVariantProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
441 void FirstSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
442 void SecondSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
443 void ShufflePopDown P(());
444 void EnginePopDown P(());
445 void UciPopDown P(());
446 void TimeControlPopDown P(());
447 void NewVariantPopDown P(());
448 void SettingsPopDown P(());
450 * XBoard depends on Xt R4 or higher
452 int xtVersion = XtSpecificationRelease;
457 Pixel lightSquareColor, darkSquareColor, whitePieceColor, blackPieceColor,
458 jailSquareColor, highlightSquareColor, premoveHighlightColor;
459 Pixel lowTimeWarningColor;
460 GC lightSquareGC, darkSquareGC, jailSquareGC, lineGC, wdPieceGC, wlPieceGC,
461 bdPieceGC, blPieceGC, wbPieceGC, bwPieceGC, coordGC, highlineGC,
462 wjPieceGC, bjPieceGC, prelineGC, countGC;
463 Pixmap iconPixmap, wIconPixmap, bIconPixmap, xMarkPixmap;
464 Widget shellWidget, layoutWidget, formWidget, boardWidget, messageWidget,
465 whiteTimerWidget, blackTimerWidget, titleWidget, widgetList[16],
466 commentShell, promotionShell, whitePieceMenu, blackPieceMenu, dropMenu,
467 menuBarWidget, buttonBarWidget, editShell, errorShell, analysisShell,
468 ICSInputShell, fileNameShell, askQuestionShell;
469 XSegment gridSegments[(BOARD_SIZE + 1) * 2];
470 XSegment jailGridSegments[(BOARD_SIZE + 3) * 2];
471 Font clockFontID, coordFontID, countFontID;
472 XFontStruct *clockFontStruct, *coordFontStruct, *countFontStruct;
473 XtAppContext appContext;
475 char *oldICSInteractionTitle;
479 char installDir[] = "."; // [HGM] UCI: needed for UCI; probably needs run-time initializtion
481 Position commentX = -1, commentY = -1;
482 Dimension commentW, commentH;
484 int squareSize, smallLayout = 0, tinyLayout = 0,
485 marginW, marginH, // [HGM] for run-time resizing
486 fromX = -1, fromY = -1, toX, toY, commentUp = False, analysisUp = False,
487 ICSInputBoxUp = False, askQuestionUp = False,
488 filenameUp = False, promotionUp = False, pmFromX = -1, pmFromY = -1,
489 editUp = False, errorUp = False, errorExitStatus = -1, lineGap;
490 Pixel timerForegroundPixel, timerBackgroundPixel;
491 Pixel buttonForegroundPixel, buttonBackgroundPixel;
492 char *chessDir, *programName, *programVersion,
493 *gameCopyFilename, *gamePasteFilename;
497 Pixmap pieceBitmap[2][(int)BlackPawn];
498 Pixmap pieceBitmap2[2][(int)BlackPawn+4]; /* [HGM] pieces */
499 Pixmap xpmPieceBitmap[4][(int)BlackPawn]; /* LL, LD, DL, DD actually used*/
500 Pixmap xpmPieceBitmap2[4][(int)BlackPawn+4]; /* LL, LD, DL, DD set to select from */
501 Pixmap xpmLightSquare, xpmDarkSquare, xpmJailSquare;
502 int useImages, useImageSqs;
503 XImage *ximPieceBitmap[4][(int)BlackPawn+4]; /* LL, LD, DL, DD */
504 Pixmap ximMaskPm[(int)BlackPawn]; /* clipmasks, used for XIM pieces */
505 Pixmap ximMaskPm2[(int)BlackPawn+4]; /* clipmasks, used for XIM pieces */
506 XImage *ximLightSquare, *ximDarkSquare;
509 #define pieceToSolid(piece) &pieceBitmap[SOLID][(piece) % (int)BlackPawn]
510 #define pieceToOutline(piece) &pieceBitmap[OUTLINE][(piece) % (int)BlackPawn]
512 #define White(piece) ((int)(piece) < (int)BlackPawn)
514 /* Variables for doing smooth animation. This whole thing
515 would be much easier if the board was double-buffered,
516 but that would require a fairly major rewrite. */
521 GC blitGC, pieceGC, outlineGC;
522 XPoint startSquare, prevFrame, mouseDelta;
526 int startBoardX, startBoardY;
529 /* There can be two pieces being animated at once: a player
530 can begin dragging a piece before the remote opponent has moved. */
532 static AnimState game, player;
534 /* Bitmaps for use as masks when drawing XPM pieces.
535 Need one for each black and white piece. */
536 static Pixmap xpmMask[BlackKing + 1];
538 /* This magic number is the number of intermediate frames used
539 in each half of the animation. For short moves it's reduced
540 by 1. The total number of frames will be factor * 2 + 1. */
543 SizeDefaults sizeDefaults[] = SIZE_DEFAULTS;
545 MenuItem fileMenu[] = {
546 {N_("New Game"), ResetProc},
547 {N_("New Shuffle Game ..."), ShuffleMenuProc},
548 {N_("New Variant ..."), NewVariantProc}, // [HGM] variant: not functional yet
549 {"----", NothingProc},
550 {N_("Load Game"), LoadGameProc},
551 {N_("Load Next Game"), LoadNextGameProc},
552 {N_("Load Previous Game"), LoadPrevGameProc},
553 {N_("Reload Same Game"), ReloadGameProc},
554 {N_("Save Game"), SaveGameProc},
555 {"----", NothingProc},
556 {N_("Copy Game"), CopyGameProc},
557 {N_("Paste Game"), PasteGameProc},
558 {"----", NothingProc},
559 {N_("Load Position"), LoadPositionProc},
560 {N_("Load Next Position"), LoadNextPositionProc},
561 {N_("Load Previous Position"), LoadPrevPositionProc},
562 {N_("Reload Same Position"), ReloadPositionProc},
563 {N_("Save Position"), SavePositionProc},
564 {"----", NothingProc},
565 {N_("Copy Position"), CopyPositionProc},
566 {N_("Paste Position"), PastePositionProc},
567 {"----", NothingProc},
568 {N_("Mail Move"), MailMoveProc},
569 {N_("Reload CMail Message"), ReloadCmailMsgProc},
570 {"----", NothingProc},
571 {N_("Exit"), QuitProc},
575 MenuItem modeMenu[] = {
576 {N_("Machine White"), MachineWhiteProc},
577 {N_("Machine Black"), MachineBlackProc},
578 {N_("Two Machines"), TwoMachinesProc},
579 {N_("Analysis Mode"), AnalyzeModeProc},
580 {N_("Analyze File"), AnalyzeFileProc },
581 {N_("ICS Client"), IcsClientProc},
582 {N_("Edit Game"), EditGameProc},
583 {N_("Edit Position"), EditPositionProc},
584 {N_("Training"), TrainingProc},
585 {"----", NothingProc},
586 {N_("Show Engine Output"), EngineOutputProc},
587 {N_("Show Evaluation Graph"), NothingProc}, // [HGM] evalgr: not functional yet
588 {N_("Show Game List"), ShowGameListProc},
589 {"Show Move History", HistoryShowProc}, // [HGM] hist: activate 4.2.7 code
590 {"----", NothingProc},
591 {N_("Edit Tags"), EditTagsProc},
592 {N_("Edit Comment"), EditCommentProc},
593 {N_("ICS Input Box"), IcsInputBoxProc},
594 {N_("Pause"), PauseProc},
598 MenuItem actionMenu[] = {
599 {N_("Accept"), AcceptProc},
600 {N_("Decline"), DeclineProc},
601 {N_("Rematch"), RematchProc},
602 {"----", NothingProc},
603 {N_("Call Flag"), CallFlagProc},
604 {N_("Draw"), DrawProc},
605 {N_("Adjourn"), AdjournProc},
606 {N_("Abort"), AbortProc},
607 {N_("Resign"), ResignProc},
608 {"----", NothingProc},
609 {N_("Stop Observing"), StopObservingProc},
610 {N_("Stop Examining"), StopExaminingProc},
611 {"----", NothingProc},
612 {N_("Adjudicate to White"), AdjuWhiteProc},
613 {N_("Adjudicate to Black"), AdjuBlackProc},
614 {N_("Adjudicate Draw"), AdjuDrawProc},
618 MenuItem stepMenu[] = {
619 {N_("Backward"), BackwardProc},
620 {N_("Forward"), ForwardProc},
621 {N_("Back to Start"), ToStartProc},
622 {N_("Forward to End"), ToEndProc},
623 {N_("Revert"), RevertProc},
624 {N_("Truncate Game"), TruncateGameProc},
625 {"----", NothingProc},
626 {N_("Move Now"), MoveNowProc},
627 {N_("Retract Move"), RetractMoveProc},
631 MenuItem optionsMenu[] = {
632 {N_("Flip View"), FlipViewProc},
633 {"----", NothingProc},
634 {N_("Adjudications ..."), EngineMenuProc},
635 {N_("General Settings ..."), UciMenuProc},
636 {N_("Engine #1 Settings ..."), FirstSettingsProc},
637 {N_("Engine #2 Settings ..."), SecondSettingsProc},
638 {N_("Time Control ..."), TimeControlProc},
639 {"----", NothingProc},
640 {N_("Always Queen"), AlwaysQueenProc},
641 {N_("Animate Dragging"), AnimateDraggingProc},
642 {N_("Animate Moving"), AnimateMovingProc},
643 {N_("Auto Comment"), AutocommProc},
644 {N_("Auto Flag"), AutoflagProc},
645 {N_("Auto Flip View"), AutoflipProc},
646 {N_("Auto Observe"), AutobsProc},
647 {N_("Auto Raise Board"), AutoraiseProc},
648 {N_("Auto Save"), AutosaveProc},
649 {N_("Blindfold"), BlindfoldProc},
650 {N_("Flash Moves"), FlashMovesProc},
651 {N_("Get Move List"), GetMoveListProc},
653 {N_("Highlight Dragging"), HighlightDraggingProc},
655 {N_("Highlight Last Move"), HighlightLastMoveProc},
656 {N_("Move Sound"), MoveSoundProc},
657 {N_("ICS Alarm"), IcsAlarmProc},
658 {N_("Old Save Style"), OldSaveStyleProc},
659 {N_("Periodic Updates"), PeriodicUpdatesProc},
660 {N_("Ponder Next Move"), PonderNextMoveProc},
661 {N_("Popup Exit Message"), PopupExitMessageProc},
662 {N_("Popup Move Errors"), PopupMoveErrorsProc},
663 {N_("Premove"), PremoveProc},
664 {N_("Quiet Play"), QuietPlayProc},
665 {N_("Show Coords"), ShowCoordsProc},
666 {N_("Hide Thinking"), HideThinkingProc},
667 {N_("Test Legality"), TestLegalityProc},
671 MenuItem helpMenu[] = {
672 {N_("Info XBoard"), InfoProc},
673 {N_("Man XBoard"), ManProc},
674 {"----", NothingProc},
675 {N_("Hint"), HintProc},
676 {N_("Book"), BookProc},
677 {"----", NothingProc},
678 {N_("About XBoard"), AboutProc},
683 {N_("File"), fileMenu},
684 {N_("Mode"), modeMenu},
685 {N_("Action"), actionMenu},
686 {N_("Step"), stepMenu},
687 {N_("Options"), optionsMenu},
688 {N_("Help"), helpMenu},
692 #define PAUSE_BUTTON N_("P")
693 MenuItem buttonBar[] = {
696 {PAUSE_BUTTON, PauseProc},
702 #define PIECE_MENU_SIZE 18
703 String pieceMenuStrings[2][PIECE_MENU_SIZE] = {
704 { N_("White"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
705 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
706 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
707 N_("Empty square"), N_("Clear board") },
708 { N_("Black"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
709 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
710 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
711 N_("Empty square"), N_("Clear board") }
713 /* must be in same order as PieceMenuStrings! */
714 ChessSquare pieceMenuTranslation[2][PIECE_MENU_SIZE] = {
715 { WhitePlay, (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
716 WhiteRook, WhiteQueen, WhiteKing, (ChessSquare) 0, WhiteAlfil,
717 WhiteCannon, WhiteAngel, WhiteMarshall, (ChessSquare) 0,
718 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
719 { BlackPlay, (ChessSquare) 0, BlackPawn, BlackKnight, BlackBishop,
720 BlackRook, BlackQueen, BlackKing, (ChessSquare) 0, BlackAlfil,
721 BlackCannon, BlackAngel, BlackMarshall, (ChessSquare) 0,
722 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
725 #define DROP_MENU_SIZE 6
726 String dropMenuStrings[DROP_MENU_SIZE] = {
727 "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"), N_("Queen")
729 /* must be in same order as PieceMenuStrings! */
730 ChessSquare dropMenuTranslation[DROP_MENU_SIZE] = {
731 (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
732 WhiteRook, WhiteQueen
740 DropMenuEnables dmEnables[] = {
758 { XtNborderWidth, 0 },
759 { XtNdefaultDistance, 0 },
763 { XtNborderWidth, 0 },
764 { XtNresizable, (XtArgVal) True },
768 { XtNborderWidth, 0 },
774 { XtNjustify, (XtArgVal) XtJustifyRight },
775 { XtNlabel, (XtArgVal) "..." },
776 { XtNresizable, (XtArgVal) True },
777 { XtNresize, (XtArgVal) False }
780 Arg messageArgs[] = {
781 { XtNjustify, (XtArgVal) XtJustifyLeft },
782 { XtNlabel, (XtArgVal) "..." },
783 { XtNresizable, (XtArgVal) True },
784 { XtNresize, (XtArgVal) False }
788 { XtNborderWidth, 0 },
789 { XtNjustify, (XtArgVal) XtJustifyLeft }
792 XtResource clientResources[] = {
793 { "whitePieceColor", "whitePieceColor", XtRString, sizeof(String),
794 XtOffset(AppDataPtr, whitePieceColor), XtRString,
796 { "blackPieceColor", "blackPieceColor", XtRString, sizeof(String),
797 XtOffset(AppDataPtr, blackPieceColor), XtRString,
799 { "lightSquareColor", "lightSquareColor", XtRString,
800 sizeof(String), XtOffset(AppDataPtr, lightSquareColor),
801 XtRString, LIGHT_SQUARE_COLOR },
802 { "darkSquareColor", "darkSquareColor", XtRString, sizeof(String),
803 XtOffset(AppDataPtr, darkSquareColor), XtRString,
805 { "highlightSquareColor", "highlightSquareColor", XtRString,
806 sizeof(String), XtOffset(AppDataPtr, highlightSquareColor),
807 XtRString, HIGHLIGHT_SQUARE_COLOR },
808 { "premoveHighlightColor", "premoveHighlightColor", XtRString,
809 sizeof(String), XtOffset(AppDataPtr, premoveHighlightColor),
810 XtRString, PREMOVE_HIGHLIGHT_COLOR },
811 { "movesPerSession", "movesPerSession", XtRInt, sizeof(int),
812 XtOffset(AppDataPtr, movesPerSession), XtRImmediate,
813 (XtPointer) MOVES_PER_SESSION },
814 { "timeIncrement", "timeIncrement", XtRInt, sizeof(int),
815 XtOffset(AppDataPtr, timeIncrement), XtRImmediate,
816 (XtPointer) TIME_INCREMENT },
817 { "initString", "initString", XtRString, sizeof(String),
818 XtOffset(AppDataPtr, initString), XtRString, INIT_STRING },
819 { "secondInitString", "secondInitString", XtRString, sizeof(String),
820 XtOffset(AppDataPtr, secondInitString), XtRString, INIT_STRING },
821 { "firstComputerString", "firstComputerString", XtRString,
822 sizeof(String), XtOffset(AppDataPtr, firstComputerString), XtRString,
824 { "secondComputerString", "secondComputerString", XtRString,
825 sizeof(String), XtOffset(AppDataPtr, secondComputerString), XtRString,
827 { "firstChessProgram", "firstChessProgram", XtRString,
828 sizeof(String), XtOffset(AppDataPtr, firstChessProgram),
829 XtRString, FIRST_CHESS_PROGRAM },
830 { "secondChessProgram", "secondChessProgram", XtRString,
831 sizeof(String), XtOffset(AppDataPtr, secondChessProgram),
832 XtRString, SECOND_CHESS_PROGRAM },
833 { "firstPlaysBlack", "firstPlaysBlack", XtRBoolean,
834 sizeof(Boolean), XtOffset(AppDataPtr, firstPlaysBlack),
835 XtRImmediate, (XtPointer) False },
836 { "noChessProgram", "noChessProgram", XtRBoolean,
837 sizeof(Boolean), XtOffset(AppDataPtr, noChessProgram),
838 XtRImmediate, (XtPointer) False },
839 { "firstHost", "firstHost", XtRString, sizeof(String),
840 XtOffset(AppDataPtr, firstHost), XtRString, FIRST_HOST },
841 { "secondHost", "secondHost", XtRString, sizeof(String),
842 XtOffset(AppDataPtr, secondHost), XtRString, SECOND_HOST },
843 { "firstDirectory", "firstDirectory", XtRString, sizeof(String),
844 XtOffset(AppDataPtr, firstDirectory), XtRString, "." },
845 { "secondDirectory", "secondDirectory", XtRString, sizeof(String),
846 XtOffset(AppDataPtr, secondDirectory), XtRString, "." },
847 { "bitmapDirectory", "bitmapDirectory", XtRString,
848 sizeof(String), XtOffset(AppDataPtr, bitmapDirectory),
850 { "remoteShell", "remoteShell", XtRString, sizeof(String),
851 XtOffset(AppDataPtr, remoteShell), XtRString, REMOTE_SHELL },
852 { "remoteUser", "remoteUser", XtRString, sizeof(String),
853 XtOffset(AppDataPtr, remoteUser), XtRString, "" },
854 { "timeDelay", "timeDelay", XtRFloat, sizeof(float),
855 XtOffset(AppDataPtr, timeDelay), XtRString,
856 (XtPointer) TIME_DELAY_QUOTE },
857 { "timeControl", "timeControl", XtRString, sizeof(String),
858 XtOffset(AppDataPtr, timeControl), XtRString,
859 (XtPointer) TIME_CONTROL },
860 { "internetChessServerMode", "internetChessServerMode",
861 XtRBoolean, sizeof(Boolean),
862 XtOffset(AppDataPtr, icsActive), XtRImmediate,
864 { "internetChessServerHost", "internetChessServerHost",
865 XtRString, sizeof(String),
866 XtOffset(AppDataPtr, icsHost),
867 XtRString, (XtPointer) ICS_HOST },
868 { "internetChessServerPort", "internetChessServerPort",
869 XtRString, sizeof(String),
870 XtOffset(AppDataPtr, icsPort), XtRString,
871 (XtPointer) ICS_PORT },
872 { "internetChessServerCommPort", "internetChessServerCommPort",
873 XtRString, sizeof(String),
874 XtOffset(AppDataPtr, icsCommPort), XtRString,
876 { "internetChessServerLogonScript", "internetChessServerLogonScript",
877 XtRString, sizeof(String),
878 XtOffset(AppDataPtr, icsLogon), XtRString,
880 { "internetChessServerHelper", "internetChessServerHelper",
881 XtRString, sizeof(String),
882 XtOffset(AppDataPtr, icsHelper), XtRString, "" },
883 { "internetChessServerInputBox", "internetChessServerInputBox",
884 XtRBoolean, sizeof(Boolean),
885 XtOffset(AppDataPtr, icsInputBox), XtRImmediate,
887 { "icsAlarm", "icsAlarm",
888 XtRBoolean, sizeof(Boolean),
889 XtOffset(AppDataPtr, icsAlarm), XtRImmediate,
891 { "icsAlarmTime", "icsAlarmTime",
893 XtOffset(AppDataPtr, icsAlarmTime), XtRImmediate,
895 { "useTelnet", "useTelnet", XtRBoolean, sizeof(Boolean),
896 XtOffset(AppDataPtr, useTelnet), XtRImmediate,
898 { "telnetProgram", "telnetProgram", XtRString, sizeof(String),
899 XtOffset(AppDataPtr, telnetProgram), XtRString, TELNET_PROGRAM },
900 { "gateway", "gateway", XtRString, sizeof(String),
901 XtOffset(AppDataPtr, gateway), XtRString, "" },
902 { "loadGameFile", "loadGameFile", XtRString, sizeof(String),
903 XtOffset(AppDataPtr, loadGameFile), XtRString, "" },
904 { "loadGameIndex", "loadGameIndex",
906 XtOffset(AppDataPtr, loadGameIndex), XtRImmediate,
908 { "saveGameFile", "saveGameFile", XtRString, sizeof(String),
909 XtOffset(AppDataPtr, saveGameFile), XtRString, "" },
910 { "autoRaiseBoard", "autoRaiseBoard", XtRBoolean,
911 sizeof(Boolean), XtOffset(AppDataPtr, autoRaiseBoard),
912 XtRImmediate, (XtPointer) True },
913 { "autoSaveGames", "autoSaveGames", XtRBoolean,
914 sizeof(Boolean), XtOffset(AppDataPtr, autoSaveGames),
915 XtRImmediate, (XtPointer) False },
916 { "blindfold", "blindfold", XtRBoolean,
917 sizeof(Boolean), XtOffset(AppDataPtr, blindfold),
918 XtRImmediate, (XtPointer) False },
919 { "loadPositionFile", "loadPositionFile", XtRString,
920 sizeof(String), XtOffset(AppDataPtr, loadPositionFile),
922 { "loadPositionIndex", "loadPositionIndex",
924 XtOffset(AppDataPtr, loadPositionIndex), XtRImmediate,
926 { "savePositionFile", "savePositionFile", XtRString,
927 sizeof(String), XtOffset(AppDataPtr, savePositionFile),
929 { "matchMode", "matchMode", XtRBoolean, sizeof(Boolean),
930 XtOffset(AppDataPtr, matchMode), XtRImmediate, (XtPointer) False },
931 { "matchGames", "matchGames", XtRInt, sizeof(int),
932 XtOffset(AppDataPtr, matchGames), XtRImmediate,
934 { "monoMode", "monoMode", XtRBoolean, sizeof(Boolean),
935 XtOffset(AppDataPtr, monoMode), XtRImmediate,
937 { "debugMode", "debugMode", XtRBoolean, sizeof(Boolean),
938 XtOffset(AppDataPtr, debugMode), XtRImmediate,
940 { "clockMode", "clockMode", XtRBoolean, sizeof(Boolean),
941 XtOffset(AppDataPtr, clockMode), XtRImmediate,
943 { "boardSize", "boardSize", XtRString, sizeof(String),
944 XtOffset(AppDataPtr, boardSize), XtRString, "" },
945 { "searchTime", "searchTime", XtRString, sizeof(String),
946 XtOffset(AppDataPtr, searchTime), XtRString,
948 { "searchDepth", "searchDepth", XtRInt, sizeof(int),
949 XtOffset(AppDataPtr, searchDepth), XtRImmediate,
951 { "showCoords", "showCoords", XtRBoolean, sizeof(Boolean),
952 XtOffset(AppDataPtr, showCoords), XtRImmediate,
954 { "showJail", "showJail", XtRInt, sizeof(int),
955 XtOffset(AppDataPtr, showJail), XtRImmediate,
957 { "showThinking", "showThinking", XtRBoolean, sizeof(Boolean),
958 XtOffset(AppDataPtr, showThinking), XtRImmediate,
960 { "ponderNextMove", "ponderNextMove", XtRBoolean, sizeof(Boolean),
961 XtOffset(AppDataPtr, ponderNextMove), XtRImmediate,
963 { "periodicUpdates", "periodicUpdates", XtRBoolean, sizeof(Boolean),
964 XtOffset(AppDataPtr, periodicUpdates), XtRImmediate,
966 { "clockFont", "clockFont", XtRString, sizeof(String),
967 XtOffset(AppDataPtr, clockFont), XtRString, CLOCK_FONT },
968 { "coordFont", "coordFont", XtRString, sizeof(String),
969 XtOffset(AppDataPtr, coordFont), XtRString, COORD_FONT },
970 { "font", "font", XtRString, sizeof(String),
971 XtOffset(AppDataPtr, font), XtRString, DEFAULT_FONT },
972 { "ringBellAfterMoves", "ringBellAfterMoves",
973 XtRBoolean, sizeof(Boolean),
974 XtOffset(AppDataPtr, ringBellAfterMoves),
975 XtRImmediate, (XtPointer) False },
976 { "autoCallFlag", "autoCallFlag", XtRBoolean,
977 sizeof(Boolean), XtOffset(AppDataPtr, autoCallFlag),
978 XtRImmediate, (XtPointer) False },
979 { "autoFlipView", "autoFlipView", XtRBoolean,
980 sizeof(Boolean), XtOffset(AppDataPtr, autoFlipView),
981 XtRImmediate, (XtPointer) True },
982 { "autoObserve", "autoObserve", XtRBoolean,
983 sizeof(Boolean), XtOffset(AppDataPtr, autoObserve),
984 XtRImmediate, (XtPointer) False },
985 { "autoComment", "autoComment", XtRBoolean,
986 sizeof(Boolean), XtOffset(AppDataPtr, autoComment),
987 XtRImmediate, (XtPointer) False },
988 { "getMoveList", "getMoveList", XtRBoolean,
989 sizeof(Boolean), XtOffset(AppDataPtr, getMoveList),
990 XtRImmediate, (XtPointer) True },
992 { "highlightDragging", "highlightDragging", XtRBoolean,
993 sizeof(Boolean), XtOffset(AppDataPtr, highlightDragging),
994 XtRImmediate, (XtPointer) False },
996 { "highlightLastMove", "highlightLastMove", XtRBoolean,
997 sizeof(Boolean), XtOffset(AppDataPtr, highlightLastMove),
998 XtRImmediate, (XtPointer) False },
999 { "premove", "premove", XtRBoolean,
1000 sizeof(Boolean), XtOffset(AppDataPtr, premove),
1001 XtRImmediate, (XtPointer) True },
1002 { "testLegality", "testLegality", XtRBoolean,
1003 sizeof(Boolean), XtOffset(AppDataPtr, testLegality),
1004 XtRImmediate, (XtPointer) True },
1005 { "flipView", "flipView", XtRBoolean,
1006 sizeof(Boolean), XtOffset(AppDataPtr, flipView),
1007 XtRImmediate, (XtPointer) False },
1008 { "cmail", "cmailGameName", XtRString, sizeof(String),
1009 XtOffset(AppDataPtr, cmailGameName), XtRString, "" },
1010 { "alwaysPromoteToQueen", "alwaysPromoteToQueen", XtRBoolean,
1011 sizeof(Boolean), XtOffset(AppDataPtr, alwaysPromoteToQueen),
1012 XtRImmediate, (XtPointer) False },
1013 { "oldSaveStyle", "oldSaveStyle", XtRBoolean,
1014 sizeof(Boolean), XtOffset(AppDataPtr, oldSaveStyle),
1015 XtRImmediate, (XtPointer) False },
1016 { "quietPlay", "quietPlay", XtRBoolean,
1017 sizeof(Boolean), XtOffset(AppDataPtr, quietPlay),
1018 XtRImmediate, (XtPointer) False },
1019 { "titleInWindow", "titleInWindow", XtRBoolean,
1020 sizeof(Boolean), XtOffset(AppDataPtr, titleInWindow),
1021 XtRImmediate, (XtPointer) False },
1022 { "localLineEditing", "localLineEditing", XtRBoolean,
1023 sizeof(Boolean), XtOffset(AppDataPtr, localLineEditing),
1024 XtRImmediate, (XtPointer) True }, /* not implemented, must be True */
1026 { "zippyTalk", "zippyTalk", XtRBoolean,
1027 sizeof(Boolean), XtOffset(AppDataPtr, zippyTalk),
1028 XtRImmediate, (XtPointer) ZIPPY_TALK },
1029 { "zippyPlay", "zippyPlay", XtRBoolean,
1030 sizeof(Boolean), XtOffset(AppDataPtr, zippyPlay),
1031 XtRImmediate, (XtPointer) ZIPPY_PLAY },
1032 { "zippyLines", "zippyLines", XtRString, sizeof(String),
1033 XtOffset(AppDataPtr, zippyLines), XtRString, ZIPPY_LINES },
1034 { "zippyPinhead", "zippyPinhead", XtRString, sizeof(String),
1035 XtOffset(AppDataPtr, zippyPinhead), XtRString, ZIPPY_PINHEAD },
1036 { "zippyPassword", "zippyPassword", XtRString, sizeof(String),
1037 XtOffset(AppDataPtr, zippyPassword), XtRString, ZIPPY_PASSWORD },
1038 { "zippyPassword2", "zippyPassword2", XtRString, sizeof(String),
1039 XtOffset(AppDataPtr, zippyPassword2), XtRString, ZIPPY_PASSWORD2 },
1040 { "zippyWrongPassword", "zippyWrongPassword", XtRString, sizeof(String),
1041 XtOffset(AppDataPtr, zippyWrongPassword), XtRString,
1042 ZIPPY_WRONG_PASSWORD },
1043 { "zippyAcceptOnly", "zippyAcceptOnly", XtRString, sizeof(String),
1044 XtOffset(AppDataPtr, zippyAcceptOnly), XtRString, ZIPPY_ACCEPT_ONLY },
1045 { "zippyUseI", "zippyUseI", XtRBoolean,
1046 sizeof(Boolean), XtOffset(AppDataPtr, zippyUseI),
1047 XtRImmediate, (XtPointer) ZIPPY_USE_I },
1048 { "zippyBughouse", "zippyBughouse", XtRInt,
1049 sizeof(int), XtOffset(AppDataPtr, zippyBughouse),
1050 XtRImmediate, (XtPointer) ZIPPY_BUGHOUSE },
1051 { "zippyNoplayCrafty", "zippyNoplayCrafty", XtRBoolean,
1052 sizeof(Boolean), XtOffset(AppDataPtr, zippyNoplayCrafty),
1053 XtRImmediate, (XtPointer) ZIPPY_NOPLAY_CRAFTY },
1054 { "zippyGameEnd", "zippyGameEnd", XtRString, sizeof(String),
1055 XtOffset(AppDataPtr, zippyGameEnd), XtRString, ZIPPY_GAME_END },
1056 { "zippyGameStart", "zippyGameStart", XtRString, sizeof(String),
1057 XtOffset(AppDataPtr, zippyGameStart), XtRString, ZIPPY_GAME_START },
1058 { "zippyAdjourn", "zippyAdjourn", XtRBoolean,
1059 sizeof(Boolean), XtOffset(AppDataPtr, zippyAdjourn),
1060 XtRImmediate, (XtPointer) ZIPPY_ADJOURN },
1061 { "zippyAbort", "zippyAbort", XtRBoolean,
1062 sizeof(Boolean), XtOffset(AppDataPtr, zippyAbort),
1063 XtRImmediate, (XtPointer) ZIPPY_ABORT },
1064 { "zippyVariants", "zippyVariants", XtRString, sizeof(String),
1065 XtOffset(AppDataPtr, zippyVariants), XtRString, ZIPPY_VARIANTS },
1066 { "zippyMaxGames", "zippyMaxGames", XtRInt, sizeof(int),
1067 XtOffset(AppDataPtr, zippyMaxGames), XtRImmediate,
1068 (XtPointer) ZIPPY_MAX_GAMES },
1069 { "zippyReplayTimeout", "zippyReplayTimeout", XtRInt, sizeof(int),
1070 XtOffset(AppDataPtr, zippyReplayTimeout), XtRImmediate,
1071 (XtPointer) ZIPPY_REPLAY_TIMEOUT },
1072 { "zippyShortGame", "zippyShortGame", XtRInt, sizeof(int),
1073 XtOffset(AppDataPtr, zippyShortGame), XtRImmediate,
1076 { "flashCount", "flashCount", XtRInt, sizeof(int),
1077 XtOffset(AppDataPtr, flashCount), XtRImmediate,
1078 (XtPointer) FLASH_COUNT },
1079 { "flashRate", "flashRate", XtRInt, sizeof(int),
1080 XtOffset(AppDataPtr, flashRate), XtRImmediate,
1081 (XtPointer) FLASH_RATE },
1082 { "pixmapDirectory", "pixmapDirectory", XtRString,
1083 sizeof(String), XtOffset(AppDataPtr, pixmapDirectory),
1085 { "msLoginDelay", "msLoginDelay", XtRInt, sizeof(int),
1086 XtOffset(AppDataPtr, msLoginDelay), XtRImmediate,
1087 (XtPointer) MS_LOGIN_DELAY },
1088 { "colorizeMessages", "colorizeMessages", XtRBoolean,
1089 sizeof(Boolean), XtOffset(AppDataPtr, colorize),
1090 XtRImmediate, (XtPointer) False },
1091 { "colorShout", "colorShout", XtRString,
1092 sizeof(String), XtOffset(AppDataPtr, colorShout),
1093 XtRString, COLOR_SHOUT },
1094 { "colorSShout", "colorSShout", XtRString,
1095 sizeof(String), XtOffset(AppDataPtr, colorSShout),
1096 XtRString, COLOR_SSHOUT },
1097 { "colorChannel1", "colorChannel1", XtRString,
1098 sizeof(String), XtOffset(AppDataPtr, colorChannel1),
1099 XtRString, COLOR_CHANNEL1 },
1100 { "colorChannel", "colorChannel", XtRString,
1101 sizeof(String), XtOffset(AppDataPtr, colorChannel),
1102 XtRString, COLOR_CHANNEL },
1103 { "colorKibitz", "colorKibitz", XtRString,
1104 sizeof(String), XtOffset(AppDataPtr, colorKibitz),
1105 XtRString, COLOR_KIBITZ },
1106 { "colorTell", "colorTell", XtRString,
1107 sizeof(String), XtOffset(AppDataPtr, colorTell),
1108 XtRString, COLOR_TELL },
1109 { "colorChallenge", "colorChallenge", XtRString,
1110 sizeof(String), XtOffset(AppDataPtr, colorChallenge),
1111 XtRString, COLOR_CHALLENGE },
1112 { "colorRequest", "colorRequest", XtRString,
1113 sizeof(String), XtOffset(AppDataPtr, colorRequest),
1114 XtRString, COLOR_REQUEST },
1115 { "colorSeek", "colorSeek", XtRString,
1116 sizeof(String), XtOffset(AppDataPtr, colorSeek),
1117 XtRString, COLOR_SEEK },
1118 { "colorNormal", "colorNormal", XtRString,
1119 sizeof(String), XtOffset(AppDataPtr, colorNormal),
1120 XtRString, COLOR_NORMAL },
1121 { "soundProgram", "soundProgram", XtRString,
1122 sizeof(String), XtOffset(AppDataPtr, soundProgram),
1123 XtRString, "play" },
1124 { "soundShout", "soundShout", XtRString,
1125 sizeof(String), XtOffset(AppDataPtr, soundShout),
1127 { "soundSShout", "soundSShout", XtRString,
1128 sizeof(String), XtOffset(AppDataPtr, soundSShout),
1130 { "soundChannel1", "soundChannel1", XtRString,
1131 sizeof(String), XtOffset(AppDataPtr, soundChannel1),
1133 { "soundChannel", "soundChannel", XtRString,
1134 sizeof(String), XtOffset(AppDataPtr, soundChannel),
1136 { "soundKibitz", "soundKibitz", XtRString,
1137 sizeof(String), XtOffset(AppDataPtr, soundKibitz),
1139 { "soundTell", "soundTell", XtRString,
1140 sizeof(String), XtOffset(AppDataPtr, soundTell),
1142 { "soundChallenge", "soundChallenge", XtRString,
1143 sizeof(String), XtOffset(AppDataPtr, soundChallenge),
1145 { "soundRequest", "soundRequest", XtRString,
1146 sizeof(String), XtOffset(AppDataPtr, soundRequest),
1148 { "soundSeek", "soundSeek", XtRString,
1149 sizeof(String), XtOffset(AppDataPtr, soundSeek),
1151 { "soundMove", "soundMove", XtRString,
1152 sizeof(String), XtOffset(AppDataPtr, soundMove),
1154 { "soundIcsWin", "soundIcsWin", XtRString,
1155 sizeof(String), XtOffset(AppDataPtr, soundIcsWin),
1157 { "soundIcsLoss", "soundIcsLoss", XtRString,
1158 sizeof(String), XtOffset(AppDataPtr, soundIcsLoss),
1160 { "soundIcsDraw", "soundIcsDraw", XtRString,
1161 sizeof(String), XtOffset(AppDataPtr, soundIcsDraw),
1163 { "soundIcsUnfinished", "soundIcsUnfinished", XtRString,
1164 sizeof(String), XtOffset(AppDataPtr, soundIcsUnfinished),
1166 { "soundIcsAlarm", "soundIcsAlarm", XtRString,
1167 sizeof(String), XtOffset(AppDataPtr, soundIcsAlarm),
1169 { "reuseFirst", "reuseFirst", XtRBoolean,
1170 sizeof(Boolean), XtOffset(AppDataPtr, reuseFirst),
1171 XtRImmediate, (XtPointer) True },
1172 { "reuseSecond", "reuseSecond", XtRBoolean,
1173 sizeof(Boolean), XtOffset(AppDataPtr, reuseSecond),
1174 XtRImmediate, (XtPointer) True },
1175 { "animateDragging", "animateDragging", XtRBoolean,
1176 sizeof(Boolean), XtOffset(AppDataPtr, animateDragging),
1177 XtRImmediate, (XtPointer) True },
1178 { "animateMoving", "animateMoving", XtRBoolean,
1179 sizeof(Boolean), XtOffset(AppDataPtr, animate),
1180 XtRImmediate, (XtPointer) True },
1181 { "animateSpeed", "animateSpeed", XtRInt,
1182 sizeof(int), XtOffset(AppDataPtr, animSpeed),
1183 XtRImmediate, (XtPointer)10 },
1184 { "popupExitMessage", "popupExitMessage", XtRBoolean,
1185 sizeof(Boolean), XtOffset(AppDataPtr, popupExitMessage),
1186 XtRImmediate, (XtPointer) True },
1187 { "popupMoveErrors", "popupMoveErrors", XtRBoolean,
1188 sizeof(Boolean), XtOffset(AppDataPtr, popupMoveErrors),
1189 XtRImmediate, (XtPointer) False },
1190 { "fontSizeTolerance", "fontSizeTolerance", XtRInt,
1191 sizeof(int), XtOffset(AppDataPtr, fontSizeTolerance),
1192 XtRImmediate, (XtPointer)4 },
1193 { "initialMode", "initialMode", XtRString,
1194 sizeof(String), XtOffset(AppDataPtr, initialMode),
1195 XtRImmediate, (XtPointer) "" },
1196 { "variant", "variant", XtRString,
1197 sizeof(String), XtOffset(AppDataPtr, variant),
1198 XtRImmediate, (XtPointer) "normal" },
1199 { "firstProtocolVersion", "firstProtocolVersion", XtRInt,
1200 sizeof(int), XtOffset(AppDataPtr, firstProtocolVersion),
1201 XtRImmediate, (XtPointer)PROTOVER },
1202 { "secondProtocolVersion", "secondProtocolVersion", XtRInt,
1203 sizeof(int), XtOffset(AppDataPtr, secondProtocolVersion),
1204 XtRImmediate, (XtPointer)PROTOVER },
1205 { "showButtonBar", "showButtonBar", XtRBoolean,
1206 sizeof(Boolean), XtOffset(AppDataPtr, showButtonBar),
1207 XtRImmediate, (XtPointer) True },
1208 { "lowTimeWarningColor", "lowTimeWarningColor", XtRString,
1209 sizeof(String), XtOffset(AppDataPtr, lowTimeWarningColor),
1210 XtRString, COLOR_LOWTIMEWARNING },
1211 { "lowTimeWarning", "lowTimeWarning", XtRBoolean,
1212 sizeof(Boolean), XtOffset(AppDataPtr, lowTimeWarning),
1213 XtRImmediate, (XtPointer) False },
1214 {"icsEngineAnalyze", "icsEngineAnalyze", XtRBoolean, /* [DM] icsEngineAnalyze */
1215 sizeof(Boolean), XtOffset(AppDataPtr, icsEngineAnalyze),
1216 XtRImmediate, (XtPointer) False },
1217 { "firstScoreAbs", "firstScoreAbs", XtRBoolean,
1218 sizeof(Boolean), XtOffset(AppDataPtr, firstScoreIsAbsolute),
1219 XtRImmediate, (XtPointer) False },
1220 { "secondScoreAbs", "secondScoreAbs", XtRBoolean,
1221 sizeof(Boolean), XtOffset(AppDataPtr, secondScoreIsAbsolute),
1222 XtRImmediate, (XtPointer) False },
1223 { "pgnExtendedInfo", "pgnExtendedInfo", XtRBoolean,
1224 sizeof(Boolean), XtOffset(AppDataPtr, saveExtendedInfoInPGN),
1225 XtRImmediate, (XtPointer) False },
1226 { "hideThinkingFromHuman", "hideThinkingFromHuman", XtRBoolean,
1227 sizeof(Boolean), XtOffset(AppDataPtr, hideThinkingFromHuman),
1228 XtRImmediate, (XtPointer) True },
1229 { "adjudicateLossThreshold", "adjudicateLossThreshold", XtRInt,
1230 sizeof(int), XtOffset(AppDataPtr, adjudicateLossThreshold),
1231 XtRImmediate, (XtPointer) 0},
1232 { "adjudicateDrawMoves", "adjudicateDrawMoves", XtRInt,
1233 sizeof(int), XtOffset(AppDataPtr, adjudicateDrawMoves),
1234 XtRImmediate, (XtPointer) 0},
1235 { "pgnEventHeader", "pgnEventHeader", XtRString,
1236 sizeof(String), XtOffset(AppDataPtr, pgnEventHeader),
1237 XtRImmediate, (XtPointer) "Computer Chess Game" },
1238 { "defaultFrcPosition", "defaultFrcPositon", XtRInt,
1239 sizeof(int), XtOffset(AppDataPtr, defaultFrcPosition),
1240 XtRImmediate, (XtPointer) -1},
1241 { "gameListTags", "gameListTags", XtRString,
1242 sizeof(String), XtOffset(AppDataPtr, gameListTags),
1243 XtRImmediate, (XtPointer) GLT_DEFAULT_TAGS },
1245 // [HGM] 4.3.xx options
1246 { "boardWidth", "boardWidth", XtRInt,
1247 sizeof(int), XtOffset(AppDataPtr, NrFiles),
1248 XtRImmediate, (XtPointer) -1},
1249 { "boardHeight", "boardHeight", XtRInt,
1250 sizeof(int), XtOffset(AppDataPtr, NrRanks),
1251 XtRImmediate, (XtPointer) -1},
1252 { "matchPause", "matchPause", XtRInt,
1253 sizeof(int), XtOffset(AppDataPtr, matchPause),
1254 XtRImmediate, (XtPointer) 10000},
1255 { "holdingsSize", "holdingsSize", XtRInt,
1256 sizeof(int), XtOffset(AppDataPtr, holdingsSize),
1257 XtRImmediate, (XtPointer) -1},
1258 { "flipBlack", "flipBlack", XtRBoolean,
1259 sizeof(Boolean), XtOffset(AppDataPtr, upsideDown),
1260 XtRImmediate, (XtPointer) False},
1261 { "allWhite", "allWhite", XtRBoolean,
1262 sizeof(Boolean), XtOffset(AppDataPtr, allWhite),
1263 XtRImmediate, (XtPointer) False},
1264 { "pieceToCharTable", "pieceToCharTable", XtRString,
1265 sizeof(String), XtOffset(AppDataPtr, pieceToCharTable),
1266 XtRImmediate, (XtPointer) 0},
1267 { "alphaRank", "alphaRank", XtRBoolean,
1268 sizeof(Boolean), XtOffset(AppDataPtr, alphaRank),
1269 XtRImmediate, (XtPointer) False},
1270 { "testClaims", "testClaims", XtRBoolean,
1271 sizeof(Boolean), XtOffset(AppDataPtr, testClaims),
1272 XtRImmediate, (XtPointer) True},
1273 { "checkMates", "checkMates", XtRBoolean,
1274 sizeof(Boolean), XtOffset(AppDataPtr, checkMates),
1275 XtRImmediate, (XtPointer) True},
1276 { "materialDraws", "materialDraws", XtRBoolean,
1277 sizeof(Boolean), XtOffset(AppDataPtr, materialDraws),
1278 XtRImmediate, (XtPointer) True},
1279 { "trivialDraws", "trivialDraws", XtRBoolean,
1280 sizeof(Boolean), XtOffset(AppDataPtr, trivialDraws),
1281 XtRImmediate, (XtPointer) False},
1282 { "ruleMoves", "ruleMoves", XtRInt,
1283 sizeof(int), XtOffset(AppDataPtr, ruleMoves),
1284 XtRImmediate, (XtPointer) 51},
1285 { "repeatsToDraw", "repeatsToDraw", XtRInt,
1286 sizeof(int), XtOffset(AppDataPtr, drawRepeats),
1287 XtRImmediate, (XtPointer) 6},
1288 { "engineDebugOutput", "engineDebugOutput", XtRInt,
1289 sizeof(int), XtOffset(AppDataPtr, engineComments),
1290 XtRImmediate, (XtPointer) 1},
1291 { "userName", "userName", XtRString,
1292 sizeof(int), XtOffset(AppDataPtr, userName),
1293 XtRImmediate, (XtPointer) 0},
1294 { "autoKibitz", "autoKibitz", XtRBoolean,
1295 sizeof(Boolean), XtOffset(AppDataPtr, autoKibitz),
1296 XtRImmediate, (XtPointer) False},
1297 { "firstTimeOdds", "firstTimeOdds", XtRInt,
1298 sizeof(int), XtOffset(AppDataPtr, firstTimeOdds),
1299 XtRImmediate, (XtPointer) 1},
1300 { "secondTimeOdds", "secondTimeOdds", XtRInt,
1301 sizeof(int), XtOffset(AppDataPtr, secondTimeOdds),
1302 XtRImmediate, (XtPointer) 1},
1303 { "timeOddsMode", "timeOddsMode", XtRInt,
1304 sizeof(int), XtOffset(AppDataPtr, timeOddsMode),
1305 XtRImmediate, (XtPointer) 0},
1306 { "firstAccumulateTC", "firstAccumulateTC", XtRInt,
1307 sizeof(int), XtOffset(AppDataPtr, firstAccumulateTC),
1308 XtRImmediate, (XtPointer) 1},
1309 { "secondAccumulateTC", "secondAccumulateTC", XtRInt,
1310 sizeof(int), XtOffset(AppDataPtr, secondAccumulateTC),
1311 XtRImmediate, (XtPointer) 1},
1312 { "firstNPS", "firstNPS", XtRInt,
1313 sizeof(int), XtOffset(AppDataPtr, firstNPS),
1314 XtRImmediate, (XtPointer) -1},
1315 { "secondNPS", "secondNPS", XtRInt,
1316 sizeof(int), XtOffset(AppDataPtr, secondNPS),
1317 XtRImmediate, (XtPointer) -1},
1318 { "serverMoves", "serverMoves", XtRString,
1319 sizeof(String), XtOffset(AppDataPtr, serverMovesName),
1320 XtRImmediate, (XtPointer) 0},
1321 { "serverPause", "serverPause", XtRInt,
1322 sizeof(int), XtOffset(AppDataPtr, serverPause),
1323 XtRImmediate, (XtPointer) 0},
1324 { "suppressLoadMoves", "suppressLoadMoves", XtRBoolean,
1325 sizeof(Boolean), XtOffset(AppDataPtr, suppressLoadMoves),
1326 XtRImmediate, (XtPointer) False},
1327 { "userName", "userName", XtRString,
1328 sizeof(String), XtOffset(AppDataPtr, userName),
1329 XtRImmediate, (XtPointer) 0},
1330 { "egtFormats", "egtFormats", XtRString,
1331 sizeof(String), XtOffset(AppDataPtr, egtFormats),
1332 XtRImmediate, (XtPointer) 0},
1333 { "rewindIndex", "rewindIndex", XtRInt,
1334 sizeof(int), XtOffset(AppDataPtr, rewindIndex),
1335 XtRImmediate, (XtPointer) 0},
1336 { "sameColorGames", "sameColorGames", XtRInt,
1337 sizeof(int), XtOffset(AppDataPtr, sameColorGames),
1338 XtRImmediate, (XtPointer) 0},
1339 { "smpCores", "smpCores", XtRInt,
1340 sizeof(int), XtOffset(AppDataPtr, smpCores),
1341 XtRImmediate, (XtPointer) 1},
1342 { "niceEngines", "niceEngines", XtRInt,
1343 sizeof(int), XtOffset(AppDataPtr, niceEngines),
1344 XtRImmediate, (XtPointer) 0},
1345 { "nameOfDebugFile", "nameOfDebugFile", XtRString,
1346 sizeof(String), XtOffset(AppDataPtr, nameOfDebugFile),
1347 XtRImmediate, (XtPointer) "xboard.debug"},
1348 { "engineDebugOutput", "engineDebugOutput", XtRInt,
1349 sizeof(int), XtOffset(AppDataPtr, engineComments),
1350 XtRImmediate, (XtPointer) 1},
1351 { "noGUI", "noGUI", XtRBoolean,
1352 sizeof(Boolean), XtOffset(AppDataPtr, noGUI),
1353 XtRImmediate, (XtPointer) 0},
1354 { "firstOptions", "firstOptions", XtRString,
1355 sizeof(String), XtOffset(AppDataPtr, firstOptions),
1356 XtRImmediate, (XtPointer) "" },
1357 { "secondOptions", "secondOptions", XtRString,
1358 sizeof(String), XtOffset(AppDataPtr, secondOptions),
1359 XtRImmediate, (XtPointer) "" },
1360 { "firstNeedsNoncompliantFEN", "firstNeedsNoncompliantFEN", XtRString,
1361 sizeof(String), XtOffset(AppDataPtr, fenOverride1),
1362 XtRImmediate, (XtPointer) 0 },
1363 { "secondNeedsNoncompliantFEN", "secondNeedsNoncompliantFEN", XtRString,
1364 sizeof(String), XtOffset(AppDataPtr, fenOverride2),
1365 XtRImmediate, (XtPointer) 0 },
1367 // [HGM] Winboard_x UCI options
1368 { "firstIsUCI", "firstIsUCI", XtRBoolean,
1369 sizeof(Boolean), XtOffset(AppDataPtr, firstIsUCI),
1370 XtRImmediate, (XtPointer) False},
1371 { "secondIsUCI", "secondIsUCI", XtRBoolean,
1372 sizeof(Boolean), XtOffset(AppDataPtr, secondIsUCI),
1373 XtRImmediate, (XtPointer) False},
1374 { "firstHasOwnBookUCI", "firstHasOwnBookUCI", XtRBoolean,
1375 sizeof(Boolean), XtOffset(AppDataPtr, firstHasOwnBookUCI),
1376 XtRImmediate, (XtPointer) True},
1377 { "secondHasOwnBookUCI", "secondHasOwnBookUCI", XtRBoolean,
1378 sizeof(Boolean), XtOffset(AppDataPtr, secondHasOwnBookUCI),
1379 XtRImmediate, (XtPointer) True},
1380 { "usePolyglotBook", "usePolyglotBook", XtRBoolean,
1381 sizeof(Boolean), XtOffset(AppDataPtr, usePolyglotBook),
1382 XtRImmediate, (XtPointer) False},
1383 { "defaultHashSize", "defaultHashSize", XtRInt,
1384 sizeof(int), XtOffset(AppDataPtr, defaultHashSize),
1385 XtRImmediate, (XtPointer) 64},
1386 { "defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XtRInt,
1387 sizeof(int), XtOffset(AppDataPtr, defaultCacheSizeEGTB),
1388 XtRImmediate, (XtPointer) 4},
1389 { "polyglotDir", "polyglotDir", XtRString,
1390 sizeof(String), XtOffset(AppDataPtr, polyglotDir),
1391 XtRImmediate, (XtPointer) "." },
1392 { "polyglotBook", "polyglotBook", XtRString,
1393 sizeof(String), XtOffset(AppDataPtr, polyglotBook),
1394 XtRImmediate, (XtPointer) "" },
1395 { "defaultPathEGTB", "defaultPathEGTB", XtRString,
1396 sizeof(String), XtOffset(AppDataPtr, defaultPathEGTB),
1397 XtRImmediate, (XtPointer) "/usr/local/share/egtb"},
1398 { "delayBeforeQuit", "delayBeforeQuit", XtRInt,
1399 sizeof(int), XtOffset(AppDataPtr, delayBeforeQuit),
1400 XtRImmediate, (XtPointer) 0},
1401 { "delayAfterQuit", "delayAfterQuit", XtRInt,
1402 sizeof(int), XtOffset(AppDataPtr, delayAfterQuit),
1403 XtRImmediate, (XtPointer) 0},
1404 { "keepAlive", "keepAlive", XtRInt,
1405 sizeof(int), XtOffset(AppDataPtr, keepAlive),
1406 XtRImmediate, (XtPointer) 0},
1407 { "forceIllegalMoves", "forceIllegalMoves", XtRBoolean,
1408 sizeof(Boolean), XtOffset(AppDataPtr, forceIllegal),
1409 XtRImmediate, (XtPointer) False},
1412 XrmOptionDescRec shellOptions[] = {
1413 { "-whitePieceColor", "whitePieceColor", XrmoptionSepArg, NULL },
1414 { "-blackPieceColor", "blackPieceColor", XrmoptionSepArg, NULL },
1415 { "-lightSquareColor", "lightSquareColor", XrmoptionSepArg, NULL },
1416 { "-darkSquareColor", "darkSquareColor", XrmoptionSepArg, NULL },
1417 { "-highlightSquareColor", "highlightSquareColor", XrmoptionSepArg, NULL },
1418 { "-premoveHighlightColor", "premoveHighlightColor", XrmoptionSepArg,NULL},
1419 { "-movesPerSession", "movesPerSession", XrmoptionSepArg, NULL },
1420 { "-mps", "movesPerSession", XrmoptionSepArg, NULL },
1421 { "-timeIncrement", "timeIncrement", XrmoptionSepArg, NULL },
1422 { "-inc", "timeIncrement", XrmoptionSepArg, NULL },
1423 { "-initString", "initString", XrmoptionSepArg, NULL },
1424 { "-firstInitString", "initString", XrmoptionSepArg, NULL },
1425 { "-secondInitString", "secondInitString", XrmoptionSepArg, NULL },
1426 { "-firstComputerString", "firstComputerString", XrmoptionSepArg, NULL },
1427 { "-secondComputerString", "secondComputerString", XrmoptionSepArg, NULL },
1428 { "-firstChessProgram", "firstChessProgram", XrmoptionSepArg, NULL },
1429 { "-fcp", "firstChessProgram", XrmoptionSepArg, NULL },
1430 { "-secondChessProgram", "secondChessProgram", XrmoptionSepArg, NULL },
1431 { "-scp", "secondChessProgram", XrmoptionSepArg, NULL },
1432 { "-firstPlaysBlack", "firstPlaysBlack", XrmoptionSepArg, NULL },
1433 { "-fb", "firstPlaysBlack", XrmoptionNoArg, "True" },
1434 { "-xfb", "firstPlaysBlack", XrmoptionNoArg, "False" },
1435 { "-noChessProgram", "noChessProgram", XrmoptionSepArg, NULL },
1436 { "-ncp", "noChessProgram", XrmoptionNoArg, "True" },
1437 { "-xncp", "noChessProgram", XrmoptionNoArg, "False" },
1438 { "-firstHost", "firstHost", XrmoptionSepArg, NULL },
1439 { "-fh", "firstHost", XrmoptionSepArg, NULL },
1440 { "-secondHost", "secondHost", XrmoptionSepArg, NULL },
1441 { "-sh", "secondHost", XrmoptionSepArg, NULL },
1442 { "-firstDirectory", "firstDirectory", XrmoptionSepArg, NULL },
1443 { "-fd", "firstDirectory", XrmoptionSepArg, NULL },
1444 { "-secondDirectory", "secondDirectory", XrmoptionSepArg, NULL },
1445 { "-sd", "secondDirectory", XrmoptionSepArg, NULL },
1446 { "-bitmapDirectory", "bitmapDirectory", XrmoptionSepArg, NULL },
1447 { "-bm", "bitmapDirectory", XrmoptionSepArg, NULL },
1448 { "-remoteShell", "remoteShell", XrmoptionSepArg, NULL },
1449 { "-rsh", "remoteShell", XrmoptionSepArg, NULL },
1450 { "-remoteUser", "remoteUser", XrmoptionSepArg, NULL },
1451 { "-ruser", "remoteUser", XrmoptionSepArg, NULL },
1452 { "-timeDelay", "timeDelay", XrmoptionSepArg, NULL },
1453 { "-td", "timeDelay", XrmoptionSepArg, NULL },
1454 { "-timeControl", "timeControl", XrmoptionSepArg, NULL },
1455 { "-tc", "timeControl", XrmoptionSepArg, NULL },
1456 { "-internetChessServerMode", "internetChessServerMode",
1457 XrmoptionSepArg, NULL },
1458 { "-ics", "internetChessServerMode", XrmoptionNoArg, "True" },
1459 { "-xics", "internetChessServerMode", XrmoptionNoArg, "False" },
1460 { "-internetChessServerHost", "internetChessServerHost",
1461 XrmoptionSepArg, NULL },
1462 { "-icshost", "internetChessServerHost", XrmoptionSepArg, NULL },
1463 { "-internetChessServerPort", "internetChessServerPort",
1464 XrmoptionSepArg, NULL },
1465 { "-icsport", "internetChessServerPort", XrmoptionSepArg, NULL },
1466 { "-internetChessServerCommPort", "internetChessServerCommPort",
1467 XrmoptionSepArg, NULL },
1468 { "-icscomm", "internetChessServerCommPort", XrmoptionSepArg, NULL },
1469 { "-internetChessServerLogonScript", "internetChessServerLogonScript",
1470 XrmoptionSepArg, NULL },
1471 { "-icslogon", "internetChessServerLogonScript", XrmoptionSepArg, NULL },
1472 { "-internetChessServerHelper", "internetChessServerHelper",
1473 XrmoptionSepArg, NULL },
1474 { "-icshelper", "internetChessServerHelper", XrmoptionSepArg, NULL },
1475 { "-internetChessServerInputBox", "internetChessServerInputBox",
1476 XrmoptionSepArg, NULL },
1477 { "-icsinput", "internetChessServerInputBox", XrmoptionNoArg, "True" },
1478 { "-xicsinput", "internetChessServerInputBox", XrmoptionNoArg, "False" },
1479 { "-icsAlarm", "icsAlarm", XrmoptionSepArg, NULL },
1480 { "-alarm", "icsAlarm", XrmoptionNoArg, "True" },
1481 { "-xalarm", "icsAlarm", XrmoptionNoArg, "False" },
1482 { "-icsAlarmTime", "icsAlarmTime", XrmoptionSepArg, NULL },
1483 { "-useTelnet", "useTelnet", XrmoptionSepArg, NULL },
1484 { "-telnet", "useTelnet", XrmoptionNoArg, "True" },
1485 { "-xtelnet", "useTelnet", XrmoptionNoArg, "False" },
1486 { "-telnetProgram", "telnetProgram", XrmoptionSepArg, NULL },
1487 { "-gateway", "gateway", XrmoptionSepArg, NULL },
1488 { "-loadGameFile", "loadGameFile", XrmoptionSepArg, NULL },
1489 { "-lgf", "loadGameFile", XrmoptionSepArg, NULL },
1490 { "-loadGameIndex", "loadGameIndex", XrmoptionSepArg, NULL },
1491 { "-lgi", "loadGameIndex", XrmoptionSepArg, NULL },
1492 { "-saveGameFile", "saveGameFile", XrmoptionSepArg, NULL },
1493 { "-sgf", "saveGameFile", XrmoptionSepArg, NULL },
1494 { "-autoSaveGames", "autoSaveGames", XrmoptionSepArg, NULL },
1495 { "-autosave", "autoSaveGames", XrmoptionNoArg, "True" },
1496 { "-xautosave", "autoSaveGames", XrmoptionNoArg, "False" },
1497 { "-autoRaiseBoard", "autoRaiseBoard", XrmoptionSepArg, NULL },
1498 { "-autoraise", "autoRaiseBoard", XrmoptionNoArg, "True" },
1499 { "-xautoraise", "autoRaiseBoard", XrmoptionNoArg, "False" },
1500 { "-blindfold", "blindfold", XrmoptionSepArg, NULL },
1501 { "-blind", "blindfold", XrmoptionNoArg, "True" },
1502 { "-xblind", "blindfold", XrmoptionNoArg, "False" },
1503 { "-loadPositionFile", "loadPositionFile", XrmoptionSepArg, NULL },
1504 { "-lpf", "loadPositionFile", XrmoptionSepArg, NULL },
1505 { "-loadPositionIndex", "loadPositionIndex", XrmoptionSepArg, NULL },
1506 { "-lpi", "loadPositionIndex", XrmoptionSepArg, NULL },
1507 { "-savePositionFile", "savePositionFile", XrmoptionSepArg, NULL },
1508 { "-spf", "savePositionFile", XrmoptionSepArg, NULL },
1509 { "-matchMode", "matchMode", XrmoptionSepArg, NULL },
1510 { "-mm", "matchMode", XrmoptionNoArg, "True" },
1511 { "-xmm", "matchMode", XrmoptionNoArg, "False" },
1512 { "-matchGames", "matchGames", XrmoptionSepArg, NULL },
1513 { "-mg", "matchGames", XrmoptionSepArg, NULL },
1514 { "-monoMode", "monoMode", XrmoptionSepArg, NULL },
1515 { "-mono", "monoMode", XrmoptionNoArg, "True" },
1516 { "-xmono", "monoMode", XrmoptionNoArg, "False" },
1517 { "-debugMode", "debugMode", XrmoptionSepArg, NULL },
1518 { "-debug", "debugMode", XrmoptionNoArg, "True" },
1519 { "-xdebug", "debugMode", XrmoptionNoArg, "False" },
1520 { "-clockMode", "clockMode", XrmoptionSepArg, NULL },
1521 { "-clock", "clockMode", XrmoptionNoArg, "True" },
1522 { "-xclock", "clockMode", XrmoptionNoArg, "False" },
1523 { "-boardSize", "boardSize", XrmoptionSepArg, NULL },
1524 { "-size", "boardSize", XrmoptionSepArg, NULL },
1525 { "-searchTime", "searchTime", XrmoptionSepArg, NULL },
1526 { "-st", "searchTime", XrmoptionSepArg, NULL },
1527 { "-searchDepth", "searchDepth", XrmoptionSepArg, NULL },
1528 { "-depth", "searchDepth", XrmoptionSepArg, NULL },
1529 { "-showCoords", "showCoords", XrmoptionSepArg, NULL },
1530 { "-coords", "showCoords", XrmoptionNoArg, "True" },
1531 { "-xcoords", "showCoords", XrmoptionNoArg, "False" },
1533 { "-showJail", "showJail", XrmoptionSepArg, NULL },
1534 { "-jail", "showJail", XrmoptionNoArg, "1" },
1535 { "-sidejail", "showJail", XrmoptionNoArg, "2" },
1536 { "-xjail", "showJail", XrmoptionNoArg, "0" },
1538 { "-showThinking", "showThinking", XrmoptionSepArg, NULL },
1539 { "-thinking", "showThinking", XrmoptionNoArg, "True" },
1540 { "-xthinking", "showThinking", XrmoptionNoArg, "False" },
1541 { "-ponderNextMove", "ponderNextMove", XrmoptionSepArg, NULL },
1542 { "-ponder", "ponderNextMove", XrmoptionNoArg, "True" },
1543 { "-xponder", "ponderNextMove", XrmoptionNoArg, "False" },
1544 { "-periodicUpdates", "periodicUpdates", XrmoptionSepArg, NULL },
1545 { "-periodic", "periodicUpdates", XrmoptionNoArg, "True" },
1546 { "-xperiodic", "periodicUpdates", XrmoptionNoArg, "False" },
1547 { "-clockFont", "clockFont", XrmoptionSepArg, NULL },
1548 { "-coordFont", "coordFont", XrmoptionSepArg, NULL },
1549 { "-font", "font", XrmoptionSepArg, NULL },
1550 { "-ringBellAfterMoves", "ringBellAfterMoves", XrmoptionSepArg, NULL },
1551 { "-bell", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1552 { "-xbell", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1553 { "-movesound", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1554 { "-xmovesound", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1555 { "-autoCallFlag", "autoCallFlag", XrmoptionSepArg, NULL },
1556 { "-autoflag", "autoCallFlag", XrmoptionNoArg, "True" },
1557 { "-xautoflag", "autoCallFlag", XrmoptionNoArg, "False" },
1558 { "-autoFlipView", "autoFlipView", XrmoptionSepArg, NULL },
1559 { "-autoflip", "autoFlipView", XrmoptionNoArg, "True" },
1560 { "-xautoflip", "autoFlipView", XrmoptionNoArg, "False" },
1561 { "-autoObserve", "autoObserve", XrmoptionSepArg, NULL },
1562 { "-autobs", "autoObserve", XrmoptionNoArg, "True" },
1563 { "-xautobs", "autoObserve", XrmoptionNoArg, "False" },
1564 { "-autoComment", "autoComment", XrmoptionSepArg, NULL },
1565 { "-autocomm", "autoComment", XrmoptionNoArg, "True" },
1566 { "-xautocomm", "autoComment", XrmoptionNoArg, "False" },
1567 { "-getMoveList", "getMoveList", XrmoptionSepArg, NULL },
1568 { "-moves", "getMoveList", XrmoptionNoArg, "True" },
1569 { "-xmoves", "getMoveList", XrmoptionNoArg, "False" },
1571 { "-highlightDragging", "highlightDragging", XrmoptionSepArg, NULL },
1572 { "-highdrag", "highlightDragging", XrmoptionNoArg, "True" },
1573 { "-xhighdrag", "highlightDragging", XrmoptionNoArg, "False" },
1575 { "-highlightLastMove", "highlightLastMove", XrmoptionSepArg, NULL },
1576 { "-highlight", "highlightLastMove", XrmoptionNoArg, "True" },
1577 { "-xhighlight", "highlightLastMove", XrmoptionNoArg, "False" },
1578 { "-premove", "premove", XrmoptionSepArg, NULL },
1579 { "-pre", "premove", XrmoptionNoArg, "True" },
1580 { "-xpre", "premove", XrmoptionNoArg, "False" },
1581 { "-testLegality", "testLegality", XrmoptionSepArg, NULL },
1582 { "-legal", "testLegality", XrmoptionNoArg, "True" },
1583 { "-xlegal", "testLegality", XrmoptionNoArg, "False" },
1584 { "-flipView", "flipView", XrmoptionSepArg, NULL },
1585 { "-flip", "flipView", XrmoptionNoArg, "True" },
1586 { "-xflip", "flipView", XrmoptionNoArg, "False" },
1587 { "-cmail", "cmailGameName", XrmoptionSepArg, NULL },
1588 { "-alwaysPromoteToQueen", "alwaysPromoteToQueen",
1589 XrmoptionSepArg, NULL },
1590 { "-queen", "alwaysPromoteToQueen", XrmoptionNoArg, "True" },
1591 { "-xqueen", "alwaysPromoteToQueen", XrmoptionNoArg, "False" },
1592 { "-oldSaveStyle", "oldSaveStyle", XrmoptionSepArg, NULL },
1593 { "-oldsave", "oldSaveStyle", XrmoptionNoArg, "True" },
1594 { "-xoldsave", "oldSaveStyle", XrmoptionNoArg, "False" },
1595 { "-quietPlay", "quietPlay", XrmoptionSepArg, NULL },
1596 { "-quiet", "quietPlay", XrmoptionNoArg, "True" },
1597 { "-xquiet", "quietPlay", XrmoptionNoArg, "False" },
1598 { "-titleInWindow", "titleInWindow", XrmoptionSepArg, NULL },
1599 { "-title", "titleInWindow", XrmoptionNoArg, "True" },
1600 { "-xtitle", "titleInWindow", XrmoptionNoArg, "False" },
1602 { "-zippyTalk", "zippyTalk", XrmoptionSepArg, NULL },
1603 { "-zt", "zippyTalk", XrmoptionNoArg, "True" },
1604 { "-xzt", "zippyTalk", XrmoptionNoArg, "False" },
1605 { "-zippyPlay", "zippyPlay", XrmoptionSepArg, NULL },
1606 { "-zp", "zippyPlay", XrmoptionNoArg, "True" },
1607 { "-xzp", "zippyPlay", XrmoptionNoArg, "False" },
1608 { "-zippyLines", "zippyLines", XrmoptionSepArg, NULL },
1609 { "-zippyPinhead", "zippyPinhead", XrmoptionSepArg, NULL },
1610 { "-zippyPassword", "zippyPassword", XrmoptionSepArg, NULL },
1611 { "-zippyPassword2", "zippyPassword2", XrmoptionSepArg, NULL },
1612 { "-zippyWrongPassword", "zippyWrongPassword", XrmoptionSepArg, NULL },
1613 { "-zippyAcceptOnly", "zippyAcceptOnly", XrmoptionSepArg, NULL },
1614 { "-zippyUseI", "zippyUseI", XrmoptionSepArg, NULL },
1615 { "-zui", "zippyUseI", XrmoptionNoArg, "True" },
1616 { "-xzui", "zippyUseI", XrmoptionNoArg, "False" },
1617 { "-zippyBughouse", "zippyBughouse", XrmoptionSepArg, NULL },
1618 { "-zippyNoplayCrafty", "zippyNoplayCrafty", XrmoptionSepArg, NULL },
1619 { "-znc", "zippyNoplayCrafty", XrmoptionNoArg, "True" },
1620 { "-xznc", "zippyNoplayCrafty", XrmoptionNoArg, "False" },
1621 { "-zippyGameEnd", "zippyGameEnd", XrmoptionSepArg, NULL },
1622 { "-zippyGameStart", "zippyGameStart", XrmoptionSepArg, NULL },
1623 { "-zippyAdjourn", "zippyAdjourn", XrmoptionSepArg, NULL },
1624 { "-zadj", "zippyAdjourn", XrmoptionNoArg, "True" },
1625 { "-xzadj", "zippyAdjourn", XrmoptionNoArg, "False" },
1626 { "-zippyAbort", "zippyAbort", XrmoptionSepArg, NULL },
1627 { "-zab", "zippyAbort", XrmoptionNoArg, "True" },
1628 { "-xzab", "zippyAbort", XrmoptionNoArg, "False" },
1629 { "-zippyVariants", "zippyVariants", XrmoptionSepArg, NULL },
1630 { "-zippyMaxGames", "zippyMaxGames", XrmoptionSepArg, NULL },
1631 { "-zippyReplayTimeout", "zippyReplayTimeout", XrmoptionSepArg, NULL },
1632 { "-zippyShortGame", "zippyShortGame", XrmoptionSepArg, NULL },
1634 { "-flashCount", "flashCount", XrmoptionSepArg, NULL },
1635 { "-flash", "flashCount", XrmoptionNoArg, "3" },
1636 { "-xflash", "flashCount", XrmoptionNoArg, "0" },
1637 { "-flashRate", "flashRate", XrmoptionSepArg, NULL },
1638 { "-pixmapDirectory", "pixmapDirectory", XrmoptionSepArg, NULL },
1639 { "-msLoginDelay", "msLoginDelay", XrmoptionSepArg, NULL },
1640 { "-pixmap", "pixmapDirectory", XrmoptionSepArg, NULL },
1641 { "-colorizeMessages", "colorizeMessages", XrmoptionSepArg, NULL },
1642 { "-colorize", "colorizeMessages", XrmoptionNoArg, "True" },
1643 { "-xcolorize", "colorizeMessages", XrmoptionNoArg, "False" },
1644 { "-colorShout", "colorShout", XrmoptionSepArg, NULL },
1645 { "-colorSShout", "colorSShout", XrmoptionSepArg, NULL },
1646 { "-colorCShout", "colorSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1647 { "-colorChannel1", "colorChannel1", XrmoptionSepArg, NULL },
1648 { "-colorChannel", "colorChannel", XrmoptionSepArg, NULL },
1649 { "-colorKibitz", "colorKibitz", XrmoptionSepArg, NULL },
1650 { "-colorTell", "colorTell", XrmoptionSepArg, NULL },
1651 { "-colorChallenge", "colorChallenge", XrmoptionSepArg, NULL },
1652 { "-colorRequest", "colorRequest", XrmoptionSepArg, NULL },
1653 { "-colorSeek", "colorSeek", XrmoptionSepArg, NULL },
1654 { "-colorNormal", "colorNormal", XrmoptionSepArg, NULL },
1655 { "-soundProgram", "soundProgram", XrmoptionSepArg, NULL },
1656 { "-soundShout", "soundShout", XrmoptionSepArg, NULL },
1657 { "-soundSShout", "soundSShout", XrmoptionSepArg, NULL },
1658 { "-soundCShout", "soundSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1659 { "-soundChannel1", "soundChannel1", XrmoptionSepArg, NULL },
1660 { "-soundChannel", "soundChannel", XrmoptionSepArg, NULL },
1661 { "-soundKibitz", "soundKibitz", XrmoptionSepArg, NULL },
1662 { "-soundTell", "soundTell", XrmoptionSepArg, NULL },
1663 { "-soundChallenge", "soundChallenge", XrmoptionSepArg, NULL },
1664 { "-soundRequest", "soundRequest", XrmoptionSepArg, NULL },
1665 { "-soundSeek", "soundSeek", XrmoptionSepArg, NULL },
1666 { "-soundMove", "soundMove", XrmoptionSepArg, NULL },
1667 { "-soundIcsWin", "soundIcsWin", XrmoptionSepArg, NULL },
1668 { "-soundIcsLoss", "soundIcsLoss", XrmoptionSepArg, NULL },
1669 { "-soundIcsDraw", "soundIcsDraw", XrmoptionSepArg, NULL },
1670 { "-soundIcsUnfinished", "soundIcsUnfinished", XrmoptionSepArg, NULL },
1671 { "-soundIcsAlarm", "soundIcsAlarm", XrmoptionSepArg, NULL },
1672 { "-reuseFirst", "reuseFirst", XrmoptionSepArg, NULL },
1673 { "-reuseChessPrograms", "reuseFirst", XrmoptionSepArg, NULL }, /*compat*/
1674 { "-reuse", "reuseFirst", XrmoptionNoArg, "True" },
1675 { "-xreuse", "reuseFirst", XrmoptionNoArg, "False" },
1676 { "-reuseSecond", "reuseSecond", XrmoptionSepArg, NULL },
1677 { "-reuse2", "reuseSecond", XrmoptionNoArg, "True" },
1678 { "-xreuse2", "reuseSecond", XrmoptionNoArg, "False" },
1679 { "-animateMoving", "animateMoving", XrmoptionSepArg, NULL },
1680 { "-animate", "animateMoving", XrmoptionNoArg, "True" },
1681 { "-xanimate", "animateMoving", XrmoptionNoArg, "False" },
1682 { "-animateDragging", "animateDragging", XrmoptionSepArg, NULL },
1683 { "-drag", "animateDragging", XrmoptionNoArg, "True" },
1684 { "-xdrag", "animateDragging", XrmoptionNoArg, "False" },
1685 { "-animateSpeed", "animateSpeed", XrmoptionSepArg, NULL },
1686 { "-popupExitMessage", "popupExitMessage", XrmoptionSepArg, NULL },
1687 { "-exit", "popupExitMessage", XrmoptionNoArg, "True" },
1688 { "-xexit", "popupExitMessage", XrmoptionNoArg, "False" },
1689 { "-popupMoveErrors", "popupMoveErrors", XrmoptionSepArg, NULL },
1690 { "-popup", "popupMoveErrors", XrmoptionNoArg, "True" },
1691 { "-xpopup", "popupMoveErrors", XrmoptionNoArg, "False" },
1692 { "-fontSizeTolerance", "fontSizeTolerance", XrmoptionSepArg, NULL },
1693 { "-initialMode", "initialMode", XrmoptionSepArg, NULL },
1694 { "-mode", "initialMode", XrmoptionSepArg, NULL },
1695 { "-variant", "variant", XrmoptionSepArg, NULL },
1696 { "-firstProtocolVersion", "firstProtocolVersion", XrmoptionSepArg, NULL },
1697 { "-secondProtocolVersion","secondProtocolVersion",XrmoptionSepArg, NULL },
1698 { "-showButtonBar", "showButtonBar", XrmoptionSepArg, NULL },
1699 { "-buttons", "showButtonBar", XrmoptionNoArg, "True" },
1700 { "-xbuttons", "showButtonBar", XrmoptionNoArg, "False" },
1701 { "-lowTimeWarningColor", "lowTimeWarningColor", XrmoptionSepArg, NULL },
1702 { "-lowTimeWarning", "lowTimeWarning", XrmoptionSepArg, NULL },
1703 /* [AS,HR] New features */
1704 { "-firstScoreAbs", "firstScoreAbs", XrmoptionSepArg, NULL },
1705 { "-secondScoreAbs", "secondScoreAbs", XrmoptionSepArg, NULL },
1706 { "-pgnExtendedInfo", "pgnExtendedInfo", XrmoptionSepArg, NULL },
1707 { "-hideThinkingFromHuman", "hideThinkingFromHuman", XrmoptionSepArg, NULL },
1708 { "-adjudicateLossThreshold", "adjudicateLossThreshold", XrmoptionSepArg, NULL },
1709 { "-adjudicateDrawMoves", "adjudicateDrawMoves", XrmoptionSepArg, NULL },
1710 { "-pgnEventHeader", "pgnEventHeader", XrmoptionSepArg, NULL },
1711 { "-firstIsUCI", "firstIsUCI", XrmoptionSepArg, NULL },
1712 { "-secondIsUCI", "secondIsUCI", XrmoptionSepArg, NULL },
1713 { "-fUCI", "firstIsUCI", XrmoptionNoArg, "True" },
1714 { "-sUCI", "secondIsUCI", XrmoptionNoArg, "True" },
1715 { "-firstHasOwnBookUCI", "firstHasOwnBookUCI", XrmoptionSepArg, NULL },
1716 { "-secondHasOwnBookUCI", "secondHasOwnBookUCI", XrmoptionSepArg, NULL },
1717 { "-fNoOwnBookUCI", "firstHasOwnBookUCI", XrmoptionNoArg, "False" },
1718 { "-sNoOwnBookUCI", "secondHasOwnBookUCI", XrmoptionNoArg, "False" },
1719 { "-firstXBook", "firstHasOwnBookUCI", XrmoptionNoArg, "False" },
1720 { "-secondXBook", "secondHasOwnBookUCI", XrmoptionNoArg, "False" },
1721 { "-polyglotDir", "polyglotDir", XrmoptionSepArg, NULL },
1722 { "-usePolyglotBook", "usePolyglotBook", XrmoptionSepArg, NULL },
1723 { "-polyglotBook", "polyglotBook", XrmoptionSepArg, NULL },
1724 { "-defaultHashSize", "defaultHashSize", XrmoptionSepArg, NULL },
1725 { "-defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XrmoptionSepArg, NULL },
1726 { "-defaultPathEGTB", "defaultPathEGTB", XrmoptionSepArg, NULL },
1727 { "-defaultFrcPosition", "defaultFrcPosition", XrmoptionSepArg, NULL },
1728 { "-gameListTags", "gameListTags", XrmoptionSepArg, NULL },
1729 // [HGM] I am sure AS added many more options, but we have to fish them out, from the list in winboard.c
1731 /* [HGM,HR] User-selectable board size */
1732 { "-boardWidth", "boardWidth", XrmoptionSepArg, NULL },
1733 { "-boardHeight", "boardHeight", XrmoptionSepArg, NULL },
1734 { "-matchPause", "matchPause", XrmoptionSepArg, NULL },
1736 /* [HGM] new arguments of 4.3.xx. All except first three are back-end options, which should work immediately */
1737 { "-holdingsSize", "holdingsSize", XrmoptionSepArg, NULL }, // requires extensive front-end changes to work
1738 { "-flipBlack", "flipBlack", XrmoptionSepArg, NULL }, // requires front-end changes to work
1739 { "-allWhite", "allWhite", XrmoptionSepArg, NULL }, // requires front-end changes to work
1740 { "-pieceToCharTable", "pieceToCharTable", XrmoptionSepArg, NULL },
1741 { "-alphaRank", "alphaRank", XrmoptionSepArg, NULL },
1742 { "-testClaims", "testClaims", XrmoptionSepArg, NULL },
1743 { "-checkMates", "checkMates", XrmoptionSepArg, NULL },
1744 { "-materialDraws", "materialDraws", XrmoptionSepArg, NULL },
1745 { "-trivialDraws", "trivialDraws", XrmoptionSepArg, NULL },
1746 { "-ruleMoves", "ruleMoves", XrmoptionSepArg, NULL },
1747 { "-repeatsToDraw", "repeatsToDraw", XrmoptionSepArg, NULL },
1748 { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL },
1749 { "-userName", "userName", XrmoptionSepArg, NULL },
1750 { "-autoKibitz", "autoKibitz", XrmoptionNoArg, "True" },
1751 { "-firstTimeOdds", "firstTimeOdds", XrmoptionSepArg, NULL },
1752 { "-secondTimeOdds", "secondTimeOdds", XrmoptionSepArg, NULL },
1753 { "-timeOddsMode", "timeOddsMode", XrmoptionSepArg, NULL },
1754 { "-firstAccumulateTC", "firstAccumulateTC", XrmoptionSepArg, NULL },
1755 { "-secondAccumulateTC", "secondAccumulateTC", XrmoptionSepArg, NULL },
1756 { "-firstNPS", "firstNPS", XrmoptionSepArg, NULL },
1757 { "-secondNPS", "secondNPS", XrmoptionSepArg, NULL },
1758 { "-serverMoves", "serverMoves", XrmoptionSepArg, NULL },
1759 { "-serverPause", "serverPause", XrmoptionSepArg, NULL },
1760 { "-suppressLoadMoves", "suppressLoadMoves", XrmoptionSepArg, NULL },
1761 { "-egtFormats", "egtFormats", XrmoptionSepArg, NULL },
1762 { "-userName", "userName", XrmoptionSepArg, NULL },
1763 { "-smpCores", "smpCores", XrmoptionSepArg, NULL },
1764 { "-sameColorGames", "sameColorGames", XrmoptionSepArg, NULL },
1765 { "-rewindIndex", "rewindIndex", XrmoptionSepArg, NULL },
1766 { "-niceEngines", "niceEngines", XrmoptionSepArg, NULL },
1767 { "-delayBeforeQuit", "delayBeforeQuit", XrmoptionSepArg, NULL },
1768 { "-delayAfterQuit", "delayAfterQuit", XrmoptionSepArg, NULL },
1769 { "-nameOfDebugFile", "nameOfDebugFile", XrmoptionSepArg, NULL },
1770 { "-debugFile", "nameOfDebugFile", XrmoptionSepArg, NULL },
1771 { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL },
1772 { "-noGUI", "noGUI", XrmoptionNoArg, "True" },
1773 { "-firstOptions", "firstOptions", XrmoptionSepArg, NULL },
1774 { "-secondOptions", "secondOptions", XrmoptionSepArg, NULL },
1775 { "-firstNeedsNoncompliantFEN", "firstNeedsNoncompliantFEN", XrmoptionSepArg, NULL },
1776 { "-secondNeedsNoncompliantFEN", "secondNeedsNoncompliantFEN", XrmoptionSepArg, NULL },
1777 { "-keepAlive", "keepAlive", XrmoptionSepArg, NULL },
1778 { "-forceIllegalMoves", "forceIllegalMoves", XrmoptionNoArg, "True" },
1782 XtActionsRec boardActions[] = {
1783 { "DrawPosition", DrawPositionProc },
1784 { "HandleUserMove", HandleUserMove },
1785 { "AnimateUserMove", AnimateUserMove },
1786 { "FileNameAction", FileNameAction },
1787 { "AskQuestionProc", AskQuestionProc },
1788 { "AskQuestionReplyAction", AskQuestionReplyAction },
1789 { "PieceMenuPopup", PieceMenuPopup },
1790 { "WhiteClock", WhiteClock },
1791 { "BlackClock", BlackClock },
1792 { "Iconify", Iconify },
1793 { "ResetProc", ResetProc },
1794 { "LoadGameProc", LoadGameProc },
1795 { "LoadNextGameProc", LoadNextGameProc },
1796 { "LoadPrevGameProc", LoadPrevGameProc },
1797 { "LoadSelectedProc", LoadSelectedProc },
1798 { "ReloadGameProc", ReloadGameProc },
1799 { "LoadPositionProc", LoadPositionProc },
1800 { "LoadNextPositionProc", LoadNextPositionProc },
1801 { "LoadPrevPositionProc", LoadPrevPositionProc },
1802 { "ReloadPositionProc", ReloadPositionProc },
1803 { "CopyPositionProc", CopyPositionProc },
1804 { "PastePositionProc", PastePositionProc },
1805 { "CopyGameProc", CopyGameProc },
1806 { "PasteGameProc", PasteGameProc },
1807 { "SaveGameProc", SaveGameProc },
1808 { "SavePositionProc", SavePositionProc },
1809 { "MailMoveProc", MailMoveProc },
1810 { "ReloadCmailMsgProc", ReloadCmailMsgProc },
1811 { "QuitProc", QuitProc },
1812 { "MachineWhiteProc", MachineWhiteProc },
1813 { "MachineBlackProc", MachineBlackProc },
1814 { "AnalysisModeProc", AnalyzeModeProc },
1815 { "AnalyzeFileProc", AnalyzeFileProc },
1816 { "TwoMachinesProc", TwoMachinesProc },
1817 { "IcsClientProc", IcsClientProc },
1818 { "EditGameProc", EditGameProc },
1819 { "EditPositionProc", EditPositionProc },
1820 { "TrainingProc", EditPositionProc },
1821 { "EngineOutputProc", EngineOutputProc}, // [HGM] Winboard_x engine-output window
1822 { "ShowGameListProc", ShowGameListProc },
1823 { "ShowMoveListProc", HistoryShowProc},
1824 { "EditTagsProc", EditCommentProc },
1825 { "EditCommentProc", EditCommentProc },
1826 { "IcsAlarmProc", IcsAlarmProc },
1827 { "IcsInputBoxProc", IcsInputBoxProc },
1828 { "PauseProc", PauseProc },
1829 { "AcceptProc", AcceptProc },
1830 { "DeclineProc", DeclineProc },
1831 { "RematchProc", RematchProc },
1832 { "CallFlagProc", CallFlagProc },
1833 { "DrawProc", DrawProc },
1834 { "AdjournProc", AdjournProc },
1835 { "AbortProc", AbortProc },
1836 { "ResignProc", ResignProc },
1837 { "AdjuWhiteProc", AdjuWhiteProc },
1838 { "AdjuBlackProc", AdjuBlackProc },
1839 { "AdjuDrawProc", AdjuDrawProc },
1840 { "EnterKeyProc", EnterKeyProc },
1841 { "StopObservingProc", StopObservingProc },
1842 { "StopExaminingProc", StopExaminingProc },
1843 { "BackwardProc", BackwardProc },
1844 { "ForwardProc", ForwardProc },
1845 { "ToStartProc", ToStartProc },
1846 { "ToEndProc", ToEndProc },
1847 { "RevertProc", RevertProc },
1848 { "TruncateGameProc", TruncateGameProc },
1849 { "MoveNowProc", MoveNowProc },
1850 { "RetractMoveProc", RetractMoveProc },
1851 { "AlwaysQueenProc", AlwaysQueenProc },
1852 { "AnimateDraggingProc", AnimateDraggingProc },
1853 { "AnimateMovingProc", AnimateMovingProc },
1854 { "AutoflagProc", AutoflagProc },
1855 { "AutoflipProc", AutoflipProc },
1856 { "AutobsProc", AutobsProc },
1857 { "AutoraiseProc", AutoraiseProc },
1858 { "AutosaveProc", AutosaveProc },
1859 { "BlindfoldProc", BlindfoldProc },
1860 { "FlashMovesProc", FlashMovesProc },
1861 { "FlipViewProc", FlipViewProc },
1862 { "GetMoveListProc", GetMoveListProc },
1864 { "HighlightDraggingProc", HighlightDraggingProc },
1866 { "HighlightLastMoveProc", HighlightLastMoveProc },
1867 { "IcsAlarmProc", IcsAlarmProc },
1868 { "MoveSoundProc", MoveSoundProc },
1869 { "OldSaveStyleProc", OldSaveStyleProc },
1870 { "PeriodicUpdatesProc", PeriodicUpdatesProc },
1871 { "PonderNextMoveProc", PonderNextMoveProc },
1872 { "PopupExitMessageProc", PopupExitMessageProc },
1873 { "PopupMoveErrorsProc", PopupMoveErrorsProc },
1874 { "PremoveProc", PremoveProc },
1875 { "QuietPlayProc", QuietPlayProc },
1876 { "ShowCoordsProc", ShowCoordsProc },
1877 { "ShowThinkingProc", ShowThinkingProc },
1878 { "HideThinkingProc", HideThinkingProc },
1879 { "TestLegalityProc", TestLegalityProc },
1880 { "InfoProc", InfoProc },
1881 { "ManProc", ManProc },
1882 { "HintProc", HintProc },
1883 { "BookProc", BookProc },
1884 { "AboutGameProc", AboutGameProc },
1885 { "AboutProc", AboutProc },
1886 { "DebugProc", DebugProc },
1887 { "NothingProc", NothingProc },
1888 { "CommentPopDown", (XtActionProc) CommentPopDown },
1889 { "EditCommentPopDown", (XtActionProc) EditCommentPopDown },
1890 { "TagsPopDown", (XtActionProc) TagsPopDown },
1891 { "ErrorPopDown", (XtActionProc) ErrorPopDown },
1892 { "ICSInputBoxPopDown", (XtActionProc) ICSInputBoxPopDown },
1893 { "AnalysisPopDown", (XtActionProc) AnalysisPopDown },
1894 { "FileNamePopDown", (XtActionProc) FileNamePopDown },
1895 { "AskQuestionPopDown", (XtActionProc) AskQuestionPopDown },
1896 { "GameListPopDown", (XtActionProc) GameListPopDown },
1897 { "PromotionPopDown", (XtActionProc) PromotionPopDown },
1898 { "HistoryPopDown", (XtActionProc) HistoryPopDown },
1899 { "EngineOutputPopDown", (XtActionProc) EngineOutputPopDown },
1900 { "ShufflePopDown", (XtActionProc) ShufflePopDown },
1901 { "EnginePopDown", (XtActionProc) EnginePopDown },
1902 { "UciPopDown", (XtActionProc) UciPopDown },
1903 { "TimeControlPopDown", (XtActionProc) TimeControlPopDown },
1904 { "NewVariantPopDown", (XtActionProc) NewVariantPopDown },
1905 { "SettingsPopDown", (XtActionProc) SettingsPopDown },
1908 char globalTranslations[] =
1909 ":<Key>R: ResignProc() \n \
1910 :<Key>r: ResetProc() \n \
1911 :<Key>g: LoadGameProc() \n \
1912 :<Key>N: LoadNextGameProc() \n \
1913 :<Key>P: LoadPrevGameProc() \n \
1914 :<Key>Q: QuitProc() \n \
1915 :<Key>F: ToEndProc() \n \
1916 :<Key>f: ForwardProc() \n \
1917 :<Key>B: ToStartProc() \n \
1918 :<Key>b: BackwardProc() \n \
1919 :<Key>p: PauseProc() \n \
1920 :<Key>d: DrawProc() \n \
1921 :<Key>t: CallFlagProc() \n \
1922 :<Key>i: Iconify() \n \
1923 :<Key>c: Iconify() \n \
1924 :<Key>v: FlipViewProc() \n \
1925 <KeyDown>Control_L: BackwardProc() \n \
1926 <KeyUp>Control_L: ForwardProc() \n \
1927 <KeyDown>Control_R: BackwardProc() \n \
1928 <KeyUp>Control_R: ForwardProc() \n \
1929 Shift<Key>1: AskQuestionProc(\"Direct command\",\
1930 \"Send to chess program:\",,1) \n \
1931 Shift<Key>2: AskQuestionProc(\"Direct command\",\
1932 \"Send to second chess program:\",,2) \n";
1934 char boardTranslations[] =
1935 "<Btn1Down>: HandleUserMove() \n \
1936 <Btn1Up>: HandleUserMove() \n \
1937 <Btn1Motion>: AnimateUserMove() \n \
1938 Shift<Btn2Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD)\
1939 PieceMenuPopup(menuB) \n \
1940 Any<Btn2Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD) \
1941 PieceMenuPopup(menuW) \n \
1942 Shift<Btn3Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD)\
1943 PieceMenuPopup(menuW) \n \
1944 Any<Btn3Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD) \
1945 PieceMenuPopup(menuB) \n";
1947 char whiteTranslations[] = "<BtnDown>: WhiteClock()\n";
1948 char blackTranslations[] = "<BtnDown>: BlackClock()\n";
1950 char ICSInputTranslations[] =
1951 "<Key>Return: EnterKeyProc() \n";
1953 String xboardResources[] = {
1954 "*fileName*value.translations: #override\\n <Key>Return: FileNameAction()",
1955 "*question*value.translations: #override\\n <Key>Return: AskQuestionReplyAction()",
1956 "*errorpopup*translations: #override\\n <Key>Return: ErrorPopDown()",
1961 /* Max possible square size */
1962 #define MAXSQSIZE 256
1964 static int xpm_avail[MAXSQSIZE];
1966 #ifdef HAVE_DIR_STRUCT
1968 /* Extract piece size from filename */
1970 xpm_getsize(name, len, ext)
1981 if ((p=strchr(name, '.')) == NULL ||
1982 StrCaseCmp(p+1, ext) != 0)
1988 while (*p && isdigit(*p))
1995 /* Setup xpm_avail */
1997 xpm_getavail(dirname, ext)
2005 for (i=0; i<MAXSQSIZE; ++i)
2008 if (appData.debugMode)
2009 fprintf(stderr, "XPM dir:%s:ext:%s:\n", dirname, ext);
2011 dir = opendir(dirname);
2014 fprintf(stderr, _("%s: Can't access XPM directory %s\n"),
2015 programName, dirname);
2019 while ((ent=readdir(dir)) != NULL) {
2020 i = xpm_getsize(ent->d_name, NAMLEN(ent), ext);
2021 if (i > 0 && i < MAXSQSIZE)
2031 xpm_print_avail(fp, ext)
2037 fprintf(fp, _("Available `%s' sizes:\n"), ext);
2038 for (i=1; i<MAXSQSIZE; ++i) {
2044 /* Return XPM piecesize closest to size */
2046 xpm_closest_to(dirname, size, ext)
2052 int sm_diff = MAXSQSIZE;
2056 xpm_getavail(dirname, ext);
2058 if (appData.debugMode)
2059 xpm_print_avail(stderr, ext);
2061 for (i=1; i<MAXSQSIZE; ++i) {
2064 diff = (diff<0) ? -diff : diff;
2065 if (diff < sm_diff) {
2073 fprintf(stderr, _("Error: No `%s' files!\n"), ext);
2079 #else /* !HAVE_DIR_STRUCT */
2080 /* If we are on a system without a DIR struct, we can't
2081 read the directory, so we can't collect a list of
2082 filenames, etc., so we can't do any size-fitting. */
2084 xpm_closest_to(dirname, size, ext)
2089 fprintf(stderr, _("\
2090 Warning: No DIR structure found on this system --\n\
2091 Unable to autosize for XPM/XIM pieces.\n\
2092 Please report this error to frankm@hiwaay.net.\n\
2093 Include system type & operating system in message.\n"));
2096 #endif /* HAVE_DIR_STRUCT */
2098 static char *cnames[9] = { "black", "red", "green", "yellow", "blue",
2099 "magenta", "cyan", "white" };
2103 TextColors textColors[(int)NColorClasses];
2105 /* String is: "fg, bg, attr". Which is 0, 1, 2 */
2107 parse_color(str, which)
2111 char *p, buf[100], *d;
2114 if (strlen(str) > 99) /* watch bounds on buf */
2119 for (i=0; i<which; ++i) {
2126 /* Could be looking at something like:
2128 .. in which case we want to stop on a comma also */
2129 while (*p && *p != ',' && !isalpha(*p) && !isdigit(*p))
2133 return -1; /* Use default for empty field */
2136 if (which == 2 || isdigit(*p))
2139 while (*p && isalpha(*p))
2144 for (i=0; i<8; ++i) {
2145 if (!StrCaseCmp(buf, cnames[i]))
2146 return which? (i+40) : (i+30);
2148 if (!StrCaseCmp(buf, "default")) return -1;
2150 fprintf(stderr, _("%s: unrecognized color %s\n"), programName, buf);
2155 parse_cpair(cc, str)
2159 if ((textColors[(int)cc].fg=parse_color(str, 0)) == -2) {
2160 fprintf(stderr, _("%s: can't parse foreground color in `%s'\n"),
2165 /* bg and attr are optional */
2166 textColors[(int)cc].bg = parse_color(str, 1);
2167 if ((textColors[(int)cc].attr = parse_color(str, 2)) < 0) {
2168 textColors[(int)cc].attr = 0;
2174 /* Arrange to catch delete-window events */
2175 Atom wm_delete_window;
2177 CatchDeleteWindow(Widget w, String procname)
2180 XSetWMProtocols(xDisplay, XtWindow(w), &wm_delete_window, 1);
2181 snprintf(buf, sizeof(buf), "<Message>WM_PROTOCOLS: %s() \n", procname);
2182 XtAugmentTranslations(w, XtParseTranslationTable(buf));
2189 XtSetArg(args[0], XtNiconic, False);
2190 XtSetValues(shellWidget, args, 1);
2192 XtPopup(shellWidget, XtGrabNone); /* Raise if lowered */
2196 // eventually, all layout determining code should go into a subroutine, but until then IDSIZE remains undefined
2198 #define BoardSize int
2199 void InitDrawingSizes(BoardSize boardSize, int flags)
2200 { // [HGM] resize is functional now, but for board format changes only (nr of ranks, files)
2201 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
2203 XtGeometryResult gres;
2206 if(!formWidget) return;
2209 * Enable shell resizing.
2211 shellArgs[0].value = (XtArgVal) &w;
2212 shellArgs[1].value = (XtArgVal) &h;
2213 XtGetValues(shellWidget, shellArgs, 2);
2215 shellArgs[4].value = 2*w; shellArgs[2].value = 10;
2216 shellArgs[5].value = 2*h; shellArgs[3].value = 10;
2217 XtSetValues(shellWidget, &shellArgs[2], 4);
2219 XtSetArg(args[0], XtNdefaultDistance, &sep);
2220 XtGetValues(formWidget, args, 1);
2222 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2223 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2226 XtSetArg(args[0], XtNwidth, boardWidth);
2227 XtSetArg(args[1], XtNheight, boardHeight);
2228 XtSetValues(boardWidget, args, 2);
2230 timerWidth = (boardWidth - sep) / 2;
2231 XtSetArg(args[0], XtNwidth, timerWidth);
2232 XtSetValues(whiteTimerWidget, args, 1);
2233 XtSetValues(blackTimerWidget, args, 1);
2235 XawFormDoLayout(formWidget, False);
2237 if (appData.titleInWindow) {
2239 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2240 XtSetArg(args[i], XtNheight, &h); i++;
2241 XtGetValues(titleWidget, args, i);
2243 w = boardWidth - 2*bor;
2245 XtSetArg(args[0], XtNwidth, &w);
2246 XtGetValues(menuBarWidget, args, 1);
2247 w = boardWidth - w - sep - 2*bor - 2; // WIDTH_FUDGE
2250 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
2251 if (gres != XtGeometryYes && appData.debugMode) {
2253 _("%s: titleWidget geometry error %d %d %d %d %d\n"),
2254 programName, gres, w, h, wr, hr);
2258 XawFormDoLayout(formWidget, True);
2261 * Inhibit shell resizing.
2263 shellArgs[0].value = w = (XtArgVal) boardWidth + marginW;
2264 shellArgs[1].value = h = (XtArgVal) boardHeight + marginH;
2265 shellArgs[4].value = shellArgs[2].value = w;
2266 shellArgs[5].value = shellArgs[3].value = h;
2267 XtSetValues(shellWidget, &shellArgs[0], 6);
2269 // [HGM] pieces: tailor piece bitmaps to needs of specific variant
2272 for(i=0; i<4; i++) {
2274 for(p=0; p<=(int)WhiteKing; p++)
2275 xpmPieceBitmap[i][p] = xpmPieceBitmap2[i][p]; // defaults
2276 if(gameInfo.variant == VariantShogi) {
2277 xpmPieceBitmap[i][(int)WhiteCannon] = xpmPieceBitmap2[i][(int)WhiteKing+1];
2278 xpmPieceBitmap[i][(int)WhiteNightrider] = xpmPieceBitmap2[i][(int)WhiteKing+2];
2279 xpmPieceBitmap[i][(int)WhiteSilver] = xpmPieceBitmap2[i][(int)WhiteKing+3];
2280 xpmPieceBitmap[i][(int)WhiteGrasshopper] = xpmPieceBitmap2[i][(int)WhiteKing+4];
2281 xpmPieceBitmap[i][(int)WhiteQueen] = xpmPieceBitmap2[i][(int)WhiteLance];
2284 if(gameInfo.variant == VariantGothic) {
2285 xpmPieceBitmap[i][(int)WhiteMarshall] = xpmPieceBitmap2[i][(int)WhiteSilver];
2289 // [HGM] why are thee ximMasks used at all? the ximPieceBitmaps seem to be never used!
2290 for(p=0; p<=(int)WhiteKing; p++)
2291 ximMaskPm[p] = ximMaskPm2[p]; // defaults
2292 if(gameInfo.variant == VariantShogi) {
2293 ximMaskPm[(int)WhiteCannon] = ximMaskPm2[(int)WhiteKing+1];
2294 ximMaskPm[(int)WhiteNightrider] = ximMaskPm2[(int)WhiteKing+2];
2295 ximMaskPm[(int)WhiteSilver] = ximMaskPm2[(int)WhiteKing+3];
2296 ximMaskPm[(int)WhiteGrasshopper] = ximMaskPm2[(int)WhiteKing+4];
2297 ximMaskPm[(int)WhiteQueen] = ximMaskPm2[(int)WhiteLance];
2300 if(gameInfo.variant == VariantGothic) {
2301 ximMaskPm[(int)WhiteMarshall] = ximMaskPm2[(int)WhiteSilver];
2307 for(i=0; i<2; i++) {
2309 for(p=0; p<=(int)WhiteKing; p++)
2310 pieceBitmap[i][p] = pieceBitmap2[i][p]; // defaults
2311 if(gameInfo.variant == VariantShogi) {
2312 pieceBitmap[i][(int)WhiteCannon] = pieceBitmap2[i][(int)WhiteKing+1];
2313 pieceBitmap[i][(int)WhiteNightrider] = pieceBitmap2[i][(int)WhiteKing+2];
2314 pieceBitmap[i][(int)WhiteSilver] = pieceBitmap2[i][(int)WhiteKing+3];
2315 pieceBitmap[i][(int)WhiteGrasshopper] = pieceBitmap2[i][(int)WhiteKing+4];
2316 pieceBitmap[i][(int)WhiteQueen] = pieceBitmap2[i][(int)WhiteLance];
2319 if(gameInfo.variant == VariantGothic) {
2320 pieceBitmap[i][(int)WhiteMarshall] = pieceBitmap2[i][(int)WhiteSilver];
2331 void EscapeExpand(char *p, char *q)
2332 { // [HGM] initstring: routine to shape up string arguments
2333 while(*p++ = *q++) if(p[-1] == '\\')
2335 case 'n': p[-1] = '\n'; break;
2336 case 'r': p[-1] = '\r'; break;
2337 case 't': p[-1] = '\t'; break;
2338 case '\\': p[-1] = '\\'; break;
2339 case 0: *p = 0; return;
2340 default: p[-1] = q[-1]; break;
2349 int i, j, clockFontPxlSize, coordFontPxlSize, fontPxlSize;
2350 XSetWindowAttributes window_attributes;
2352 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
2353 XrmValue vFrom, vTo;
2354 XtGeometryResult gres;
2357 int forceMono = False;
2360 // [HGM] before anything else, expand any indirection files amongst options
2361 char *argvCopy[1000]; // 1000 seems enough
2362 char newArgs[10000]; // holds actual characters
2365 srandom(time(0)); // [HGM] book: make random truly random
2368 for(i=0; i<argc; i++) {
2369 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2370 //fprintf(stderr, "arg %s\n", argv[i]);
2371 if(argv[i][0] != '@') argvCopy[j++] = argv[i]; else {
2373 FILE *f = fopen(argv[i]+1, "rb");
2374 if(f == NULL) { fprintf(stderr, _("ignore %s\n"), argv[i]); continue; } // do not expand non-existing
2375 argvCopy[j++] = newArgs + k; // get ready for first argument from file
2376 while((c = fgetc(f)) != EOF) { // each line of file inserts 1 argument in the list
2378 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2379 newArgs[k++] = 0; // terminate current arg
2380 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2381 argvCopy[j++] = newArgs + k; // get ready for next
2383 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2397 setbuf(stdout, NULL);
2398 setbuf(stderr, NULL);
2401 programName = strrchr(argv[0], '/');
2402 if (programName == NULL)
2403 programName = argv[0];
2408 XtSetLanguageProc(NULL, NULL, NULL);
2409 bindtextdomain(PACKAGE, LOCALEDIR);
2410 textdomain(PACKAGE);
2414 XtAppInitialize(&appContext, "XBoard", shellOptions,
2415 XtNumber(shellOptions),
2416 &argc, argv, xboardResources, NULL, 0);
2418 { /* left over command line arguments, print out help and exit.
2419 * Use two columns to print help
2421 fprintf(stderr, _("%s: unrecognized argument %s\n"),
2422 programName, argv[1]);
2424 fprintf(stderr, "Recognized options:\n");
2425 for(i = 0; i < XtNumber(shellOptions); i++)
2427 /* print first column */
2428 j = fprintf(stderr, " %s%s", shellOptions[i].option,
2429 (shellOptions[i].argKind == XrmoptionSepArg
2431 /* print second column and end line */
2432 if (++i < XtNumber(shellOptions))
2434 fprintf(stderr, "%*c%s%s\n", 40 - j, ' ',
2435 shellOptions[i].option,
2436 (shellOptions[i].argKind == XrmoptionSepArg
2441 fprintf(stderr, "\n");
2448 if (p == NULL) p = "/tmp";
2449 i = strlen(p) + strlen("/.xboardXXXXXx.pgn") + 1;
2450 gameCopyFilename = (char*) malloc(i);
2451 gamePasteFilename = (char*) malloc(i);
2452 snprintf(gameCopyFilename,i, "%s/.xboard%05uc.pgn", p, getpid());
2453 snprintf(gamePasteFilename,i, "%s/.xboard%05up.pgn", p, getpid());
2455 XtGetApplicationResources(shellWidget, (XtPointer) &appData,
2456 clientResources, XtNumber(clientResources),
2459 { // [HGM] initstring: kludge to fix bad bug. expand '\n' characters in init string and computer string.
2460 static char buf[MSG_SIZ];
2461 EscapeExpand(buf, appData.initString);
2462 appData.initString = strdup(buf);
2463 EscapeExpand(buf, appData.secondInitString);
2464 appData.secondInitString = strdup(buf);
2465 EscapeExpand(buf, appData.firstComputerString);
2466 appData.firstComputerString = strdup(buf);
2467 EscapeExpand(buf, appData.secondComputerString);
2468 appData.secondComputerString = strdup(buf);
2471 if ((chessDir = (char *) getenv("CHESSDIR")) == NULL) {
2474 if (chdir(chessDir) != 0) {
2475 fprintf(stderr, _("%s: can't cd to CHESSDIR: "), programName);
2481 if (appData.debugMode && appData.nameOfDebugFile && strcmp(appData.nameOfDebugFile, "stderr")) {
2482 /* [DM] debug info to file [HGM] make the filename a command-line option, and allow it to remain stderr */
2483 if ((debugFP = fopen(appData.nameOfDebugFile, "w")) == NULL) {
2484 printf(_("Failed to open file '%s'\n"), appData.nameOfDebugFile);
2487 setbuf(debugFP, NULL);
2490 /* [HGM,HR] make sure board size is acceptable */
2491 if(appData.NrFiles > BOARD_SIZE ||
2492 appData.NrRanks > BOARD_SIZE )
2493 DisplayFatalError(_("Recompile with BOARD_SIZE > 12, to support this size"), 0, 2);
2496 /* This feature does not work; animation needs a rewrite */
2497 appData.highlightDragging = FALSE;
2501 xDisplay = XtDisplay(shellWidget);
2502 xScreen = DefaultScreen(xDisplay);
2503 wm_delete_window = XInternAtom(xDisplay, "WM_DELETE_WINDOW", True);
2505 gameInfo.variant = StringToVariant(appData.variant);
2506 InitPosition(FALSE);
2509 InitDrawingSizes(-1, 0); // [HGM] initsize: make this into a subroutine
2511 if (isdigit(appData.boardSize[0])) {
2512 i = sscanf(appData.boardSize, "%d,%d,%d,%d,%d,%d,%d", &squareSize,
2513 &lineGap, &clockFontPxlSize, &coordFontPxlSize,
2514 &fontPxlSize, &smallLayout, &tinyLayout);
2516 fprintf(stderr, _("%s: bad boardSize syntax %s\n"),
2517 programName, appData.boardSize);
2521 /* Find some defaults; use the nearest known size */
2522 SizeDefaults *szd, *nearest;
2523 int distance = 99999;
2524 nearest = szd = sizeDefaults;
2525 while (szd->name != NULL) {
2526 if (abs(szd->squareSize - squareSize) < distance) {
2528 distance = abs(szd->squareSize - squareSize);
2529 if (distance == 0) break;
2533 if (i < 2) lineGap = nearest->lineGap;
2534 if (i < 3) clockFontPxlSize = nearest->clockFontPxlSize;
2535 if (i < 4) coordFontPxlSize = nearest->coordFontPxlSize;
2536 if (i < 5) fontPxlSize = nearest->fontPxlSize;
2537 if (i < 6) smallLayout = nearest->smallLayout;
2538 if (i < 7) tinyLayout = nearest->tinyLayout;
2541 SizeDefaults *szd = sizeDefaults;
2542 if (*appData.boardSize == NULLCHAR) {
2543 while (DisplayWidth(xDisplay, xScreen) < szd->minScreenSize ||
2544 DisplayHeight(xDisplay, xScreen) < szd->minScreenSize) {
2547 if (szd->name == NULL) szd--;
2549 while (szd->name != NULL &&
2550 StrCaseCmp(szd->name, appData.boardSize) != 0) szd++;
2551 if (szd->name == NULL) {
2552 fprintf(stderr, _("%s: unrecognized boardSize name %s\n"),
2553 programName, appData.boardSize);
2557 squareSize = szd->squareSize;
2558 lineGap = szd->lineGap;
2559 clockFontPxlSize = szd->clockFontPxlSize;
2560 coordFontPxlSize = szd->coordFontPxlSize;
2561 fontPxlSize = szd->fontPxlSize;
2562 smallLayout = szd->smallLayout;
2563 tinyLayout = szd->tinyLayout;
2566 /* Now, using squareSize as a hint, find a good XPM/XIM set size */
2567 if (strlen(appData.pixmapDirectory) > 0) {
2568 p = ExpandPathName(appData.pixmapDirectory);
2570 fprintf(stderr, _("Error expanding path name \"%s\"\n"),
2571 appData.pixmapDirectory);
2574 if (appData.debugMode) {
2575 fprintf(stderr, _("\
2576 XBoard square size (hint): %d\n\
2577 %s fulldir:%s:\n"), squareSize, IMAGE_EXT, p);
2579 squareSize = xpm_closest_to(p, squareSize, IMAGE_EXT);
2580 if (appData.debugMode) {
2581 fprintf(stderr, _("Closest %s size: %d\n"), IMAGE_EXT, squareSize);
2585 /* [HR] height treated separately (hacked) */
2586 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2587 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2588 if (appData.showJail == 1) {
2589 /* Jail on top and bottom */
2590 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2591 XtSetArg(boardArgs[2], XtNheight,
2592 boardHeight + 2*(lineGap + squareSize));
2593 } else if (appData.showJail == 2) {
2595 XtSetArg(boardArgs[1], XtNwidth,
2596 boardWidth + 2*(lineGap + squareSize));
2597 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2600 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2601 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2605 * Determine what fonts to use.
2607 appData.clockFont = FindFont(appData.clockFont, clockFontPxlSize);
2608 clockFontID = XLoadFont(xDisplay, appData.clockFont);
2609 clockFontStruct = XQueryFont(xDisplay, clockFontID);
2610 appData.coordFont = FindFont(appData.coordFont, coordFontPxlSize);
2611 coordFontID = XLoadFont(xDisplay, appData.coordFont);
2612 coordFontStruct = XQueryFont(xDisplay, coordFontID);
2613 appData.font = FindFont(appData.font, fontPxlSize);
2614 countFontID = XLoadFont(xDisplay, appData.coordFont); // [HGM] holdings
2615 countFontStruct = XQueryFont(xDisplay, countFontID);
2616 // appData.font = FindFont(appData.font, fontPxlSize);
2618 xdb = XtDatabase(xDisplay);
2619 XrmPutStringResource(&xdb, "*font", appData.font);
2622 * Detect if there are not enough colors available and adapt.
2624 if (DefaultDepth(xDisplay, xScreen) <= 2) {
2625 appData.monoMode = True;
2628 if (!appData.monoMode) {
2629 vFrom.addr = (caddr_t) appData.lightSquareColor;
2630 vFrom.size = strlen(appData.lightSquareColor);
2631 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2632 if (vTo.addr == NULL) {
2633 appData.monoMode = True;
2636 lightSquareColor = *(Pixel *) vTo.addr;
2639 if (!appData.monoMode) {
2640 vFrom.addr = (caddr_t) appData.darkSquareColor;
2641 vFrom.size = strlen(appData.darkSquareColor);
2642 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2643 if (vTo.addr == NULL) {
2644 appData.monoMode = True;
2647 darkSquareColor = *(Pixel *) vTo.addr;
2650 if (!appData.monoMode) {
2651 vFrom.addr = (caddr_t) appData.whitePieceColor;
2652 vFrom.size = strlen(appData.whitePieceColor);
2653 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2654 if (vTo.addr == NULL) {
2655 appData.monoMode = True;
2658 whitePieceColor = *(Pixel *) vTo.addr;
2661 if (!appData.monoMode) {
2662 vFrom.addr = (caddr_t) appData.blackPieceColor;
2663 vFrom.size = strlen(appData.blackPieceColor);
2664 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2665 if (vTo.addr == NULL) {
2666 appData.monoMode = True;
2669 blackPieceColor = *(Pixel *) vTo.addr;
2673 if (!appData.monoMode) {
2674 vFrom.addr = (caddr_t) appData.highlightSquareColor;
2675 vFrom.size = strlen(appData.highlightSquareColor);
2676 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2677 if (vTo.addr == NULL) {
2678 appData.monoMode = True;
2681 highlightSquareColor = *(Pixel *) vTo.addr;
2685 if (!appData.monoMode) {
2686 vFrom.addr = (caddr_t) appData.premoveHighlightColor;
2687 vFrom.size = strlen(appData.premoveHighlightColor);
2688 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2689 if (vTo.addr == NULL) {
2690 appData.monoMode = True;
2693 premoveHighlightColor = *(Pixel *) vTo.addr;
2698 fprintf(stderr, _("%s: too few colors available; trying monochrome mode\n"),
2701 if (appData.bitmapDirectory == NULL ||
2702 appData.bitmapDirectory[0] == NULLCHAR)
2703 appData.bitmapDirectory = DEF_BITMAP_DIR;
2706 if (appData.lowTimeWarning && !appData.monoMode) {
2707 vFrom.addr = (caddr_t) appData.lowTimeWarningColor;
2708 vFrom.size = strlen(appData.lowTimeWarningColor);
2709 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2710 if (vTo.addr == NULL)
2711 appData.monoMode = True;
2713 lowTimeWarningColor = *(Pixel *) vTo.addr;
2716 if (appData.monoMode && appData.debugMode) {
2717 fprintf(stderr, _("white pixel = 0x%lx, black pixel = 0x%lx\n"),
2718 (unsigned long) XWhitePixel(xDisplay, xScreen),
2719 (unsigned long) XBlackPixel(xDisplay, xScreen));
2722 if (parse_cpair(ColorShout, appData.colorShout) < 0 ||
2723 parse_cpair(ColorSShout, appData.colorSShout) < 0 ||
2724 parse_cpair(ColorChannel1, appData.colorChannel1) < 0 ||
2725 parse_cpair(ColorChannel, appData.colorChannel) < 0 ||
2726 parse_cpair(ColorKibitz, appData.colorKibitz) < 0 ||
2727 parse_cpair(ColorTell, appData.colorTell) < 0 ||
2728 parse_cpair(ColorChallenge, appData.colorChallenge) < 0 ||
2729 parse_cpair(ColorRequest, appData.colorRequest) < 0 ||
2730 parse_cpair(ColorSeek, appData.colorSeek) < 0 ||
2731 parse_cpair(ColorNormal, appData.colorNormal) < 0)
2733 if (appData.colorize) {
2735 _("%s: can't parse color names; disabling colorization\n"),
2738 appData.colorize = FALSE;
2740 textColors[ColorNone].fg = textColors[ColorNone].bg = -1;
2741 textColors[ColorNone].attr = 0;
2743 XtAppAddActions(appContext, boardActions, XtNumber(boardActions));
2749 layoutName = "tinyLayout";
2750 } else if (smallLayout) {
2751 layoutName = "smallLayout";
2753 layoutName = "normalLayout";
2755 /* Outer layoutWidget is there only to provide a name for use in
2756 resources that depend on the layout style */
2758 XtCreateManagedWidget(layoutName, formWidgetClass, shellWidget,
2759 layoutArgs, XtNumber(layoutArgs));
2761 XtCreateManagedWidget("form", formWidgetClass, layoutWidget,
2762 formArgs, XtNumber(formArgs));
2763 XtSetArg(args[0], XtNdefaultDistance, &sep);
2764 XtGetValues(formWidget, args, 1);
2767 widgetList[j++] = menuBarWidget = CreateMenuBar(menuBar);
2768 XtSetArg(args[0], XtNtop, XtChainTop);
2769 XtSetArg(args[1], XtNbottom, XtChainTop);
2770 XtSetValues(menuBarWidget, args, 2);
2772 widgetList[j++] = whiteTimerWidget =
2773 XtCreateWidget("whiteTime", labelWidgetClass,
2774 formWidget, timerArgs, XtNumber(timerArgs));
2775 XtSetArg(args[0], XtNfont, clockFontStruct);
2776 XtSetArg(args[1], XtNtop, XtChainTop);
2777 XtSetArg(args[2], XtNbottom, XtChainTop);
2778 XtSetValues(whiteTimerWidget, args, 3);
2780 widgetList[j++] = blackTimerWidget =
2781 XtCreateWidget("blackTime", labelWidgetClass,
2782 formWidget, timerArgs, XtNumber(timerArgs));
2783 XtSetArg(args[0], XtNfont, clockFontStruct);
2784 XtSetArg(args[1], XtNtop, XtChainTop);
2785 XtSetArg(args[2], XtNbottom, XtChainTop);
2786 XtSetValues(blackTimerWidget, args, 3);
2788 if (appData.titleInWindow) {
2789 widgetList[j++] = titleWidget =
2790 XtCreateWidget("title", labelWidgetClass, formWidget,
2791 titleArgs, XtNumber(titleArgs));
2792 XtSetArg(args[0], XtNtop, XtChainTop);
2793 XtSetArg(args[1], XtNbottom, XtChainTop);
2794 XtSetValues(titleWidget, args, 2);
2797 if (appData.showButtonBar) {
2798 widgetList[j++] = buttonBarWidget = CreateButtonBar(buttonBar);
2799 XtSetArg(args[0], XtNleft, XtChainRight); // [HGM] glue to right window edge
2800 XtSetArg(args[1], XtNright, XtChainRight); // for good run-time sizing
2801 XtSetArg(args[2], XtNtop, XtChainTop);
2802 XtSetArg(args[3], XtNbottom, XtChainTop);
2803 XtSetValues(buttonBarWidget, args, 4);
2806 widgetList[j++] = messageWidget =
2807 XtCreateWidget("message", labelWidgetClass, formWidget,
2808 messageArgs, XtNumber(messageArgs));
2809 XtSetArg(args[0], XtNtop, XtChainTop);
2810 XtSetArg(args[1], XtNbottom, XtChainTop);
2811 XtSetValues(messageWidget, args, 2);
2813 widgetList[j++] = boardWidget =
2814 XtCreateWidget("board", widgetClass, formWidget, boardArgs,
2815 XtNumber(boardArgs));
2817 XtManageChildren(widgetList, j);
2819 timerWidth = (boardWidth - sep) / 2;
2820 XtSetArg(args[0], XtNwidth, timerWidth);
2821 XtSetValues(whiteTimerWidget, args, 1);
2822 XtSetValues(blackTimerWidget, args, 1);
2824 XtSetArg(args[0], XtNbackground, &timerBackgroundPixel);
2825 XtSetArg(args[1], XtNforeground, &timerForegroundPixel);
2826 XtGetValues(whiteTimerWidget, args, 2);
2828 if (appData.showButtonBar) {
2829 XtSetArg(args[0], XtNbackground, &buttonBackgroundPixel);
2830 XtSetArg(args[1], XtNforeground, &buttonForegroundPixel);
2831 XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
2835 * formWidget uses these constraints but they are stored
2839 XtSetArg(args[i], XtNfromHoriz, 0); i++;
2840 XtSetValues(menuBarWidget, args, i);
2841 if (appData.titleInWindow) {
2844 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2845 XtSetValues(whiteTimerWidget, args, i);
2847 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2848 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2849 XtSetValues(blackTimerWidget, args, i);
2851 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2852 XtSetArg(args[i], XtNjustify, XtJustifyLeft); i++;
2853 XtSetValues(titleWidget, args, i);
2855 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2856 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2857 XtSetValues(messageWidget, args, i);
2858 if (appData.showButtonBar) {
2860 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2861 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2862 XtSetValues(buttonBarWidget, args, i);
2866 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2867 XtSetValues(whiteTimerWidget, args, i);
2869 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2870 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2871 XtSetValues(blackTimerWidget, args, i);
2873 XtSetArg(args[i], XtNfromHoriz, menuBarWidget); i++;
2874 XtSetValues(titleWidget, args, i);
2876 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2877 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2878 XtSetValues(messageWidget, args, i);
2879 if (appData.showButtonBar) {
2881 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2882 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2883 XtSetValues(buttonBarWidget, args, i);
2888 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2889 XtSetValues(whiteTimerWidget, args, i);
2891 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2892 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2893 XtSetValues(blackTimerWidget, args, i);
2895 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2896 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2897 XtSetValues(messageWidget, args, i);
2898 if (appData.showButtonBar) {
2900 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2901 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2902 XtSetValues(buttonBarWidget, args, i);
2906 XtSetArg(args[0], XtNfromVert, messageWidget);
2907 XtSetArg(args[1], XtNtop, XtChainTop);
2908 XtSetArg(args[2], XtNbottom, XtChainBottom);
2909 XtSetArg(args[3], XtNleft, XtChainLeft);
2910 XtSetArg(args[4], XtNright, XtChainRight);
2911 XtSetValues(boardWidget, args, 5);
2913 XtRealizeWidget(shellWidget);
2916 * Correct the width of the message and title widgets.
2917 * It is not known why some systems need the extra fudge term.
2918 * The value "2" is probably larger than needed.
2920 XawFormDoLayout(formWidget, False);
2922 #define WIDTH_FUDGE 2
2924 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2925 XtSetArg(args[i], XtNheight, &h); i++;
2926 XtGetValues(messageWidget, args, i);
2927 if (appData.showButtonBar) {
2929 XtSetArg(args[i], XtNwidth, &w); i++;
2930 XtGetValues(buttonBarWidget, args, i);
2931 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2933 w = boardWidth - 2*bor + 1; /*!! +1 compensates for kludge below */
2936 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2937 if (gres != XtGeometryYes && appData.debugMode) {
2938 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2939 programName, gres, w, h, wr, hr);
2942 /* !! Horrible hack to work around bug in XFree86 4.0.1 (X11R6.4.3) */
2943 /* The size used for the child widget in layout lags one resize behind
2944 its true size, so we resize a second time, 1 pixel smaller. Yeech! */
2946 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2947 if (gres != XtGeometryYes && appData.debugMode) {
2948 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2949 programName, gres, w, h, wr, hr);
2952 XtSetArg(args[0], XtNleft, XtChainLeft); // [HGM] glue ends for good run-time sizing
2953 XtSetArg(args[1], XtNright, XtChainRight);
2954 XtSetValues(messageWidget, args, 2);
2956 if (appData.titleInWindow) {
2958 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2959 XtSetArg(args[i], XtNheight, &h); i++;
2960 XtGetValues(titleWidget, args, i);
2962 w = boardWidth - 2*bor;
2964 XtSetArg(args[0], XtNwidth, &w);
2965 XtGetValues(menuBarWidget, args, 1);
2966 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2969 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
2970 if (gres != XtGeometryYes && appData.debugMode) {
2972 _("%s: titleWidget geometry error %d %d %d %d %d\n"),
2973 programName, gres, w, h, wr, hr);
2976 XawFormDoLayout(formWidget, True);
2978 xBoardWindow = XtWindow(boardWidget);
2980 // [HGM] it seems the layout code ends here, but perhaps the color stuff is size independent and would
2981 // not need to go into InitDrawingSizes().
2985 * Create X checkmark bitmap and initialize option menu checks.
2987 ReadBitmap(&xMarkPixmap, "checkmark.bm",
2988 checkmark_bits, checkmark_width, checkmark_height);
2989 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
2990 if (appData.alwaysPromoteToQueen) {
2991 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
2994 if (appData.animateDragging) {
2995 XtSetValues(XtNameToWidget(menuBarWidget,
2996 "menuOptions.Animate Dragging"),
2999 if (appData.animate) {
3000 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
3003 if (appData.autoComment) {
3004 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
3007 if (appData.autoCallFlag) {
3008 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
3011 if (appData.autoFlipView) {
3012 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Auto Flip View"),
3015 if (appData.autoObserve) {
3016 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
3019 if (appData.autoRaiseBoard) {
3020 XtSetValues(XtNameToWidget(menuBarWidget,
3021 "menuOptions.Auto Raise Board"), args, 1);
3023 if (appData.autoSaveGames) {
3024 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
3027 if (appData.saveGameFile[0] != NULLCHAR) {
3028 /* Can't turn this off from menu */
3029 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
3031 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
3035 if (appData.blindfold) {
3036 XtSetValues(XtNameToWidget(menuBarWidget,
3037 "menuOptions.Blindfold"), args, 1);
3039 if (appData.flashCount > 0) {
3040 XtSetValues(XtNameToWidget(menuBarWidget,
3041 "menuOptions.Flash Moves"),
3044 if (appData.getMoveList) {
3045 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
3049 if (appData.highlightDragging) {
3050 XtSetValues(XtNameToWidget(menuBarWidget,
3051 "menuOptions.Highlight Dragging"),
3055 if (appData.highlightLastMove) {
3056 XtSetValues(XtNameToWidget(menuBarWidget,
3057 "menuOptions.Highlight Last Move"),
3060 if (appData.icsAlarm) {
3061 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.ICS Alarm"),
3064 if (appData.ringBellAfterMoves) {
3065 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
3068 if (appData.oldSaveStyle) {
3069 XtSetValues(XtNameToWidget(menuBarWidget,
3070 "menuOptions.Old Save Style"), args, 1);
3072 if (appData.periodicUpdates) {
3073 XtSetValues(XtNameToWidget(menuBarWidget,
3074 "menuOptions.Periodic Updates"), args, 1);
3076 if (appData.ponderNextMove) {
3077 XtSetValues(XtNameToWidget(menuBarWidget,
3078 "menuOptions.Ponder Next Move"), args, 1);
3080 if (appData.popupExitMessage) {
3081 XtSetValues(XtNameToWidget(menuBarWidget,
3082 "menuOptions.Popup Exit Message"), args, 1);
3084 if (appData.popupMoveErrors) {
3085 XtSetValues(XtNameToWidget(menuBarWidget,
3086 "menuOptions.Popup Move Errors"), args, 1);
3088 if (appData.premove) {
3089 XtSetValues(XtNameToWidget(menuBarWidget,
3090 "menuOptions.Premove"), args, 1);
3092 if (appData.quietPlay) {
3093 XtSetValues(XtNameToWidget(menuBarWidget,
3094 "menuOptions.Quiet Play"), args, 1);
3096 if (appData.showCoords) {
3097 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
3100 if (appData.hideThinkingFromHuman) {
3101 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
3104 if (appData.testLegality) {
3105 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Test Legality"),
3112 ReadBitmap(&wIconPixmap, "icon_white.bm",
3113 icon_white_bits, icon_white_width, icon_white_height);
3114 ReadBitmap(&bIconPixmap, "icon_black.bm",
3115 icon_black_bits, icon_black_width, icon_black_height);
3116 iconPixmap = wIconPixmap;
3118 XtSetArg(args[i], XtNiconPixmap, iconPixmap); i++;
3119 XtSetValues(shellWidget, args, i);
3122 * Create a cursor for the board widget.
3124 window_attributes.cursor = XCreateFontCursor(xDisplay, XC_hand2);
3125 XChangeWindowAttributes(xDisplay, xBoardWindow,
3126 CWCursor, &window_attributes);
3129 * Inhibit shell resizing.
3131 shellArgs[0].value = (XtArgVal) &w;
3132 shellArgs[1].value = (XtArgVal) &h;
3133 XtGetValues(shellWidget, shellArgs, 2);
3134 shellArgs[4].value = shellArgs[2].value = w;
3135 shellArgs[5].value = shellArgs[3].value = h;
3136 XtSetValues(shellWidget, &shellArgs[2], 4);
3137 marginW = w - boardWidth; // [HGM] needed to set new shellWidget size when we resize board
3138 marginH = h - boardHeight;
3140 CatchDeleteWindow(shellWidget, "QuitProc");
3145 if (appData.bitmapDirectory[0] != NULLCHAR) {
3152 /* Create regular pieces */
3153 if (!useImages) CreatePieces();
3158 if (appData.animate || appData.animateDragging)
3161 XtAugmentTranslations(formWidget,
3162 XtParseTranslationTable(globalTranslations));
3163 XtAugmentTranslations(boardWidget,
3164 XtParseTranslationTable(boardTranslations));
3165 XtAugmentTranslations(whiteTimerWidget,
3166 XtParseTranslationTable(whiteTranslations));
3167 XtAugmentTranslations(blackTimerWidget,
3168 XtParseTranslationTable(blackTranslations));
3170 /* Why is the following needed on some versions of X instead
3171 * of a translation? */
3172 XtAddEventHandler(boardWidget, ExposureMask, False,
3173 (XtEventHandler) EventProc, NULL);
3178 if (errorExitStatus == -1) {
3179 if (appData.icsActive) {
3180 /* We now wait until we see "login:" from the ICS before
3181 sending the logon script (problems with timestamp otherwise) */
3182 /*ICSInitScript();*/
3183 if (appData.icsInputBox) ICSInputBoxPopUp();
3186 signal(SIGINT, IntSigHandler);
3187 signal(SIGTERM, IntSigHandler);
3188 if (*appData.cmailGameName != NULLCHAR) {
3189 signal(SIGUSR1, CmailSigHandler);
3192 gameInfo.boardWidth = 0; // [HGM] pieces: kludge to ensure InitPosition() calls InitDrawingSizes()
3195 XtAppMainLoop(appContext);
3196 if (appData.debugMode) fclose(debugFP); // [DM] debug
3203 if (appData.icsActive && oldICSInteractionTitle != NULL) {
3204 DisplayIcsInteractionTitle(oldICSInteractionTitle);
3206 unlink(gameCopyFilename);
3207 unlink(gamePasteFilename);
3218 CmailSigHandler(sig)
3224 signal(SIGUSR1, SIG_IGN); /* suspend handler */
3226 /* Activate call-back function CmailSigHandlerCallBack() */
3227 OutputToProcess(cmailPR, (char *)(&dummy), sizeof(int), &error);
3229 signal(SIGUSR1, CmailSigHandler); /* re-activate handler */
3233 CmailSigHandlerCallBack(isr, closure, message, count, error)
3241 ReloadCmailMsgEvent(TRUE); /* Reload cmail msg */
3243 /**** end signal code ****/
3253 f = fopen(appData.icsLogon, "r");
3259 strcat(buf, appData.icsLogon);
3260 f = fopen(buf, "r");
3264 ProcessICSInitScript(f);
3271 EditCommentPopDown();
3282 SetMenuEnables(enab)
3286 if (!menuBarWidget) return;
3287 while (enab->name != NULL) {
3288 w = XtNameToWidget(menuBarWidget, enab->name);
3290 DisplayError(enab->name, 0);
3292 XtSetSensitive(w, enab->value);
3298 Enables icsEnables[] = {
3299 { "menuFile.Mail Move", False },
3300 { "menuFile.Reload CMail Message", False },
3301 { "menuMode.Machine Black", False },
3302 { "menuMode.Machine White", False },
3303 { "menuMode.Analysis Mode", False },
3304 { "menuMode.Analyze File", False },
3305 { "menuMode.Two Machines", False },
3307 { "menuHelp.Hint", False },
3308 { "menuHelp.Book", False },
3309 { "menuStep.Move Now", False },
3310 { "menuOptions.Periodic Updates", False },
3311 { "menuOptions.Hide Thinking", False },
3312 { "menuOptions.Ponder Next Move", False },
3317 Enables ncpEnables[] = {
3318 { "menuFile.Mail Move", False },
3319 { "menuFile.Reload CMail Message", False },
3320 { "menuMode.Machine White", False },
3321 { "menuMode.Machine Black", False },
3322 { "menuMode.Analysis Mode", False },
3323 { "menuMode.Analyze File", False },
3324 { "menuMode.Two Machines", False },
3325 { "menuMode.ICS Client", False },
3326 { "menuMode.ICS Input Box", False },
3327 { "Action", False },
3328 { "menuStep.Revert", False },
3329 { "menuStep.Move Now", False },
3330 { "menuStep.Retract Move", False },
3331 { "menuOptions.Auto Comment", False },
3332 { "menuOptions.Auto Flag", False },
3333 { "menuOptions.Auto Flip View", False },
3334 { "menuOptions.Auto Observe", False },
3335 { "menuOptions.Auto Raise Board", False },
3336 { "menuOptions.Get Move List", False },
3337 { "menuOptions.ICS Alarm", False },
3338 { "menuOptions.Move Sound", False },
3339 { "menuOptions.Quiet Play", False },
3340 { "menuOptions.Hide Thinking", False },
3341 { "menuOptions.Periodic Updates", False },
3342 { "menuOptions.Ponder Next Move", False },
3343 { "menuHelp.Hint", False },
3344 { "menuHelp.Book", False },
3348 Enables gnuEnables[] = {
3349 { "menuMode.ICS Client", False },
3350 { "menuMode.ICS Input Box", False },
3351 { "menuAction.Accept", False },
3352 { "menuAction.Decline", False },
3353 { "menuAction.Rematch", False },
3354 { "menuAction.Adjourn", False },
3355 { "menuAction.Stop Examining", False },
3356 { "menuAction.Stop Observing", False },
3357 { "menuStep.Revert", False },
3358 { "menuOptions.Auto Comment", False },
3359 { "menuOptions.Auto Observe", False },
3360 { "menuOptions.Auto Raise Board", False },
3361 { "menuOptions.Get Move List", False },
3362 { "menuOptions.Premove", False },
3363 { "menuOptions.Quiet Play", False },
3365 /* The next two options rely on SetCmailMode being called *after* */
3366 /* SetGNUMode so that when GNU is being used to give hints these */
3367 /* menu options are still available */
3369 { "menuFile.Mail Move", False },
3370 { "menuFile.Reload CMail Message", False },
3374 Enables cmailEnables[] = {
3376 { "menuAction.Call Flag", False },
3377 { "menuAction.Draw", True },
3378 { "menuAction.Adjourn", False },
3379 { "menuAction.Abort", False },
3380 { "menuAction.Stop Observing", False },
3381 { "menuAction.Stop Examining", False },
3382 { "menuFile.Mail Move", True },
3383 { "menuFile.Reload CMail Message", True },
3387 Enables trainingOnEnables[] = {
3388 { "menuMode.Edit Comment", False },
3389 { "menuMode.Pause", False },
3390 { "menuStep.Forward", False },
3391 { "menuStep.Backward", False },
3392 { "menuStep.Forward to End", False },
3393 { "menuStep.Back to Start", False },
3394 { "menuStep.Move Now", False },
3395 { "menuStep.Truncate Game", False },
3399 Enables trainingOffEnables[] = {
3400 { "menuMode.Edit Comment", True },
3401 { "menuMode.Pause", True },
3402 { "menuStep.Forward", True },
3403 { "menuStep.Backward", True },
3404 { "menuStep.Forward to End", True },
3405 { "menuStep.Back to Start", True },
3406 { "menuStep.Move Now", True },
3407 { "menuStep.Truncate Game", True },
3411 Enables machineThinkingEnables[] = {
3412 { "menuFile.Load Game", False },
3413 { "menuFile.Load Next Game", False },
3414 { "menuFile.Load Previous Game", False },
3415 { "menuFile.Reload Same Game", False },
3416 { "menuFile.Paste Game", False },
3417 { "menuFile.Load Position", False },
3418 { "menuFile.Load Next Position", False },
3419 { "menuFile.Load Previous Position", False },
3420 { "menuFile.Reload Same Position", False },
3421 { "menuFile.Paste Position", False },
3422 { "menuMode.Machine White", False },
3423 { "menuMode.Machine Black", False },
3424 { "menuMode.Two Machines", False },
3425 { "menuStep.Retract Move", False },
3429 Enables userThinkingEnables[] = {
3430 { "menuFile.Load Game", True },
3431 { "menuFile.Load Next Game", True },
3432 { "menuFile.Load Previous Game", True },
3433 { "menuFile.Reload Same Game", True },
3434 { "menuFile.Paste Game", True },
3435 { "menuFile.Load Position", True },
3436 { "menuFile.Load Next Position", True },
3437 { "menuFile.Load Previous Position", True },
3438 { "menuFile.Reload Same Position", True },
3439 { "menuFile.Paste Position", True },
3440 { "menuMode.Machine White", True },
3441 { "menuMode.Machine Black", True },
3442 { "menuMode.Two Machines", True },
3443 { "menuStep.Retract Move", True },
3449 SetMenuEnables(icsEnables);
3452 if (appData.zippyPlay && !appData.noChessProgram) /* [DM] icsEngineAnalyze */
3453 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Analysis Mode"), True);
3460 SetMenuEnables(ncpEnables);
3466 SetMenuEnables(gnuEnables);
3472 SetMenuEnables(cmailEnables);
3478 SetMenuEnables(trainingOnEnables);
3479 if (appData.showButtonBar) {
3480 XtSetSensitive(buttonBarWidget, False);
3486 SetTrainingModeOff()
3488 SetMenuEnables(trainingOffEnables);
3489 if (appData.showButtonBar) {
3490 XtSetSensitive(buttonBarWidget, True);
3495 SetUserThinkingEnables()
3497 if (appData.noChessProgram) return;
3498 SetMenuEnables(userThinkingEnables);
3502 SetMachineThinkingEnables()
3504 if (appData.noChessProgram) return;
3505 SetMenuEnables(machineThinkingEnables);
3507 case MachinePlaysBlack:
3508 case MachinePlaysWhite:
3509 case TwoMachinesPlay:
3510 XtSetSensitive(XtNameToWidget(menuBarWidget,
3511 ModeToWidgetName(gameMode)), True);
3518 #define Abs(n) ((n)<0 ? -(n) : (n))
3521 * Find a font that matches "pattern" that is as close as
3522 * possible to the targetPxlSize. Prefer fonts that are k
3523 * pixels smaller to fonts that are k pixels larger. The
3524 * pattern must be in the X Consortium standard format,
3525 * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".
3526 * The return value should be freed with XtFree when no
3529 char *FindFont(pattern, targetPxlSize)
3533 char **fonts, *p, *best, *scalable, *scalableTail;
3534 int i, j, nfonts, minerr, err, pxlSize;
3537 char **missing_list;
3539 char *def_string, *base_fnt_lst, strInt[3];
3541 XFontStruct **fnt_list;
3543 base_fnt_lst = calloc(1, strlen(pattern) + 3);
3544 sprintf(strInt, "%d", targetPxlSize);
3545 p = strstr(pattern, "--");
3546 strncpy(base_fnt_lst, pattern, p - pattern + 2);
3547 strcat(base_fnt_lst, strInt);
3548 strcat(base_fnt_lst, strchr(p + 2, '-'));
3550 if ((fntSet = XCreateFontSet(xDisplay,
3554 &def_string)) == NULL) {
3556 fprintf(stderr, _("Unable to create font set.\n"));
3560 nfonts = XFontsOfFontSet(fntSet, &fnt_list, &fonts);
3562 fonts = XListFonts(xDisplay, pattern, 999999, &nfonts);
3564 fprintf(stderr, _("%s: no fonts match pattern %s\n"),
3565 programName, pattern);
3573 for (i=0; i<nfonts; i++) {
3576 if (*p != '-') continue;
3578 if (*p == NULLCHAR) break;
3579 if (*p++ == '-') j++;
3581 if (j < 7) continue;
3584 scalable = fonts[i];
3587 err = pxlSize - targetPxlSize;
3588 if (Abs(err) < Abs(minerr) ||
3589 (minerr > 0 && err < 0 && -err == minerr)) {
3595 if (scalable && Abs(minerr) > appData.fontSizeTolerance) {
3596 /* If the error is too big and there is a scalable font,
3597 use the scalable font. */
3598 int headlen = scalableTail - scalable;
3599 p = (char *) XtMalloc(strlen(scalable) + 10);
3600 while (isdigit(*scalableTail)) scalableTail++;
3601 sprintf(p, "%.*s%d%s", headlen, scalable, targetPxlSize, scalableTail);
3603 p = (char *) XtMalloc(strlen(best) + 1);
3606 if (appData.debugMode) {
3607 fprintf(debugFP, _("resolved %s at pixel size %d\n to %s\n"),
3608 pattern, targetPxlSize, p);
3611 if (missing_count > 0)
3612 XFreeStringList(missing_list);
3613 XFreeFontSet(xDisplay, fntSet);
3615 XFreeFontNames(fonts);
3622 XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
3623 | GCBackground | GCFunction | GCPlaneMask;
3624 XGCValues gc_values;
3627 gc_values.plane_mask = AllPlanes;
3628 gc_values.line_width = lineGap;
3629 gc_values.line_style = LineSolid;
3630 gc_values.function = GXcopy;
3632 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3633 gc_values.background = XBlackPixel(xDisplay, xScreen);
3634 lineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3636 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3637 gc_values.background = XWhitePixel(xDisplay, xScreen);
3638 coordGC = XtGetGC(shellWidget, value_mask, &gc_values);
3639 XSetFont(xDisplay, coordGC, coordFontID);
3641 // [HGM] make font for holdings counts (white on black0
3642 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3643 gc_values.background = XBlackPixel(xDisplay, xScreen);
3644 countGC = XtGetGC(shellWidget, value_mask, &gc_values);
3645 XSetFont(xDisplay, countGC, countFontID);
3647 if (appData.monoMode) {
3648 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3649 gc_values.background = XWhitePixel(xDisplay, xScreen);
3650 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3652 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3653 gc_values.background = XBlackPixel(xDisplay, xScreen);
3654 lightSquareGC = wbPieceGC
3655 = XtGetGC(shellWidget, value_mask, &gc_values);
3657 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3658 gc_values.background = XWhitePixel(xDisplay, xScreen);
3659 darkSquareGC = bwPieceGC
3660 = XtGetGC(shellWidget, value_mask, &gc_values);
3662 if (DefaultDepth(xDisplay, xScreen) == 1) {
3663 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
3664 gc_values.function = GXcopyInverted;
3665 copyInvertedGC = XtGetGC(shellWidget, value_mask, &gc_values);
3666 gc_values.function = GXcopy;
3667 if (XBlackPixel(xDisplay, xScreen) == 1) {
3668 bwPieceGC = darkSquareGC;
3669 wbPieceGC = copyInvertedGC;
3671 bwPieceGC = copyInvertedGC;
3672 wbPieceGC = lightSquareGC;
3676 gc_values.foreground = highlightSquareColor;
3677 gc_values.background = highlightSquareColor;
3678 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3680 gc_values.foreground = premoveHighlightColor;
3681 gc_values.background = premoveHighlightColor;
3682 prelineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3684 gc_values.foreground = lightSquareColor;
3685 gc_values.background = darkSquareColor;
3686 lightSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3688 gc_values.foreground = darkSquareColor;
3689 gc_values.background = lightSquareColor;
3690 darkSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3692 gc_values.foreground = jailSquareColor;
3693 gc_values.background = jailSquareColor;
3694 jailSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3696 gc_values.foreground = whitePieceColor;
3697 gc_values.background = darkSquareColor;
3698 wdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3700 gc_values.foreground = whitePieceColor;
3701 gc_values.background = lightSquareColor;
3702 wlPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3704 gc_values.foreground = whitePieceColor;
3705 gc_values.background = jailSquareColor;
3706 wjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3708 gc_values.foreground = blackPieceColor;
3709 gc_values.background = darkSquareColor;
3710 bdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3712 gc_values.foreground = blackPieceColor;
3713 gc_values.background = lightSquareColor;
3714 blPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3716 gc_values.foreground = blackPieceColor;
3717 gc_values.background = jailSquareColor;
3718 bjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3722 void loadXIM(xim, xmask, filename, dest, mask)
3735 fp = fopen(filename, "rb");
3737 fprintf(stderr, _("%s: error loading XIM!\n"), programName);
3744 for (y=0; y<h; ++y) {
3745 for (x=0; x<h; ++x) {
3750 XPutPixel(xim, x, y, blackPieceColor);
3752 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3755 XPutPixel(xim, x, y, darkSquareColor);
3757 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3760 XPutPixel(xim, x, y, whitePieceColor);
3762 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3765 XPutPixel(xim, x, y, lightSquareColor);
3767 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3773 /* create Pixmap of piece */
3774 *dest = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3776 XPutImage(xDisplay, *dest, lightSquareGC, xim,
3779 /* create Pixmap of clipmask
3780 Note: We assume the white/black pieces have the same
3781 outline, so we make only 6 masks. This is okay
3782 since the XPM clipmask routines do the same. */
3784 temp = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3786 XPutImage(xDisplay, temp, lightSquareGC, xmask,
3789 /* now create the 1-bit version */
3790 *mask = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3793 values.foreground = 1;
3794 values.background = 0;
3796 /* Don't use XtGetGC, not read only */
3797 maskGC = XCreateGC(xDisplay, *mask,
3798 GCForeground | GCBackground, &values);
3799 XCopyPlane(xDisplay, temp, *mask, maskGC,
3800 0, 0, squareSize, squareSize, 0, 0, 1);
3801 XFreePixmap(xDisplay, temp);
3806 char pieceBitmapNames[] = "pnbrqfeacwmohijgdvlsukpnsl";
3808 void CreateXIMPieces()
3813 static char *ximkind[] = { "ll", "ld", "dl", "dd" };
3818 /* The XSynchronize calls were copied from CreatePieces.
3819 Not sure if needed, but can't hurt */
3820 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3823 /* temp needed by loadXIM() */
3824 ximtemp = XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3825 0, 0, ss, ss, AllPlanes, XYPixmap);
3827 if (strlen(appData.pixmapDirectory) == 0) {
3831 if (appData.monoMode) {
3832 DisplayFatalError(_("XIM pieces cannot be used in monochrome mode"),
3836 fprintf(stderr, _("\nLoading XIMs...\n"));
3838 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3839 fprintf(stderr, "%d", piece+1);
3840 for (kind=0; kind<4; kind++) {
3841 fprintf(stderr, ".");
3842 snprintf(buf, sizeof(buf), "%s/%s%c%s%u.xim",
3843 ExpandPathName(appData.pixmapDirectory),
3844 piece <= (int) WhiteKing ? "" : "w",
3845 pieceBitmapNames[piece],
3847 ximPieceBitmap[kind][piece] =
3848 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3849 0, 0, ss, ss, AllPlanes, XYPixmap);
3850 if (appData.debugMode)
3851 fprintf(stderr, _("(File:%s:) "), buf);
3852 loadXIM(ximPieceBitmap[kind][piece],
3854 &(xpmPieceBitmap2[kind][piece]),
3855 &(ximMaskPm2[piece]));
3856 if(piece <= (int)WhiteKing)
3857 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3859 fprintf(stderr," ");
3861 /* Load light and dark squares */
3862 /* If the LSQ and DSQ pieces don't exist, we will
3863 draw them with solid squares. */
3864 snprintf(buf,sizeof(buf), "%s/lsq%u.xim", ExpandPathName(appData.pixmapDirectory), ss);
3865 if (access(buf, 0) != 0) {
3869 fprintf(stderr, _("light square "));
3871 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3872 0, 0, ss, ss, AllPlanes, XYPixmap);
3873 if (appData.debugMode)
3874 fprintf(stderr, _("(File:%s:) "), buf);
3876 loadXIM(ximLightSquare, NULL, buf, &xpmLightSquare, NULL);
3877 fprintf(stderr, _("dark square "));
3878 snprintf(buf,sizeof(buf), "%s/dsq%u.xim",
3879 ExpandPathName(appData.pixmapDirectory), ss);
3880 if (appData.debugMode)
3881 fprintf(stderr, _("(File:%s:) "), buf);
3883 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3884 0, 0, ss, ss, AllPlanes, XYPixmap);
3885 loadXIM(ximDarkSquare, NULL, buf, &xpmDarkSquare, NULL);
3886 xpmJailSquare = xpmLightSquare;
3888 fprintf(stderr, _("Done.\n"));
3890 XSynchronize(xDisplay, False); /* Work-around for xlib/xt buffering bug */
3894 void CreateXPMPieces()
3898 u_int ss = squareSize;
3900 static char *xpmkind[] = { "ll", "ld", "dl", "dd" };
3901 XpmColorSymbol symbols[4];
3903 /* The XSynchronize calls were copied from CreatePieces.
3904 Not sure if needed, but can't hurt */
3905 XSynchronize(xDisplay, True); /* Work-around for xlib/xt buffering bug */
3907 /* Setup translations so piece colors match square colors */
3908 symbols[0].name = "light_piece";
3909 symbols[0].value = appData.whitePieceColor;
3910 symbols[1].name = "dark_piece";
3911 symbols[1].value = appData.blackPieceColor;
3912 symbols[2].name = "light_square";
3913 symbols[2].value = appData.lightSquareColor;
3914 symbols[3].name = "dark_square";
3915 symbols[3].value = appData.darkSquareColor;
3917 attr.valuemask = XpmColorSymbols;
3918 attr.colorsymbols = symbols;
3919 attr.numsymbols = 4;
3921 if (appData.monoMode) {
3922 DisplayFatalError(_("XPM pieces cannot be used in monochrome mode"),
3926 if (strlen(appData.pixmapDirectory) == 0) {
3927 XpmPieces* pieces = builtInXpms;
3930 while (pieces->size != squareSize && pieces->size) pieces++;
3931 if (!pieces->size) {
3932 fprintf(stderr, _("No builtin XPM pieces of size %d\n"), squareSize);
3935 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3936 for (kind=0; kind<4; kind++) {
3938 if ((r=XpmCreatePixmapFromData(xDisplay, xBoardWindow,
3939 pieces->xpm[piece][kind],
3940 &(xpmPieceBitmap2[kind][piece]),
3941 NULL, &attr)) != 0) {
3942 fprintf(stderr, _("Error %d loading XPM image \"%s\"\n"),
3946 if(piece <= (int) WhiteKing)
3947 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3951 xpmJailSquare = xpmLightSquare;
3955 fprintf(stderr, _("\nLoading XPMs...\n"));
3958 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3959 fprintf(stderr, "%d ", piece+1);
3960 for (kind=0; kind<4; kind++) {
3961 snprintf(buf, sizeof(buf), "%s/%s%c%s%u.xpm",
3962 ExpandPathName(appData.pixmapDirectory),
3963 piece > (int) WhiteKing ? "w" : "",
3964 pieceBitmapNames[piece],
3966 if (appData.debugMode) {
3967 fprintf(stderr, _("(File:%s:) "), buf);
3969 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3970 &(xpmPieceBitmap2[kind][piece]),
3971 NULL, &attr)) != 0) {
3972 if(piece != (int)WhiteKing && piece > (int)WhiteQueen) {
3973 // [HGM] missing: read of unorthodox piece failed; substitute King.
3974 snprintf(buf, sizeof(buf), "%s/k%s%u.xpm",
3975 ExpandPathName(appData.pixmapDirectory),
3977 if (appData.debugMode) {
3978 fprintf(stderr, _("(Replace by File:%s:) "), buf);
3980 r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3981 &(xpmPieceBitmap2[kind][piece]),
3985 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"),
3990 if(piece <= (int) WhiteKing)
3991 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3994 /* Load light and dark squares */
3995 /* If the LSQ and DSQ pieces don't exist, we will
3996 draw them with solid squares. */
3997 fprintf(stderr, _("light square "));
3998 snprintf(buf, sizeof(buf), "%s/lsq%u.xpm", ExpandPathName(appData.pixmapDirectory), ss);
3999 if (access(buf, 0) != 0) {
4003 if (appData.debugMode)
4004 fprintf(stderr, _("(File:%s:) "), buf);
4006 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
4007 &xpmLightSquare, NULL, &attr)) != 0) {
4008 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
4011 fprintf(stderr, _("dark square "));
4012 snprintf(buf, sizeof(buf), "%s/dsq%u.xpm",
4013 ExpandPathName(appData.pixmapDirectory), ss);
4014 if (appData.debugMode) {
4015 fprintf(stderr, _("(File:%s:) "), buf);
4017 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
4018 &xpmDarkSquare, NULL, &attr)) != 0) {
4019 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
4023 xpmJailSquare = xpmLightSquare;
4024 fprintf(stderr, _("Done.\n"));
4026 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
4029 #endif /* HAVE_LIBXPM */
4032 /* No built-in bitmaps */
4037 u_int ss = squareSize;
4039 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
4042 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
4043 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
4044 sprintf(buf, "%s%c%u%c.bm", piece > (int)WhiteKing ? "w" : "",
4045 pieceBitmapNames[piece],
4046 ss, kind == SOLID ? 's' : 'o');
4047 ReadBitmap(&pieceBitmap2[kind][piece], buf, NULL, ss, ss);
4048 if(piece <= (int)WhiteKing)
4049 pieceBitmap[kind][piece] = pieceBitmap2[kind][piece];
4053 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
4057 /* With built-in bitmaps */
4060 BuiltInBits* bib = builtInBits;
4063 u_int ss = squareSize;
4065 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
4068 while (bib->squareSize != ss && bib->squareSize != 0) bib++;
4070 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
4071 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
4072 sprintf(buf, "%s%c%u%c.bm", piece > (int)WhiteKing ? "w" : "",
4073 pieceBitmapNames[piece],
4074 ss, kind == SOLID ? 's' : 'o');
4075 ReadBitmap(&pieceBitmap2[kind][piece], buf,
4076 bib->bits[kind][piece], ss, ss);
4077 if(piece <= (int)WhiteKing)
4078 pieceBitmap[kind][piece] = pieceBitmap2[kind][piece];
4082 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
4087 void ReadBitmap(pm, name, bits, wreq, hreq)
4090 unsigned char bits[];
4096 char msg[MSG_SIZ], fullname[MSG_SIZ];
4098 if (*appData.bitmapDirectory != NULLCHAR) {
4099 strcpy(fullname, appData.bitmapDirectory);
4100 strcat(fullname, "/");
4101 strcat(fullname, name);
4102 errcode = XReadBitmapFile(xDisplay, xBoardWindow, fullname,
4103 &w, &h, pm, &x_hot, &y_hot);
4104 fprintf(stderr, "load %s\n", name);
4105 if (errcode != BitmapSuccess) {
4107 case BitmapOpenFailed:
4108 snprintf(msg, sizeof(msg), _("Can't open bitmap file %s"), fullname);
4110 case BitmapFileInvalid:
4111 snprintf(msg, sizeof(msg), _("Invalid bitmap in file %s"), fullname);
4113 case BitmapNoMemory:
4114 snprintf(msg, sizeof(msg), _("Ran out of memory reading bitmap file %s"),
4118 snprintf(msg, sizeof(msg), _("Unknown XReadBitmapFile error %d on file %s"),
4122 fprintf(stderr, _("%s: %s...using built-in\n"),
4124 } else if (w != wreq || h != hreq) {
4126 _("%s: Bitmap %s is %dx%d, not %dx%d...using built-in\n"),
4127 programName, fullname, w, h, wreq, hreq);
4133 *pm = XCreateBitmapFromData(xDisplay, xBoardWindow, (char *) bits,
4142 if (lineGap == 0) return;
4144 /* [HR] Split this into 2 loops for non-square boards. */
4146 for (i = 0; i < BOARD_HEIGHT + 1; i++) {
4147 gridSegments[i].x1 = 0;
4148 gridSegments[i].x2 =
4149 lineGap + BOARD_WIDTH * (squareSize + lineGap);
4150 gridSegments[i].y1 = gridSegments[i].y2
4151 = lineGap / 2 + (i * (squareSize + lineGap));
4154 for (j = 0; j < BOARD_WIDTH + 1; j++) {
4155 gridSegments[j + i].y1 = 0;
4156 gridSegments[j + i].y2 =
4157 lineGap + BOARD_HEIGHT * (squareSize + lineGap);
4158 gridSegments[j + i].x1 = gridSegments[j + i].x2
4159 = lineGap / 2 + (j * (squareSize + lineGap));
4163 static void MenuBarSelect(w, addr, index)
4168 XtActionProc proc = (XtActionProc) addr;
4170 (proc)(NULL, NULL, NULL, NULL);
4173 void CreateMenuBarPopup(parent, name, mb)
4183 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
4186 XtSetArg(args[j], XtNleftMargin, 20); j++;
4187 XtSetArg(args[j], XtNrightMargin, 20); j++;
4189 while (mi->string != NULL) {
4190 if (strcmp(mi->string, "----") == 0) {
4191 entry = XtCreateManagedWidget(mi->string, smeLineObjectClass,
4194 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string)));
4195 entry = XtCreateManagedWidget(mi->string, smeBSBObjectClass,
4197 XtAddCallback(entry, XtNcallback,
4198 (XtCallbackProc) MenuBarSelect,
4199 (caddr_t) mi->proc);
4205 Widget CreateMenuBar(mb)
4209 Widget anchor, menuBar;
4211 char menuName[MSG_SIZ];
4214 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
4215 XtSetArg(args[j], XtNvSpace, 0); j++;
4216 XtSetArg(args[j], XtNborderWidth, 0); j++;
4217 menuBar = XtCreateWidget("menuBar", boxWidgetClass,
4218 formWidget, args, j);
4220 while (mb->name != NULL) {
4221 strcpy(menuName, "menu");
4222 strcat(menuName, mb->name);
4224 XtSetArg(args[j], XtNmenuName, XtNewString(menuName)); j++;
4227 shortName[0] = _(mb->name)[0];
4228 shortName[1] = NULLCHAR;
4229 XtSetArg(args[j], XtNlabel, XtNewString(shortName)); j++;
4232 XtSetArg(args[j], XtNlabel, XtNewString(_(mb->name))); j++;
4235 XtSetArg(args[j], XtNborderWidth, 0); j++;
4236 anchor = XtCreateManagedWidget(mb->name, menuButtonWidgetClass,
4238 CreateMenuBarPopup(menuBar, menuName, mb);
4244 Widget CreateButtonBar(mi)
4248 Widget button, buttonBar;
4252 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
4254 XtSetArg(args[j], XtNhSpace, 0); j++;
4256 XtSetArg(args[j], XtNborderWidth, 0); j++;
4257 XtSetArg(args[j], XtNvSpace, 0); j++;
4258 buttonBar = XtCreateWidget("buttonBar", boxWidgetClass,
4259 formWidget, args, j);
4261 while (mi->string != NULL) {
4264 XtSetArg(args[j], XtNinternalWidth, 2); j++;
4265 XtSetArg(args[j], XtNborderWidth, 0); j++;
4267 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string))); j++;
4268 button = XtCreateManagedWidget(mi->string, commandWidgetClass,
4269 buttonBar, args, j);
4270 XtAddCallback(button, XtNcallback,
4271 (XtCallbackProc) MenuBarSelect,
4272 (caddr_t) mi->proc);
4279 CreatePieceMenu(name, color)
4286 ChessSquare selection;
4288 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
4289 boardWidget, args, 0);
4291 for (i = 0; i < PIECE_MENU_SIZE; i++) {
4292 String item = pieceMenuStrings[color][i];
4294 if (strcmp(item, "----") == 0) {
4295 entry = XtCreateManagedWidget(item, smeLineObjectClass,
4298 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
4299 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
4301 selection = pieceMenuTranslation[color][i];
4302 XtAddCallback(entry, XtNcallback,
4303 (XtCallbackProc) PieceMenuSelect,
4304 (caddr_t) selection);
4305 if (selection == WhitePawn || selection == BlackPawn) {
4306 XtSetArg(args[0], XtNpopupOnEntry, entry);
4307 XtSetValues(menu, args, 1);
4320 ChessSquare selection;
4322 whitePieceMenu = CreatePieceMenu("menuW", 0);
4323 blackPieceMenu = CreatePieceMenu("menuB", 1);
4325 XtRegisterGrabAction(PieceMenuPopup, True,
4326 (unsigned)(ButtonPressMask|ButtonReleaseMask),
4327 GrabModeAsync, GrabModeAsync);
4329 XtSetArg(args[0], XtNlabel, _("Drop"));
4330 dropMenu = XtCreatePopupShell("menuD", simpleMenuWidgetClass,
4331 boardWidget, args, 1);
4332 for (i = 0; i < DROP_MENU_SIZE; i++) {
4333 String item = dropMenuStrings[i];
4335 if (strcmp(item, "----") == 0) {
4336 entry = XtCreateManagedWidget(item, smeLineObjectClass,
4339 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
4340 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
4342 selection = dropMenuTranslation[i];
4343 XtAddCallback(entry, XtNcallback,
4344 (XtCallbackProc) DropMenuSelect,
4345 (caddr_t) selection);
4350 void SetupDropMenu()
4358 for (i=0; i<sizeof(dmEnables)/sizeof(DropMenuEnables); i++) {
4359 entry = XtNameToWidget(dropMenu, dmEnables[i].widget);
4360 p = strchr(gameMode == IcsPlayingWhite ? white_holding : black_holding,
4361 dmEnables[i].piece);
4362 XtSetSensitive(entry, p != NULL || !appData.testLegality
4363 /*!!temp:*/ || (gameInfo.variant == VariantCrazyhouse
4364 && !appData.icsActive));
4366 while (p && *p++ == dmEnables[i].piece) count++;
4367 snprintf(label, sizeof(label), "%s %d", dmEnables[i].widget, count);
4369 XtSetArg(args[j], XtNlabel, label); j++;
4370 XtSetValues(entry, args, j);
4374 void PieceMenuPopup(w, event, params, num_params)
4378 Cardinal *num_params;
4381 if (event->type != ButtonPress) return;
4382 if (errorUp) ErrorPopDown();
4386 whichMenu = params[0];
4388 case IcsPlayingWhite:
4389 case IcsPlayingBlack:
4391 case MachinePlaysWhite:
4392 case MachinePlaysBlack:
4393 if (appData.testLegality &&
4394 gameInfo.variant != VariantBughouse &&
4395 gameInfo.variant != VariantCrazyhouse) return;
4397 whichMenu = "menuD";
4403 if (((pmFromX = EventToSquare(event->xbutton.x, BOARD_WIDTH)) < 0) ||
4404 ((pmFromY = EventToSquare(event->xbutton.y, BOARD_HEIGHT)) < 0)) {
4405 pmFromX = pmFromY = -1;
4409 pmFromX = BOARD_WIDTH - 1 - pmFromX;
4411 pmFromY = BOARD_HEIGHT - 1 - pmFromY;
4413 XtPopupSpringLoaded(XtNameToWidget(boardWidget, whichMenu));
4416 static void PieceMenuSelect(w, piece, junk)
4421 if (pmFromX < 0 || pmFromY < 0) return;
4422 EditPositionMenuEvent(piece, pmFromX, pmFromY);
4425 static void DropMenuSelect(w, piece, junk)
4430 if (pmFromX < 0 || pmFromY < 0) return;
4431 DropMenuEvent(piece, pmFromX, pmFromY);
4434 void WhiteClock(w, event, prms, nprms)
4440 if (gameMode == EditPosition || gameMode == IcsExamining) {
4441 SetWhiteToPlayEvent();
4442 } else if (gameMode == IcsPlayingBlack || gameMode == MachinePlaysWhite) {
4447 void BlackClock(w, event, prms, nprms)
4453 if (gameMode == EditPosition || gameMode == IcsExamining) {
4454 SetBlackToPlayEvent();
4455 } else if (gameMode == IcsPlayingWhite || gameMode == MachinePlaysBlack) {
4462 * If the user selects on a border boundary, return -1; if off the board,
4463 * return -2. Otherwise map the event coordinate to the square.
4465 int EventToSquare(x, limit)
4473 if ((x % (squareSize + lineGap)) >= squareSize)
4475 x /= (squareSize + lineGap);
4481 static void do_flash_delay(msec)
4487 static void drawHighlight(file, rank, gc)
4493 if (lineGap == 0 || appData.blindfold) return;
4496 x = lineGap/2 + ((BOARD_WIDTH-1)-file) *
4497 (squareSize + lineGap);
4498 y = lineGap/2 + rank * (squareSize + lineGap);
4500 x = lineGap/2 + file * (squareSize + lineGap);
4501 y = lineGap/2 + ((BOARD_HEIGHT-1)-rank) *
4502 (squareSize + lineGap);
4505 XDrawRectangle(xDisplay, xBoardWindow, gc, x, y,
4506 squareSize+lineGap, squareSize+lineGap);
4509 int hi1X = -1, hi1Y = -1, hi2X = -1, hi2Y = -1;
4510 int pm1X = -1, pm1Y = -1, pm2X = -1, pm2Y = -1;
4513 SetHighlights(fromX, fromY, toX, toY)
4514 int fromX, fromY, toX, toY;
4516 if (hi1X != fromX || hi1Y != fromY) {
4517 if (hi1X >= 0 && hi1Y >= 0) {
4518 drawHighlight(hi1X, hi1Y, lineGC);
4520 if (fromX >= 0 && fromY >= 0) {
4521 drawHighlight(fromX, fromY, highlineGC);
4524 if (hi2X != toX || hi2Y != toY) {
4525 if (hi2X >= 0 && hi2Y >= 0) {
4526 drawHighlight(hi2X, hi2Y, lineGC);
4528 if (toX >= 0 && toY >= 0) {
4529 drawHighlight(toX, toY, highlineGC);
4541 SetHighlights(-1, -1, -1, -1);
4546 SetPremoveHighlights(fromX, fromY, toX, toY)
4547 int fromX, fromY, toX, toY;
4549 if (pm1X != fromX || pm1Y != fromY) {
4550 if (pm1X >= 0 && pm1Y >= 0) {
4551 drawHighlight(pm1X, pm1Y, lineGC);
4553 if (fromX >= 0 && fromY >= 0) {
4554 drawHighlight(fromX, fromY, prelineGC);
4557 if (pm2X != toX || pm2Y != toY) {
4558 if (pm2X >= 0 && pm2Y >= 0) {
4559 drawHighlight(pm2X, pm2Y, lineGC);
4561 if (toX >= 0 && toY >= 0) {
4562 drawHighlight(toX, toY, prelineGC);
4572 ClearPremoveHighlights()
4574 SetPremoveHighlights(-1, -1, -1, -1);
4577 static void BlankSquare(x, y, color, piece, dest)
4582 if (useImages && useImageSqs) {
4586 pm = xpmLightSquare;
4591 case 2: /* neutral */
4596 XCopyArea(xDisplay, pm, dest, wlPieceGC, 0, 0,
4597 squareSize, squareSize, x, y);
4607 case 2: /* neutral */
4612 XFillRectangle(xDisplay, dest, gc, x, y, squareSize, squareSize);
4617 I split out the routines to draw a piece so that I could
4618 make a generic flash routine.
4620 static void monoDrawPiece_1bit(piece, square_color, x, y, dest)
4622 int square_color, x, y;
4625 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
4626 switch (square_color) {
4628 case 2: /* neutral */
4630 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
4631 ? *pieceToOutline(piece)
4632 : *pieceToSolid(piece),
4633 dest, bwPieceGC, 0, 0,
4634 squareSize, squareSize, x, y);
4637 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
4638 ? *pieceToSolid(piece)
4639 : *pieceToOutline(piece),
4640 dest, wbPieceGC, 0, 0,
4641 squareSize, squareSize, x, y);
4646 static void monoDrawPiece(piece, square_color, x, y, dest)
4648 int square_color, x, y;
4651 switch (square_color) {
4653 case 2: /* neutral */
4655 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
4656 ? *pieceToOutline(piece)
4657 : *pieceToSolid(piece),
4658 dest, bwPieceGC, 0, 0,
4659 squareSize, squareSize, x, y, 1);
4662 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
4663 ? *pieceToSolid(piece)
4664 : *pieceToOutline(piece),
4665 dest, wbPieceGC, 0, 0,
4666 squareSize, squareSize, x, y, 1);
4671 static void colorDrawPiece(piece, square_color, x, y, dest)
4673 int square_color, x, y;
4676 if(pieceToSolid(piece) == NULL) return; // [HGM] bitmaps: make it non-fatal if we have no bitmap;
4677 switch (square_color) {
4679 XCopyPlane(xDisplay, *pieceToSolid(piece),
4680 dest, (int) piece < (int) BlackPawn
4681 ? wlPieceGC : blPieceGC, 0, 0,
4682 squareSize, squareSize, x, y, 1);
4685 XCopyPlane(xDisplay, *pieceToSolid(piece),
4686 dest, (int) piece < (int) BlackPawn
4687 ? wdPieceGC : bdPieceGC, 0, 0,
4688 squareSize, squareSize, x, y, 1);
4690 case 2: /* neutral */
4692 XCopyPlane(xDisplay, *pieceToSolid(piece),
4693 dest, (int) piece < (int) BlackPawn
4694 ? wjPieceGC : bjPieceGC, 0, 0,
4695 squareSize, squareSize, x, y, 1);
4700 static void colorDrawPieceImage(piece, square_color, x, y, dest)
4702 int square_color, x, y;
4707 switch (square_color) {
4709 case 2: /* neutral */
4711 if ((int)piece < (int) BlackPawn) {
4719 if ((int)piece < (int) BlackPawn) {
4727 XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
4728 dest, wlPieceGC, 0, 0,
4729 squareSize, squareSize, x, y);
4732 typedef void (*DrawFunc)();
4734 DrawFunc ChooseDrawFunc()
4736 if (appData.monoMode) {
4737 if (DefaultDepth(xDisplay, xScreen) == 1) {
4738 return monoDrawPiece_1bit;
4740 return monoDrawPiece;
4744 return colorDrawPieceImage;
4746 return colorDrawPiece;
4750 /* [HR] determine square color depending on chess variant. */
4751 static int SquareColor(row, column)
4756 if (gameInfo.variant == VariantXiangqi) {
4757 if (column >= 3 && column <= 5 && row >= 0 && row <= 2) {
4759 } else if (column >= 3 && column <= 5 && row >= 7 && row <= 9) {
4761 } else if (row <= 4) {
4767 square_color = ((column + row) % 2) == 1;
4770 /* [hgm] holdings: next line makes all holdings squares light */
4771 if(column < BOARD_LEFT || column >= BOARD_RGHT) square_color = 1;
4773 return square_color;
4776 void DrawSquare(row, column, piece, do_flash)
4777 int row, column, do_flash;
4780 int square_color, x, y, direction, font_ascent, font_descent;
4783 XCharStruct overall;
4787 /* Calculate delay in milliseconds (2-delays per complete flash) */
4788 flash_delay = 500 / appData.flashRate;
4791 x = lineGap + ((BOARD_WIDTH-1)-column) *
4792 (squareSize + lineGap);
4793 y = lineGap + row * (squareSize + lineGap);
4795 x = lineGap + column * (squareSize + lineGap);
4796 y = lineGap + ((BOARD_HEIGHT-1)-row) *
4797 (squareSize + lineGap);
4800 square_color = SquareColor(row, column);
4802 if ( // [HGM] holdings: blank out area between board and holdings
4803 column == BOARD_LEFT-1 || column == BOARD_RGHT
4804 || (column == BOARD_LEFT-2 && row < BOARD_HEIGHT-gameInfo.holdingsSize)
4805 || (column == BOARD_RGHT+1 && row >= gameInfo.holdingsSize) ) {
4806 BlankSquare(x, y, 2, EmptySquare, xBoardWindow);
4808 // [HGM] print piece counts next to holdings
4809 string[1] = NULLCHAR;
4810 if (column == (flipView ? BOARD_LEFT-1 : BOARD_RGHT) && piece > 1 ) {
4811 string[0] = '0' + piece;
4812 XTextExtents(countFontStruct, string, 1, &direction,
4813 &font_ascent, &font_descent, &overall);
4814 if (appData.monoMode) {
4815 XDrawImageString(xDisplay, xBoardWindow, countGC,
4816 x + squareSize - overall.width - 2,
4817 y + font_ascent + 1, string, 1);
4819 XDrawString(xDisplay, xBoardWindow, countGC,
4820 x + squareSize - overall.width - 2,
4821 y + font_ascent + 1, string, 1);
4824 if (column == (flipView ? BOARD_RGHT : BOARD_LEFT-1) && piece > 1) {
4825 string[0] = '0' + piece;
4826 XTextExtents(countFontStruct, string, 1, &direction,
4827 &font_ascent, &font_descent, &overall);
4828 if (appData.monoMode) {
4829 XDrawImageString(xDisplay, xBoardWindow, countGC,
4830 x + 2, y + font_ascent + 1, string, 1);
4832 XDrawString(xDisplay, xBoardWindow, countGC,
4833 x + 2, y + font_ascent + 1, string, 1);
4837 if (piece == EmptySquare || appData.blindfold) {
4838 BlankSquare(x, y, square_color, piece, xBoardWindow);
4840 drawfunc = ChooseDrawFunc();
4841 if (do_flash && appData.flashCount > 0) {
4842 for (i=0; i<appData.flashCount; ++i) {
4844 drawfunc(piece, square_color, x, y, xBoardWindow);
4845 XSync(xDisplay, False);
4846 do_flash_delay(flash_delay);
4848 BlankSquare(x, y, square_color, piece, xBoardWindow);
4849 XSync(xDisplay, False);
4850 do_flash_delay(flash_delay);
4853 drawfunc(piece, square_color, x, y, xBoardWindow);
4857 string[1] = NULLCHAR;
4858 if (appData.showCoords && row == (flipView ? BOARD_HEIGHT-1 : 0)
4859 && column >= BOARD_LEFT && column < BOARD_RGHT) {
4860 string[0] = 'a' + column - BOARD_LEFT;
4861 XTextExtents(coordFontStruct, string, 1, &direction,
4862 &font_ascent, &font_descent, &overall);
4863 if (appData.monoMode) {
4864 XDrawImageString(xDisplay, xBoardWindow, coordGC,
4865 x + squareSize - overall.width - 2,
4866 y + squareSize - font_descent - 1, string, 1);
4868 XDrawString(xDisplay, xBoardWindow, coordGC,
4869 x + squareSize - overall.width - 2,
4870 y + squareSize - font_descent - 1, string, 1);
4873 if (appData.showCoords && column == (flipView ? BOARD_RGHT-1 : BOARD_LEFT)) {
4874 string[0] = ONE + row;
4875 XTextExtents(coordFontStruct, string, 1, &direction,
4876 &font_ascent, &font_descent, &overall);
4877 if (appData.monoMode) {
4878 XDrawImageString(xDisplay, xBoardWindow, coordGC,
4879 x + 2, y + font_ascent + 1, string, 1);
4881 XDrawString(xDisplay, xBoardWindow, coordGC,
4882 x + 2, y + font_ascent + 1, string, 1);
4888 /* Why is this needed on some versions of X? */
4889 void EventProc(widget, unused, event)
4894 if (!XtIsRealized(widget))
4897 switch (event->type) {
4899 if (event->xexpose.count > 0) return; /* no clipping is done */
4900 XDrawPosition(widget, True, NULL);
4908 void DrawPosition(fullRedraw, board)
4909 /*Boolean*/int fullRedraw;
4912 XDrawPosition(boardWidget, fullRedraw, board);
4915 /* Returns 1 if there are "too many" differences between b1 and b2
4916 (i.e. more than 1 move was made) */
4917 static int too_many_diffs(b1, b2)
4923 for (i=0; i<BOARD_HEIGHT; ++i) {
4924 for (j=0; j<BOARD_WIDTH; ++j) {
4925 if (b1[i][j] != b2[i][j]) {
4926 if (++c > 4) /* Castling causes 4 diffs */
4935 /* Matrix describing castling maneuvers */
4936 /* Row, ColRookFrom, ColKingFrom, ColRookTo, ColKingTo */
4937 static int castling_matrix[4][5] = {
4938 { 0, 0, 4, 3, 2 }, /* 0-0-0, white */
4939 { 0, 7, 4, 5, 6 }, /* 0-0, white */
4940 { 7, 0, 4, 3, 2 }, /* 0-0-0, black */
4941 { 7, 7, 4, 5, 6 } /* 0-0, black */
4944 /* Checks whether castling occurred. If it did, *rrow and *rcol
4945 are set to the destination (row,col) of the rook that moved.
4947 Returns 1 if castling occurred, 0 if not.
4949 Note: Only handles a max of 1 castling move, so be sure
4950 to call too_many_diffs() first.
4952 static int check_castle_draw(newb, oldb, rrow, rcol)
4959 /* For each type of castling... */
4960 for (i=0; i<4; ++i) {
4961 r = castling_matrix[i];
4963 /* Check the 4 squares involved in the castling move */
4965 for (j=1; j<=4; ++j) {
4966 if (newb[r[0]][r[j]] == oldb[r[0]][r[j]]) {
4973 /* All 4 changed, so it must be a castling move */
4982 static int damage[BOARD_SIZE][BOARD_SIZE];
4985 * event handler for redrawing the board
4987 void XDrawPosition(w, repaint, board)
4989 /*Boolean*/int repaint;
4993 static int lastFlipView = 0;
4994 static int lastBoardValid = 0;
4995 static Board lastBoard;
4999 if (board == NULL) {
5000 if (!lastBoardValid) return;
5003 if (!lastBoardValid || lastFlipView != flipView) {
5004 XtSetArg(args[0], XtNleftBitmap, (flipView ? xMarkPixmap : None));
5005 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flip View"),
5010 * It would be simpler to clear the window with XClearWindow()
5011 * but this causes a very distracting flicker.
5014 if (!repaint && lastBoardValid && lastFlipView == flipView) {
5016 /* If too much changes (begin observing new game, etc.), don't
5018 do_flash = too_many_diffs(board, lastBoard) ? 0 : 1;
5020 /* Special check for castling so we don't flash both the king
5021 and the rook (just flash the king). */
5023 if (check_castle_draw(board, lastBoard, &rrow, &rcol)) {
5024 /* Draw rook with NO flashing. King will be drawn flashing later */
5025 DrawSquare(rrow, rcol, board[rrow][rcol], 0);
5026 lastBoard[rrow][rcol] = board[rrow][rcol];
5030 /* First pass -- Draw (newly) empty squares and repair damage.
5031 This prevents you from having a piece show up twice while it
5032 is flashing on its new square */
5033 for (i = 0; i < BOARD_HEIGHT; i++)
5034 for (j = 0; j < BOARD_WIDTH; j++)
5035 if ((board[i][j] != lastBoard[i][j] && board[i][j] == EmptySquare)
5037 DrawSquare(i, j, board[i][j], 0);
5038 damage[i][j] = False;
5041 /* Second pass -- Draw piece(s) in new position and flash them */
5042 for (i = 0; i < BOARD_HEIGHT; i++)
5043 for (j = 0; j < BOARD_WIDTH; j++)
5044 if (board[i][j] != lastBoard[i][j]) {
5045 DrawSquare(i, j, board[i][j], do_flash);
5049 XDrawSegments(xDisplay, xBoardWindow, lineGC,
5050 gridSegments, BOARD_HEIGHT + BOARD_WIDTH + 2);
5052 for (i = 0; i < BOARD_HEIGHT; i++)
5053 for (j = 0; j < BOARD_WIDTH; j++) {
5054 DrawSquare(i, j, board[i][j], 0);
5055 damage[i][j] = False;
5059 CopyBoard(lastBoard, board);
5061 lastFlipView = flipView;
5063 /* Draw highlights */
5064 if (pm1X >= 0 && pm1Y >= 0) {
5065 drawHighlight(pm1X, pm1Y, prelineGC);
5067 if (pm2X >= 0 && pm2Y >= 0) {
5068 drawHighlight(pm2X, pm2Y, prelineGC);
5070 if (hi1X >= 0 && hi1Y >= 0) {
5071 drawHighlight(hi1X, hi1Y, highlineGC);
5073 if (hi2X >= 0 && hi2Y >= 0) {
5074 drawHighlight(hi2X, hi2Y, highlineGC);
5077 /* If piece being dragged around board, must redraw that too */
5080 XSync(xDisplay, False);
5085 * event handler for redrawing the board
5087 void DrawPositionProc(w, event, prms, nprms)
5093 XDrawPosition(w, True, NULL);
5098 * event handler for parsing user moves
5100 // [HGM] This routine will need quite some reworking. Although the backend still supports the old
5101 // way of doing things, by calling UserMoveEvent() to test the legality of the move and then perform
5102 // it at the end, and doing all kind of preliminary tests here (e.g. to weed out self-captures), it
5103 // should be made to use the new way, of calling UserMoveTest early to determine the legality of the
5104 // move, (which will weed out the illegal selfcaptures and moves into the holdings, and flag promotions),
5105 // and at the end FinishMove() to perform the move after optional promotion popups.
5106 // For now I patched it to allow self-capture with King, and suppress clicks between board and holdings.
5107 void HandleUserMove(w, event, prms, nprms)
5114 Boolean saveAnimate;
5115 static int second = 0, promotionChoice = 0;
5118 if (w != boardWidget || errorExitStatus != -1) return;
5120 x = EventToSquare(event->xbutton.x, BOARD_WIDTH);
5121 y = EventToSquare(event->xbutton.y, BOARD_HEIGHT);
5122 if (!flipView && y >= 0) {
5123 y = BOARD_HEIGHT - 1 - y;
5125 if (flipView && x >= 0) {
5126 x = BOARD_WIDTH - 1 - x;
5129 if(promotionChoice) { // we are waiting for a click to indicate promotion piece
5130 if(event->type == ButtonRelease) return; // ignore upclick of click-click destination
5131 promotionChoice = FALSE; // only one chance: if click not OK it is interpreted as cancel
5132 if(appData.debugMode) fprintf(debugFP, "promotion click, x=%d, y=%d\n", x, y);
5133 if(gameInfo.holdingsWidth &&
5134 (WhiteOnMove(currentMove)
5135 ? x == BOARD_WIDTH-1 && y < gameInfo.holdingsSize && y > 0
5136 : x == 0 && y >= BOARD_HEIGHT - gameInfo.holdingsSize && y < BOARD_HEIGHT-1) ) {
5137 // click in right holdings, for determining promotion piece
5138 ChessSquare p = boards[currentMove][y][x];
5139 if(appData.debugMode) fprintf(debugFP, "square contains %d\n", (int)p);
5140 if(p != EmptySquare) {
5141 FinishMove(NormalMove, fromX, fromY, toX, toY, ToLower(PieceToChar(p)));
5146 DrawPosition(FALSE, boards[currentMove]);
5149 if (event->type == ButtonPress) ErrorPopDown();
5152 if (event->type == ButtonPress) {
5153 XtPopdown(promotionShell);
5154 XtDestroyWidget(promotionShell);
5155 promotionUp = False;
5163 /* [HGM] holdings: next 5 lines: ignore all clicks between board and holdings */
5164 if(event->type == ButtonPress
5165 && ( x == BOARD_LEFT-1 || x == BOARD_RGHT
5166 || x == BOARD_LEFT-2 && y < BOARD_HEIGHT-gameInfo.holdingsSize
5167 || x == BOARD_RGHT+1 && y >= gameInfo.holdingsSize) )
5171 if (event->type == ButtonPress) {
5172 /* First square, prepare to drag */
5173 if (OKToStartUserMove(x, y)) {
5177 DragPieceBegin(event->xbutton.x, event->xbutton.y);
5178 if (appData.highlightDragging) {
5179 SetHighlights(x, y, -1, -1);
5187 if (event->type == ButtonRelease && x == fromX && y == fromY) {
5188 /* Click on single square in stead of drag-drop */
5189 DragPieceEnd(event->xbutton.x, event->xbutton.y);
5190 if (appData.animateDragging) {
5191 /* Undo animation damage if any */
5192 DrawPosition(FALSE, NULL);
5195 /* Second up/down in same square; just abort move */
5200 ClearPremoveHighlights();
5202 /* First upclick in same square; start click-click mode */
5203 SetHighlights(x, y, -1, -1);
5208 moveType = UserMoveTest(fromX, fromY, x, y, NULLCHAR, event->type == ButtonRelease);
5210 if (moveType == Comment) { // kludge for indicating capture-own on Press
5211 /* Clicked again on same color piece -- changed his mind */
5212 /* note that re-clicking same square always hits same color piece */
5213 second = (x == fromX && y == fromY);
5214 if (appData.highlightDragging) {
5215 SetHighlights(x, y, -1, -1);
5219 if (OKToStartUserMove(x, y)) {
5222 DragPieceBegin(event->xbutton.x, event->xbutton.y);
5227 if(moveType == AmbiguousMove) { // kludge to indicate edit-position move
5230 DragPieceEnd(event->xbutton.x, event->xbutton.y);
5231 DrawPosition(FALSE, boards[currentMove]);
5235 /* Complete move; (x,y) is now different from (fromX, fromY) on both Press and Release */
5238 saveAnimate = appData.animate;
5239 if (event->type == ButtonPress) {
5240 /* Finish clickclick move */
5241 if (appData.animate || appData.highlightLastMove) {
5242 SetHighlights(fromX, fromY, toX, toY);
5247 /* Finish drag move */
5248 if (appData.highlightLastMove) {
5249 SetHighlights(fromX, fromY, toX, toY);
5253 DragPieceEnd(event->xbutton.x, event->xbutton.y);
5254 /* Don't animate move and drag both */
5255 appData.animate = FALSE;
5257 if (moveType == WhitePromotionKnight || moveType == BlackPromotionKnight ||
5258 (moveType == WhitePromotionQueen || moveType == BlackPromotionQueen) &&
5259 appData.alwaysPromoteToQueen) { // promotion, but no choice
5260 FinishMove(moveType, fromX, fromY, toX, toY, 'q');
5262 if (moveType == WhitePromotionQueen || moveType == BlackPromotionQueen ) {
5263 SetHighlights(fromX, fromY, toX, toY);
5264 if(gameInfo.variant == VariantSuper || gameInfo.variant == VariantGreat) {
5265 // [HGM] super: promotion to captured piece selected from holdings
5266 ChessSquare p = boards[currentMove][fromY][fromX], q = boards[currentMove][toY][toX];
5267 promotionChoice = TRUE;
5268 // kludge follows to temporarily execute move on display, without promoting yet
5269 boards[currentMove][fromY][fromX] = EmptySquare; // move Pawn to 8th rank
5270 boards[currentMove][toY][toX] = p;
5271 DrawPosition(FALSE, boards[currentMove]);
5272 boards[currentMove][fromY][fromX] = p; // take back, but display stays
5273 boards[currentMove][toY][toX] = q;
5274 DisplayMessage("Click in holdings to choose piece", "");
5278 goto skipClearingFrom; // the skipped stuff is done asynchronously by PromotionCallback
5280 if(moveType != ImpossibleMove) { // valid move, but no promotion
5281 FinishMove(moveType, fromX, fromY, toX, toY, NULLCHAR);
5282 } else { // invalid move; could have set premove
5285 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
5286 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
5289 appData.animate = saveAnimate;
5290 if (appData.animate || appData.animateDragging) {
5291 /* Undo animation damage if needed */
5292 DrawPosition(FALSE, NULL);
5296 void AnimateUserMove (Widget w, XEvent * event,
5297 String * params, Cardinal * nParams)
5299 DragPieceMove(event->xmotion.x, event->xmotion.y);
5302 Widget CommentCreate(name, text, mutable, callback, lines)
5304 int /*Boolean*/ mutable;
5305 XtCallbackProc callback;
5309 Widget shell, layout, form, edit, b_ok, b_cancel, b_clear, b_close, b_edit;
5314 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5315 XtGetValues(boardWidget, args, j);
5318 XtSetArg(args[j], XtNresizable, True); j++;
5321 XtCreatePopupShell(name, topLevelShellWidgetClass,
5322 shellWidget, args, j);
5325 XtCreatePopupShell(name, transientShellWidgetClass,
5326 shellWidget, args, j);
5329 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
5330 layoutArgs, XtNumber(layoutArgs));
5332 XtCreateManagedWidget("form", formWidgetClass, layout,
5333 formArgs, XtNumber(formArgs));
5337 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
5338 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
5340 XtSetArg(args[j], XtNstring, text); j++;
5341 XtSetArg(args[j], XtNtop, XtChainTop); j++;
5342 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5343 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5344 XtSetArg(args[j], XtNright, XtChainRight); j++;
5345 XtSetArg(args[j], XtNresizable, True); j++;
5346 XtSetArg(args[j], XtNwidth, bw_width); j++; /*force wider than buttons*/
5347 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
5348 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
5349 XtSetArg(args[j], XtNautoFill, True); j++;
5350 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
5352 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
5356 XtSetArg(args[j], XtNfromVert, edit); j++;
5357 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5358 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5359 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5360 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5362 XtCreateManagedWidget(_("ok"), commandWidgetClass, form, args, j);
5363 XtAddCallback(b_ok, XtNcallback, callback, (XtPointer) 0);
5366 XtSetArg(args[j], XtNfromVert, edit); j++;
5367 XtSetArg(args[j], XtNfromHoriz, b_ok); j++;
5368 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5369 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5370 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5371 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5373 XtCreateManagedWidget(_("cancel"), commandWidgetClass, form, args, j);
5374 XtAddCallback(b_cancel, XtNcallback, callback, (XtPointer) 0);
5377 XtSetArg(args[j], XtNfromVert, edit); j++;
5378 XtSetArg(args[j], XtNfromHoriz, b_cancel); j++;
5379 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5380 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5381 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5382 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5384 XtCreateManagedWidget(_("clear"), commandWidgetClass, form, args, j);
5385 XtAddCallback(b_clear, XtNcallback, callback, (XtPointer) 0);
5388 XtSetArg(args[j], XtNfromVert, edit); j++;
5389 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5390 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5391 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5392 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5394 XtCreateManagedWidget(_("close"), commandWidgetClass, form, args, j);
5395 XtAddCallback(b_close, XtNcallback, callback, (XtPointer) 0);
5398 XtSetArg(args[j], XtNfromVert, edit); j++;
5399 XtSetArg(args[j], XtNfromHoriz, b_close); j++;
5400 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5401 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5402 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5403 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5405 XtCreateManagedWidget(_("edit"), commandWidgetClass, form, args, j);
5406 XtAddCallback(b_edit, XtNcallback, callback, (XtPointer) 0);
5409 XtRealizeWidget(shell);
5411 if (commentX == -1) {
5414 Dimension pw_height;
5415 Dimension ew_height;
5418 XtSetArg(args[j], XtNheight, &ew_height); j++;
5419 XtGetValues(edit, args, j);
5422 XtSetArg(args[j], XtNheight, &pw_height); j++;
5423 XtGetValues(shell, args, j);
5424 commentH = pw_height + (lines - 1) * ew_height;
5425 commentW = bw_width - 16;
5427 XSync(xDisplay, False);
5429 /* This code seems to tickle an X bug if it is executed too soon
5430 after xboard starts up. The coordinates get transformed as if
5431 the main window was positioned at (0, 0).
5433 XtTranslateCoords(shellWidget,
5434 (bw_width - commentW) / 2, 0 - commentH / 2,
5435 &commentX, &commentY);
5437 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
5438 RootWindowOfScreen(XtScreen(shellWidget)),
5439 (bw_width - commentW) / 2, 0 - commentH / 2,
5444 if (commentY < 0) commentY = 0; /*avoid positioning top offscreen*/
5447 XtSetArg(args[j], XtNheight, commentH); j++;
5448 XtSetArg(args[j], XtNwidth, commentW); j++;
5449 XtSetArg(args[j], XtNx, commentX); j++;
5450 XtSetArg(args[j], XtNy, commentY); j++;
5451 XtSetValues(shell, args, j);
5452 XtSetKeyboardFocus(shell, edit);
5457 /* Used for analysis window and ICS input window */
5458 Widget MiscCreate(name, text, mutable, callback, lines)
5460 int /*Boolean*/ mutable;
5461 XtCallbackProc callback;
5465 Widget shell, layout, form, edit;
5467 Dimension bw_width, pw_height, ew_height, w, h;
5473 XtSetArg(args[j], XtNresizable, True); j++;
5476 XtCreatePopupShell(name, topLevelShellWidgetClass,
5477 shellWidget, args, j);
5480 XtCreatePopupShell(name, transientShellWidgetClass,
5481 shellWidget, args, j);
5484 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
5485 layoutArgs, XtNumber(layoutArgs));
5487 XtCreateManagedWidget("form", formWidgetClass, layout,
5488 formArgs, XtNumber(formArgs));
5492 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
5493 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
5495 XtSetArg(args[j], XtNstring, text); j++;
5496 XtSetArg(args[j], XtNtop, XtChainTop); j++;
5497 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5498 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5499 XtSetArg(args[j], XtNright, XtChainRight); j++;
5500 XtSetArg(args[j], XtNresizable, True); j++;
5501 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
5502 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
5503 XtSetArg(args[j], XtNautoFill, True); j++;
5504 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
5506 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
5508 XtRealizeWidget(shell);
5511 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5512 XtGetValues(boardWidget, args, j);
5515 XtSetArg(args[j], XtNheight, &ew_height); j++;
5516 XtGetValues(edit, args, j);
5519 XtSetArg(args[j], XtNheight, &pw_height); j++;
5520 XtGetValues(shell, args, j);
5521 h = pw_height + (lines - 1) * ew_height;
5524 XSync(xDisplay, False);
5526 /* This code seems to tickle an X bug if it is executed too soon
5527 after xboard starts up. The coordinates get transformed as if
5528 the main window was positioned at (0, 0).
5530 XtTranslateCoords(shellWidget, (bw_width - w) / 2, 0 - h / 2, &x, &y);
5532 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
5533 RootWindowOfScreen(XtScreen(shellWidget)),
5534 (bw_width - w) / 2, 0 - h / 2, &xx, &yy, &junk);
5538 if (y < 0) y = 0; /*avoid positioning top offscreen*/
5541 XtSetArg(args[j], XtNheight, h); j++;
5542 XtSetArg(args[j], XtNwidth, w); j++;
5543 XtSetArg(args[j], XtNx, x); j++;
5544 XtSetArg(args[j], XtNy, y); j++;
5545 XtSetValues(shell, args, j);
5551 static int savedIndex; /* gross that this is global */
5553 void EditCommentPopUp(index, title, text)
5562 if (text == NULL) text = "";
5564 if (editShell == NULL) {
5566 CommentCreate(title, text, True, EditCommentCallback, 4);
5567 XtRealizeWidget(editShell);
5568 CatchDeleteWindow(editShell, "EditCommentPopDown");
5570 edit = XtNameToWidget(editShell, "*form.text");
5572 XtSetArg(args[j], XtNstring, text); j++;
5573 XtSetValues(edit, args, j);
5575 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5576 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5577 XtSetValues(editShell, args, j);
5580 XtPopup(editShell, XtGrabNone);
5584 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
5585 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
5589 void EditCommentCallback(w, client_data, call_data)
5591 XtPointer client_data, call_data;
5599 XtSetArg(args[j], XtNlabel, &name); j++;
5600 XtGetValues(w, args, j);
5602 if (strcmp(name, _("ok")) == 0) {
5603 edit = XtNameToWidget(editShell, "*form.text");
5605 XtSetArg(args[j], XtNstring, &val); j++;
5606 XtGetValues(edit, args, j);
5607 ReplaceComment(savedIndex, val);
5608 EditCommentPopDown();
5609 } else if (strcmp(name, _("cancel")) == 0) {
5610 EditCommentPopDown();
5611 } else if (strcmp(name, _("clear")) == 0) {
5612 edit = XtNameToWidget(editShell, "*form.text");
5613 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
5614 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
5618 void EditCommentPopDown()
5623 if (!editUp) return;
5625 XtSetArg(args[j], XtNx, &commentX); j++;
5626 XtSetArg(args[j], XtNy, &commentY); j++;
5627 XtSetArg(args[j], XtNheight, &commentH); j++;
5628 XtSetArg(args[j], XtNwidth, &commentW); j++;
5629 XtGetValues(editShell, args, j);
5630 XtPopdown(editShell);
5633 XtSetArg(args[j], XtNleftBitmap, None); j++;
5634 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
5638 void ICSInputBoxPopUp()
5643 char *title = _("ICS Input");
5646 if (ICSInputShell == NULL) {
5647 ICSInputShell = MiscCreate(title, "", True, NULL, 1);
5648 tr = XtParseTranslationTable(ICSInputTranslations);
5649 edit = XtNameToWidget(ICSInputShell, "*form.text");
5650 XtOverrideTranslations(edit, tr);
5651 XtRealizeWidget(ICSInputShell);
5652 CatchDeleteWindow(ICSInputShell, "ICSInputBoxPopDown");
5655 edit = XtNameToWidget(ICSInputShell, "*form.text");
5657 XtSetArg(args[j], XtNstring, ""); j++;
5658 XtSetValues(edit, args, j);
5660 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5661 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5662 XtSetValues(ICSInputShell, args, j);
5665 XtPopup(ICSInputShell, XtGrabNone);
5666 XtSetKeyboardFocus(ICSInputShell, edit);
5668 ICSInputBoxUp = True;
5670 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
5671 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
5675 void ICSInputSendText()
5682 edit = XtNameToWidget(ICSInputShell, "*form.text");
5684 XtSetArg(args[j], XtNstring, &val); j++;
5685 XtGetValues(edit, args, j);
5686 SendMultiLineToICS(val);
5687 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
5688 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
5691 void ICSInputBoxPopDown()
5696 if (!ICSInputBoxUp) return;
5698 XtPopdown(ICSInputShell);
5699 ICSInputBoxUp = False;
5701 XtSetArg(args[j], XtNleftBitmap, None); j++;
5702 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
5706 void CommentPopUp(title, text)
5713 if (commentShell == NULL) {
5715 CommentCreate(title, text, False, CommentCallback, 4);
5716 XtRealizeWidget(commentShell);
5717 CatchDeleteWindow(commentShell, "CommentPopDown");
5719 edit = XtNameToWidget(commentShell, "*form.text");
5721 XtSetArg(args[j], XtNstring, text); j++;
5722 XtSetValues(edit, args, j);
5724 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5725 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5726 XtSetValues(commentShell, args, j);
5729 XtPopup(commentShell, XtGrabNone);
5730 XSync(xDisplay, False);
5735 void AnalysisPopUp(title, text)
5742 if (analysisShell == NULL) {
5743 analysisShell = MiscCreate(title, text, False, NULL, 4);
5744 XtRealizeWidget(analysisShell);
5745 CatchDeleteWindow(analysisShell, "AnalysisPopDown");
5748 edit = XtNameToWidget(analysisShell, "*form.text");
5750 XtSetArg(args[j], XtNstring, text); j++;
5751 XtSetValues(edit, args, j);
5753 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5754 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5755 XtSetValues(analysisShell, args, j);
5759 XtPopup(analysisShell, XtGrabNone);
5761 XSync(xDisplay, False);
5766 void CommentCallback(w, client_data, call_data)
5768 XtPointer client_data, call_data;
5775 XtSetArg(args[j], XtNlabel, &name); j++;
5776 XtGetValues(w, args, j);
5778 if (strcmp(name, _("close")) == 0) {
5780 } else if (strcmp(name, _("edit")) == 0) {
5787 void CommentPopDown()
5792 if (!commentUp) return;
5794 XtSetArg(args[j], XtNx, &commentX); j++;
5795 XtSetArg(args[j], XtNy, &commentY); j++;
5796 XtSetArg(args[j], XtNwidth, &commentW); j++;
5797 XtSetArg(args[j], XtNheight, &commentH); j++;
5798 XtGetValues(commentShell, args, j);
5799 XtPopdown(commentShell);
5800 XSync(xDisplay, False);
5804 void AnalysisPopDown()
5806 if (!analysisUp) return;
5807 XtPopdown(analysisShell);
5808 XSync(xDisplay, False);
5810 if (appData.icsEngineAnalyze) ExitAnalyzeMode(); /* [DM] icsEngineAnalyze */
5814 void FileNamePopUp(label, def, proc, openMode)
5821 Widget popup, layout, dialog, edit;
5827 fileProc = proc; /* I can't see a way not */
5828 fileOpenMode = openMode; /* to use globals here */
5831 XtSetArg(args[i], XtNresizable, True); i++;
5832 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
5833 XtSetArg(args[i], XtNtitle, XtNewString(_("File name prompt"))); i++;
5834 fileNameShell = popup =
5835 XtCreatePopupShell("File name prompt", transientShellWidgetClass,
5836 shellWidget, args, i);
5839 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
5840 layoutArgs, XtNumber(layoutArgs));
5843 XtSetArg(args[i], XtNlabel, label); i++;
5844 XtSetArg(args[i], XtNvalue, def); i++;
5845 XtSetArg(args[i], XtNborderWidth, 0); i++;
5846 dialog = XtCreateManagedWidget("fileName", dialogWidgetClass,
5849 XawDialogAddButton(dialog, _("ok"), FileNameCallback, (XtPointer) dialog);
5850 XawDialogAddButton(dialog, _("cancel"), FileNameCallback,
5851 (XtPointer) dialog);
5853 XtRealizeWidget(popup);
5854 CatchDeleteWindow(popup, "FileNamePopDown");
5856 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
5857 &x, &y, &win_x, &win_y, &mask);
5859 XtSetArg(args[0], XtNx, x - 10);
5860 XtSetArg(args[1], XtNy, y - 30);
5861 XtSetValues(popup, args, 2);
5863 XtPopup(popup, XtGrabExclusive);
5866 edit = XtNameToWidget(dialog, "*value");
5867 XtSetKeyboardFocus(popup, edit);
5870 void FileNamePopDown()
5872 if (!filenameUp) return;
5873 XtPopdown(fileNameShell);
5874 XtDestroyWidget(fileNameShell);
5879 void FileNameCallback(w, client_data, call_data)
5881 XtPointer client_data, call_data;
5886 XtSetArg(args[0], XtNlabel, &name);
5887 XtGetValues(w, args, 1);
5889 if (strcmp(name, _("cancel")) == 0) {
5894 FileNameAction(w, NULL, NULL, NULL);
5897 void FileNameAction(w, event, prms, nprms)
5909 name = XawDialogGetValueString(w = XtParent(w));
5911 if ((name != NULL) && (*name != NULLCHAR)) {
5913 XtPopdown(w = XtParent(XtParent(w)));
5917 p = strrchr(buf, ' ');
5924 fullname = ExpandPathName(buf);
5926 ErrorPopUp(_("Error"), _("Can't open file"), FALSE);
5929 f = fopen(fullname, fileOpenMode);
5931 DisplayError(_("Failed to open file"), errno);
5933 (void) (*fileProc)(f, index, buf);
5940 XtPopdown(w = XtParent(XtParent(w)));
5946 void PromotionPopUp()
5949 Widget dialog, layout;
5951 Dimension bw_width, pw_width;
5955 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5956 XtGetValues(boardWidget, args, j);
5959 XtSetArg(args[j], XtNresizable, True); j++;
5960 XtSetArg(args[j], XtNtitle, XtNewString(_("Promotion"))); j++;
5962 XtCreatePopupShell("Promotion", transientShellWidgetClass,
5963 shellWidget, args, j);
5965 XtCreateManagedWidget(layoutName, formWidgetClass, promotionShell,
5966 layoutArgs, XtNumber(layoutArgs));
5969 XtSetArg(args[j], XtNlabel, _("Promote to what?")); j++;
5970 XtSetArg(args[j], XtNborderWidth, 0); j++;
5971 dialog = XtCreateManagedWidget("promotion", dialogWidgetClass,
5974 if(gameInfo.variant != VariantShogi) {
5975 XawDialogAddButton(dialog, _("Queen"), PromotionCallback,
5976 (XtPointer) dialog);
5977 XawDialogAddButton(dialog, _("Rook"), PromotionCallback,
5978 (XtPointer) dialog);
5979 XawDialogAddButton(dialog, _("Bishop"), PromotionCallback,
5980 (XtPointer) dialog);
5981 XawDialogAddButton(dialog, _("Knight"), PromotionCallback,
5982 (XtPointer) dialog);
5983 if (!appData.testLegality || gameInfo.variant == VariantSuicide ||
5984 gameInfo.variant == VariantGiveaway) {
5985 XawDialogAddButton(dialog, _("King"), PromotionCallback,
5986 (XtPointer) dialog);
5988 if(gameInfo.variant == VariantCapablanca ||
5989 gameInfo.variant == VariantGothic ||
5990 gameInfo.variant == VariantCapaRandom) {
5991 XawDialogAddButton(dialog, _("Archbishop"), PromotionCallback,
5992 (XtPointer) dialog);
5993 XawDialogAddButton(dialog, _("Chancellor"), PromotionCallback,
5994 (XtPointer) dialog);
5996 } else // [HGM] shogi
5998 XawDialogAddButton(dialog, _("Promote"), PromotionCallback,
5999 (XtPointer) dialog);
6000 XawDialogAddButton(dialog, _("Defer"), PromotionCallback,
6001 (XtPointer) dialog);
6003 XawDialogAddButton(dialog, _("cancel"), PromotionCallback,
6004 (XtPointer) dialog);
6006 XtRealizeWidget(promotionShell);
6007 CatchDeleteWindow(promotionShell, "PromotionPopDown");
6010 XtSetArg(args[j], XtNwidth, &pw_width); j++;
6011 XtGetValues(promotionShell, args, j);
6013 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
6014 lineGap + squareSize/3 +
6015 ((toY == BOARD_HEIGHT-1) ^ (flipView) ?
6016 0 : 6*(squareSize + lineGap)), &x, &y);
6019 XtSetArg(args[j], XtNx, x); j++;
6020 XtSetArg(args[j], XtNy, y); j++;
6021 XtSetValues(promotionShell, args, j);
6023 XtPopup(promotionShell, XtGrabNone);
6028 void PromotionPopDown()
6030 if (!promotionUp) return;
6031 XtPopdown(promotionShell);
6032 XtDestroyWidget(promotionShell);
6033 promotionUp = False;
6036 void PromotionCallback(w, client_data, call_data)
6038 XtPointer client_data, call_data;
6044 XtSetArg(args[0], XtNlabel, &name);
6045 XtGetValues(w, args, 1);
6049 if (fromX == -1) return;
6051 if (strcmp(name, _("cancel")) == 0) {
6055 } else if (strcmp(name, _("Knight")) == 0) {
6057 } else if (strcmp(name, _("Promote")) == 0) {
6059 } else if (strcmp(name, _("Defer")) == 0) {
6062 promoChar = ToLower(name[0]);
6065 FinishMove(NormalMove, fromX, fromY, toX, toY, promoChar);
6067 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
6068 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
6073 void ErrorCallback(w, client_data, call_data)
6075 XtPointer client_data, call_data;
6078 XtPopdown(w = XtParent(XtParent(XtParent(w))));
6080 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
6086 if (!errorUp) return;
6088 XtPopdown(errorShell);
6089 XtDestroyWidget(errorShell);
6090 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
6093 void ErrorPopUp(title, label, modal)
6094 char *title, *label;
6098 Widget dialog, layout;
6102 Dimension bw_width, pw_width;
6103 Dimension pw_height;
6107 XtSetArg(args[i], XtNresizable, True); i++;
6108 XtSetArg(args[i], XtNtitle, title); i++;
6110 XtCreatePopupShell("errorpopup", transientShellWidgetClass,
6111 shellWidget, args, i);
6113 XtCreateManagedWidget(layoutName, formWidgetClass, errorShell,
6114 layoutArgs, XtNumber(layoutArgs));
6117 XtSetArg(args[i], XtNlabel, label); i++;
6118 XtSetArg(args[i], XtNborderWidth, 0); i++;
6119 dialog = XtCreateManagedWidget("dialog", dialogWidgetClass,
6122 XawDialogAddButton(dialog, _("ok"), ErrorCallback, (XtPointer) dialog);
6124 XtRealizeWidget(errorShell);
6125 CatchDeleteWindow(errorShell, "ErrorPopDown");
6128 XtSetArg(args[i], XtNwidth, &bw_width); i++;
6129 XtGetValues(boardWidget, args, i);
6131 XtSetArg(args[i], XtNwidth, &pw_width); i++;
6132 XtSetArg(args[i], XtNheight, &pw_height); i++;
6133 XtGetValues(errorShell, args, i);
6136 /* This code seems to tickle an X bug if it is executed too soon
6137 after xboard starts up. The coordinates get transformed as if
6138 the main window was positioned at (0, 0).
6140 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
6141 0 - pw_height + squareSize / 3, &x, &y);
6143 XTranslateCoordinates(xDisplay, XtWindow(boardWidget),
6144 RootWindowOfScreen(XtScreen(boardWidget)),
6145 (bw_width - pw_width) / 2,
6146 0 - pw_height + squareSize / 3, &xx, &yy, &junk);
6150 if (y < 0) y = 0; /*avoid positioning top offscreen*/
6153 XtSetArg(args[i], XtNx, x); i++;
6154 XtSetArg(args[i], XtNy, y); i++;
6155 XtSetValues(errorShell, args, i);
6158 XtPopup(errorShell, modal ? XtGrabExclusive : XtGrabNone);
6161 /* Disable all user input other than deleting the window */
6162 static int frozen = 0;
6166 /* Grab by a widget that doesn't accept input */
6167 XtAddGrab(messageWidget, TRUE, FALSE);
6171 /* Undo a FreezeUI */
6174 if (!frozen) return;
6175 XtRemoveGrab(messageWidget);
6179 char *ModeToWidgetName(mode)
6183 case BeginningOfGame:
6184 if (appData.icsActive)
6185 return "menuMode.ICS Client";
6186 else if (appData.noChessProgram ||
6187 *appData.cmailGameName != NULLCHAR)
6188 return "menuMode.Edit Game";
6190 return "menuMode.Machine Black";
6191 case MachinePlaysBlack:
6192 return "menuMode.Machine Black";
6193 case MachinePlaysWhite:
6194 return "menuMode.Machine White";
6196 return "menuMode.Analysis Mode";
6198 return "menuMode.Analyze File";
6199 case TwoMachinesPlay:
6200 return "menuMode.Two Machines";
6202 return "menuMode.Edit Game";
6203 case PlayFromGameFile:
6204 return "menuFile.Load Game";
6206 return "menuMode.Edit Position";
6208 return "menuMode.Training";
6209 case IcsPlayingWhite:
6210 case IcsPlayingBlack:
6214 return "menuMode.ICS Client";
6221 void ModeHighlight()
6224 static int oldPausing = FALSE;
6225 static GameMode oldmode = (GameMode) -1;
6228 if (!boardWidget || !XtIsRealized(boardWidget)) return;
6230 if (pausing != oldPausing) {
6231 oldPausing = pausing;
6233 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6235 XtSetArg(args[0], XtNleftBitmap, None);
6237 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Pause"),
6240 if (appData.showButtonBar) {
6241 /* Always toggle, don't set. Previous code messes up when
6242 invoked while the button is pressed, as releasing it
6243 toggles the state again. */
6246 XtSetArg(args[0], XtNbackground, &oldbg);
6247 XtSetArg(args[1], XtNforeground, &oldfg);
6248 XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON),
6250 XtSetArg(args[0], XtNbackground, oldfg);
6251 XtSetArg(args[1], XtNforeground, oldbg);
6253 XtSetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
6257 wname = ModeToWidgetName(oldmode);
6258 if (wname != NULL) {
6259 XtSetArg(args[0], XtNleftBitmap, None);
6260 XtSetValues(XtNameToWidget(menuBarWidget, wname), args, 1);
6262 wname = ModeToWidgetName(gameMode);
6263 if (wname != NULL) {
6264 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6265 XtSetValues(XtNameToWidget(menuBarWidget, wname), args, 1);
6269 /* Maybe all the enables should be handled here, not just this one */
6270 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Training"),
6271 gameMode == Training || gameMode == PlayFromGameFile);
6276 * Button/menu procedures
6278 void ResetProc(w, event, prms, nprms)
6288 int LoadGamePopUp(f, gameNumber, title)
6293 cmailMsgLoaded = FALSE;
6294 if (gameNumber == 0) {
6295 int error = GameListBuild(f);
6297 DisplayError(_("Cannot build game list"), error);
6298 } else if (!ListEmpty(&gameList) &&
6299 ((ListGame *) gameList.tailPred)->number > 1) {
6300 GameListPopUp(f, title);
6306 return LoadGame(f, gameNumber, title, FALSE);
6309 void LoadGameProc(w, event, prms, nprms)
6315 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
6318 FileNamePopUp(_("Load game file name?"), "", LoadGamePopUp, "rb");
6321 void LoadNextGameProc(w, event, prms, nprms)
6330 void LoadPrevGameProc(w, event, prms, nprms)
6339 void ReloadGameProc(w, event, prms, nprms)
6348 void LoadNextPositionProc(w, event, prms, nprms)
6357 void LoadPrevPositionProc(w, event, prms, nprms)
6366 void ReloadPositionProc(w, event, prms, nprms)
6375 void LoadPositionProc(w, event, prms, nprms)
6381 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
6384 FileNamePopUp(_("Load position file name?"), "", LoadPosition, "rb");
6387 void SaveGameProc(w, event, prms, nprms)
6393 FileNamePopUp(_("Save game file name?"),
6394 DefaultFileName(appData.oldSaveStyle ? "game" : "pgn"),
6398 void SavePositionProc(w, event, prms, nprms)
6404 FileNamePopUp(_("Save position file name?"),
6405 DefaultFileName(appData.oldSaveStyle ? "pos" : "fen"),
6409 void ReloadCmailMsgProc(w, event, prms, nprms)
6415 ReloadCmailMsgEvent(FALSE);
6418 void MailMoveProc(w, event, prms, nprms)
6427 /* this variable is shared between CopyPositionProc and SendPositionSelection */
6428 static char *selected_fen_position=NULL;
6431 SendPositionSelection(Widget w, Atom *selection, Atom *target,
6432 Atom *type_return, XtPointer *value_return,
6433 unsigned long *length_return, int *format_return)
6435 char *selection_tmp;
6437 if (!selected_fen_position) return False; /* should never happen */
6438 if (*target == XA_STRING){
6439 /* note: since no XtSelectionDoneProc was registered, Xt will
6440 * automatically call XtFree on the value returned. So have to
6441 * make a copy of it allocated with XtMalloc */
6442 selection_tmp= XtMalloc(strlen(selected_fen_position)+16);
6443 strcpy(selection_tmp, selected_fen_position);
6445 *value_return=selection_tmp;
6446 *length_return=strlen(selection_tmp);
6447 *type_return=XA_STRING;
6448 *format_return = 8; /* bits per byte */
6455 /* note: when called from menu all parameters are NULL, so no clue what the
6456 * Widget which was clicked on was, or what the click event was
6458 void CopyPositionProc(w, event, prms, nprms)
6466 if (selected_fen_position) free(selected_fen_position);
6467 selected_fen_position = (char *)PositionToFEN(currentMove, NULL);
6468 if (!selected_fen_position) return;
6469 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
6471 SendPositionSelection,
6472 NULL/* lose_ownership_proc */ ,
6473 NULL/* transfer_done_proc */);
6475 free(selected_fen_position);
6476 selected_fen_position=NULL;
6480 /* function called when the data to Paste is ready */
6482 PastePositionCB(Widget w, XtPointer client_data, Atom *selection,
6483 Atom *type, XtPointer value, unsigned long *len, int *format)
6486 if (value==NULL || *len==0) return; /* nothing had been selected to copy */
6487 fenstr[*len]='\0'; /* normally this string is terminated, but be safe */
6488 EditPositionPasteFEN(fenstr);
6492 /* called when Paste Position button is pressed,
6493 * all parameters will be NULL */
6494 void PastePositionProc(w, event, prms, nprms)
6500 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
6501 /* (XtSelectionCallbackProc) */ PastePositionCB,
6502 NULL, /* client_data passed to PastePositionCB */
6504 /* better to use the time field from the event that triggered the
6505 * call to this function, but that isn't trivial to get
6513 SendGameSelection(Widget w, Atom *selection, Atom *target,
6514 Atom *type_return, XtPointer *value_return,
6515 unsigned long *length_return, int *format_return)
6517 char *selection_tmp;
6519 if (*target == XA_STRING){
6520 FILE* f = fopen(gameCopyFilename, "r");
6523 if (f == NULL) return False;
6527 selection_tmp = XtMalloc(len + 1);
6528 count = fread(selection_tmp, 1, len, f);
6530 XtFree(selection_tmp);
6533 selection_tmp[len] = NULLCHAR;
6534 *value_return = selection_tmp;
6535 *length_return = len;
6536 *type_return = XA_STRING;
6537 *format_return = 8; /* bits per byte */
6544 /* note: when called from menu all parameters are NULL, so no clue what the
6545 * Widget which was clicked on was, or what the click event was
6547 void CopyGameProc(w, event, prms, nprms)
6555 ret = SaveGameToFile(gameCopyFilename, FALSE);
6558 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
6561 NULL/* lose_ownership_proc */ ,
6562 NULL/* transfer_done_proc */);
6565 /* function called when the data to Paste is ready */
6567 PasteGameCB(Widget w, XtPointer client_data, Atom *selection,
6568 Atom *type, XtPointer value, unsigned long *len, int *format)
6571 if (value == NULL || *len == 0) {
6572 return; /* nothing had been selected to copy */
6574 f = fopen(gamePasteFilename, "w");
6576 DisplayError(_("Can't open temp file"), errno);
6579 fwrite(value, 1, *len, f);
6582 LoadGameFromFile(gamePasteFilename, 0, gamePasteFilename, TRUE);
6585 /* called when Paste Game button is pressed,
6586 * all parameters will be NULL */
6587 void PasteGameProc(w, event, prms, nprms)
6593 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
6594 /* (XtSelectionCallbackProc) */ PasteGameCB,
6595 NULL, /* client_data passed to PasteGameCB */
6597 /* better to use the time field from the event that triggered the
6598 * call to this function, but that isn't trivial to get
6608 SaveGameProc(NULL, NULL, NULL, NULL);
6612 void QuitProc(w, event, prms, nprms)
6621 void PauseProc(w, event, prms, nprms)
6631 void MachineBlackProc(w, event, prms, nprms)
6637 MachineBlackEvent();
6640 void MachineWhiteProc(w, event, prms, nprms)
6646 MachineWhiteEvent();
6649 void AnalyzeModeProc(w, event, prms, nprms)
6657 if (!first.analysisSupport) {
6658 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
6659 DisplayError(buf, 0);
6662 /* [DM] icsEngineAnalyze [HGM] This is horrible code; reverse the gameMode and isEngineAnalyze tests! */
6663 if (appData.icsActive) {
6664 if (gameMode != IcsObserving) {
6665 sprintf(buf,_("You are not observing a game"));
6666 DisplayError(buf, 0);
6668 if (appData.icsEngineAnalyze) {
6669 if (appData.debugMode)
6670 fprintf(debugFP, _("Found unexpected active ICS engine analyze \n"));
6676 /* if enable, use want disable icsEngineAnalyze */
6677 if (appData.icsEngineAnalyze) {
6682 appData.icsEngineAnalyze = TRUE;
6683 if (appData.debugMode)
6684 fprintf(debugFP, _("ICS engine analyze starting... \n"));
6686 if (!appData.showThinking)
6687 ShowThinkingProc(w,event,prms,nprms);
6692 void AnalyzeFileProc(w, event, prms, nprms)
6698 if (!first.analysisSupport) {
6700 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
6701 DisplayError(buf, 0);
6706 if (!appData.showThinking)
6707 ShowThinkingProc(w,event,prms,nprms);
6710 FileNamePopUp(_("File to analyze"), "", LoadGamePopUp, "rb");
6711 AnalysisPeriodicEvent(1);
6714 void TwoMachinesProc(w, event, prms, nprms)
6723 void IcsClientProc(w, event, prms, nprms)
6732 void EditGameProc(w, event, prms, nprms)
6741 void EditPositionProc(w, event, prms, nprms)
6747 EditPositionEvent();
6750 void TrainingProc(w, event, prms, nprms)
6759 void EditCommentProc(w, event, prms, nprms)
6766 EditCommentPopDown();
6772 void IcsInputBoxProc(w, event, prms, nprms)
6778 if (ICSInputBoxUp) {
6779 ICSInputBoxPopDown();
6785 void AcceptProc(w, event, prms, nprms)
6794 void DeclineProc(w, event, prms, nprms)
6803 void RematchProc(w, event, prms, nprms)
6812 void CallFlagProc(w, event, prms, nprms)
6821 void DrawProc(w, event, prms, nprms)
6830 void AbortProc(w, event, prms, nprms)
6839 void AdjournProc(w, event, prms, nprms)
6848 void ResignProc(w, event, prms, nprms)
6857 void AdjuWhiteProc(w, event, prms, nprms)
6863 UserAdjudicationEvent(+1);
6866 void AdjuBlackProc(w, event, prms, nprms)
6872 UserAdjudicationEvent(-1);
6875 void AdjuDrawProc(w, event, prms, nprms)
6881 UserAdjudicationEvent(0);
6884 void EnterKeyProc(w, event, prms, nprms)
6890 if (ICSInputBoxUp == True)
6894 void StopObservingProc(w, event, prms, nprms)
6900 StopObservingEvent();
6903 void StopExaminingProc(w, event, prms, nprms)
6909 StopExaminingEvent();
6913 void ForwardProc(w, event, prms, nprms)
6923 void BackwardProc(w, event, prms, nprms)
6932 void ToStartProc(w, event, prms, nprms)
6941 void ToEndProc(w, event, prms, nprms)
6950 void RevertProc(w, event, prms, nprms)
6959 void TruncateGameProc(w, event, prms, nprms)
6965 TruncateGameEvent();
6967 void RetractMoveProc(w, event, prms, nprms)
6976 void MoveNowProc(w, event, prms, nprms)
6986 void AlwaysQueenProc(w, event, prms, nprms)
6994 appData.alwaysPromoteToQueen = !appData.alwaysPromoteToQueen;
6996 if (appData.alwaysPromoteToQueen) {
6997 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6999 XtSetArg(args[0], XtNleftBitmap, None);
7001 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
7005 void AnimateDraggingProc(w, event, prms, nprms)
7013 appData.animateDragging = !appData.animateDragging;
7015 if (appData.animateDragging) {
7016 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7019 XtSetArg(args[0], XtNleftBitmap, None);
7021 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Dragging"),
7025 void AnimateMovingProc(w, event, prms, nprms)
7033 appData.animate = !appData.animate;
7035 if (appData.animate) {
7036 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7039 XtSetArg(args[0], XtNleftBitmap, None);
7041 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
7045 void AutocommProc(w, event, prms, nprms)
7053 appData.autoComment = !appData.autoComment;
7055 if (appData.autoComment) {
7056 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7058 XtSetArg(args[0], XtNleftBitmap, None);
7060 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
7065 void AutoflagProc(w, event, prms, nprms)
7073 appData.autoCallFlag = !appData.autoCallFlag;
7075 if (appData.autoCallFlag) {
7076 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7078 XtSetArg(args[0], XtNleftBitmap, None);
7080 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
7084 void AutoflipProc(w, event, prms, nprms)
7092 appData.autoFlipView = !appData.autoFlipView;
7094 if (appData.autoFlipView) {
7095 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7097 XtSetArg(args[0], XtNleftBitmap, None);
7099 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flip View"),
7103 void AutobsProc(w, event, prms, nprms)
7111 appData.autoObserve = !appData.autoObserve;
7113 if (appData.autoObserve) {
7114 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7116 XtSetArg(args[0], XtNleftBitmap, None);
7118 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
7122 void AutoraiseProc(w, event, prms, nprms)
7130 appData.autoRaiseBoard = !appData.autoRaiseBoard;
7132 if (appData.autoRaiseBoard) {
7133 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7135 XtSetArg(args[0], XtNleftBitmap, None);
7137 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Raise Board"),
7141 void AutosaveProc(w, event, prms, nprms)
7149 appData.autoSaveGames = !appData.autoSaveGames;
7151 if (appData.autoSaveGames) {
7152 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7154 XtSetArg(args[0], XtNleftBitmap, None);
7156 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
7160 void BlindfoldProc(w, event, prms, nprms)
7168 appData.blindfold = !appData.blindfold;
7170 if (appData.blindfold) {
7171 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7173 XtSetArg(args[0], XtNleftBitmap, None);
7175 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Blindfold"),
7178 DrawPosition(True, NULL);
7181 void TestLegalityProc(w, event, prms, nprms)
7189 appData.testLegality = !appData.testLegality;
7191 if (appData.testLegality) {
7192 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7194 XtSetArg(args[0], XtNleftBitmap, None);
7196 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Test Legality"),
7201 void FlashMovesProc(w, event, prms, nprms)
7209 if (appData.flashCount == 0) {
7210 appData.flashCount = 3;
7212 appData.flashCount = -appData.flashCount;
7215 if (appData.flashCount > 0) {
7216 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7218 XtSetArg(args[0], XtNleftBitmap, None);
7220 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flash Moves"),
7224 void FlipViewProc(w, event, prms, nprms)
7230 flipView = !flipView;
7231 DrawPosition(True, NULL);
7234 void GetMoveListProc(w, event, prms, nprms)
7242 appData.getMoveList = !appData.getMoveList;
7244 if (appData.getMoveList) {
7245 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7248 XtSetArg(args[0], XtNleftBitmap, None);
7250 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
7255 void HighlightDraggingProc(w, event, prms, nprms)
7263 appData.highlightDragging = !appData.highlightDragging;
7265 if (appData.highlightDragging) {
7266 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7268 XtSetArg(args[0], XtNleftBitmap, None);
7270 XtSetValues(XtNameToWidget(menuBarWidget,
7271 "menuOptions.Highlight Dragging"), args, 1);
7275 void HighlightLastMoveProc(w, event, prms, nprms)
7283 appData.highlightLastMove = !appData.highlightLastMove;
7285 if (appData.highlightLastMove) {
7286 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7288 XtSetArg(args[0], XtNleftBitmap, None);
7290 XtSetValues(XtNameToWidget(menuBarWidget,
7291 "menuOptions.Highlight Last Move"), args, 1);
7294 void IcsAlarmProc(w, event, prms, nprms)
7302 appData.icsAlarm = !appData.icsAlarm;
7304 if (appData.icsAlarm) {
7305 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7307 XtSetArg(args[0], XtNleftBitmap, None);
7309 XtSetValues(XtNameToWidget(menuBarWidget,
7310 "menuOptions.ICS Alarm"), args, 1);
7313 void MoveSoundProc(w, event, prms, nprms)
7321 appData.ringBellAfterMoves = !appData.ringBellAfterMoves;
7323 if (appData.ringBellAfterMoves) {
7324 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7326 XtSetArg(args[0], XtNleftBitmap, None);
7328 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
7333 void OldSaveStyleProc(w, event, prms, nprms)
7341 appData.oldSaveStyle = !appData.oldSaveStyle;
7343 if (appData.oldSaveStyle) {
7344 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7346 XtSetArg(args[0], XtNleftBitmap, None);
7348 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Old Save Style"),
7352 void PeriodicUpdatesProc(w, event, prms, nprms)
7360 PeriodicUpdatesEvent(!appData.periodicUpdates);
7362 if (appData.periodicUpdates) {
7363 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7365 XtSetArg(args[0], XtNleftBitmap, None);
7367 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Periodic Updates"),
7371 void PonderNextMoveProc(w, event, prms, nprms)
7379 PonderNextMoveEvent(!appData.ponderNextMove);
7381 if (appData.ponderNextMove) {
7382 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7384 XtSetArg(args[0], XtNleftBitmap, None);
7386 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Ponder Next Move"),
7390 void PopupExitMessageProc(w, event, prms, nprms)
7398 appData.popupExitMessage = !appData.popupExitMessage;
7400 if (appData.popupExitMessage) {
7401 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7403 XtSetArg(args[0], XtNleftBitmap, None);
7405 XtSetValues(XtNameToWidget(menuBarWidget,
7406 "menuOptions.Popup Exit Message"), args, 1);
7409 void PopupMoveErrorsProc(w, event, prms, nprms)
7417 appData.popupMoveErrors = !appData.popupMoveErrors;
7419 if (appData.popupMoveErrors) {
7420 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7422 XtSetArg(args[0], XtNleftBitmap, None);
7424 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Popup Move Errors"),
7428 void PremoveProc(w, event, prms, nprms)
7436 appData.premove = !appData.premove;
7438 if (appData.premove) {
7439 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7441 XtSetArg(args[0], XtNleftBitmap, None);
7443 XtSetValues(XtNameToWidget(menuBarWidget,
7444 "menuOptions.Premove"), args, 1);
7447 void QuietPlayProc(w, event, prms, nprms)
7455 appData.quietPlay = !appData.quietPlay;
7457 if (appData.quietPlay) {
7458 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7460 XtSetArg(args[0], XtNleftBitmap, None);
7462 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Quiet Play"),
7466 void ShowCoordsProc(w, event, prms, nprms)
7474 appData.showCoords = !appData.showCoords;
7476 if (appData.showCoords) {
7477 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7479 XtSetArg(args[0], XtNleftBitmap, None);
7481 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
7484 DrawPosition(True, NULL);
7487 void ShowThinkingProc(w, event, prms, nprms)
7495 appData.showThinking = !appData.showThinking; // [HGM] thinking: tken out of ShowThinkingEvent
7496 ShowThinkingEvent();
7499 void HideThinkingProc(w, event, prms, nprms)
7507 appData.hideThinkingFromHuman = !appData.hideThinkingFromHuman; // [HGM] thinking: tken out of ShowThinkingEvent
7508 ShowThinkingEvent();
7510 if (appData.hideThinkingFromHuman) {
7511 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7513 XtSetArg(args[0], XtNleftBitmap, None);
7515 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
7519 void InfoProc(w, event, prms, nprms)
7526 snprintf(buf, sizeof(buf), "xterm -e info --directory %s --directory . -f %s &",
7531 void ManProc(w, event, prms, nprms)
7539 if (nprms && *nprms > 0)
7543 snprintf(buf, sizeof(buf), "xterm -e man %s &", name);
7547 void HintProc(w, event, prms, nprms)
7556 void BookProc(w, event, prms, nprms)
7565 void AboutProc(w, event, prms, nprms)
7573 char *zippy = " (with Zippy code)";
7577 snprintf(buf, sizeof(buf), "%s%s\n\n%s\n%s\n%s\n\n%s%s\n%s",
7578 programVersion, zippy,
7579 "Copyright 1991 Digital Equipment Corporation",
7580 "Enhancements Copyright 1992-2009 Free Software Foundation",
7581 "Enhancements Copyright 2005 Alessandro Scotti",
7582 PACKAGE, " is free software and carries NO WARRANTY;",
7583 "see the file COPYING for more information.");
7584 ErrorPopUp(_("About XBoard"), buf, FALSE);
7587 void DebugProc(w, event, prms, nprms)
7593 appData.debugMode = !appData.debugMode;
7596 void AboutGameProc(w, event, prms, nprms)
7605 void NothingProc(w, event, prms, nprms)
7614 void Iconify(w, event, prms, nprms)
7623 XtSetArg(args[0], XtNiconic, True);
7624 XtSetValues(shellWidget, args, 1);
7627 void DisplayMessage(message, extMessage)
7628 char *message, *extMessage;
7630 /* display a message in the message widget */
7639 snprintf(buf, sizeof(buf), "%s %s", message, extMessage);
7644 message = extMessage;
7648 /* need to test if messageWidget already exists, since this function
7649 can also be called during the startup, if for example a Xresource
7650 is not set up correctly */
7653 XtSetArg(arg, XtNlabel, message);
7654 XtSetValues(messageWidget, &arg, 1);
7660 void DisplayTitle(text)
7665 char title[MSG_SIZ];
7668 if (text == NULL) text = "";
7670 if (appData.titleInWindow) {
7672 XtSetArg(args[i], XtNlabel, text); i++;
7673 XtSetValues(titleWidget, args, i);
7676 if (*text != NULLCHAR) {
7678 strcpy(title, text);
7679 } else if (appData.icsActive) {
7680 snprintf(icon, sizeof(icon), "%s", appData.icsHost);
7681 snprintf(title, sizeof(title), "%s: %s", programName, appData.icsHost);
7682 } else if (appData.cmailGameName[0] != NULLCHAR) {
7683 snprintf(icon, sizeof(icon), "%s", "CMail");
7684 snprintf(title,sizeof(title), "%s: %s", programName, "CMail");
7686 // [HGM] license: This stuff should really be done in back-end, but WinBoard already had a pop-up for it
7687 } else if (gameInfo.variant == VariantGothic) {
7688 strcpy(icon, programName);
7689 strcpy(title, GOTHIC);
7692 } else if (gameInfo.variant == VariantFalcon) {
7693 strcpy(icon, programName);
7694 strcpy(title, FALCON);
7696 } else if (appData.noChessProgram) {
7697 strcpy(icon, programName);
7698 strcpy(title, programName);
7700 strcpy(icon, first.tidy);
7701 snprintf(title,sizeof(title), "%s: %s", programName, first.tidy);
7704 XtSetArg(args[i], XtNiconName, (XtArgVal) icon); i++;
7705 XtSetArg(args[i], XtNtitle, (XtArgVal) title); i++;
7706 XtSetValues(shellWidget, args, i);
7710 void DisplayError(message, error)
7717 if (appData.debugMode || appData.matchMode) {
7718 fprintf(stderr, "%s: %s\n", programName, message);
7721 if (appData.debugMode || appData.matchMode) {
7722 fprintf(stderr, "%s: %s: %s\n",
7723 programName, message, strerror(error));
7725 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
7728 ErrorPopUp(_("Error"), message, FALSE);
7732 void DisplayMoveError(message)
7737 DrawPosition(FALSE, NULL);
7738 if (appData.debugMode || appData.matchMode) {
7739 fprintf(stderr, "%s: %s\n", programName, message);
7741 if (appData.popupMoveErrors) {
7742 ErrorPopUp(_("Error"), message, FALSE);
7744 DisplayMessage(message, "");
7749 void DisplayFatalError(message, error, status)
7755 errorExitStatus = status;
7757 fprintf(stderr, "%s: %s\n", programName, message);
7759 fprintf(stderr, "%s: %s: %s\n",
7760 programName, message, strerror(error));
7761 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
7764 if (appData.popupExitMessage && boardWidget && XtIsRealized(boardWidget)) {
7765 ErrorPopUp(status ? _("Fatal Error") : _("Exiting"), message, TRUE);
7771 void DisplayInformation(message)
7775 ErrorPopUp(_("Information"), message, TRUE);
7778 void DisplayNote(message)
7782 ErrorPopUp(_("Note"), message, FALSE);
7786 NullXErrorCheck(dpy, error_event)
7788 XErrorEvent *error_event;
7793 void DisplayIcsInteractionTitle(message)
7796 if (oldICSInteractionTitle == NULL) {
7797 /* Magic to find the old window title, adapted from vim */
7798 char *wina = getenv("WINDOWID");
7800 Window win = (Window) atoi(wina);
7801 Window root, parent, *children;
7802 unsigned int nchildren;
7803 int (*oldHandler)() = XSetErrorHandler(NullXErrorCheck);
7805 if (XFetchName(xDisplay, win, &oldICSInteractionTitle)) break;
7806 if (!XQueryTree(xDisplay, win, &root, &parent,
7807 &children, &nchildren)) break;
7808 if (children) XFree((void *)children);
7809 if (parent == root || parent == 0) break;
7812 XSetErrorHandler(oldHandler);
7814 if (oldICSInteractionTitle == NULL) {
7815 oldICSInteractionTitle = "xterm";
7818 printf("\033]0;%s\007", message);
7822 char pendingReplyPrefix[MSG_SIZ];
7823 ProcRef pendingReplyPR;
7825 void AskQuestionProc(w, event, prms, nprms)
7832 fprintf(stderr, _("AskQuestionProc needed 4 parameters, got %d\n"),
7836 AskQuestionEvent(prms[0], prms[1], prms[2], prms[3]);
7839 void AskQuestionPopDown()
7841 if (!askQuestionUp) return;
7842 XtPopdown(askQuestionShell);
7843 XtDestroyWidget(askQuestionShell);
7844 askQuestionUp = False;
7847 void AskQuestionReplyAction(w, event, prms, nprms)
7857 reply = XawDialogGetValueString(w = XtParent(w));
7858 strcpy(buf, pendingReplyPrefix);
7859 if (*buf) strcat(buf, " ");
7862 OutputToProcess(pendingReplyPR, buf, strlen(buf), &err);
7863 AskQuestionPopDown();
7865 if (err) DisplayFatalError(_("Error writing to chess program"), err, 0);
7868 void AskQuestionCallback(w, client_data, call_data)
7870 XtPointer client_data, call_data;
7875 XtSetArg(args[0], XtNlabel, &name);
7876 XtGetValues(w, args, 1);
7878 if (strcmp(name, _("cancel")) == 0) {
7879 AskQuestionPopDown();
7881 AskQuestionReplyAction(w, NULL, NULL, NULL);
7885 void AskQuestion(title, question, replyPrefix, pr)
7886 char *title, *question, *replyPrefix;
7890 Widget popup, layout, dialog, edit;
7896 strcpy(pendingReplyPrefix, replyPrefix);
7897 pendingReplyPR = pr;
7900 XtSetArg(args[i], XtNresizable, True); i++;
7901 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
7902 askQuestionShell = popup =
7903 XtCreatePopupShell(title, transientShellWidgetClass,
7904 shellWidget, args, i);
7907 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
7908 layoutArgs, XtNumber(layoutArgs));
7911 XtSetArg(args[i], XtNlabel, question); i++;
7912 XtSetArg(args[i], XtNvalue, ""); i++;
7913 XtSetArg(args[i], XtNborderWidth, 0); i++;
7914 dialog = XtCreateManagedWidget("question", dialogWidgetClass,
7917 XawDialogAddButton(dialog, _("enter"), AskQuestionCallback,
7918 (XtPointer) dialog);
7919 XawDialogAddButton(dialog, _("cancel"), AskQuestionCallback,
7920 (XtPointer) dialog);
7922 XtRealizeWidget(popup);
7923 CatchDeleteWindow(popup, "AskQuestionPopDown");
7925 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
7926 &x, &y, &win_x, &win_y, &mask);
7928 XtSetArg(args[0], XtNx, x - 10);
7929 XtSetArg(args[1], XtNy, y - 30);
7930 XtSetValues(popup, args, 2);
7932 XtPopup(popup, XtGrabExclusive);
7933 askQuestionUp = True;
7935 edit = XtNameToWidget(dialog, "*value");
7936 XtSetKeyboardFocus(popup, edit);
7944 if (*name == NULLCHAR) {
7946 } else if (strcmp(name, "$") == 0) {
7947 putc(BELLCHAR, stderr);
7950 snprintf(buf, sizeof(buf), "%s '%s' &", appData.soundProgram, name);
7958 PlaySound(appData.soundMove);
7964 PlaySound(appData.soundIcsWin);
7970 PlaySound(appData.soundIcsLoss);
7976 PlaySound(appData.soundIcsDraw);
7980 PlayIcsUnfinishedSound()
7982 PlaySound(appData.soundIcsUnfinished);
7988 PlaySound(appData.soundIcsAlarm);
7994 system("stty echo");
8000 system("stty -echo");
8004 Colorize(cc, continuation)
8009 int count, outCount, error;
8011 if (textColors[(int)cc].bg > 0) {
8012 if (textColors[(int)cc].fg > 0) {
8013 sprintf(buf, "\033[0;%d;%d;%dm", textColors[(int)cc].attr,
8014 textColors[(int)cc].fg, textColors[(int)cc].bg);
8016 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
8017 textColors[(int)cc].bg);
8020 if (textColors[(int)cc].fg > 0) {
8021 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
8022 textColors[(int)cc].fg);
8024 sprintf(buf, "\033[0;%dm", textColors[(int)cc].attr);
8027 count = strlen(buf);
8028 outCount = OutputToProcess(NoProc, buf, count, &error);
8029 if (outCount < count) {
8030 DisplayFatalError(_("Error writing to display"), error, 1);
8033 if (continuation) return;
8036 PlaySound(appData.soundShout);
8039 PlaySound(appData.soundSShout);
8042 PlaySound(appData.soundChannel1);
8045 PlaySound(appData.soundChannel);
8048 PlaySound(appData.soundKibitz);
8051 PlaySound(appData.soundTell);
8053 case ColorChallenge:
8054 PlaySound(appData.soundChallenge);
8057 PlaySound(appData.soundRequest);
8060 PlaySound(appData.soundSeek);
8071 return getpwuid(getuid())->pw_name;
8074 static char *ExpandPathName(path)
8077 static char static_buf[2000];
8078 char *d, *s, buf[2000];
8084 while (*s && isspace(*s))
8093 if (*(s+1) == '/') {
8094 strcpy(d, getpwuid(getuid())->pw_dir);
8099 *strchr(buf, '/') = 0;
8100 pwd = getpwnam(buf);
8103 fprintf(stderr, _("ERROR: Unknown user %s (in path %s)\n"),
8107 strcpy(d, pwd->pw_dir);
8108 strcat(d, strchr(s+1, '/'));
8119 static char host_name[MSG_SIZ];
8121 #if HAVE_GETHOSTNAME
8122 gethostname(host_name, MSG_SIZ);
8124 #else /* not HAVE_GETHOSTNAME */
8125 # if HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H
8126 sysinfo(SI_HOSTNAME, host_name, MSG_SIZ);
8128 # else /* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
8130 # endif/* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
8131 #endif /* not HAVE_GETHOSTNAME */
8134 XtIntervalId delayedEventTimerXID = 0;
8135 DelayedEventCallback delayedEventCallback = 0;
8140 delayedEventTimerXID = 0;
8141 delayedEventCallback();
8145 ScheduleDelayedEvent(cb, millisec)
8146 DelayedEventCallback cb; long millisec;
8148 if(delayedEventTimerXID && delayedEventCallback == cb)
8149 // [HGM] alive: replace, rather than add or flush identical event
8150 XtRemoveTimeOut(delayedEventTimerXID);
8151 delayedEventCallback = cb;
8152 delayedEventTimerXID =
8153 XtAppAddTimeOut(appContext, millisec,
8154 (XtTimerCallbackProc) FireDelayedEvent, (XtPointer) 0);
8157 DelayedEventCallback
8160 if (delayedEventTimerXID) {
8161 return delayedEventCallback;
8168 CancelDelayedEvent()
8170 if (delayedEventTimerXID) {
8171 XtRemoveTimeOut(delayedEventTimerXID);
8172 delayedEventTimerXID = 0;
8176 XtIntervalId loadGameTimerXID = 0;
8178 int LoadGameTimerRunning()
8180 return loadGameTimerXID != 0;
8183 int StopLoadGameTimer()
8185 if (loadGameTimerXID != 0) {
8186 XtRemoveTimeOut(loadGameTimerXID);
8187 loadGameTimerXID = 0;
8195 LoadGameTimerCallback(arg, id)
8199 loadGameTimerXID = 0;
8204 StartLoadGameTimer(millisec)
8208 XtAppAddTimeOut(appContext, millisec,
8209 (XtTimerCallbackProc) LoadGameTimerCallback,
8213 XtIntervalId analysisClockXID = 0;
8216 AnalysisClockCallback(arg, id)
8220 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile
8221 || appData.icsEngineAnalyze) { // [DM]
8222 AnalysisPeriodicEvent(0);
8223 StartAnalysisClock();
8228 StartAnalysisClock()
8231 XtAppAddTimeOut(appContext, 2000,
8232 (XtTimerCallbackProc) AnalysisClockCallback,
8236 XtIntervalId clockTimerXID = 0;
8238 int ClockTimerRunning()
8240 return clockTimerXID != 0;
8243 int StopClockTimer()
8245 if (clockTimerXID != 0) {
8246 XtRemoveTimeOut(clockTimerXID);
8255 ClockTimerCallback(arg, id)
8264 StartClockTimer(millisec)
8268 XtAppAddTimeOut(appContext, millisec,
8269 (XtTimerCallbackProc) ClockTimerCallback,
8274 DisplayTimerLabel(w, color, timer, highlight)
8283 /* check for low time warning */
8284 Pixel foregroundOrWarningColor = timerForegroundPixel;
8287 appData.lowTimeWarning &&
8288 (timer / 1000) < appData.icsAlarmTime)
8289 foregroundOrWarningColor = lowTimeWarningColor;
8291 if (appData.clockMode) {
8292 sprintf(buf, "%s: %s", color, TimeString(timer));
8293 XtSetArg(args[0], XtNlabel, buf);
8295 sprintf(buf, "%s ", color);
8296 XtSetArg(args[0], XtNlabel, buf);
8301 XtSetArg(args[1], XtNbackground, foregroundOrWarningColor);
8302 XtSetArg(args[2], XtNforeground, timerBackgroundPixel);
8304 XtSetArg(args[1], XtNbackground, timerBackgroundPixel);
8305 XtSetArg(args[2], XtNforeground, foregroundOrWarningColor);
8308 XtSetValues(w, args, 3);
8312 DisplayWhiteClock(timeRemaining, highlight)
8318 if(appData.noGUI) return;
8319 DisplayTimerLabel(whiteTimerWidget, _("White"), timeRemaining, highlight);
8320 if (highlight && iconPixmap == bIconPixmap) {
8321 iconPixmap = wIconPixmap;
8322 XtSetArg(args[0], XtNiconPixmap, iconPixmap);
8323 XtSetValues(shellWidget, args, 1);
8328 DisplayBlackClock(timeRemaining, highlight)
8334 if(appData.noGUI) return;
8335 DisplayTimerLabel(blackTimerWidget, _("Black"), timeRemaining, highlight);
8336 if (highlight && iconPixmap == wIconPixmap) {
8337 iconPixmap = bIconPixmap;
8338 XtSetArg(args[0], XtNiconPixmap, iconPixmap);
8339 XtSetValues(shellWidget, args, 1);
8357 int StartChildProcess(cmdLine, dir, pr)
8364 int to_prog[2], from_prog[2];
8368 if (appData.debugMode) {
8369 fprintf(stderr, "StartChildProcess (dir=\"%s\") %s\n",dir, cmdLine);
8372 /* We do NOT feed the cmdLine to the shell; we just
8373 parse it into blank-separated arguments in the
8374 most simple-minded way possible.
8377 strcpy(buf, cmdLine);
8382 if (p == NULL) break;
8387 SetUpChildIO(to_prog, from_prog);
8389 if ((pid = fork()) == 0) {
8391 // [HGM] PSWBTM: made order resistant against case where fd of created pipe was 0 or 1
8392 close(to_prog[1]); // first close the unused pipe ends
8393 close(from_prog[0]);
8394 dup2(to_prog[0], 0); // to_prog was created first, nd is the only one to use 0 or 1
8395 dup2(from_prog[1], 1);
8396 if(to_prog[0] >= 2) close(to_prog[0]); // if 0 or 1, the dup2 already cosed the original
8397 close(from_prog[1]); // and closing again loses one of the pipes!
8398 if(fileno(stderr) >= 2) // better safe than sorry...
8399 dup2(1, fileno(stderr)); /* force stderr to the pipe */
8401 if (dir[0] != NULLCHAR && chdir(dir) != 0) {
8406 nice(appData.niceEngines); // [HGM] nice: adjust priority of engine proc
8408 execvp(argv[0], argv);
8410 /* If we get here, exec failed */
8415 /* Parent process */
8417 close(from_prog[1]);
8419 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8422 cp->fdFrom = from_prog[0];
8423 cp->fdTo = to_prog[1];
8428 // [HGM] kill: implement the 'hard killing' of AS's Winboard_x
8429 static RETSIGTYPE AlarmCallBack(int n)
8435 DestroyChildProcess(pr, signalType)
8439 ChildProc *cp = (ChildProc *) pr;
8441 if (cp->kind != CPReal) return;
8443 if (signalType == 10) { // [HGM] kill: if it does not terminate in 3 sec, kill
8444 signal(SIGALRM, AlarmCallBack);
8446 if(wait((int *) 0) == -1) { // process does not terminate on its own accord
8447 kill(cp->pid, SIGKILL); // kill it forcefully
8448 wait((int *) 0); // and wait again
8452 kill(cp->pid, signalType == 9 ? SIGKILL : SIGTERM); // [HGM] kill: use hard kill if so requested
8454 /* Process is exiting either because of the kill or because of
8455 a quit command sent by the backend; either way, wait for it to die.
8464 InterruptChildProcess(pr)
8467 ChildProc *cp = (ChildProc *) pr;
8469 if (cp->kind != CPReal) return;
8470 (void) kill(cp->pid, SIGINT); /* stop it thinking */
8473 int OpenTelnet(host, port, pr)
8478 char cmdLine[MSG_SIZ];
8480 if (port[0] == NULLCHAR) {
8481 snprintf(cmdLine, sizeof(cmdLine), "%s %s", appData.telnetProgram, host);
8483 snprintf(cmdLine, sizeof(cmdLine), "%s %s %s", appData.telnetProgram, host, port);
8485 return StartChildProcess(cmdLine, "", pr);
8488 int OpenTCP(host, port, pr)
8494 DisplayFatalError(_("Socket support is not configured in"), 0, 2);
8495 #else /* !OMIT_SOCKETS */
8497 struct sockaddr_in sa;
8499 unsigned short uport;
8502 if ((s = socket(AF_INET, SOCK_STREAM, 6)) < 0) {
8506 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
8507 sa.sin_family = AF_INET;
8508 sa.sin_addr.s_addr = INADDR_ANY;
8509 uport = (unsigned short) 0;
8510 sa.sin_port = htons(uport);
8511 if (bind(s, (struct sockaddr *) &sa, sizeof(struct sockaddr_in)) < 0) {
8515 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
8516 if (!(hp = gethostbyname(host))) {
8518 if (sscanf(host, "%d.%d.%d.%d", &b0, &b1, &b2, &b3) == 4) {
8519 hp = (struct hostent *) calloc(1, sizeof(struct hostent));
8520 hp->h_addrtype = AF_INET;
8522 hp->h_addr_list = (char **) calloc(2, sizeof(char *));
8523 hp->h_addr_list[0] = (char *) malloc(4);
8524 hp->h_addr_list[0][0] = b0;
8525 hp->h_addr_list[0][1] = b1;
8526 hp->h_addr_list[0][2] = b2;
8527 hp->h_addr_list[0][3] = b3;
8532 sa.sin_family = hp->h_addrtype;
8533 uport = (unsigned short) atoi(port);
8534 sa.sin_port = htons(uport);
8535 memcpy((char *) &sa.sin_addr, hp->h_addr, hp->h_length);
8537 if (connect(s, (struct sockaddr *) &sa,
8538 sizeof(struct sockaddr_in)) < 0) {
8542 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8549 #endif /* !OMIT_SOCKETS */
8554 int OpenCommPort(name, pr)
8561 fd = open(name, 2, 0);
8562 if (fd < 0) return errno;
8564 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8574 int OpenLoopback(pr)
8580 SetUpChildIO(to, from);
8582 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8585 cp->fdFrom = to[0]; /* note not from[0]; we are doing a loopback */
8592 int OpenRcmd(host, user, cmd, pr)
8593 char *host, *user, *cmd;
8596 DisplayFatalError(_("internal rcmd not implemented for Unix"), 0, 1);
8600 #define INPUT_SOURCE_BUF_SIZE 8192
8609 char buf[INPUT_SOURCE_BUF_SIZE];
8614 DoInputCallback(closure, source, xid)
8619 InputSource *is = (InputSource *) closure;
8624 if (is->lineByLine) {
8625 count = read(is->fd, is->unused,
8626 INPUT_SOURCE_BUF_SIZE - (is->unused - is->buf));
8628 (is->func)(is, is->closure, is->buf, count, count ? errno : 0);
8631 is->unused += count;
8633 while (p < is->unused) {
8634 q = memchr(p, '\n', is->unused - p);
8635 if (q == NULL) break;
8637 (is->func)(is, is->closure, p, q - p, 0);
8641 while (p < is->unused) {
8646 count = read(is->fd, is->buf, INPUT_SOURCE_BUF_SIZE);
8651 (is->func)(is, is->closure, is->buf, count, error);
8655 InputSourceRef AddInputSource(pr, lineByLine, func, closure)
8662 ChildProc *cp = (ChildProc *) pr;
8664 is = (InputSource *) calloc(1, sizeof(InputSource));
8665 is->lineByLine = lineByLine;
8669 is->fd = fileno(stdin);
8671 is->kind = cp->kind;
8672 is->fd = cp->fdFrom;
8675 is->unused = is->buf;
8678 is->xid = XtAppAddInput(appContext, is->fd,
8679 (XtPointer) (XtInputReadMask),
8680 (XtInputCallbackProc) DoInputCallback,
8682 is->closure = closure;
8683 return (InputSourceRef) is;
8687 RemoveInputSource(isr)
8690 InputSource *is = (InputSource *) isr;
8692 if (is->xid == 0) return;
8693 XtRemoveInput(is->xid);
8697 int OutputToProcess(pr, message, count, outError)
8703 ChildProc *cp = (ChildProc *) pr;
8707 outCount = fwrite(message, 1, count, stdout);
8709 outCount = write(cp->fdTo, message, count);
8719 /* Output message to process, with "ms" milliseconds of delay
8720 between each character. This is needed when sending the logon
8721 script to ICC, which for some reason doesn't like the
8722 instantaneous send. */
8723 int OutputToProcessDelayed(pr, message, count, outError, msdelay)
8730 ChildProc *cp = (ChildProc *) pr;
8735 r = write(cp->fdTo, message++, 1);
8748 /**** Animation code by Hugh Fisher, DCS, ANU.
8750 Known problem: if a window overlapping the board is
8751 moved away while a piece is being animated underneath,
8752 the newly exposed area won't be updated properly.
8753 I can live with this.
8755 Known problem: if you look carefully at the animation
8756 of pieces in mono mode, they are being drawn as solid
8757 shapes without interior detail while moving. Fixing
8758 this would be a major complication for minimal return.
8761 /* Masks for XPM pieces. Black and white pieces can have
8762 different shapes, but in the interest of retaining my
8763 sanity pieces must have the same outline on both light
8764 and dark squares, and all pieces must use the same
8765 background square colors/images. */
8767 static int xpmDone = 0;
8770 CreateAnimMasks (pieceDepth)
8777 unsigned long plane;
8780 /* Need a bitmap just to get a GC with right depth */
8781 buf = XCreatePixmap(xDisplay, xBoardWindow,
8783 values.foreground = 1;
8784 values.background = 0;
8785 /* Don't use XtGetGC, not read only */
8786 maskGC = XCreateGC(xDisplay, buf,
8787 GCForeground | GCBackground, &values);
8788 XFreePixmap(xDisplay, buf);
8790 buf = XCreatePixmap(xDisplay, xBoardWindow,
8791 squareSize, squareSize, pieceDepth);
8792 values.foreground = XBlackPixel(xDisplay, xScreen);
8793 values.background = XWhitePixel(xDisplay, xScreen);
8794 bufGC = XCreateGC(xDisplay, buf,
8795 GCForeground | GCBackground, &values);
8797 for (piece = WhitePawn; piece <= BlackKing; piece++) {
8798 /* Begin with empty mask */
8799 if(!xpmDone) // [HGM] pieces: keep using existing
8800 xpmMask[piece] = XCreatePixmap(xDisplay, xBoardWindow,
8801 squareSize, squareSize, 1);
8802 XSetFunction(xDisplay, maskGC, GXclear);
8803 XFillRectangle(xDisplay, xpmMask[piece], maskGC,
8804 0, 0, squareSize, squareSize);
8806 /* Take a copy of the piece */
8811 XSetFunction(xDisplay, bufGC, GXcopy);
8812 XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % (int)BlackPawn],
8814 0, 0, squareSize, squareSize, 0, 0);
8816 /* XOR the background (light) over the piece */
8817 XSetFunction(xDisplay, bufGC, GXxor);
8819 XCopyArea(xDisplay, xpmLightSquare, buf, bufGC,
8820 0, 0, squareSize, squareSize, 0, 0);
8822 XSetForeground(xDisplay, bufGC, lightSquareColor);
8823 XFillRectangle(xDisplay, buf, bufGC, 0, 0, squareSize, squareSize);
8826 /* We now have an inverted piece image with the background
8827 erased. Construct mask by just selecting all the non-zero
8828 pixels - no need to reconstruct the original image. */
8829 XSetFunction(xDisplay, maskGC, GXor);
8831 /* Might be quicker to download an XImage and create bitmap
8832 data from it rather than this N copies per piece, but it
8833 only takes a fraction of a second and there is a much
8834 longer delay for loading the pieces. */
8835 for (n = 0; n < pieceDepth; n ++) {
8836 XCopyPlane(xDisplay, buf, xpmMask[piece], maskGC,
8837 0, 0, squareSize, squareSize,
8843 XFreePixmap(xDisplay, buf);
8844 XFreeGC(xDisplay, bufGC);
8845 XFreeGC(xDisplay, maskGC);
8849 InitAnimState (anim, info)
8851 XWindowAttributes * info;
8856 /* Each buffer is square size, same depth as window */
8857 anim->saveBuf = XCreatePixmap(xDisplay, xBoardWindow,
8858 squareSize, squareSize, info->depth);
8859 anim->newBuf = XCreatePixmap(xDisplay, xBoardWindow,
8860 squareSize, squareSize, info->depth);
8862 /* Create a plain GC for blitting */
8863 mask = GCForeground | GCBackground | GCFunction |
8864 GCPlaneMask | GCGraphicsExposures;
8865 values.foreground = XBlackPixel(xDisplay, xScreen);
8866 values.background = XWhitePixel(xDisplay, xScreen);
8867 values.function = GXcopy;
8868 values.plane_mask = AllPlanes;
8869 values.graphics_exposures = False;
8870 anim->blitGC = XCreateGC(xDisplay, xBoardWindow, mask, &values);
8872 /* Piece will be copied from an existing context at
8873 the start of each new animation/drag. */
8874 anim->pieceGC = XCreateGC(xDisplay, xBoardWindow, 0, &values);
8876 /* Outline will be a read-only copy of an existing */
8877 anim->outlineGC = None;
8883 static VariantClass old = (VariantClass) -1; // [HGM] pieces: redo every time variant changes
8884 XWindowAttributes info;
8886 if (xpmDone && gameInfo.variant == old) return;
8887 if(xpmDone) old = gameInfo.variant; // first time pieces might not be created yet
8888 XGetWindowAttributes(xDisplay, xBoardWindow, &info);
8890 InitAnimState(&game, &info);
8891 InitAnimState(&player, &info);
8893 /* For XPM pieces, we need bitmaps to use as masks. */
8895 CreateAnimMasks(info.depth);
8901 static Boolean frameWaiting;
8903 static RETSIGTYPE FrameAlarm (sig)
8906 frameWaiting = False;
8907 /* In case System-V style signals. Needed?? */
8908 signal(SIGALRM, FrameAlarm);
8915 struct itimerval delay;
8917 XSync(xDisplay, False);
8920 frameWaiting = True;
8921 signal(SIGALRM, FrameAlarm);
8922 delay.it_interval.tv_sec =
8923 delay.it_value.tv_sec = time / 1000;
8924 delay.it_interval.tv_usec =
8925 delay.it_value.tv_usec = (time % 1000) * 1000;
8926 setitimer(ITIMER_REAL, &delay, NULL);
8927 while (frameWaiting) pause();
8928 delay.it_interval.tv_sec = delay.it_value.tv_sec = 0;
8929 delay.it_interval.tv_usec = delay.it_value.tv_usec = 0;
8930 setitimer(ITIMER_REAL, &delay, NULL);
8940 XSync(xDisplay, False);
8942 usleep(time * 1000);
8947 /* Convert board position to corner of screen rect and color */
8950 ScreenSquare(column, row, pt, color)
8951 int column; int row; XPoint * pt; int * color;
8954 pt->x = lineGap + ((BOARD_WIDTH-1)-column) * (squareSize + lineGap);
8955 pt->y = lineGap + row * (squareSize + lineGap);
8957 pt->x = lineGap + column * (squareSize + lineGap);
8958 pt->y = lineGap + ((BOARD_HEIGHT-1)-row) * (squareSize + lineGap);
8960 *color = SquareColor(row, column);
8963 /* Convert window coords to square */
8966 BoardSquare(x, y, column, row)
8967 int x; int y; int * column; int * row;
8969 *column = EventToSquare(x, BOARD_WIDTH);
8970 if (flipView && *column >= 0)
8971 *column = BOARD_WIDTH - 1 - *column;
8972 *row = EventToSquare(y, BOARD_HEIGHT);
8973 if (!flipView && *row >= 0)
8974 *row = BOARD_HEIGHT - 1 - *row;
8979 #undef Max /* just in case */
8981 #define Max(a, b) ((a) > (b) ? (a) : (b))
8982 #define Min(a, b) ((a) < (b) ? (a) : (b))
8985 SetRect(rect, x, y, width, height)
8986 XRectangle * rect; int x; int y; int width; int height;
8990 rect->width = width;
8991 rect->height = height;
8994 /* Test if two frames overlap. If they do, return
8995 intersection rect within old and location of
8996 that rect within new. */
8999 Intersect(old, new, size, area, pt)
9000 XPoint * old; XPoint * new;
9001 int size; XRectangle * area; XPoint * pt;
9003 if (old->x > new->x + size || new->x > old->x + size ||
9004 old->y > new->y + size || new->y > old->y + size) {
9007 SetRect(area, Max(new->x - old->x, 0), Max(new->y - old->y, 0),
9008 size - abs(old->x - new->x), size - abs(old->y - new->y));
9009 pt->x = Max(old->x - new->x, 0);
9010 pt->y = Max(old->y - new->y, 0);
9015 /* For two overlapping frames, return the rect(s)
9016 in the old that do not intersect with the new. */
9019 CalcUpdateRects(old, new, size, update, nUpdates)
9020 XPoint * old; XPoint * new; int size;
9021 XRectangle update[]; int * nUpdates;
9025 /* If old = new (shouldn't happen) then nothing to draw */
9026 if (old->x == new->x && old->y == new->y) {
9030 /* Work out what bits overlap. Since we know the rects
9031 are the same size we don't need a full intersect calc. */
9033 /* Top or bottom edge? */
9034 if (new->y > old->y) {
9035 SetRect(&(update[count]), old->x, old->y, size, new->y - old->y);
9037 } else if (old->y > new->y) {
9038 SetRect(&(update[count]), old->x, old->y + size - (old->y - new->y),
9039 size, old->y - new->y);
9042 /* Left or right edge - don't overlap any update calculated above. */
9043 if (new->x > old->x) {
9044 SetRect(&(update[count]), old->x, Max(new->y, old->y),
9045 new->x - old->x, size - abs(new->y - old->y));
9047 } else if (old->x > new->x) {
9048 SetRect(&(update[count]), new->x + size, Max(new->y, old->y),
9049 old->x - new->x, size - abs(new->y - old->y));
9056 /* Generate a series of frame coords from start->mid->finish.
9057 The movement rate doubles until the half way point is
9058 reached, then halves back down to the final destination,
9059 which gives a nice slow in/out effect. The algorithmn
9060 may seem to generate too many intermediates for short
9061 moves, but remember that the purpose is to attract the
9062 viewers attention to the piece about to be moved and
9063 then to where it ends up. Too few frames would be less
9067 Tween(start, mid, finish, factor, frames, nFrames)
9068 XPoint * start; XPoint * mid;
9069 XPoint * finish; int factor;
9070 XPoint frames[]; int * nFrames;
9072 int fraction, n, count;
9076 /* Slow in, stepping 1/16th, then 1/8th, ... */
9078 for (n = 0; n < factor; n++)
9080 for (n = 0; n < factor; n++) {
9081 frames[count].x = start->x + (mid->x - start->x) / fraction;
9082 frames[count].y = start->y + (mid->y - start->y) / fraction;
9084 fraction = fraction / 2;
9088 frames[count] = *mid;
9091 /* Slow out, stepping 1/2, then 1/4, ... */
9093 for (n = 0; n < factor; n++) {
9094 frames[count].x = finish->x - (finish->x - mid->x) / fraction;
9095 frames[count].y = finish->y - (finish->y - mid->y) / fraction;
9097 fraction = fraction * 2;
9102 /* Draw a piece on the screen without disturbing what's there */
9105 SelectGCMask(piece, clip, outline, mask)
9106 ChessSquare piece; GC * clip; GC * outline; Pixmap * mask;
9110 /* Bitmap for piece being moved. */
9111 if (appData.monoMode) {
9112 *mask = *pieceToSolid(piece);
9113 } else if (useImages) {
9115 *mask = xpmMask[piece];
9117 *mask = ximMaskPm[piece];
9120 *mask = *pieceToSolid(piece);
9123 /* GC for piece being moved. Square color doesn't matter, but
9124 since it gets modified we make a copy of the original. */
9126 if (appData.monoMode)
9131 if (appData.monoMode)
9136 XCopyGC(xDisplay, source, 0xFFFFFFFF, *clip);
9138 /* Outline only used in mono mode and is not modified */
9140 *outline = bwPieceGC;
9142 *outline = wbPieceGC;
9146 OverlayPiece(piece, clip, outline, dest)
9147 ChessSquare piece; GC clip; GC outline; Drawable dest;
9152 /* Draw solid rectangle which will be clipped to shape of piece */
9153 XFillRectangle(xDisplay, dest, clip,
9154 0, 0, squareSize, squareSize);
9155 if (appData.monoMode)
9156 /* Also draw outline in contrasting color for black
9157 on black / white on white cases */
9158 XCopyPlane(xDisplay, *pieceToOutline(piece), dest, outline,
9159 0, 0, squareSize, squareSize, 0, 0, 1);
9161 /* Copy the piece */
9166 XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
9168 0, 0, squareSize, squareSize,
9173 /* Animate the movement of a single piece */
9176 BeginAnimation(anim, piece, startColor, start)
9184 /* The old buffer is initialised with the start square (empty) */
9185 BlankSquare(0, 0, startColor, EmptySquare, anim->saveBuf);
9186 anim->prevFrame = *start;
9188 /* The piece will be drawn using its own bitmap as a matte */
9189 SelectGCMask(piece, &anim->pieceGC, &anim->outlineGC, &mask);
9190 XSetClipMask(xDisplay, anim->pieceGC, mask);
9194 AnimationFrame(anim, frame, piece)
9199 XRectangle updates[4];
9204 /* Save what we are about to draw into the new buffer */
9205 XCopyArea(xDisplay, xBoardWindow, anim->newBuf, anim->blitGC,
9206 frame->x, frame->y, squareSize, squareSize,
9209 /* Erase bits of the previous frame */
9210 if (Intersect(&anim->prevFrame, frame, squareSize, &overlap, &pt)) {
9211 /* Where the new frame overlapped the previous,
9212 the contents in newBuf are wrong. */
9213 XCopyArea(xDisplay, anim->saveBuf, anim->newBuf, anim->blitGC,
9214 overlap.x, overlap.y,
9215 overlap.width, overlap.height,
9217 /* Repaint the areas in the old that don't overlap new */
9218 CalcUpdateRects(&anim->prevFrame, frame, squareSize, updates, &count);
9219 for (i = 0; i < count; i++)
9220 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9221 updates[i].x - anim->prevFrame.x,
9222 updates[i].y - anim->prevFrame.y,
9223 updates[i].width, updates[i].height,
9224 updates[i].x, updates[i].y);
9226 /* Easy when no overlap */
9227 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9228 0, 0, squareSize, squareSize,
9229 anim->prevFrame.x, anim->prevFrame.y);
9232 /* Save this frame for next time round */
9233 XCopyArea(xDisplay, anim->newBuf, anim->saveBuf, anim->blitGC,
9234 0, 0, squareSize, squareSize,
9236 anim->prevFrame = *frame;
9238 /* Draw piece over original screen contents, not current,
9239 and copy entire rect. Wipes out overlapping piece images. */
9240 OverlayPiece(piece, anim->pieceGC, anim->outlineGC, anim->newBuf);
9241 XCopyArea(xDisplay, anim->newBuf, xBoardWindow, anim->blitGC,
9242 0, 0, squareSize, squareSize,
9243 frame->x, frame->y);
9247 EndAnimation (anim, finish)
9251 XRectangle updates[4];
9256 /* The main code will redraw the final square, so we
9257 only need to erase the bits that don't overlap. */
9258 if (Intersect(&anim->prevFrame, finish, squareSize, &overlap, &pt)) {
9259 CalcUpdateRects(&anim->prevFrame, finish, squareSize, updates, &count);
9260 for (i = 0; i < count; i++)
9261 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9262 updates[i].x - anim->prevFrame.x,
9263 updates[i].y - anim->prevFrame.y,
9264 updates[i].width, updates[i].height,
9265 updates[i].x, updates[i].y);
9267 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9268 0, 0, squareSize, squareSize,
9269 anim->prevFrame.x, anim->prevFrame.y);
9274 FrameSequence(anim, piece, startColor, start, finish, frames, nFrames)
9276 ChessSquare piece; int startColor;
9277 XPoint * start; XPoint * finish;
9278 XPoint frames[]; int nFrames;
9282 BeginAnimation(anim, piece, startColor, start);
9283 for (n = 0; n < nFrames; n++) {
9284 AnimationFrame(anim, &(frames[n]), piece);
9285 FrameDelay(appData.animSpeed);
9287 EndAnimation(anim, finish);
9290 /* Main control logic for deciding what to animate and how */
9293 AnimateMove(board, fromX, fromY, toX, toY)
9302 XPoint start, finish, mid;
9303 XPoint frames[kFactor * 2 + 1];
9304 int nFrames, startColor, endColor;
9306 /* Are we animating? */
9307 if (!appData.animate || appData.blindfold)
9310 if(board[toY][toX] == WhiteRook && board[fromY][fromX] == WhiteKing ||
9311 board[toY][toX] == BlackRook && board[fromY][fromX] == BlackKing)
9312 return; // [HGM] FRC: no animtion of FRC castlings, as to-square is not true to-square
9314 if (fromY < 0 || fromX < 0 || toX < 0 || toY < 0) return;
9315 piece = board[fromY][fromX];
9316 if (piece >= EmptySquare) return;
9321 hop = (piece == WhiteKnight || piece == BlackKnight);
9324 if (appData.debugMode) {
9325 fprintf(debugFP, hop ? _("AnimateMove: piece %d hops from %d,%d to %d,%d \n") :
9326 _("AnimateMove: piece %d slides from %d,%d to %d,%d \n"),
9327 piece, fromX, fromY, toX, toY); }
9329 ScreenSquare(fromX, fromY, &start, &startColor);
9330 ScreenSquare(toX, toY, &finish, &endColor);
9333 /* Knight: make diagonal movement then straight */
9334 if (abs(toY - fromY) < abs(toX - fromX)) {
9335 mid.x = start.x + (finish.x - start.x) / 2;
9339 mid.y = start.y + (finish.y - start.y) / 2;
9342 mid.x = start.x + (finish.x - start.x) / 2;
9343 mid.y = start.y + (finish.y - start.y) / 2;
9346 /* Don't use as many frames for very short moves */
9347 if (abs(toY - fromY) + abs(toX - fromX) <= 2)
9348 Tween(&start, &mid, &finish, kFactor - 1, frames, &nFrames);
9350 Tween(&start, &mid, &finish, kFactor, frames, &nFrames);
9351 FrameSequence(&game, piece, startColor, &start, &finish, frames, nFrames);
9353 /* Be sure end square is redrawn */
9354 damage[toY][toX] = True;
9358 DragPieceBegin(x, y)
9361 int boardX, boardY, color;
9364 /* Are we animating? */
9365 if (!appData.animateDragging || appData.blindfold)
9368 /* Figure out which square we start in and the
9369 mouse position relative to top left corner. */
9370 BoardSquare(x, y, &boardX, &boardY);
9371 player.startBoardX = boardX;
9372 player.startBoardY = boardY;
9373 ScreenSquare(boardX, boardY, &corner, &color);
9374 player.startSquare = corner;
9375 player.startColor = color;
9376 /* As soon as we start dragging, the piece will jump slightly to
9377 be centered over the mouse pointer. */
9378 player.mouseDelta.x = squareSize/2;
9379 player.mouseDelta.y = squareSize/2;
9380 /* Initialise animation */
9381 player.dragPiece = PieceForSquare(boardX, boardY);
9383 if (player.dragPiece >= 0 && player.dragPiece < EmptySquare) {
9384 player.dragActive = True;
9385 BeginAnimation(&player, player.dragPiece, color, &corner);
9386 /* Mark this square as needing to be redrawn. Note that
9387 we don't remove the piece though, since logically (ie
9388 as seen by opponent) the move hasn't been made yet. */
9389 if(boardX == BOARD_RGHT+1 && PieceForSquare(boardX-1, boardY) > 1 ||
9390 boardX == BOARD_LEFT-2 && PieceForSquare(boardX+1, boardY) > 1)
9391 XCopyArea(xDisplay, xBoardWindow, player.saveBuf, player.blitGC,
9392 corner.x, corner.y, squareSize, squareSize,
9393 0, 0); // [HGM] zh: unstack in stead of grab
9394 damage[boardY][boardX] = True;
9396 player.dragActive = False;
9406 /* Are we animating? */
9407 if (!appData.animateDragging || appData.blindfold)
9411 if (! player.dragActive)
9413 /* Move piece, maintaining same relative position
9414 of mouse within square */
9415 corner.x = x - player.mouseDelta.x;
9416 corner.y = y - player.mouseDelta.y;
9417 AnimationFrame(&player, &corner, player.dragPiece);
9419 if (appData.highlightDragging) {
9421 BoardSquare(x, y, &boardX, &boardY);
9422 SetHighlights(fromX, fromY, boardX, boardY);
9431 int boardX, boardY, color;
9434 /* Are we animating? */
9435 if (!appData.animateDragging || appData.blindfold)
9439 if (! player.dragActive)
9441 /* Last frame in sequence is square piece is
9442 placed on, which may not match mouse exactly. */
9443 BoardSquare(x, y, &boardX, &boardY);
9444 ScreenSquare(boardX, boardY, &corner, &color);
9445 EndAnimation(&player, &corner);
9447 /* Be sure end square is redrawn */
9448 damage[boardY][boardX] = True;
9450 /* This prevents weird things happening with fast successive
9451 clicks which on my Sun at least can cause motion events
9452 without corresponding press/release. */
9453 player.dragActive = False;
9456 /* Handle expose event while piece being dragged */
9461 if (!player.dragActive || appData.blindfold)
9464 /* What we're doing: logically, the move hasn't been made yet,
9465 so the piece is still in it's original square. But visually
9466 it's being dragged around the board. So we erase the square
9467 that the piece is on and draw it at the last known drag point. */
9468 BlankSquare(player.startSquare.x, player.startSquare.y,
9469 player.startColor, EmptySquare, xBoardWindow);
9470 AnimationFrame(&player, &player.prevFrame, player.dragPiece);
9471 damage[player.startBoardY][player.startBoardX] = TRUE;
9475 SetProgramStats( FrontEndProgramStats * stats )
9478 // [HGM] done, but perhaps backend should call this directly?
9479 EngineOutputUpdate( stats );