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},
1410 { "keepLineBreaksICS", "keepLineBreaksICS", XtRBoolean,
1411 sizeof(Boolean), XtOffset(AppDataPtr, noJoin),
1412 XtRImmediate, (XtPointer) True},
1415 XrmOptionDescRec shellOptions[] = {
1416 { "-whitePieceColor", "whitePieceColor", XrmoptionSepArg, NULL },
1417 { "-blackPieceColor", "blackPieceColor", XrmoptionSepArg, NULL },
1418 { "-lightSquareColor", "lightSquareColor", XrmoptionSepArg, NULL },
1419 { "-darkSquareColor", "darkSquareColor", XrmoptionSepArg, NULL },
1420 { "-highlightSquareColor", "highlightSquareColor", XrmoptionSepArg, NULL },
1421 { "-premoveHighlightColor", "premoveHighlightColor", XrmoptionSepArg,NULL},
1422 { "-movesPerSession", "movesPerSession", XrmoptionSepArg, NULL },
1423 { "-mps", "movesPerSession", XrmoptionSepArg, NULL },
1424 { "-timeIncrement", "timeIncrement", XrmoptionSepArg, NULL },
1425 { "-inc", "timeIncrement", XrmoptionSepArg, NULL },
1426 { "-initString", "initString", XrmoptionSepArg, NULL },
1427 { "-firstInitString", "initString", XrmoptionSepArg, NULL },
1428 { "-secondInitString", "secondInitString", XrmoptionSepArg, NULL },
1429 { "-firstComputerString", "firstComputerString", XrmoptionSepArg, NULL },
1430 { "-secondComputerString", "secondComputerString", XrmoptionSepArg, NULL },
1431 { "-firstChessProgram", "firstChessProgram", XrmoptionSepArg, NULL },
1432 { "-fcp", "firstChessProgram", XrmoptionSepArg, NULL },
1433 { "-secondChessProgram", "secondChessProgram", XrmoptionSepArg, NULL },
1434 { "-scp", "secondChessProgram", XrmoptionSepArg, NULL },
1435 { "-firstPlaysBlack", "firstPlaysBlack", XrmoptionSepArg, NULL },
1436 { "-fb", "firstPlaysBlack", XrmoptionNoArg, "True" },
1437 { "-xfb", "firstPlaysBlack", XrmoptionNoArg, "False" },
1438 { "-noChessProgram", "noChessProgram", XrmoptionSepArg, NULL },
1439 { "-ncp", "noChessProgram", XrmoptionNoArg, "True" },
1440 { "-xncp", "noChessProgram", XrmoptionNoArg, "False" },
1441 { "-firstHost", "firstHost", XrmoptionSepArg, NULL },
1442 { "-fh", "firstHost", XrmoptionSepArg, NULL },
1443 { "-secondHost", "secondHost", XrmoptionSepArg, NULL },
1444 { "-sh", "secondHost", XrmoptionSepArg, NULL },
1445 { "-firstDirectory", "firstDirectory", XrmoptionSepArg, NULL },
1446 { "-fd", "firstDirectory", XrmoptionSepArg, NULL },
1447 { "-secondDirectory", "secondDirectory", XrmoptionSepArg, NULL },
1448 { "-sd", "secondDirectory", XrmoptionSepArg, NULL },
1449 { "-bitmapDirectory", "bitmapDirectory", XrmoptionSepArg, NULL },
1450 { "-bm", "bitmapDirectory", XrmoptionSepArg, NULL },
1451 { "-remoteShell", "remoteShell", XrmoptionSepArg, NULL },
1452 { "-rsh", "remoteShell", XrmoptionSepArg, NULL },
1453 { "-remoteUser", "remoteUser", XrmoptionSepArg, NULL },
1454 { "-ruser", "remoteUser", XrmoptionSepArg, NULL },
1455 { "-timeDelay", "timeDelay", XrmoptionSepArg, NULL },
1456 { "-td", "timeDelay", XrmoptionSepArg, NULL },
1457 { "-timeControl", "timeControl", XrmoptionSepArg, NULL },
1458 { "-tc", "timeControl", XrmoptionSepArg, NULL },
1459 { "-internetChessServerMode", "internetChessServerMode",
1460 XrmoptionSepArg, NULL },
1461 { "-ics", "internetChessServerMode", XrmoptionNoArg, "True" },
1462 { "-xics", "internetChessServerMode", XrmoptionNoArg, "False" },
1463 { "-internetChessServerHost", "internetChessServerHost",
1464 XrmoptionSepArg, NULL },
1465 { "-icshost", "internetChessServerHost", XrmoptionSepArg, NULL },
1466 { "-internetChessServerPort", "internetChessServerPort",
1467 XrmoptionSepArg, NULL },
1468 { "-icsport", "internetChessServerPort", XrmoptionSepArg, NULL },
1469 { "-internetChessServerCommPort", "internetChessServerCommPort",
1470 XrmoptionSepArg, NULL },
1471 { "-icscomm", "internetChessServerCommPort", XrmoptionSepArg, NULL },
1472 { "-internetChessServerLogonScript", "internetChessServerLogonScript",
1473 XrmoptionSepArg, NULL },
1474 { "-icslogon", "internetChessServerLogonScript", XrmoptionSepArg, NULL },
1475 { "-internetChessServerHelper", "internetChessServerHelper",
1476 XrmoptionSepArg, NULL },
1477 { "-icshelper", "internetChessServerHelper", XrmoptionSepArg, NULL },
1478 { "-internetChessServerInputBox", "internetChessServerInputBox",
1479 XrmoptionSepArg, NULL },
1480 { "-icsinput", "internetChessServerInputBox", XrmoptionNoArg, "True" },
1481 { "-xicsinput", "internetChessServerInputBox", XrmoptionNoArg, "False" },
1482 { "-icsAlarm", "icsAlarm", XrmoptionSepArg, NULL },
1483 { "-alarm", "icsAlarm", XrmoptionNoArg, "True" },
1484 { "-xalarm", "icsAlarm", XrmoptionNoArg, "False" },
1485 { "-icsAlarmTime", "icsAlarmTime", XrmoptionSepArg, NULL },
1486 { "-useTelnet", "useTelnet", XrmoptionSepArg, NULL },
1487 { "-telnet", "useTelnet", XrmoptionNoArg, "True" },
1488 { "-xtelnet", "useTelnet", XrmoptionNoArg, "False" },
1489 { "-telnetProgram", "telnetProgram", XrmoptionSepArg, NULL },
1490 { "-gateway", "gateway", XrmoptionSepArg, NULL },
1491 { "-loadGameFile", "loadGameFile", XrmoptionSepArg, NULL },
1492 { "-lgf", "loadGameFile", XrmoptionSepArg, NULL },
1493 { "-loadGameIndex", "loadGameIndex", XrmoptionSepArg, NULL },
1494 { "-lgi", "loadGameIndex", XrmoptionSepArg, NULL },
1495 { "-saveGameFile", "saveGameFile", XrmoptionSepArg, NULL },
1496 { "-sgf", "saveGameFile", XrmoptionSepArg, NULL },
1497 { "-autoSaveGames", "autoSaveGames", XrmoptionSepArg, NULL },
1498 { "-autosave", "autoSaveGames", XrmoptionNoArg, "True" },
1499 { "-xautosave", "autoSaveGames", XrmoptionNoArg, "False" },
1500 { "-autoRaiseBoard", "autoRaiseBoard", XrmoptionSepArg, NULL },
1501 { "-autoraise", "autoRaiseBoard", XrmoptionNoArg, "True" },
1502 { "-xautoraise", "autoRaiseBoard", XrmoptionNoArg, "False" },
1503 { "-blindfold", "blindfold", XrmoptionSepArg, NULL },
1504 { "-blind", "blindfold", XrmoptionNoArg, "True" },
1505 { "-xblind", "blindfold", XrmoptionNoArg, "False" },
1506 { "-loadPositionFile", "loadPositionFile", XrmoptionSepArg, NULL },
1507 { "-lpf", "loadPositionFile", XrmoptionSepArg, NULL },
1508 { "-loadPositionIndex", "loadPositionIndex", XrmoptionSepArg, NULL },
1509 { "-lpi", "loadPositionIndex", XrmoptionSepArg, NULL },
1510 { "-savePositionFile", "savePositionFile", XrmoptionSepArg, NULL },
1511 { "-spf", "savePositionFile", XrmoptionSepArg, NULL },
1512 { "-matchMode", "matchMode", XrmoptionSepArg, NULL },
1513 { "-mm", "matchMode", XrmoptionNoArg, "True" },
1514 { "-xmm", "matchMode", XrmoptionNoArg, "False" },
1515 { "-matchGames", "matchGames", XrmoptionSepArg, NULL },
1516 { "-mg", "matchGames", XrmoptionSepArg, NULL },
1517 { "-monoMode", "monoMode", XrmoptionSepArg, NULL },
1518 { "-mono", "monoMode", XrmoptionNoArg, "True" },
1519 { "-xmono", "monoMode", XrmoptionNoArg, "False" },
1520 { "-debugMode", "debugMode", XrmoptionSepArg, NULL },
1521 { "-debug", "debugMode", XrmoptionNoArg, "True" },
1522 { "-xdebug", "debugMode", XrmoptionNoArg, "False" },
1523 { "-clockMode", "clockMode", XrmoptionSepArg, NULL },
1524 { "-clock", "clockMode", XrmoptionNoArg, "True" },
1525 { "-xclock", "clockMode", XrmoptionNoArg, "False" },
1526 { "-boardSize", "boardSize", XrmoptionSepArg, NULL },
1527 { "-size", "boardSize", XrmoptionSepArg, NULL },
1528 { "-searchTime", "searchTime", XrmoptionSepArg, NULL },
1529 { "-st", "searchTime", XrmoptionSepArg, NULL },
1530 { "-searchDepth", "searchDepth", XrmoptionSepArg, NULL },
1531 { "-depth", "searchDepth", XrmoptionSepArg, NULL },
1532 { "-showCoords", "showCoords", XrmoptionSepArg, NULL },
1533 { "-coords", "showCoords", XrmoptionNoArg, "True" },
1534 { "-xcoords", "showCoords", XrmoptionNoArg, "False" },
1536 { "-showJail", "showJail", XrmoptionSepArg, NULL },
1537 { "-jail", "showJail", XrmoptionNoArg, "1" },
1538 { "-sidejail", "showJail", XrmoptionNoArg, "2" },
1539 { "-xjail", "showJail", XrmoptionNoArg, "0" },
1541 { "-showThinking", "showThinking", XrmoptionSepArg, NULL },
1542 { "-thinking", "showThinking", XrmoptionNoArg, "True" },
1543 { "-xthinking", "showThinking", XrmoptionNoArg, "False" },
1544 { "-ponderNextMove", "ponderNextMove", XrmoptionSepArg, NULL },
1545 { "-ponder", "ponderNextMove", XrmoptionNoArg, "True" },
1546 { "-xponder", "ponderNextMove", XrmoptionNoArg, "False" },
1547 { "-periodicUpdates", "periodicUpdates", XrmoptionSepArg, NULL },
1548 { "-periodic", "periodicUpdates", XrmoptionNoArg, "True" },
1549 { "-xperiodic", "periodicUpdates", XrmoptionNoArg, "False" },
1550 { "-clockFont", "clockFont", XrmoptionSepArg, NULL },
1551 { "-coordFont", "coordFont", XrmoptionSepArg, NULL },
1552 { "-font", "font", XrmoptionSepArg, NULL },
1553 { "-ringBellAfterMoves", "ringBellAfterMoves", XrmoptionSepArg, NULL },
1554 { "-bell", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1555 { "-xbell", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1556 { "-movesound", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1557 { "-xmovesound", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1558 { "-autoCallFlag", "autoCallFlag", XrmoptionSepArg, NULL },
1559 { "-autoflag", "autoCallFlag", XrmoptionNoArg, "True" },
1560 { "-xautoflag", "autoCallFlag", XrmoptionNoArg, "False" },
1561 { "-autoFlipView", "autoFlipView", XrmoptionSepArg, NULL },
1562 { "-autoflip", "autoFlipView", XrmoptionNoArg, "True" },
1563 { "-xautoflip", "autoFlipView", XrmoptionNoArg, "False" },
1564 { "-autoObserve", "autoObserve", XrmoptionSepArg, NULL },
1565 { "-autobs", "autoObserve", XrmoptionNoArg, "True" },
1566 { "-xautobs", "autoObserve", XrmoptionNoArg, "False" },
1567 { "-autoComment", "autoComment", XrmoptionSepArg, NULL },
1568 { "-autocomm", "autoComment", XrmoptionNoArg, "True" },
1569 { "-xautocomm", "autoComment", XrmoptionNoArg, "False" },
1570 { "-getMoveList", "getMoveList", XrmoptionSepArg, NULL },
1571 { "-moves", "getMoveList", XrmoptionNoArg, "True" },
1572 { "-xmoves", "getMoveList", XrmoptionNoArg, "False" },
1574 { "-highlightDragging", "highlightDragging", XrmoptionSepArg, NULL },
1575 { "-highdrag", "highlightDragging", XrmoptionNoArg, "True" },
1576 { "-xhighdrag", "highlightDragging", XrmoptionNoArg, "False" },
1578 { "-highlightLastMove", "highlightLastMove", XrmoptionSepArg, NULL },
1579 { "-highlight", "highlightLastMove", XrmoptionNoArg, "True" },
1580 { "-xhighlight", "highlightLastMove", XrmoptionNoArg, "False" },
1581 { "-premove", "premove", XrmoptionSepArg, NULL },
1582 { "-pre", "premove", XrmoptionNoArg, "True" },
1583 { "-xpre", "premove", XrmoptionNoArg, "False" },
1584 { "-testLegality", "testLegality", XrmoptionSepArg, NULL },
1585 { "-legal", "testLegality", XrmoptionNoArg, "True" },
1586 { "-xlegal", "testLegality", XrmoptionNoArg, "False" },
1587 { "-flipView", "flipView", XrmoptionSepArg, NULL },
1588 { "-flip", "flipView", XrmoptionNoArg, "True" },
1589 { "-xflip", "flipView", XrmoptionNoArg, "False" },
1590 { "-cmail", "cmailGameName", XrmoptionSepArg, NULL },
1591 { "-alwaysPromoteToQueen", "alwaysPromoteToQueen",
1592 XrmoptionSepArg, NULL },
1593 { "-queen", "alwaysPromoteToQueen", XrmoptionNoArg, "True" },
1594 { "-xqueen", "alwaysPromoteToQueen", XrmoptionNoArg, "False" },
1595 { "-oldSaveStyle", "oldSaveStyle", XrmoptionSepArg, NULL },
1596 { "-oldsave", "oldSaveStyle", XrmoptionNoArg, "True" },
1597 { "-xoldsave", "oldSaveStyle", XrmoptionNoArg, "False" },
1598 { "-quietPlay", "quietPlay", XrmoptionSepArg, NULL },
1599 { "-quiet", "quietPlay", XrmoptionNoArg, "True" },
1600 { "-xquiet", "quietPlay", XrmoptionNoArg, "False" },
1601 { "-titleInWindow", "titleInWindow", XrmoptionSepArg, NULL },
1602 { "-title", "titleInWindow", XrmoptionNoArg, "True" },
1603 { "-xtitle", "titleInWindow", XrmoptionNoArg, "False" },
1605 { "-zippyTalk", "zippyTalk", XrmoptionSepArg, NULL },
1606 { "-zt", "zippyTalk", XrmoptionNoArg, "True" },
1607 { "-xzt", "zippyTalk", XrmoptionNoArg, "False" },
1608 { "-zippyPlay", "zippyPlay", XrmoptionSepArg, NULL },
1609 { "-zp", "zippyPlay", XrmoptionNoArg, "True" },
1610 { "-xzp", "zippyPlay", XrmoptionNoArg, "False" },
1611 { "-zippyLines", "zippyLines", XrmoptionSepArg, NULL },
1612 { "-zippyPinhead", "zippyPinhead", XrmoptionSepArg, NULL },
1613 { "-zippyPassword", "zippyPassword", XrmoptionSepArg, NULL },
1614 { "-zippyPassword2", "zippyPassword2", XrmoptionSepArg, NULL },
1615 { "-zippyWrongPassword", "zippyWrongPassword", XrmoptionSepArg, NULL },
1616 { "-zippyAcceptOnly", "zippyAcceptOnly", XrmoptionSepArg, NULL },
1617 { "-zippyUseI", "zippyUseI", XrmoptionSepArg, NULL },
1618 { "-zui", "zippyUseI", XrmoptionNoArg, "True" },
1619 { "-xzui", "zippyUseI", XrmoptionNoArg, "False" },
1620 { "-zippyBughouse", "zippyBughouse", XrmoptionSepArg, NULL },
1621 { "-zippyNoplayCrafty", "zippyNoplayCrafty", XrmoptionSepArg, NULL },
1622 { "-znc", "zippyNoplayCrafty", XrmoptionNoArg, "True" },
1623 { "-xznc", "zippyNoplayCrafty", XrmoptionNoArg, "False" },
1624 { "-zippyGameEnd", "zippyGameEnd", XrmoptionSepArg, NULL },
1625 { "-zippyGameStart", "zippyGameStart", XrmoptionSepArg, NULL },
1626 { "-zippyAdjourn", "zippyAdjourn", XrmoptionSepArg, NULL },
1627 { "-zadj", "zippyAdjourn", XrmoptionNoArg, "True" },
1628 { "-xzadj", "zippyAdjourn", XrmoptionNoArg, "False" },
1629 { "-zippyAbort", "zippyAbort", XrmoptionSepArg, NULL },
1630 { "-zab", "zippyAbort", XrmoptionNoArg, "True" },
1631 { "-xzab", "zippyAbort", XrmoptionNoArg, "False" },
1632 { "-zippyVariants", "zippyVariants", XrmoptionSepArg, NULL },
1633 { "-zippyMaxGames", "zippyMaxGames", XrmoptionSepArg, NULL },
1634 { "-zippyReplayTimeout", "zippyReplayTimeout", XrmoptionSepArg, NULL },
1635 { "-zippyShortGame", "zippyShortGame", XrmoptionSepArg, NULL },
1637 { "-flashCount", "flashCount", XrmoptionSepArg, NULL },
1638 { "-flash", "flashCount", XrmoptionNoArg, "3" },
1639 { "-xflash", "flashCount", XrmoptionNoArg, "0" },
1640 { "-flashRate", "flashRate", XrmoptionSepArg, NULL },
1641 { "-pixmapDirectory", "pixmapDirectory", XrmoptionSepArg, NULL },
1642 { "-msLoginDelay", "msLoginDelay", XrmoptionSepArg, NULL },
1643 { "-pixmap", "pixmapDirectory", XrmoptionSepArg, NULL },
1644 { "-colorizeMessages", "colorizeMessages", XrmoptionSepArg, NULL },
1645 { "-colorize", "colorizeMessages", XrmoptionNoArg, "True" },
1646 { "-xcolorize", "colorizeMessages", XrmoptionNoArg, "False" },
1647 { "-colorShout", "colorShout", XrmoptionSepArg, NULL },
1648 { "-colorSShout", "colorSShout", XrmoptionSepArg, NULL },
1649 { "-colorCShout", "colorSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1650 { "-colorChannel1", "colorChannel1", XrmoptionSepArg, NULL },
1651 { "-colorChannel", "colorChannel", XrmoptionSepArg, NULL },
1652 { "-colorKibitz", "colorKibitz", XrmoptionSepArg, NULL },
1653 { "-colorTell", "colorTell", XrmoptionSepArg, NULL },
1654 { "-colorChallenge", "colorChallenge", XrmoptionSepArg, NULL },
1655 { "-colorRequest", "colorRequest", XrmoptionSepArg, NULL },
1656 { "-colorSeek", "colorSeek", XrmoptionSepArg, NULL },
1657 { "-colorNormal", "colorNormal", XrmoptionSepArg, NULL },
1658 { "-soundProgram", "soundProgram", XrmoptionSepArg, NULL },
1659 { "-soundShout", "soundShout", XrmoptionSepArg, NULL },
1660 { "-soundSShout", "soundSShout", XrmoptionSepArg, NULL },
1661 { "-soundCShout", "soundSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1662 { "-soundChannel1", "soundChannel1", XrmoptionSepArg, NULL },
1663 { "-soundChannel", "soundChannel", XrmoptionSepArg, NULL },
1664 { "-soundKibitz", "soundKibitz", XrmoptionSepArg, NULL },
1665 { "-soundTell", "soundTell", XrmoptionSepArg, NULL },
1666 { "-soundChallenge", "soundChallenge", XrmoptionSepArg, NULL },
1667 { "-soundRequest", "soundRequest", XrmoptionSepArg, NULL },
1668 { "-soundSeek", "soundSeek", XrmoptionSepArg, NULL },
1669 { "-soundMove", "soundMove", XrmoptionSepArg, NULL },
1670 { "-soundIcsWin", "soundIcsWin", XrmoptionSepArg, NULL },
1671 { "-soundIcsLoss", "soundIcsLoss", XrmoptionSepArg, NULL },
1672 { "-soundIcsDraw", "soundIcsDraw", XrmoptionSepArg, NULL },
1673 { "-soundIcsUnfinished", "soundIcsUnfinished", XrmoptionSepArg, NULL },
1674 { "-soundIcsAlarm", "soundIcsAlarm", XrmoptionSepArg, NULL },
1675 { "-reuseFirst", "reuseFirst", XrmoptionSepArg, NULL },
1676 { "-reuseChessPrograms", "reuseFirst", XrmoptionSepArg, NULL }, /*compat*/
1677 { "-reuse", "reuseFirst", XrmoptionNoArg, "True" },
1678 { "-xreuse", "reuseFirst", XrmoptionNoArg, "False" },
1679 { "-reuseSecond", "reuseSecond", XrmoptionSepArg, NULL },
1680 { "-reuse2", "reuseSecond", XrmoptionNoArg, "True" },
1681 { "-xreuse2", "reuseSecond", XrmoptionNoArg, "False" },
1682 { "-animateMoving", "animateMoving", XrmoptionSepArg, NULL },
1683 { "-animate", "animateMoving", XrmoptionNoArg, "True" },
1684 { "-xanimate", "animateMoving", XrmoptionNoArg, "False" },
1685 { "-animateDragging", "animateDragging", XrmoptionSepArg, NULL },
1686 { "-drag", "animateDragging", XrmoptionNoArg, "True" },
1687 { "-xdrag", "animateDragging", XrmoptionNoArg, "False" },
1688 { "-animateSpeed", "animateSpeed", XrmoptionSepArg, NULL },
1689 { "-popupExitMessage", "popupExitMessage", XrmoptionSepArg, NULL },
1690 { "-exit", "popupExitMessage", XrmoptionNoArg, "True" },
1691 { "-xexit", "popupExitMessage", XrmoptionNoArg, "False" },
1692 { "-popupMoveErrors", "popupMoveErrors", XrmoptionSepArg, NULL },
1693 { "-popup", "popupMoveErrors", XrmoptionNoArg, "True" },
1694 { "-xpopup", "popupMoveErrors", XrmoptionNoArg, "False" },
1695 { "-fontSizeTolerance", "fontSizeTolerance", XrmoptionSepArg, NULL },
1696 { "-initialMode", "initialMode", XrmoptionSepArg, NULL },
1697 { "-mode", "initialMode", XrmoptionSepArg, NULL },
1698 { "-variant", "variant", XrmoptionSepArg, NULL },
1699 { "-firstProtocolVersion", "firstProtocolVersion", XrmoptionSepArg, NULL },
1700 { "-secondProtocolVersion","secondProtocolVersion",XrmoptionSepArg, NULL },
1701 { "-showButtonBar", "showButtonBar", XrmoptionSepArg, NULL },
1702 { "-buttons", "showButtonBar", XrmoptionNoArg, "True" },
1703 { "-xbuttons", "showButtonBar", XrmoptionNoArg, "False" },
1704 { "-lowTimeWarningColor", "lowTimeWarningColor", XrmoptionSepArg, NULL },
1705 { "-lowTimeWarning", "lowTimeWarning", XrmoptionSepArg, NULL },
1706 /* [AS,HR] New features */
1707 { "-firstScoreAbs", "firstScoreAbs", XrmoptionSepArg, NULL },
1708 { "-secondScoreAbs", "secondScoreAbs", XrmoptionSepArg, NULL },
1709 { "-pgnExtendedInfo", "pgnExtendedInfo", XrmoptionSepArg, NULL },
1710 { "-hideThinkingFromHuman", "hideThinkingFromHuman", XrmoptionSepArg, NULL },
1711 { "-adjudicateLossThreshold", "adjudicateLossThreshold", XrmoptionSepArg, NULL },
1712 { "-adjudicateDrawMoves", "adjudicateDrawMoves", XrmoptionSepArg, NULL },
1713 { "-pgnEventHeader", "pgnEventHeader", XrmoptionSepArg, NULL },
1714 { "-firstIsUCI", "firstIsUCI", XrmoptionSepArg, NULL },
1715 { "-secondIsUCI", "secondIsUCI", XrmoptionSepArg, NULL },
1716 { "-fUCI", "firstIsUCI", XrmoptionNoArg, "True" },
1717 { "-sUCI", "secondIsUCI", XrmoptionNoArg, "True" },
1718 { "-firstHasOwnBookUCI", "firstHasOwnBookUCI", XrmoptionSepArg, NULL },
1719 { "-secondHasOwnBookUCI", "secondHasOwnBookUCI", XrmoptionSepArg, NULL },
1720 { "-fNoOwnBookUCI", "firstHasOwnBookUCI", XrmoptionNoArg, "False" },
1721 { "-sNoOwnBookUCI", "secondHasOwnBookUCI", XrmoptionNoArg, "False" },
1722 { "-firstXBook", "firstHasOwnBookUCI", XrmoptionNoArg, "False" },
1723 { "-secondXBook", "secondHasOwnBookUCI", XrmoptionNoArg, "False" },
1724 { "-polyglotDir", "polyglotDir", XrmoptionSepArg, NULL },
1725 { "-usePolyglotBook", "usePolyglotBook", XrmoptionSepArg, NULL },
1726 { "-polyglotBook", "polyglotBook", XrmoptionSepArg, NULL },
1727 { "-defaultHashSize", "defaultHashSize", XrmoptionSepArg, NULL },
1728 { "-defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XrmoptionSepArg, NULL },
1729 { "-defaultPathEGTB", "defaultPathEGTB", XrmoptionSepArg, NULL },
1730 { "-defaultFrcPosition", "defaultFrcPosition", XrmoptionSepArg, NULL },
1731 { "-gameListTags", "gameListTags", XrmoptionSepArg, NULL },
1732 // [HGM] I am sure AS added many more options, but we have to fish them out, from the list in winboard.c
1734 /* [HGM,HR] User-selectable board size */
1735 { "-boardWidth", "boardWidth", XrmoptionSepArg, NULL },
1736 { "-boardHeight", "boardHeight", XrmoptionSepArg, NULL },
1737 { "-matchPause", "matchPause", XrmoptionSepArg, NULL },
1739 /* [HGM] new arguments of 4.3.xx. All except first three are back-end options, which should work immediately */
1740 { "-holdingsSize", "holdingsSize", XrmoptionSepArg, NULL }, // requires extensive front-end changes to work
1741 { "-flipBlack", "flipBlack", XrmoptionSepArg, NULL }, // requires front-end changes to work
1742 { "-allWhite", "allWhite", XrmoptionSepArg, NULL }, // requires front-end changes to work
1743 { "-pieceToCharTable", "pieceToCharTable", XrmoptionSepArg, NULL },
1744 { "-alphaRank", "alphaRank", XrmoptionSepArg, NULL },
1745 { "-testClaims", "testClaims", XrmoptionSepArg, NULL },
1746 { "-checkMates", "checkMates", XrmoptionSepArg, NULL },
1747 { "-materialDraws", "materialDraws", XrmoptionSepArg, NULL },
1748 { "-trivialDraws", "trivialDraws", XrmoptionSepArg, NULL },
1749 { "-ruleMoves", "ruleMoves", XrmoptionSepArg, NULL },
1750 { "-repeatsToDraw", "repeatsToDraw", XrmoptionSepArg, NULL },
1751 { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL },
1752 { "-userName", "userName", XrmoptionSepArg, NULL },
1753 { "-autoKibitz", "autoKibitz", XrmoptionNoArg, "True" },
1754 { "-firstTimeOdds", "firstTimeOdds", XrmoptionSepArg, NULL },
1755 { "-secondTimeOdds", "secondTimeOdds", XrmoptionSepArg, NULL },
1756 { "-timeOddsMode", "timeOddsMode", XrmoptionSepArg, NULL },
1757 { "-firstAccumulateTC", "firstAccumulateTC", XrmoptionSepArg, NULL },
1758 { "-secondAccumulateTC", "secondAccumulateTC", XrmoptionSepArg, NULL },
1759 { "-firstNPS", "firstNPS", XrmoptionSepArg, NULL },
1760 { "-secondNPS", "secondNPS", XrmoptionSepArg, NULL },
1761 { "-serverMoves", "serverMoves", XrmoptionSepArg, NULL },
1762 { "-serverPause", "serverPause", XrmoptionSepArg, NULL },
1763 { "-suppressLoadMoves", "suppressLoadMoves", XrmoptionSepArg, NULL },
1764 { "-egtFormats", "egtFormats", XrmoptionSepArg, NULL },
1765 { "-userName", "userName", XrmoptionSepArg, NULL },
1766 { "-smpCores", "smpCores", XrmoptionSepArg, NULL },
1767 { "-sameColorGames", "sameColorGames", XrmoptionSepArg, NULL },
1768 { "-rewindIndex", "rewindIndex", XrmoptionSepArg, NULL },
1769 { "-niceEngines", "niceEngines", XrmoptionSepArg, NULL },
1770 { "-delayBeforeQuit", "delayBeforeQuit", XrmoptionSepArg, NULL },
1771 { "-delayAfterQuit", "delayAfterQuit", XrmoptionSepArg, NULL },
1772 { "-nameOfDebugFile", "nameOfDebugFile", XrmoptionSepArg, NULL },
1773 { "-debugFile", "nameOfDebugFile", XrmoptionSepArg, NULL },
1774 { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL },
1775 { "-noGUI", "noGUI", XrmoptionNoArg, "True" },
1776 { "-firstOptions", "firstOptions", XrmoptionSepArg, NULL },
1777 { "-secondOptions", "secondOptions", XrmoptionSepArg, NULL },
1778 { "-firstNeedsNoncompliantFEN", "firstNeedsNoncompliantFEN", XrmoptionSepArg, NULL },
1779 { "-secondNeedsNoncompliantFEN", "secondNeedsNoncompliantFEN", XrmoptionSepArg, NULL },
1780 { "-keepAlive", "keepAlive", XrmoptionSepArg, NULL },
1781 { "-forceIllegalMoves", "forceIllegalMoves", XrmoptionNoArg, "True" },
1782 { "-keepLineBreaksICS", "keepLineBreaksICS", XrmoptionSepArg, NULL },
1786 XtActionsRec boardActions[] = {
1787 { "DrawPosition", DrawPositionProc },
1788 { "HandleUserMove", HandleUserMove },
1789 { "AnimateUserMove", AnimateUserMove },
1790 { "FileNameAction", FileNameAction },
1791 { "AskQuestionProc", AskQuestionProc },
1792 { "AskQuestionReplyAction", AskQuestionReplyAction },
1793 { "PieceMenuPopup", PieceMenuPopup },
1794 { "WhiteClock", WhiteClock },
1795 { "BlackClock", BlackClock },
1796 { "Iconify", Iconify },
1797 { "ResetProc", ResetProc },
1798 { "LoadGameProc", LoadGameProc },
1799 { "LoadNextGameProc", LoadNextGameProc },
1800 { "LoadPrevGameProc", LoadPrevGameProc },
1801 { "LoadSelectedProc", LoadSelectedProc },
1802 { "ReloadGameProc", ReloadGameProc },
1803 { "LoadPositionProc", LoadPositionProc },
1804 { "LoadNextPositionProc", LoadNextPositionProc },
1805 { "LoadPrevPositionProc", LoadPrevPositionProc },
1806 { "ReloadPositionProc", ReloadPositionProc },
1807 { "CopyPositionProc", CopyPositionProc },
1808 { "PastePositionProc", PastePositionProc },
1809 { "CopyGameProc", CopyGameProc },
1810 { "PasteGameProc", PasteGameProc },
1811 { "SaveGameProc", SaveGameProc },
1812 { "SavePositionProc", SavePositionProc },
1813 { "MailMoveProc", MailMoveProc },
1814 { "ReloadCmailMsgProc", ReloadCmailMsgProc },
1815 { "QuitProc", QuitProc },
1816 { "MachineWhiteProc", MachineWhiteProc },
1817 { "MachineBlackProc", MachineBlackProc },
1818 { "AnalysisModeProc", AnalyzeModeProc },
1819 { "AnalyzeFileProc", AnalyzeFileProc },
1820 { "TwoMachinesProc", TwoMachinesProc },
1821 { "IcsClientProc", IcsClientProc },
1822 { "EditGameProc", EditGameProc },
1823 { "EditPositionProc", EditPositionProc },
1824 { "TrainingProc", EditPositionProc },
1825 { "EngineOutputProc", EngineOutputProc}, // [HGM] Winboard_x engine-output window
1826 { "ShowGameListProc", ShowGameListProc },
1827 { "ShowMoveListProc", HistoryShowProc},
1828 { "EditTagsProc", EditCommentProc },
1829 { "EditCommentProc", EditCommentProc },
1830 { "IcsAlarmProc", IcsAlarmProc },
1831 { "IcsInputBoxProc", IcsInputBoxProc },
1832 { "PauseProc", PauseProc },
1833 { "AcceptProc", AcceptProc },
1834 { "DeclineProc", DeclineProc },
1835 { "RematchProc", RematchProc },
1836 { "CallFlagProc", CallFlagProc },
1837 { "DrawProc", DrawProc },
1838 { "AdjournProc", AdjournProc },
1839 { "AbortProc", AbortProc },
1840 { "ResignProc", ResignProc },
1841 { "AdjuWhiteProc", AdjuWhiteProc },
1842 { "AdjuBlackProc", AdjuBlackProc },
1843 { "AdjuDrawProc", AdjuDrawProc },
1844 { "EnterKeyProc", EnterKeyProc },
1845 { "StopObservingProc", StopObservingProc },
1846 { "StopExaminingProc", StopExaminingProc },
1847 { "BackwardProc", BackwardProc },
1848 { "ForwardProc", ForwardProc },
1849 { "ToStartProc", ToStartProc },
1850 { "ToEndProc", ToEndProc },
1851 { "RevertProc", RevertProc },
1852 { "TruncateGameProc", TruncateGameProc },
1853 { "MoveNowProc", MoveNowProc },
1854 { "RetractMoveProc", RetractMoveProc },
1855 { "AlwaysQueenProc", AlwaysQueenProc },
1856 { "AnimateDraggingProc", AnimateDraggingProc },
1857 { "AnimateMovingProc", AnimateMovingProc },
1858 { "AutoflagProc", AutoflagProc },
1859 { "AutoflipProc", AutoflipProc },
1860 { "AutobsProc", AutobsProc },
1861 { "AutoraiseProc", AutoraiseProc },
1862 { "AutosaveProc", AutosaveProc },
1863 { "BlindfoldProc", BlindfoldProc },
1864 { "FlashMovesProc", FlashMovesProc },
1865 { "FlipViewProc", FlipViewProc },
1866 { "GetMoveListProc", GetMoveListProc },
1868 { "HighlightDraggingProc", HighlightDraggingProc },
1870 { "HighlightLastMoveProc", HighlightLastMoveProc },
1871 { "IcsAlarmProc", IcsAlarmProc },
1872 { "MoveSoundProc", MoveSoundProc },
1873 { "OldSaveStyleProc", OldSaveStyleProc },
1874 { "PeriodicUpdatesProc", PeriodicUpdatesProc },
1875 { "PonderNextMoveProc", PonderNextMoveProc },
1876 { "PopupExitMessageProc", PopupExitMessageProc },
1877 { "PopupMoveErrorsProc", PopupMoveErrorsProc },
1878 { "PremoveProc", PremoveProc },
1879 { "QuietPlayProc", QuietPlayProc },
1880 { "ShowCoordsProc", ShowCoordsProc },
1881 { "ShowThinkingProc", ShowThinkingProc },
1882 { "HideThinkingProc", HideThinkingProc },
1883 { "TestLegalityProc", TestLegalityProc },
1884 { "InfoProc", InfoProc },
1885 { "ManProc", ManProc },
1886 { "HintProc", HintProc },
1887 { "BookProc", BookProc },
1888 { "AboutGameProc", AboutGameProc },
1889 { "AboutProc", AboutProc },
1890 { "DebugProc", DebugProc },
1891 { "NothingProc", NothingProc },
1892 { "CommentPopDown", (XtActionProc) CommentPopDown },
1893 { "EditCommentPopDown", (XtActionProc) EditCommentPopDown },
1894 { "TagsPopDown", (XtActionProc) TagsPopDown },
1895 { "ErrorPopDown", (XtActionProc) ErrorPopDown },
1896 { "ICSInputBoxPopDown", (XtActionProc) ICSInputBoxPopDown },
1897 { "AnalysisPopDown", (XtActionProc) AnalysisPopDown },
1898 { "FileNamePopDown", (XtActionProc) FileNamePopDown },
1899 { "AskQuestionPopDown", (XtActionProc) AskQuestionPopDown },
1900 { "GameListPopDown", (XtActionProc) GameListPopDown },
1901 { "PromotionPopDown", (XtActionProc) PromotionPopDown },
1902 { "HistoryPopDown", (XtActionProc) HistoryPopDown },
1903 { "EngineOutputPopDown", (XtActionProc) EngineOutputPopDown },
1904 { "ShufflePopDown", (XtActionProc) ShufflePopDown },
1905 { "EnginePopDown", (XtActionProc) EnginePopDown },
1906 { "UciPopDown", (XtActionProc) UciPopDown },
1907 { "TimeControlPopDown", (XtActionProc) TimeControlPopDown },
1908 { "NewVariantPopDown", (XtActionProc) NewVariantPopDown },
1909 { "SettingsPopDown", (XtActionProc) SettingsPopDown },
1912 char globalTranslations[] =
1913 ":<Key>R: ResignProc() \n \
1914 :<Key>r: ResetProc() \n \
1915 :<Key>g: LoadGameProc() \n \
1916 :<Key>N: LoadNextGameProc() \n \
1917 :<Key>P: LoadPrevGameProc() \n \
1918 :<Key>Q: QuitProc() \n \
1919 :<Key>F: ToEndProc() \n \
1920 :<Key>f: ForwardProc() \n \
1921 :<Key>B: ToStartProc() \n \
1922 :<Key>b: BackwardProc() \n \
1923 :<Key>p: PauseProc() \n \
1924 :<Key>d: DrawProc() \n \
1925 :<Key>t: CallFlagProc() \n \
1926 :<Key>i: Iconify() \n \
1927 :<Key>c: Iconify() \n \
1928 :<Key>v: FlipViewProc() \n \
1929 <KeyDown>Control_L: BackwardProc() \n \
1930 <KeyUp>Control_L: ForwardProc() \n \
1931 <KeyDown>Control_R: BackwardProc() \n \
1932 <KeyUp>Control_R: ForwardProc() \n \
1933 Shift<Key>1: AskQuestionProc(\"Direct command\",\
1934 \"Send to chess program:\",,1) \n \
1935 Shift<Key>2: AskQuestionProc(\"Direct command\",\
1936 \"Send to second chess program:\",,2) \n";
1938 char boardTranslations[] =
1939 "<Btn1Down>: HandleUserMove() \n \
1940 <Btn1Up>: HandleUserMove() \n \
1941 <Btn1Motion>: AnimateUserMove() \n \
1942 Shift<Btn2Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD)\
1943 PieceMenuPopup(menuB) \n \
1944 Any<Btn2Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD) \
1945 PieceMenuPopup(menuW) \n \
1946 Shift<Btn3Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD)\
1947 PieceMenuPopup(menuW) \n \
1948 Any<Btn3Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD) \
1949 PieceMenuPopup(menuB) \n";
1951 char whiteTranslations[] = "<BtnDown>: WhiteClock()\n";
1952 char blackTranslations[] = "<BtnDown>: BlackClock()\n";
1954 char ICSInputTranslations[] =
1955 "<Key>Return: EnterKeyProc() \n";
1957 String xboardResources[] = {
1958 "*fileName*value.translations: #override\\n <Key>Return: FileNameAction()",
1959 "*question*value.translations: #override\\n <Key>Return: AskQuestionReplyAction()",
1960 "*errorpopup*translations: #override\\n <Key>Return: ErrorPopDown()",
1965 /* Max possible square size */
1966 #define MAXSQSIZE 256
1968 static int xpm_avail[MAXSQSIZE];
1970 #ifdef HAVE_DIR_STRUCT
1972 /* Extract piece size from filename */
1974 xpm_getsize(name, len, ext)
1985 if ((p=strchr(name, '.')) == NULL ||
1986 StrCaseCmp(p+1, ext) != 0)
1992 while (*p && isdigit(*p))
1999 /* Setup xpm_avail */
2001 xpm_getavail(dirname, ext)
2009 for (i=0; i<MAXSQSIZE; ++i)
2012 if (appData.debugMode)
2013 fprintf(stderr, "XPM dir:%s:ext:%s:\n", dirname, ext);
2015 dir = opendir(dirname);
2018 fprintf(stderr, _("%s: Can't access XPM directory %s\n"),
2019 programName, dirname);
2023 while ((ent=readdir(dir)) != NULL) {
2024 i = xpm_getsize(ent->d_name, NAMLEN(ent), ext);
2025 if (i > 0 && i < MAXSQSIZE)
2035 xpm_print_avail(fp, ext)
2041 fprintf(fp, _("Available `%s' sizes:\n"), ext);
2042 for (i=1; i<MAXSQSIZE; ++i) {
2048 /* Return XPM piecesize closest to size */
2050 xpm_closest_to(dirname, size, ext)
2056 int sm_diff = MAXSQSIZE;
2060 xpm_getavail(dirname, ext);
2062 if (appData.debugMode)
2063 xpm_print_avail(stderr, ext);
2065 for (i=1; i<MAXSQSIZE; ++i) {
2068 diff = (diff<0) ? -diff : diff;
2069 if (diff < sm_diff) {
2077 fprintf(stderr, _("Error: No `%s' files!\n"), ext);
2083 #else /* !HAVE_DIR_STRUCT */
2084 /* If we are on a system without a DIR struct, we can't
2085 read the directory, so we can't collect a list of
2086 filenames, etc., so we can't do any size-fitting. */
2088 xpm_closest_to(dirname, size, ext)
2093 fprintf(stderr, _("\
2094 Warning: No DIR structure found on this system --\n\
2095 Unable to autosize for XPM/XIM pieces.\n\
2096 Please report this error to frankm@hiwaay.net.\n\
2097 Include system type & operating system in message.\n"));
2100 #endif /* HAVE_DIR_STRUCT */
2102 static char *cnames[9] = { "black", "red", "green", "yellow", "blue",
2103 "magenta", "cyan", "white" };
2107 TextColors textColors[(int)NColorClasses];
2109 /* String is: "fg, bg, attr". Which is 0, 1, 2 */
2111 parse_color(str, which)
2115 char *p, buf[100], *d;
2118 if (strlen(str) > 99) /* watch bounds on buf */
2123 for (i=0; i<which; ++i) {
2130 /* Could be looking at something like:
2132 .. in which case we want to stop on a comma also */
2133 while (*p && *p != ',' && !isalpha(*p) && !isdigit(*p))
2137 return -1; /* Use default for empty field */
2140 if (which == 2 || isdigit(*p))
2143 while (*p && isalpha(*p))
2148 for (i=0; i<8; ++i) {
2149 if (!StrCaseCmp(buf, cnames[i]))
2150 return which? (i+40) : (i+30);
2152 if (!StrCaseCmp(buf, "default")) return -1;
2154 fprintf(stderr, _("%s: unrecognized color %s\n"), programName, buf);
2159 parse_cpair(cc, str)
2163 if ((textColors[(int)cc].fg=parse_color(str, 0)) == -2) {
2164 fprintf(stderr, _("%s: can't parse foreground color in `%s'\n"),
2169 /* bg and attr are optional */
2170 textColors[(int)cc].bg = parse_color(str, 1);
2171 if ((textColors[(int)cc].attr = parse_color(str, 2)) < 0) {
2172 textColors[(int)cc].attr = 0;
2178 /* Arrange to catch delete-window events */
2179 Atom wm_delete_window;
2181 CatchDeleteWindow(Widget w, String procname)
2184 XSetWMProtocols(xDisplay, XtWindow(w), &wm_delete_window, 1);
2185 snprintf(buf, sizeof(buf), "<Message>WM_PROTOCOLS: %s() \n", procname);
2186 XtAugmentTranslations(w, XtParseTranslationTable(buf));
2193 XtSetArg(args[0], XtNiconic, False);
2194 XtSetValues(shellWidget, args, 1);
2196 XtPopup(shellWidget, XtGrabNone); /* Raise if lowered */
2200 // eventually, all layout determining code should go into a subroutine, but until then IDSIZE remains undefined
2202 #define BoardSize int
2203 void InitDrawingSizes(BoardSize boardSize, int flags)
2204 { // [HGM] resize is functional now, but for board format changes only (nr of ranks, files)
2205 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
2207 XtGeometryResult gres;
2210 if(!formWidget) return;
2213 * Enable shell resizing.
2215 shellArgs[0].value = (XtArgVal) &w;
2216 shellArgs[1].value = (XtArgVal) &h;
2217 XtGetValues(shellWidget, shellArgs, 2);
2219 shellArgs[4].value = 2*w; shellArgs[2].value = 10;
2220 shellArgs[5].value = 2*h; shellArgs[3].value = 10;
2221 XtSetValues(shellWidget, &shellArgs[2], 4);
2223 XtSetArg(args[0], XtNdefaultDistance, &sep);
2224 XtGetValues(formWidget, args, 1);
2226 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2227 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2230 XtSetArg(args[0], XtNwidth, boardWidth);
2231 XtSetArg(args[1], XtNheight, boardHeight);
2232 XtSetValues(boardWidget, args, 2);
2234 timerWidth = (boardWidth - sep) / 2;
2235 XtSetArg(args[0], XtNwidth, timerWidth);
2236 XtSetValues(whiteTimerWidget, args, 1);
2237 XtSetValues(blackTimerWidget, args, 1);
2239 XawFormDoLayout(formWidget, False);
2241 if (appData.titleInWindow) {
2243 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2244 XtSetArg(args[i], XtNheight, &h); i++;
2245 XtGetValues(titleWidget, args, i);
2247 w = boardWidth - 2*bor;
2249 XtSetArg(args[0], XtNwidth, &w);
2250 XtGetValues(menuBarWidget, args, 1);
2251 w = boardWidth - w - sep - 2*bor - 2; // WIDTH_FUDGE
2254 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
2255 if (gres != XtGeometryYes && appData.debugMode) {
2257 _("%s: titleWidget geometry error %d %d %d %d %d\n"),
2258 programName, gres, w, h, wr, hr);
2262 XawFormDoLayout(formWidget, True);
2265 * Inhibit shell resizing.
2267 shellArgs[0].value = w = (XtArgVal) boardWidth + marginW;
2268 shellArgs[1].value = h = (XtArgVal) boardHeight + marginH;
2269 shellArgs[4].value = shellArgs[2].value = w;
2270 shellArgs[5].value = shellArgs[3].value = h;
2271 XtSetValues(shellWidget, &shellArgs[0], 6);
2273 // [HGM] pieces: tailor piece bitmaps to needs of specific variant
2276 for(i=0; i<4; i++) {
2278 for(p=0; p<=(int)WhiteKing; p++)
2279 xpmPieceBitmap[i][p] = xpmPieceBitmap2[i][p]; // defaults
2280 if(gameInfo.variant == VariantShogi) {
2281 xpmPieceBitmap[i][(int)WhiteCannon] = xpmPieceBitmap2[i][(int)WhiteKing+1];
2282 xpmPieceBitmap[i][(int)WhiteNightrider] = xpmPieceBitmap2[i][(int)WhiteKing+2];
2283 xpmPieceBitmap[i][(int)WhiteSilver] = xpmPieceBitmap2[i][(int)WhiteKing+3];
2284 xpmPieceBitmap[i][(int)WhiteGrasshopper] = xpmPieceBitmap2[i][(int)WhiteKing+4];
2285 xpmPieceBitmap[i][(int)WhiteQueen] = xpmPieceBitmap2[i][(int)WhiteLance];
2288 if(gameInfo.variant == VariantGothic) {
2289 xpmPieceBitmap[i][(int)WhiteMarshall] = xpmPieceBitmap2[i][(int)WhiteSilver];
2293 // [HGM] why are thee ximMasks used at all? the ximPieceBitmaps seem to be never used!
2294 for(p=0; p<=(int)WhiteKing; p++)
2295 ximMaskPm[p] = ximMaskPm2[p]; // defaults
2296 if(gameInfo.variant == VariantShogi) {
2297 ximMaskPm[(int)WhiteCannon] = ximMaskPm2[(int)WhiteKing+1];
2298 ximMaskPm[(int)WhiteNightrider] = ximMaskPm2[(int)WhiteKing+2];
2299 ximMaskPm[(int)WhiteSilver] = ximMaskPm2[(int)WhiteKing+3];
2300 ximMaskPm[(int)WhiteGrasshopper] = ximMaskPm2[(int)WhiteKing+4];
2301 ximMaskPm[(int)WhiteQueen] = ximMaskPm2[(int)WhiteLance];
2304 if(gameInfo.variant == VariantGothic) {
2305 ximMaskPm[(int)WhiteMarshall] = ximMaskPm2[(int)WhiteSilver];
2311 for(i=0; i<2; i++) {
2313 for(p=0; p<=(int)WhiteKing; p++)
2314 pieceBitmap[i][p] = pieceBitmap2[i][p]; // defaults
2315 if(gameInfo.variant == VariantShogi) {
2316 pieceBitmap[i][(int)WhiteCannon] = pieceBitmap2[i][(int)WhiteKing+1];
2317 pieceBitmap[i][(int)WhiteNightrider] = pieceBitmap2[i][(int)WhiteKing+2];
2318 pieceBitmap[i][(int)WhiteSilver] = pieceBitmap2[i][(int)WhiteKing+3];
2319 pieceBitmap[i][(int)WhiteGrasshopper] = pieceBitmap2[i][(int)WhiteKing+4];
2320 pieceBitmap[i][(int)WhiteQueen] = pieceBitmap2[i][(int)WhiteLance];
2323 if(gameInfo.variant == VariantGothic) {
2324 pieceBitmap[i][(int)WhiteMarshall] = pieceBitmap2[i][(int)WhiteSilver];
2335 void EscapeExpand(char *p, char *q)
2336 { // [HGM] initstring: routine to shape up string arguments
2337 while(*p++ = *q++) if(p[-1] == '\\')
2339 case 'n': p[-1] = '\n'; break;
2340 case 'r': p[-1] = '\r'; break;
2341 case 't': p[-1] = '\t'; break;
2342 case '\\': p[-1] = '\\'; break;
2343 case 0: *p = 0; return;
2344 default: p[-1] = q[-1]; break;
2353 int i, j, clockFontPxlSize, coordFontPxlSize, fontPxlSize;
2354 XSetWindowAttributes window_attributes;
2356 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
2357 XrmValue vFrom, vTo;
2358 XtGeometryResult gres;
2361 int forceMono = False;
2364 // [HGM] before anything else, expand any indirection files amongst options
2365 char *argvCopy[1000]; // 1000 seems enough
2366 char newArgs[10000]; // holds actual characters
2369 srandom(time(0)); // [HGM] book: make random truly random
2372 for(i=0; i<argc; i++) {
2373 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2374 //fprintf(stderr, "arg %s\n", argv[i]);
2375 if(argv[i][0] != '@') argvCopy[j++] = argv[i]; else {
2377 FILE *f = fopen(argv[i]+1, "rb");
2378 if(f == NULL) { fprintf(stderr, _("ignore %s\n"), argv[i]); continue; } // do not expand non-existing
2379 argvCopy[j++] = newArgs + k; // get ready for first argument from file
2380 while((c = fgetc(f)) != EOF) { // each line of file inserts 1 argument in the list
2382 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2383 newArgs[k++] = 0; // terminate current arg
2384 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2385 argvCopy[j++] = newArgs + k; // get ready for next
2387 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2401 setbuf(stdout, NULL);
2402 setbuf(stderr, NULL);
2405 programName = strrchr(argv[0], '/');
2406 if (programName == NULL)
2407 programName = argv[0];
2412 XtSetLanguageProc(NULL, NULL, NULL);
2413 bindtextdomain(PACKAGE, LOCALEDIR);
2414 textdomain(PACKAGE);
2418 XtAppInitialize(&appContext, "XBoard", shellOptions,
2419 XtNumber(shellOptions),
2420 &argc, argv, xboardResources, NULL, 0);
2422 { /* left over command line arguments, print out help and exit.
2423 * Use two columns to print help
2425 fprintf(stderr, _("%s: unrecognized argument %s\n"),
2426 programName, argv[1]);
2428 fprintf(stderr, "Recognized options:\n");
2429 for(i = 0; i < XtNumber(shellOptions); i++)
2431 /* print first column */
2432 j = fprintf(stderr, " %s%s", shellOptions[i].option,
2433 (shellOptions[i].argKind == XrmoptionSepArg
2435 /* print second column and end line */
2436 if (++i < XtNumber(shellOptions))
2438 fprintf(stderr, "%*c%s%s\n", 40 - j, ' ',
2439 shellOptions[i].option,
2440 (shellOptions[i].argKind == XrmoptionSepArg
2445 fprintf(stderr, "\n");
2452 if (p == NULL) p = "/tmp";
2453 i = strlen(p) + strlen("/.xboardXXXXXx.pgn") + 1;
2454 gameCopyFilename = (char*) malloc(i);
2455 gamePasteFilename = (char*) malloc(i);
2456 snprintf(gameCopyFilename,i, "%s/.xboard%05uc.pgn", p, getpid());
2457 snprintf(gamePasteFilename,i, "%s/.xboard%05up.pgn", p, getpid());
2459 XtGetApplicationResources(shellWidget, (XtPointer) &appData,
2460 clientResources, XtNumber(clientResources),
2463 { // [HGM] initstring: kludge to fix bad bug. expand '\n' characters in init string and computer string.
2464 static char buf[MSG_SIZ];
2465 EscapeExpand(buf, appData.initString);
2466 appData.initString = strdup(buf);
2467 EscapeExpand(buf, appData.secondInitString);
2468 appData.secondInitString = strdup(buf);
2469 EscapeExpand(buf, appData.firstComputerString);
2470 appData.firstComputerString = strdup(buf);
2471 EscapeExpand(buf, appData.secondComputerString);
2472 appData.secondComputerString = strdup(buf);
2475 if ((chessDir = (char *) getenv("CHESSDIR")) == NULL) {
2478 if (chdir(chessDir) != 0) {
2479 fprintf(stderr, _("%s: can't cd to CHESSDIR: "), programName);
2485 if (appData.debugMode && appData.nameOfDebugFile && strcmp(appData.nameOfDebugFile, "stderr")) {
2486 /* [DM] debug info to file [HGM] make the filename a command-line option, and allow it to remain stderr */
2487 if ((debugFP = fopen(appData.nameOfDebugFile, "w")) == NULL) {
2488 printf(_("Failed to open file '%s'\n"), appData.nameOfDebugFile);
2491 setbuf(debugFP, NULL);
2494 /* [HGM,HR] make sure board size is acceptable */
2495 if(appData.NrFiles > BOARD_SIZE ||
2496 appData.NrRanks > BOARD_SIZE )
2497 DisplayFatalError(_("Recompile with BOARD_SIZE > 12, to support this size"), 0, 2);
2500 /* This feature does not work; animation needs a rewrite */
2501 appData.highlightDragging = FALSE;
2505 xDisplay = XtDisplay(shellWidget);
2506 xScreen = DefaultScreen(xDisplay);
2507 wm_delete_window = XInternAtom(xDisplay, "WM_DELETE_WINDOW", True);
2509 gameInfo.variant = StringToVariant(appData.variant);
2510 InitPosition(FALSE);
2513 InitDrawingSizes(-1, 0); // [HGM] initsize: make this into a subroutine
2515 if (isdigit(appData.boardSize[0])) {
2516 i = sscanf(appData.boardSize, "%d,%d,%d,%d,%d,%d,%d", &squareSize,
2517 &lineGap, &clockFontPxlSize, &coordFontPxlSize,
2518 &fontPxlSize, &smallLayout, &tinyLayout);
2520 fprintf(stderr, _("%s: bad boardSize syntax %s\n"),
2521 programName, appData.boardSize);
2525 /* Find some defaults; use the nearest known size */
2526 SizeDefaults *szd, *nearest;
2527 int distance = 99999;
2528 nearest = szd = sizeDefaults;
2529 while (szd->name != NULL) {
2530 if (abs(szd->squareSize - squareSize) < distance) {
2532 distance = abs(szd->squareSize - squareSize);
2533 if (distance == 0) break;
2537 if (i < 2) lineGap = nearest->lineGap;
2538 if (i < 3) clockFontPxlSize = nearest->clockFontPxlSize;
2539 if (i < 4) coordFontPxlSize = nearest->coordFontPxlSize;
2540 if (i < 5) fontPxlSize = nearest->fontPxlSize;
2541 if (i < 6) smallLayout = nearest->smallLayout;
2542 if (i < 7) tinyLayout = nearest->tinyLayout;
2545 SizeDefaults *szd = sizeDefaults;
2546 if (*appData.boardSize == NULLCHAR) {
2547 while (DisplayWidth(xDisplay, xScreen) < szd->minScreenSize ||
2548 DisplayHeight(xDisplay, xScreen) < szd->minScreenSize) {
2551 if (szd->name == NULL) szd--;
2553 while (szd->name != NULL &&
2554 StrCaseCmp(szd->name, appData.boardSize) != 0) szd++;
2555 if (szd->name == NULL) {
2556 fprintf(stderr, _("%s: unrecognized boardSize name %s\n"),
2557 programName, appData.boardSize);
2561 squareSize = szd->squareSize;
2562 lineGap = szd->lineGap;
2563 clockFontPxlSize = szd->clockFontPxlSize;
2564 coordFontPxlSize = szd->coordFontPxlSize;
2565 fontPxlSize = szd->fontPxlSize;
2566 smallLayout = szd->smallLayout;
2567 tinyLayout = szd->tinyLayout;
2570 /* Now, using squareSize as a hint, find a good XPM/XIM set size */
2571 if (strlen(appData.pixmapDirectory) > 0) {
2572 p = ExpandPathName(appData.pixmapDirectory);
2574 fprintf(stderr, _("Error expanding path name \"%s\"\n"),
2575 appData.pixmapDirectory);
2578 if (appData.debugMode) {
2579 fprintf(stderr, _("\
2580 XBoard square size (hint): %d\n\
2581 %s fulldir:%s:\n"), squareSize, IMAGE_EXT, p);
2583 squareSize = xpm_closest_to(p, squareSize, IMAGE_EXT);
2584 if (appData.debugMode) {
2585 fprintf(stderr, _("Closest %s size: %d\n"), IMAGE_EXT, squareSize);
2589 /* [HR] height treated separately (hacked) */
2590 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2591 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2592 if (appData.showJail == 1) {
2593 /* Jail on top and bottom */
2594 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2595 XtSetArg(boardArgs[2], XtNheight,
2596 boardHeight + 2*(lineGap + squareSize));
2597 } else if (appData.showJail == 2) {
2599 XtSetArg(boardArgs[1], XtNwidth,
2600 boardWidth + 2*(lineGap + squareSize));
2601 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2604 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2605 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2609 * Determine what fonts to use.
2611 appData.clockFont = FindFont(appData.clockFont, clockFontPxlSize);
2612 clockFontID = XLoadFont(xDisplay, appData.clockFont);
2613 clockFontStruct = XQueryFont(xDisplay, clockFontID);
2614 appData.coordFont = FindFont(appData.coordFont, coordFontPxlSize);
2615 coordFontID = XLoadFont(xDisplay, appData.coordFont);
2616 coordFontStruct = XQueryFont(xDisplay, coordFontID);
2617 appData.font = FindFont(appData.font, fontPxlSize);
2618 countFontID = XLoadFont(xDisplay, appData.coordFont); // [HGM] holdings
2619 countFontStruct = XQueryFont(xDisplay, countFontID);
2620 // appData.font = FindFont(appData.font, fontPxlSize);
2622 xdb = XtDatabase(xDisplay);
2623 XrmPutStringResource(&xdb, "*font", appData.font);
2626 * Detect if there are not enough colors available and adapt.
2628 if (DefaultDepth(xDisplay, xScreen) <= 2) {
2629 appData.monoMode = True;
2632 if (!appData.monoMode) {
2633 vFrom.addr = (caddr_t) appData.lightSquareColor;
2634 vFrom.size = strlen(appData.lightSquareColor);
2635 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2636 if (vTo.addr == NULL) {
2637 appData.monoMode = True;
2640 lightSquareColor = *(Pixel *) vTo.addr;
2643 if (!appData.monoMode) {
2644 vFrom.addr = (caddr_t) appData.darkSquareColor;
2645 vFrom.size = strlen(appData.darkSquareColor);
2646 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2647 if (vTo.addr == NULL) {
2648 appData.monoMode = True;
2651 darkSquareColor = *(Pixel *) vTo.addr;
2654 if (!appData.monoMode) {
2655 vFrom.addr = (caddr_t) appData.whitePieceColor;
2656 vFrom.size = strlen(appData.whitePieceColor);
2657 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2658 if (vTo.addr == NULL) {
2659 appData.monoMode = True;
2662 whitePieceColor = *(Pixel *) vTo.addr;
2665 if (!appData.monoMode) {
2666 vFrom.addr = (caddr_t) appData.blackPieceColor;
2667 vFrom.size = strlen(appData.blackPieceColor);
2668 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2669 if (vTo.addr == NULL) {
2670 appData.monoMode = True;
2673 blackPieceColor = *(Pixel *) vTo.addr;
2677 if (!appData.monoMode) {
2678 vFrom.addr = (caddr_t) appData.highlightSquareColor;
2679 vFrom.size = strlen(appData.highlightSquareColor);
2680 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2681 if (vTo.addr == NULL) {
2682 appData.monoMode = True;
2685 highlightSquareColor = *(Pixel *) vTo.addr;
2689 if (!appData.monoMode) {
2690 vFrom.addr = (caddr_t) appData.premoveHighlightColor;
2691 vFrom.size = strlen(appData.premoveHighlightColor);
2692 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2693 if (vTo.addr == NULL) {
2694 appData.monoMode = True;
2697 premoveHighlightColor = *(Pixel *) vTo.addr;
2702 fprintf(stderr, _("%s: too few colors available; trying monochrome mode\n"),
2705 if (appData.bitmapDirectory == NULL ||
2706 appData.bitmapDirectory[0] == NULLCHAR)
2707 appData.bitmapDirectory = DEF_BITMAP_DIR;
2710 if (appData.lowTimeWarning && !appData.monoMode) {
2711 vFrom.addr = (caddr_t) appData.lowTimeWarningColor;
2712 vFrom.size = strlen(appData.lowTimeWarningColor);
2713 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2714 if (vTo.addr == NULL)
2715 appData.monoMode = True;
2717 lowTimeWarningColor = *(Pixel *) vTo.addr;
2720 if (appData.monoMode && appData.debugMode) {
2721 fprintf(stderr, _("white pixel = 0x%lx, black pixel = 0x%lx\n"),
2722 (unsigned long) XWhitePixel(xDisplay, xScreen),
2723 (unsigned long) XBlackPixel(xDisplay, xScreen));
2726 if (parse_cpair(ColorShout, appData.colorShout) < 0 ||
2727 parse_cpair(ColorSShout, appData.colorSShout) < 0 ||
2728 parse_cpair(ColorChannel1, appData.colorChannel1) < 0 ||
2729 parse_cpair(ColorChannel, appData.colorChannel) < 0 ||
2730 parse_cpair(ColorKibitz, appData.colorKibitz) < 0 ||
2731 parse_cpair(ColorTell, appData.colorTell) < 0 ||
2732 parse_cpair(ColorChallenge, appData.colorChallenge) < 0 ||
2733 parse_cpair(ColorRequest, appData.colorRequest) < 0 ||
2734 parse_cpair(ColorSeek, appData.colorSeek) < 0 ||
2735 parse_cpair(ColorNormal, appData.colorNormal) < 0)
2737 if (appData.colorize) {
2739 _("%s: can't parse color names; disabling colorization\n"),
2742 appData.colorize = FALSE;
2744 textColors[ColorNone].fg = textColors[ColorNone].bg = -1;
2745 textColors[ColorNone].attr = 0;
2747 XtAppAddActions(appContext, boardActions, XtNumber(boardActions));
2753 layoutName = "tinyLayout";
2754 } else if (smallLayout) {
2755 layoutName = "smallLayout";
2757 layoutName = "normalLayout";
2759 /* Outer layoutWidget is there only to provide a name for use in
2760 resources that depend on the layout style */
2762 XtCreateManagedWidget(layoutName, formWidgetClass, shellWidget,
2763 layoutArgs, XtNumber(layoutArgs));
2765 XtCreateManagedWidget("form", formWidgetClass, layoutWidget,
2766 formArgs, XtNumber(formArgs));
2767 XtSetArg(args[0], XtNdefaultDistance, &sep);
2768 XtGetValues(formWidget, args, 1);
2771 widgetList[j++] = menuBarWidget = CreateMenuBar(menuBar);
2772 XtSetArg(args[0], XtNtop, XtChainTop);
2773 XtSetArg(args[1], XtNbottom, XtChainTop);
2774 XtSetValues(menuBarWidget, args, 2);
2776 widgetList[j++] = whiteTimerWidget =
2777 XtCreateWidget("whiteTime", labelWidgetClass,
2778 formWidget, timerArgs, XtNumber(timerArgs));
2779 XtSetArg(args[0], XtNfont, clockFontStruct);
2780 XtSetArg(args[1], XtNtop, XtChainTop);
2781 XtSetArg(args[2], XtNbottom, XtChainTop);
2782 XtSetValues(whiteTimerWidget, args, 3);
2784 widgetList[j++] = blackTimerWidget =
2785 XtCreateWidget("blackTime", labelWidgetClass,
2786 formWidget, timerArgs, XtNumber(timerArgs));
2787 XtSetArg(args[0], XtNfont, clockFontStruct);
2788 XtSetArg(args[1], XtNtop, XtChainTop);
2789 XtSetArg(args[2], XtNbottom, XtChainTop);
2790 XtSetValues(blackTimerWidget, args, 3);
2792 if (appData.titleInWindow) {
2793 widgetList[j++] = titleWidget =
2794 XtCreateWidget("title", labelWidgetClass, formWidget,
2795 titleArgs, XtNumber(titleArgs));
2796 XtSetArg(args[0], XtNtop, XtChainTop);
2797 XtSetArg(args[1], XtNbottom, XtChainTop);
2798 XtSetValues(titleWidget, args, 2);
2801 if (appData.showButtonBar) {
2802 widgetList[j++] = buttonBarWidget = CreateButtonBar(buttonBar);
2803 XtSetArg(args[0], XtNleft, XtChainRight); // [HGM] glue to right window edge
2804 XtSetArg(args[1], XtNright, XtChainRight); // for good run-time sizing
2805 XtSetArg(args[2], XtNtop, XtChainTop);
2806 XtSetArg(args[3], XtNbottom, XtChainTop);
2807 XtSetValues(buttonBarWidget, args, 4);
2810 widgetList[j++] = messageWidget =
2811 XtCreateWidget("message", labelWidgetClass, formWidget,
2812 messageArgs, XtNumber(messageArgs));
2813 XtSetArg(args[0], XtNtop, XtChainTop);
2814 XtSetArg(args[1], XtNbottom, XtChainTop);
2815 XtSetValues(messageWidget, args, 2);
2817 widgetList[j++] = boardWidget =
2818 XtCreateWidget("board", widgetClass, formWidget, boardArgs,
2819 XtNumber(boardArgs));
2821 XtManageChildren(widgetList, j);
2823 timerWidth = (boardWidth - sep) / 2;
2824 XtSetArg(args[0], XtNwidth, timerWidth);
2825 XtSetValues(whiteTimerWidget, args, 1);
2826 XtSetValues(blackTimerWidget, args, 1);
2828 XtSetArg(args[0], XtNbackground, &timerBackgroundPixel);
2829 XtSetArg(args[1], XtNforeground, &timerForegroundPixel);
2830 XtGetValues(whiteTimerWidget, args, 2);
2832 if (appData.showButtonBar) {
2833 XtSetArg(args[0], XtNbackground, &buttonBackgroundPixel);
2834 XtSetArg(args[1], XtNforeground, &buttonForegroundPixel);
2835 XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
2839 * formWidget uses these constraints but they are stored
2843 XtSetArg(args[i], XtNfromHoriz, 0); i++;
2844 XtSetValues(menuBarWidget, args, i);
2845 if (appData.titleInWindow) {
2848 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2849 XtSetValues(whiteTimerWidget, args, i);
2851 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2852 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2853 XtSetValues(blackTimerWidget, args, i);
2855 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2856 XtSetArg(args[i], XtNjustify, XtJustifyLeft); i++;
2857 XtSetValues(titleWidget, args, i);
2859 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2860 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2861 XtSetValues(messageWidget, args, i);
2862 if (appData.showButtonBar) {
2864 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2865 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2866 XtSetValues(buttonBarWidget, args, i);
2870 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2871 XtSetValues(whiteTimerWidget, args, i);
2873 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2874 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2875 XtSetValues(blackTimerWidget, args, i);
2877 XtSetArg(args[i], XtNfromHoriz, menuBarWidget); i++;
2878 XtSetValues(titleWidget, args, i);
2880 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2881 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2882 XtSetValues(messageWidget, args, i);
2883 if (appData.showButtonBar) {
2885 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2886 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2887 XtSetValues(buttonBarWidget, args, i);
2892 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2893 XtSetValues(whiteTimerWidget, args, i);
2895 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2896 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2897 XtSetValues(blackTimerWidget, args, i);
2899 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2900 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2901 XtSetValues(messageWidget, args, i);
2902 if (appData.showButtonBar) {
2904 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2905 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2906 XtSetValues(buttonBarWidget, args, i);
2910 XtSetArg(args[0], XtNfromVert, messageWidget);
2911 XtSetArg(args[1], XtNtop, XtChainTop);
2912 XtSetArg(args[2], XtNbottom, XtChainBottom);
2913 XtSetArg(args[3], XtNleft, XtChainLeft);
2914 XtSetArg(args[4], XtNright, XtChainRight);
2915 XtSetValues(boardWidget, args, 5);
2917 XtRealizeWidget(shellWidget);
2920 * Correct the width of the message and title widgets.
2921 * It is not known why some systems need the extra fudge term.
2922 * The value "2" is probably larger than needed.
2924 XawFormDoLayout(formWidget, False);
2926 #define WIDTH_FUDGE 2
2928 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2929 XtSetArg(args[i], XtNheight, &h); i++;
2930 XtGetValues(messageWidget, args, i);
2931 if (appData.showButtonBar) {
2933 XtSetArg(args[i], XtNwidth, &w); i++;
2934 XtGetValues(buttonBarWidget, args, i);
2935 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2937 w = boardWidth - 2*bor + 1; /*!! +1 compensates for kludge below */
2940 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2941 if (gres != XtGeometryYes && appData.debugMode) {
2942 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2943 programName, gres, w, h, wr, hr);
2946 /* !! Horrible hack to work around bug in XFree86 4.0.1 (X11R6.4.3) */
2947 /* The size used for the child widget in layout lags one resize behind
2948 its true size, so we resize a second time, 1 pixel smaller. Yeech! */
2950 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2951 if (gres != XtGeometryYes && appData.debugMode) {
2952 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2953 programName, gres, w, h, wr, hr);
2956 XtSetArg(args[0], XtNleft, XtChainLeft); // [HGM] glue ends for good run-time sizing
2957 XtSetArg(args[1], XtNright, XtChainRight);
2958 XtSetValues(messageWidget, args, 2);
2960 if (appData.titleInWindow) {
2962 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2963 XtSetArg(args[i], XtNheight, &h); i++;
2964 XtGetValues(titleWidget, args, i);
2966 w = boardWidth - 2*bor;
2968 XtSetArg(args[0], XtNwidth, &w);
2969 XtGetValues(menuBarWidget, args, 1);
2970 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2973 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
2974 if (gres != XtGeometryYes && appData.debugMode) {
2976 _("%s: titleWidget geometry error %d %d %d %d %d\n"),
2977 programName, gres, w, h, wr, hr);
2980 XawFormDoLayout(formWidget, True);
2982 xBoardWindow = XtWindow(boardWidget);
2984 // [HGM] it seems the layout code ends here, but perhaps the color stuff is size independent and would
2985 // not need to go into InitDrawingSizes().
2989 * Create X checkmark bitmap and initialize option menu checks.
2991 ReadBitmap(&xMarkPixmap, "checkmark.bm",
2992 checkmark_bits, checkmark_width, checkmark_height);
2993 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
2994 if (appData.alwaysPromoteToQueen) {
2995 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
2998 if (appData.animateDragging) {
2999 XtSetValues(XtNameToWidget(menuBarWidget,
3000 "menuOptions.Animate Dragging"),
3003 if (appData.animate) {
3004 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
3007 if (appData.autoComment) {
3008 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
3011 if (appData.autoCallFlag) {
3012 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
3015 if (appData.autoFlipView) {
3016 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Auto Flip View"),
3019 if (appData.autoObserve) {
3020 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
3023 if (appData.autoRaiseBoard) {
3024 XtSetValues(XtNameToWidget(menuBarWidget,
3025 "menuOptions.Auto Raise Board"), args, 1);
3027 if (appData.autoSaveGames) {
3028 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
3031 if (appData.saveGameFile[0] != NULLCHAR) {
3032 /* Can't turn this off from menu */
3033 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
3035 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
3039 if (appData.blindfold) {
3040 XtSetValues(XtNameToWidget(menuBarWidget,
3041 "menuOptions.Blindfold"), args, 1);
3043 if (appData.flashCount > 0) {
3044 XtSetValues(XtNameToWidget(menuBarWidget,
3045 "menuOptions.Flash Moves"),
3048 if (appData.getMoveList) {
3049 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
3053 if (appData.highlightDragging) {
3054 XtSetValues(XtNameToWidget(menuBarWidget,
3055 "menuOptions.Highlight Dragging"),
3059 if (appData.highlightLastMove) {
3060 XtSetValues(XtNameToWidget(menuBarWidget,
3061 "menuOptions.Highlight Last Move"),
3064 if (appData.icsAlarm) {
3065 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.ICS Alarm"),
3068 if (appData.ringBellAfterMoves) {
3069 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
3072 if (appData.oldSaveStyle) {
3073 XtSetValues(XtNameToWidget(menuBarWidget,
3074 "menuOptions.Old Save Style"), args, 1);
3076 if (appData.periodicUpdates) {
3077 XtSetValues(XtNameToWidget(menuBarWidget,
3078 "menuOptions.Periodic Updates"), args, 1);
3080 if (appData.ponderNextMove) {
3081 XtSetValues(XtNameToWidget(menuBarWidget,
3082 "menuOptions.Ponder Next Move"), args, 1);
3084 if (appData.popupExitMessage) {
3085 XtSetValues(XtNameToWidget(menuBarWidget,
3086 "menuOptions.Popup Exit Message"), args, 1);
3088 if (appData.popupMoveErrors) {
3089 XtSetValues(XtNameToWidget(menuBarWidget,
3090 "menuOptions.Popup Move Errors"), args, 1);
3092 if (appData.premove) {
3093 XtSetValues(XtNameToWidget(menuBarWidget,
3094 "menuOptions.Premove"), args, 1);
3096 if (appData.quietPlay) {
3097 XtSetValues(XtNameToWidget(menuBarWidget,
3098 "menuOptions.Quiet Play"), args, 1);
3100 if (appData.showCoords) {
3101 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
3104 if (appData.hideThinkingFromHuman) {
3105 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
3108 if (appData.testLegality) {
3109 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Test Legality"),
3116 ReadBitmap(&wIconPixmap, "icon_white.bm",
3117 icon_white_bits, icon_white_width, icon_white_height);
3118 ReadBitmap(&bIconPixmap, "icon_black.bm",
3119 icon_black_bits, icon_black_width, icon_black_height);
3120 iconPixmap = wIconPixmap;
3122 XtSetArg(args[i], XtNiconPixmap, iconPixmap); i++;
3123 XtSetValues(shellWidget, args, i);
3126 * Create a cursor for the board widget.
3128 window_attributes.cursor = XCreateFontCursor(xDisplay, XC_hand2);
3129 XChangeWindowAttributes(xDisplay, xBoardWindow,
3130 CWCursor, &window_attributes);
3133 * Inhibit shell resizing.
3135 shellArgs[0].value = (XtArgVal) &w;
3136 shellArgs[1].value = (XtArgVal) &h;
3137 XtGetValues(shellWidget, shellArgs, 2);
3138 shellArgs[4].value = shellArgs[2].value = w;
3139 shellArgs[5].value = shellArgs[3].value = h;
3140 XtSetValues(shellWidget, &shellArgs[2], 4);
3141 marginW = w - boardWidth; // [HGM] needed to set new shellWidget size when we resize board
3142 marginH = h - boardHeight;
3144 CatchDeleteWindow(shellWidget, "QuitProc");
3149 if (appData.bitmapDirectory[0] != NULLCHAR) {
3156 /* Create regular pieces */
3157 if (!useImages) CreatePieces();
3162 if (appData.animate || appData.animateDragging)
3165 XtAugmentTranslations(formWidget,
3166 XtParseTranslationTable(globalTranslations));
3167 XtAugmentTranslations(boardWidget,
3168 XtParseTranslationTable(boardTranslations));
3169 XtAugmentTranslations(whiteTimerWidget,
3170 XtParseTranslationTable(whiteTranslations));
3171 XtAugmentTranslations(blackTimerWidget,
3172 XtParseTranslationTable(blackTranslations));
3174 /* Why is the following needed on some versions of X instead
3175 * of a translation? */
3176 XtAddEventHandler(boardWidget, ExposureMask, False,
3177 (XtEventHandler) EventProc, NULL);
3182 if (errorExitStatus == -1) {
3183 if (appData.icsActive) {
3184 /* We now wait until we see "login:" from the ICS before
3185 sending the logon script (problems with timestamp otherwise) */
3186 /*ICSInitScript();*/
3187 if (appData.icsInputBox) ICSInputBoxPopUp();
3190 signal(SIGINT, IntSigHandler);
3191 signal(SIGTERM, IntSigHandler);
3192 if (*appData.cmailGameName != NULLCHAR) {
3193 signal(SIGUSR1, CmailSigHandler);
3196 gameInfo.boardWidth = 0; // [HGM] pieces: kludge to ensure InitPosition() calls InitDrawingSizes()
3199 XtAppMainLoop(appContext);
3200 if (appData.debugMode) fclose(debugFP); // [DM] debug
3207 if (appData.icsActive && oldICSInteractionTitle != NULL) {
3208 DisplayIcsInteractionTitle(oldICSInteractionTitle);
3210 unlink(gameCopyFilename);
3211 unlink(gamePasteFilename);
3222 CmailSigHandler(sig)
3228 signal(SIGUSR1, SIG_IGN); /* suspend handler */
3230 /* Activate call-back function CmailSigHandlerCallBack() */
3231 OutputToProcess(cmailPR, (char *)(&dummy), sizeof(int), &error);
3233 signal(SIGUSR1, CmailSigHandler); /* re-activate handler */
3237 CmailSigHandlerCallBack(isr, closure, message, count, error)
3245 ReloadCmailMsgEvent(TRUE); /* Reload cmail msg */
3247 /**** end signal code ****/
3257 f = fopen(appData.icsLogon, "r");
3263 strcat(buf, appData.icsLogon);
3264 f = fopen(buf, "r");
3268 ProcessICSInitScript(f);
3275 EditCommentPopDown();
3280 void NotifyFrontendLogin()
3291 SetMenuEnables(enab)
3295 if (!menuBarWidget) return;
3296 while (enab->name != NULL) {
3297 w = XtNameToWidget(menuBarWidget, enab->name);
3299 DisplayError(enab->name, 0);
3301 XtSetSensitive(w, enab->value);
3307 Enables icsEnables[] = {
3308 { "menuFile.Mail Move", False },
3309 { "menuFile.Reload CMail Message", False },
3310 { "menuMode.Machine Black", False },
3311 { "menuMode.Machine White", False },
3312 { "menuMode.Analysis Mode", False },
3313 { "menuMode.Analyze File", False },
3314 { "menuMode.Two Machines", False },
3316 { "menuHelp.Hint", False },
3317 { "menuHelp.Book", False },
3318 { "menuStep.Move Now", False },
3319 { "menuOptions.Periodic Updates", False },
3320 { "menuOptions.Hide Thinking", False },
3321 { "menuOptions.Ponder Next Move", False },
3326 Enables ncpEnables[] = {
3327 { "menuFile.Mail Move", False },
3328 { "menuFile.Reload CMail Message", False },
3329 { "menuMode.Machine White", False },
3330 { "menuMode.Machine Black", False },
3331 { "menuMode.Analysis Mode", False },
3332 { "menuMode.Analyze File", False },
3333 { "menuMode.Two Machines", False },
3334 { "menuMode.ICS Client", False },
3335 { "menuMode.ICS Input Box", False },
3336 { "Action", False },
3337 { "menuStep.Revert", False },
3338 { "menuStep.Move Now", False },
3339 { "menuStep.Retract Move", False },
3340 { "menuOptions.Auto Comment", False },
3341 { "menuOptions.Auto Flag", False },
3342 { "menuOptions.Auto Flip View", False },
3343 { "menuOptions.Auto Observe", False },
3344 { "menuOptions.Auto Raise Board", False },
3345 { "menuOptions.Get Move List", False },
3346 { "menuOptions.ICS Alarm", False },
3347 { "menuOptions.Move Sound", False },
3348 { "menuOptions.Quiet Play", False },
3349 { "menuOptions.Hide Thinking", False },
3350 { "menuOptions.Periodic Updates", False },
3351 { "menuOptions.Ponder Next Move", False },
3352 { "menuHelp.Hint", False },
3353 { "menuHelp.Book", False },
3357 Enables gnuEnables[] = {
3358 { "menuMode.ICS Client", False },
3359 { "menuMode.ICS Input Box", False },
3360 { "menuAction.Accept", False },
3361 { "menuAction.Decline", False },
3362 { "menuAction.Rematch", False },
3363 { "menuAction.Adjourn", False },
3364 { "menuAction.Stop Examining", False },
3365 { "menuAction.Stop Observing", False },
3366 { "menuStep.Revert", False },
3367 { "menuOptions.Auto Comment", False },
3368 { "menuOptions.Auto Observe", False },
3369 { "menuOptions.Auto Raise Board", False },
3370 { "menuOptions.Get Move List", False },
3371 { "menuOptions.Premove", False },
3372 { "menuOptions.Quiet Play", False },
3374 /* The next two options rely on SetCmailMode being called *after* */
3375 /* SetGNUMode so that when GNU is being used to give hints these */
3376 /* menu options are still available */
3378 { "menuFile.Mail Move", False },
3379 { "menuFile.Reload CMail Message", False },
3383 Enables cmailEnables[] = {
3385 { "menuAction.Call Flag", False },
3386 { "menuAction.Draw", True },
3387 { "menuAction.Adjourn", False },
3388 { "menuAction.Abort", False },
3389 { "menuAction.Stop Observing", False },
3390 { "menuAction.Stop Examining", False },
3391 { "menuFile.Mail Move", True },
3392 { "menuFile.Reload CMail Message", True },
3396 Enables trainingOnEnables[] = {
3397 { "menuMode.Edit Comment", False },
3398 { "menuMode.Pause", False },
3399 { "menuStep.Forward", False },
3400 { "menuStep.Backward", False },
3401 { "menuStep.Forward to End", False },
3402 { "menuStep.Back to Start", False },
3403 { "menuStep.Move Now", False },
3404 { "menuStep.Truncate Game", False },
3408 Enables trainingOffEnables[] = {
3409 { "menuMode.Edit Comment", True },
3410 { "menuMode.Pause", True },
3411 { "menuStep.Forward", True },
3412 { "menuStep.Backward", True },
3413 { "menuStep.Forward to End", True },
3414 { "menuStep.Back to Start", True },
3415 { "menuStep.Move Now", True },
3416 { "menuStep.Truncate Game", True },
3420 Enables machineThinkingEnables[] = {
3421 { "menuFile.Load Game", False },
3422 { "menuFile.Load Next Game", False },
3423 { "menuFile.Load Previous Game", False },
3424 { "menuFile.Reload Same Game", False },
3425 { "menuFile.Paste Game", False },
3426 { "menuFile.Load Position", False },
3427 { "menuFile.Load Next Position", False },
3428 { "menuFile.Load Previous Position", False },
3429 { "menuFile.Reload Same Position", False },
3430 { "menuFile.Paste Position", False },
3431 { "menuMode.Machine White", False },
3432 { "menuMode.Machine Black", False },
3433 { "menuMode.Two Machines", False },
3434 { "menuStep.Retract Move", False },
3438 Enables userThinkingEnables[] = {
3439 { "menuFile.Load Game", True },
3440 { "menuFile.Load Next Game", True },
3441 { "menuFile.Load Previous Game", True },
3442 { "menuFile.Reload Same Game", True },
3443 { "menuFile.Paste Game", True },
3444 { "menuFile.Load Position", True },
3445 { "menuFile.Load Next Position", True },
3446 { "menuFile.Load Previous Position", True },
3447 { "menuFile.Reload Same Position", True },
3448 { "menuFile.Paste Position", True },
3449 { "menuMode.Machine White", True },
3450 { "menuMode.Machine Black", True },
3451 { "menuMode.Two Machines", True },
3452 { "menuStep.Retract Move", True },
3458 SetMenuEnables(icsEnables);
3461 if (appData.zippyPlay && !appData.noChessProgram) /* [DM] icsEngineAnalyze */
3462 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Analysis Mode"), True);
3469 SetMenuEnables(ncpEnables);
3475 SetMenuEnables(gnuEnables);
3481 SetMenuEnables(cmailEnables);
3487 SetMenuEnables(trainingOnEnables);
3488 if (appData.showButtonBar) {
3489 XtSetSensitive(buttonBarWidget, False);
3495 SetTrainingModeOff()
3497 SetMenuEnables(trainingOffEnables);
3498 if (appData.showButtonBar) {
3499 XtSetSensitive(buttonBarWidget, True);
3504 SetUserThinkingEnables()
3506 if (appData.noChessProgram) return;
3507 SetMenuEnables(userThinkingEnables);
3511 SetMachineThinkingEnables()
3513 if (appData.noChessProgram) return;
3514 SetMenuEnables(machineThinkingEnables);
3516 case MachinePlaysBlack:
3517 case MachinePlaysWhite:
3518 case TwoMachinesPlay:
3519 XtSetSensitive(XtNameToWidget(menuBarWidget,
3520 ModeToWidgetName(gameMode)), True);
3527 #define Abs(n) ((n)<0 ? -(n) : (n))
3530 * Find a font that matches "pattern" that is as close as
3531 * possible to the targetPxlSize. Prefer fonts that are k
3532 * pixels smaller to fonts that are k pixels larger. The
3533 * pattern must be in the X Consortium standard format,
3534 * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".
3535 * The return value should be freed with XtFree when no
3538 char *FindFont(pattern, targetPxlSize)
3542 char **fonts, *p, *best, *scalable, *scalableTail;
3543 int i, j, nfonts, minerr, err, pxlSize;
3546 char **missing_list;
3548 char *def_string, *base_fnt_lst, strInt[3];
3550 XFontStruct **fnt_list;
3552 base_fnt_lst = calloc(1, strlen(pattern) + 3);
3553 sprintf(strInt, "%d", targetPxlSize);
3554 p = strstr(pattern, "--");
3555 strncpy(base_fnt_lst, pattern, p - pattern + 2);
3556 strcat(base_fnt_lst, strInt);
3557 strcat(base_fnt_lst, strchr(p + 2, '-'));
3559 if ((fntSet = XCreateFontSet(xDisplay,
3563 &def_string)) == NULL) {
3565 fprintf(stderr, _("Unable to create font set.\n"));
3569 nfonts = XFontsOfFontSet(fntSet, &fnt_list, &fonts);
3571 fonts = XListFonts(xDisplay, pattern, 999999, &nfonts);
3573 fprintf(stderr, _("%s: no fonts match pattern %s\n"),
3574 programName, pattern);
3582 for (i=0; i<nfonts; i++) {
3585 if (*p != '-') continue;
3587 if (*p == NULLCHAR) break;
3588 if (*p++ == '-') j++;
3590 if (j < 7) continue;
3593 scalable = fonts[i];
3596 err = pxlSize - targetPxlSize;
3597 if (Abs(err) < Abs(minerr) ||
3598 (minerr > 0 && err < 0 && -err == minerr)) {
3604 if (scalable && Abs(minerr) > appData.fontSizeTolerance) {
3605 /* If the error is too big and there is a scalable font,
3606 use the scalable font. */
3607 int headlen = scalableTail - scalable;
3608 p = (char *) XtMalloc(strlen(scalable) + 10);
3609 while (isdigit(*scalableTail)) scalableTail++;
3610 sprintf(p, "%.*s%d%s", headlen, scalable, targetPxlSize, scalableTail);
3612 p = (char *) XtMalloc(strlen(best) + 1);
3615 if (appData.debugMode) {
3616 fprintf(debugFP, _("resolved %s at pixel size %d\n to %s\n"),
3617 pattern, targetPxlSize, p);
3620 if (missing_count > 0)
3621 XFreeStringList(missing_list);
3622 XFreeFontSet(xDisplay, fntSet);
3624 XFreeFontNames(fonts);
3631 XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
3632 | GCBackground | GCFunction | GCPlaneMask;
3633 XGCValues gc_values;
3636 gc_values.plane_mask = AllPlanes;
3637 gc_values.line_width = lineGap;
3638 gc_values.line_style = LineSolid;
3639 gc_values.function = GXcopy;
3641 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3642 gc_values.background = XBlackPixel(xDisplay, xScreen);
3643 lineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3645 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3646 gc_values.background = XWhitePixel(xDisplay, xScreen);
3647 coordGC = XtGetGC(shellWidget, value_mask, &gc_values);
3648 XSetFont(xDisplay, coordGC, coordFontID);
3650 // [HGM] make font for holdings counts (white on black0
3651 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3652 gc_values.background = XBlackPixel(xDisplay, xScreen);
3653 countGC = XtGetGC(shellWidget, value_mask, &gc_values);
3654 XSetFont(xDisplay, countGC, countFontID);
3656 if (appData.monoMode) {
3657 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3658 gc_values.background = XWhitePixel(xDisplay, xScreen);
3659 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3661 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3662 gc_values.background = XBlackPixel(xDisplay, xScreen);
3663 lightSquareGC = wbPieceGC
3664 = XtGetGC(shellWidget, value_mask, &gc_values);
3666 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3667 gc_values.background = XWhitePixel(xDisplay, xScreen);
3668 darkSquareGC = bwPieceGC
3669 = XtGetGC(shellWidget, value_mask, &gc_values);
3671 if (DefaultDepth(xDisplay, xScreen) == 1) {
3672 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
3673 gc_values.function = GXcopyInverted;
3674 copyInvertedGC = XtGetGC(shellWidget, value_mask, &gc_values);
3675 gc_values.function = GXcopy;
3676 if (XBlackPixel(xDisplay, xScreen) == 1) {
3677 bwPieceGC = darkSquareGC;
3678 wbPieceGC = copyInvertedGC;
3680 bwPieceGC = copyInvertedGC;
3681 wbPieceGC = lightSquareGC;
3685 gc_values.foreground = highlightSquareColor;
3686 gc_values.background = highlightSquareColor;
3687 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3689 gc_values.foreground = premoveHighlightColor;
3690 gc_values.background = premoveHighlightColor;
3691 prelineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3693 gc_values.foreground = lightSquareColor;
3694 gc_values.background = darkSquareColor;
3695 lightSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3697 gc_values.foreground = darkSquareColor;
3698 gc_values.background = lightSquareColor;
3699 darkSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3701 gc_values.foreground = jailSquareColor;
3702 gc_values.background = jailSquareColor;
3703 jailSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3705 gc_values.foreground = whitePieceColor;
3706 gc_values.background = darkSquareColor;
3707 wdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3709 gc_values.foreground = whitePieceColor;
3710 gc_values.background = lightSquareColor;
3711 wlPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3713 gc_values.foreground = whitePieceColor;
3714 gc_values.background = jailSquareColor;
3715 wjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3717 gc_values.foreground = blackPieceColor;
3718 gc_values.background = darkSquareColor;
3719 bdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3721 gc_values.foreground = blackPieceColor;
3722 gc_values.background = lightSquareColor;
3723 blPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3725 gc_values.foreground = blackPieceColor;
3726 gc_values.background = jailSquareColor;
3727 bjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3731 void loadXIM(xim, xmask, filename, dest, mask)
3744 fp = fopen(filename, "rb");
3746 fprintf(stderr, _("%s: error loading XIM!\n"), programName);
3753 for (y=0; y<h; ++y) {
3754 for (x=0; x<h; ++x) {
3759 XPutPixel(xim, x, y, blackPieceColor);
3761 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3764 XPutPixel(xim, x, y, darkSquareColor);
3766 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3769 XPutPixel(xim, x, y, whitePieceColor);
3771 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3774 XPutPixel(xim, x, y, lightSquareColor);
3776 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3782 /* create Pixmap of piece */
3783 *dest = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3785 XPutImage(xDisplay, *dest, lightSquareGC, xim,
3788 /* create Pixmap of clipmask
3789 Note: We assume the white/black pieces have the same
3790 outline, so we make only 6 masks. This is okay
3791 since the XPM clipmask routines do the same. */
3793 temp = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3795 XPutImage(xDisplay, temp, lightSquareGC, xmask,
3798 /* now create the 1-bit version */
3799 *mask = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3802 values.foreground = 1;
3803 values.background = 0;
3805 /* Don't use XtGetGC, not read only */
3806 maskGC = XCreateGC(xDisplay, *mask,
3807 GCForeground | GCBackground, &values);
3808 XCopyPlane(xDisplay, temp, *mask, maskGC,
3809 0, 0, squareSize, squareSize, 0, 0, 1);
3810 XFreePixmap(xDisplay, temp);
3815 char pieceBitmapNames[] = "pnbrqfeacwmohijgdvlsukpnsl";
3817 void CreateXIMPieces()
3822 static char *ximkind[] = { "ll", "ld", "dl", "dd" };
3827 /* The XSynchronize calls were copied from CreatePieces.
3828 Not sure if needed, but can't hurt */
3829 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3832 /* temp needed by loadXIM() */
3833 ximtemp = XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3834 0, 0, ss, ss, AllPlanes, XYPixmap);
3836 if (strlen(appData.pixmapDirectory) == 0) {
3840 if (appData.monoMode) {
3841 DisplayFatalError(_("XIM pieces cannot be used in monochrome mode"),
3845 fprintf(stderr, _("\nLoading XIMs...\n"));
3847 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3848 fprintf(stderr, "%d", piece+1);
3849 for (kind=0; kind<4; kind++) {
3850 fprintf(stderr, ".");
3851 snprintf(buf, sizeof(buf), "%s/%s%c%s%u.xim",
3852 ExpandPathName(appData.pixmapDirectory),
3853 piece <= (int) WhiteKing ? "" : "w",
3854 pieceBitmapNames[piece],
3856 ximPieceBitmap[kind][piece] =
3857 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3858 0, 0, ss, ss, AllPlanes, XYPixmap);
3859 if (appData.debugMode)
3860 fprintf(stderr, _("(File:%s:) "), buf);
3861 loadXIM(ximPieceBitmap[kind][piece],
3863 &(xpmPieceBitmap2[kind][piece]),
3864 &(ximMaskPm2[piece]));
3865 if(piece <= (int)WhiteKing)
3866 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3868 fprintf(stderr," ");
3870 /* Load light and dark squares */
3871 /* If the LSQ and DSQ pieces don't exist, we will
3872 draw them with solid squares. */
3873 snprintf(buf,sizeof(buf), "%s/lsq%u.xim", ExpandPathName(appData.pixmapDirectory), ss);
3874 if (access(buf, 0) != 0) {
3878 fprintf(stderr, _("light square "));
3880 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3881 0, 0, ss, ss, AllPlanes, XYPixmap);
3882 if (appData.debugMode)
3883 fprintf(stderr, _("(File:%s:) "), buf);
3885 loadXIM(ximLightSquare, NULL, buf, &xpmLightSquare, NULL);
3886 fprintf(stderr, _("dark square "));
3887 snprintf(buf,sizeof(buf), "%s/dsq%u.xim",
3888 ExpandPathName(appData.pixmapDirectory), ss);
3889 if (appData.debugMode)
3890 fprintf(stderr, _("(File:%s:) "), buf);
3892 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3893 0, 0, ss, ss, AllPlanes, XYPixmap);
3894 loadXIM(ximDarkSquare, NULL, buf, &xpmDarkSquare, NULL);
3895 xpmJailSquare = xpmLightSquare;
3897 fprintf(stderr, _("Done.\n"));
3899 XSynchronize(xDisplay, False); /* Work-around for xlib/xt buffering bug */
3903 void CreateXPMPieces()
3907 u_int ss = squareSize;
3909 static char *xpmkind[] = { "ll", "ld", "dl", "dd" };
3910 XpmColorSymbol symbols[4];
3912 /* The XSynchronize calls were copied from CreatePieces.
3913 Not sure if needed, but can't hurt */
3914 XSynchronize(xDisplay, True); /* Work-around for xlib/xt buffering bug */
3916 /* Setup translations so piece colors match square colors */
3917 symbols[0].name = "light_piece";
3918 symbols[0].value = appData.whitePieceColor;
3919 symbols[1].name = "dark_piece";
3920 symbols[1].value = appData.blackPieceColor;
3921 symbols[2].name = "light_square";
3922 symbols[2].value = appData.lightSquareColor;
3923 symbols[3].name = "dark_square";
3924 symbols[3].value = appData.darkSquareColor;
3926 attr.valuemask = XpmColorSymbols;
3927 attr.colorsymbols = symbols;
3928 attr.numsymbols = 4;
3930 if (appData.monoMode) {
3931 DisplayFatalError(_("XPM pieces cannot be used in monochrome mode"),
3935 if (strlen(appData.pixmapDirectory) == 0) {
3936 XpmPieces* pieces = builtInXpms;
3939 while (pieces->size != squareSize && pieces->size) pieces++;
3940 if (!pieces->size) {
3941 fprintf(stderr, _("No builtin XPM pieces of size %d\n"), squareSize);
3944 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3945 for (kind=0; kind<4; kind++) {
3947 if ((r=XpmCreatePixmapFromData(xDisplay, xBoardWindow,
3948 pieces->xpm[piece][kind],
3949 &(xpmPieceBitmap2[kind][piece]),
3950 NULL, &attr)) != 0) {
3951 fprintf(stderr, _("Error %d loading XPM image \"%s\"\n"),
3955 if(piece <= (int) WhiteKing)
3956 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3960 xpmJailSquare = xpmLightSquare;
3964 fprintf(stderr, _("\nLoading XPMs...\n"));
3967 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3968 fprintf(stderr, "%d ", piece+1);
3969 for (kind=0; kind<4; kind++) {
3970 snprintf(buf, sizeof(buf), "%s/%s%c%s%u.xpm",
3971 ExpandPathName(appData.pixmapDirectory),
3972 piece > (int) WhiteKing ? "w" : "",
3973 pieceBitmapNames[piece],
3975 if (appData.debugMode) {
3976 fprintf(stderr, _("(File:%s:) "), buf);
3978 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3979 &(xpmPieceBitmap2[kind][piece]),
3980 NULL, &attr)) != 0) {
3981 if(piece != (int)WhiteKing && piece > (int)WhiteQueen) {
3982 // [HGM] missing: read of unorthodox piece failed; substitute King.
3983 snprintf(buf, sizeof(buf), "%s/k%s%u.xpm",
3984 ExpandPathName(appData.pixmapDirectory),
3986 if (appData.debugMode) {
3987 fprintf(stderr, _("(Replace by File:%s:) "), buf);
3989 r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3990 &(xpmPieceBitmap2[kind][piece]),
3994 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"),
3999 if(piece <= (int) WhiteKing)
4000 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
4003 /* Load light and dark squares */
4004 /* If the LSQ and DSQ pieces don't exist, we will
4005 draw them with solid squares. */
4006 fprintf(stderr, _("light square "));
4007 snprintf(buf, sizeof(buf), "%s/lsq%u.xpm", ExpandPathName(appData.pixmapDirectory), ss);
4008 if (access(buf, 0) != 0) {
4012 if (appData.debugMode)
4013 fprintf(stderr, _("(File:%s:) "), buf);
4015 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
4016 &xpmLightSquare, NULL, &attr)) != 0) {
4017 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
4020 fprintf(stderr, _("dark square "));
4021 snprintf(buf, sizeof(buf), "%s/dsq%u.xpm",
4022 ExpandPathName(appData.pixmapDirectory), ss);
4023 if (appData.debugMode) {
4024 fprintf(stderr, _("(File:%s:) "), buf);
4026 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
4027 &xpmDarkSquare, NULL, &attr)) != 0) {
4028 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
4032 xpmJailSquare = xpmLightSquare;
4033 fprintf(stderr, _("Done.\n"));
4035 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
4038 #endif /* HAVE_LIBXPM */
4041 /* No built-in bitmaps */
4046 u_int ss = squareSize;
4048 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
4051 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
4052 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
4053 sprintf(buf, "%s%c%u%c.bm", piece > (int)WhiteKing ? "w" : "",
4054 pieceBitmapNames[piece],
4055 ss, kind == SOLID ? 's' : 'o');
4056 ReadBitmap(&pieceBitmap2[kind][piece], buf, NULL, ss, ss);
4057 if(piece <= (int)WhiteKing)
4058 pieceBitmap[kind][piece] = pieceBitmap2[kind][piece];
4062 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
4066 /* With built-in bitmaps */
4069 BuiltInBits* bib = builtInBits;
4072 u_int ss = squareSize;
4074 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
4077 while (bib->squareSize != ss && bib->squareSize != 0) bib++;
4079 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
4080 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
4081 sprintf(buf, "%s%c%u%c.bm", piece > (int)WhiteKing ? "w" : "",
4082 pieceBitmapNames[piece],
4083 ss, kind == SOLID ? 's' : 'o');
4084 ReadBitmap(&pieceBitmap2[kind][piece], buf,
4085 bib->bits[kind][piece], ss, ss);
4086 if(piece <= (int)WhiteKing)
4087 pieceBitmap[kind][piece] = pieceBitmap2[kind][piece];
4091 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
4096 void ReadBitmap(pm, name, bits, wreq, hreq)
4099 unsigned char bits[];
4105 char msg[MSG_SIZ], fullname[MSG_SIZ];
4107 if (*appData.bitmapDirectory != NULLCHAR) {
4108 strcpy(fullname, appData.bitmapDirectory);
4109 strcat(fullname, "/");
4110 strcat(fullname, name);
4111 errcode = XReadBitmapFile(xDisplay, xBoardWindow, fullname,
4112 &w, &h, pm, &x_hot, &y_hot);
4113 fprintf(stderr, "load %s\n", name);
4114 if (errcode != BitmapSuccess) {
4116 case BitmapOpenFailed:
4117 snprintf(msg, sizeof(msg), _("Can't open bitmap file %s"), fullname);
4119 case BitmapFileInvalid:
4120 snprintf(msg, sizeof(msg), _("Invalid bitmap in file %s"), fullname);
4122 case BitmapNoMemory:
4123 snprintf(msg, sizeof(msg), _("Ran out of memory reading bitmap file %s"),
4127 snprintf(msg, sizeof(msg), _("Unknown XReadBitmapFile error %d on file %s"),
4131 fprintf(stderr, _("%s: %s...using built-in\n"),
4133 } else if (w != wreq || h != hreq) {
4135 _("%s: Bitmap %s is %dx%d, not %dx%d...using built-in\n"),
4136 programName, fullname, w, h, wreq, hreq);
4142 *pm = XCreateBitmapFromData(xDisplay, xBoardWindow, (char *) bits,
4151 if (lineGap == 0) return;
4153 /* [HR] Split this into 2 loops for non-square boards. */
4155 for (i = 0; i < BOARD_HEIGHT + 1; i++) {
4156 gridSegments[i].x1 = 0;
4157 gridSegments[i].x2 =
4158 lineGap + BOARD_WIDTH * (squareSize + lineGap);
4159 gridSegments[i].y1 = gridSegments[i].y2
4160 = lineGap / 2 + (i * (squareSize + lineGap));
4163 for (j = 0; j < BOARD_WIDTH + 1; j++) {
4164 gridSegments[j + i].y1 = 0;
4165 gridSegments[j + i].y2 =
4166 lineGap + BOARD_HEIGHT * (squareSize + lineGap);
4167 gridSegments[j + i].x1 = gridSegments[j + i].x2
4168 = lineGap / 2 + (j * (squareSize + lineGap));
4172 static void MenuBarSelect(w, addr, index)
4177 XtActionProc proc = (XtActionProc) addr;
4179 (proc)(NULL, NULL, NULL, NULL);
4182 void CreateMenuBarPopup(parent, name, mb)
4192 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
4195 XtSetArg(args[j], XtNleftMargin, 20); j++;
4196 XtSetArg(args[j], XtNrightMargin, 20); j++;
4198 while (mi->string != NULL) {
4199 if (strcmp(mi->string, "----") == 0) {
4200 entry = XtCreateManagedWidget(mi->string, smeLineObjectClass,
4203 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string)));
4204 entry = XtCreateManagedWidget(mi->string, smeBSBObjectClass,
4206 XtAddCallback(entry, XtNcallback,
4207 (XtCallbackProc) MenuBarSelect,
4208 (caddr_t) mi->proc);
4214 Widget CreateMenuBar(mb)
4218 Widget anchor, menuBar;
4220 char menuName[MSG_SIZ];
4223 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
4224 XtSetArg(args[j], XtNvSpace, 0); j++;
4225 XtSetArg(args[j], XtNborderWidth, 0); j++;
4226 menuBar = XtCreateWidget("menuBar", boxWidgetClass,
4227 formWidget, args, j);
4229 while (mb->name != NULL) {
4230 strcpy(menuName, "menu");
4231 strcat(menuName, mb->name);
4233 XtSetArg(args[j], XtNmenuName, XtNewString(menuName)); j++;
4236 shortName[0] = _(mb->name)[0];
4237 shortName[1] = NULLCHAR;
4238 XtSetArg(args[j], XtNlabel, XtNewString(shortName)); j++;
4241 XtSetArg(args[j], XtNlabel, XtNewString(_(mb->name))); j++;
4244 XtSetArg(args[j], XtNborderWidth, 0); j++;
4245 anchor = XtCreateManagedWidget(mb->name, menuButtonWidgetClass,
4247 CreateMenuBarPopup(menuBar, menuName, mb);
4253 Widget CreateButtonBar(mi)
4257 Widget button, buttonBar;
4261 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
4263 XtSetArg(args[j], XtNhSpace, 0); j++;
4265 XtSetArg(args[j], XtNborderWidth, 0); j++;
4266 XtSetArg(args[j], XtNvSpace, 0); j++;
4267 buttonBar = XtCreateWidget("buttonBar", boxWidgetClass,
4268 formWidget, args, j);
4270 while (mi->string != NULL) {
4273 XtSetArg(args[j], XtNinternalWidth, 2); j++;
4274 XtSetArg(args[j], XtNborderWidth, 0); j++;
4276 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string))); j++;
4277 button = XtCreateManagedWidget(mi->string, commandWidgetClass,
4278 buttonBar, args, j);
4279 XtAddCallback(button, XtNcallback,
4280 (XtCallbackProc) MenuBarSelect,
4281 (caddr_t) mi->proc);
4288 CreatePieceMenu(name, color)
4295 ChessSquare selection;
4297 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
4298 boardWidget, args, 0);
4300 for (i = 0; i < PIECE_MENU_SIZE; i++) {
4301 String item = pieceMenuStrings[color][i];
4303 if (strcmp(item, "----") == 0) {
4304 entry = XtCreateManagedWidget(item, smeLineObjectClass,
4307 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
4308 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
4310 selection = pieceMenuTranslation[color][i];
4311 XtAddCallback(entry, XtNcallback,
4312 (XtCallbackProc) PieceMenuSelect,
4313 (caddr_t) selection);
4314 if (selection == WhitePawn || selection == BlackPawn) {
4315 XtSetArg(args[0], XtNpopupOnEntry, entry);
4316 XtSetValues(menu, args, 1);
4329 ChessSquare selection;
4331 whitePieceMenu = CreatePieceMenu("menuW", 0);
4332 blackPieceMenu = CreatePieceMenu("menuB", 1);
4334 XtRegisterGrabAction(PieceMenuPopup, True,
4335 (unsigned)(ButtonPressMask|ButtonReleaseMask),
4336 GrabModeAsync, GrabModeAsync);
4338 XtSetArg(args[0], XtNlabel, _("Drop"));
4339 dropMenu = XtCreatePopupShell("menuD", simpleMenuWidgetClass,
4340 boardWidget, args, 1);
4341 for (i = 0; i < DROP_MENU_SIZE; i++) {
4342 String item = dropMenuStrings[i];
4344 if (strcmp(item, "----") == 0) {
4345 entry = XtCreateManagedWidget(item, smeLineObjectClass,
4348 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
4349 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
4351 selection = dropMenuTranslation[i];
4352 XtAddCallback(entry, XtNcallback,
4353 (XtCallbackProc) DropMenuSelect,
4354 (caddr_t) selection);
4359 void SetupDropMenu()
4367 for (i=0; i<sizeof(dmEnables)/sizeof(DropMenuEnables); i++) {
4368 entry = XtNameToWidget(dropMenu, dmEnables[i].widget);
4369 p = strchr(gameMode == IcsPlayingWhite ? white_holding : black_holding,
4370 dmEnables[i].piece);
4371 XtSetSensitive(entry, p != NULL || !appData.testLegality
4372 /*!!temp:*/ || (gameInfo.variant == VariantCrazyhouse
4373 && !appData.icsActive));
4375 while (p && *p++ == dmEnables[i].piece) count++;
4376 snprintf(label, sizeof(label), "%s %d", dmEnables[i].widget, count);
4378 XtSetArg(args[j], XtNlabel, label); j++;
4379 XtSetValues(entry, args, j);
4383 void PieceMenuPopup(w, event, params, num_params)
4387 Cardinal *num_params;
4390 if (event->type != ButtonPress) return;
4391 if (errorUp) ErrorPopDown();
4395 whichMenu = params[0];
4397 case IcsPlayingWhite:
4398 case IcsPlayingBlack:
4400 case MachinePlaysWhite:
4401 case MachinePlaysBlack:
4402 if (appData.testLegality &&
4403 gameInfo.variant != VariantBughouse &&
4404 gameInfo.variant != VariantCrazyhouse) return;
4406 whichMenu = "menuD";
4412 if (((pmFromX = EventToSquare(event->xbutton.x, BOARD_WIDTH)) < 0) ||
4413 ((pmFromY = EventToSquare(event->xbutton.y, BOARD_HEIGHT)) < 0)) {
4414 pmFromX = pmFromY = -1;
4418 pmFromX = BOARD_WIDTH - 1 - pmFromX;
4420 pmFromY = BOARD_HEIGHT - 1 - pmFromY;
4422 XtPopupSpringLoaded(XtNameToWidget(boardWidget, whichMenu));
4425 static void PieceMenuSelect(w, piece, junk)
4430 if (pmFromX < 0 || pmFromY < 0) return;
4431 EditPositionMenuEvent(piece, pmFromX, pmFromY);
4434 static void DropMenuSelect(w, piece, junk)
4439 if (pmFromX < 0 || pmFromY < 0) return;
4440 DropMenuEvent(piece, pmFromX, pmFromY);
4443 void WhiteClock(w, event, prms, nprms)
4449 if (gameMode == EditPosition || gameMode == IcsExamining) {
4450 SetWhiteToPlayEvent();
4451 } else if (gameMode == IcsPlayingBlack || gameMode == MachinePlaysWhite) {
4456 void BlackClock(w, event, prms, nprms)
4462 if (gameMode == EditPosition || gameMode == IcsExamining) {
4463 SetBlackToPlayEvent();
4464 } else if (gameMode == IcsPlayingWhite || gameMode == MachinePlaysBlack) {
4471 * If the user selects on a border boundary, return -1; if off the board,
4472 * return -2. Otherwise map the event coordinate to the square.
4474 int EventToSquare(x, limit)
4482 if ((x % (squareSize + lineGap)) >= squareSize)
4484 x /= (squareSize + lineGap);
4490 static void do_flash_delay(msec)
4496 static void drawHighlight(file, rank, gc)
4502 if (lineGap == 0 || appData.blindfold) return;
4505 x = lineGap/2 + ((BOARD_WIDTH-1)-file) *
4506 (squareSize + lineGap);
4507 y = lineGap/2 + rank * (squareSize + lineGap);
4509 x = lineGap/2 + file * (squareSize + lineGap);
4510 y = lineGap/2 + ((BOARD_HEIGHT-1)-rank) *
4511 (squareSize + lineGap);
4514 XDrawRectangle(xDisplay, xBoardWindow, gc, x, y,
4515 squareSize+lineGap, squareSize+lineGap);
4518 int hi1X = -1, hi1Y = -1, hi2X = -1, hi2Y = -1;
4519 int pm1X = -1, pm1Y = -1, pm2X = -1, pm2Y = -1;
4522 SetHighlights(fromX, fromY, toX, toY)
4523 int fromX, fromY, toX, toY;
4525 if (hi1X != fromX || hi1Y != fromY) {
4526 if (hi1X >= 0 && hi1Y >= 0) {
4527 drawHighlight(hi1X, hi1Y, lineGC);
4529 if (fromX >= 0 && fromY >= 0) {
4530 drawHighlight(fromX, fromY, highlineGC);
4533 if (hi2X != toX || hi2Y != toY) {
4534 if (hi2X >= 0 && hi2Y >= 0) {
4535 drawHighlight(hi2X, hi2Y, lineGC);
4537 if (toX >= 0 && toY >= 0) {
4538 drawHighlight(toX, toY, highlineGC);
4550 SetHighlights(-1, -1, -1, -1);
4555 SetPremoveHighlights(fromX, fromY, toX, toY)
4556 int fromX, fromY, toX, toY;
4558 if (pm1X != fromX || pm1Y != fromY) {
4559 if (pm1X >= 0 && pm1Y >= 0) {
4560 drawHighlight(pm1X, pm1Y, lineGC);
4562 if (fromX >= 0 && fromY >= 0) {
4563 drawHighlight(fromX, fromY, prelineGC);
4566 if (pm2X != toX || pm2Y != toY) {
4567 if (pm2X >= 0 && pm2Y >= 0) {
4568 drawHighlight(pm2X, pm2Y, lineGC);
4570 if (toX >= 0 && toY >= 0) {
4571 drawHighlight(toX, toY, prelineGC);
4581 ClearPremoveHighlights()
4583 SetPremoveHighlights(-1, -1, -1, -1);
4586 static void BlankSquare(x, y, color, piece, dest)
4591 if (useImages && useImageSqs) {
4595 pm = xpmLightSquare;
4600 case 2: /* neutral */
4605 XCopyArea(xDisplay, pm, dest, wlPieceGC, 0, 0,
4606 squareSize, squareSize, x, y);
4616 case 2: /* neutral */
4621 XFillRectangle(xDisplay, dest, gc, x, y, squareSize, squareSize);
4626 I split out the routines to draw a piece so that I could
4627 make a generic flash routine.
4629 static void monoDrawPiece_1bit(piece, square_color, x, y, dest)
4631 int square_color, x, y;
4634 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
4635 switch (square_color) {
4637 case 2: /* neutral */
4639 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
4640 ? *pieceToOutline(piece)
4641 : *pieceToSolid(piece),
4642 dest, bwPieceGC, 0, 0,
4643 squareSize, squareSize, x, y);
4646 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
4647 ? *pieceToSolid(piece)
4648 : *pieceToOutline(piece),
4649 dest, wbPieceGC, 0, 0,
4650 squareSize, squareSize, x, y);
4655 static void monoDrawPiece(piece, square_color, x, y, dest)
4657 int square_color, x, y;
4660 switch (square_color) {
4662 case 2: /* neutral */
4664 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
4665 ? *pieceToOutline(piece)
4666 : *pieceToSolid(piece),
4667 dest, bwPieceGC, 0, 0,
4668 squareSize, squareSize, x, y, 1);
4671 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
4672 ? *pieceToSolid(piece)
4673 : *pieceToOutline(piece),
4674 dest, wbPieceGC, 0, 0,
4675 squareSize, squareSize, x, y, 1);
4680 static void colorDrawPiece(piece, square_color, x, y, dest)
4682 int square_color, x, y;
4685 if(pieceToSolid(piece) == NULL) return; // [HGM] bitmaps: make it non-fatal if we have no bitmap;
4686 switch (square_color) {
4688 XCopyPlane(xDisplay, *pieceToSolid(piece),
4689 dest, (int) piece < (int) BlackPawn
4690 ? wlPieceGC : blPieceGC, 0, 0,
4691 squareSize, squareSize, x, y, 1);
4694 XCopyPlane(xDisplay, *pieceToSolid(piece),
4695 dest, (int) piece < (int) BlackPawn
4696 ? wdPieceGC : bdPieceGC, 0, 0,
4697 squareSize, squareSize, x, y, 1);
4699 case 2: /* neutral */
4701 XCopyPlane(xDisplay, *pieceToSolid(piece),
4702 dest, (int) piece < (int) BlackPawn
4703 ? wjPieceGC : bjPieceGC, 0, 0,
4704 squareSize, squareSize, x, y, 1);
4709 static void colorDrawPieceImage(piece, square_color, x, y, dest)
4711 int square_color, x, y;
4716 switch (square_color) {
4718 case 2: /* neutral */
4720 if ((int)piece < (int) BlackPawn) {
4728 if ((int)piece < (int) BlackPawn) {
4736 XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
4737 dest, wlPieceGC, 0, 0,
4738 squareSize, squareSize, x, y);
4741 typedef void (*DrawFunc)();
4743 DrawFunc ChooseDrawFunc()
4745 if (appData.monoMode) {
4746 if (DefaultDepth(xDisplay, xScreen) == 1) {
4747 return monoDrawPiece_1bit;
4749 return monoDrawPiece;
4753 return colorDrawPieceImage;
4755 return colorDrawPiece;
4759 /* [HR] determine square color depending on chess variant. */
4760 static int SquareColor(row, column)
4765 if (gameInfo.variant == VariantXiangqi) {
4766 if (column >= 3 && column <= 5 && row >= 0 && row <= 2) {
4768 } else if (column >= 3 && column <= 5 && row >= 7 && row <= 9) {
4770 } else if (row <= 4) {
4776 square_color = ((column + row) % 2) == 1;
4779 /* [hgm] holdings: next line makes all holdings squares light */
4780 if(column < BOARD_LEFT || column >= BOARD_RGHT) square_color = 1;
4782 return square_color;
4785 void DrawSquare(row, column, piece, do_flash)
4786 int row, column, do_flash;
4789 int square_color, x, y, direction, font_ascent, font_descent;
4792 XCharStruct overall;
4796 /* Calculate delay in milliseconds (2-delays per complete flash) */
4797 flash_delay = 500 / appData.flashRate;
4800 x = lineGap + ((BOARD_WIDTH-1)-column) *
4801 (squareSize + lineGap);
4802 y = lineGap + row * (squareSize + lineGap);
4804 x = lineGap + column * (squareSize + lineGap);
4805 y = lineGap + ((BOARD_HEIGHT-1)-row) *
4806 (squareSize + lineGap);
4809 square_color = SquareColor(row, column);
4811 if ( // [HGM] holdings: blank out area between board and holdings
4812 column == BOARD_LEFT-1 || column == BOARD_RGHT
4813 || (column == BOARD_LEFT-2 && row < BOARD_HEIGHT-gameInfo.holdingsSize)
4814 || (column == BOARD_RGHT+1 && row >= gameInfo.holdingsSize) ) {
4815 BlankSquare(x, y, 2, EmptySquare, xBoardWindow);
4817 // [HGM] print piece counts next to holdings
4818 string[1] = NULLCHAR;
4819 if (column == (flipView ? BOARD_LEFT-1 : BOARD_RGHT) && piece > 1 ) {
4820 string[0] = '0' + piece;
4821 XTextExtents(countFontStruct, string, 1, &direction,
4822 &font_ascent, &font_descent, &overall);
4823 if (appData.monoMode) {
4824 XDrawImageString(xDisplay, xBoardWindow, countGC,
4825 x + squareSize - overall.width - 2,
4826 y + font_ascent + 1, string, 1);
4828 XDrawString(xDisplay, xBoardWindow, countGC,
4829 x + squareSize - overall.width - 2,
4830 y + font_ascent + 1, string, 1);
4833 if (column == (flipView ? BOARD_RGHT : BOARD_LEFT-1) && piece > 1) {
4834 string[0] = '0' + piece;
4835 XTextExtents(countFontStruct, string, 1, &direction,
4836 &font_ascent, &font_descent, &overall);
4837 if (appData.monoMode) {
4838 XDrawImageString(xDisplay, xBoardWindow, countGC,
4839 x + 2, y + font_ascent + 1, string, 1);
4841 XDrawString(xDisplay, xBoardWindow, countGC,
4842 x + 2, y + font_ascent + 1, string, 1);
4846 if (piece == EmptySquare || appData.blindfold) {
4847 BlankSquare(x, y, square_color, piece, xBoardWindow);
4849 drawfunc = ChooseDrawFunc();
4850 if (do_flash && appData.flashCount > 0) {
4851 for (i=0; i<appData.flashCount; ++i) {
4853 drawfunc(piece, square_color, x, y, xBoardWindow);
4854 XSync(xDisplay, False);
4855 do_flash_delay(flash_delay);
4857 BlankSquare(x, y, square_color, piece, xBoardWindow);
4858 XSync(xDisplay, False);
4859 do_flash_delay(flash_delay);
4862 drawfunc(piece, square_color, x, y, xBoardWindow);
4866 string[1] = NULLCHAR;
4867 if (appData.showCoords && row == (flipView ? BOARD_HEIGHT-1 : 0)
4868 && column >= BOARD_LEFT && column < BOARD_RGHT) {
4869 string[0] = 'a' + column - BOARD_LEFT;
4870 XTextExtents(coordFontStruct, string, 1, &direction,
4871 &font_ascent, &font_descent, &overall);
4872 if (appData.monoMode) {
4873 XDrawImageString(xDisplay, xBoardWindow, coordGC,
4874 x + squareSize - overall.width - 2,
4875 y + squareSize - font_descent - 1, string, 1);
4877 XDrawString(xDisplay, xBoardWindow, coordGC,
4878 x + squareSize - overall.width - 2,
4879 y + squareSize - font_descent - 1, string, 1);
4882 if (appData.showCoords && column == (flipView ? BOARD_RGHT-1 : BOARD_LEFT)) {
4883 string[0] = ONE + row;
4884 XTextExtents(coordFontStruct, string, 1, &direction,
4885 &font_ascent, &font_descent, &overall);
4886 if (appData.monoMode) {
4887 XDrawImageString(xDisplay, xBoardWindow, coordGC,
4888 x + 2, y + font_ascent + 1, string, 1);
4890 XDrawString(xDisplay, xBoardWindow, coordGC,
4891 x + 2, y + font_ascent + 1, string, 1);
4897 /* Why is this needed on some versions of X? */
4898 void EventProc(widget, unused, event)
4903 if (!XtIsRealized(widget))
4906 switch (event->type) {
4908 if (event->xexpose.count > 0) return; /* no clipping is done */
4909 XDrawPosition(widget, True, NULL);
4917 void DrawPosition(fullRedraw, board)
4918 /*Boolean*/int fullRedraw;
4921 XDrawPosition(boardWidget, fullRedraw, board);
4924 /* Returns 1 if there are "too many" differences between b1 and b2
4925 (i.e. more than 1 move was made) */
4926 static int too_many_diffs(b1, b2)
4932 for (i=0; i<BOARD_HEIGHT; ++i) {
4933 for (j=0; j<BOARD_WIDTH; ++j) {
4934 if (b1[i][j] != b2[i][j]) {
4935 if (++c > 4) /* Castling causes 4 diffs */
4944 /* Matrix describing castling maneuvers */
4945 /* Row, ColRookFrom, ColKingFrom, ColRookTo, ColKingTo */
4946 static int castling_matrix[4][5] = {
4947 { 0, 0, 4, 3, 2 }, /* 0-0-0, white */
4948 { 0, 7, 4, 5, 6 }, /* 0-0, white */
4949 { 7, 0, 4, 3, 2 }, /* 0-0-0, black */
4950 { 7, 7, 4, 5, 6 } /* 0-0, black */
4953 /* Checks whether castling occurred. If it did, *rrow and *rcol
4954 are set to the destination (row,col) of the rook that moved.
4956 Returns 1 if castling occurred, 0 if not.
4958 Note: Only handles a max of 1 castling move, so be sure
4959 to call too_many_diffs() first.
4961 static int check_castle_draw(newb, oldb, rrow, rcol)
4968 /* For each type of castling... */
4969 for (i=0; i<4; ++i) {
4970 r = castling_matrix[i];
4972 /* Check the 4 squares involved in the castling move */
4974 for (j=1; j<=4; ++j) {
4975 if (newb[r[0]][r[j]] == oldb[r[0]][r[j]]) {
4982 /* All 4 changed, so it must be a castling move */
4991 static int damage[BOARD_SIZE][BOARD_SIZE];
4994 * event handler for redrawing the board
4996 void XDrawPosition(w, repaint, board)
4998 /*Boolean*/int repaint;
5002 static int lastFlipView = 0;
5003 static int lastBoardValid = 0;
5004 static Board lastBoard;
5008 if (board == NULL) {
5009 if (!lastBoardValid) return;
5012 if (!lastBoardValid || lastFlipView != flipView) {
5013 XtSetArg(args[0], XtNleftBitmap, (flipView ? xMarkPixmap : None));
5014 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flip View"),
5019 * It would be simpler to clear the window with XClearWindow()
5020 * but this causes a very distracting flicker.
5023 if (!repaint && lastBoardValid && lastFlipView == flipView) {
5025 /* If too much changes (begin observing new game, etc.), don't
5027 do_flash = too_many_diffs(board, lastBoard) ? 0 : 1;
5029 /* Special check for castling so we don't flash both the king
5030 and the rook (just flash the king). */
5032 if (check_castle_draw(board, lastBoard, &rrow, &rcol)) {
5033 /* Draw rook with NO flashing. King will be drawn flashing later */
5034 DrawSquare(rrow, rcol, board[rrow][rcol], 0);
5035 lastBoard[rrow][rcol] = board[rrow][rcol];
5039 /* First pass -- Draw (newly) empty squares and repair damage.
5040 This prevents you from having a piece show up twice while it
5041 is flashing on its new square */
5042 for (i = 0; i < BOARD_HEIGHT; i++)
5043 for (j = 0; j < BOARD_WIDTH; j++)
5044 if ((board[i][j] != lastBoard[i][j] && board[i][j] == EmptySquare)
5046 DrawSquare(i, j, board[i][j], 0);
5047 damage[i][j] = False;
5050 /* Second pass -- Draw piece(s) in new position and flash them */
5051 for (i = 0; i < BOARD_HEIGHT; i++)
5052 for (j = 0; j < BOARD_WIDTH; j++)
5053 if (board[i][j] != lastBoard[i][j]) {
5054 DrawSquare(i, j, board[i][j], do_flash);
5058 XDrawSegments(xDisplay, xBoardWindow, lineGC,
5059 gridSegments, BOARD_HEIGHT + BOARD_WIDTH + 2);
5061 for (i = 0; i < BOARD_HEIGHT; i++)
5062 for (j = 0; j < BOARD_WIDTH; j++) {
5063 DrawSquare(i, j, board[i][j], 0);
5064 damage[i][j] = False;
5068 CopyBoard(lastBoard, board);
5070 lastFlipView = flipView;
5072 /* Draw highlights */
5073 if (pm1X >= 0 && pm1Y >= 0) {
5074 drawHighlight(pm1X, pm1Y, prelineGC);
5076 if (pm2X >= 0 && pm2Y >= 0) {
5077 drawHighlight(pm2X, pm2Y, prelineGC);
5079 if (hi1X >= 0 && hi1Y >= 0) {
5080 drawHighlight(hi1X, hi1Y, highlineGC);
5082 if (hi2X >= 0 && hi2Y >= 0) {
5083 drawHighlight(hi2X, hi2Y, highlineGC);
5086 /* If piece being dragged around board, must redraw that too */
5089 XSync(xDisplay, False);
5094 * event handler for redrawing the board
5096 void DrawPositionProc(w, event, prms, nprms)
5102 XDrawPosition(w, True, NULL);
5107 * event handler for parsing user moves
5109 // [HGM] This routine will need quite some reworking. Although the backend still supports the old
5110 // way of doing things, by calling UserMoveEvent() to test the legality of the move and then perform
5111 // it at the end, and doing all kind of preliminary tests here (e.g. to weed out self-captures), it
5112 // should be made to use the new way, of calling UserMoveTest early to determine the legality of the
5113 // move, (which will weed out the illegal selfcaptures and moves into the holdings, and flag promotions),
5114 // and at the end FinishMove() to perform the move after optional promotion popups.
5115 // For now I patched it to allow self-capture with King, and suppress clicks between board and holdings.
5116 void HandleUserMove(w, event, prms, nprms)
5123 Boolean saveAnimate;
5124 static int second = 0, promotionChoice = 0;
5127 if (w != boardWidget || errorExitStatus != -1) return;
5129 x = EventToSquare(event->xbutton.x, BOARD_WIDTH);
5130 y = EventToSquare(event->xbutton.y, BOARD_HEIGHT);
5131 if (!flipView && y >= 0) {
5132 y = BOARD_HEIGHT - 1 - y;
5134 if (flipView && x >= 0) {
5135 x = BOARD_WIDTH - 1 - x;
5138 if(promotionChoice) { // we are waiting for a click to indicate promotion piece
5139 if(event->type == ButtonRelease) return; // ignore upclick of click-click destination
5140 promotionChoice = FALSE; // only one chance: if click not OK it is interpreted as cancel
5141 if(appData.debugMode) fprintf(debugFP, "promotion click, x=%d, y=%d\n", x, y);
5142 if(gameInfo.holdingsWidth &&
5143 (WhiteOnMove(currentMove)
5144 ? x == BOARD_WIDTH-1 && y < gameInfo.holdingsSize && y > 0
5145 : x == 0 && y >= BOARD_HEIGHT - gameInfo.holdingsSize && y < BOARD_HEIGHT-1) ) {
5146 // click in right holdings, for determining promotion piece
5147 ChessSquare p = boards[currentMove][y][x];
5148 if(appData.debugMode) fprintf(debugFP, "square contains %d\n", (int)p);
5149 if(p != EmptySquare) {
5150 FinishMove(NormalMove, fromX, fromY, toX, toY, ToLower(PieceToChar(p)));
5155 DrawPosition(FALSE, boards[currentMove]);
5158 if (event->type == ButtonPress) ErrorPopDown();
5161 if (event->type == ButtonPress) {
5162 XtPopdown(promotionShell);
5163 XtDestroyWidget(promotionShell);
5164 promotionUp = False;
5172 /* [HGM] holdings: next 5 lines: ignore all clicks between board and holdings */
5173 if(event->type == ButtonPress
5174 && ( x == BOARD_LEFT-1 || x == BOARD_RGHT
5175 || x == BOARD_LEFT-2 && y < BOARD_HEIGHT-gameInfo.holdingsSize
5176 || x == BOARD_RGHT+1 && y >= gameInfo.holdingsSize) )
5180 if (event->type == ButtonPress) {
5181 /* First square, prepare to drag */
5182 if (OKToStartUserMove(x, y)) {
5186 DragPieceBegin(event->xbutton.x, event->xbutton.y);
5187 if (appData.highlightDragging) {
5188 SetHighlights(x, y, -1, -1);
5196 if (event->type == ButtonRelease && x == fromX && y == fromY) {
5197 /* Click on single square in stead of drag-drop */
5198 DragPieceEnd(event->xbutton.x, event->xbutton.y);
5199 if (appData.animateDragging) {
5200 /* Undo animation damage if any */
5201 DrawPosition(FALSE, NULL);
5204 /* Second up/down in same square; just abort move */
5209 ClearPremoveHighlights();
5211 /* First upclick in same square; start click-click mode */
5212 SetHighlights(x, y, -1, -1);
5217 moveType = UserMoveTest(fromX, fromY, x, y, NULLCHAR, event->type == ButtonRelease);
5219 if (moveType == Comment) { // kludge for indicating capture-own on Press
5220 /* Clicked again on same color piece -- changed his mind */
5221 /* note that re-clicking same square always hits same color piece */
5222 second = (x == fromX && y == fromY);
5223 if (appData.highlightDragging) {
5224 SetHighlights(x, y, -1, -1);
5228 if (OKToStartUserMove(x, y)) {
5231 DragPieceBegin(event->xbutton.x, event->xbutton.y);
5236 if(moveType == AmbiguousMove) { // kludge to indicate edit-position move
5239 DragPieceEnd(event->xbutton.x, event->xbutton.y);
5240 DrawPosition(FALSE, boards[currentMove]);
5244 /* Complete move; (x,y) is now different from (fromX, fromY) on both Press and Release */
5247 saveAnimate = appData.animate;
5248 if (event->type == ButtonPress) {
5249 /* Finish clickclick move */
5250 if (appData.animate || appData.highlightLastMove) {
5251 SetHighlights(fromX, fromY, toX, toY);
5256 /* Finish drag move */
5257 if (appData.highlightLastMove) {
5258 SetHighlights(fromX, fromY, toX, toY);
5262 DragPieceEnd(event->xbutton.x, event->xbutton.y);
5263 /* Don't animate move and drag both */
5264 appData.animate = FALSE;
5266 if (moveType == WhitePromotionKnight || moveType == BlackPromotionKnight ||
5267 (moveType == WhitePromotionQueen || moveType == BlackPromotionQueen) &&
5268 appData.alwaysPromoteToQueen) { // promotion, but no choice
5269 FinishMove(moveType, fromX, fromY, toX, toY, 'q');
5271 if (moveType == WhitePromotionQueen || moveType == BlackPromotionQueen ) {
5272 SetHighlights(fromX, fromY, toX, toY);
5273 if(gameInfo.variant == VariantSuper || gameInfo.variant == VariantGreat) {
5274 // [HGM] super: promotion to captured piece selected from holdings
5275 ChessSquare p = boards[currentMove][fromY][fromX], q = boards[currentMove][toY][toX];
5276 promotionChoice = TRUE;
5277 // kludge follows to temporarily execute move on display, without promoting yet
5278 boards[currentMove][fromY][fromX] = EmptySquare; // move Pawn to 8th rank
5279 boards[currentMove][toY][toX] = p;
5280 DrawPosition(FALSE, boards[currentMove]);
5281 boards[currentMove][fromY][fromX] = p; // take back, but display stays
5282 boards[currentMove][toY][toX] = q;
5283 DisplayMessage("Click in holdings to choose piece", "");
5287 goto skipClearingFrom; // the skipped stuff is done asynchronously by PromotionCallback
5289 if(moveType != ImpossibleMove) { // valid move, but no promotion
5290 FinishMove(moveType, fromX, fromY, toX, toY, NULLCHAR);
5291 } else { // invalid move; could have set premove
5294 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
5295 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
5298 appData.animate = saveAnimate;
5299 if (appData.animate || appData.animateDragging) {
5300 /* Undo animation damage if needed */
5301 DrawPosition(FALSE, NULL);
5305 void AnimateUserMove (Widget w, XEvent * event,
5306 String * params, Cardinal * nParams)
5308 DragPieceMove(event->xmotion.x, event->xmotion.y);
5311 Widget CommentCreate(name, text, mutable, callback, lines)
5313 int /*Boolean*/ mutable;
5314 XtCallbackProc callback;
5318 Widget shell, layout, form, edit, b_ok, b_cancel, b_clear, b_close, b_edit;
5323 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5324 XtGetValues(boardWidget, args, j);
5327 XtSetArg(args[j], XtNresizable, True); j++;
5330 XtCreatePopupShell(name, topLevelShellWidgetClass,
5331 shellWidget, args, j);
5334 XtCreatePopupShell(name, transientShellWidgetClass,
5335 shellWidget, args, j);
5338 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
5339 layoutArgs, XtNumber(layoutArgs));
5341 XtCreateManagedWidget("form", formWidgetClass, layout,
5342 formArgs, XtNumber(formArgs));
5346 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
5347 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
5349 XtSetArg(args[j], XtNstring, text); j++;
5350 XtSetArg(args[j], XtNtop, XtChainTop); j++;
5351 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5352 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5353 XtSetArg(args[j], XtNright, XtChainRight); j++;
5354 XtSetArg(args[j], XtNresizable, True); j++;
5355 XtSetArg(args[j], XtNwidth, bw_width); j++; /*force wider than buttons*/
5356 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
5357 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
5358 XtSetArg(args[j], XtNautoFill, True); j++;
5359 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
5361 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
5365 XtSetArg(args[j], XtNfromVert, edit); j++;
5366 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5367 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5368 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5369 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5371 XtCreateManagedWidget(_("ok"), commandWidgetClass, form, args, j);
5372 XtAddCallback(b_ok, XtNcallback, callback, (XtPointer) 0);
5375 XtSetArg(args[j], XtNfromVert, edit); j++;
5376 XtSetArg(args[j], XtNfromHoriz, b_ok); j++;
5377 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5378 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5379 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5380 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5382 XtCreateManagedWidget(_("cancel"), commandWidgetClass, form, args, j);
5383 XtAddCallback(b_cancel, XtNcallback, callback, (XtPointer) 0);
5386 XtSetArg(args[j], XtNfromVert, edit); j++;
5387 XtSetArg(args[j], XtNfromHoriz, b_cancel); j++;
5388 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5389 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5390 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5391 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5393 XtCreateManagedWidget(_("clear"), commandWidgetClass, form, args, j);
5394 XtAddCallback(b_clear, XtNcallback, callback, (XtPointer) 0);
5397 XtSetArg(args[j], XtNfromVert, edit); j++;
5398 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5399 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5400 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5401 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5403 XtCreateManagedWidget(_("close"), commandWidgetClass, form, args, j);
5404 XtAddCallback(b_close, XtNcallback, callback, (XtPointer) 0);
5407 XtSetArg(args[j], XtNfromVert, edit); j++;
5408 XtSetArg(args[j], XtNfromHoriz, b_close); j++;
5409 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5410 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5411 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5412 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5414 XtCreateManagedWidget(_("edit"), commandWidgetClass, form, args, j);
5415 XtAddCallback(b_edit, XtNcallback, callback, (XtPointer) 0);
5418 XtRealizeWidget(shell);
5420 if (commentX == -1) {
5423 Dimension pw_height;
5424 Dimension ew_height;
5427 XtSetArg(args[j], XtNheight, &ew_height); j++;
5428 XtGetValues(edit, args, j);
5431 XtSetArg(args[j], XtNheight, &pw_height); j++;
5432 XtGetValues(shell, args, j);
5433 commentH = pw_height + (lines - 1) * ew_height;
5434 commentW = bw_width - 16;
5436 XSync(xDisplay, False);
5438 /* This code seems to tickle an X bug if it is executed too soon
5439 after xboard starts up. The coordinates get transformed as if
5440 the main window was positioned at (0, 0).
5442 XtTranslateCoords(shellWidget,
5443 (bw_width - commentW) / 2, 0 - commentH / 2,
5444 &commentX, &commentY);
5446 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
5447 RootWindowOfScreen(XtScreen(shellWidget)),
5448 (bw_width - commentW) / 2, 0 - commentH / 2,
5453 if (commentY < 0) commentY = 0; /*avoid positioning top offscreen*/
5456 XtSetArg(args[j], XtNheight, commentH); j++;
5457 XtSetArg(args[j], XtNwidth, commentW); j++;
5458 XtSetArg(args[j], XtNx, commentX); j++;
5459 XtSetArg(args[j], XtNy, commentY); j++;
5460 XtSetValues(shell, args, j);
5461 XtSetKeyboardFocus(shell, edit);
5466 /* Used for analysis window and ICS input window */
5467 Widget MiscCreate(name, text, mutable, callback, lines)
5469 int /*Boolean*/ mutable;
5470 XtCallbackProc callback;
5474 Widget shell, layout, form, edit;
5476 Dimension bw_width, pw_height, ew_height, w, h;
5482 XtSetArg(args[j], XtNresizable, True); j++;
5485 XtCreatePopupShell(name, topLevelShellWidgetClass,
5486 shellWidget, args, j);
5489 XtCreatePopupShell(name, transientShellWidgetClass,
5490 shellWidget, args, j);
5493 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
5494 layoutArgs, XtNumber(layoutArgs));
5496 XtCreateManagedWidget("form", formWidgetClass, layout,
5497 formArgs, XtNumber(formArgs));
5501 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
5502 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
5504 XtSetArg(args[j], XtNstring, text); j++;
5505 XtSetArg(args[j], XtNtop, XtChainTop); j++;
5506 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5507 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5508 XtSetArg(args[j], XtNright, XtChainRight); j++;
5509 XtSetArg(args[j], XtNresizable, True); j++;
5510 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
5511 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
5512 XtSetArg(args[j], XtNautoFill, True); j++;
5513 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
5515 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
5517 XtRealizeWidget(shell);
5520 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5521 XtGetValues(boardWidget, args, j);
5524 XtSetArg(args[j], XtNheight, &ew_height); j++;
5525 XtGetValues(edit, args, j);
5528 XtSetArg(args[j], XtNheight, &pw_height); j++;
5529 XtGetValues(shell, args, j);
5530 h = pw_height + (lines - 1) * ew_height;
5533 XSync(xDisplay, False);
5535 /* This code seems to tickle an X bug if it is executed too soon
5536 after xboard starts up. The coordinates get transformed as if
5537 the main window was positioned at (0, 0).
5539 XtTranslateCoords(shellWidget, (bw_width - w) / 2, 0 - h / 2, &x, &y);
5541 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
5542 RootWindowOfScreen(XtScreen(shellWidget)),
5543 (bw_width - w) / 2, 0 - h / 2, &xx, &yy, &junk);
5547 if (y < 0) y = 0; /*avoid positioning top offscreen*/
5550 XtSetArg(args[j], XtNheight, h); j++;
5551 XtSetArg(args[j], XtNwidth, w); j++;
5552 XtSetArg(args[j], XtNx, x); j++;
5553 XtSetArg(args[j], XtNy, y); j++;
5554 XtSetValues(shell, args, j);
5560 static int savedIndex; /* gross that this is global */
5562 void EditCommentPopUp(index, title, text)
5571 if (text == NULL) text = "";
5573 if (editShell == NULL) {
5575 CommentCreate(title, text, True, EditCommentCallback, 4);
5576 XtRealizeWidget(editShell);
5577 CatchDeleteWindow(editShell, "EditCommentPopDown");
5579 edit = XtNameToWidget(editShell, "*form.text");
5581 XtSetArg(args[j], XtNstring, text); j++;
5582 XtSetValues(edit, args, j);
5584 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5585 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5586 XtSetValues(editShell, args, j);
5589 XtPopup(editShell, XtGrabNone);
5593 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
5594 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
5598 void EditCommentCallback(w, client_data, call_data)
5600 XtPointer client_data, call_data;
5608 XtSetArg(args[j], XtNlabel, &name); j++;
5609 XtGetValues(w, args, j);
5611 if (strcmp(name, _("ok")) == 0) {
5612 edit = XtNameToWidget(editShell, "*form.text");
5614 XtSetArg(args[j], XtNstring, &val); j++;
5615 XtGetValues(edit, args, j);
5616 ReplaceComment(savedIndex, val);
5617 EditCommentPopDown();
5618 } else if (strcmp(name, _("cancel")) == 0) {
5619 EditCommentPopDown();
5620 } else if (strcmp(name, _("clear")) == 0) {
5621 edit = XtNameToWidget(editShell, "*form.text");
5622 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
5623 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
5627 void EditCommentPopDown()
5632 if (!editUp) return;
5634 XtSetArg(args[j], XtNx, &commentX); j++;
5635 XtSetArg(args[j], XtNy, &commentY); j++;
5636 XtSetArg(args[j], XtNheight, &commentH); j++;
5637 XtSetArg(args[j], XtNwidth, &commentW); j++;
5638 XtGetValues(editShell, args, j);
5639 XtPopdown(editShell);
5642 XtSetArg(args[j], XtNleftBitmap, None); j++;
5643 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
5647 void ICSInputBoxPopUp()
5652 char *title = _("ICS Input");
5655 if (ICSInputShell == NULL) {
5656 ICSInputShell = MiscCreate(title, "", True, NULL, 1);
5657 tr = XtParseTranslationTable(ICSInputTranslations);
5658 edit = XtNameToWidget(ICSInputShell, "*form.text");
5659 XtOverrideTranslations(edit, tr);
5660 XtRealizeWidget(ICSInputShell);
5661 CatchDeleteWindow(ICSInputShell, "ICSInputBoxPopDown");
5664 edit = XtNameToWidget(ICSInputShell, "*form.text");
5666 XtSetArg(args[j], XtNstring, ""); j++;
5667 XtSetValues(edit, args, j);
5669 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5670 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5671 XtSetValues(ICSInputShell, args, j);
5674 XtPopup(ICSInputShell, XtGrabNone);
5675 XtSetKeyboardFocus(ICSInputShell, edit);
5677 ICSInputBoxUp = True;
5679 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
5680 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
5684 void ICSInputSendText()
5691 edit = XtNameToWidget(ICSInputShell, "*form.text");
5693 XtSetArg(args[j], XtNstring, &val); j++;
5694 XtGetValues(edit, args, j);
5695 SendMultiLineToICS(val);
5696 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
5697 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
5700 void ICSInputBoxPopDown()
5705 if (!ICSInputBoxUp) return;
5707 XtPopdown(ICSInputShell);
5708 ICSInputBoxUp = False;
5710 XtSetArg(args[j], XtNleftBitmap, None); j++;
5711 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
5715 void CommentPopUp(title, text)
5722 if (commentShell == NULL) {
5724 CommentCreate(title, text, False, CommentCallback, 4);
5725 XtRealizeWidget(commentShell);
5726 CatchDeleteWindow(commentShell, "CommentPopDown");
5728 edit = XtNameToWidget(commentShell, "*form.text");
5730 XtSetArg(args[j], XtNstring, text); j++;
5731 XtSetValues(edit, args, j);
5733 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5734 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5735 XtSetValues(commentShell, args, j);
5738 XtPopup(commentShell, XtGrabNone);
5739 XSync(xDisplay, False);
5744 void AnalysisPopUp(title, text)
5751 if (analysisShell == NULL) {
5752 analysisShell = MiscCreate(title, text, False, NULL, 4);
5753 XtRealizeWidget(analysisShell);
5754 CatchDeleteWindow(analysisShell, "AnalysisPopDown");
5757 edit = XtNameToWidget(analysisShell, "*form.text");
5759 XtSetArg(args[j], XtNstring, text); j++;
5760 XtSetValues(edit, args, j);
5762 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5763 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5764 XtSetValues(analysisShell, args, j);
5768 XtPopup(analysisShell, XtGrabNone);
5770 XSync(xDisplay, False);
5775 void CommentCallback(w, client_data, call_data)
5777 XtPointer client_data, call_data;
5784 XtSetArg(args[j], XtNlabel, &name); j++;
5785 XtGetValues(w, args, j);
5787 if (strcmp(name, _("close")) == 0) {
5789 } else if (strcmp(name, _("edit")) == 0) {
5796 void CommentPopDown()
5801 if (!commentUp) return;
5803 XtSetArg(args[j], XtNx, &commentX); j++;
5804 XtSetArg(args[j], XtNy, &commentY); j++;
5805 XtSetArg(args[j], XtNwidth, &commentW); j++;
5806 XtSetArg(args[j], XtNheight, &commentH); j++;
5807 XtGetValues(commentShell, args, j);
5808 XtPopdown(commentShell);
5809 XSync(xDisplay, False);
5813 void AnalysisPopDown()
5815 if (!analysisUp) return;
5816 XtPopdown(analysisShell);
5817 XSync(xDisplay, False);
5819 if (appData.icsEngineAnalyze) ExitAnalyzeMode(); /* [DM] icsEngineAnalyze */
5823 void FileNamePopUp(label, def, proc, openMode)
5830 Widget popup, layout, dialog, edit;
5836 fileProc = proc; /* I can't see a way not */
5837 fileOpenMode = openMode; /* to use globals here */
5840 XtSetArg(args[i], XtNresizable, True); i++;
5841 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
5842 XtSetArg(args[i], XtNtitle, XtNewString(_("File name prompt"))); i++;
5843 fileNameShell = popup =
5844 XtCreatePopupShell("File name prompt", transientShellWidgetClass,
5845 shellWidget, args, i);
5848 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
5849 layoutArgs, XtNumber(layoutArgs));
5852 XtSetArg(args[i], XtNlabel, label); i++;
5853 XtSetArg(args[i], XtNvalue, def); i++;
5854 XtSetArg(args[i], XtNborderWidth, 0); i++;
5855 dialog = XtCreateManagedWidget("fileName", dialogWidgetClass,
5858 XawDialogAddButton(dialog, _("ok"), FileNameCallback, (XtPointer) dialog);
5859 XawDialogAddButton(dialog, _("cancel"), FileNameCallback,
5860 (XtPointer) dialog);
5862 XtRealizeWidget(popup);
5863 CatchDeleteWindow(popup, "FileNamePopDown");
5865 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
5866 &x, &y, &win_x, &win_y, &mask);
5868 XtSetArg(args[0], XtNx, x - 10);
5869 XtSetArg(args[1], XtNy, y - 30);
5870 XtSetValues(popup, args, 2);
5872 XtPopup(popup, XtGrabExclusive);
5875 edit = XtNameToWidget(dialog, "*value");
5876 XtSetKeyboardFocus(popup, edit);
5879 void FileNamePopDown()
5881 if (!filenameUp) return;
5882 XtPopdown(fileNameShell);
5883 XtDestroyWidget(fileNameShell);
5888 void FileNameCallback(w, client_data, call_data)
5890 XtPointer client_data, call_data;
5895 XtSetArg(args[0], XtNlabel, &name);
5896 XtGetValues(w, args, 1);
5898 if (strcmp(name, _("cancel")) == 0) {
5903 FileNameAction(w, NULL, NULL, NULL);
5906 void FileNameAction(w, event, prms, nprms)
5918 name = XawDialogGetValueString(w = XtParent(w));
5920 if ((name != NULL) && (*name != NULLCHAR)) {
5922 XtPopdown(w = XtParent(XtParent(w)));
5926 p = strrchr(buf, ' ');
5933 fullname = ExpandPathName(buf);
5935 ErrorPopUp(_("Error"), _("Can't open file"), FALSE);
5938 f = fopen(fullname, fileOpenMode);
5940 DisplayError(_("Failed to open file"), errno);
5942 (void) (*fileProc)(f, index, buf);
5949 XtPopdown(w = XtParent(XtParent(w)));
5955 void PromotionPopUp()
5958 Widget dialog, layout;
5960 Dimension bw_width, pw_width;
5964 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5965 XtGetValues(boardWidget, args, j);
5968 XtSetArg(args[j], XtNresizable, True); j++;
5969 XtSetArg(args[j], XtNtitle, XtNewString(_("Promotion"))); j++;
5971 XtCreatePopupShell("Promotion", transientShellWidgetClass,
5972 shellWidget, args, j);
5974 XtCreateManagedWidget(layoutName, formWidgetClass, promotionShell,
5975 layoutArgs, XtNumber(layoutArgs));
5978 XtSetArg(args[j], XtNlabel, _("Promote to what?")); j++;
5979 XtSetArg(args[j], XtNborderWidth, 0); j++;
5980 dialog = XtCreateManagedWidget("promotion", dialogWidgetClass,
5983 if(gameInfo.variant != VariantShogi) {
5984 XawDialogAddButton(dialog, _("Queen"), PromotionCallback,
5985 (XtPointer) dialog);
5986 XawDialogAddButton(dialog, _("Rook"), PromotionCallback,
5987 (XtPointer) dialog);
5988 XawDialogAddButton(dialog, _("Bishop"), PromotionCallback,
5989 (XtPointer) dialog);
5990 XawDialogAddButton(dialog, _("Knight"), PromotionCallback,
5991 (XtPointer) dialog);
5992 if (!appData.testLegality || gameInfo.variant == VariantSuicide ||
5993 gameInfo.variant == VariantGiveaway) {
5994 XawDialogAddButton(dialog, _("King"), PromotionCallback,
5995 (XtPointer) dialog);
5997 if(gameInfo.variant == VariantCapablanca ||
5998 gameInfo.variant == VariantGothic ||
5999 gameInfo.variant == VariantCapaRandom) {
6000 XawDialogAddButton(dialog, _("Archbishop"), PromotionCallback,
6001 (XtPointer) dialog);
6002 XawDialogAddButton(dialog, _("Chancellor"), PromotionCallback,
6003 (XtPointer) dialog);
6005 } else // [HGM] shogi
6007 XawDialogAddButton(dialog, _("Promote"), PromotionCallback,
6008 (XtPointer) dialog);
6009 XawDialogAddButton(dialog, _("Defer"), PromotionCallback,
6010 (XtPointer) dialog);
6012 XawDialogAddButton(dialog, _("cancel"), PromotionCallback,
6013 (XtPointer) dialog);
6015 XtRealizeWidget(promotionShell);
6016 CatchDeleteWindow(promotionShell, "PromotionPopDown");
6019 XtSetArg(args[j], XtNwidth, &pw_width); j++;
6020 XtGetValues(promotionShell, args, j);
6022 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
6023 lineGap + squareSize/3 +
6024 ((toY == BOARD_HEIGHT-1) ^ (flipView) ?
6025 0 : 6*(squareSize + lineGap)), &x, &y);
6028 XtSetArg(args[j], XtNx, x); j++;
6029 XtSetArg(args[j], XtNy, y); j++;
6030 XtSetValues(promotionShell, args, j);
6032 XtPopup(promotionShell, XtGrabNone);
6037 void PromotionPopDown()
6039 if (!promotionUp) return;
6040 XtPopdown(promotionShell);
6041 XtDestroyWidget(promotionShell);
6042 promotionUp = False;
6045 void PromotionCallback(w, client_data, call_data)
6047 XtPointer client_data, call_data;
6053 XtSetArg(args[0], XtNlabel, &name);
6054 XtGetValues(w, args, 1);
6058 if (fromX == -1) return;
6060 if (strcmp(name, _("cancel")) == 0) {
6064 } else if (strcmp(name, _("Knight")) == 0) {
6066 } else if (strcmp(name, _("Promote")) == 0) {
6068 } else if (strcmp(name, _("Defer")) == 0) {
6071 promoChar = ToLower(name[0]);
6074 FinishMove(NormalMove, fromX, fromY, toX, toY, promoChar);
6076 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
6077 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
6082 void ErrorCallback(w, client_data, call_data)
6084 XtPointer client_data, call_data;
6087 XtPopdown(w = XtParent(XtParent(XtParent(w))));
6089 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
6095 if (!errorUp) return;
6097 XtPopdown(errorShell);
6098 XtDestroyWidget(errorShell);
6099 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
6102 void ErrorPopUp(title, label, modal)
6103 char *title, *label;
6107 Widget dialog, layout;
6111 Dimension bw_width, pw_width;
6112 Dimension pw_height;
6116 XtSetArg(args[i], XtNresizable, True); i++;
6117 XtSetArg(args[i], XtNtitle, title); i++;
6119 XtCreatePopupShell("errorpopup", transientShellWidgetClass,
6120 shellWidget, args, i);
6122 XtCreateManagedWidget(layoutName, formWidgetClass, errorShell,
6123 layoutArgs, XtNumber(layoutArgs));
6126 XtSetArg(args[i], XtNlabel, label); i++;
6127 XtSetArg(args[i], XtNborderWidth, 0); i++;
6128 dialog = XtCreateManagedWidget("dialog", dialogWidgetClass,
6131 XawDialogAddButton(dialog, _("ok"), ErrorCallback, (XtPointer) dialog);
6133 XtRealizeWidget(errorShell);
6134 CatchDeleteWindow(errorShell, "ErrorPopDown");
6137 XtSetArg(args[i], XtNwidth, &bw_width); i++;
6138 XtGetValues(boardWidget, args, i);
6140 XtSetArg(args[i], XtNwidth, &pw_width); i++;
6141 XtSetArg(args[i], XtNheight, &pw_height); i++;
6142 XtGetValues(errorShell, args, i);
6145 /* This code seems to tickle an X bug if it is executed too soon
6146 after xboard starts up. The coordinates get transformed as if
6147 the main window was positioned at (0, 0).
6149 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
6150 0 - pw_height + squareSize / 3, &x, &y);
6152 XTranslateCoordinates(xDisplay, XtWindow(boardWidget),
6153 RootWindowOfScreen(XtScreen(boardWidget)),
6154 (bw_width - pw_width) / 2,
6155 0 - pw_height + squareSize / 3, &xx, &yy, &junk);
6159 if (y < 0) y = 0; /*avoid positioning top offscreen*/
6162 XtSetArg(args[i], XtNx, x); i++;
6163 XtSetArg(args[i], XtNy, y); i++;
6164 XtSetValues(errorShell, args, i);
6167 XtPopup(errorShell, modal ? XtGrabExclusive : XtGrabNone);
6170 /* Disable all user input other than deleting the window */
6171 static int frozen = 0;
6175 /* Grab by a widget that doesn't accept input */
6176 XtAddGrab(messageWidget, TRUE, FALSE);
6180 /* Undo a FreezeUI */
6183 if (!frozen) return;
6184 XtRemoveGrab(messageWidget);
6188 char *ModeToWidgetName(mode)
6192 case BeginningOfGame:
6193 if (appData.icsActive)
6194 return "menuMode.ICS Client";
6195 else if (appData.noChessProgram ||
6196 *appData.cmailGameName != NULLCHAR)
6197 return "menuMode.Edit Game";
6199 return "menuMode.Machine Black";
6200 case MachinePlaysBlack:
6201 return "menuMode.Machine Black";
6202 case MachinePlaysWhite:
6203 return "menuMode.Machine White";
6205 return "menuMode.Analysis Mode";
6207 return "menuMode.Analyze File";
6208 case TwoMachinesPlay:
6209 return "menuMode.Two Machines";
6211 return "menuMode.Edit Game";
6212 case PlayFromGameFile:
6213 return "menuFile.Load Game";
6215 return "menuMode.Edit Position";
6217 return "menuMode.Training";
6218 case IcsPlayingWhite:
6219 case IcsPlayingBlack:
6223 return "menuMode.ICS Client";
6230 void ModeHighlight()
6233 static int oldPausing = FALSE;
6234 static GameMode oldmode = (GameMode) -1;
6237 if (!boardWidget || !XtIsRealized(boardWidget)) return;
6239 if (pausing != oldPausing) {
6240 oldPausing = pausing;
6242 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6244 XtSetArg(args[0], XtNleftBitmap, None);
6246 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Pause"),
6249 if (appData.showButtonBar) {
6250 /* Always toggle, don't set. Previous code messes up when
6251 invoked while the button is pressed, as releasing it
6252 toggles the state again. */
6255 XtSetArg(args[0], XtNbackground, &oldbg);
6256 XtSetArg(args[1], XtNforeground, &oldfg);
6257 XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON),
6259 XtSetArg(args[0], XtNbackground, oldfg);
6260 XtSetArg(args[1], XtNforeground, oldbg);
6262 XtSetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
6266 wname = ModeToWidgetName(oldmode);
6267 if (wname != NULL) {
6268 XtSetArg(args[0], XtNleftBitmap, None);
6269 XtSetValues(XtNameToWidget(menuBarWidget, wname), args, 1);
6271 wname = ModeToWidgetName(gameMode);
6272 if (wname != NULL) {
6273 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6274 XtSetValues(XtNameToWidget(menuBarWidget, wname), args, 1);
6278 /* Maybe all the enables should be handled here, not just this one */
6279 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Training"),
6280 gameMode == Training || gameMode == PlayFromGameFile);
6285 * Button/menu procedures
6287 void ResetProc(w, event, prms, nprms)
6297 int LoadGamePopUp(f, gameNumber, title)
6302 cmailMsgLoaded = FALSE;
6303 if (gameNumber == 0) {
6304 int error = GameListBuild(f);
6306 DisplayError(_("Cannot build game list"), error);
6307 } else if (!ListEmpty(&gameList) &&
6308 ((ListGame *) gameList.tailPred)->number > 1) {
6309 GameListPopUp(f, title);
6315 return LoadGame(f, gameNumber, title, FALSE);
6318 void LoadGameProc(w, event, prms, nprms)
6324 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
6327 FileNamePopUp(_("Load game file name?"), "", LoadGamePopUp, "rb");
6330 void LoadNextGameProc(w, event, prms, nprms)
6339 void LoadPrevGameProc(w, event, prms, nprms)
6348 void ReloadGameProc(w, event, prms, nprms)
6357 void LoadNextPositionProc(w, event, prms, nprms)
6366 void LoadPrevPositionProc(w, event, prms, nprms)
6375 void ReloadPositionProc(w, event, prms, nprms)
6384 void LoadPositionProc(w, event, prms, nprms)
6390 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
6393 FileNamePopUp(_("Load position file name?"), "", LoadPosition, "rb");
6396 void SaveGameProc(w, event, prms, nprms)
6402 FileNamePopUp(_("Save game file name?"),
6403 DefaultFileName(appData.oldSaveStyle ? "game" : "pgn"),
6407 void SavePositionProc(w, event, prms, nprms)
6413 FileNamePopUp(_("Save position file name?"),
6414 DefaultFileName(appData.oldSaveStyle ? "pos" : "fen"),
6418 void ReloadCmailMsgProc(w, event, prms, nprms)
6424 ReloadCmailMsgEvent(FALSE);
6427 void MailMoveProc(w, event, prms, nprms)
6436 /* this variable is shared between CopyPositionProc and SendPositionSelection */
6437 static char *selected_fen_position=NULL;
6440 SendPositionSelection(Widget w, Atom *selection, Atom *target,
6441 Atom *type_return, XtPointer *value_return,
6442 unsigned long *length_return, int *format_return)
6444 char *selection_tmp;
6446 if (!selected_fen_position) return False; /* should never happen */
6447 if (*target == XA_STRING){
6448 /* note: since no XtSelectionDoneProc was registered, Xt will
6449 * automatically call XtFree on the value returned. So have to
6450 * make a copy of it allocated with XtMalloc */
6451 selection_tmp= XtMalloc(strlen(selected_fen_position)+16);
6452 strcpy(selection_tmp, selected_fen_position);
6454 *value_return=selection_tmp;
6455 *length_return=strlen(selection_tmp);
6456 *type_return=XA_STRING;
6457 *format_return = 8; /* bits per byte */
6464 /* note: when called from menu all parameters are NULL, so no clue what the
6465 * Widget which was clicked on was, or what the click event was
6467 void CopyPositionProc(w, event, prms, nprms)
6475 if (selected_fen_position) free(selected_fen_position);
6476 selected_fen_position = (char *)PositionToFEN(currentMove, NULL);
6477 if (!selected_fen_position) return;
6478 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
6480 SendPositionSelection,
6481 NULL/* lose_ownership_proc */ ,
6482 NULL/* transfer_done_proc */);
6484 free(selected_fen_position);
6485 selected_fen_position=NULL;
6489 /* function called when the data to Paste is ready */
6491 PastePositionCB(Widget w, XtPointer client_data, Atom *selection,
6492 Atom *type, XtPointer value, unsigned long *len, int *format)
6495 if (value==NULL || *len==0) return; /* nothing had been selected to copy */
6496 fenstr[*len]='\0'; /* normally this string is terminated, but be safe */
6497 EditPositionPasteFEN(fenstr);
6501 /* called when Paste Position button is pressed,
6502 * all parameters will be NULL */
6503 void PastePositionProc(w, event, prms, nprms)
6509 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
6510 /* (XtSelectionCallbackProc) */ PastePositionCB,
6511 NULL, /* client_data passed to PastePositionCB */
6513 /* better to use the time field from the event that triggered the
6514 * call to this function, but that isn't trivial to get
6522 SendGameSelection(Widget w, Atom *selection, Atom *target,
6523 Atom *type_return, XtPointer *value_return,
6524 unsigned long *length_return, int *format_return)
6526 char *selection_tmp;
6528 if (*target == XA_STRING){
6529 FILE* f = fopen(gameCopyFilename, "r");
6532 if (f == NULL) return False;
6536 selection_tmp = XtMalloc(len + 1);
6537 count = fread(selection_tmp, 1, len, f);
6539 XtFree(selection_tmp);
6542 selection_tmp[len] = NULLCHAR;
6543 *value_return = selection_tmp;
6544 *length_return = len;
6545 *type_return = XA_STRING;
6546 *format_return = 8; /* bits per byte */
6553 /* note: when called from menu all parameters are NULL, so no clue what the
6554 * Widget which was clicked on was, or what the click event was
6556 void CopyGameProc(w, event, prms, nprms)
6564 ret = SaveGameToFile(gameCopyFilename, FALSE);
6567 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
6570 NULL/* lose_ownership_proc */ ,
6571 NULL/* transfer_done_proc */);
6574 /* function called when the data to Paste is ready */
6576 PasteGameCB(Widget w, XtPointer client_data, Atom *selection,
6577 Atom *type, XtPointer value, unsigned long *len, int *format)
6580 if (value == NULL || *len == 0) {
6581 return; /* nothing had been selected to copy */
6583 f = fopen(gamePasteFilename, "w");
6585 DisplayError(_("Can't open temp file"), errno);
6588 fwrite(value, 1, *len, f);
6591 LoadGameFromFile(gamePasteFilename, 0, gamePasteFilename, TRUE);
6594 /* called when Paste Game button is pressed,
6595 * all parameters will be NULL */
6596 void PasteGameProc(w, event, prms, nprms)
6602 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
6603 /* (XtSelectionCallbackProc) */ PasteGameCB,
6604 NULL, /* client_data passed to PasteGameCB */
6606 /* better to use the time field from the event that triggered the
6607 * call to this function, but that isn't trivial to get
6617 SaveGameProc(NULL, NULL, NULL, NULL);
6621 void QuitProc(w, event, prms, nprms)
6630 void PauseProc(w, event, prms, nprms)
6640 void MachineBlackProc(w, event, prms, nprms)
6646 MachineBlackEvent();
6649 void MachineWhiteProc(w, event, prms, nprms)
6655 MachineWhiteEvent();
6658 void AnalyzeModeProc(w, event, prms, nprms)
6666 if (!first.analysisSupport) {
6667 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
6668 DisplayError(buf, 0);
6671 /* [DM] icsEngineAnalyze [HGM] This is horrible code; reverse the gameMode and isEngineAnalyze tests! */
6672 if (appData.icsActive) {
6673 if (gameMode != IcsObserving) {
6674 sprintf(buf,_("You are not observing a game"));
6675 DisplayError(buf, 0);
6677 if (appData.icsEngineAnalyze) {
6678 if (appData.debugMode)
6679 fprintf(debugFP, _("Found unexpected active ICS engine analyze \n"));
6685 /* if enable, use want disable icsEngineAnalyze */
6686 if (appData.icsEngineAnalyze) {
6691 appData.icsEngineAnalyze = TRUE;
6692 if (appData.debugMode)
6693 fprintf(debugFP, _("ICS engine analyze starting... \n"));
6695 if (!appData.showThinking)
6696 ShowThinkingProc(w,event,prms,nprms);
6701 void AnalyzeFileProc(w, event, prms, nprms)
6707 if (!first.analysisSupport) {
6709 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
6710 DisplayError(buf, 0);
6715 if (!appData.showThinking)
6716 ShowThinkingProc(w,event,prms,nprms);
6719 FileNamePopUp(_("File to analyze"), "", LoadGamePopUp, "rb");
6720 AnalysisPeriodicEvent(1);
6723 void TwoMachinesProc(w, event, prms, nprms)
6732 void IcsClientProc(w, event, prms, nprms)
6741 void EditGameProc(w, event, prms, nprms)
6750 void EditPositionProc(w, event, prms, nprms)
6756 EditPositionEvent();
6759 void TrainingProc(w, event, prms, nprms)
6768 void EditCommentProc(w, event, prms, nprms)
6775 EditCommentPopDown();
6781 void IcsInputBoxProc(w, event, prms, nprms)
6787 if (ICSInputBoxUp) {
6788 ICSInputBoxPopDown();
6794 void AcceptProc(w, event, prms, nprms)
6803 void DeclineProc(w, event, prms, nprms)
6812 void RematchProc(w, event, prms, nprms)
6821 void CallFlagProc(w, event, prms, nprms)
6830 void DrawProc(w, event, prms, nprms)
6839 void AbortProc(w, event, prms, nprms)
6848 void AdjournProc(w, event, prms, nprms)
6857 void ResignProc(w, event, prms, nprms)
6866 void AdjuWhiteProc(w, event, prms, nprms)
6872 UserAdjudicationEvent(+1);
6875 void AdjuBlackProc(w, event, prms, nprms)
6881 UserAdjudicationEvent(-1);
6884 void AdjuDrawProc(w, event, prms, nprms)
6890 UserAdjudicationEvent(0);
6893 void EnterKeyProc(w, event, prms, nprms)
6899 if (ICSInputBoxUp == True)
6903 void StopObservingProc(w, event, prms, nprms)
6909 StopObservingEvent();
6912 void StopExaminingProc(w, event, prms, nprms)
6918 StopExaminingEvent();
6922 void ForwardProc(w, event, prms, nprms)
6932 void BackwardProc(w, event, prms, nprms)
6941 void ToStartProc(w, event, prms, nprms)
6950 void ToEndProc(w, event, prms, nprms)
6959 void RevertProc(w, event, prms, nprms)
6968 void TruncateGameProc(w, event, prms, nprms)
6974 TruncateGameEvent();
6976 void RetractMoveProc(w, event, prms, nprms)
6985 void MoveNowProc(w, event, prms, nprms)
6995 void AlwaysQueenProc(w, event, prms, nprms)
7003 appData.alwaysPromoteToQueen = !appData.alwaysPromoteToQueen;
7005 if (appData.alwaysPromoteToQueen) {
7006 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7008 XtSetArg(args[0], XtNleftBitmap, None);
7010 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
7014 void AnimateDraggingProc(w, event, prms, nprms)
7022 appData.animateDragging = !appData.animateDragging;
7024 if (appData.animateDragging) {
7025 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7028 XtSetArg(args[0], XtNleftBitmap, None);
7030 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Dragging"),
7034 void AnimateMovingProc(w, event, prms, nprms)
7042 appData.animate = !appData.animate;
7044 if (appData.animate) {
7045 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7048 XtSetArg(args[0], XtNleftBitmap, None);
7050 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
7054 void AutocommProc(w, event, prms, nprms)
7062 appData.autoComment = !appData.autoComment;
7064 if (appData.autoComment) {
7065 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7067 XtSetArg(args[0], XtNleftBitmap, None);
7069 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
7074 void AutoflagProc(w, event, prms, nprms)
7082 appData.autoCallFlag = !appData.autoCallFlag;
7084 if (appData.autoCallFlag) {
7085 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7087 XtSetArg(args[0], XtNleftBitmap, None);
7089 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
7093 void AutoflipProc(w, event, prms, nprms)
7101 appData.autoFlipView = !appData.autoFlipView;
7103 if (appData.autoFlipView) {
7104 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7106 XtSetArg(args[0], XtNleftBitmap, None);
7108 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flip View"),
7112 void AutobsProc(w, event, prms, nprms)
7120 appData.autoObserve = !appData.autoObserve;
7122 if (appData.autoObserve) {
7123 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7125 XtSetArg(args[0], XtNleftBitmap, None);
7127 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
7131 void AutoraiseProc(w, event, prms, nprms)
7139 appData.autoRaiseBoard = !appData.autoRaiseBoard;
7141 if (appData.autoRaiseBoard) {
7142 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7144 XtSetArg(args[0], XtNleftBitmap, None);
7146 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Raise Board"),
7150 void AutosaveProc(w, event, prms, nprms)
7158 appData.autoSaveGames = !appData.autoSaveGames;
7160 if (appData.autoSaveGames) {
7161 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7163 XtSetArg(args[0], XtNleftBitmap, None);
7165 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
7169 void BlindfoldProc(w, event, prms, nprms)
7177 appData.blindfold = !appData.blindfold;
7179 if (appData.blindfold) {
7180 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7182 XtSetArg(args[0], XtNleftBitmap, None);
7184 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Blindfold"),
7187 DrawPosition(True, NULL);
7190 void TestLegalityProc(w, event, prms, nprms)
7198 appData.testLegality = !appData.testLegality;
7200 if (appData.testLegality) {
7201 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7203 XtSetArg(args[0], XtNleftBitmap, None);
7205 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Test Legality"),
7210 void FlashMovesProc(w, event, prms, nprms)
7218 if (appData.flashCount == 0) {
7219 appData.flashCount = 3;
7221 appData.flashCount = -appData.flashCount;
7224 if (appData.flashCount > 0) {
7225 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7227 XtSetArg(args[0], XtNleftBitmap, None);
7229 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flash Moves"),
7233 void FlipViewProc(w, event, prms, nprms)
7239 flipView = !flipView;
7240 DrawPosition(True, NULL);
7243 void GetMoveListProc(w, event, prms, nprms)
7251 appData.getMoveList = !appData.getMoveList;
7253 if (appData.getMoveList) {
7254 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7257 XtSetArg(args[0], XtNleftBitmap, None);
7259 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
7264 void HighlightDraggingProc(w, event, prms, nprms)
7272 appData.highlightDragging = !appData.highlightDragging;
7274 if (appData.highlightDragging) {
7275 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7277 XtSetArg(args[0], XtNleftBitmap, None);
7279 XtSetValues(XtNameToWidget(menuBarWidget,
7280 "menuOptions.Highlight Dragging"), args, 1);
7284 void HighlightLastMoveProc(w, event, prms, nprms)
7292 appData.highlightLastMove = !appData.highlightLastMove;
7294 if (appData.highlightLastMove) {
7295 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7297 XtSetArg(args[0], XtNleftBitmap, None);
7299 XtSetValues(XtNameToWidget(menuBarWidget,
7300 "menuOptions.Highlight Last Move"), args, 1);
7303 void IcsAlarmProc(w, event, prms, nprms)
7311 appData.icsAlarm = !appData.icsAlarm;
7313 if (appData.icsAlarm) {
7314 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7316 XtSetArg(args[0], XtNleftBitmap, None);
7318 XtSetValues(XtNameToWidget(menuBarWidget,
7319 "menuOptions.ICS Alarm"), args, 1);
7322 void MoveSoundProc(w, event, prms, nprms)
7330 appData.ringBellAfterMoves = !appData.ringBellAfterMoves;
7332 if (appData.ringBellAfterMoves) {
7333 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7335 XtSetArg(args[0], XtNleftBitmap, None);
7337 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
7342 void OldSaveStyleProc(w, event, prms, nprms)
7350 appData.oldSaveStyle = !appData.oldSaveStyle;
7352 if (appData.oldSaveStyle) {
7353 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7355 XtSetArg(args[0], XtNleftBitmap, None);
7357 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Old Save Style"),
7361 void PeriodicUpdatesProc(w, event, prms, nprms)
7369 PeriodicUpdatesEvent(!appData.periodicUpdates);
7371 if (appData.periodicUpdates) {
7372 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7374 XtSetArg(args[0], XtNleftBitmap, None);
7376 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Periodic Updates"),
7380 void PonderNextMoveProc(w, event, prms, nprms)
7388 PonderNextMoveEvent(!appData.ponderNextMove);
7390 if (appData.ponderNextMove) {
7391 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7393 XtSetArg(args[0], XtNleftBitmap, None);
7395 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Ponder Next Move"),
7399 void PopupExitMessageProc(w, event, prms, nprms)
7407 appData.popupExitMessage = !appData.popupExitMessage;
7409 if (appData.popupExitMessage) {
7410 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7412 XtSetArg(args[0], XtNleftBitmap, None);
7414 XtSetValues(XtNameToWidget(menuBarWidget,
7415 "menuOptions.Popup Exit Message"), args, 1);
7418 void PopupMoveErrorsProc(w, event, prms, nprms)
7426 appData.popupMoveErrors = !appData.popupMoveErrors;
7428 if (appData.popupMoveErrors) {
7429 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7431 XtSetArg(args[0], XtNleftBitmap, None);
7433 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Popup Move Errors"),
7437 void PremoveProc(w, event, prms, nprms)
7445 appData.premove = !appData.premove;
7447 if (appData.premove) {
7448 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7450 XtSetArg(args[0], XtNleftBitmap, None);
7452 XtSetValues(XtNameToWidget(menuBarWidget,
7453 "menuOptions.Premove"), args, 1);
7456 void QuietPlayProc(w, event, prms, nprms)
7464 appData.quietPlay = !appData.quietPlay;
7466 if (appData.quietPlay) {
7467 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7469 XtSetArg(args[0], XtNleftBitmap, None);
7471 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Quiet Play"),
7475 void ShowCoordsProc(w, event, prms, nprms)
7483 appData.showCoords = !appData.showCoords;
7485 if (appData.showCoords) {
7486 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7488 XtSetArg(args[0], XtNleftBitmap, None);
7490 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
7493 DrawPosition(True, NULL);
7496 void ShowThinkingProc(w, event, prms, nprms)
7504 appData.showThinking = !appData.showThinking; // [HGM] thinking: tken out of ShowThinkingEvent
7505 ShowThinkingEvent();
7508 void HideThinkingProc(w, event, prms, nprms)
7516 appData.hideThinkingFromHuman = !appData.hideThinkingFromHuman; // [HGM] thinking: tken out of ShowThinkingEvent
7517 ShowThinkingEvent();
7519 if (appData.hideThinkingFromHuman) {
7520 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7522 XtSetArg(args[0], XtNleftBitmap, None);
7524 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
7528 void InfoProc(w, event, prms, nprms)
7535 snprintf(buf, sizeof(buf), "xterm -e info --directory %s --directory . -f %s &",
7540 void ManProc(w, event, prms, nprms)
7548 if (nprms && *nprms > 0)
7552 snprintf(buf, sizeof(buf), "xterm -e man %s &", name);
7556 void HintProc(w, event, prms, nprms)
7565 void BookProc(w, event, prms, nprms)
7574 void AboutProc(w, event, prms, nprms)
7582 char *zippy = " (with Zippy code)";
7586 snprintf(buf, sizeof(buf), "%s%s\n\n%s\n%s\n%s\n\n%s%s\n%s",
7587 programVersion, zippy,
7588 "Copyright 1991 Digital Equipment Corporation",
7589 "Enhancements Copyright 1992-2009 Free Software Foundation",
7590 "Enhancements Copyright 2005 Alessandro Scotti",
7591 PACKAGE, " is free software and carries NO WARRANTY;",
7592 "see the file COPYING for more information.");
7593 ErrorPopUp(_("About XBoard"), buf, FALSE);
7596 void DebugProc(w, event, prms, nprms)
7602 appData.debugMode = !appData.debugMode;
7605 void AboutGameProc(w, event, prms, nprms)
7614 void NothingProc(w, event, prms, nprms)
7623 void Iconify(w, event, prms, nprms)
7632 XtSetArg(args[0], XtNiconic, True);
7633 XtSetValues(shellWidget, args, 1);
7636 void DisplayMessage(message, extMessage)
7637 char *message, *extMessage;
7639 /* display a message in the message widget */
7648 snprintf(buf, sizeof(buf), "%s %s", message, extMessage);
7653 message = extMessage;
7657 /* need to test if messageWidget already exists, since this function
7658 can also be called during the startup, if for example a Xresource
7659 is not set up correctly */
7662 XtSetArg(arg, XtNlabel, message);
7663 XtSetValues(messageWidget, &arg, 1);
7669 void DisplayTitle(text)
7674 char title[MSG_SIZ];
7677 if (text == NULL) text = "";
7679 if (appData.titleInWindow) {
7681 XtSetArg(args[i], XtNlabel, text); i++;
7682 XtSetValues(titleWidget, args, i);
7685 if (*text != NULLCHAR) {
7687 strcpy(title, text);
7688 } else if (appData.icsActive) {
7689 snprintf(icon, sizeof(icon), "%s", appData.icsHost);
7690 snprintf(title, sizeof(title), "%s: %s", programName, appData.icsHost);
7691 } else if (appData.cmailGameName[0] != NULLCHAR) {
7692 snprintf(icon, sizeof(icon), "%s", "CMail");
7693 snprintf(title,sizeof(title), "%s: %s", programName, "CMail");
7695 // [HGM] license: This stuff should really be done in back-end, but WinBoard already had a pop-up for it
7696 } else if (gameInfo.variant == VariantGothic) {
7697 strcpy(icon, programName);
7698 strcpy(title, GOTHIC);
7701 } else if (gameInfo.variant == VariantFalcon) {
7702 strcpy(icon, programName);
7703 strcpy(title, FALCON);
7705 } else if (appData.noChessProgram) {
7706 strcpy(icon, programName);
7707 strcpy(title, programName);
7709 strcpy(icon, first.tidy);
7710 snprintf(title,sizeof(title), "%s: %s", programName, first.tidy);
7713 XtSetArg(args[i], XtNiconName, (XtArgVal) icon); i++;
7714 XtSetArg(args[i], XtNtitle, (XtArgVal) title); i++;
7715 XtSetValues(shellWidget, args, i);
7719 void DisplayError(message, error)
7726 if (appData.debugMode || appData.matchMode) {
7727 fprintf(stderr, "%s: %s\n", programName, message);
7730 if (appData.debugMode || appData.matchMode) {
7731 fprintf(stderr, "%s: %s: %s\n",
7732 programName, message, strerror(error));
7734 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
7737 ErrorPopUp(_("Error"), message, FALSE);
7741 void DisplayMoveError(message)
7746 DrawPosition(FALSE, NULL);
7747 if (appData.debugMode || appData.matchMode) {
7748 fprintf(stderr, "%s: %s\n", programName, message);
7750 if (appData.popupMoveErrors) {
7751 ErrorPopUp(_("Error"), message, FALSE);
7753 DisplayMessage(message, "");
7758 void DisplayFatalError(message, error, status)
7764 errorExitStatus = status;
7766 fprintf(stderr, "%s: %s\n", programName, message);
7768 fprintf(stderr, "%s: %s: %s\n",
7769 programName, message, strerror(error));
7770 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
7773 if (appData.popupExitMessage && boardWidget && XtIsRealized(boardWidget)) {
7774 ErrorPopUp(status ? _("Fatal Error") : _("Exiting"), message, TRUE);
7780 void DisplayInformation(message)
7784 ErrorPopUp(_("Information"), message, TRUE);
7787 void DisplayNote(message)
7791 ErrorPopUp(_("Note"), message, FALSE);
7795 NullXErrorCheck(dpy, error_event)
7797 XErrorEvent *error_event;
7802 void DisplayIcsInteractionTitle(message)
7805 if (oldICSInteractionTitle == NULL) {
7806 /* Magic to find the old window title, adapted from vim */
7807 char *wina = getenv("WINDOWID");
7809 Window win = (Window) atoi(wina);
7810 Window root, parent, *children;
7811 unsigned int nchildren;
7812 int (*oldHandler)() = XSetErrorHandler(NullXErrorCheck);
7814 if (XFetchName(xDisplay, win, &oldICSInteractionTitle)) break;
7815 if (!XQueryTree(xDisplay, win, &root, &parent,
7816 &children, &nchildren)) break;
7817 if (children) XFree((void *)children);
7818 if (parent == root || parent == 0) break;
7821 XSetErrorHandler(oldHandler);
7823 if (oldICSInteractionTitle == NULL) {
7824 oldICSInteractionTitle = "xterm";
7827 printf("\033]0;%s\007", message);
7831 char pendingReplyPrefix[MSG_SIZ];
7832 ProcRef pendingReplyPR;
7834 void AskQuestionProc(w, event, prms, nprms)
7841 fprintf(stderr, _("AskQuestionProc needed 4 parameters, got %d\n"),
7845 AskQuestionEvent(prms[0], prms[1], prms[2], prms[3]);
7848 void AskQuestionPopDown()
7850 if (!askQuestionUp) return;
7851 XtPopdown(askQuestionShell);
7852 XtDestroyWidget(askQuestionShell);
7853 askQuestionUp = False;
7856 void AskQuestionReplyAction(w, event, prms, nprms)
7866 reply = XawDialogGetValueString(w = XtParent(w));
7867 strcpy(buf, pendingReplyPrefix);
7868 if (*buf) strcat(buf, " ");
7871 OutputToProcess(pendingReplyPR, buf, strlen(buf), &err);
7872 AskQuestionPopDown();
7874 if (err) DisplayFatalError(_("Error writing to chess program"), err, 0);
7877 void AskQuestionCallback(w, client_data, call_data)
7879 XtPointer client_data, call_data;
7884 XtSetArg(args[0], XtNlabel, &name);
7885 XtGetValues(w, args, 1);
7887 if (strcmp(name, _("cancel")) == 0) {
7888 AskQuestionPopDown();
7890 AskQuestionReplyAction(w, NULL, NULL, NULL);
7894 void AskQuestion(title, question, replyPrefix, pr)
7895 char *title, *question, *replyPrefix;
7899 Widget popup, layout, dialog, edit;
7905 strcpy(pendingReplyPrefix, replyPrefix);
7906 pendingReplyPR = pr;
7909 XtSetArg(args[i], XtNresizable, True); i++;
7910 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
7911 askQuestionShell = popup =
7912 XtCreatePopupShell(title, transientShellWidgetClass,
7913 shellWidget, args, i);
7916 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
7917 layoutArgs, XtNumber(layoutArgs));
7920 XtSetArg(args[i], XtNlabel, question); i++;
7921 XtSetArg(args[i], XtNvalue, ""); i++;
7922 XtSetArg(args[i], XtNborderWidth, 0); i++;
7923 dialog = XtCreateManagedWidget("question", dialogWidgetClass,
7926 XawDialogAddButton(dialog, _("enter"), AskQuestionCallback,
7927 (XtPointer) dialog);
7928 XawDialogAddButton(dialog, _("cancel"), AskQuestionCallback,
7929 (XtPointer) dialog);
7931 XtRealizeWidget(popup);
7932 CatchDeleteWindow(popup, "AskQuestionPopDown");
7934 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
7935 &x, &y, &win_x, &win_y, &mask);
7937 XtSetArg(args[0], XtNx, x - 10);
7938 XtSetArg(args[1], XtNy, y - 30);
7939 XtSetValues(popup, args, 2);
7941 XtPopup(popup, XtGrabExclusive);
7942 askQuestionUp = True;
7944 edit = XtNameToWidget(dialog, "*value");
7945 XtSetKeyboardFocus(popup, edit);
7953 if (*name == NULLCHAR) {
7955 } else if (strcmp(name, "$") == 0) {
7956 putc(BELLCHAR, stderr);
7959 snprintf(buf, sizeof(buf), "%s '%s' &", appData.soundProgram, name);
7967 PlaySound(appData.soundMove);
7973 PlaySound(appData.soundIcsWin);
7979 PlaySound(appData.soundIcsLoss);
7985 PlaySound(appData.soundIcsDraw);
7989 PlayIcsUnfinishedSound()
7991 PlaySound(appData.soundIcsUnfinished);
7997 PlaySound(appData.soundIcsAlarm);
8003 system("stty echo");
8009 system("stty -echo");
8013 Colorize(cc, continuation)
8018 int count, outCount, error;
8020 if (textColors[(int)cc].bg > 0) {
8021 if (textColors[(int)cc].fg > 0) {
8022 sprintf(buf, "\033[0;%d;%d;%dm", textColors[(int)cc].attr,
8023 textColors[(int)cc].fg, textColors[(int)cc].bg);
8025 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
8026 textColors[(int)cc].bg);
8029 if (textColors[(int)cc].fg > 0) {
8030 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
8031 textColors[(int)cc].fg);
8033 sprintf(buf, "\033[0;%dm", textColors[(int)cc].attr);
8036 count = strlen(buf);
8037 outCount = OutputToProcess(NoProc, buf, count, &error);
8038 if (outCount < count) {
8039 DisplayFatalError(_("Error writing to display"), error, 1);
8042 if (continuation) return;
8045 PlaySound(appData.soundShout);
8048 PlaySound(appData.soundSShout);
8051 PlaySound(appData.soundChannel1);
8054 PlaySound(appData.soundChannel);
8057 PlaySound(appData.soundKibitz);
8060 PlaySound(appData.soundTell);
8062 case ColorChallenge:
8063 PlaySound(appData.soundChallenge);
8066 PlaySound(appData.soundRequest);
8069 PlaySound(appData.soundSeek);
8080 return getpwuid(getuid())->pw_name;
8083 static char *ExpandPathName(path)
8086 static char static_buf[2000];
8087 char *d, *s, buf[2000];
8093 while (*s && isspace(*s))
8102 if (*(s+1) == '/') {
8103 strcpy(d, getpwuid(getuid())->pw_dir);
8108 *strchr(buf, '/') = 0;
8109 pwd = getpwnam(buf);
8112 fprintf(stderr, _("ERROR: Unknown user %s (in path %s)\n"),
8116 strcpy(d, pwd->pw_dir);
8117 strcat(d, strchr(s+1, '/'));
8128 static char host_name[MSG_SIZ];
8130 #if HAVE_GETHOSTNAME
8131 gethostname(host_name, MSG_SIZ);
8133 #else /* not HAVE_GETHOSTNAME */
8134 # if HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H
8135 sysinfo(SI_HOSTNAME, host_name, MSG_SIZ);
8137 # else /* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
8139 # endif/* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
8140 #endif /* not HAVE_GETHOSTNAME */
8143 XtIntervalId delayedEventTimerXID = 0;
8144 DelayedEventCallback delayedEventCallback = 0;
8149 delayedEventTimerXID = 0;
8150 delayedEventCallback();
8154 ScheduleDelayedEvent(cb, millisec)
8155 DelayedEventCallback cb; long millisec;
8157 if(delayedEventTimerXID && delayedEventCallback == cb)
8158 // [HGM] alive: replace, rather than add or flush identical event
8159 XtRemoveTimeOut(delayedEventTimerXID);
8160 delayedEventCallback = cb;
8161 delayedEventTimerXID =
8162 XtAppAddTimeOut(appContext, millisec,
8163 (XtTimerCallbackProc) FireDelayedEvent, (XtPointer) 0);
8166 DelayedEventCallback
8169 if (delayedEventTimerXID) {
8170 return delayedEventCallback;
8177 CancelDelayedEvent()
8179 if (delayedEventTimerXID) {
8180 XtRemoveTimeOut(delayedEventTimerXID);
8181 delayedEventTimerXID = 0;
8185 XtIntervalId loadGameTimerXID = 0;
8187 int LoadGameTimerRunning()
8189 return loadGameTimerXID != 0;
8192 int StopLoadGameTimer()
8194 if (loadGameTimerXID != 0) {
8195 XtRemoveTimeOut(loadGameTimerXID);
8196 loadGameTimerXID = 0;
8204 LoadGameTimerCallback(arg, id)
8208 loadGameTimerXID = 0;
8213 StartLoadGameTimer(millisec)
8217 XtAppAddTimeOut(appContext, millisec,
8218 (XtTimerCallbackProc) LoadGameTimerCallback,
8222 XtIntervalId analysisClockXID = 0;
8225 AnalysisClockCallback(arg, id)
8229 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile
8230 || appData.icsEngineAnalyze) { // [DM]
8231 AnalysisPeriodicEvent(0);
8232 StartAnalysisClock();
8237 StartAnalysisClock()
8240 XtAppAddTimeOut(appContext, 2000,
8241 (XtTimerCallbackProc) AnalysisClockCallback,
8245 XtIntervalId clockTimerXID = 0;
8247 int ClockTimerRunning()
8249 return clockTimerXID != 0;
8252 int StopClockTimer()
8254 if (clockTimerXID != 0) {
8255 XtRemoveTimeOut(clockTimerXID);
8264 ClockTimerCallback(arg, id)
8273 StartClockTimer(millisec)
8277 XtAppAddTimeOut(appContext, millisec,
8278 (XtTimerCallbackProc) ClockTimerCallback,
8283 DisplayTimerLabel(w, color, timer, highlight)
8292 /* check for low time warning */
8293 Pixel foregroundOrWarningColor = timerForegroundPixel;
8296 appData.lowTimeWarning &&
8297 (timer / 1000) < appData.icsAlarmTime)
8298 foregroundOrWarningColor = lowTimeWarningColor;
8300 if (appData.clockMode) {
8301 sprintf(buf, "%s: %s", color, TimeString(timer));
8302 XtSetArg(args[0], XtNlabel, buf);
8304 sprintf(buf, "%s ", color);
8305 XtSetArg(args[0], XtNlabel, buf);
8310 XtSetArg(args[1], XtNbackground, foregroundOrWarningColor);
8311 XtSetArg(args[2], XtNforeground, timerBackgroundPixel);
8313 XtSetArg(args[1], XtNbackground, timerBackgroundPixel);
8314 XtSetArg(args[2], XtNforeground, foregroundOrWarningColor);
8317 XtSetValues(w, args, 3);
8321 DisplayWhiteClock(timeRemaining, highlight)
8327 if(appData.noGUI) return;
8328 DisplayTimerLabel(whiteTimerWidget, _("White"), timeRemaining, highlight);
8329 if (highlight && iconPixmap == bIconPixmap) {
8330 iconPixmap = wIconPixmap;
8331 XtSetArg(args[0], XtNiconPixmap, iconPixmap);
8332 XtSetValues(shellWidget, args, 1);
8337 DisplayBlackClock(timeRemaining, highlight)
8343 if(appData.noGUI) return;
8344 DisplayTimerLabel(blackTimerWidget, _("Black"), timeRemaining, highlight);
8345 if (highlight && iconPixmap == wIconPixmap) {
8346 iconPixmap = bIconPixmap;
8347 XtSetArg(args[0], XtNiconPixmap, iconPixmap);
8348 XtSetValues(shellWidget, args, 1);
8366 int StartChildProcess(cmdLine, dir, pr)
8373 int to_prog[2], from_prog[2];
8377 if (appData.debugMode) {
8378 fprintf(stderr, "StartChildProcess (dir=\"%s\") %s\n",dir, cmdLine);
8381 /* We do NOT feed the cmdLine to the shell; we just
8382 parse it into blank-separated arguments in the
8383 most simple-minded way possible.
8386 strcpy(buf, cmdLine);
8391 if (p == NULL) break;
8396 SetUpChildIO(to_prog, from_prog);
8398 if ((pid = fork()) == 0) {
8400 // [HGM] PSWBTM: made order resistant against case where fd of created pipe was 0 or 1
8401 close(to_prog[1]); // first close the unused pipe ends
8402 close(from_prog[0]);
8403 dup2(to_prog[0], 0); // to_prog was created first, nd is the only one to use 0 or 1
8404 dup2(from_prog[1], 1);
8405 if(to_prog[0] >= 2) close(to_prog[0]); // if 0 or 1, the dup2 already cosed the original
8406 close(from_prog[1]); // and closing again loses one of the pipes!
8407 if(fileno(stderr) >= 2) // better safe than sorry...
8408 dup2(1, fileno(stderr)); /* force stderr to the pipe */
8410 if (dir[0] != NULLCHAR && chdir(dir) != 0) {
8415 nice(appData.niceEngines); // [HGM] nice: adjust priority of engine proc
8417 execvp(argv[0], argv);
8419 /* If we get here, exec failed */
8424 /* Parent process */
8426 close(from_prog[1]);
8428 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8431 cp->fdFrom = from_prog[0];
8432 cp->fdTo = to_prog[1];
8437 // [HGM] kill: implement the 'hard killing' of AS's Winboard_x
8438 static RETSIGTYPE AlarmCallBack(int n)
8444 DestroyChildProcess(pr, signalType)
8448 ChildProc *cp = (ChildProc *) pr;
8450 if (cp->kind != CPReal) return;
8452 if (signalType == 10) { // [HGM] kill: if it does not terminate in 3 sec, kill
8453 signal(SIGALRM, AlarmCallBack);
8455 if(wait((int *) 0) == -1) { // process does not terminate on its own accord
8456 kill(cp->pid, SIGKILL); // kill it forcefully
8457 wait((int *) 0); // and wait again
8461 kill(cp->pid, signalType == 9 ? SIGKILL : SIGTERM); // [HGM] kill: use hard kill if so requested
8463 /* Process is exiting either because of the kill or because of
8464 a quit command sent by the backend; either way, wait for it to die.
8473 InterruptChildProcess(pr)
8476 ChildProc *cp = (ChildProc *) pr;
8478 if (cp->kind != CPReal) return;
8479 (void) kill(cp->pid, SIGINT); /* stop it thinking */
8482 int OpenTelnet(host, port, pr)
8487 char cmdLine[MSG_SIZ];
8489 if (port[0] == NULLCHAR) {
8490 snprintf(cmdLine, sizeof(cmdLine), "%s %s", appData.telnetProgram, host);
8492 snprintf(cmdLine, sizeof(cmdLine), "%s %s %s", appData.telnetProgram, host, port);
8494 return StartChildProcess(cmdLine, "", pr);
8497 int OpenTCP(host, port, pr)
8503 DisplayFatalError(_("Socket support is not configured in"), 0, 2);
8504 #else /* !OMIT_SOCKETS */
8506 struct sockaddr_in sa;
8508 unsigned short uport;
8511 if ((s = socket(AF_INET, SOCK_STREAM, 6)) < 0) {
8515 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
8516 sa.sin_family = AF_INET;
8517 sa.sin_addr.s_addr = INADDR_ANY;
8518 uport = (unsigned short) 0;
8519 sa.sin_port = htons(uport);
8520 if (bind(s, (struct sockaddr *) &sa, sizeof(struct sockaddr_in)) < 0) {
8524 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
8525 if (!(hp = gethostbyname(host))) {
8527 if (sscanf(host, "%d.%d.%d.%d", &b0, &b1, &b2, &b3) == 4) {
8528 hp = (struct hostent *) calloc(1, sizeof(struct hostent));
8529 hp->h_addrtype = AF_INET;
8531 hp->h_addr_list = (char **) calloc(2, sizeof(char *));
8532 hp->h_addr_list[0] = (char *) malloc(4);
8533 hp->h_addr_list[0][0] = b0;
8534 hp->h_addr_list[0][1] = b1;
8535 hp->h_addr_list[0][2] = b2;
8536 hp->h_addr_list[0][3] = b3;
8541 sa.sin_family = hp->h_addrtype;
8542 uport = (unsigned short) atoi(port);
8543 sa.sin_port = htons(uport);
8544 memcpy((char *) &sa.sin_addr, hp->h_addr, hp->h_length);
8546 if (connect(s, (struct sockaddr *) &sa,
8547 sizeof(struct sockaddr_in)) < 0) {
8551 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8558 #endif /* !OMIT_SOCKETS */
8563 int OpenCommPort(name, pr)
8570 fd = open(name, 2, 0);
8571 if (fd < 0) return errno;
8573 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8583 int OpenLoopback(pr)
8589 SetUpChildIO(to, from);
8591 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8594 cp->fdFrom = to[0]; /* note not from[0]; we are doing a loopback */
8601 int OpenRcmd(host, user, cmd, pr)
8602 char *host, *user, *cmd;
8605 DisplayFatalError(_("internal rcmd not implemented for Unix"), 0, 1);
8609 #define INPUT_SOURCE_BUF_SIZE 8192
8618 char buf[INPUT_SOURCE_BUF_SIZE];
8623 DoInputCallback(closure, source, xid)
8628 InputSource *is = (InputSource *) closure;
8633 if (is->lineByLine) {
8634 count = read(is->fd, is->unused,
8635 INPUT_SOURCE_BUF_SIZE - (is->unused - is->buf));
8637 (is->func)(is, is->closure, is->buf, count, count ? errno : 0);
8640 is->unused += count;
8642 while (p < is->unused) {
8643 q = memchr(p, '\n', is->unused - p);
8644 if (q == NULL) break;
8646 (is->func)(is, is->closure, p, q - p, 0);
8650 while (p < is->unused) {
8655 count = read(is->fd, is->buf, INPUT_SOURCE_BUF_SIZE);
8660 (is->func)(is, is->closure, is->buf, count, error);
8664 InputSourceRef AddInputSource(pr, lineByLine, func, closure)
8671 ChildProc *cp = (ChildProc *) pr;
8673 is = (InputSource *) calloc(1, sizeof(InputSource));
8674 is->lineByLine = lineByLine;
8678 is->fd = fileno(stdin);
8680 is->kind = cp->kind;
8681 is->fd = cp->fdFrom;
8684 is->unused = is->buf;
8687 is->xid = XtAppAddInput(appContext, is->fd,
8688 (XtPointer) (XtInputReadMask),
8689 (XtInputCallbackProc) DoInputCallback,
8691 is->closure = closure;
8692 return (InputSourceRef) is;
8696 RemoveInputSource(isr)
8699 InputSource *is = (InputSource *) isr;
8701 if (is->xid == 0) return;
8702 XtRemoveInput(is->xid);
8706 int OutputToProcess(pr, message, count, outError)
8712 ChildProc *cp = (ChildProc *) pr;
8716 outCount = fwrite(message, 1, count, stdout);
8718 outCount = write(cp->fdTo, message, count);
8728 /* Output message to process, with "ms" milliseconds of delay
8729 between each character. This is needed when sending the logon
8730 script to ICC, which for some reason doesn't like the
8731 instantaneous send. */
8732 int OutputToProcessDelayed(pr, message, count, outError, msdelay)
8739 ChildProc *cp = (ChildProc *) pr;
8744 r = write(cp->fdTo, message++, 1);
8757 /**** Animation code by Hugh Fisher, DCS, ANU.
8759 Known problem: if a window overlapping the board is
8760 moved away while a piece is being animated underneath,
8761 the newly exposed area won't be updated properly.
8762 I can live with this.
8764 Known problem: if you look carefully at the animation
8765 of pieces in mono mode, they are being drawn as solid
8766 shapes without interior detail while moving. Fixing
8767 this would be a major complication for minimal return.
8770 /* Masks for XPM pieces. Black and white pieces can have
8771 different shapes, but in the interest of retaining my
8772 sanity pieces must have the same outline on both light
8773 and dark squares, and all pieces must use the same
8774 background square colors/images. */
8776 static int xpmDone = 0;
8779 CreateAnimMasks (pieceDepth)
8786 unsigned long plane;
8789 /* Need a bitmap just to get a GC with right depth */
8790 buf = XCreatePixmap(xDisplay, xBoardWindow,
8792 values.foreground = 1;
8793 values.background = 0;
8794 /* Don't use XtGetGC, not read only */
8795 maskGC = XCreateGC(xDisplay, buf,
8796 GCForeground | GCBackground, &values);
8797 XFreePixmap(xDisplay, buf);
8799 buf = XCreatePixmap(xDisplay, xBoardWindow,
8800 squareSize, squareSize, pieceDepth);
8801 values.foreground = XBlackPixel(xDisplay, xScreen);
8802 values.background = XWhitePixel(xDisplay, xScreen);
8803 bufGC = XCreateGC(xDisplay, buf,
8804 GCForeground | GCBackground, &values);
8806 for (piece = WhitePawn; piece <= BlackKing; piece++) {
8807 /* Begin with empty mask */
8808 if(!xpmDone) // [HGM] pieces: keep using existing
8809 xpmMask[piece] = XCreatePixmap(xDisplay, xBoardWindow,
8810 squareSize, squareSize, 1);
8811 XSetFunction(xDisplay, maskGC, GXclear);
8812 XFillRectangle(xDisplay, xpmMask[piece], maskGC,
8813 0, 0, squareSize, squareSize);
8815 /* Take a copy of the piece */
8820 XSetFunction(xDisplay, bufGC, GXcopy);
8821 XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % (int)BlackPawn],
8823 0, 0, squareSize, squareSize, 0, 0);
8825 /* XOR the background (light) over the piece */
8826 XSetFunction(xDisplay, bufGC, GXxor);
8828 XCopyArea(xDisplay, xpmLightSquare, buf, bufGC,
8829 0, 0, squareSize, squareSize, 0, 0);
8831 XSetForeground(xDisplay, bufGC, lightSquareColor);
8832 XFillRectangle(xDisplay, buf, bufGC, 0, 0, squareSize, squareSize);
8835 /* We now have an inverted piece image with the background
8836 erased. Construct mask by just selecting all the non-zero
8837 pixels - no need to reconstruct the original image. */
8838 XSetFunction(xDisplay, maskGC, GXor);
8840 /* Might be quicker to download an XImage and create bitmap
8841 data from it rather than this N copies per piece, but it
8842 only takes a fraction of a second and there is a much
8843 longer delay for loading the pieces. */
8844 for (n = 0; n < pieceDepth; n ++) {
8845 XCopyPlane(xDisplay, buf, xpmMask[piece], maskGC,
8846 0, 0, squareSize, squareSize,
8852 XFreePixmap(xDisplay, buf);
8853 XFreeGC(xDisplay, bufGC);
8854 XFreeGC(xDisplay, maskGC);
8858 InitAnimState (anim, info)
8860 XWindowAttributes * info;
8865 /* Each buffer is square size, same depth as window */
8866 anim->saveBuf = XCreatePixmap(xDisplay, xBoardWindow,
8867 squareSize, squareSize, info->depth);
8868 anim->newBuf = XCreatePixmap(xDisplay, xBoardWindow,
8869 squareSize, squareSize, info->depth);
8871 /* Create a plain GC for blitting */
8872 mask = GCForeground | GCBackground | GCFunction |
8873 GCPlaneMask | GCGraphicsExposures;
8874 values.foreground = XBlackPixel(xDisplay, xScreen);
8875 values.background = XWhitePixel(xDisplay, xScreen);
8876 values.function = GXcopy;
8877 values.plane_mask = AllPlanes;
8878 values.graphics_exposures = False;
8879 anim->blitGC = XCreateGC(xDisplay, xBoardWindow, mask, &values);
8881 /* Piece will be copied from an existing context at
8882 the start of each new animation/drag. */
8883 anim->pieceGC = XCreateGC(xDisplay, xBoardWindow, 0, &values);
8885 /* Outline will be a read-only copy of an existing */
8886 anim->outlineGC = None;
8892 static VariantClass old = (VariantClass) -1; // [HGM] pieces: redo every time variant changes
8893 XWindowAttributes info;
8895 if (xpmDone && gameInfo.variant == old) return;
8896 if(xpmDone) old = gameInfo.variant; // first time pieces might not be created yet
8897 XGetWindowAttributes(xDisplay, xBoardWindow, &info);
8899 InitAnimState(&game, &info);
8900 InitAnimState(&player, &info);
8902 /* For XPM pieces, we need bitmaps to use as masks. */
8904 CreateAnimMasks(info.depth);
8910 static Boolean frameWaiting;
8912 static RETSIGTYPE FrameAlarm (sig)
8915 frameWaiting = False;
8916 /* In case System-V style signals. Needed?? */
8917 signal(SIGALRM, FrameAlarm);
8924 struct itimerval delay;
8926 XSync(xDisplay, False);
8929 frameWaiting = True;
8930 signal(SIGALRM, FrameAlarm);
8931 delay.it_interval.tv_sec =
8932 delay.it_value.tv_sec = time / 1000;
8933 delay.it_interval.tv_usec =
8934 delay.it_value.tv_usec = (time % 1000) * 1000;
8935 setitimer(ITIMER_REAL, &delay, NULL);
8936 while (frameWaiting) pause();
8937 delay.it_interval.tv_sec = delay.it_value.tv_sec = 0;
8938 delay.it_interval.tv_usec = delay.it_value.tv_usec = 0;
8939 setitimer(ITIMER_REAL, &delay, NULL);
8949 XSync(xDisplay, False);
8951 usleep(time * 1000);
8956 /* Convert board position to corner of screen rect and color */
8959 ScreenSquare(column, row, pt, color)
8960 int column; int row; XPoint * pt; int * color;
8963 pt->x = lineGap + ((BOARD_WIDTH-1)-column) * (squareSize + lineGap);
8964 pt->y = lineGap + row * (squareSize + lineGap);
8966 pt->x = lineGap + column * (squareSize + lineGap);
8967 pt->y = lineGap + ((BOARD_HEIGHT-1)-row) * (squareSize + lineGap);
8969 *color = SquareColor(row, column);
8972 /* Convert window coords to square */
8975 BoardSquare(x, y, column, row)
8976 int x; int y; int * column; int * row;
8978 *column = EventToSquare(x, BOARD_WIDTH);
8979 if (flipView && *column >= 0)
8980 *column = BOARD_WIDTH - 1 - *column;
8981 *row = EventToSquare(y, BOARD_HEIGHT);
8982 if (!flipView && *row >= 0)
8983 *row = BOARD_HEIGHT - 1 - *row;
8988 #undef Max /* just in case */
8990 #define Max(a, b) ((a) > (b) ? (a) : (b))
8991 #define Min(a, b) ((a) < (b) ? (a) : (b))
8994 SetRect(rect, x, y, width, height)
8995 XRectangle * rect; int x; int y; int width; int height;
8999 rect->width = width;
9000 rect->height = height;
9003 /* Test if two frames overlap. If they do, return
9004 intersection rect within old and location of
9005 that rect within new. */
9008 Intersect(old, new, size, area, pt)
9009 XPoint * old; XPoint * new;
9010 int size; XRectangle * area; XPoint * pt;
9012 if (old->x > new->x + size || new->x > old->x + size ||
9013 old->y > new->y + size || new->y > old->y + size) {
9016 SetRect(area, Max(new->x - old->x, 0), Max(new->y - old->y, 0),
9017 size - abs(old->x - new->x), size - abs(old->y - new->y));
9018 pt->x = Max(old->x - new->x, 0);
9019 pt->y = Max(old->y - new->y, 0);
9024 /* For two overlapping frames, return the rect(s)
9025 in the old that do not intersect with the new. */
9028 CalcUpdateRects(old, new, size, update, nUpdates)
9029 XPoint * old; XPoint * new; int size;
9030 XRectangle update[]; int * nUpdates;
9034 /* If old = new (shouldn't happen) then nothing to draw */
9035 if (old->x == new->x && old->y == new->y) {
9039 /* Work out what bits overlap. Since we know the rects
9040 are the same size we don't need a full intersect calc. */
9042 /* Top or bottom edge? */
9043 if (new->y > old->y) {
9044 SetRect(&(update[count]), old->x, old->y, size, new->y - old->y);
9046 } else if (old->y > new->y) {
9047 SetRect(&(update[count]), old->x, old->y + size - (old->y - new->y),
9048 size, old->y - new->y);
9051 /* Left or right edge - don't overlap any update calculated above. */
9052 if (new->x > old->x) {
9053 SetRect(&(update[count]), old->x, Max(new->y, old->y),
9054 new->x - old->x, size - abs(new->y - old->y));
9056 } else if (old->x > new->x) {
9057 SetRect(&(update[count]), new->x + size, Max(new->y, old->y),
9058 old->x - new->x, size - abs(new->y - old->y));
9065 /* Generate a series of frame coords from start->mid->finish.
9066 The movement rate doubles until the half way point is
9067 reached, then halves back down to the final destination,
9068 which gives a nice slow in/out effect. The algorithmn
9069 may seem to generate too many intermediates for short
9070 moves, but remember that the purpose is to attract the
9071 viewers attention to the piece about to be moved and
9072 then to where it ends up. Too few frames would be less
9076 Tween(start, mid, finish, factor, frames, nFrames)
9077 XPoint * start; XPoint * mid;
9078 XPoint * finish; int factor;
9079 XPoint frames[]; int * nFrames;
9081 int fraction, n, count;
9085 /* Slow in, stepping 1/16th, then 1/8th, ... */
9087 for (n = 0; n < factor; n++)
9089 for (n = 0; n < factor; n++) {
9090 frames[count].x = start->x + (mid->x - start->x) / fraction;
9091 frames[count].y = start->y + (mid->y - start->y) / fraction;
9093 fraction = fraction / 2;
9097 frames[count] = *mid;
9100 /* Slow out, stepping 1/2, then 1/4, ... */
9102 for (n = 0; n < factor; n++) {
9103 frames[count].x = finish->x - (finish->x - mid->x) / fraction;
9104 frames[count].y = finish->y - (finish->y - mid->y) / fraction;
9106 fraction = fraction * 2;
9111 /* Draw a piece on the screen without disturbing what's there */
9114 SelectGCMask(piece, clip, outline, mask)
9115 ChessSquare piece; GC * clip; GC * outline; Pixmap * mask;
9119 /* Bitmap for piece being moved. */
9120 if (appData.monoMode) {
9121 *mask = *pieceToSolid(piece);
9122 } else if (useImages) {
9124 *mask = xpmMask[piece];
9126 *mask = ximMaskPm[piece];
9129 *mask = *pieceToSolid(piece);
9132 /* GC for piece being moved. Square color doesn't matter, but
9133 since it gets modified we make a copy of the original. */
9135 if (appData.monoMode)
9140 if (appData.monoMode)
9145 XCopyGC(xDisplay, source, 0xFFFFFFFF, *clip);
9147 /* Outline only used in mono mode and is not modified */
9149 *outline = bwPieceGC;
9151 *outline = wbPieceGC;
9155 OverlayPiece(piece, clip, outline, dest)
9156 ChessSquare piece; GC clip; GC outline; Drawable dest;
9161 /* Draw solid rectangle which will be clipped to shape of piece */
9162 XFillRectangle(xDisplay, dest, clip,
9163 0, 0, squareSize, squareSize);
9164 if (appData.monoMode)
9165 /* Also draw outline in contrasting color for black
9166 on black / white on white cases */
9167 XCopyPlane(xDisplay, *pieceToOutline(piece), dest, outline,
9168 0, 0, squareSize, squareSize, 0, 0, 1);
9170 /* Copy the piece */
9175 XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
9177 0, 0, squareSize, squareSize,
9182 /* Animate the movement of a single piece */
9185 BeginAnimation(anim, piece, startColor, start)
9193 /* The old buffer is initialised with the start square (empty) */
9194 BlankSquare(0, 0, startColor, EmptySquare, anim->saveBuf);
9195 anim->prevFrame = *start;
9197 /* The piece will be drawn using its own bitmap as a matte */
9198 SelectGCMask(piece, &anim->pieceGC, &anim->outlineGC, &mask);
9199 XSetClipMask(xDisplay, anim->pieceGC, mask);
9203 AnimationFrame(anim, frame, piece)
9208 XRectangle updates[4];
9213 /* Save what we are about to draw into the new buffer */
9214 XCopyArea(xDisplay, xBoardWindow, anim->newBuf, anim->blitGC,
9215 frame->x, frame->y, squareSize, squareSize,
9218 /* Erase bits of the previous frame */
9219 if (Intersect(&anim->prevFrame, frame, squareSize, &overlap, &pt)) {
9220 /* Where the new frame overlapped the previous,
9221 the contents in newBuf are wrong. */
9222 XCopyArea(xDisplay, anim->saveBuf, anim->newBuf, anim->blitGC,
9223 overlap.x, overlap.y,
9224 overlap.width, overlap.height,
9226 /* Repaint the areas in the old that don't overlap new */
9227 CalcUpdateRects(&anim->prevFrame, frame, squareSize, updates, &count);
9228 for (i = 0; i < count; i++)
9229 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9230 updates[i].x - anim->prevFrame.x,
9231 updates[i].y - anim->prevFrame.y,
9232 updates[i].width, updates[i].height,
9233 updates[i].x, updates[i].y);
9235 /* Easy when no overlap */
9236 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9237 0, 0, squareSize, squareSize,
9238 anim->prevFrame.x, anim->prevFrame.y);
9241 /* Save this frame for next time round */
9242 XCopyArea(xDisplay, anim->newBuf, anim->saveBuf, anim->blitGC,
9243 0, 0, squareSize, squareSize,
9245 anim->prevFrame = *frame;
9247 /* Draw piece over original screen contents, not current,
9248 and copy entire rect. Wipes out overlapping piece images. */
9249 OverlayPiece(piece, anim->pieceGC, anim->outlineGC, anim->newBuf);
9250 XCopyArea(xDisplay, anim->newBuf, xBoardWindow, anim->blitGC,
9251 0, 0, squareSize, squareSize,
9252 frame->x, frame->y);
9256 EndAnimation (anim, finish)
9260 XRectangle updates[4];
9265 /* The main code will redraw the final square, so we
9266 only need to erase the bits that don't overlap. */
9267 if (Intersect(&anim->prevFrame, finish, squareSize, &overlap, &pt)) {
9268 CalcUpdateRects(&anim->prevFrame, finish, squareSize, updates, &count);
9269 for (i = 0; i < count; i++)
9270 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9271 updates[i].x - anim->prevFrame.x,
9272 updates[i].y - anim->prevFrame.y,
9273 updates[i].width, updates[i].height,
9274 updates[i].x, updates[i].y);
9276 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9277 0, 0, squareSize, squareSize,
9278 anim->prevFrame.x, anim->prevFrame.y);
9283 FrameSequence(anim, piece, startColor, start, finish, frames, nFrames)
9285 ChessSquare piece; int startColor;
9286 XPoint * start; XPoint * finish;
9287 XPoint frames[]; int nFrames;
9291 BeginAnimation(anim, piece, startColor, start);
9292 for (n = 0; n < nFrames; n++) {
9293 AnimationFrame(anim, &(frames[n]), piece);
9294 FrameDelay(appData.animSpeed);
9296 EndAnimation(anim, finish);
9299 /* Main control logic for deciding what to animate and how */
9302 AnimateMove(board, fromX, fromY, toX, toY)
9311 XPoint start, finish, mid;
9312 XPoint frames[kFactor * 2 + 1];
9313 int nFrames, startColor, endColor;
9315 /* Are we animating? */
9316 if (!appData.animate || appData.blindfold)
9319 if(board[toY][toX] == WhiteRook && board[fromY][fromX] == WhiteKing ||
9320 board[toY][toX] == BlackRook && board[fromY][fromX] == BlackKing)
9321 return; // [HGM] FRC: no animtion of FRC castlings, as to-square is not true to-square
9323 if (fromY < 0 || fromX < 0 || toX < 0 || toY < 0) return;
9324 piece = board[fromY][fromX];
9325 if (piece >= EmptySquare) return;
9330 hop = (piece == WhiteKnight || piece == BlackKnight);
9333 if (appData.debugMode) {
9334 fprintf(debugFP, hop ? _("AnimateMove: piece %d hops from %d,%d to %d,%d \n") :
9335 _("AnimateMove: piece %d slides from %d,%d to %d,%d \n"),
9336 piece, fromX, fromY, toX, toY); }
9338 ScreenSquare(fromX, fromY, &start, &startColor);
9339 ScreenSquare(toX, toY, &finish, &endColor);
9342 /* Knight: make diagonal movement then straight */
9343 if (abs(toY - fromY) < abs(toX - fromX)) {
9344 mid.x = start.x + (finish.x - start.x) / 2;
9348 mid.y = start.y + (finish.y - start.y) / 2;
9351 mid.x = start.x + (finish.x - start.x) / 2;
9352 mid.y = start.y + (finish.y - start.y) / 2;
9355 /* Don't use as many frames for very short moves */
9356 if (abs(toY - fromY) + abs(toX - fromX) <= 2)
9357 Tween(&start, &mid, &finish, kFactor - 1, frames, &nFrames);
9359 Tween(&start, &mid, &finish, kFactor, frames, &nFrames);
9360 FrameSequence(&game, piece, startColor, &start, &finish, frames, nFrames);
9362 /* Be sure end square is redrawn */
9363 damage[toY][toX] = True;
9367 DragPieceBegin(x, y)
9370 int boardX, boardY, color;
9373 /* Are we animating? */
9374 if (!appData.animateDragging || appData.blindfold)
9377 /* Figure out which square we start in and the
9378 mouse position relative to top left corner. */
9379 BoardSquare(x, y, &boardX, &boardY);
9380 player.startBoardX = boardX;
9381 player.startBoardY = boardY;
9382 ScreenSquare(boardX, boardY, &corner, &color);
9383 player.startSquare = corner;
9384 player.startColor = color;
9385 /* As soon as we start dragging, the piece will jump slightly to
9386 be centered over the mouse pointer. */
9387 player.mouseDelta.x = squareSize/2;
9388 player.mouseDelta.y = squareSize/2;
9389 /* Initialise animation */
9390 player.dragPiece = PieceForSquare(boardX, boardY);
9392 if (player.dragPiece >= 0 && player.dragPiece < EmptySquare) {
9393 player.dragActive = True;
9394 BeginAnimation(&player, player.dragPiece, color, &corner);
9395 /* Mark this square as needing to be redrawn. Note that
9396 we don't remove the piece though, since logically (ie
9397 as seen by opponent) the move hasn't been made yet. */
9398 if(boardX == BOARD_RGHT+1 && PieceForSquare(boardX-1, boardY) > 1 ||
9399 boardX == BOARD_LEFT-2 && PieceForSquare(boardX+1, boardY) > 1)
9400 XCopyArea(xDisplay, xBoardWindow, player.saveBuf, player.blitGC,
9401 corner.x, corner.y, squareSize, squareSize,
9402 0, 0); // [HGM] zh: unstack in stead of grab
9403 damage[boardY][boardX] = True;
9405 player.dragActive = False;
9415 /* Are we animating? */
9416 if (!appData.animateDragging || appData.blindfold)
9420 if (! player.dragActive)
9422 /* Move piece, maintaining same relative position
9423 of mouse within square */
9424 corner.x = x - player.mouseDelta.x;
9425 corner.y = y - player.mouseDelta.y;
9426 AnimationFrame(&player, &corner, player.dragPiece);
9428 if (appData.highlightDragging) {
9430 BoardSquare(x, y, &boardX, &boardY);
9431 SetHighlights(fromX, fromY, boardX, boardY);
9440 int boardX, boardY, color;
9443 /* Are we animating? */
9444 if (!appData.animateDragging || appData.blindfold)
9448 if (! player.dragActive)
9450 /* Last frame in sequence is square piece is
9451 placed on, which may not match mouse exactly. */
9452 BoardSquare(x, y, &boardX, &boardY);
9453 ScreenSquare(boardX, boardY, &corner, &color);
9454 EndAnimation(&player, &corner);
9456 /* Be sure end square is redrawn */
9457 damage[boardY][boardX] = True;
9459 /* This prevents weird things happening with fast successive
9460 clicks which on my Sun at least can cause motion events
9461 without corresponding press/release. */
9462 player.dragActive = False;
9465 /* Handle expose event while piece being dragged */
9470 if (!player.dragActive || appData.blindfold)
9473 /* What we're doing: logically, the move hasn't been made yet,
9474 so the piece is still in it's original square. But visually
9475 it's being dragged around the board. So we erase the square
9476 that the piece is on and draw it at the last known drag point. */
9477 BlankSquare(player.startSquare.x, player.startSquare.y,
9478 player.startColor, EmptySquare, xBoardWindow);
9479 AnimationFrame(&player, &player.prevFrame, player.dragPiece);
9480 damage[player.startBoardY][player.startBoardX] = TRUE;
9484 SetProgramStats( FrontEndProgramStats * stats )
9487 // [HGM] done, but perhaps backend should call this directly?
9488 EngineOutputUpdate( stats );