2 * xboard.c -- X front end for XBoard
4 * Copyright 1991 by Digital Equipment Corporation, Maynard,
7 * Enhancements Copyright 1992-2001, 2002, 2003, 2004, 2005, 2006,
8 * 2007, 2008, 2009 Free Software Foundation, Inc.
10 * The following terms apply to Digital Equipment Corporation's copyright
12 * ------------------------------------------------------------------------
15 * Permission to use, copy, modify, and distribute this software and its
16 * documentation for any purpose and without fee is hereby granted,
17 * provided that the above copyright notice appear in all copies and that
18 * both that copyright notice and this permission notice appear in
19 * supporting documentation, and that the name of Digital not be
20 * used in advertising or publicity pertaining to distribution of the
21 * software without specific, written prior permission.
23 * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
24 * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
25 * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
26 * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
27 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
28 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
30 * ------------------------------------------------------------------------
32 * The following terms apply to the enhanced version of XBoard
33 * distributed by the Free Software Foundation:
34 * ------------------------------------------------------------------------
36 * GNU XBoard is free software: you can redistribute it and/or modify
37 * it under the terms of the GNU General Public License as published by
38 * the Free Software Foundation, either version 3 of the License, or (at
39 * your option) any later version.
41 * GNU XBoard is distributed in the hope that it will be useful, but
42 * WITHOUT ANY WARRANTY; without even the implied warranty of
43 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
44 * General Public License for more details.
46 * You should have received a copy of the GNU General Public License
47 * along with this program. If not, see http://www.gnu.org/licenses/. *
49 *------------------------------------------------------------------------
50 ** See the file ChangeLog for a revision history. */
58 #include <sys/types.h>
63 # if HAVE_SYS_SOCKET_H
64 # include <sys/socket.h>
65 # include <netinet/in.h>
67 # else /* not HAVE_SYS_SOCKET_H */
68 # if HAVE_LAN_SOCKET_H
69 # include <lan/socket.h>
71 # include <lan/netdb.h>
72 # else /* not HAVE_LAN_SOCKET_H */
73 # define OMIT_SOCKETS 1
74 # endif /* not HAVE_LAN_SOCKET_H */
75 # endif /* not HAVE_SYS_SOCKET_H */
76 #endif /* !OMIT_SOCKETS */
81 #else /* not STDC_HEADERS */
82 extern char *getenv();
85 # else /* not HAVE_STRING_H */
87 # endif /* not HAVE_STRING_H */
88 #endif /* not STDC_HEADERS */
91 # include <sys/fcntl.h>
92 #else /* not HAVE_SYS_FCNTL_H */
95 # endif /* HAVE_FCNTL_H */
96 #endif /* not HAVE_SYS_FCNTL_H */
98 #if HAVE_SYS_SYSTEMINFO_H
99 # include <sys/systeminfo.h>
100 #endif /* HAVE_SYS_SYSTEMINFO_H */
102 #if TIME_WITH_SYS_TIME
103 # include <sys/time.h>
107 # include <sys/time.h>
118 # include <sys/wait.h>
123 # define NAMLEN(dirent) strlen((dirent)->d_name)
124 # define HAVE_DIR_STRUCT
126 # define dirent direct
127 # define NAMLEN(dirent) (dirent)->d_namlen
129 # include <sys/ndir.h>
130 # define HAVE_DIR_STRUCT
133 # include <sys/dir.h>
134 # define HAVE_DIR_STRUCT
138 # define HAVE_DIR_STRUCT
142 #include <X11/Intrinsic.h>
143 #include <X11/StringDefs.h>
144 #include <X11/Shell.h>
145 #include <X11/cursorfont.h>
146 #include <X11/Xatom.h>
148 #include <X11/Xaw3d/Dialog.h>
149 #include <X11/Xaw3d/Form.h>
150 #include <X11/Xaw3d/List.h>
151 #include <X11/Xaw3d/Label.h>
152 #include <X11/Xaw3d/SimpleMenu.h>
153 #include <X11/Xaw3d/SmeBSB.h>
154 #include <X11/Xaw3d/SmeLine.h>
155 #include <X11/Xaw3d/Box.h>
156 #include <X11/Xaw3d/MenuButton.h>
157 #include <X11/Xaw3d/Text.h>
158 #include <X11/Xaw3d/AsciiText.h>
160 #include <X11/Xaw/Dialog.h>
161 #include <X11/Xaw/Form.h>
162 #include <X11/Xaw/List.h>
163 #include <X11/Xaw/Label.h>
164 #include <X11/Xaw/SimpleMenu.h>
165 #include <X11/Xaw/SmeBSB.h>
166 #include <X11/Xaw/SmeLine.h>
167 #include <X11/Xaw/Box.h>
168 #include <X11/Xaw/MenuButton.h>
169 #include <X11/Xaw/Text.h>
170 #include <X11/Xaw/AsciiText.h>
173 // [HGM] bitmaps: put before incuding the bitmaps / pixmaps, to know how many piece types there are.
178 #include "pixmaps/pixmaps.h"
179 #define IMAGE_EXT "xpm"
181 #define IMAGE_EXT "xim"
182 #include "bitmaps/bitmaps.h"
185 #include "bitmaps/icon_white.bm"
186 #include "bitmaps/icon_black.bm"
187 #include "bitmaps/checkmark.bm"
189 #include "frontend.h"
194 #include "xgamelist.h"
195 #include "xhistory.h"
196 #include "xedittags.h"
199 // must be moved to xengineoutput.h
201 void EngineOutputProc P((Widget w, XEvent *event,
202 String *prms, Cardinal *nprms));
204 void EngineOutputPopDown();
211 #define usleep(t) _sleep2(((t)+500)/1000)
215 # define _(s) gettext (s)
216 # define N_(s) gettext_noop (s)
232 int main P((int argc, char **argv));
233 RETSIGTYPE CmailSigHandler P((int sig));
234 RETSIGTYPE IntSigHandler P((int sig));
235 void CreateGCs P((void));
236 void CreateXIMPieces P((void));
237 void CreateXPMPieces P((void));
238 void CreatePieces P((void));
239 void CreatePieceMenus P((void));
240 Widget CreateMenuBar P((Menu *mb));
241 Widget CreateButtonBar P ((MenuItem *mi));
242 char *FindFont P((char *pattern, int targetPxlSize));
243 void PieceMenuPopup P((Widget w, XEvent *event,
244 String *params, Cardinal *num_params));
245 static void PieceMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
246 static void DropMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
247 void ReadBitmap P((Pixmap *pm, String name, unsigned char bits[],
248 u_int wreq, u_int hreq));
249 void CreateGrid P((void));
250 int EventToSquare P((int x, int limit));
251 void DrawSquare P((int row, int column, ChessSquare piece, int do_flash));
252 void EventProc P((Widget widget, caddr_t unused, XEvent *event));
253 void HandleUserMove P((Widget w, XEvent *event,
254 String *prms, Cardinal *nprms));
255 void AnimateUserMove P((Widget w, XEvent * event,
256 String * params, Cardinal * nParams));
257 void WhiteClock P((Widget w, XEvent *event,
258 String *prms, Cardinal *nprms));
259 void BlackClock P((Widget w, XEvent *event,
260 String *prms, Cardinal *nprms));
261 void DrawPositionProc P((Widget w, XEvent *event,
262 String *prms, Cardinal *nprms));
263 void XDrawPosition P((Widget w, /*Boolean*/int repaint,
265 void CommentPopUp P((char *title, char *label));
266 void CommentPopDown P((void));
267 void CommentCallback P((Widget w, XtPointer client_data,
268 XtPointer call_data));
269 void ICSInputBoxPopUp P((void));
270 void ICSInputBoxPopDown P((void));
271 void FileNamePopUp P((char *label, char *def,
272 FileProc proc, char *openMode));
273 void FileNamePopDown P((void));
274 void FileNameCallback P((Widget w, XtPointer client_data,
275 XtPointer call_data));
276 void FileNameAction P((Widget w, XEvent *event,
277 String *prms, Cardinal *nprms));
278 void AskQuestionReplyAction P((Widget w, XEvent *event,
279 String *prms, Cardinal *nprms));
280 void AskQuestionProc P((Widget w, XEvent *event,
281 String *prms, Cardinal *nprms));
282 void AskQuestionPopDown P((void));
283 void PromotionPopUp P((void));
284 void PromotionPopDown P((void));
285 void PromotionCallback P((Widget w, XtPointer client_data,
286 XtPointer call_data));
287 void EditCommentPopDown P((void));
288 void EditCommentCallback P((Widget w, XtPointer client_data,
289 XtPointer call_data));
290 void SelectCommand P((Widget w, XtPointer client_data, XtPointer call_data));
291 void ResetProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
292 void LoadGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
293 void LoadNextGameProc P((Widget w, XEvent *event, String *prms,
295 void LoadPrevGameProc P((Widget w, XEvent *event, String *prms,
297 void ReloadGameProc P((Widget w, XEvent *event, String *prms,
299 void LoadPositionProc P((Widget w, XEvent *event,
300 String *prms, Cardinal *nprms));
301 void LoadNextPositionProc P((Widget w, XEvent *event, String *prms,
303 void LoadPrevPositionProc P((Widget w, XEvent *event, String *prms,
305 void ReloadPositionProc P((Widget w, XEvent *event, String *prms,
307 void CopyPositionProc P((Widget w, XEvent *event, String *prms,
309 void PastePositionProc P((Widget w, XEvent *event, String *prms,
311 void CopyGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
312 void PasteGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
313 void SaveGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
314 void SavePositionProc P((Widget w, XEvent *event,
315 String *prms, Cardinal *nprms));
316 void MailMoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
317 void ReloadCmailMsgProc P((Widget w, XEvent *event, String *prms,
319 void QuitProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
320 void PauseProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
321 void MachineBlackProc P((Widget w, XEvent *event, String *prms,
323 void MachineWhiteProc P((Widget w, XEvent *event,
324 String *prms, Cardinal *nprms));
325 void AnalyzeModeProc P((Widget w, XEvent *event,
326 String *prms, Cardinal *nprms));
327 void AnalyzeFileProc P((Widget w, XEvent *event,
328 String *prms, Cardinal *nprms));
329 void TwoMachinesProc P((Widget w, XEvent *event, String *prms,
331 void IcsClientProc P((Widget w, XEvent *event, String *prms,
333 void EditGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
334 void EditPositionProc P((Widget w, XEvent *event,
335 String *prms, Cardinal *nprms));
336 void TrainingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
337 void EditCommentProc P((Widget w, XEvent *event,
338 String *prms, Cardinal *nprms));
339 void IcsInputBoxProc P((Widget w, XEvent *event,
340 String *prms, Cardinal *nprms));
341 void AcceptProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
342 void DeclineProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
343 void RematchProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
344 void CallFlagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
345 void DrawProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
346 void AbortProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
347 void AdjournProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
348 void ResignProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
349 void AdjuWhiteProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
350 void AdjuBlackProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
351 void AdjuDrawProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
352 void EnterKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
353 void StopObservingProc P((Widget w, XEvent *event, String *prms,
355 void StopExaminingProc P((Widget w, XEvent *event, String *prms,
357 void BackwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
358 void ForwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
359 void ToStartProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
360 void ToEndProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
361 void RevertProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
362 void TruncateGameProc P((Widget w, XEvent *event, String *prms,
364 void RetractMoveProc P((Widget w, XEvent *event, String *prms,
366 void MoveNowProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
367 void AlwaysQueenProc P((Widget w, XEvent *event, String *prms,
369 void AnimateDraggingProc P((Widget w, XEvent *event, String *prms,
371 void AnimateMovingProc P((Widget w, XEvent *event, String *prms,
373 void AutocommProc P((Widget w, XEvent *event, String *prms,
375 void AutoflagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
376 void AutoflipProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
377 void AutobsProc P((Widget w, XEvent *event, String *prms,
379 void AutoraiseProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
380 void AutosaveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
381 void BlindfoldProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
382 void FlashMovesProc P((Widget w, XEvent *event, String *prms,
384 void FlipViewProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
385 void GetMoveListProc P((Widget w, XEvent *event, String *prms,
387 void HighlightDraggingProc P((Widget w, XEvent *event, String *prms,
389 void HighlightLastMoveProc P((Widget w, XEvent *event, String *prms,
391 void MoveSoundProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
392 void IcsAlarmProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
393 void OldSaveStyleProc P((Widget w, XEvent *event, String *prms,
395 void PeriodicUpdatesProc P((Widget w, XEvent *event, String *prms,
397 void PonderNextMoveProc P((Widget w, XEvent *event, String *prms,
399 void PopupMoveErrorsProc P((Widget w, XEvent *event, String *prms,
401 void PopupExitMessageProc P((Widget w, XEvent *event, String *prms,
403 void PremoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
404 void QuietPlayProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
405 void ShowCoordsProc P((Widget w, XEvent *event, String *prms,
407 void ShowThinkingProc P((Widget w, XEvent *event, String *prms,
409 void HideThinkingProc P((Widget w, XEvent *event, String *prms,
411 void TestLegalityProc P((Widget w, XEvent *event, String *prms,
413 void InfoProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
414 void ManProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
415 void HintProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
416 void BookProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
417 void AboutGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
418 void AboutProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
419 void DebugProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
420 void NothingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
421 void Iconify P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
422 void DisplayMove P((int moveNumber));
423 void DisplayTitle P((char *title));
424 void ICSInitScript P((void));
425 int LoadGamePopUp P((FILE *f, int gameNumber, char *title));
426 void ErrorPopUp P((char *title, char *text, int modal));
427 void ErrorPopDown P((void));
428 static char *ExpandPathName P((char *path));
429 static void CreateAnimVars P((void));
430 static void DragPieceBegin P((int x, int y));
431 static void DragPieceMove P((int x, int y));
432 static void DragPieceEnd P((int x, int y));
433 static void DrawDragPiece P((void));
434 char *ModeToWidgetName P((GameMode mode));
435 void EngineOutputUpdate( FrontEndProgramStats * stats );
436 void ShuffleMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
437 void EngineMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
438 void UciMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
439 void TimeControlProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
440 void NewVariantProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
441 void FirstSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
442 void SecondSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
443 void ShufflePopDown P(());
444 void EnginePopDown P(());
445 void UciPopDown P(());
446 void TimeControlPopDown P(());
447 void NewVariantPopDown P(());
448 void SettingsPopDown P(());
450 * XBoard depends on Xt R4 or higher
452 int xtVersion = XtSpecificationRelease;
457 Pixel lightSquareColor, darkSquareColor, whitePieceColor, blackPieceColor,
458 jailSquareColor, highlightSquareColor, premoveHighlightColor;
459 Pixel lowTimeWarningColor;
460 GC lightSquareGC, darkSquareGC, jailSquareGC, lineGC, wdPieceGC, wlPieceGC,
461 bdPieceGC, blPieceGC, wbPieceGC, bwPieceGC, coordGC, highlineGC,
462 wjPieceGC, bjPieceGC, prelineGC, countGC;
463 Pixmap iconPixmap, wIconPixmap, bIconPixmap, xMarkPixmap;
464 Widget shellWidget, layoutWidget, formWidget, boardWidget, messageWidget,
465 whiteTimerWidget, blackTimerWidget, titleWidget, widgetList[16],
466 commentShell, promotionShell, whitePieceMenu, blackPieceMenu, dropMenu,
467 menuBarWidget, buttonBarWidget, editShell, errorShell, analysisShell,
468 ICSInputShell, fileNameShell, askQuestionShell;
469 XSegment gridSegments[(BOARD_SIZE + 1) * 2];
470 XSegment jailGridSegments[(BOARD_SIZE + 3) * 2];
471 Font clockFontID, coordFontID, countFontID;
472 XFontStruct *clockFontStruct, *coordFontStruct, *countFontStruct;
473 XtAppContext appContext;
475 char *oldICSInteractionTitle;
479 char installDir[] = "."; // [HGM] UCI: needed for UCI; probably needs run-time initializtion
481 Position commentX = -1, commentY = -1;
482 Dimension commentW, commentH;
484 int squareSize, smallLayout = 0, tinyLayout = 0,
485 marginW, marginH, // [HGM] for run-time resizing
486 fromX = -1, fromY = -1, toX, toY, commentUp = False, analysisUp = False,
487 ICSInputBoxUp = False, askQuestionUp = False,
488 filenameUp = False, promotionUp = False, pmFromX = -1, pmFromY = -1,
489 editUp = False, errorUp = False, errorExitStatus = -1, lineGap;
490 Pixel timerForegroundPixel, timerBackgroundPixel;
491 Pixel buttonForegroundPixel, buttonBackgroundPixel;
492 char *chessDir, *programName, *programVersion,
493 *gameCopyFilename, *gamePasteFilename;
497 Pixmap pieceBitmap[2][(int)BlackPawn];
498 Pixmap pieceBitmap2[2][(int)BlackPawn+4]; /* [HGM] pieces */
499 Pixmap xpmPieceBitmap[4][(int)BlackPawn]; /* LL, LD, DL, DD actually used*/
500 Pixmap xpmPieceBitmap2[4][(int)BlackPawn+4]; /* LL, LD, DL, DD set to select from */
501 Pixmap xpmLightSquare, xpmDarkSquare, xpmJailSquare;
502 int useImages, useImageSqs;
503 XImage *ximPieceBitmap[4][(int)BlackPawn+4]; /* LL, LD, DL, DD */
504 Pixmap ximMaskPm[(int)BlackPawn]; /* clipmasks, used for XIM pieces */
505 Pixmap ximMaskPm2[(int)BlackPawn+4]; /* clipmasks, used for XIM pieces */
506 XImage *ximLightSquare, *ximDarkSquare;
509 #define pieceToSolid(piece) &pieceBitmap[SOLID][(piece) % (int)BlackPawn]
510 #define pieceToOutline(piece) &pieceBitmap[OUTLINE][(piece) % (int)BlackPawn]
512 #define White(piece) ((int)(piece) < (int)BlackPawn)
514 /* Variables for doing smooth animation. This whole thing
515 would be much easier if the board was double-buffered,
516 but that would require a fairly major rewrite. */
521 GC blitGC, pieceGC, outlineGC;
522 XPoint startSquare, prevFrame, mouseDelta;
526 int startBoardX, startBoardY;
529 /* There can be two pieces being animated at once: a player
530 can begin dragging a piece before the remote opponent has moved. */
532 static AnimState game, player;
534 /* Bitmaps for use as masks when drawing XPM pieces.
535 Need one for each black and white piece. */
536 static Pixmap xpmMask[BlackKing + 1];
538 /* This magic number is the number of intermediate frames used
539 in each half of the animation. For short moves it's reduced
540 by 1. The total number of frames will be factor * 2 + 1. */
543 SizeDefaults sizeDefaults[] = SIZE_DEFAULTS;
545 MenuItem fileMenu[] = {
546 {N_("New Game"), ResetProc},
547 {N_("New Shuffle Game ..."), ShuffleMenuProc},
548 {N_("New Variant ..."), NewVariantProc}, // [HGM] variant: not functional yet
549 {"----", NothingProc},
550 {N_("Load Game"), LoadGameProc},
551 {N_("Load Next Game"), LoadNextGameProc},
552 {N_("Load Previous Game"), LoadPrevGameProc},
553 {N_("Reload Same Game"), ReloadGameProc},
554 {N_("Save Game"), SaveGameProc},
555 {"----", NothingProc},
556 {N_("Copy Game"), CopyGameProc},
557 {N_("Paste Game"), PasteGameProc},
558 {"----", NothingProc},
559 {N_("Load Position"), LoadPositionProc},
560 {N_("Load Next Position"), LoadNextPositionProc},
561 {N_("Load Previous Position"), LoadPrevPositionProc},
562 {N_("Reload Same Position"), ReloadPositionProc},
563 {N_("Save Position"), SavePositionProc},
564 {"----", NothingProc},
565 {N_("Copy Position"), CopyPositionProc},
566 {N_("Paste Position"), PastePositionProc},
567 {"----", NothingProc},
568 {N_("Mail Move"), MailMoveProc},
569 {N_("Reload CMail Message"), ReloadCmailMsgProc},
570 {"----", NothingProc},
571 {N_("Exit"), QuitProc},
575 MenuItem modeMenu[] = {
576 {N_("Machine White"), MachineWhiteProc},
577 {N_("Machine Black"), MachineBlackProc},
578 {N_("Two Machines"), TwoMachinesProc},
579 {N_("Analysis Mode"), AnalyzeModeProc},
580 {N_("Analyze File"), AnalyzeFileProc },
581 {N_("ICS Client"), IcsClientProc},
582 {N_("Edit Game"), EditGameProc},
583 {N_("Edit Position"), EditPositionProc},
584 {N_("Training"), TrainingProc},
585 {"----", NothingProc},
586 {N_("Show Engine Output"), EngineOutputProc},
587 {N_("Show Evaluation Graph"), NothingProc}, // [HGM] evalgr: not functional yet
588 {N_("Show Game List"), ShowGameListProc},
589 {"Show Move History", HistoryShowProc}, // [HGM] hist: activate 4.2.7 code
590 {"----", NothingProc},
591 {N_("Edit Tags"), EditTagsProc},
592 {N_("Edit Comment"), EditCommentProc},
593 {N_("ICS Input Box"), IcsInputBoxProc},
594 {N_("Pause"), PauseProc},
598 MenuItem actionMenu[] = {
599 {N_("Accept"), AcceptProc},
600 {N_("Decline"), DeclineProc},
601 {N_("Rematch"), RematchProc},
602 {"----", NothingProc},
603 {N_("Call Flag"), CallFlagProc},
604 {N_("Draw"), DrawProc},
605 {N_("Adjourn"), AdjournProc},
606 {N_("Abort"), AbortProc},
607 {N_("Resign"), ResignProc},
608 {"----", NothingProc},
609 {N_("Stop Observing"), StopObservingProc},
610 {N_("Stop Examining"), StopExaminingProc},
611 {"----", NothingProc},
612 {N_("Adjudicate to White"), AdjuWhiteProc},
613 {N_("Adjudicate to Black"), AdjuBlackProc},
614 {N_("Adjudicate Draw"), AdjuDrawProc},
618 MenuItem stepMenu[] = {
619 {N_("Backward"), BackwardProc},
620 {N_("Forward"), ForwardProc},
621 {N_("Back to Start"), ToStartProc},
622 {N_("Forward to End"), ToEndProc},
623 {N_("Revert"), RevertProc},
624 {N_("Truncate Game"), TruncateGameProc},
625 {"----", NothingProc},
626 {N_("Move Now"), MoveNowProc},
627 {N_("Retract Move"), RetractMoveProc},
631 MenuItem optionsMenu[] = {
632 {N_("Flip View"), FlipViewProc},
633 {"----", NothingProc},
634 {N_("Adjudications ..."), EngineMenuProc},
635 {N_("General Settings ..."), UciMenuProc},
636 {N_("Engine #1 Settings ..."), FirstSettingsProc},
637 {N_("Engine #2 Settings ..."), SecondSettingsProc},
638 {N_("Time Control ..."), TimeControlProc},
639 {"----", NothingProc},
640 {N_("Always Queen"), AlwaysQueenProc},
641 {N_("Animate Dragging"), AnimateDraggingProc},
642 {N_("Animate Moving"), AnimateMovingProc},
643 {N_("Auto Comment"), AutocommProc},
644 {N_("Auto Flag"), AutoflagProc},
645 {N_("Auto Flip View"), AutoflipProc},
646 {N_("Auto Observe"), AutobsProc},
647 {N_("Auto Raise Board"), AutoraiseProc},
648 {N_("Auto Save"), AutosaveProc},
649 {N_("Blindfold"), BlindfoldProc},
650 {N_("Flash Moves"), FlashMovesProc},
651 {N_("Get Move List"), GetMoveListProc},
653 {N_("Highlight Dragging"), HighlightDraggingProc},
655 {N_("Highlight Last Move"), HighlightLastMoveProc},
656 {N_("Move Sound"), MoveSoundProc},
657 {N_("ICS Alarm"), IcsAlarmProc},
658 {N_("Old Save Style"), OldSaveStyleProc},
659 {N_("Periodic Updates"), PeriodicUpdatesProc},
660 {N_("Ponder Next Move"), PonderNextMoveProc},
661 {N_("Popup Exit Message"), PopupExitMessageProc},
662 {N_("Popup Move Errors"), PopupMoveErrorsProc},
663 {N_("Premove"), PremoveProc},
664 {N_("Quiet Play"), QuietPlayProc},
665 {N_("Show Coords"), ShowCoordsProc},
666 {N_("Hide Thinking"), HideThinkingProc},
667 {N_("Test Legality"), TestLegalityProc},
671 MenuItem helpMenu[] = {
672 {N_("Info XBoard"), InfoProc},
673 {N_("Man XBoard"), ManProc},
674 {"----", NothingProc},
675 {N_("Hint"), HintProc},
676 {N_("Book"), BookProc},
677 {"----", NothingProc},
678 {N_("About XBoard"), AboutProc},
683 {N_("File"), fileMenu},
684 {N_("Mode"), modeMenu},
685 {N_("Action"), actionMenu},
686 {N_("Step"), stepMenu},
687 {N_("Options"), optionsMenu},
688 {N_("Help"), helpMenu},
692 #define PAUSE_BUTTON N_("P")
693 MenuItem buttonBar[] = {
696 {PAUSE_BUTTON, PauseProc},
702 #define PIECE_MENU_SIZE 18
703 String pieceMenuStrings[2][PIECE_MENU_SIZE] = {
704 { N_("White"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
705 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
706 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
707 N_("Empty square"), N_("Clear board") },
708 { N_("Black"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
709 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
710 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
711 N_("Empty square"), N_("Clear board") }
713 /* must be in same order as PieceMenuStrings! */
714 ChessSquare pieceMenuTranslation[2][PIECE_MENU_SIZE] = {
715 { WhitePlay, (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
716 WhiteRook, WhiteQueen, WhiteKing, (ChessSquare) 0, WhiteAlfil,
717 WhiteCannon, WhiteAngel, WhiteMarshall, (ChessSquare) 0,
718 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
719 { BlackPlay, (ChessSquare) 0, BlackPawn, BlackKnight, BlackBishop,
720 BlackRook, BlackQueen, BlackKing, (ChessSquare) 0, BlackAlfil,
721 BlackCannon, BlackAngel, BlackMarshall, (ChessSquare) 0,
722 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
725 #define DROP_MENU_SIZE 6
726 String dropMenuStrings[DROP_MENU_SIZE] = {
727 "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"), N_("Queen")
729 /* must be in same order as PieceMenuStrings! */
730 ChessSquare dropMenuTranslation[DROP_MENU_SIZE] = {
731 (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
732 WhiteRook, WhiteQueen
740 DropMenuEnables dmEnables[] = {
758 { XtNborderWidth, 0 },
759 { XtNdefaultDistance, 0 },
763 { XtNborderWidth, 0 },
764 { XtNresizable, (XtArgVal) True },
768 { XtNborderWidth, 0 },
774 { XtNjustify, (XtArgVal) XtJustifyRight },
775 { XtNlabel, (XtArgVal) "..." },
776 { XtNresizable, (XtArgVal) True },
777 { XtNresize, (XtArgVal) False }
780 Arg messageArgs[] = {
781 { XtNjustify, (XtArgVal) XtJustifyLeft },
782 { XtNlabel, (XtArgVal) "..." },
783 { XtNresizable, (XtArgVal) True },
784 { XtNresize, (XtArgVal) False }
788 { XtNborderWidth, 0 },
789 { XtNjustify, (XtArgVal) XtJustifyLeft }
792 XtResource clientResources[] = {
793 { "whitePieceColor", "whitePieceColor", XtRString, sizeof(String),
794 XtOffset(AppDataPtr, whitePieceColor), XtRString,
796 { "blackPieceColor", "blackPieceColor", XtRString, sizeof(String),
797 XtOffset(AppDataPtr, blackPieceColor), XtRString,
799 { "lightSquareColor", "lightSquareColor", XtRString,
800 sizeof(String), XtOffset(AppDataPtr, lightSquareColor),
801 XtRString, LIGHT_SQUARE_COLOR },
802 { "darkSquareColor", "darkSquareColor", XtRString, sizeof(String),
803 XtOffset(AppDataPtr, darkSquareColor), XtRString,
805 { "highlightSquareColor", "highlightSquareColor", XtRString,
806 sizeof(String), XtOffset(AppDataPtr, highlightSquareColor),
807 XtRString, HIGHLIGHT_SQUARE_COLOR },
808 { "premoveHighlightColor", "premoveHighlightColor", XtRString,
809 sizeof(String), XtOffset(AppDataPtr, premoveHighlightColor),
810 XtRString, PREMOVE_HIGHLIGHT_COLOR },
811 { "movesPerSession", "movesPerSession", XtRInt, sizeof(int),
812 XtOffset(AppDataPtr, movesPerSession), XtRImmediate,
813 (XtPointer) MOVES_PER_SESSION },
814 { "timeIncrement", "timeIncrement", XtRInt, sizeof(int),
815 XtOffset(AppDataPtr, timeIncrement), XtRImmediate,
816 (XtPointer) TIME_INCREMENT },
817 { "initString", "initString", XtRString, sizeof(String),
818 XtOffset(AppDataPtr, initString), XtRString, INIT_STRING },
819 { "secondInitString", "secondInitString", XtRString, sizeof(String),
820 XtOffset(AppDataPtr, secondInitString), XtRString, INIT_STRING },
821 { "firstComputerString", "firstComputerString", XtRString,
822 sizeof(String), XtOffset(AppDataPtr, firstComputerString), XtRString,
824 { "secondComputerString", "secondComputerString", XtRString,
825 sizeof(String), XtOffset(AppDataPtr, secondComputerString), XtRString,
827 { "firstChessProgram", "firstChessProgram", XtRString,
828 sizeof(String), XtOffset(AppDataPtr, firstChessProgram),
829 XtRString, FIRST_CHESS_PROGRAM },
830 { "secondChessProgram", "secondChessProgram", XtRString,
831 sizeof(String), XtOffset(AppDataPtr, secondChessProgram),
832 XtRString, SECOND_CHESS_PROGRAM },
833 { "firstPlaysBlack", "firstPlaysBlack", XtRBoolean,
834 sizeof(Boolean), XtOffset(AppDataPtr, firstPlaysBlack),
835 XtRImmediate, (XtPointer) False },
836 { "noChessProgram", "noChessProgram", XtRBoolean,
837 sizeof(Boolean), XtOffset(AppDataPtr, noChessProgram),
838 XtRImmediate, (XtPointer) False },
839 { "firstHost", "firstHost", XtRString, sizeof(String),
840 XtOffset(AppDataPtr, firstHost), XtRString, FIRST_HOST },
841 { "secondHost", "secondHost", XtRString, sizeof(String),
842 XtOffset(AppDataPtr, secondHost), XtRString, SECOND_HOST },
843 { "firstDirectory", "firstDirectory", XtRString, sizeof(String),
844 XtOffset(AppDataPtr, firstDirectory), XtRString, "." },
845 { "secondDirectory", "secondDirectory", XtRString, sizeof(String),
846 XtOffset(AppDataPtr, secondDirectory), XtRString, "." },
847 { "bitmapDirectory", "bitmapDirectory", XtRString,
848 sizeof(String), XtOffset(AppDataPtr, bitmapDirectory),
850 { "remoteShell", "remoteShell", XtRString, sizeof(String),
851 XtOffset(AppDataPtr, remoteShell), XtRString, REMOTE_SHELL },
852 { "remoteUser", "remoteUser", XtRString, sizeof(String),
853 XtOffset(AppDataPtr, remoteUser), XtRString, "" },
854 { "timeDelay", "timeDelay", XtRFloat, sizeof(float),
855 XtOffset(AppDataPtr, timeDelay), XtRString,
856 (XtPointer) TIME_DELAY_QUOTE },
857 { "timeControl", "timeControl", XtRString, sizeof(String),
858 XtOffset(AppDataPtr, timeControl), XtRString,
859 (XtPointer) TIME_CONTROL },
860 { "internetChessServerMode", "internetChessServerMode",
861 XtRBoolean, sizeof(Boolean),
862 XtOffset(AppDataPtr, icsActive), XtRImmediate,
864 { "internetChessServerHost", "internetChessServerHost",
865 XtRString, sizeof(String),
866 XtOffset(AppDataPtr, icsHost),
867 XtRString, (XtPointer) ICS_HOST },
868 { "internetChessServerPort", "internetChessServerPort",
869 XtRString, sizeof(String),
870 XtOffset(AppDataPtr, icsPort), XtRString,
871 (XtPointer) ICS_PORT },
872 { "internetChessServerCommPort", "internetChessServerCommPort",
873 XtRString, sizeof(String),
874 XtOffset(AppDataPtr, icsCommPort), XtRString,
876 { "internetChessServerLogonScript", "internetChessServerLogonScript",
877 XtRString, sizeof(String),
878 XtOffset(AppDataPtr, icsLogon), XtRString,
880 { "internetChessServerHelper", "internetChessServerHelper",
881 XtRString, sizeof(String),
882 XtOffset(AppDataPtr, icsHelper), XtRString, "" },
883 { "internetChessServerInputBox", "internetChessServerInputBox",
884 XtRBoolean, sizeof(Boolean),
885 XtOffset(AppDataPtr, icsInputBox), XtRImmediate,
887 { "icsAlarm", "icsAlarm",
888 XtRBoolean, sizeof(Boolean),
889 XtOffset(AppDataPtr, icsAlarm), XtRImmediate,
891 { "icsAlarmTime", "icsAlarmTime",
893 XtOffset(AppDataPtr, icsAlarmTime), XtRImmediate,
895 { "useTelnet", "useTelnet", XtRBoolean, sizeof(Boolean),
896 XtOffset(AppDataPtr, useTelnet), XtRImmediate,
898 { "telnetProgram", "telnetProgram", XtRString, sizeof(String),
899 XtOffset(AppDataPtr, telnetProgram), XtRString, TELNET_PROGRAM },
900 { "gateway", "gateway", XtRString, sizeof(String),
901 XtOffset(AppDataPtr, gateway), XtRString, "" },
902 { "loadGameFile", "loadGameFile", XtRString, sizeof(String),
903 XtOffset(AppDataPtr, loadGameFile), XtRString, "" },
904 { "loadGameIndex", "loadGameIndex",
906 XtOffset(AppDataPtr, loadGameIndex), XtRImmediate,
908 { "saveGameFile", "saveGameFile", XtRString, sizeof(String),
909 XtOffset(AppDataPtr, saveGameFile), XtRString, "" },
910 { "autoRaiseBoard", "autoRaiseBoard", XtRBoolean,
911 sizeof(Boolean), XtOffset(AppDataPtr, autoRaiseBoard),
912 XtRImmediate, (XtPointer) True },
913 { "autoSaveGames", "autoSaveGames", XtRBoolean,
914 sizeof(Boolean), XtOffset(AppDataPtr, autoSaveGames),
915 XtRImmediate, (XtPointer) False },
916 { "blindfold", "blindfold", XtRBoolean,
917 sizeof(Boolean), XtOffset(AppDataPtr, blindfold),
918 XtRImmediate, (XtPointer) False },
919 { "loadPositionFile", "loadPositionFile", XtRString,
920 sizeof(String), XtOffset(AppDataPtr, loadPositionFile),
922 { "loadPositionIndex", "loadPositionIndex",
924 XtOffset(AppDataPtr, loadPositionIndex), XtRImmediate,
926 { "savePositionFile", "savePositionFile", XtRString,
927 sizeof(String), XtOffset(AppDataPtr, savePositionFile),
929 { "matchMode", "matchMode", XtRBoolean, sizeof(Boolean),
930 XtOffset(AppDataPtr, matchMode), XtRImmediate, (XtPointer) False },
931 { "matchGames", "matchGames", XtRInt, sizeof(int),
932 XtOffset(AppDataPtr, matchGames), XtRImmediate,
934 { "monoMode", "monoMode", XtRBoolean, sizeof(Boolean),
935 XtOffset(AppDataPtr, monoMode), XtRImmediate,
937 { "debugMode", "debugMode", XtRBoolean, sizeof(Boolean),
938 XtOffset(AppDataPtr, debugMode), XtRImmediate,
940 { "clockMode", "clockMode", XtRBoolean, sizeof(Boolean),
941 XtOffset(AppDataPtr, clockMode), XtRImmediate,
943 { "boardSize", "boardSize", XtRString, sizeof(String),
944 XtOffset(AppDataPtr, boardSize), XtRString, "" },
945 { "searchTime", "searchTime", XtRString, sizeof(String),
946 XtOffset(AppDataPtr, searchTime), XtRString,
948 { "searchDepth", "searchDepth", XtRInt, sizeof(int),
949 XtOffset(AppDataPtr, searchDepth), XtRImmediate,
951 { "showCoords", "showCoords", XtRBoolean, sizeof(Boolean),
952 XtOffset(AppDataPtr, showCoords), XtRImmediate,
954 { "showJail", "showJail", XtRInt, sizeof(int),
955 XtOffset(AppDataPtr, showJail), XtRImmediate,
957 { "showThinking", "showThinking", XtRBoolean, sizeof(Boolean),
958 XtOffset(AppDataPtr, showThinking), XtRImmediate,
960 { "ponderNextMove", "ponderNextMove", XtRBoolean, sizeof(Boolean),
961 XtOffset(AppDataPtr, ponderNextMove), XtRImmediate,
963 { "periodicUpdates", "periodicUpdates", XtRBoolean, sizeof(Boolean),
964 XtOffset(AppDataPtr, periodicUpdates), XtRImmediate,
966 { "clockFont", "clockFont", XtRString, sizeof(String),
967 XtOffset(AppDataPtr, clockFont), XtRString, CLOCK_FONT },
968 { "coordFont", "coordFont", XtRString, sizeof(String),
969 XtOffset(AppDataPtr, coordFont), XtRString, COORD_FONT },
970 { "font", "font", XtRString, sizeof(String),
971 XtOffset(AppDataPtr, font), XtRString, DEFAULT_FONT },
972 { "ringBellAfterMoves", "ringBellAfterMoves",
973 XtRBoolean, sizeof(Boolean),
974 XtOffset(AppDataPtr, ringBellAfterMoves),
975 XtRImmediate, (XtPointer) False },
976 { "autoCallFlag", "autoCallFlag", XtRBoolean,
977 sizeof(Boolean), XtOffset(AppDataPtr, autoCallFlag),
978 XtRImmediate, (XtPointer) False },
979 { "autoFlipView", "autoFlipView", XtRBoolean,
980 sizeof(Boolean), XtOffset(AppDataPtr, autoFlipView),
981 XtRImmediate, (XtPointer) True },
982 { "autoObserve", "autoObserve", XtRBoolean,
983 sizeof(Boolean), XtOffset(AppDataPtr, autoObserve),
984 XtRImmediate, (XtPointer) False },
985 { "autoComment", "autoComment", XtRBoolean,
986 sizeof(Boolean), XtOffset(AppDataPtr, autoComment),
987 XtRImmediate, (XtPointer) False },
988 { "getMoveList", "getMoveList", XtRBoolean,
989 sizeof(Boolean), XtOffset(AppDataPtr, getMoveList),
990 XtRImmediate, (XtPointer) True },
992 { "highlightDragging", "highlightDragging", XtRBoolean,
993 sizeof(Boolean), XtOffset(AppDataPtr, highlightDragging),
994 XtRImmediate, (XtPointer) False },
996 { "highlightLastMove", "highlightLastMove", XtRBoolean,
997 sizeof(Boolean), XtOffset(AppDataPtr, highlightLastMove),
998 XtRImmediate, (XtPointer) False },
999 { "premove", "premove", XtRBoolean,
1000 sizeof(Boolean), XtOffset(AppDataPtr, premove),
1001 XtRImmediate, (XtPointer) True },
1002 { "testLegality", "testLegality", XtRBoolean,
1003 sizeof(Boolean), XtOffset(AppDataPtr, testLegality),
1004 XtRImmediate, (XtPointer) True },
1005 { "flipView", "flipView", XtRBoolean,
1006 sizeof(Boolean), XtOffset(AppDataPtr, flipView),
1007 XtRImmediate, (XtPointer) False },
1008 { "cmail", "cmailGameName", XtRString, sizeof(String),
1009 XtOffset(AppDataPtr, cmailGameName), XtRString, "" },
1010 { "alwaysPromoteToQueen", "alwaysPromoteToQueen", XtRBoolean,
1011 sizeof(Boolean), XtOffset(AppDataPtr, alwaysPromoteToQueen),
1012 XtRImmediate, (XtPointer) False },
1013 { "oldSaveStyle", "oldSaveStyle", XtRBoolean,
1014 sizeof(Boolean), XtOffset(AppDataPtr, oldSaveStyle),
1015 XtRImmediate, (XtPointer) False },
1016 { "quietPlay", "quietPlay", XtRBoolean,
1017 sizeof(Boolean), XtOffset(AppDataPtr, quietPlay),
1018 XtRImmediate, (XtPointer) False },
1019 { "titleInWindow", "titleInWindow", XtRBoolean,
1020 sizeof(Boolean), XtOffset(AppDataPtr, titleInWindow),
1021 XtRImmediate, (XtPointer) False },
1022 { "localLineEditing", "localLineEditing", XtRBoolean,
1023 sizeof(Boolean), XtOffset(AppDataPtr, localLineEditing),
1024 XtRImmediate, (XtPointer) True }, /* not implemented, must be True */
1026 { "zippyTalk", "zippyTalk", XtRBoolean,
1027 sizeof(Boolean), XtOffset(AppDataPtr, zippyTalk),
1028 XtRImmediate, (XtPointer) ZIPPY_TALK },
1029 { "zippyPlay", "zippyPlay", XtRBoolean,
1030 sizeof(Boolean), XtOffset(AppDataPtr, zippyPlay),
1031 XtRImmediate, (XtPointer) ZIPPY_PLAY },
1032 { "zippyLines", "zippyLines", XtRString, sizeof(String),
1033 XtOffset(AppDataPtr, zippyLines), XtRString, ZIPPY_LINES },
1034 { "zippyPinhead", "zippyPinhead", XtRString, sizeof(String),
1035 XtOffset(AppDataPtr, zippyPinhead), XtRString, ZIPPY_PINHEAD },
1036 { "zippyPassword", "zippyPassword", XtRString, sizeof(String),
1037 XtOffset(AppDataPtr, zippyPassword), XtRString, ZIPPY_PASSWORD },
1038 { "zippyPassword2", "zippyPassword2", XtRString, sizeof(String),
1039 XtOffset(AppDataPtr, zippyPassword2), XtRString, ZIPPY_PASSWORD2 },
1040 { "zippyWrongPassword", "zippyWrongPassword", XtRString, sizeof(String),
1041 XtOffset(AppDataPtr, zippyWrongPassword), XtRString,
1042 ZIPPY_WRONG_PASSWORD },
1043 { "zippyAcceptOnly", "zippyAcceptOnly", XtRString, sizeof(String),
1044 XtOffset(AppDataPtr, zippyAcceptOnly), XtRString, ZIPPY_ACCEPT_ONLY },
1045 { "zippyUseI", "zippyUseI", XtRBoolean,
1046 sizeof(Boolean), XtOffset(AppDataPtr, zippyUseI),
1047 XtRImmediate, (XtPointer) ZIPPY_USE_I },
1048 { "zippyBughouse", "zippyBughouse", XtRInt,
1049 sizeof(int), XtOffset(AppDataPtr, zippyBughouse),
1050 XtRImmediate, (XtPointer) ZIPPY_BUGHOUSE },
1051 { "zippyNoplayCrafty", "zippyNoplayCrafty", XtRBoolean,
1052 sizeof(Boolean), XtOffset(AppDataPtr, zippyNoplayCrafty),
1053 XtRImmediate, (XtPointer) ZIPPY_NOPLAY_CRAFTY },
1054 { "zippyGameEnd", "zippyGameEnd", XtRString, sizeof(String),
1055 XtOffset(AppDataPtr, zippyGameEnd), XtRString, ZIPPY_GAME_END },
1056 { "zippyGameStart", "zippyGameStart", XtRString, sizeof(String),
1057 XtOffset(AppDataPtr, zippyGameStart), XtRString, ZIPPY_GAME_START },
1058 { "zippyAdjourn", "zippyAdjourn", XtRBoolean,
1059 sizeof(Boolean), XtOffset(AppDataPtr, zippyAdjourn),
1060 XtRImmediate, (XtPointer) ZIPPY_ADJOURN },
1061 { "zippyAbort", "zippyAbort", XtRBoolean,
1062 sizeof(Boolean), XtOffset(AppDataPtr, zippyAbort),
1063 XtRImmediate, (XtPointer) ZIPPY_ABORT },
1064 { "zippyVariants", "zippyVariants", XtRString, sizeof(String),
1065 XtOffset(AppDataPtr, zippyVariants), XtRString, ZIPPY_VARIANTS },
1066 { "zippyMaxGames", "zippyMaxGames", XtRInt, sizeof(int),
1067 XtOffset(AppDataPtr, zippyMaxGames), XtRImmediate,
1068 (XtPointer) ZIPPY_MAX_GAMES },
1069 { "zippyReplayTimeout", "zippyReplayTimeout", XtRInt, sizeof(int),
1070 XtOffset(AppDataPtr, zippyReplayTimeout), XtRImmediate,
1071 (XtPointer) ZIPPY_REPLAY_TIMEOUT },
1072 { "zippyShortGame", "zippyShortGame", XtRInt, sizeof(int),
1073 XtOffset(AppDataPtr, zippyShortGame), XtRImmediate,
1076 { "flashCount", "flashCount", XtRInt, sizeof(int),
1077 XtOffset(AppDataPtr, flashCount), XtRImmediate,
1078 (XtPointer) FLASH_COUNT },
1079 { "flashRate", "flashRate", XtRInt, sizeof(int),
1080 XtOffset(AppDataPtr, flashRate), XtRImmediate,
1081 (XtPointer) FLASH_RATE },
1082 { "pixmapDirectory", "pixmapDirectory", XtRString,
1083 sizeof(String), XtOffset(AppDataPtr, pixmapDirectory),
1085 { "msLoginDelay", "msLoginDelay", XtRInt, sizeof(int),
1086 XtOffset(AppDataPtr, msLoginDelay), XtRImmediate,
1087 (XtPointer) MS_LOGIN_DELAY },
1088 { "colorizeMessages", "colorizeMessages", XtRBoolean,
1089 sizeof(Boolean), XtOffset(AppDataPtr, colorize),
1090 XtRImmediate, (XtPointer) False },
1091 { "colorShout", "colorShout", XtRString,
1092 sizeof(String), XtOffset(AppDataPtr, colorShout),
1093 XtRString, COLOR_SHOUT },
1094 { "colorSShout", "colorSShout", XtRString,
1095 sizeof(String), XtOffset(AppDataPtr, colorSShout),
1096 XtRString, COLOR_SSHOUT },
1097 { "colorChannel1", "colorChannel1", XtRString,
1098 sizeof(String), XtOffset(AppDataPtr, colorChannel1),
1099 XtRString, COLOR_CHANNEL1 },
1100 { "colorChannel", "colorChannel", XtRString,
1101 sizeof(String), XtOffset(AppDataPtr, colorChannel),
1102 XtRString, COLOR_CHANNEL },
1103 { "colorKibitz", "colorKibitz", XtRString,
1104 sizeof(String), XtOffset(AppDataPtr, colorKibitz),
1105 XtRString, COLOR_KIBITZ },
1106 { "colorTell", "colorTell", XtRString,
1107 sizeof(String), XtOffset(AppDataPtr, colorTell),
1108 XtRString, COLOR_TELL },
1109 { "colorChallenge", "colorChallenge", XtRString,
1110 sizeof(String), XtOffset(AppDataPtr, colorChallenge),
1111 XtRString, COLOR_CHALLENGE },
1112 { "colorRequest", "colorRequest", XtRString,
1113 sizeof(String), XtOffset(AppDataPtr, colorRequest),
1114 XtRString, COLOR_REQUEST },
1115 { "colorSeek", "colorSeek", XtRString,
1116 sizeof(String), XtOffset(AppDataPtr, colorSeek),
1117 XtRString, COLOR_SEEK },
1118 { "colorNormal", "colorNormal", XtRString,
1119 sizeof(String), XtOffset(AppDataPtr, colorNormal),
1120 XtRString, COLOR_NORMAL },
1121 { "soundProgram", "soundProgram", XtRString,
1122 sizeof(String), XtOffset(AppDataPtr, soundProgram),
1123 XtRString, "play" },
1124 { "soundShout", "soundShout", XtRString,
1125 sizeof(String), XtOffset(AppDataPtr, soundShout),
1127 { "soundSShout", "soundSShout", XtRString,
1128 sizeof(String), XtOffset(AppDataPtr, soundSShout),
1130 { "soundChannel1", "soundChannel1", XtRString,
1131 sizeof(String), XtOffset(AppDataPtr, soundChannel1),
1133 { "soundChannel", "soundChannel", XtRString,
1134 sizeof(String), XtOffset(AppDataPtr, soundChannel),
1136 { "soundKibitz", "soundKibitz", XtRString,
1137 sizeof(String), XtOffset(AppDataPtr, soundKibitz),
1139 { "soundTell", "soundTell", XtRString,
1140 sizeof(String), XtOffset(AppDataPtr, soundTell),
1142 { "soundChallenge", "soundChallenge", XtRString,
1143 sizeof(String), XtOffset(AppDataPtr, soundChallenge),
1145 { "soundRequest", "soundRequest", XtRString,
1146 sizeof(String), XtOffset(AppDataPtr, soundRequest),
1148 { "soundSeek", "soundSeek", XtRString,
1149 sizeof(String), XtOffset(AppDataPtr, soundSeek),
1151 { "soundMove", "soundMove", XtRString,
1152 sizeof(String), XtOffset(AppDataPtr, soundMove),
1154 { "soundIcsWin", "soundIcsWin", XtRString,
1155 sizeof(String), XtOffset(AppDataPtr, soundIcsWin),
1157 { "soundIcsLoss", "soundIcsLoss", XtRString,
1158 sizeof(String), XtOffset(AppDataPtr, soundIcsLoss),
1160 { "soundIcsDraw", "soundIcsDraw", XtRString,
1161 sizeof(String), XtOffset(AppDataPtr, soundIcsDraw),
1163 { "soundIcsUnfinished", "soundIcsUnfinished", XtRString,
1164 sizeof(String), XtOffset(AppDataPtr, soundIcsUnfinished),
1166 { "soundIcsAlarm", "soundIcsAlarm", XtRString,
1167 sizeof(String), XtOffset(AppDataPtr, soundIcsAlarm),
1169 { "reuseFirst", "reuseFirst", XtRBoolean,
1170 sizeof(Boolean), XtOffset(AppDataPtr, reuseFirst),
1171 XtRImmediate, (XtPointer) True },
1172 { "reuseSecond", "reuseSecond", XtRBoolean,
1173 sizeof(Boolean), XtOffset(AppDataPtr, reuseSecond),
1174 XtRImmediate, (XtPointer) True },
1175 { "animateDragging", "animateDragging", XtRBoolean,
1176 sizeof(Boolean), XtOffset(AppDataPtr, animateDragging),
1177 XtRImmediate, (XtPointer) True },
1178 { "animateMoving", "animateMoving", XtRBoolean,
1179 sizeof(Boolean), XtOffset(AppDataPtr, animate),
1180 XtRImmediate, (XtPointer) True },
1181 { "animateSpeed", "animateSpeed", XtRInt,
1182 sizeof(int), XtOffset(AppDataPtr, animSpeed),
1183 XtRImmediate, (XtPointer)10 },
1184 { "popupExitMessage", "popupExitMessage", XtRBoolean,
1185 sizeof(Boolean), XtOffset(AppDataPtr, popupExitMessage),
1186 XtRImmediate, (XtPointer) True },
1187 { "popupMoveErrors", "popupMoveErrors", XtRBoolean,
1188 sizeof(Boolean), XtOffset(AppDataPtr, popupMoveErrors),
1189 XtRImmediate, (XtPointer) False },
1190 { "fontSizeTolerance", "fontSizeTolerance", XtRInt,
1191 sizeof(int), XtOffset(AppDataPtr, fontSizeTolerance),
1192 XtRImmediate, (XtPointer)4 },
1193 { "initialMode", "initialMode", XtRString,
1194 sizeof(String), XtOffset(AppDataPtr, initialMode),
1195 XtRImmediate, (XtPointer) "" },
1196 { "variant", "variant", XtRString,
1197 sizeof(String), XtOffset(AppDataPtr, variant),
1198 XtRImmediate, (XtPointer) "normal" },
1199 { "firstProtocolVersion", "firstProtocolVersion", XtRInt,
1200 sizeof(int), XtOffset(AppDataPtr, firstProtocolVersion),
1201 XtRImmediate, (XtPointer)PROTOVER },
1202 { "secondProtocolVersion", "secondProtocolVersion", XtRInt,
1203 sizeof(int), XtOffset(AppDataPtr, secondProtocolVersion),
1204 XtRImmediate, (XtPointer)PROTOVER },
1205 { "showButtonBar", "showButtonBar", XtRBoolean,
1206 sizeof(Boolean), XtOffset(AppDataPtr, showButtonBar),
1207 XtRImmediate, (XtPointer) True },
1208 { "lowTimeWarningColor", "lowTimeWarningColor", XtRString,
1209 sizeof(String), XtOffset(AppDataPtr, lowTimeWarningColor),
1210 XtRString, COLOR_LOWTIMEWARNING },
1211 { "lowTimeWarning", "lowTimeWarning", XtRBoolean,
1212 sizeof(Boolean), XtOffset(AppDataPtr, lowTimeWarning),
1213 XtRImmediate, (XtPointer) False },
1214 {"icsEngineAnalyze", "icsEngineAnalyze", XtRBoolean, /* [DM] icsEngineAnalyze */
1215 sizeof(Boolean), XtOffset(AppDataPtr, icsEngineAnalyze),
1216 XtRImmediate, (XtPointer) False },
1217 { "firstScoreAbs", "firstScoreAbs", XtRBoolean,
1218 sizeof(Boolean), XtOffset(AppDataPtr, firstScoreIsAbsolute),
1219 XtRImmediate, (XtPointer) False },
1220 { "secondScoreAbs", "secondScoreAbs", XtRBoolean,
1221 sizeof(Boolean), XtOffset(AppDataPtr, secondScoreIsAbsolute),
1222 XtRImmediate, (XtPointer) False },
1223 { "pgnExtendedInfo", "pgnExtendedInfo", XtRBoolean,
1224 sizeof(Boolean), XtOffset(AppDataPtr, saveExtendedInfoInPGN),
1225 XtRImmediate, (XtPointer) False },
1226 { "hideThinkingFromHuman", "hideThinkingFromHuman", XtRBoolean,
1227 sizeof(Boolean), XtOffset(AppDataPtr, hideThinkingFromHuman),
1228 XtRImmediate, (XtPointer) True },
1229 { "adjudicateLossThreshold", "adjudicateLossThreshold", XtRInt,
1230 sizeof(int), XtOffset(AppDataPtr, adjudicateLossThreshold),
1231 XtRImmediate, (XtPointer) 0},
1232 { "adjudicateDrawMoves", "adjudicateDrawMoves", XtRInt,
1233 sizeof(int), XtOffset(AppDataPtr, adjudicateDrawMoves),
1234 XtRImmediate, (XtPointer) 0},
1235 { "pgnEventHeader", "pgnEventHeader", XtRString,
1236 sizeof(String), XtOffset(AppDataPtr, pgnEventHeader),
1237 XtRImmediate, (XtPointer) "Computer Chess Game" },
1238 { "defaultFrcPosition", "defaultFrcPositon", XtRInt,
1239 sizeof(int), XtOffset(AppDataPtr, defaultFrcPosition),
1240 XtRImmediate, (XtPointer) -1},
1241 { "gameListTags", "gameListTags", XtRString,
1242 sizeof(String), XtOffset(AppDataPtr, gameListTags),
1243 XtRImmediate, (XtPointer) GLT_DEFAULT_TAGS },
1245 // [HGM] 4.3.xx options
1246 { "boardWidth", "boardWidth", XtRInt,
1247 sizeof(int), XtOffset(AppDataPtr, NrFiles),
1248 XtRImmediate, (XtPointer) -1},
1249 { "boardHeight", "boardHeight", XtRInt,
1250 sizeof(int), XtOffset(AppDataPtr, NrRanks),
1251 XtRImmediate, (XtPointer) -1},
1252 { "matchPause", "matchPause", XtRInt,
1253 sizeof(int), XtOffset(AppDataPtr, matchPause),
1254 XtRImmediate, (XtPointer) 10000},
1255 { "holdingsSize", "holdingsSize", XtRInt,
1256 sizeof(int), XtOffset(AppDataPtr, holdingsSize),
1257 XtRImmediate, (XtPointer) -1},
1258 { "flipBlack", "flipBlack", XtRBoolean,
1259 sizeof(Boolean), XtOffset(AppDataPtr, upsideDown),
1260 XtRImmediate, (XtPointer) False},
1261 { "allWhite", "allWhite", XtRBoolean,
1262 sizeof(Boolean), XtOffset(AppDataPtr, allWhite),
1263 XtRImmediate, (XtPointer) False},
1264 { "pieceToCharTable", "pieceToCharTable", XtRString,
1265 sizeof(String), XtOffset(AppDataPtr, pieceToCharTable),
1266 XtRImmediate, (XtPointer) 0},
1267 { "alphaRank", "alphaRank", XtRBoolean,
1268 sizeof(Boolean), XtOffset(AppDataPtr, alphaRank),
1269 XtRImmediate, (XtPointer) False},
1270 { "testClaims", "testClaims", XtRBoolean,
1271 sizeof(Boolean), XtOffset(AppDataPtr, testClaims),
1272 XtRImmediate, (XtPointer) True},
1273 { "checkMates", "checkMates", XtRBoolean,
1274 sizeof(Boolean), XtOffset(AppDataPtr, checkMates),
1275 XtRImmediate, (XtPointer) True},
1276 { "materialDraws", "materialDraws", XtRBoolean,
1277 sizeof(Boolean), XtOffset(AppDataPtr, materialDraws),
1278 XtRImmediate, (XtPointer) True},
1279 { "trivialDraws", "trivialDraws", XtRBoolean,
1280 sizeof(Boolean), XtOffset(AppDataPtr, trivialDraws),
1281 XtRImmediate, (XtPointer) False},
1282 { "ruleMoves", "ruleMoves", XtRInt,
1283 sizeof(int), XtOffset(AppDataPtr, ruleMoves),
1284 XtRImmediate, (XtPointer) 51},
1285 { "repeatsToDraw", "repeatsToDraw", XtRInt,
1286 sizeof(int), XtOffset(AppDataPtr, drawRepeats),
1287 XtRImmediate, (XtPointer) 6},
1288 { "engineDebugOutput", "engineDebugOutput", XtRInt,
1289 sizeof(int), XtOffset(AppDataPtr, engineComments),
1290 XtRImmediate, (XtPointer) 1},
1291 { "userName", "userName", XtRString,
1292 sizeof(int), XtOffset(AppDataPtr, userName),
1293 XtRImmediate, (XtPointer) 0},
1294 { "autoKibitz", "autoKibitz", XtRBoolean,
1295 sizeof(Boolean), XtOffset(AppDataPtr, autoKibitz),
1296 XtRImmediate, (XtPointer) False},
1297 { "firstTimeOdds", "firstTimeOdds", XtRInt,
1298 sizeof(int), XtOffset(AppDataPtr, firstTimeOdds),
1299 XtRImmediate, (XtPointer) 1},
1300 { "secondTimeOdds", "secondTimeOdds", XtRInt,
1301 sizeof(int), XtOffset(AppDataPtr, secondTimeOdds),
1302 XtRImmediate, (XtPointer) 1},
1303 { "timeOddsMode", "timeOddsMode", XtRInt,
1304 sizeof(int), XtOffset(AppDataPtr, timeOddsMode),
1305 XtRImmediate, (XtPointer) 0},
1306 { "firstAccumulateTC", "firstAccumulateTC", XtRInt,
1307 sizeof(int), XtOffset(AppDataPtr, firstAccumulateTC),
1308 XtRImmediate, (XtPointer) 1},
1309 { "secondAccumulateTC", "secondAccumulateTC", XtRInt,
1310 sizeof(int), XtOffset(AppDataPtr, secondAccumulateTC),
1311 XtRImmediate, (XtPointer) 1},
1312 { "firstNPS", "firstNPS", XtRInt,
1313 sizeof(int), XtOffset(AppDataPtr, firstNPS),
1314 XtRImmediate, (XtPointer) -1},
1315 { "secondNPS", "secondNPS", XtRInt,
1316 sizeof(int), XtOffset(AppDataPtr, secondNPS),
1317 XtRImmediate, (XtPointer) -1},
1318 { "serverMoves", "serverMoves", XtRString,
1319 sizeof(String), XtOffset(AppDataPtr, serverMovesName),
1320 XtRImmediate, (XtPointer) 0},
1321 { "serverPause", "serverPause", XtRInt,
1322 sizeof(int), XtOffset(AppDataPtr, serverPause),
1323 XtRImmediate, (XtPointer) 0},
1324 { "suppressLoadMoves", "suppressLoadMoves", XtRBoolean,
1325 sizeof(Boolean), XtOffset(AppDataPtr, suppressLoadMoves),
1326 XtRImmediate, (XtPointer) False},
1327 { "userName", "userName", XtRString,
1328 sizeof(String), XtOffset(AppDataPtr, userName),
1329 XtRImmediate, (XtPointer) 0},
1330 { "egtFormats", "egtFormats", XtRString,
1331 sizeof(String), XtOffset(AppDataPtr, egtFormats),
1332 XtRImmediate, (XtPointer) 0},
1333 { "rewindIndex", "rewindIndex", XtRInt,
1334 sizeof(int), XtOffset(AppDataPtr, rewindIndex),
1335 XtRImmediate, (XtPointer) 0},
1336 { "sameColorGames", "sameColorGames", XtRInt,
1337 sizeof(int), XtOffset(AppDataPtr, sameColorGames),
1338 XtRImmediate, (XtPointer) 0},
1339 { "smpCores", "smpCores", XtRInt,
1340 sizeof(int), XtOffset(AppDataPtr, smpCores),
1341 XtRImmediate, (XtPointer) 1},
1342 { "niceEngines", "niceEngines", XtRInt,
1343 sizeof(int), XtOffset(AppDataPtr, niceEngines),
1344 XtRImmediate, (XtPointer) 0},
1345 { "nameOfDebugFile", "nameOfDebugFile", XtRString,
1346 sizeof(String), XtOffset(AppDataPtr, nameOfDebugFile),
1347 XtRImmediate, (XtPointer) "xboard.debug"},
1348 { "engineDebugOutput", "engineDebugOutput", XtRInt,
1349 sizeof(int), XtOffset(AppDataPtr, engineComments),
1350 XtRImmediate, (XtPointer) 1},
1351 { "noGUI", "noGUI", XtRBoolean,
1352 sizeof(Boolean), XtOffset(AppDataPtr, noGUI),
1353 XtRImmediate, (XtPointer) 0},
1354 { "firstOptions", "firstOptions", XtRString,
1355 sizeof(String), XtOffset(AppDataPtr, firstOptions),
1356 XtRImmediate, (XtPointer) "" },
1357 { "secondOptions", "secondOptions", XtRString,
1358 sizeof(String), XtOffset(AppDataPtr, secondOptions),
1359 XtRImmediate, (XtPointer) "" },
1360 { "firstNeedsNoncompliantFEN", "firstNeedsNoncompliantFEN", XtRString,
1361 sizeof(String), XtOffset(AppDataPtr, fenOverride1),
1362 XtRImmediate, (XtPointer) 0 },
1363 { "secondNeedsNoncompliantFEN", "secondNeedsNoncompliantFEN", XtRString,
1364 sizeof(String), XtOffset(AppDataPtr, fenOverride2),
1365 XtRImmediate, (XtPointer) 0 },
1367 // [HGM] Winboard_x UCI options
1368 { "firstIsUCI", "firstIsUCI", XtRBoolean,
1369 sizeof(Boolean), XtOffset(AppDataPtr, firstIsUCI),
1370 XtRImmediate, (XtPointer) False},
1371 { "secondIsUCI", "secondIsUCI", XtRBoolean,
1372 sizeof(Boolean), XtOffset(AppDataPtr, secondIsUCI),
1373 XtRImmediate, (XtPointer) False},
1374 { "firstHasOwnBookUCI", "firstHasOwnBookUCI", XtRBoolean,
1375 sizeof(Boolean), XtOffset(AppDataPtr, firstHasOwnBookUCI),
1376 XtRImmediate, (XtPointer) True},
1377 { "secondHasOwnBookUCI", "secondHasOwnBookUCI", XtRBoolean,
1378 sizeof(Boolean), XtOffset(AppDataPtr, secondHasOwnBookUCI),
1379 XtRImmediate, (XtPointer) True},
1380 { "usePolyglotBook", "usePolyglotBook", XtRBoolean,
1381 sizeof(Boolean), XtOffset(AppDataPtr, usePolyglotBook),
1382 XtRImmediate, (XtPointer) False},
1383 { "defaultHashSize", "defaultHashSize", XtRInt,
1384 sizeof(int), XtOffset(AppDataPtr, defaultHashSize),
1385 XtRImmediate, (XtPointer) 64},
1386 { "defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XtRInt,
1387 sizeof(int), XtOffset(AppDataPtr, defaultCacheSizeEGTB),
1388 XtRImmediate, (XtPointer) 4},
1389 { "polyglotDir", "polyglotDir", XtRString,
1390 sizeof(String), XtOffset(AppDataPtr, polyglotDir),
1391 XtRImmediate, (XtPointer) "." },
1392 { "polyglotBook", "polyglotBook", XtRString,
1393 sizeof(String), XtOffset(AppDataPtr, polyglotBook),
1394 XtRImmediate, (XtPointer) "" },
1395 { "defaultPathEGTB", "defaultPathEGTB", XtRString,
1396 sizeof(String), XtOffset(AppDataPtr, defaultPathEGTB),
1397 XtRImmediate, (XtPointer) "/usr/local/share/egtb"},
1398 { "delayBeforeQuit", "delayBeforeQuit", XtRInt,
1399 sizeof(int), XtOffset(AppDataPtr, delayBeforeQuit),
1400 XtRImmediate, (XtPointer) 0},
1401 { "delayAfterQuit", "delayAfterQuit", XtRInt,
1402 sizeof(int), XtOffset(AppDataPtr, delayAfterQuit),
1403 XtRImmediate, (XtPointer) 0},
1404 { "keepAlive", "keepAlive", XtRInt,
1405 sizeof(int), XtOffset(AppDataPtr, keepAlive),
1406 XtRImmediate, (XtPointer) 0},
1407 { "forceIllegalMoves", "forceIllegalMoves", XtRBoolean,
1408 sizeof(Boolean), XtOffset(AppDataPtr, forceIllegal),
1409 XtRImmediate, (XtPointer) False},
1412 XrmOptionDescRec shellOptions[] = {
1413 { "-whitePieceColor", "whitePieceColor", XrmoptionSepArg, NULL },
1414 { "-blackPieceColor", "blackPieceColor", XrmoptionSepArg, NULL },
1415 { "-lightSquareColor", "lightSquareColor", XrmoptionSepArg, NULL },
1416 { "-darkSquareColor", "darkSquareColor", XrmoptionSepArg, NULL },
1417 { "-highlightSquareColor", "highlightSquareColor", XrmoptionSepArg, NULL },
1418 { "-premoveHighlightColor", "premoveHighlightColor", XrmoptionSepArg,NULL},
1419 { "-movesPerSession", "movesPerSession", XrmoptionSepArg, NULL },
1420 { "-mps", "movesPerSession", XrmoptionSepArg, NULL },
1421 { "-timeIncrement", "timeIncrement", XrmoptionSepArg, NULL },
1422 { "-inc", "timeIncrement", XrmoptionSepArg, NULL },
1423 { "-initString", "initString", XrmoptionSepArg, NULL },
1424 { "-firstInitString", "initString", XrmoptionSepArg, NULL },
1425 { "-secondInitString", "secondInitString", XrmoptionSepArg, NULL },
1426 { "-firstComputerString", "firstComputerString", XrmoptionSepArg, NULL },
1427 { "-secondComputerString", "secondComputerString", XrmoptionSepArg, NULL },
1428 { "-firstChessProgram", "firstChessProgram", XrmoptionSepArg, NULL },
1429 { "-fcp", "firstChessProgram", XrmoptionSepArg, NULL },
1430 { "-secondChessProgram", "secondChessProgram", XrmoptionSepArg, NULL },
1431 { "-scp", "secondChessProgram", XrmoptionSepArg, NULL },
1432 { "-firstPlaysBlack", "firstPlaysBlack", XrmoptionSepArg, NULL },
1433 { "-fb", "firstPlaysBlack", XrmoptionNoArg, "True" },
1434 { "-xfb", "firstPlaysBlack", XrmoptionNoArg, "False" },
1435 { "-noChessProgram", "noChessProgram", XrmoptionSepArg, NULL },
1436 { "-ncp", "noChessProgram", XrmoptionNoArg, "True" },
1437 { "-xncp", "noChessProgram", XrmoptionNoArg, "False" },
1438 { "-firstHost", "firstHost", XrmoptionSepArg, NULL },
1439 { "-fh", "firstHost", XrmoptionSepArg, NULL },
1440 { "-secondHost", "secondHost", XrmoptionSepArg, NULL },
1441 { "-sh", "secondHost", XrmoptionSepArg, NULL },
1442 { "-firstDirectory", "firstDirectory", XrmoptionSepArg, NULL },
1443 { "-fd", "firstDirectory", XrmoptionSepArg, NULL },
1444 { "-secondDirectory", "secondDirectory", XrmoptionSepArg, NULL },
1445 { "-sd", "secondDirectory", XrmoptionSepArg, NULL },
1446 { "-bitmapDirectory", "bitmapDirectory", XrmoptionSepArg, NULL },
1447 { "-bm", "bitmapDirectory", XrmoptionSepArg, NULL },
1448 { "-remoteShell", "remoteShell", XrmoptionSepArg, NULL },
1449 { "-rsh", "remoteShell", XrmoptionSepArg, NULL },
1450 { "-remoteUser", "remoteUser", XrmoptionSepArg, NULL },
1451 { "-ruser", "remoteUser", XrmoptionSepArg, NULL },
1452 { "-timeDelay", "timeDelay", XrmoptionSepArg, NULL },
1453 { "-td", "timeDelay", XrmoptionSepArg, NULL },
1454 { "-timeControl", "timeControl", XrmoptionSepArg, NULL },
1455 { "-tc", "timeControl", XrmoptionSepArg, NULL },
1456 { "-internetChessServerMode", "internetChessServerMode",
1457 XrmoptionSepArg, NULL },
1458 { "-ics", "internetChessServerMode", XrmoptionNoArg, "True" },
1459 { "-xics", "internetChessServerMode", XrmoptionNoArg, "False" },
1460 { "-internetChessServerHost", "internetChessServerHost",
1461 XrmoptionSepArg, NULL },
1462 { "-icshost", "internetChessServerHost", XrmoptionSepArg, NULL },
1463 { "-internetChessServerPort", "internetChessServerPort",
1464 XrmoptionSepArg, NULL },
1465 { "-icsport", "internetChessServerPort", XrmoptionSepArg, NULL },
1466 { "-internetChessServerCommPort", "internetChessServerCommPort",
1467 XrmoptionSepArg, NULL },
1468 { "-icscomm", "internetChessServerCommPort", XrmoptionSepArg, NULL },
1469 { "-internetChessServerLogonScript", "internetChessServerLogonScript",
1470 XrmoptionSepArg, NULL },
1471 { "-icslogon", "internetChessServerLogonScript", XrmoptionSepArg, NULL },
1472 { "-internetChessServerHelper", "internetChessServerHelper",
1473 XrmoptionSepArg, NULL },
1474 { "-icshelper", "internetChessServerHelper", XrmoptionSepArg, NULL },
1475 { "-internetChessServerInputBox", "internetChessServerInputBox",
1476 XrmoptionSepArg, NULL },
1477 { "-icsinput", "internetChessServerInputBox", XrmoptionNoArg, "True" },
1478 { "-xicsinput", "internetChessServerInputBox", XrmoptionNoArg, "False" },
1479 { "-icsAlarm", "icsAlarm", XrmoptionSepArg, NULL },
1480 { "-alarm", "icsAlarm", XrmoptionNoArg, "True" },
1481 { "-xalarm", "icsAlarm", XrmoptionNoArg, "False" },
1482 { "-icsAlarmTime", "icsAlarmTime", XrmoptionSepArg, NULL },
1483 { "-useTelnet", "useTelnet", XrmoptionSepArg, NULL },
1484 { "-telnet", "useTelnet", XrmoptionNoArg, "True" },
1485 { "-xtelnet", "useTelnet", XrmoptionNoArg, "False" },
1486 { "-telnetProgram", "telnetProgram", XrmoptionSepArg, NULL },
1487 { "-gateway", "gateway", XrmoptionSepArg, NULL },
1488 { "-loadGameFile", "loadGameFile", XrmoptionSepArg, NULL },
1489 { "-lgf", "loadGameFile", XrmoptionSepArg, NULL },
1490 { "-loadGameIndex", "loadGameIndex", XrmoptionSepArg, NULL },
1491 { "-lgi", "loadGameIndex", XrmoptionSepArg, NULL },
1492 { "-saveGameFile", "saveGameFile", XrmoptionSepArg, NULL },
1493 { "-sgf", "saveGameFile", XrmoptionSepArg, NULL },
1494 { "-autoSaveGames", "autoSaveGames", XrmoptionSepArg, NULL },
1495 { "-autosave", "autoSaveGames", XrmoptionNoArg, "True" },
1496 { "-xautosave", "autoSaveGames", XrmoptionNoArg, "False" },
1497 { "-autoRaiseBoard", "autoRaiseBoard", XrmoptionSepArg, NULL },
1498 { "-autoraise", "autoRaiseBoard", XrmoptionNoArg, "True" },
1499 { "-xautoraise", "autoRaiseBoard", XrmoptionNoArg, "False" },
1500 { "-blindfold", "blindfold", XrmoptionSepArg, NULL },
1501 { "-blind", "blindfold", XrmoptionNoArg, "True" },
1502 { "-xblind", "blindfold", XrmoptionNoArg, "False" },
1503 { "-loadPositionFile", "loadPositionFile", XrmoptionSepArg, NULL },
1504 { "-lpf", "loadPositionFile", XrmoptionSepArg, NULL },
1505 { "-loadPositionIndex", "loadPositionIndex", XrmoptionSepArg, NULL },
1506 { "-lpi", "loadPositionIndex", XrmoptionSepArg, NULL },
1507 { "-savePositionFile", "savePositionFile", XrmoptionSepArg, NULL },
1508 { "-spf", "savePositionFile", XrmoptionSepArg, NULL },
1509 { "-matchMode", "matchMode", XrmoptionSepArg, NULL },
1510 { "-mm", "matchMode", XrmoptionNoArg, "True" },
1511 { "-xmm", "matchMode", XrmoptionNoArg, "False" },
1512 { "-matchGames", "matchGames", XrmoptionSepArg, NULL },
1513 { "-mg", "matchGames", XrmoptionSepArg, NULL },
1514 { "-monoMode", "monoMode", XrmoptionSepArg, NULL },
1515 { "-mono", "monoMode", XrmoptionNoArg, "True" },
1516 { "-xmono", "monoMode", XrmoptionNoArg, "False" },
1517 { "-debugMode", "debugMode", XrmoptionSepArg, NULL },
1518 { "-debug", "debugMode", XrmoptionNoArg, "True" },
1519 { "-xdebug", "debugMode", XrmoptionNoArg, "False" },
1520 { "-clockMode", "clockMode", XrmoptionSepArg, NULL },
1521 { "-clock", "clockMode", XrmoptionNoArg, "True" },
1522 { "-xclock", "clockMode", XrmoptionNoArg, "False" },
1523 { "-boardSize", "boardSize", XrmoptionSepArg, NULL },
1524 { "-size", "boardSize", XrmoptionSepArg, NULL },
1525 { "-searchTime", "searchTime", XrmoptionSepArg, NULL },
1526 { "-st", "searchTime", XrmoptionSepArg, NULL },
1527 { "-searchDepth", "searchDepth", XrmoptionSepArg, NULL },
1528 { "-depth", "searchDepth", XrmoptionSepArg, NULL },
1529 { "-showCoords", "showCoords", XrmoptionSepArg, NULL },
1530 { "-coords", "showCoords", XrmoptionNoArg, "True" },
1531 { "-xcoords", "showCoords", XrmoptionNoArg, "False" },
1533 { "-showJail", "showJail", XrmoptionSepArg, NULL },
1534 { "-jail", "showJail", XrmoptionNoArg, "1" },
1535 { "-sidejail", "showJail", XrmoptionNoArg, "2" },
1536 { "-xjail", "showJail", XrmoptionNoArg, "0" },
1538 { "-showThinking", "showThinking", XrmoptionSepArg, NULL },
1539 { "-thinking", "showThinking", XrmoptionNoArg, "True" },
1540 { "-xthinking", "showThinking", XrmoptionNoArg, "False" },
1541 { "-ponderNextMove", "ponderNextMove", XrmoptionSepArg, NULL },
1542 { "-ponder", "ponderNextMove", XrmoptionNoArg, "True" },
1543 { "-xponder", "ponderNextMove", XrmoptionNoArg, "False" },
1544 { "-periodicUpdates", "periodicUpdates", XrmoptionSepArg, NULL },
1545 { "-periodic", "periodicUpdates", XrmoptionNoArg, "True" },
1546 { "-xperiodic", "periodicUpdates", XrmoptionNoArg, "False" },
1547 { "-clockFont", "clockFont", XrmoptionSepArg, NULL },
1548 { "-coordFont", "coordFont", XrmoptionSepArg, NULL },
1549 { "-font", "font", XrmoptionSepArg, NULL },
1550 { "-ringBellAfterMoves", "ringBellAfterMoves", XrmoptionSepArg, NULL },
1551 { "-bell", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1552 { "-xbell", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1553 { "-movesound", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1554 { "-xmovesound", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1555 { "-autoCallFlag", "autoCallFlag", XrmoptionSepArg, NULL },
1556 { "-autoflag", "autoCallFlag", XrmoptionNoArg, "True" },
1557 { "-xautoflag", "autoCallFlag", XrmoptionNoArg, "False" },
1558 { "-autoFlipView", "autoFlipView", XrmoptionSepArg, NULL },
1559 { "-autoflip", "autoFlipView", XrmoptionNoArg, "True" },
1560 { "-xautoflip", "autoFlipView", XrmoptionNoArg, "False" },
1561 { "-autoObserve", "autoObserve", XrmoptionSepArg, NULL },
1562 { "-autobs", "autoObserve", XrmoptionNoArg, "True" },
1563 { "-xautobs", "autoObserve", XrmoptionNoArg, "False" },
1564 { "-autoComment", "autoComment", XrmoptionSepArg, NULL },
1565 { "-autocomm", "autoComment", XrmoptionNoArg, "True" },
1566 { "-xautocomm", "autoComment", XrmoptionNoArg, "False" },
1567 { "-getMoveList", "getMoveList", XrmoptionSepArg, NULL },
1568 { "-moves", "getMoveList", XrmoptionNoArg, "True" },
1569 { "-xmoves", "getMoveList", XrmoptionNoArg, "False" },
1571 { "-highlightDragging", "highlightDragging", XrmoptionSepArg, NULL },
1572 { "-highdrag", "highlightDragging", XrmoptionNoArg, "True" },
1573 { "-xhighdrag", "highlightDragging", XrmoptionNoArg, "False" },
1575 { "-highlightLastMove", "highlightLastMove", XrmoptionSepArg, NULL },
1576 { "-highlight", "highlightLastMove", XrmoptionNoArg, "True" },
1577 { "-xhighlight", "highlightLastMove", XrmoptionNoArg, "False" },
1578 { "-premove", "premove", XrmoptionSepArg, NULL },
1579 { "-pre", "premove", XrmoptionNoArg, "True" },
1580 { "-xpre", "premove", XrmoptionNoArg, "False" },
1581 { "-testLegality", "testLegality", XrmoptionSepArg, NULL },
1582 { "-legal", "testLegality", XrmoptionNoArg, "True" },
1583 { "-xlegal", "testLegality", XrmoptionNoArg, "False" },
1584 { "-flipView", "flipView", XrmoptionSepArg, NULL },
1585 { "-flip", "flipView", XrmoptionNoArg, "True" },
1586 { "-xflip", "flipView", XrmoptionNoArg, "False" },
1587 { "-cmail", "cmailGameName", XrmoptionSepArg, NULL },
1588 { "-alwaysPromoteToQueen", "alwaysPromoteToQueen",
1589 XrmoptionSepArg, NULL },
1590 { "-queen", "alwaysPromoteToQueen", XrmoptionNoArg, "True" },
1591 { "-xqueen", "alwaysPromoteToQueen", XrmoptionNoArg, "False" },
1592 { "-oldSaveStyle", "oldSaveStyle", XrmoptionSepArg, NULL },
1593 { "-oldsave", "oldSaveStyle", XrmoptionNoArg, "True" },
1594 { "-xoldsave", "oldSaveStyle", XrmoptionNoArg, "False" },
1595 { "-quietPlay", "quietPlay", XrmoptionSepArg, NULL },
1596 { "-quiet", "quietPlay", XrmoptionNoArg, "True" },
1597 { "-xquiet", "quietPlay", XrmoptionNoArg, "False" },
1598 { "-titleInWindow", "titleInWindow", XrmoptionSepArg, NULL },
1599 { "-title", "titleInWindow", XrmoptionNoArg, "True" },
1600 { "-xtitle", "titleInWindow", XrmoptionNoArg, "False" },
1602 { "-zippyTalk", "zippyTalk", XrmoptionSepArg, NULL },
1603 { "-zt", "zippyTalk", XrmoptionNoArg, "True" },
1604 { "-xzt", "zippyTalk", XrmoptionNoArg, "False" },
1605 { "-zippyPlay", "zippyPlay", XrmoptionSepArg, NULL },
1606 { "-zp", "zippyPlay", XrmoptionNoArg, "True" },
1607 { "-xzp", "zippyPlay", XrmoptionNoArg, "False" },
1608 { "-zippyLines", "zippyLines", XrmoptionSepArg, NULL },
1609 { "-zippyPinhead", "zippyPinhead", XrmoptionSepArg, NULL },
1610 { "-zippyPassword", "zippyPassword", XrmoptionSepArg, NULL },
1611 { "-zippyPassword2", "zippyPassword2", XrmoptionSepArg, NULL },
1612 { "-zippyWrongPassword", "zippyWrongPassword", XrmoptionSepArg, NULL },
1613 { "-zippyAcceptOnly", "zippyAcceptOnly", XrmoptionSepArg, NULL },
1614 { "-zippyUseI", "zippyUseI", XrmoptionSepArg, NULL },
1615 { "-zui", "zippyUseI", XrmoptionNoArg, "True" },
1616 { "-xzui", "zippyUseI", XrmoptionNoArg, "False" },
1617 { "-zippyBughouse", "zippyBughouse", XrmoptionSepArg, NULL },
1618 { "-zippyNoplayCrafty", "zippyNoplayCrafty", XrmoptionSepArg, NULL },
1619 { "-znc", "zippyNoplayCrafty", XrmoptionNoArg, "True" },
1620 { "-xznc", "zippyNoplayCrafty", XrmoptionNoArg, "False" },
1621 { "-zippyGameEnd", "zippyGameEnd", XrmoptionSepArg, NULL },
1622 { "-zippyGameStart", "zippyGameStart", XrmoptionSepArg, NULL },
1623 { "-zippyAdjourn", "zippyAdjourn", XrmoptionSepArg, NULL },
1624 { "-zadj", "zippyAdjourn", XrmoptionNoArg, "True" },
1625 { "-xzadj", "zippyAdjourn", XrmoptionNoArg, "False" },
1626 { "-zippyAbort", "zippyAbort", XrmoptionSepArg, NULL },
1627 { "-zab", "zippyAbort", XrmoptionNoArg, "True" },
1628 { "-xzab", "zippyAbort", XrmoptionNoArg, "False" },
1629 { "-zippyVariants", "zippyVariants", XrmoptionSepArg, NULL },
1630 { "-zippyMaxGames", "zippyMaxGames", XrmoptionSepArg, NULL },
1631 { "-zippyReplayTimeout", "zippyReplayTimeout", XrmoptionSepArg, NULL },
1632 { "-zippyShortGame", "zippyShortGame", XrmoptionSepArg, NULL },
1634 { "-flashCount", "flashCount", XrmoptionSepArg, NULL },
1635 { "-flash", "flashCount", XrmoptionNoArg, "3" },
1636 { "-xflash", "flashCount", XrmoptionNoArg, "0" },
1637 { "-flashRate", "flashRate", XrmoptionSepArg, NULL },
1638 { "-pixmapDirectory", "pixmapDirectory", XrmoptionSepArg, NULL },
1639 { "-msLoginDelay", "msLoginDelay", XrmoptionSepArg, NULL },
1640 { "-pixmap", "pixmapDirectory", XrmoptionSepArg, NULL },
1641 { "-colorizeMessages", "colorizeMessages", XrmoptionSepArg, NULL },
1642 { "-colorize", "colorizeMessages", XrmoptionNoArg, "True" },
1643 { "-xcolorize", "colorizeMessages", XrmoptionNoArg, "False" },
1644 { "-colorShout", "colorShout", XrmoptionSepArg, NULL },
1645 { "-colorSShout", "colorSShout", XrmoptionSepArg, NULL },
1646 { "-colorCShout", "colorSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1647 { "-colorChannel1", "colorChannel1", XrmoptionSepArg, NULL },
1648 { "-colorChannel", "colorChannel", XrmoptionSepArg, NULL },
1649 { "-colorKibitz", "colorKibitz", XrmoptionSepArg, NULL },
1650 { "-colorTell", "colorTell", XrmoptionSepArg, NULL },
1651 { "-colorChallenge", "colorChallenge", XrmoptionSepArg, NULL },
1652 { "-colorRequest", "colorRequest", XrmoptionSepArg, NULL },
1653 { "-colorSeek", "colorSeek", XrmoptionSepArg, NULL },
1654 { "-colorNormal", "colorNormal", XrmoptionSepArg, NULL },
1655 { "-soundProgram", "soundProgram", XrmoptionSepArg, NULL },
1656 { "-soundShout", "soundShout", XrmoptionSepArg, NULL },
1657 { "-soundSShout", "soundSShout", XrmoptionSepArg, NULL },
1658 { "-soundCShout", "soundSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1659 { "-soundChannel1", "soundChannel1", XrmoptionSepArg, NULL },
1660 { "-soundChannel", "soundChannel", XrmoptionSepArg, NULL },
1661 { "-soundKibitz", "soundKibitz", XrmoptionSepArg, NULL },
1662 { "-soundTell", "soundTell", XrmoptionSepArg, NULL },
1663 { "-soundChallenge", "soundChallenge", XrmoptionSepArg, NULL },
1664 { "-soundRequest", "soundRequest", XrmoptionSepArg, NULL },
1665 { "-soundSeek", "soundSeek", XrmoptionSepArg, NULL },
1666 { "-soundMove", "soundMove", XrmoptionSepArg, NULL },
1667 { "-soundIcsWin", "soundIcsWin", XrmoptionSepArg, NULL },
1668 { "-soundIcsLoss", "soundIcsLoss", XrmoptionSepArg, NULL },
1669 { "-soundIcsDraw", "soundIcsDraw", XrmoptionSepArg, NULL },
1670 { "-soundIcsUnfinished", "soundIcsUnfinished", XrmoptionSepArg, NULL },
1671 { "-soundIcsAlarm", "soundIcsAlarm", XrmoptionSepArg, NULL },
1672 { "-reuseFirst", "reuseFirst", XrmoptionSepArg, NULL },
1673 { "-reuseChessPrograms", "reuseFirst", XrmoptionSepArg, NULL }, /*compat*/
1674 { "-reuse", "reuseFirst", XrmoptionNoArg, "True" },
1675 { "-xreuse", "reuseFirst", XrmoptionNoArg, "False" },
1676 { "-reuseSecond", "reuseSecond", XrmoptionSepArg, NULL },
1677 { "-reuse2", "reuseSecond", XrmoptionNoArg, "True" },
1678 { "-xreuse2", "reuseSecond", XrmoptionNoArg, "False" },
1679 { "-animateMoving", "animateMoving", XrmoptionSepArg, NULL },
1680 { "-animate", "animateMoving", XrmoptionNoArg, "True" },
1681 { "-xanimate", "animateMoving", XrmoptionNoArg, "False" },
1682 { "-animateDragging", "animateDragging", XrmoptionSepArg, NULL },
1683 { "-drag", "animateDragging", XrmoptionNoArg, "True" },
1684 { "-xdrag", "animateDragging", XrmoptionNoArg, "False" },
1685 { "-animateSpeed", "animateSpeed", XrmoptionSepArg, NULL },
1686 { "-popupExitMessage", "popupExitMessage", XrmoptionSepArg, NULL },
1687 { "-exit", "popupExitMessage", XrmoptionNoArg, "True" },
1688 { "-xexit", "popupExitMessage", XrmoptionNoArg, "False" },
1689 { "-popupMoveErrors", "popupMoveErrors", XrmoptionSepArg, NULL },
1690 { "-popup", "popupMoveErrors", XrmoptionNoArg, "True" },
1691 { "-xpopup", "popupMoveErrors", XrmoptionNoArg, "False" },
1692 { "-fontSizeTolerance", "fontSizeTolerance", XrmoptionSepArg, NULL },
1693 { "-initialMode", "initialMode", XrmoptionSepArg, NULL },
1694 { "-mode", "initialMode", XrmoptionSepArg, NULL },
1695 { "-variant", "variant", XrmoptionSepArg, NULL },
1696 { "-firstProtocolVersion", "firstProtocolVersion", XrmoptionSepArg, NULL },
1697 { "-secondProtocolVersion","secondProtocolVersion",XrmoptionSepArg, NULL },
1698 { "-showButtonBar", "showButtonBar", XrmoptionSepArg, NULL },
1699 { "-buttons", "showButtonBar", XrmoptionNoArg, "True" },
1700 { "-xbuttons", "showButtonBar", XrmoptionNoArg, "False" },
1701 { "-lowTimeWarningColor", "lowTimeWarningColor", XrmoptionSepArg, NULL },
1702 { "-lowTimeWarning", "lowTimeWarning", XrmoptionSepArg, NULL },
1703 /* [AS,HR] New features */
1704 { "-firstScoreAbs", "firstScoreAbs", XrmoptionSepArg, NULL },
1705 { "-secondScoreAbs", "secondScoreAbs", XrmoptionSepArg, NULL },
1706 { "-pgnExtendedInfo", "pgnExtendedInfo", XrmoptionSepArg, NULL },
1707 { "-hideThinkingFromHuman", "hideThinkingFromHuman", XrmoptionSepArg, NULL },
1708 { "-adjudicateLossThreshold", "adjudicateLossThreshold", XrmoptionSepArg, NULL },
1709 { "-adjudicateDrawMoves", "adjudicateDrawMoves", XrmoptionSepArg, NULL },
1710 { "-pgnEventHeader", "pgnEventHeader", XrmoptionSepArg, NULL },
1711 { "-firstIsUCI", "firstIsUCI", XrmoptionSepArg, NULL },
1712 { "-secondIsUCI", "secondIsUCI", XrmoptionSepArg, NULL },
1713 { "-fUCI", "firstIsUCI", XrmoptionNoArg, "True" },
1714 { "-sUCI", "secondIsUCI", XrmoptionNoArg, "True" },
1715 { "-firstHasOwnBookUCI", "firstHasOwnBookUCI", XrmoptionSepArg, NULL },
1716 { "-secondHasOwnBookUCI", "secondHasOwnBookUCI", XrmoptionSepArg, NULL },
1717 { "-fNoOwnBookUCI", "firstHasOwnBookUCI", XrmoptionNoArg, "False" },
1718 { "-sNoOwnBookUCI", "secondHasOwnBookUCI", XrmoptionNoArg, "False" },
1719 { "-firstXBook", "firstHasOwnBookUCI", XrmoptionNoArg, "False" },
1720 { "-secondXBook", "secondHasOwnBookUCI", XrmoptionNoArg, "False" },
1721 { "-polyglotDir", "polyglotDir", XrmoptionSepArg, NULL },
1722 { "-usePolyglotBook", "usePolyglotBook", XrmoptionSepArg, NULL },
1723 { "-polyglotBook", "polyglotBook", XrmoptionSepArg, NULL },
1724 { "-defaultHashSize", "defaultHashSize", XrmoptionSepArg, NULL },
1725 { "-defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XrmoptionSepArg, NULL },
1726 { "-defaultPathEGTB", "defaultPathEGTB", XrmoptionSepArg, NULL },
1727 { "-defaultFrcPosition", "defaultFrcPosition", XrmoptionSepArg, NULL },
1728 { "-gameListTags", "gameListTags", XrmoptionSepArg, NULL },
1729 // [HGM] I am sure AS added many more options, but we have to fish them out, from the list in winboard.c
1731 /* [HGM,HR] User-selectable board size */
1732 { "-boardWidth", "boardWidth", XrmoptionSepArg, NULL },
1733 { "-boardHeight", "boardHeight", XrmoptionSepArg, NULL },
1734 { "-matchPause", "matchPause", XrmoptionSepArg, NULL },
1736 /* [HGM] new arguments of 4.3.xx. All except first three are back-end options, which should work immediately */
1737 { "-holdingsSize", "holdingsSize", XrmoptionSepArg, NULL }, // requires extensive front-end changes to work
1738 { "-flipBlack", "flipBlack", XrmoptionSepArg, NULL }, // requires front-end changes to work
1739 { "-allWhite", "allWhite", XrmoptionSepArg, NULL }, // requires front-end changes to work
1740 { "-pieceToCharTable", "pieceToCharTable", XrmoptionSepArg, NULL },
1741 { "-alphaRank", "alphaRank", XrmoptionSepArg, NULL },
1742 { "-testClaims", "testClaims", XrmoptionSepArg, NULL },
1743 { "-checkMates", "checkMates", XrmoptionSepArg, NULL },
1744 { "-materialDraws", "materialDraws", XrmoptionSepArg, NULL },
1745 { "-trivialDraws", "trivialDraws", XrmoptionSepArg, NULL },
1746 { "-ruleMoves", "ruleMoves", XrmoptionSepArg, NULL },
1747 { "-repeatsToDraw", "repeatsToDraw", XrmoptionSepArg, NULL },
1748 { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL },
1749 { "-userName", "userName", XrmoptionSepArg, NULL },
1750 { "-autoKibitz", "autoKibitz", XrmoptionNoArg, "True" },
1751 { "-firstTimeOdds", "firstTimeOdds", XrmoptionSepArg, NULL },
1752 { "-secondTimeOdds", "secondTimeOdds", XrmoptionSepArg, NULL },
1753 { "-timeOddsMode", "timeOddsMode", XrmoptionSepArg, NULL },
1754 { "-firstAccumulateTC", "firstAccumulateTC", XrmoptionSepArg, NULL },
1755 { "-secondAccumulateTC", "secondAccumulateTC", XrmoptionSepArg, NULL },
1756 { "-firstNPS", "firstNPS", XrmoptionSepArg, NULL },
1757 { "-secondNPS", "secondNPS", XrmoptionSepArg, NULL },
1758 { "-serverMoves", "serverMoves", XrmoptionSepArg, NULL },
1759 { "-serverPause", "serverPause", XrmoptionSepArg, NULL },
1760 { "-suppressLoadMoves", "suppressLoadMoves", XrmoptionSepArg, NULL },
1761 { "-egtFormats", "egtFormats", XrmoptionSepArg, NULL },
1762 { "-userName", "userName", XrmoptionSepArg, NULL },
1763 { "-smpCores", "smpCores", XrmoptionSepArg, NULL },
1764 { "-sameColorGames", "sameColorGames", XrmoptionSepArg, NULL },
1765 { "-rewindIndex", "rewindIndex", XrmoptionSepArg, NULL },
1766 { "-niceEngines", "niceEngines", XrmoptionSepArg, NULL },
1767 { "-delayBeforeQuit", "delayBeforeQuit", XrmoptionSepArg, NULL },
1768 { "-delayAfterQuit", "delayAfterQuit", XrmoptionSepArg, NULL },
1769 { "-nameOfDebugFile", "nameOfDebugFile", XrmoptionSepArg, NULL },
1770 { "-debugFile", "nameOfDebugFile", XrmoptionSepArg, NULL },
1771 { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL },
1772 { "-noGUI", "noGUI", XrmoptionNoArg, "True" },
1773 { "-firstOptions", "firstOptions", XrmoptionSepArg, NULL },
1774 { "-secondOptions", "secondOptions", XrmoptionSepArg, NULL },
1775 { "-firstNeedsNoncompliantFEN", "firstNeedsNoncompliantFEN", XrmoptionSepArg, NULL },
1776 { "-secondNeedsNoncompliantFEN", "secondNeedsNoncompliantFEN", XrmoptionSepArg, NULL },
1777 { "-keepAlive", "keepAlive", XrmoptionSepArg, NULL },
1778 { "-forceIllegalMoves", "forceIllegalMoves", XrmoptionNoArg, "True" },
1782 XtActionsRec boardActions[] = {
1783 { "DrawPosition", DrawPositionProc },
1784 { "HandleUserMove", HandleUserMove },
1785 { "AnimateUserMove", AnimateUserMove },
1786 { "FileNameAction", FileNameAction },
1787 { "AskQuestionProc", AskQuestionProc },
1788 { "AskQuestionReplyAction", AskQuestionReplyAction },
1789 { "PieceMenuPopup", PieceMenuPopup },
1790 { "WhiteClock", WhiteClock },
1791 { "BlackClock", BlackClock },
1792 { "Iconify", Iconify },
1793 { "ResetProc", ResetProc },
1794 { "LoadGameProc", LoadGameProc },
1795 { "LoadNextGameProc", LoadNextGameProc },
1796 { "LoadPrevGameProc", LoadPrevGameProc },
1797 { "LoadSelectedProc", LoadSelectedProc },
1798 { "ReloadGameProc", ReloadGameProc },
1799 { "LoadPositionProc", LoadPositionProc },
1800 { "LoadNextPositionProc", LoadNextPositionProc },
1801 { "LoadPrevPositionProc", LoadPrevPositionProc },
1802 { "ReloadPositionProc", ReloadPositionProc },
1803 { "CopyPositionProc", CopyPositionProc },
1804 { "PastePositionProc", PastePositionProc },
1805 { "CopyGameProc", CopyGameProc },
1806 { "PasteGameProc", PasteGameProc },
1807 { "SaveGameProc", SaveGameProc },
1808 { "SavePositionProc", SavePositionProc },
1809 { "MailMoveProc", MailMoveProc },
1810 { "ReloadCmailMsgProc", ReloadCmailMsgProc },
1811 { "QuitProc", QuitProc },
1812 { "MachineWhiteProc", MachineWhiteProc },
1813 { "MachineBlackProc", MachineBlackProc },
1814 { "AnalysisModeProc", AnalyzeModeProc },
1815 { "AnalyzeFileProc", AnalyzeFileProc },
1816 { "TwoMachinesProc", TwoMachinesProc },
1817 { "IcsClientProc", IcsClientProc },
1818 { "EditGameProc", EditGameProc },
1819 { "EditPositionProc", EditPositionProc },
1820 { "TrainingProc", EditPositionProc },
1821 { "EngineOutputProc", EngineOutputProc}, // [HGM] Winboard_x engine-output window
1822 { "ShowGameListProc", ShowGameListProc },
1823 { "ShowMoveListProc", HistoryShowProc},
1824 { "EditTagsProc", EditCommentProc },
1825 { "EditCommentProc", EditCommentProc },
1826 { "IcsAlarmProc", IcsAlarmProc },
1827 { "IcsInputBoxProc", IcsInputBoxProc },
1828 { "PauseProc", PauseProc },
1829 { "AcceptProc", AcceptProc },
1830 { "DeclineProc", DeclineProc },
1831 { "RematchProc", RematchProc },
1832 { "CallFlagProc", CallFlagProc },
1833 { "DrawProc", DrawProc },
1834 { "AdjournProc", AdjournProc },
1835 { "AbortProc", AbortProc },
1836 { "ResignProc", ResignProc },
1837 { "AdjuWhiteProc", AdjuWhiteProc },
1838 { "AdjuBlackProc", AdjuBlackProc },
1839 { "AdjuDrawProc", AdjuDrawProc },
1840 { "EnterKeyProc", EnterKeyProc },
1841 { "StopObservingProc", StopObservingProc },
1842 { "StopExaminingProc", StopExaminingProc },
1843 { "BackwardProc", BackwardProc },
1844 { "ForwardProc", ForwardProc },
1845 { "ToStartProc", ToStartProc },
1846 { "ToEndProc", ToEndProc },
1847 { "RevertProc", RevertProc },
1848 { "TruncateGameProc", TruncateGameProc },
1849 { "MoveNowProc", MoveNowProc },
1850 { "RetractMoveProc", RetractMoveProc },
1851 { "AlwaysQueenProc", AlwaysQueenProc },
1852 { "AnimateDraggingProc", AnimateDraggingProc },
1853 { "AnimateMovingProc", AnimateMovingProc },
1854 { "AutoflagProc", AutoflagProc },
1855 { "AutoflipProc", AutoflipProc },
1856 { "AutobsProc", AutobsProc },
1857 { "AutoraiseProc", AutoraiseProc },
1858 { "AutosaveProc", AutosaveProc },
1859 { "BlindfoldProc", BlindfoldProc },
1860 { "FlashMovesProc", FlashMovesProc },
1861 { "FlipViewProc", FlipViewProc },
1862 { "GetMoveListProc", GetMoveListProc },
1864 { "HighlightDraggingProc", HighlightDraggingProc },
1866 { "HighlightLastMoveProc", HighlightLastMoveProc },
1867 { "IcsAlarmProc", IcsAlarmProc },
1868 { "MoveSoundProc", MoveSoundProc },
1869 { "OldSaveStyleProc", OldSaveStyleProc },
1870 { "PeriodicUpdatesProc", PeriodicUpdatesProc },
1871 { "PonderNextMoveProc", PonderNextMoveProc },
1872 { "PopupExitMessageProc", PopupExitMessageProc },
1873 { "PopupMoveErrorsProc", PopupMoveErrorsProc },
1874 { "PremoveProc", PremoveProc },
1875 { "QuietPlayProc", QuietPlayProc },
1876 { "ShowCoordsProc", ShowCoordsProc },
1877 { "ShowThinkingProc", ShowThinkingProc },
1878 { "HideThinkingProc", HideThinkingProc },
1879 { "TestLegalityProc", TestLegalityProc },
1880 { "InfoProc", InfoProc },
1881 { "ManProc", ManProc },
1882 { "HintProc", HintProc },
1883 { "BookProc", BookProc },
1884 { "AboutGameProc", AboutGameProc },
1885 { "AboutProc", AboutProc },
1886 { "DebugProc", DebugProc },
1887 { "NothingProc", NothingProc },
1888 { "CommentPopDown", (XtActionProc) CommentPopDown },
1889 { "EditCommentPopDown", (XtActionProc) EditCommentPopDown },
1890 { "TagsPopDown", (XtActionProc) TagsPopDown },
1891 { "ErrorPopDown", (XtActionProc) ErrorPopDown },
1892 { "ICSInputBoxPopDown", (XtActionProc) ICSInputBoxPopDown },
1893 { "AnalysisPopDown", (XtActionProc) AnalysisPopDown },
1894 { "FileNamePopDown", (XtActionProc) FileNamePopDown },
1895 { "AskQuestionPopDown", (XtActionProc) AskQuestionPopDown },
1896 { "GameListPopDown", (XtActionProc) GameListPopDown },
1897 { "PromotionPopDown", (XtActionProc) PromotionPopDown },
1898 { "HistoryPopDown", (XtActionProc) HistoryPopDown },
1899 { "EngineOutputPopDown", (XtActionProc) EngineOutputPopDown },
1900 { "ShufflePopDown", (XtActionProc) ShufflePopDown },
1901 { "EnginePopDown", (XtActionProc) EnginePopDown },
1902 { "UciPopDown", (XtActionProc) UciPopDown },
1903 { "TimeControlPopDown", (XtActionProc) TimeControlPopDown },
1904 { "NewVariantPopDown", (XtActionProc) NewVariantPopDown },
1905 { "SettingsPopDown", (XtActionProc) SettingsPopDown },
1908 char globalTranslations[] =
1909 ":<Key>R: ResignProc() \n \
1910 :<Key>r: ResetProc() \n \
1911 :<Key>g: LoadGameProc() \n \
1912 :<Key>N: LoadNextGameProc() \n \
1913 :<Key>P: LoadPrevGameProc() \n \
1914 :<Key>Q: QuitProc() \n \
1915 :<Key>F: ToEndProc() \n \
1916 :<Key>f: ForwardProc() \n \
1917 :<Key>B: ToStartProc() \n \
1918 :<Key>b: BackwardProc() \n \
1919 :<Key>p: PauseProc() \n \
1920 :<Key>d: DrawProc() \n \
1921 :<Key>t: CallFlagProc() \n \
1922 :<Key>i: Iconify() \n \
1923 :<Key>c: Iconify() \n \
1924 :<Key>v: FlipViewProc() \n \
1925 <KeyDown>Control_L: BackwardProc() \n \
1926 <KeyUp>Control_L: ForwardProc() \n \
1927 <KeyDown>Control_R: BackwardProc() \n \
1928 <KeyUp>Control_R: ForwardProc() \n \
1929 Shift<Key>1: AskQuestionProc(\"Direct command\",\
1930 \"Send to chess program:\",,1) \n \
1931 Shift<Key>2: AskQuestionProc(\"Direct command\",\
1932 \"Send to second chess program:\",,2) \n";
1934 char boardTranslations[] =
1935 "<Btn1Down>: HandleUserMove() \n \
1936 <Btn1Up>: HandleUserMove() \n \
1937 <Btn1Motion>: AnimateUserMove() \n \
1938 Shift<Btn2Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD)\
1939 PieceMenuPopup(menuB) \n \
1940 Any<Btn2Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD) \
1941 PieceMenuPopup(menuW) \n \
1942 Shift<Btn3Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD)\
1943 PieceMenuPopup(menuW) \n \
1944 Any<Btn3Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD) \
1945 PieceMenuPopup(menuB) \n";
1947 char whiteTranslations[] = "<BtnDown>: WhiteClock()\n";
1948 char blackTranslations[] = "<BtnDown>: BlackClock()\n";
1950 char ICSInputTranslations[] =
1951 "<Key>Return: EnterKeyProc() \n";
1953 String xboardResources[] = {
1954 "*fileName*value.translations: #override\\n <Key>Return: FileNameAction()",
1955 "*question*value.translations: #override\\n <Key>Return: AskQuestionReplyAction()",
1956 "*errorpopup*translations: #override\\n <Key>Return: ErrorPopDown()",
1961 /* Max possible square size */
1962 #define MAXSQSIZE 256
1964 static int xpm_avail[MAXSQSIZE];
1966 #ifdef HAVE_DIR_STRUCT
1968 /* Extract piece size from filename */
1970 xpm_getsize(name, len, ext)
1981 if ((p=strchr(name, '.')) == NULL ||
1982 StrCaseCmp(p+1, ext) != 0)
1988 while (*p && isdigit(*p))
1995 /* Setup xpm_avail */
1997 xpm_getavail(dirname, ext)
2005 for (i=0; i<MAXSQSIZE; ++i)
2008 if (appData.debugMode)
2009 fprintf(stderr, "XPM dir:%s:ext:%s:\n", dirname, ext);
2011 dir = opendir(dirname);
2014 fprintf(stderr, _("%s: Can't access XPM directory %s\n"),
2015 programName, dirname);
2019 while ((ent=readdir(dir)) != NULL) {
2020 i = xpm_getsize(ent->d_name, NAMLEN(ent), ext);
2021 if (i > 0 && i < MAXSQSIZE)
2031 xpm_print_avail(fp, ext)
2037 fprintf(fp, _("Available `%s' sizes:\n"), ext);
2038 for (i=1; i<MAXSQSIZE; ++i) {
2044 /* Return XPM piecesize closest to size */
2046 xpm_closest_to(dirname, size, ext)
2052 int sm_diff = MAXSQSIZE;
2056 xpm_getavail(dirname, ext);
2058 if (appData.debugMode)
2059 xpm_print_avail(stderr, ext);
2061 for (i=1; i<MAXSQSIZE; ++i) {
2064 diff = (diff<0) ? -diff : diff;
2065 if (diff < sm_diff) {
2073 fprintf(stderr, _("Error: No `%s' files!\n"), ext);
2079 #else /* !HAVE_DIR_STRUCT */
2080 /* If we are on a system without a DIR struct, we can't
2081 read the directory, so we can't collect a list of
2082 filenames, etc., so we can't do any size-fitting. */
2084 xpm_closest_to(dirname, size, ext)
2089 fprintf(stderr, _("\
2090 Warning: No DIR structure found on this system --\n\
2091 Unable to autosize for XPM/XIM pieces.\n\
2092 Please report this error to frankm@hiwaay.net.\n\
2093 Include system type & operating system in message.\n"));
2096 #endif /* HAVE_DIR_STRUCT */
2098 static char *cnames[9] = { "black", "red", "green", "yellow", "blue",
2099 "magenta", "cyan", "white" };
2103 TextColors textColors[(int)NColorClasses];
2105 /* String is: "fg, bg, attr". Which is 0, 1, 2 */
2107 parse_color(str, which)
2111 char *p, buf[100], *d;
2114 if (strlen(str) > 99) /* watch bounds on buf */
2119 for (i=0; i<which; ++i) {
2126 /* Could be looking at something like:
2128 .. in which case we want to stop on a comma also */
2129 while (*p && *p != ',' && !isalpha(*p) && !isdigit(*p))
2133 return -1; /* Use default for empty field */
2136 if (which == 2 || isdigit(*p))
2139 while (*p && isalpha(*p))
2144 for (i=0; i<8; ++i) {
2145 if (!StrCaseCmp(buf, cnames[i]))
2146 return which? (i+40) : (i+30);
2148 if (!StrCaseCmp(buf, "default")) return -1;
2150 fprintf(stderr, _("%s: unrecognized color %s\n"), programName, buf);
2155 parse_cpair(cc, str)
2159 if ((textColors[(int)cc].fg=parse_color(str, 0)) == -2) {
2160 fprintf(stderr, _("%s: can't parse foreground color in `%s'\n"),
2165 /* bg and attr are optional */
2166 textColors[(int)cc].bg = parse_color(str, 1);
2167 if ((textColors[(int)cc].attr = parse_color(str, 2)) < 0) {
2168 textColors[(int)cc].attr = 0;
2174 /* Arrange to catch delete-window events */
2175 Atom wm_delete_window;
2177 CatchDeleteWindow(Widget w, String procname)
2180 XSetWMProtocols(xDisplay, XtWindow(w), &wm_delete_window, 1);
2181 snprintf(buf, sizeof(buf), "<Message>WM_PROTOCOLS: %s() \n", procname);
2182 XtAugmentTranslations(w, XtParseTranslationTable(buf));
2189 XtSetArg(args[0], XtNiconic, False);
2190 XtSetValues(shellWidget, args, 1);
2192 XtPopup(shellWidget, XtGrabNone); /* Raise if lowered */
2196 // eventually, all layout determining code should go into a subroutine, but until then IDSIZE remains undefined
2198 #define BoardSize int
2199 void InitDrawingSizes(BoardSize boardSize, int flags)
2200 { // [HGM] resize is functional now, but for board format changes only (nr of ranks, files)
2201 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
2203 XtGeometryResult gres;
2206 if(!formWidget) return;
2209 * Enable shell resizing.
2211 shellArgs[0].value = (XtArgVal) &w;
2212 shellArgs[1].value = (XtArgVal) &h;
2213 XtGetValues(shellWidget, shellArgs, 2);
2215 shellArgs[4].value = 2*w; shellArgs[2].value = 10;
2216 shellArgs[5].value = 2*h; shellArgs[3].value = 10;
2217 XtSetValues(shellWidget, &shellArgs[2], 4);
2219 XtSetArg(args[0], XtNdefaultDistance, &sep);
2220 XtGetValues(formWidget, args, 1);
2222 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2223 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2226 XtSetArg(args[0], XtNwidth, boardWidth);
2227 XtSetArg(args[1], XtNheight, boardHeight);
2228 XtSetValues(boardWidget, args, 2);
2230 timerWidth = (boardWidth - sep) / 2;
2231 XtSetArg(args[0], XtNwidth, timerWidth);
2232 XtSetValues(whiteTimerWidget, args, 1);
2233 XtSetValues(blackTimerWidget, args, 1);
2235 XawFormDoLayout(formWidget, False);
2237 if (appData.titleInWindow) {
2239 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2240 XtSetArg(args[i], XtNheight, &h); i++;
2241 XtGetValues(titleWidget, args, i);
2243 w = boardWidth - 2*bor;
2245 XtSetArg(args[0], XtNwidth, &w);
2246 XtGetValues(menuBarWidget, args, 1);
2247 w = boardWidth - w - sep - 2*bor - 2; // WIDTH_FUDGE
2250 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
2251 if (gres != XtGeometryYes && appData.debugMode) {
2253 _("%s: titleWidget geometry error %d %d %d %d %d\n"),
2254 programName, gres, w, h, wr, hr);
2258 XawFormDoLayout(formWidget, True);
2261 * Inhibit shell resizing.
2263 shellArgs[0].value = w = (XtArgVal) boardWidth + marginW;
2264 shellArgs[1].value = h = (XtArgVal) boardHeight + marginH;
2265 shellArgs[4].value = shellArgs[2].value = w;
2266 shellArgs[5].value = shellArgs[3].value = h;
2267 XtSetValues(shellWidget, &shellArgs[0], 6);
2269 // [HGM] pieces: tailor piece bitmaps to needs of specific variant
2272 for(i=0; i<4; i++) {
2274 for(p=0; p<=(int)WhiteKing; p++)
2275 xpmPieceBitmap[i][p] = xpmPieceBitmap2[i][p]; // defaults
2276 if(gameInfo.variant == VariantShogi) {
2277 xpmPieceBitmap[i][(int)WhiteCannon] = xpmPieceBitmap2[i][(int)WhiteKing+1];
2278 xpmPieceBitmap[i][(int)WhiteNightrider] = xpmPieceBitmap2[i][(int)WhiteKing+2];
2279 xpmPieceBitmap[i][(int)WhiteSilver] = xpmPieceBitmap2[i][(int)WhiteKing+3];
2280 xpmPieceBitmap[i][(int)WhiteGrasshopper] = xpmPieceBitmap2[i][(int)WhiteKing+4];
2281 xpmPieceBitmap[i][(int)WhiteQueen] = xpmPieceBitmap2[i][(int)WhiteLance];
2284 if(gameInfo.variant == VariantGothic) {
2285 xpmPieceBitmap[i][(int)WhiteMarshall] = xpmPieceBitmap2[i][(int)WhiteSilver];
2289 // [HGM] why are thee ximMasks used at all? the ximPieceBitmaps seem to be never used!
2290 for(p=0; p<=(int)WhiteKing; p++)
2291 ximMaskPm[p] = ximMaskPm2[p]; // defaults
2292 if(gameInfo.variant == VariantShogi) {
2293 ximMaskPm[(int)WhiteCannon] = ximMaskPm2[(int)WhiteKing+1];
2294 ximMaskPm[(int)WhiteNightrider] = ximMaskPm2[(int)WhiteKing+2];
2295 ximMaskPm[(int)WhiteSilver] = ximMaskPm2[(int)WhiteKing+3];
2296 ximMaskPm[(int)WhiteGrasshopper] = ximMaskPm2[(int)WhiteKing+4];
2297 ximMaskPm[(int)WhiteQueen] = ximMaskPm2[(int)WhiteLance];
2300 if(gameInfo.variant == VariantGothic) {
2301 ximMaskPm[(int)WhiteMarshall] = ximMaskPm2[(int)WhiteSilver];
2307 for(i=0; i<2; i++) {
2309 for(p=0; p<=(int)WhiteKing; p++)
2310 pieceBitmap[i][p] = pieceBitmap2[i][p]; // defaults
2311 if(gameInfo.variant == VariantShogi) {
2312 pieceBitmap[i][(int)WhiteCannon] = pieceBitmap2[i][(int)WhiteKing+1];
2313 pieceBitmap[i][(int)WhiteNightrider] = pieceBitmap2[i][(int)WhiteKing+2];
2314 pieceBitmap[i][(int)WhiteSilver] = pieceBitmap2[i][(int)WhiteKing+3];
2315 pieceBitmap[i][(int)WhiteGrasshopper] = pieceBitmap2[i][(int)WhiteKing+4];
2316 pieceBitmap[i][(int)WhiteQueen] = pieceBitmap2[i][(int)WhiteLance];
2319 if(gameInfo.variant == VariantGothic) {
2320 pieceBitmap[i][(int)WhiteMarshall] = pieceBitmap2[i][(int)WhiteSilver];
2331 void EscapeExpand(char *p, char *q)
2332 { // [HGM] initstring: routine to shape up string arguments
2333 while(*p++ = *q++) if(p[-1] == '\\')
2335 case 'n': p[-1] = '\n'; break;
2336 case 'r': p[-1] = '\r'; break;
2337 case 't': p[-1] = '\t'; break;
2338 case '\\': p[-1] = '\\'; break;
2339 case 0: *p = 0; return;
2340 default: p[-1] = q[-1]; break;
2349 int i, j, clockFontPxlSize, coordFontPxlSize, fontPxlSize;
2350 XSetWindowAttributes window_attributes;
2352 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
2353 XrmValue vFrom, vTo;
2354 XtGeometryResult gres;
2357 int forceMono = False;
2360 // [HGM] before anything else, expand any indirection files amongst options
2361 char *argvCopy[1000]; // 1000 seems enough
2362 char newArgs[10000]; // holds actual characters
2365 srandom(time(0)); // [HGM] book: make random truly random
2368 for(i=0; i<argc; i++) {
2369 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2370 //fprintf(stderr, "arg %s\n", argv[i]);
2371 if(argv[i][0] != '@') argvCopy[j++] = argv[i]; else {
2373 FILE *f = fopen(argv[i]+1, "rb");
2374 if(f == NULL) { fprintf(stderr, _("ignore %s\n"), argv[i]); continue; } // do not expand non-existing
2375 argvCopy[j++] = newArgs + k; // get ready for first argument from file
2376 while((c = fgetc(f)) != EOF) { // each line of file inserts 1 argument in the list
2378 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2379 newArgs[k++] = 0; // terminate current arg
2380 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2381 argvCopy[j++] = newArgs + k; // get ready for next
2383 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2397 setbuf(stdout, NULL);
2398 setbuf(stderr, NULL);
2401 programName = strrchr(argv[0], '/');
2402 if (programName == NULL)
2403 programName = argv[0];
2408 XtSetLanguageProc(NULL, NULL, NULL);
2409 bindtextdomain(PACKAGE, LOCALEDIR);
2410 textdomain(PACKAGE);
2414 XtAppInitialize(&appContext, "XBoard", shellOptions,
2415 XtNumber(shellOptions),
2416 &argc, argv, xboardResources, NULL, 0);
2418 { /* left over command line arguments, print out help and exit.
2419 * Use two columns to print help
2421 fprintf(stderr, _("%s: unrecognized argument %s\n"),
2422 programName, argv[1]);
2424 fprintf(stderr, "Recognized options:\n");
2425 for(i = 0; i < XtNumber(shellOptions); i++)
2427 /* print first column */
2428 j = fprintf(stderr, " %s%s", shellOptions[i].option,
2429 (shellOptions[i].argKind == XrmoptionSepArg
2431 /* print second column and end line */
2432 if (++i < XtNumber(shellOptions))
2434 fprintf(stderr, "%*c%s%s\n", 40 - j, ' ',
2435 shellOptions[i].option,
2436 (shellOptions[i].argKind == XrmoptionSepArg
2441 fprintf(stderr, "\n");
2448 if (p == NULL) p = "/tmp";
2449 i = strlen(p) + strlen("/.xboardXXXXXx.pgn") + 1;
2450 gameCopyFilename = (char*) malloc(i);
2451 gamePasteFilename = (char*) malloc(i);
2452 snprintf(gameCopyFilename,i, "%s/.xboard%05uc.pgn", p, getpid());
2453 snprintf(gamePasteFilename,i, "%s/.xboard%05up.pgn", p, getpid());
2455 XtGetApplicationResources(shellWidget, (XtPointer) &appData,
2456 clientResources, XtNumber(clientResources),
2459 { // [HGM] initstring: kludge to fix bad bug. expand '\n' characters in init string and computer string.
2460 static char buf[MSG_SIZ];
2461 EscapeExpand(buf, appData.initString);
2462 appData.initString = strdup(buf);
2463 EscapeExpand(buf, appData.secondInitString);
2464 appData.secondInitString = strdup(buf);
2465 EscapeExpand(buf, appData.firstComputerString);
2466 appData.firstComputerString = strdup(buf);
2467 EscapeExpand(buf, appData.secondComputerString);
2468 appData.secondComputerString = strdup(buf);
2471 if ((chessDir = (char *) getenv("CHESSDIR")) == NULL) {
2474 if (chdir(chessDir) != 0) {
2475 fprintf(stderr, _("%s: can't cd to CHESSDIR: "), programName);
2481 if (appData.debugMode && appData.nameOfDebugFile && strcmp(appData.nameOfDebugFile, "stderr")) {
2482 /* [DM] debug info to file [HGM] make the filename a command-line option, and allow it to remain stderr */
2483 if ((debugFP = fopen(appData.nameOfDebugFile, "w")) == NULL) {
2484 printf(_("Failed to open file '%s'\n"), appData.nameOfDebugFile);
2487 setbuf(debugFP, NULL);
2490 /* [HGM,HR] make sure board size is acceptable */
2491 if(appData.NrFiles > BOARD_SIZE ||
2492 appData.NrRanks > BOARD_SIZE )
2493 DisplayFatalError(_("Recompile with BOARD_SIZE > 12, to support this size"), 0, 2);
2496 /* This feature does not work; animation needs a rewrite */
2497 appData.highlightDragging = FALSE;
2501 xDisplay = XtDisplay(shellWidget);
2502 xScreen = DefaultScreen(xDisplay);
2503 wm_delete_window = XInternAtom(xDisplay, "WM_DELETE_WINDOW", True);
2505 gameInfo.variant = StringToVariant(appData.variant);
2506 InitPosition(FALSE);
2509 InitDrawingSizes(-1, 0); // [HGM] initsize: make this into a subroutine
2511 if (isdigit(appData.boardSize[0])) {
2512 i = sscanf(appData.boardSize, "%d,%d,%d,%d,%d,%d,%d", &squareSize,
2513 &lineGap, &clockFontPxlSize, &coordFontPxlSize,
2514 &fontPxlSize, &smallLayout, &tinyLayout);
2516 fprintf(stderr, _("%s: bad boardSize syntax %s\n"),
2517 programName, appData.boardSize);
2521 /* Find some defaults; use the nearest known size */
2522 SizeDefaults *szd, *nearest;
2523 int distance = 99999;
2524 nearest = szd = sizeDefaults;
2525 while (szd->name != NULL) {
2526 if (abs(szd->squareSize - squareSize) < distance) {
2528 distance = abs(szd->squareSize - squareSize);
2529 if (distance == 0) break;
2533 if (i < 2) lineGap = nearest->lineGap;
2534 if (i < 3) clockFontPxlSize = nearest->clockFontPxlSize;
2535 if (i < 4) coordFontPxlSize = nearest->coordFontPxlSize;
2536 if (i < 5) fontPxlSize = nearest->fontPxlSize;
2537 if (i < 6) smallLayout = nearest->smallLayout;
2538 if (i < 7) tinyLayout = nearest->tinyLayout;
2541 SizeDefaults *szd = sizeDefaults;
2542 if (*appData.boardSize == NULLCHAR) {
2543 while (DisplayWidth(xDisplay, xScreen) < szd->minScreenSize ||
2544 DisplayHeight(xDisplay, xScreen) < szd->minScreenSize) {
2547 if (szd->name == NULL) szd--;
2549 while (szd->name != NULL &&
2550 StrCaseCmp(szd->name, appData.boardSize) != 0) szd++;
2551 if (szd->name == NULL) {
2552 fprintf(stderr, _("%s: unrecognized boardSize name %s\n"),
2553 programName, appData.boardSize);
2557 squareSize = szd->squareSize;
2558 lineGap = szd->lineGap;
2559 clockFontPxlSize = szd->clockFontPxlSize;
2560 coordFontPxlSize = szd->coordFontPxlSize;
2561 fontPxlSize = szd->fontPxlSize;
2562 smallLayout = szd->smallLayout;
2563 tinyLayout = szd->tinyLayout;
2566 /* Now, using squareSize as a hint, find a good XPM/XIM set size */
2567 if (strlen(appData.pixmapDirectory) > 0) {
2568 p = ExpandPathName(appData.pixmapDirectory);
2570 fprintf(stderr, _("Error expanding path name \"%s\"\n"),
2571 appData.pixmapDirectory);
2574 if (appData.debugMode) {
2575 fprintf(stderr, _("\
2576 XBoard square size (hint): %d\n\
2577 %s fulldir:%s:\n"), squareSize, IMAGE_EXT, p);
2579 squareSize = xpm_closest_to(p, squareSize, IMAGE_EXT);
2580 if (appData.debugMode) {
2581 fprintf(stderr, _("Closest %s size: %d\n"), IMAGE_EXT, squareSize);
2585 /* [HR] height treated separately (hacked) */
2586 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2587 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2588 if (appData.showJail == 1) {
2589 /* Jail on top and bottom */
2590 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2591 XtSetArg(boardArgs[2], XtNheight,
2592 boardHeight + 2*(lineGap + squareSize));
2593 } else if (appData.showJail == 2) {
2595 XtSetArg(boardArgs[1], XtNwidth,
2596 boardWidth + 2*(lineGap + squareSize));
2597 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2600 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2601 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2605 * Determine what fonts to use.
2607 appData.clockFont = FindFont(appData.clockFont, clockFontPxlSize);
2608 clockFontID = XLoadFont(xDisplay, appData.clockFont);
2609 clockFontStruct = XQueryFont(xDisplay, clockFontID);
2610 appData.coordFont = FindFont(appData.coordFont, coordFontPxlSize);
2611 coordFontID = XLoadFont(xDisplay, appData.coordFont);
2612 coordFontStruct = XQueryFont(xDisplay, coordFontID);
2613 appData.font = FindFont(appData.font, fontPxlSize);
2614 countFontID = XLoadFont(xDisplay, appData.coordFont); // [HGM] holdings
2615 countFontStruct = XQueryFont(xDisplay, countFontID);
2616 // appData.font = FindFont(appData.font, fontPxlSize);
2618 xdb = XtDatabase(xDisplay);
2619 XrmPutStringResource(&xdb, "*font", appData.font);
2622 * Detect if there are not enough colors available and adapt.
2624 if (DefaultDepth(xDisplay, xScreen) <= 2) {
2625 appData.monoMode = True;
2628 if (!appData.monoMode) {
2629 vFrom.addr = (caddr_t) appData.lightSquareColor;
2630 vFrom.size = strlen(appData.lightSquareColor);
2631 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2632 if (vTo.addr == NULL) {
2633 appData.monoMode = True;
2636 lightSquareColor = *(Pixel *) vTo.addr;
2639 if (!appData.monoMode) {
2640 vFrom.addr = (caddr_t) appData.darkSquareColor;
2641 vFrom.size = strlen(appData.darkSquareColor);
2642 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2643 if (vTo.addr == NULL) {
2644 appData.monoMode = True;
2647 darkSquareColor = *(Pixel *) vTo.addr;
2650 if (!appData.monoMode) {
2651 vFrom.addr = (caddr_t) appData.whitePieceColor;
2652 vFrom.size = strlen(appData.whitePieceColor);
2653 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2654 if (vTo.addr == NULL) {
2655 appData.monoMode = True;
2658 whitePieceColor = *(Pixel *) vTo.addr;
2661 if (!appData.monoMode) {
2662 vFrom.addr = (caddr_t) appData.blackPieceColor;
2663 vFrom.size = strlen(appData.blackPieceColor);
2664 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2665 if (vTo.addr == NULL) {
2666 appData.monoMode = True;
2669 blackPieceColor = *(Pixel *) vTo.addr;
2673 if (!appData.monoMode) {
2674 vFrom.addr = (caddr_t) appData.highlightSquareColor;
2675 vFrom.size = strlen(appData.highlightSquareColor);
2676 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2677 if (vTo.addr == NULL) {
2678 appData.monoMode = True;
2681 highlightSquareColor = *(Pixel *) vTo.addr;
2685 if (!appData.monoMode) {
2686 vFrom.addr = (caddr_t) appData.premoveHighlightColor;
2687 vFrom.size = strlen(appData.premoveHighlightColor);
2688 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2689 if (vTo.addr == NULL) {
2690 appData.monoMode = True;
2693 premoveHighlightColor = *(Pixel *) vTo.addr;
2698 fprintf(stderr, _("%s: too few colors available; trying monochrome mode\n"),
2701 if (appData.bitmapDirectory == NULL ||
2702 appData.bitmapDirectory[0] == NULLCHAR)
2703 appData.bitmapDirectory = DEF_BITMAP_DIR;
2706 if (appData.lowTimeWarning && !appData.monoMode) {
2707 vFrom.addr = (caddr_t) appData.lowTimeWarningColor;
2708 vFrom.size = strlen(appData.lowTimeWarningColor);
2709 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2710 if (vTo.addr == NULL)
2711 appData.monoMode = True;
2713 lowTimeWarningColor = *(Pixel *) vTo.addr;
2716 if (appData.monoMode && appData.debugMode) {
2717 fprintf(stderr, _("white pixel = 0x%lx, black pixel = 0x%lx\n"),
2718 (unsigned long) XWhitePixel(xDisplay, xScreen),
2719 (unsigned long) XBlackPixel(xDisplay, xScreen));
2722 if (parse_cpair(ColorShout, appData.colorShout) < 0 ||
2723 parse_cpair(ColorSShout, appData.colorSShout) < 0 ||
2724 parse_cpair(ColorChannel1, appData.colorChannel1) < 0 ||
2725 parse_cpair(ColorChannel, appData.colorChannel) < 0 ||
2726 parse_cpair(ColorKibitz, appData.colorKibitz) < 0 ||
2727 parse_cpair(ColorTell, appData.colorTell) < 0 ||
2728 parse_cpair(ColorChallenge, appData.colorChallenge) < 0 ||
2729 parse_cpair(ColorRequest, appData.colorRequest) < 0 ||
2730 parse_cpair(ColorSeek, appData.colorSeek) < 0 ||
2731 parse_cpair(ColorNormal, appData.colorNormal) < 0)
2733 if (appData.colorize) {
2735 _("%s: can't parse color names; disabling colorization\n"),
2738 appData.colorize = FALSE;
2740 textColors[ColorNone].fg = textColors[ColorNone].bg = -1;
2741 textColors[ColorNone].attr = 0;
2743 XtAppAddActions(appContext, boardActions, XtNumber(boardActions));
2749 layoutName = "tinyLayout";
2750 } else if (smallLayout) {
2751 layoutName = "smallLayout";
2753 layoutName = "normalLayout";
2755 /* Outer layoutWidget is there only to provide a name for use in
2756 resources that depend on the layout style */
2758 XtCreateManagedWidget(layoutName, formWidgetClass, shellWidget,
2759 layoutArgs, XtNumber(layoutArgs));
2761 XtCreateManagedWidget("form", formWidgetClass, layoutWidget,
2762 formArgs, XtNumber(formArgs));
2763 XtSetArg(args[0], XtNdefaultDistance, &sep);
2764 XtGetValues(formWidget, args, 1);
2767 widgetList[j++] = menuBarWidget = CreateMenuBar(menuBar);
2768 XtSetArg(args[0], XtNtop, XtChainTop);
2769 XtSetArg(args[1], XtNbottom, XtChainTop);
2770 XtSetValues(menuBarWidget, args, 2);
2772 widgetList[j++] = whiteTimerWidget =
2773 XtCreateWidget("whiteTime", labelWidgetClass,
2774 formWidget, timerArgs, XtNumber(timerArgs));
2775 XtSetArg(args[0], XtNfont, clockFontStruct);
2776 XtSetArg(args[1], XtNtop, XtChainTop);
2777 XtSetArg(args[2], XtNbottom, XtChainTop);
2778 XtSetValues(whiteTimerWidget, args, 3);
2780 widgetList[j++] = blackTimerWidget =
2781 XtCreateWidget("blackTime", labelWidgetClass,
2782 formWidget, timerArgs, XtNumber(timerArgs));
2783 XtSetArg(args[0], XtNfont, clockFontStruct);
2784 XtSetArg(args[1], XtNtop, XtChainTop);
2785 XtSetArg(args[2], XtNbottom, XtChainTop);
2786 XtSetValues(blackTimerWidget, args, 3);
2788 if (appData.titleInWindow) {
2789 widgetList[j++] = titleWidget =
2790 XtCreateWidget("title", labelWidgetClass, formWidget,
2791 titleArgs, XtNumber(titleArgs));
2792 XtSetArg(args[0], XtNtop, XtChainTop);
2793 XtSetArg(args[1], XtNbottom, XtChainTop);
2794 XtSetValues(titleWidget, args, 2);
2797 if (appData.showButtonBar) {
2798 widgetList[j++] = buttonBarWidget = CreateButtonBar(buttonBar);
2799 XtSetArg(args[0], XtNleft, XtChainRight); // [HGM] glue to right window edge
2800 XtSetArg(args[1], XtNright, XtChainRight); // for good run-time sizing
2801 XtSetArg(args[2], XtNtop, XtChainTop);
2802 XtSetArg(args[3], XtNbottom, XtChainTop);
2803 XtSetValues(buttonBarWidget, args, 4);
2806 widgetList[j++] = messageWidget =
2807 XtCreateWidget("message", labelWidgetClass, formWidget,
2808 messageArgs, XtNumber(messageArgs));
2809 XtSetArg(args[0], XtNtop, XtChainTop);
2810 XtSetArg(args[1], XtNbottom, XtChainTop);
2811 XtSetValues(messageWidget, args, 2);
2813 widgetList[j++] = boardWidget =
2814 XtCreateWidget("board", widgetClass, formWidget, boardArgs,
2815 XtNumber(boardArgs));
2817 XtManageChildren(widgetList, j);
2819 timerWidth = (boardWidth - sep) / 2;
2820 XtSetArg(args[0], XtNwidth, timerWidth);
2821 XtSetValues(whiteTimerWidget, args, 1);
2822 XtSetValues(blackTimerWidget, args, 1);
2824 XtSetArg(args[0], XtNbackground, &timerBackgroundPixel);
2825 XtSetArg(args[1], XtNforeground, &timerForegroundPixel);
2826 XtGetValues(whiteTimerWidget, args, 2);
2828 if (appData.showButtonBar) {
2829 XtSetArg(args[0], XtNbackground, &buttonBackgroundPixel);
2830 XtSetArg(args[1], XtNforeground, &buttonForegroundPixel);
2831 XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
2835 * formWidget uses these constraints but they are stored
2839 XtSetArg(args[i], XtNfromHoriz, 0); i++;
2840 XtSetValues(menuBarWidget, args, i);
2841 if (appData.titleInWindow) {
2844 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2845 XtSetValues(whiteTimerWidget, args, i);
2847 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2848 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2849 XtSetValues(blackTimerWidget, args, i);
2851 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2852 XtSetArg(args[i], XtNjustify, XtJustifyLeft); i++;
2853 XtSetValues(titleWidget, args, i);
2855 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2856 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2857 XtSetValues(messageWidget, args, i);
2858 if (appData.showButtonBar) {
2860 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2861 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2862 XtSetValues(buttonBarWidget, args, i);
2866 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2867 XtSetValues(whiteTimerWidget, args, i);
2869 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2870 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2871 XtSetValues(blackTimerWidget, args, i);
2873 XtSetArg(args[i], XtNfromHoriz, menuBarWidget); i++;
2874 XtSetValues(titleWidget, args, i);
2876 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2877 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2878 XtSetValues(messageWidget, args, i);
2879 if (appData.showButtonBar) {
2881 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2882 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2883 XtSetValues(buttonBarWidget, args, i);
2888 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2889 XtSetValues(whiteTimerWidget, args, i);
2891 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2892 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2893 XtSetValues(blackTimerWidget, args, i);
2895 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2896 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2897 XtSetValues(messageWidget, args, i);
2898 if (appData.showButtonBar) {
2900 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2901 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2902 XtSetValues(buttonBarWidget, args, i);
2906 XtSetArg(args[0], XtNfromVert, messageWidget);
2907 XtSetArg(args[1], XtNtop, XtChainTop);
2908 XtSetArg(args[2], XtNbottom, XtChainBottom);
2909 XtSetArg(args[3], XtNleft, XtChainLeft);
2910 XtSetArg(args[4], XtNright, XtChainRight);
2911 XtSetValues(boardWidget, args, 5);
2913 XtRealizeWidget(shellWidget);
2916 * Correct the width of the message and title widgets.
2917 * It is not known why some systems need the extra fudge term.
2918 * The value "2" is probably larger than needed.
2920 XawFormDoLayout(formWidget, False);
2922 #define WIDTH_FUDGE 2
2924 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2925 XtSetArg(args[i], XtNheight, &h); i++;
2926 XtGetValues(messageWidget, args, i);
2927 if (appData.showButtonBar) {
2929 XtSetArg(args[i], XtNwidth, &w); i++;
2930 XtGetValues(buttonBarWidget, args, i);
2931 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2933 w = boardWidth - 2*bor + 1; /*!! +1 compensates for kludge below */
2936 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2937 if (gres != XtGeometryYes && appData.debugMode) {
2938 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2939 programName, gres, w, h, wr, hr);
2942 /* !! Horrible hack to work around bug in XFree86 4.0.1 (X11R6.4.3) */
2943 /* The size used for the child widget in layout lags one resize behind
2944 its true size, so we resize a second time, 1 pixel smaller. Yeech! */
2946 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2947 if (gres != XtGeometryYes && appData.debugMode) {
2948 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2949 programName, gres, w, h, wr, hr);
2952 XtSetArg(args[0], XtNleft, XtChainLeft); // [HGM] glue ends for good run-time sizing
2953 XtSetArg(args[1], XtNright, XtChainRight);
2954 XtSetValues(messageWidget, args, 2);
2956 if (appData.titleInWindow) {
2958 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2959 XtSetArg(args[i], XtNheight, &h); i++;
2960 XtGetValues(titleWidget, args, i);
2962 w = boardWidth - 2*bor;
2964 XtSetArg(args[0], XtNwidth, &w);
2965 XtGetValues(menuBarWidget, args, 1);
2966 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2969 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
2970 if (gres != XtGeometryYes && appData.debugMode) {
2972 _("%s: titleWidget geometry error %d %d %d %d %d\n"),
2973 programName, gres, w, h, wr, hr);
2976 XawFormDoLayout(formWidget, True);
2978 xBoardWindow = XtWindow(boardWidget);
2980 // [HGM] it seems the layout code ends here, but perhaps the color stuff is size independent and would
2981 // not need to go into InitDrawingSizes().
2985 * Create X checkmark bitmap and initialize option menu checks.
2987 ReadBitmap(&xMarkPixmap, "checkmark.bm",
2988 checkmark_bits, checkmark_width, checkmark_height);
2989 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
2990 if (appData.alwaysPromoteToQueen) {
2991 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
2994 if (appData.animateDragging) {
2995 XtSetValues(XtNameToWidget(menuBarWidget,
2996 "menuOptions.Animate Dragging"),
2999 if (appData.animate) {
3000 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
3003 if (appData.autoComment) {
3004 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
3007 if (appData.autoCallFlag) {
3008 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
3011 if (appData.autoFlipView) {
3012 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Auto Flip View"),
3015 if (appData.autoObserve) {
3016 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
3019 if (appData.autoRaiseBoard) {
3020 XtSetValues(XtNameToWidget(menuBarWidget,
3021 "menuOptions.Auto Raise Board"), args, 1);
3023 if (appData.autoSaveGames) {
3024 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
3027 if (appData.saveGameFile[0] != NULLCHAR) {
3028 /* Can't turn this off from menu */
3029 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
3031 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
3035 if (appData.blindfold) {
3036 XtSetValues(XtNameToWidget(menuBarWidget,
3037 "menuOptions.Blindfold"), args, 1);
3039 if (appData.flashCount > 0) {
3040 XtSetValues(XtNameToWidget(menuBarWidget,
3041 "menuOptions.Flash Moves"),
3044 if (appData.getMoveList) {
3045 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
3049 if (appData.highlightDragging) {
3050 XtSetValues(XtNameToWidget(menuBarWidget,
3051 "menuOptions.Highlight Dragging"),
3055 if (appData.highlightLastMove) {
3056 XtSetValues(XtNameToWidget(menuBarWidget,
3057 "menuOptions.Highlight Last Move"),
3060 if (appData.icsAlarm) {
3061 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.ICS Alarm"),
3064 if (appData.ringBellAfterMoves) {
3065 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
3068 if (appData.oldSaveStyle) {
3069 XtSetValues(XtNameToWidget(menuBarWidget,
3070 "menuOptions.Old Save Style"), args, 1);
3072 if (appData.periodicUpdates) {
3073 XtSetValues(XtNameToWidget(menuBarWidget,
3074 "menuOptions.Periodic Updates"), args, 1);
3076 if (appData.ponderNextMove) {
3077 XtSetValues(XtNameToWidget(menuBarWidget,
3078 "menuOptions.Ponder Next Move"), args, 1);
3080 if (appData.popupExitMessage) {
3081 XtSetValues(XtNameToWidget(menuBarWidget,
3082 "menuOptions.Popup Exit Message"), args, 1);
3084 if (appData.popupMoveErrors) {
3085 XtSetValues(XtNameToWidget(menuBarWidget,
3086 "menuOptions.Popup Move Errors"), args, 1);
3088 if (appData.premove) {
3089 XtSetValues(XtNameToWidget(menuBarWidget,
3090 "menuOptions.Premove"), args, 1);
3092 if (appData.quietPlay) {
3093 XtSetValues(XtNameToWidget(menuBarWidget,
3094 "menuOptions.Quiet Play"), args, 1);
3096 if (appData.showCoords) {
3097 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
3100 if (appData.hideThinkingFromHuman) {
3101 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
3104 if (appData.testLegality) {
3105 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Test Legality"),
3112 ReadBitmap(&wIconPixmap, "icon_white.bm",
3113 icon_white_bits, icon_white_width, icon_white_height);
3114 ReadBitmap(&bIconPixmap, "icon_black.bm",
3115 icon_black_bits, icon_black_width, icon_black_height);
3116 iconPixmap = wIconPixmap;
3118 XtSetArg(args[i], XtNiconPixmap, iconPixmap); i++;
3119 XtSetValues(shellWidget, args, i);
3122 * Create a cursor for the board widget.
3124 window_attributes.cursor = XCreateFontCursor(xDisplay, XC_hand2);
3125 XChangeWindowAttributes(xDisplay, xBoardWindow,
3126 CWCursor, &window_attributes);
3129 * Inhibit shell resizing.
3131 shellArgs[0].value = (XtArgVal) &w;
3132 shellArgs[1].value = (XtArgVal) &h;
3133 XtGetValues(shellWidget, shellArgs, 2);
3134 shellArgs[4].value = shellArgs[2].value = w;
3135 shellArgs[5].value = shellArgs[3].value = h;
3136 XtSetValues(shellWidget, &shellArgs[2], 4);
3137 marginW = w - boardWidth; // [HGM] needed to set new shellWidget size when we resize board
3138 marginH = h - boardHeight;
3140 CatchDeleteWindow(shellWidget, "QuitProc");
3145 if (appData.bitmapDirectory[0] != NULLCHAR) {
3152 /* Create regular pieces */
3153 if (!useImages) CreatePieces();
3158 if (appData.animate || appData.animateDragging)
3161 XtAugmentTranslations(formWidget,
3162 XtParseTranslationTable(globalTranslations));
3163 XtAugmentTranslations(boardWidget,
3164 XtParseTranslationTable(boardTranslations));
3165 XtAugmentTranslations(whiteTimerWidget,
3166 XtParseTranslationTable(whiteTranslations));
3167 XtAugmentTranslations(blackTimerWidget,
3168 XtParseTranslationTable(blackTranslations));
3170 /* Why is the following needed on some versions of X instead
3171 * of a translation? */
3172 XtAddEventHandler(boardWidget, ExposureMask, False,
3173 (XtEventHandler) EventProc, NULL);
3178 if (errorExitStatus == -1) {
3179 if (appData.icsActive) {
3180 /* We now wait until we see "login:" from the ICS before
3181 sending the logon script (problems with timestamp otherwise) */
3182 /*ICSInitScript();*/
3183 if (appData.icsInputBox) ICSInputBoxPopUp();
3186 signal(SIGINT, IntSigHandler);
3187 signal(SIGTERM, IntSigHandler);
3188 if (*appData.cmailGameName != NULLCHAR) {
3189 signal(SIGUSR1, CmailSigHandler);
3192 gameInfo.boardWidth = 0; // [HGM] pieces: kludge to ensure InitPosition() calls InitDrawingSizes()
3195 XtAppMainLoop(appContext);
3196 if (appData.debugMode) fclose(debugFP); // [DM] debug
3203 if (appData.icsActive && oldICSInteractionTitle != NULL) {
3204 DisplayIcsInteractionTitle(oldICSInteractionTitle);
3206 unlink(gameCopyFilename);
3207 unlink(gamePasteFilename);
3218 CmailSigHandler(sig)
3224 signal(SIGUSR1, SIG_IGN); /* suspend handler */
3226 /* Activate call-back function CmailSigHandlerCallBack() */
3227 OutputToProcess(cmailPR, (char *)(&dummy), sizeof(int), &error);
3229 signal(SIGUSR1, CmailSigHandler); /* re-activate handler */
3233 CmailSigHandlerCallBack(isr, closure, message, count, error)
3241 ReloadCmailMsgEvent(TRUE); /* Reload cmail msg */
3243 /**** end signal code ****/
3253 f = fopen(appData.icsLogon, "r");
3259 strcat(buf, appData.icsLogon);
3260 f = fopen(buf, "r");
3264 ProcessICSInitScript(f);
3271 EditCommentPopDown();
3276 void NotifyFrontendLogin()
3287 SetMenuEnables(enab)
3291 if (!menuBarWidget) return;
3292 while (enab->name != NULL) {
3293 w = XtNameToWidget(menuBarWidget, enab->name);
3295 DisplayError(enab->name, 0);
3297 XtSetSensitive(w, enab->value);
3303 Enables icsEnables[] = {
3304 { "menuFile.Mail Move", False },
3305 { "menuFile.Reload CMail Message", False },
3306 { "menuMode.Machine Black", False },
3307 { "menuMode.Machine White", False },
3308 { "menuMode.Analysis Mode", False },
3309 { "menuMode.Analyze File", False },
3310 { "menuMode.Two Machines", False },
3312 { "menuHelp.Hint", False },
3313 { "menuHelp.Book", False },
3314 { "menuStep.Move Now", False },
3315 { "menuOptions.Periodic Updates", False },
3316 { "menuOptions.Hide Thinking", False },
3317 { "menuOptions.Ponder Next Move", False },
3322 Enables ncpEnables[] = {
3323 { "menuFile.Mail Move", False },
3324 { "menuFile.Reload CMail Message", False },
3325 { "menuMode.Machine White", False },
3326 { "menuMode.Machine Black", False },
3327 { "menuMode.Analysis Mode", False },
3328 { "menuMode.Analyze File", False },
3329 { "menuMode.Two Machines", False },
3330 { "menuMode.ICS Client", False },
3331 { "menuMode.ICS Input Box", False },
3332 { "Action", False },
3333 { "menuStep.Revert", False },
3334 { "menuStep.Move Now", False },
3335 { "menuStep.Retract Move", False },
3336 { "menuOptions.Auto Comment", False },
3337 { "menuOptions.Auto Flag", False },
3338 { "menuOptions.Auto Flip View", False },
3339 { "menuOptions.Auto Observe", False },
3340 { "menuOptions.Auto Raise Board", False },
3341 { "menuOptions.Get Move List", False },
3342 { "menuOptions.ICS Alarm", False },
3343 { "menuOptions.Move Sound", False },
3344 { "menuOptions.Quiet Play", False },
3345 { "menuOptions.Hide Thinking", False },
3346 { "menuOptions.Periodic Updates", False },
3347 { "menuOptions.Ponder Next Move", False },
3348 { "menuHelp.Hint", False },
3349 { "menuHelp.Book", False },
3353 Enables gnuEnables[] = {
3354 { "menuMode.ICS Client", False },
3355 { "menuMode.ICS Input Box", False },
3356 { "menuAction.Accept", False },
3357 { "menuAction.Decline", False },
3358 { "menuAction.Rematch", False },
3359 { "menuAction.Adjourn", False },
3360 { "menuAction.Stop Examining", False },
3361 { "menuAction.Stop Observing", False },
3362 { "menuStep.Revert", False },
3363 { "menuOptions.Auto Comment", False },
3364 { "menuOptions.Auto Observe", False },
3365 { "menuOptions.Auto Raise Board", False },
3366 { "menuOptions.Get Move List", False },
3367 { "menuOptions.Premove", False },
3368 { "menuOptions.Quiet Play", False },
3370 /* The next two options rely on SetCmailMode being called *after* */
3371 /* SetGNUMode so that when GNU is being used to give hints these */
3372 /* menu options are still available */
3374 { "menuFile.Mail Move", False },
3375 { "menuFile.Reload CMail Message", False },
3379 Enables cmailEnables[] = {
3381 { "menuAction.Call Flag", False },
3382 { "menuAction.Draw", True },
3383 { "menuAction.Adjourn", False },
3384 { "menuAction.Abort", False },
3385 { "menuAction.Stop Observing", False },
3386 { "menuAction.Stop Examining", False },
3387 { "menuFile.Mail Move", True },
3388 { "menuFile.Reload CMail Message", True },
3392 Enables trainingOnEnables[] = {
3393 { "menuMode.Edit Comment", False },
3394 { "menuMode.Pause", False },
3395 { "menuStep.Forward", False },
3396 { "menuStep.Backward", False },
3397 { "menuStep.Forward to End", False },
3398 { "menuStep.Back to Start", False },
3399 { "menuStep.Move Now", False },
3400 { "menuStep.Truncate Game", False },
3404 Enables trainingOffEnables[] = {
3405 { "menuMode.Edit Comment", True },
3406 { "menuMode.Pause", True },
3407 { "menuStep.Forward", True },
3408 { "menuStep.Backward", True },
3409 { "menuStep.Forward to End", True },
3410 { "menuStep.Back to Start", True },
3411 { "menuStep.Move Now", True },
3412 { "menuStep.Truncate Game", True },
3416 Enables machineThinkingEnables[] = {
3417 { "menuFile.Load Game", False },
3418 { "menuFile.Load Next Game", False },
3419 { "menuFile.Load Previous Game", False },
3420 { "menuFile.Reload Same Game", False },
3421 { "menuFile.Paste Game", False },
3422 { "menuFile.Load Position", False },
3423 { "menuFile.Load Next Position", False },
3424 { "menuFile.Load Previous Position", False },
3425 { "menuFile.Reload Same Position", False },
3426 { "menuFile.Paste Position", False },
3427 { "menuMode.Machine White", False },
3428 { "menuMode.Machine Black", False },
3429 { "menuMode.Two Machines", False },
3430 { "menuStep.Retract Move", False },
3434 Enables userThinkingEnables[] = {
3435 { "menuFile.Load Game", True },
3436 { "menuFile.Load Next Game", True },
3437 { "menuFile.Load Previous Game", True },
3438 { "menuFile.Reload Same Game", True },
3439 { "menuFile.Paste Game", True },
3440 { "menuFile.Load Position", True },
3441 { "menuFile.Load Next Position", True },
3442 { "menuFile.Load Previous Position", True },
3443 { "menuFile.Reload Same Position", True },
3444 { "menuFile.Paste Position", True },
3445 { "menuMode.Machine White", True },
3446 { "menuMode.Machine Black", True },
3447 { "menuMode.Two Machines", True },
3448 { "menuStep.Retract Move", True },
3454 SetMenuEnables(icsEnables);
3457 if (appData.zippyPlay && !appData.noChessProgram) /* [DM] icsEngineAnalyze */
3458 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Analysis Mode"), True);
3465 SetMenuEnables(ncpEnables);
3471 SetMenuEnables(gnuEnables);
3477 SetMenuEnables(cmailEnables);
3483 SetMenuEnables(trainingOnEnables);
3484 if (appData.showButtonBar) {
3485 XtSetSensitive(buttonBarWidget, False);
3491 SetTrainingModeOff()
3493 SetMenuEnables(trainingOffEnables);
3494 if (appData.showButtonBar) {
3495 XtSetSensitive(buttonBarWidget, True);
3500 SetUserThinkingEnables()
3502 if (appData.noChessProgram) return;
3503 SetMenuEnables(userThinkingEnables);
3507 SetMachineThinkingEnables()
3509 if (appData.noChessProgram) return;
3510 SetMenuEnables(machineThinkingEnables);
3512 case MachinePlaysBlack:
3513 case MachinePlaysWhite:
3514 case TwoMachinesPlay:
3515 XtSetSensitive(XtNameToWidget(menuBarWidget,
3516 ModeToWidgetName(gameMode)), True);
3523 #define Abs(n) ((n)<0 ? -(n) : (n))
3526 * Find a font that matches "pattern" that is as close as
3527 * possible to the targetPxlSize. Prefer fonts that are k
3528 * pixels smaller to fonts that are k pixels larger. The
3529 * pattern must be in the X Consortium standard format,
3530 * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".
3531 * The return value should be freed with XtFree when no
3534 char *FindFont(pattern, targetPxlSize)
3538 char **fonts, *p, *best, *scalable, *scalableTail;
3539 int i, j, nfonts, minerr, err, pxlSize;
3542 char **missing_list;
3544 char *def_string, *base_fnt_lst, strInt[3];
3546 XFontStruct **fnt_list;
3548 base_fnt_lst = calloc(1, strlen(pattern) + 3);
3549 sprintf(strInt, "%d", targetPxlSize);
3550 p = strstr(pattern, "--");
3551 strncpy(base_fnt_lst, pattern, p - pattern + 2);
3552 strcat(base_fnt_lst, strInt);
3553 strcat(base_fnt_lst, strchr(p + 2, '-'));
3555 if ((fntSet = XCreateFontSet(xDisplay,
3559 &def_string)) == NULL) {
3561 fprintf(stderr, _("Unable to create font set.\n"));
3565 nfonts = XFontsOfFontSet(fntSet, &fnt_list, &fonts);
3567 fonts = XListFonts(xDisplay, pattern, 999999, &nfonts);
3569 fprintf(stderr, _("%s: no fonts match pattern %s\n"),
3570 programName, pattern);
3578 for (i=0; i<nfonts; i++) {
3581 if (*p != '-') continue;
3583 if (*p == NULLCHAR) break;
3584 if (*p++ == '-') j++;
3586 if (j < 7) continue;
3589 scalable = fonts[i];
3592 err = pxlSize - targetPxlSize;
3593 if (Abs(err) < Abs(minerr) ||
3594 (minerr > 0 && err < 0 && -err == minerr)) {
3600 if (scalable && Abs(minerr) > appData.fontSizeTolerance) {
3601 /* If the error is too big and there is a scalable font,
3602 use the scalable font. */
3603 int headlen = scalableTail - scalable;
3604 p = (char *) XtMalloc(strlen(scalable) + 10);
3605 while (isdigit(*scalableTail)) scalableTail++;
3606 sprintf(p, "%.*s%d%s", headlen, scalable, targetPxlSize, scalableTail);
3608 p = (char *) XtMalloc(strlen(best) + 1);
3611 if (appData.debugMode) {
3612 fprintf(debugFP, _("resolved %s at pixel size %d\n to %s\n"),
3613 pattern, targetPxlSize, p);
3616 if (missing_count > 0)
3617 XFreeStringList(missing_list);
3618 XFreeFontSet(xDisplay, fntSet);
3620 XFreeFontNames(fonts);
3627 XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
3628 | GCBackground | GCFunction | GCPlaneMask;
3629 XGCValues gc_values;
3632 gc_values.plane_mask = AllPlanes;
3633 gc_values.line_width = lineGap;
3634 gc_values.line_style = LineSolid;
3635 gc_values.function = GXcopy;
3637 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3638 gc_values.background = XBlackPixel(xDisplay, xScreen);
3639 lineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3641 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3642 gc_values.background = XWhitePixel(xDisplay, xScreen);
3643 coordGC = XtGetGC(shellWidget, value_mask, &gc_values);
3644 XSetFont(xDisplay, coordGC, coordFontID);
3646 // [HGM] make font for holdings counts (white on black0
3647 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3648 gc_values.background = XBlackPixel(xDisplay, xScreen);
3649 countGC = XtGetGC(shellWidget, value_mask, &gc_values);
3650 XSetFont(xDisplay, countGC, countFontID);
3652 if (appData.monoMode) {
3653 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3654 gc_values.background = XWhitePixel(xDisplay, xScreen);
3655 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3657 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3658 gc_values.background = XBlackPixel(xDisplay, xScreen);
3659 lightSquareGC = wbPieceGC
3660 = XtGetGC(shellWidget, value_mask, &gc_values);
3662 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3663 gc_values.background = XWhitePixel(xDisplay, xScreen);
3664 darkSquareGC = bwPieceGC
3665 = XtGetGC(shellWidget, value_mask, &gc_values);
3667 if (DefaultDepth(xDisplay, xScreen) == 1) {
3668 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
3669 gc_values.function = GXcopyInverted;
3670 copyInvertedGC = XtGetGC(shellWidget, value_mask, &gc_values);
3671 gc_values.function = GXcopy;
3672 if (XBlackPixel(xDisplay, xScreen) == 1) {
3673 bwPieceGC = darkSquareGC;
3674 wbPieceGC = copyInvertedGC;
3676 bwPieceGC = copyInvertedGC;
3677 wbPieceGC = lightSquareGC;
3681 gc_values.foreground = highlightSquareColor;
3682 gc_values.background = highlightSquareColor;
3683 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3685 gc_values.foreground = premoveHighlightColor;
3686 gc_values.background = premoveHighlightColor;
3687 prelineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3689 gc_values.foreground = lightSquareColor;
3690 gc_values.background = darkSquareColor;
3691 lightSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3693 gc_values.foreground = darkSquareColor;
3694 gc_values.background = lightSquareColor;
3695 darkSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3697 gc_values.foreground = jailSquareColor;
3698 gc_values.background = jailSquareColor;
3699 jailSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3701 gc_values.foreground = whitePieceColor;
3702 gc_values.background = darkSquareColor;
3703 wdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3705 gc_values.foreground = whitePieceColor;
3706 gc_values.background = lightSquareColor;
3707 wlPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3709 gc_values.foreground = whitePieceColor;
3710 gc_values.background = jailSquareColor;
3711 wjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3713 gc_values.foreground = blackPieceColor;
3714 gc_values.background = darkSquareColor;
3715 bdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3717 gc_values.foreground = blackPieceColor;
3718 gc_values.background = lightSquareColor;
3719 blPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3721 gc_values.foreground = blackPieceColor;
3722 gc_values.background = jailSquareColor;
3723 bjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3727 void loadXIM(xim, xmask, filename, dest, mask)
3740 fp = fopen(filename, "rb");
3742 fprintf(stderr, _("%s: error loading XIM!\n"), programName);
3749 for (y=0; y<h; ++y) {
3750 for (x=0; x<h; ++x) {
3755 XPutPixel(xim, x, y, blackPieceColor);
3757 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3760 XPutPixel(xim, x, y, darkSquareColor);
3762 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3765 XPutPixel(xim, x, y, whitePieceColor);
3767 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3770 XPutPixel(xim, x, y, lightSquareColor);
3772 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3778 /* create Pixmap of piece */
3779 *dest = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3781 XPutImage(xDisplay, *dest, lightSquareGC, xim,
3784 /* create Pixmap of clipmask
3785 Note: We assume the white/black pieces have the same
3786 outline, so we make only 6 masks. This is okay
3787 since the XPM clipmask routines do the same. */
3789 temp = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3791 XPutImage(xDisplay, temp, lightSquareGC, xmask,
3794 /* now create the 1-bit version */
3795 *mask = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3798 values.foreground = 1;
3799 values.background = 0;
3801 /* Don't use XtGetGC, not read only */
3802 maskGC = XCreateGC(xDisplay, *mask,
3803 GCForeground | GCBackground, &values);
3804 XCopyPlane(xDisplay, temp, *mask, maskGC,
3805 0, 0, squareSize, squareSize, 0, 0, 1);
3806 XFreePixmap(xDisplay, temp);
3811 char pieceBitmapNames[] = "pnbrqfeacwmohijgdvlsukpnsl";
3813 void CreateXIMPieces()
3818 static char *ximkind[] = { "ll", "ld", "dl", "dd" };
3823 /* The XSynchronize calls were copied from CreatePieces.
3824 Not sure if needed, but can't hurt */
3825 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3828 /* temp needed by loadXIM() */
3829 ximtemp = XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3830 0, 0, ss, ss, AllPlanes, XYPixmap);
3832 if (strlen(appData.pixmapDirectory) == 0) {
3836 if (appData.monoMode) {
3837 DisplayFatalError(_("XIM pieces cannot be used in monochrome mode"),
3841 fprintf(stderr, _("\nLoading XIMs...\n"));
3843 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3844 fprintf(stderr, "%d", piece+1);
3845 for (kind=0; kind<4; kind++) {
3846 fprintf(stderr, ".");
3847 snprintf(buf, sizeof(buf), "%s/%s%c%s%u.xim",
3848 ExpandPathName(appData.pixmapDirectory),
3849 piece <= (int) WhiteKing ? "" : "w",
3850 pieceBitmapNames[piece],
3852 ximPieceBitmap[kind][piece] =
3853 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3854 0, 0, ss, ss, AllPlanes, XYPixmap);
3855 if (appData.debugMode)
3856 fprintf(stderr, _("(File:%s:) "), buf);
3857 loadXIM(ximPieceBitmap[kind][piece],
3859 &(xpmPieceBitmap2[kind][piece]),
3860 &(ximMaskPm2[piece]));
3861 if(piece <= (int)WhiteKing)
3862 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3864 fprintf(stderr," ");
3866 /* Load light and dark squares */
3867 /* If the LSQ and DSQ pieces don't exist, we will
3868 draw them with solid squares. */
3869 snprintf(buf,sizeof(buf), "%s/lsq%u.xim", ExpandPathName(appData.pixmapDirectory), ss);
3870 if (access(buf, 0) != 0) {
3874 fprintf(stderr, _("light square "));
3876 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3877 0, 0, ss, ss, AllPlanes, XYPixmap);
3878 if (appData.debugMode)
3879 fprintf(stderr, _("(File:%s:) "), buf);
3881 loadXIM(ximLightSquare, NULL, buf, &xpmLightSquare, NULL);
3882 fprintf(stderr, _("dark square "));
3883 snprintf(buf,sizeof(buf), "%s/dsq%u.xim",
3884 ExpandPathName(appData.pixmapDirectory), ss);
3885 if (appData.debugMode)
3886 fprintf(stderr, _("(File:%s:) "), buf);
3888 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3889 0, 0, ss, ss, AllPlanes, XYPixmap);
3890 loadXIM(ximDarkSquare, NULL, buf, &xpmDarkSquare, NULL);
3891 xpmJailSquare = xpmLightSquare;
3893 fprintf(stderr, _("Done.\n"));
3895 XSynchronize(xDisplay, False); /* Work-around for xlib/xt buffering bug */
3899 void CreateXPMPieces()
3903 u_int ss = squareSize;
3905 static char *xpmkind[] = { "ll", "ld", "dl", "dd" };
3906 XpmColorSymbol symbols[4];
3908 /* The XSynchronize calls were copied from CreatePieces.
3909 Not sure if needed, but can't hurt */
3910 XSynchronize(xDisplay, True); /* Work-around for xlib/xt buffering bug */
3912 /* Setup translations so piece colors match square colors */
3913 symbols[0].name = "light_piece";
3914 symbols[0].value = appData.whitePieceColor;
3915 symbols[1].name = "dark_piece";
3916 symbols[1].value = appData.blackPieceColor;
3917 symbols[2].name = "light_square";
3918 symbols[2].value = appData.lightSquareColor;
3919 symbols[3].name = "dark_square";
3920 symbols[3].value = appData.darkSquareColor;
3922 attr.valuemask = XpmColorSymbols;
3923 attr.colorsymbols = symbols;
3924 attr.numsymbols = 4;
3926 if (appData.monoMode) {
3927 DisplayFatalError(_("XPM pieces cannot be used in monochrome mode"),
3931 if (strlen(appData.pixmapDirectory) == 0) {
3932 XpmPieces* pieces = builtInXpms;
3935 while (pieces->size != squareSize && pieces->size) pieces++;
3936 if (!pieces->size) {
3937 fprintf(stderr, _("No builtin XPM pieces of size %d\n"), squareSize);
3940 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3941 for (kind=0; kind<4; kind++) {
3943 if ((r=XpmCreatePixmapFromData(xDisplay, xBoardWindow,
3944 pieces->xpm[piece][kind],
3945 &(xpmPieceBitmap2[kind][piece]),
3946 NULL, &attr)) != 0) {
3947 fprintf(stderr, _("Error %d loading XPM image \"%s\"\n"),
3951 if(piece <= (int) WhiteKing)
3952 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3956 xpmJailSquare = xpmLightSquare;
3960 fprintf(stderr, _("\nLoading XPMs...\n"));
3963 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3964 fprintf(stderr, "%d ", piece+1);
3965 for (kind=0; kind<4; kind++) {
3966 snprintf(buf, sizeof(buf), "%s/%s%c%s%u.xpm",
3967 ExpandPathName(appData.pixmapDirectory),
3968 piece > (int) WhiteKing ? "w" : "",
3969 pieceBitmapNames[piece],
3971 if (appData.debugMode) {
3972 fprintf(stderr, _("(File:%s:) "), buf);
3974 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3975 &(xpmPieceBitmap2[kind][piece]),
3976 NULL, &attr)) != 0) {
3977 if(piece != (int)WhiteKing && piece > (int)WhiteQueen) {
3978 // [HGM] missing: read of unorthodox piece failed; substitute King.
3979 snprintf(buf, sizeof(buf), "%s/k%s%u.xpm",
3980 ExpandPathName(appData.pixmapDirectory),
3982 if (appData.debugMode) {
3983 fprintf(stderr, _("(Replace by File:%s:) "), buf);
3985 r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3986 &(xpmPieceBitmap2[kind][piece]),
3990 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"),
3995 if(piece <= (int) WhiteKing)
3996 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3999 /* Load light and dark squares */
4000 /* If the LSQ and DSQ pieces don't exist, we will
4001 draw them with solid squares. */
4002 fprintf(stderr, _("light square "));
4003 snprintf(buf, sizeof(buf), "%s/lsq%u.xpm", ExpandPathName(appData.pixmapDirectory), ss);
4004 if (access(buf, 0) != 0) {
4008 if (appData.debugMode)
4009 fprintf(stderr, _("(File:%s:) "), buf);
4011 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
4012 &xpmLightSquare, NULL, &attr)) != 0) {
4013 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
4016 fprintf(stderr, _("dark square "));
4017 snprintf(buf, sizeof(buf), "%s/dsq%u.xpm",
4018 ExpandPathName(appData.pixmapDirectory), ss);
4019 if (appData.debugMode) {
4020 fprintf(stderr, _("(File:%s:) "), buf);
4022 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
4023 &xpmDarkSquare, NULL, &attr)) != 0) {
4024 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
4028 xpmJailSquare = xpmLightSquare;
4029 fprintf(stderr, _("Done.\n"));
4031 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
4034 #endif /* HAVE_LIBXPM */
4037 /* No built-in bitmaps */
4042 u_int ss = squareSize;
4044 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
4047 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
4048 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
4049 sprintf(buf, "%s%c%u%c.bm", piece > (int)WhiteKing ? "w" : "",
4050 pieceBitmapNames[piece],
4051 ss, kind == SOLID ? 's' : 'o');
4052 ReadBitmap(&pieceBitmap2[kind][piece], buf, NULL, ss, ss);
4053 if(piece <= (int)WhiteKing)
4054 pieceBitmap[kind][piece] = pieceBitmap2[kind][piece];
4058 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
4062 /* With built-in bitmaps */
4065 BuiltInBits* bib = builtInBits;
4068 u_int ss = squareSize;
4070 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
4073 while (bib->squareSize != ss && bib->squareSize != 0) bib++;
4075 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
4076 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
4077 sprintf(buf, "%s%c%u%c.bm", piece > (int)WhiteKing ? "w" : "",
4078 pieceBitmapNames[piece],
4079 ss, kind == SOLID ? 's' : 'o');
4080 ReadBitmap(&pieceBitmap2[kind][piece], buf,
4081 bib->bits[kind][piece], ss, ss);
4082 if(piece <= (int)WhiteKing)
4083 pieceBitmap[kind][piece] = pieceBitmap2[kind][piece];
4087 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
4092 void ReadBitmap(pm, name, bits, wreq, hreq)
4095 unsigned char bits[];
4101 char msg[MSG_SIZ], fullname[MSG_SIZ];
4103 if (*appData.bitmapDirectory != NULLCHAR) {
4104 strcpy(fullname, appData.bitmapDirectory);
4105 strcat(fullname, "/");
4106 strcat(fullname, name);
4107 errcode = XReadBitmapFile(xDisplay, xBoardWindow, fullname,
4108 &w, &h, pm, &x_hot, &y_hot);
4109 fprintf(stderr, "load %s\n", name);
4110 if (errcode != BitmapSuccess) {
4112 case BitmapOpenFailed:
4113 snprintf(msg, sizeof(msg), _("Can't open bitmap file %s"), fullname);
4115 case BitmapFileInvalid:
4116 snprintf(msg, sizeof(msg), _("Invalid bitmap in file %s"), fullname);
4118 case BitmapNoMemory:
4119 snprintf(msg, sizeof(msg), _("Ran out of memory reading bitmap file %s"),
4123 snprintf(msg, sizeof(msg), _("Unknown XReadBitmapFile error %d on file %s"),
4127 fprintf(stderr, _("%s: %s...using built-in\n"),
4129 } else if (w != wreq || h != hreq) {
4131 _("%s: Bitmap %s is %dx%d, not %dx%d...using built-in\n"),
4132 programName, fullname, w, h, wreq, hreq);
4138 *pm = XCreateBitmapFromData(xDisplay, xBoardWindow, (char *) bits,
4147 if (lineGap == 0) return;
4149 /* [HR] Split this into 2 loops for non-square boards. */
4151 for (i = 0; i < BOARD_HEIGHT + 1; i++) {
4152 gridSegments[i].x1 = 0;
4153 gridSegments[i].x2 =
4154 lineGap + BOARD_WIDTH * (squareSize + lineGap);
4155 gridSegments[i].y1 = gridSegments[i].y2
4156 = lineGap / 2 + (i * (squareSize + lineGap));
4159 for (j = 0; j < BOARD_WIDTH + 1; j++) {
4160 gridSegments[j + i].y1 = 0;
4161 gridSegments[j + i].y2 =
4162 lineGap + BOARD_HEIGHT * (squareSize + lineGap);
4163 gridSegments[j + i].x1 = gridSegments[j + i].x2
4164 = lineGap / 2 + (j * (squareSize + lineGap));
4168 static void MenuBarSelect(w, addr, index)
4173 XtActionProc proc = (XtActionProc) addr;
4175 (proc)(NULL, NULL, NULL, NULL);
4178 void CreateMenuBarPopup(parent, name, mb)
4188 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
4191 XtSetArg(args[j], XtNleftMargin, 20); j++;
4192 XtSetArg(args[j], XtNrightMargin, 20); j++;
4194 while (mi->string != NULL) {
4195 if (strcmp(mi->string, "----") == 0) {
4196 entry = XtCreateManagedWidget(mi->string, smeLineObjectClass,
4199 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string)));
4200 entry = XtCreateManagedWidget(mi->string, smeBSBObjectClass,
4202 XtAddCallback(entry, XtNcallback,
4203 (XtCallbackProc) MenuBarSelect,
4204 (caddr_t) mi->proc);
4210 Widget CreateMenuBar(mb)
4214 Widget anchor, menuBar;
4216 char menuName[MSG_SIZ];
4219 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
4220 XtSetArg(args[j], XtNvSpace, 0); j++;
4221 XtSetArg(args[j], XtNborderWidth, 0); j++;
4222 menuBar = XtCreateWidget("menuBar", boxWidgetClass,
4223 formWidget, args, j);
4225 while (mb->name != NULL) {
4226 strcpy(menuName, "menu");
4227 strcat(menuName, mb->name);
4229 XtSetArg(args[j], XtNmenuName, XtNewString(menuName)); j++;
4232 shortName[0] = _(mb->name)[0];
4233 shortName[1] = NULLCHAR;
4234 XtSetArg(args[j], XtNlabel, XtNewString(shortName)); j++;
4237 XtSetArg(args[j], XtNlabel, XtNewString(_(mb->name))); j++;
4240 XtSetArg(args[j], XtNborderWidth, 0); j++;
4241 anchor = XtCreateManagedWidget(mb->name, menuButtonWidgetClass,
4243 CreateMenuBarPopup(menuBar, menuName, mb);
4249 Widget CreateButtonBar(mi)
4253 Widget button, buttonBar;
4257 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
4259 XtSetArg(args[j], XtNhSpace, 0); j++;
4261 XtSetArg(args[j], XtNborderWidth, 0); j++;
4262 XtSetArg(args[j], XtNvSpace, 0); j++;
4263 buttonBar = XtCreateWidget("buttonBar", boxWidgetClass,
4264 formWidget, args, j);
4266 while (mi->string != NULL) {
4269 XtSetArg(args[j], XtNinternalWidth, 2); j++;
4270 XtSetArg(args[j], XtNborderWidth, 0); j++;
4272 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string))); j++;
4273 button = XtCreateManagedWidget(mi->string, commandWidgetClass,
4274 buttonBar, args, j);
4275 XtAddCallback(button, XtNcallback,
4276 (XtCallbackProc) MenuBarSelect,
4277 (caddr_t) mi->proc);
4284 CreatePieceMenu(name, color)
4291 ChessSquare selection;
4293 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
4294 boardWidget, args, 0);
4296 for (i = 0; i < PIECE_MENU_SIZE; i++) {
4297 String item = pieceMenuStrings[color][i];
4299 if (strcmp(item, "----") == 0) {
4300 entry = XtCreateManagedWidget(item, smeLineObjectClass,
4303 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
4304 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
4306 selection = pieceMenuTranslation[color][i];
4307 XtAddCallback(entry, XtNcallback,
4308 (XtCallbackProc) PieceMenuSelect,
4309 (caddr_t) selection);
4310 if (selection == WhitePawn || selection == BlackPawn) {
4311 XtSetArg(args[0], XtNpopupOnEntry, entry);
4312 XtSetValues(menu, args, 1);
4325 ChessSquare selection;
4327 whitePieceMenu = CreatePieceMenu("menuW", 0);
4328 blackPieceMenu = CreatePieceMenu("menuB", 1);
4330 XtRegisterGrabAction(PieceMenuPopup, True,
4331 (unsigned)(ButtonPressMask|ButtonReleaseMask),
4332 GrabModeAsync, GrabModeAsync);
4334 XtSetArg(args[0], XtNlabel, _("Drop"));
4335 dropMenu = XtCreatePopupShell("menuD", simpleMenuWidgetClass,
4336 boardWidget, args, 1);
4337 for (i = 0; i < DROP_MENU_SIZE; i++) {
4338 String item = dropMenuStrings[i];
4340 if (strcmp(item, "----") == 0) {
4341 entry = XtCreateManagedWidget(item, smeLineObjectClass,
4344 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
4345 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
4347 selection = dropMenuTranslation[i];
4348 XtAddCallback(entry, XtNcallback,
4349 (XtCallbackProc) DropMenuSelect,
4350 (caddr_t) selection);
4355 void SetupDropMenu()
4363 for (i=0; i<sizeof(dmEnables)/sizeof(DropMenuEnables); i++) {
4364 entry = XtNameToWidget(dropMenu, dmEnables[i].widget);
4365 p = strchr(gameMode == IcsPlayingWhite ? white_holding : black_holding,
4366 dmEnables[i].piece);
4367 XtSetSensitive(entry, p != NULL || !appData.testLegality
4368 /*!!temp:*/ || (gameInfo.variant == VariantCrazyhouse
4369 && !appData.icsActive));
4371 while (p && *p++ == dmEnables[i].piece) count++;
4372 snprintf(label, sizeof(label), "%s %d", dmEnables[i].widget, count);
4374 XtSetArg(args[j], XtNlabel, label); j++;
4375 XtSetValues(entry, args, j);
4379 void PieceMenuPopup(w, event, params, num_params)
4383 Cardinal *num_params;
4386 if (event->type != ButtonPress) return;
4387 if (errorUp) ErrorPopDown();
4391 whichMenu = params[0];
4393 case IcsPlayingWhite:
4394 case IcsPlayingBlack:
4396 case MachinePlaysWhite:
4397 case MachinePlaysBlack:
4398 if (appData.testLegality &&
4399 gameInfo.variant != VariantBughouse &&
4400 gameInfo.variant != VariantCrazyhouse) return;
4402 whichMenu = "menuD";
4408 if (((pmFromX = EventToSquare(event->xbutton.x, BOARD_WIDTH)) < 0) ||
4409 ((pmFromY = EventToSquare(event->xbutton.y, BOARD_HEIGHT)) < 0)) {
4410 pmFromX = pmFromY = -1;
4414 pmFromX = BOARD_WIDTH - 1 - pmFromX;
4416 pmFromY = BOARD_HEIGHT - 1 - pmFromY;
4418 XtPopupSpringLoaded(XtNameToWidget(boardWidget, whichMenu));
4421 static void PieceMenuSelect(w, piece, junk)
4426 if (pmFromX < 0 || pmFromY < 0) return;
4427 EditPositionMenuEvent(piece, pmFromX, pmFromY);
4430 static void DropMenuSelect(w, piece, junk)
4435 if (pmFromX < 0 || pmFromY < 0) return;
4436 DropMenuEvent(piece, pmFromX, pmFromY);
4439 void WhiteClock(w, event, prms, nprms)
4445 if (gameMode == EditPosition || gameMode == IcsExamining) {
4446 SetWhiteToPlayEvent();
4447 } else if (gameMode == IcsPlayingBlack || gameMode == MachinePlaysWhite) {
4452 void BlackClock(w, event, prms, nprms)
4458 if (gameMode == EditPosition || gameMode == IcsExamining) {
4459 SetBlackToPlayEvent();
4460 } else if (gameMode == IcsPlayingWhite || gameMode == MachinePlaysBlack) {
4467 * If the user selects on a border boundary, return -1; if off the board,
4468 * return -2. Otherwise map the event coordinate to the square.
4470 int EventToSquare(x, limit)
4478 if ((x % (squareSize + lineGap)) >= squareSize)
4480 x /= (squareSize + lineGap);
4486 static void do_flash_delay(msec)
4492 static void drawHighlight(file, rank, gc)
4498 if (lineGap == 0 || appData.blindfold) return;
4501 x = lineGap/2 + ((BOARD_WIDTH-1)-file) *
4502 (squareSize + lineGap);
4503 y = lineGap/2 + rank * (squareSize + lineGap);
4505 x = lineGap/2 + file * (squareSize + lineGap);
4506 y = lineGap/2 + ((BOARD_HEIGHT-1)-rank) *
4507 (squareSize + lineGap);
4510 XDrawRectangle(xDisplay, xBoardWindow, gc, x, y,
4511 squareSize+lineGap, squareSize+lineGap);
4514 int hi1X = -1, hi1Y = -1, hi2X = -1, hi2Y = -1;
4515 int pm1X = -1, pm1Y = -1, pm2X = -1, pm2Y = -1;
4518 SetHighlights(fromX, fromY, toX, toY)
4519 int fromX, fromY, toX, toY;
4521 if (hi1X != fromX || hi1Y != fromY) {
4522 if (hi1X >= 0 && hi1Y >= 0) {
4523 drawHighlight(hi1X, hi1Y, lineGC);
4525 if (fromX >= 0 && fromY >= 0) {
4526 drawHighlight(fromX, fromY, highlineGC);
4529 if (hi2X != toX || hi2Y != toY) {
4530 if (hi2X >= 0 && hi2Y >= 0) {
4531 drawHighlight(hi2X, hi2Y, lineGC);
4533 if (toX >= 0 && toY >= 0) {
4534 drawHighlight(toX, toY, highlineGC);
4546 SetHighlights(-1, -1, -1, -1);
4551 SetPremoveHighlights(fromX, fromY, toX, toY)
4552 int fromX, fromY, toX, toY;
4554 if (pm1X != fromX || pm1Y != fromY) {
4555 if (pm1X >= 0 && pm1Y >= 0) {
4556 drawHighlight(pm1X, pm1Y, lineGC);
4558 if (fromX >= 0 && fromY >= 0) {
4559 drawHighlight(fromX, fromY, prelineGC);
4562 if (pm2X != toX || pm2Y != toY) {
4563 if (pm2X >= 0 && pm2Y >= 0) {
4564 drawHighlight(pm2X, pm2Y, lineGC);
4566 if (toX >= 0 && toY >= 0) {
4567 drawHighlight(toX, toY, prelineGC);
4577 ClearPremoveHighlights()
4579 SetPremoveHighlights(-1, -1, -1, -1);
4582 static void BlankSquare(x, y, color, piece, dest)
4587 if (useImages && useImageSqs) {
4591 pm = xpmLightSquare;
4596 case 2: /* neutral */
4601 XCopyArea(xDisplay, pm, dest, wlPieceGC, 0, 0,
4602 squareSize, squareSize, x, y);
4612 case 2: /* neutral */
4617 XFillRectangle(xDisplay, dest, gc, x, y, squareSize, squareSize);
4622 I split out the routines to draw a piece so that I could
4623 make a generic flash routine.
4625 static void monoDrawPiece_1bit(piece, square_color, x, y, dest)
4627 int square_color, x, y;
4630 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
4631 switch (square_color) {
4633 case 2: /* neutral */
4635 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
4636 ? *pieceToOutline(piece)
4637 : *pieceToSolid(piece),
4638 dest, bwPieceGC, 0, 0,
4639 squareSize, squareSize, x, y);
4642 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
4643 ? *pieceToSolid(piece)
4644 : *pieceToOutline(piece),
4645 dest, wbPieceGC, 0, 0,
4646 squareSize, squareSize, x, y);
4651 static void monoDrawPiece(piece, square_color, x, y, dest)
4653 int square_color, x, y;
4656 switch (square_color) {
4658 case 2: /* neutral */
4660 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
4661 ? *pieceToOutline(piece)
4662 : *pieceToSolid(piece),
4663 dest, bwPieceGC, 0, 0,
4664 squareSize, squareSize, x, y, 1);
4667 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
4668 ? *pieceToSolid(piece)
4669 : *pieceToOutline(piece),
4670 dest, wbPieceGC, 0, 0,
4671 squareSize, squareSize, x, y, 1);
4676 static void colorDrawPiece(piece, square_color, x, y, dest)
4678 int square_color, x, y;
4681 if(pieceToSolid(piece) == NULL) return; // [HGM] bitmaps: make it non-fatal if we have no bitmap;
4682 switch (square_color) {
4684 XCopyPlane(xDisplay, *pieceToSolid(piece),
4685 dest, (int) piece < (int) BlackPawn
4686 ? wlPieceGC : blPieceGC, 0, 0,
4687 squareSize, squareSize, x, y, 1);
4690 XCopyPlane(xDisplay, *pieceToSolid(piece),
4691 dest, (int) piece < (int) BlackPawn
4692 ? wdPieceGC : bdPieceGC, 0, 0,
4693 squareSize, squareSize, x, y, 1);
4695 case 2: /* neutral */
4697 XCopyPlane(xDisplay, *pieceToSolid(piece),
4698 dest, (int) piece < (int) BlackPawn
4699 ? wjPieceGC : bjPieceGC, 0, 0,
4700 squareSize, squareSize, x, y, 1);
4705 static void colorDrawPieceImage(piece, square_color, x, y, dest)
4707 int square_color, x, y;
4712 switch (square_color) {
4714 case 2: /* neutral */
4716 if ((int)piece < (int) BlackPawn) {
4724 if ((int)piece < (int) BlackPawn) {
4732 XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
4733 dest, wlPieceGC, 0, 0,
4734 squareSize, squareSize, x, y);
4737 typedef void (*DrawFunc)();
4739 DrawFunc ChooseDrawFunc()
4741 if (appData.monoMode) {
4742 if (DefaultDepth(xDisplay, xScreen) == 1) {
4743 return monoDrawPiece_1bit;
4745 return monoDrawPiece;
4749 return colorDrawPieceImage;
4751 return colorDrawPiece;
4755 /* [HR] determine square color depending on chess variant. */
4756 static int SquareColor(row, column)
4761 if (gameInfo.variant == VariantXiangqi) {
4762 if (column >= 3 && column <= 5 && row >= 0 && row <= 2) {
4764 } else if (column >= 3 && column <= 5 && row >= 7 && row <= 9) {
4766 } else if (row <= 4) {
4772 square_color = ((column + row) % 2) == 1;
4775 /* [hgm] holdings: next line makes all holdings squares light */
4776 if(column < BOARD_LEFT || column >= BOARD_RGHT) square_color = 1;
4778 return square_color;
4781 void DrawSquare(row, column, piece, do_flash)
4782 int row, column, do_flash;
4785 int square_color, x, y, direction, font_ascent, font_descent;
4788 XCharStruct overall;
4792 /* Calculate delay in milliseconds (2-delays per complete flash) */
4793 flash_delay = 500 / appData.flashRate;
4796 x = lineGap + ((BOARD_WIDTH-1)-column) *
4797 (squareSize + lineGap);
4798 y = lineGap + row * (squareSize + lineGap);
4800 x = lineGap + column * (squareSize + lineGap);
4801 y = lineGap + ((BOARD_HEIGHT-1)-row) *
4802 (squareSize + lineGap);
4805 square_color = SquareColor(row, column);
4807 if ( // [HGM] holdings: blank out area between board and holdings
4808 column == BOARD_LEFT-1 || column == BOARD_RGHT
4809 || (column == BOARD_LEFT-2 && row < BOARD_HEIGHT-gameInfo.holdingsSize)
4810 || (column == BOARD_RGHT+1 && row >= gameInfo.holdingsSize) ) {
4811 BlankSquare(x, y, 2, EmptySquare, xBoardWindow);
4813 // [HGM] print piece counts next to holdings
4814 string[1] = NULLCHAR;
4815 if (column == (flipView ? BOARD_LEFT-1 : BOARD_RGHT) && piece > 1 ) {
4816 string[0] = '0' + piece;
4817 XTextExtents(countFontStruct, string, 1, &direction,
4818 &font_ascent, &font_descent, &overall);
4819 if (appData.monoMode) {
4820 XDrawImageString(xDisplay, xBoardWindow, countGC,
4821 x + squareSize - overall.width - 2,
4822 y + font_ascent + 1, string, 1);
4824 XDrawString(xDisplay, xBoardWindow, countGC,
4825 x + squareSize - overall.width - 2,
4826 y + font_ascent + 1, string, 1);
4829 if (column == (flipView ? BOARD_RGHT : BOARD_LEFT-1) && piece > 1) {
4830 string[0] = '0' + piece;
4831 XTextExtents(countFontStruct, string, 1, &direction,
4832 &font_ascent, &font_descent, &overall);
4833 if (appData.monoMode) {
4834 XDrawImageString(xDisplay, xBoardWindow, countGC,
4835 x + 2, y + font_ascent + 1, string, 1);
4837 XDrawString(xDisplay, xBoardWindow, countGC,
4838 x + 2, y + font_ascent + 1, string, 1);
4842 if (piece == EmptySquare || appData.blindfold) {
4843 BlankSquare(x, y, square_color, piece, xBoardWindow);
4845 drawfunc = ChooseDrawFunc();
4846 if (do_flash && appData.flashCount > 0) {
4847 for (i=0; i<appData.flashCount; ++i) {
4849 drawfunc(piece, square_color, x, y, xBoardWindow);
4850 XSync(xDisplay, False);
4851 do_flash_delay(flash_delay);
4853 BlankSquare(x, y, square_color, piece, xBoardWindow);
4854 XSync(xDisplay, False);
4855 do_flash_delay(flash_delay);
4858 drawfunc(piece, square_color, x, y, xBoardWindow);
4862 string[1] = NULLCHAR;
4863 if (appData.showCoords && row == (flipView ? BOARD_HEIGHT-1 : 0)
4864 && column >= BOARD_LEFT && column < BOARD_RGHT) {
4865 string[0] = 'a' + column - BOARD_LEFT;
4866 XTextExtents(coordFontStruct, string, 1, &direction,
4867 &font_ascent, &font_descent, &overall);
4868 if (appData.monoMode) {
4869 XDrawImageString(xDisplay, xBoardWindow, coordGC,
4870 x + squareSize - overall.width - 2,
4871 y + squareSize - font_descent - 1, string, 1);
4873 XDrawString(xDisplay, xBoardWindow, coordGC,
4874 x + squareSize - overall.width - 2,
4875 y + squareSize - font_descent - 1, string, 1);
4878 if (appData.showCoords && column == (flipView ? BOARD_RGHT-1 : BOARD_LEFT)) {
4879 string[0] = ONE + row;
4880 XTextExtents(coordFontStruct, string, 1, &direction,
4881 &font_ascent, &font_descent, &overall);
4882 if (appData.monoMode) {
4883 XDrawImageString(xDisplay, xBoardWindow, coordGC,
4884 x + 2, y + font_ascent + 1, string, 1);
4886 XDrawString(xDisplay, xBoardWindow, coordGC,
4887 x + 2, y + font_ascent + 1, string, 1);
4893 /* Why is this needed on some versions of X? */
4894 void EventProc(widget, unused, event)
4899 if (!XtIsRealized(widget))
4902 switch (event->type) {
4904 if (event->xexpose.count > 0) return; /* no clipping is done */
4905 XDrawPosition(widget, True, NULL);
4913 void DrawPosition(fullRedraw, board)
4914 /*Boolean*/int fullRedraw;
4917 XDrawPosition(boardWidget, fullRedraw, board);
4920 /* Returns 1 if there are "too many" differences between b1 and b2
4921 (i.e. more than 1 move was made) */
4922 static int too_many_diffs(b1, b2)
4928 for (i=0; i<BOARD_HEIGHT; ++i) {
4929 for (j=0; j<BOARD_WIDTH; ++j) {
4930 if (b1[i][j] != b2[i][j]) {
4931 if (++c > 4) /* Castling causes 4 diffs */
4940 /* Matrix describing castling maneuvers */
4941 /* Row, ColRookFrom, ColKingFrom, ColRookTo, ColKingTo */
4942 static int castling_matrix[4][5] = {
4943 { 0, 0, 4, 3, 2 }, /* 0-0-0, white */
4944 { 0, 7, 4, 5, 6 }, /* 0-0, white */
4945 { 7, 0, 4, 3, 2 }, /* 0-0-0, black */
4946 { 7, 7, 4, 5, 6 } /* 0-0, black */
4949 /* Checks whether castling occurred. If it did, *rrow and *rcol
4950 are set to the destination (row,col) of the rook that moved.
4952 Returns 1 if castling occurred, 0 if not.
4954 Note: Only handles a max of 1 castling move, so be sure
4955 to call too_many_diffs() first.
4957 static int check_castle_draw(newb, oldb, rrow, rcol)
4964 /* For each type of castling... */
4965 for (i=0; i<4; ++i) {
4966 r = castling_matrix[i];
4968 /* Check the 4 squares involved in the castling move */
4970 for (j=1; j<=4; ++j) {
4971 if (newb[r[0]][r[j]] == oldb[r[0]][r[j]]) {
4978 /* All 4 changed, so it must be a castling move */
4987 static int damage[BOARD_SIZE][BOARD_SIZE];
4990 * event handler for redrawing the board
4992 void XDrawPosition(w, repaint, board)
4994 /*Boolean*/int repaint;
4998 static int lastFlipView = 0;
4999 static int lastBoardValid = 0;
5000 static Board lastBoard;
5004 if (board == NULL) {
5005 if (!lastBoardValid) return;
5008 if (!lastBoardValid || lastFlipView != flipView) {
5009 XtSetArg(args[0], XtNleftBitmap, (flipView ? xMarkPixmap : None));
5010 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flip View"),
5015 * It would be simpler to clear the window with XClearWindow()
5016 * but this causes a very distracting flicker.
5019 if (!repaint && lastBoardValid && lastFlipView == flipView) {
5021 /* If too much changes (begin observing new game, etc.), don't
5023 do_flash = too_many_diffs(board, lastBoard) ? 0 : 1;
5025 /* Special check for castling so we don't flash both the king
5026 and the rook (just flash the king). */
5028 if (check_castle_draw(board, lastBoard, &rrow, &rcol)) {
5029 /* Draw rook with NO flashing. King will be drawn flashing later */
5030 DrawSquare(rrow, rcol, board[rrow][rcol], 0);
5031 lastBoard[rrow][rcol] = board[rrow][rcol];
5035 /* First pass -- Draw (newly) empty squares and repair damage.
5036 This prevents you from having a piece show up twice while it
5037 is flashing on its new square */
5038 for (i = 0; i < BOARD_HEIGHT; i++)
5039 for (j = 0; j < BOARD_WIDTH; j++)
5040 if ((board[i][j] != lastBoard[i][j] && board[i][j] == EmptySquare)
5042 DrawSquare(i, j, board[i][j], 0);
5043 damage[i][j] = False;
5046 /* Second pass -- Draw piece(s) in new position and flash them */
5047 for (i = 0; i < BOARD_HEIGHT; i++)
5048 for (j = 0; j < BOARD_WIDTH; j++)
5049 if (board[i][j] != lastBoard[i][j]) {
5050 DrawSquare(i, j, board[i][j], do_flash);
5054 XDrawSegments(xDisplay, xBoardWindow, lineGC,
5055 gridSegments, BOARD_HEIGHT + BOARD_WIDTH + 2);
5057 for (i = 0; i < BOARD_HEIGHT; i++)
5058 for (j = 0; j < BOARD_WIDTH; j++) {
5059 DrawSquare(i, j, board[i][j], 0);
5060 damage[i][j] = False;
5064 CopyBoard(lastBoard, board);
5066 lastFlipView = flipView;
5068 /* Draw highlights */
5069 if (pm1X >= 0 && pm1Y >= 0) {
5070 drawHighlight(pm1X, pm1Y, prelineGC);
5072 if (pm2X >= 0 && pm2Y >= 0) {
5073 drawHighlight(pm2X, pm2Y, prelineGC);
5075 if (hi1X >= 0 && hi1Y >= 0) {
5076 drawHighlight(hi1X, hi1Y, highlineGC);
5078 if (hi2X >= 0 && hi2Y >= 0) {
5079 drawHighlight(hi2X, hi2Y, highlineGC);
5082 /* If piece being dragged around board, must redraw that too */
5085 XSync(xDisplay, False);
5090 * event handler for redrawing the board
5092 void DrawPositionProc(w, event, prms, nprms)
5098 XDrawPosition(w, True, NULL);
5103 * event handler for parsing user moves
5105 // [HGM] This routine will need quite some reworking. Although the backend still supports the old
5106 // way of doing things, by calling UserMoveEvent() to test the legality of the move and then perform
5107 // it at the end, and doing all kind of preliminary tests here (e.g. to weed out self-captures), it
5108 // should be made to use the new way, of calling UserMoveTest early to determine the legality of the
5109 // move, (which will weed out the illegal selfcaptures and moves into the holdings, and flag promotions),
5110 // and at the end FinishMove() to perform the move after optional promotion popups.
5111 // For now I patched it to allow self-capture with King, and suppress clicks between board and holdings.
5112 void HandleUserMove(w, event, prms, nprms)
5119 Boolean saveAnimate;
5120 static int second = 0, promotionChoice = 0;
5123 if (w != boardWidget || errorExitStatus != -1) return;
5125 x = EventToSquare(event->xbutton.x, BOARD_WIDTH);
5126 y = EventToSquare(event->xbutton.y, BOARD_HEIGHT);
5127 if (!flipView && y >= 0) {
5128 y = BOARD_HEIGHT - 1 - y;
5130 if (flipView && x >= 0) {
5131 x = BOARD_WIDTH - 1 - x;
5134 if(promotionChoice) { // we are waiting for a click to indicate promotion piece
5135 if(event->type == ButtonRelease) return; // ignore upclick of click-click destination
5136 promotionChoice = FALSE; // only one chance: if click not OK it is interpreted as cancel
5137 if(appData.debugMode) fprintf(debugFP, "promotion click, x=%d, y=%d\n", x, y);
5138 if(gameInfo.holdingsWidth &&
5139 (WhiteOnMove(currentMove)
5140 ? x == BOARD_WIDTH-1 && y < gameInfo.holdingsSize && y > 0
5141 : x == 0 && y >= BOARD_HEIGHT - gameInfo.holdingsSize && y < BOARD_HEIGHT-1) ) {
5142 // click in right holdings, for determining promotion piece
5143 ChessSquare p = boards[currentMove][y][x];
5144 if(appData.debugMode) fprintf(debugFP, "square contains %d\n", (int)p);
5145 if(p != EmptySquare) {
5146 FinishMove(NormalMove, fromX, fromY, toX, toY, ToLower(PieceToChar(p)));
5151 DrawPosition(FALSE, boards[currentMove]);
5154 if (event->type == ButtonPress) ErrorPopDown();
5157 if (event->type == ButtonPress) {
5158 XtPopdown(promotionShell);
5159 XtDestroyWidget(promotionShell);
5160 promotionUp = False;
5168 /* [HGM] holdings: next 5 lines: ignore all clicks between board and holdings */
5169 if(event->type == ButtonPress
5170 && ( x == BOARD_LEFT-1 || x == BOARD_RGHT
5171 || x == BOARD_LEFT-2 && y < BOARD_HEIGHT-gameInfo.holdingsSize
5172 || x == BOARD_RGHT+1 && y >= gameInfo.holdingsSize) )
5176 if (event->type == ButtonPress) {
5177 /* First square, prepare to drag */
5178 if (OKToStartUserMove(x, y)) {
5182 DragPieceBegin(event->xbutton.x, event->xbutton.y);
5183 if (appData.highlightDragging) {
5184 SetHighlights(x, y, -1, -1);
5192 if (event->type == ButtonRelease && x == fromX && y == fromY) {
5193 /* Click on single square in stead of drag-drop */
5194 DragPieceEnd(event->xbutton.x, event->xbutton.y);
5195 if (appData.animateDragging) {
5196 /* Undo animation damage if any */
5197 DrawPosition(FALSE, NULL);
5200 /* Second up/down in same square; just abort move */
5205 ClearPremoveHighlights();
5207 /* First upclick in same square; start click-click mode */
5208 SetHighlights(x, y, -1, -1);
5213 moveType = UserMoveTest(fromX, fromY, x, y, NULLCHAR, event->type == ButtonRelease);
5215 if (moveType == Comment) { // kludge for indicating capture-own on Press
5216 /* Clicked again on same color piece -- changed his mind */
5217 /* note that re-clicking same square always hits same color piece */
5218 second = (x == fromX && y == fromY);
5219 if (appData.highlightDragging) {
5220 SetHighlights(x, y, -1, -1);
5224 if (OKToStartUserMove(x, y)) {
5227 DragPieceBegin(event->xbutton.x, event->xbutton.y);
5232 if(moveType == AmbiguousMove) { // kludge to indicate edit-position move
5235 DragPieceEnd(event->xbutton.x, event->xbutton.y);
5236 DrawPosition(FALSE, boards[currentMove]);
5240 /* Complete move; (x,y) is now different from (fromX, fromY) on both Press and Release */
5243 saveAnimate = appData.animate;
5244 if (event->type == ButtonPress) {
5245 /* Finish clickclick move */
5246 if (appData.animate || appData.highlightLastMove) {
5247 SetHighlights(fromX, fromY, toX, toY);
5252 /* Finish drag move */
5253 if (appData.highlightLastMove) {
5254 SetHighlights(fromX, fromY, toX, toY);
5258 DragPieceEnd(event->xbutton.x, event->xbutton.y);
5259 /* Don't animate move and drag both */
5260 appData.animate = FALSE;
5262 if (moveType == WhitePromotionKnight || moveType == BlackPromotionKnight ||
5263 (moveType == WhitePromotionQueen || moveType == BlackPromotionQueen) &&
5264 appData.alwaysPromoteToQueen) { // promotion, but no choice
5265 FinishMove(moveType, fromX, fromY, toX, toY, 'q');
5267 if (moveType == WhitePromotionQueen || moveType == BlackPromotionQueen ) {
5268 SetHighlights(fromX, fromY, toX, toY);
5269 if(gameInfo.variant == VariantSuper || gameInfo.variant == VariantGreat) {
5270 // [HGM] super: promotion to captured piece selected from holdings
5271 ChessSquare p = boards[currentMove][fromY][fromX], q = boards[currentMove][toY][toX];
5272 promotionChoice = TRUE;
5273 // kludge follows to temporarily execute move on display, without promoting yet
5274 boards[currentMove][fromY][fromX] = EmptySquare; // move Pawn to 8th rank
5275 boards[currentMove][toY][toX] = p;
5276 DrawPosition(FALSE, boards[currentMove]);
5277 boards[currentMove][fromY][fromX] = p; // take back, but display stays
5278 boards[currentMove][toY][toX] = q;
5279 DisplayMessage("Click in holdings to choose piece", "");
5283 goto skipClearingFrom; // the skipped stuff is done asynchronously by PromotionCallback
5285 if(moveType != ImpossibleMove) { // valid move, but no promotion
5286 FinishMove(moveType, fromX, fromY, toX, toY, NULLCHAR);
5287 } else { // invalid move; could have set premove
5290 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
5291 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
5294 appData.animate = saveAnimate;
5295 if (appData.animate || appData.animateDragging) {
5296 /* Undo animation damage if needed */
5297 DrawPosition(FALSE, NULL);
5301 void AnimateUserMove (Widget w, XEvent * event,
5302 String * params, Cardinal * nParams)
5304 DragPieceMove(event->xmotion.x, event->xmotion.y);
5307 Widget CommentCreate(name, text, mutable, callback, lines)
5309 int /*Boolean*/ mutable;
5310 XtCallbackProc callback;
5314 Widget shell, layout, form, edit, b_ok, b_cancel, b_clear, b_close, b_edit;
5319 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5320 XtGetValues(boardWidget, args, j);
5323 XtSetArg(args[j], XtNresizable, True); j++;
5326 XtCreatePopupShell(name, topLevelShellWidgetClass,
5327 shellWidget, args, j);
5330 XtCreatePopupShell(name, transientShellWidgetClass,
5331 shellWidget, args, j);
5334 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
5335 layoutArgs, XtNumber(layoutArgs));
5337 XtCreateManagedWidget("form", formWidgetClass, layout,
5338 formArgs, XtNumber(formArgs));
5342 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
5343 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
5345 XtSetArg(args[j], XtNstring, text); j++;
5346 XtSetArg(args[j], XtNtop, XtChainTop); j++;
5347 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5348 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5349 XtSetArg(args[j], XtNright, XtChainRight); j++;
5350 XtSetArg(args[j], XtNresizable, True); j++;
5351 XtSetArg(args[j], XtNwidth, bw_width); j++; /*force wider than buttons*/
5352 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
5353 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
5354 XtSetArg(args[j], XtNautoFill, True); j++;
5355 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
5357 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
5361 XtSetArg(args[j], XtNfromVert, edit); j++;
5362 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5363 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5364 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5365 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5367 XtCreateManagedWidget(_("ok"), commandWidgetClass, form, args, j);
5368 XtAddCallback(b_ok, XtNcallback, callback, (XtPointer) 0);
5371 XtSetArg(args[j], XtNfromVert, edit); j++;
5372 XtSetArg(args[j], XtNfromHoriz, b_ok); j++;
5373 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5374 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5375 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5376 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5378 XtCreateManagedWidget(_("cancel"), commandWidgetClass, form, args, j);
5379 XtAddCallback(b_cancel, XtNcallback, callback, (XtPointer) 0);
5382 XtSetArg(args[j], XtNfromVert, edit); j++;
5383 XtSetArg(args[j], XtNfromHoriz, b_cancel); j++;
5384 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5385 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5386 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5387 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5389 XtCreateManagedWidget(_("clear"), commandWidgetClass, form, args, j);
5390 XtAddCallback(b_clear, XtNcallback, callback, (XtPointer) 0);
5393 XtSetArg(args[j], XtNfromVert, edit); j++;
5394 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5395 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5396 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5397 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5399 XtCreateManagedWidget(_("close"), commandWidgetClass, form, args, j);
5400 XtAddCallback(b_close, XtNcallback, callback, (XtPointer) 0);
5403 XtSetArg(args[j], XtNfromVert, edit); j++;
5404 XtSetArg(args[j], XtNfromHoriz, b_close); j++;
5405 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5406 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5407 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5408 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5410 XtCreateManagedWidget(_("edit"), commandWidgetClass, form, args, j);
5411 XtAddCallback(b_edit, XtNcallback, callback, (XtPointer) 0);
5414 XtRealizeWidget(shell);
5416 if (commentX == -1) {
5419 Dimension pw_height;
5420 Dimension ew_height;
5423 XtSetArg(args[j], XtNheight, &ew_height); j++;
5424 XtGetValues(edit, args, j);
5427 XtSetArg(args[j], XtNheight, &pw_height); j++;
5428 XtGetValues(shell, args, j);
5429 commentH = pw_height + (lines - 1) * ew_height;
5430 commentW = bw_width - 16;
5432 XSync(xDisplay, False);
5434 /* This code seems to tickle an X bug if it is executed too soon
5435 after xboard starts up. The coordinates get transformed as if
5436 the main window was positioned at (0, 0).
5438 XtTranslateCoords(shellWidget,
5439 (bw_width - commentW) / 2, 0 - commentH / 2,
5440 &commentX, &commentY);
5442 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
5443 RootWindowOfScreen(XtScreen(shellWidget)),
5444 (bw_width - commentW) / 2, 0 - commentH / 2,
5449 if (commentY < 0) commentY = 0; /*avoid positioning top offscreen*/
5452 XtSetArg(args[j], XtNheight, commentH); j++;
5453 XtSetArg(args[j], XtNwidth, commentW); j++;
5454 XtSetArg(args[j], XtNx, commentX); j++;
5455 XtSetArg(args[j], XtNy, commentY); j++;
5456 XtSetValues(shell, args, j);
5457 XtSetKeyboardFocus(shell, edit);
5462 /* Used for analysis window and ICS input window */
5463 Widget MiscCreate(name, text, mutable, callback, lines)
5465 int /*Boolean*/ mutable;
5466 XtCallbackProc callback;
5470 Widget shell, layout, form, edit;
5472 Dimension bw_width, pw_height, ew_height, w, h;
5478 XtSetArg(args[j], XtNresizable, True); j++;
5481 XtCreatePopupShell(name, topLevelShellWidgetClass,
5482 shellWidget, args, j);
5485 XtCreatePopupShell(name, transientShellWidgetClass,
5486 shellWidget, args, j);
5489 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
5490 layoutArgs, XtNumber(layoutArgs));
5492 XtCreateManagedWidget("form", formWidgetClass, layout,
5493 formArgs, XtNumber(formArgs));
5497 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
5498 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
5500 XtSetArg(args[j], XtNstring, text); j++;
5501 XtSetArg(args[j], XtNtop, XtChainTop); j++;
5502 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5503 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5504 XtSetArg(args[j], XtNright, XtChainRight); j++;
5505 XtSetArg(args[j], XtNresizable, True); j++;
5506 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
5507 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
5508 XtSetArg(args[j], XtNautoFill, True); j++;
5509 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
5511 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
5513 XtRealizeWidget(shell);
5516 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5517 XtGetValues(boardWidget, args, j);
5520 XtSetArg(args[j], XtNheight, &ew_height); j++;
5521 XtGetValues(edit, args, j);
5524 XtSetArg(args[j], XtNheight, &pw_height); j++;
5525 XtGetValues(shell, args, j);
5526 h = pw_height + (lines - 1) * ew_height;
5529 XSync(xDisplay, False);
5531 /* This code seems to tickle an X bug if it is executed too soon
5532 after xboard starts up. The coordinates get transformed as if
5533 the main window was positioned at (0, 0).
5535 XtTranslateCoords(shellWidget, (bw_width - w) / 2, 0 - h / 2, &x, &y);
5537 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
5538 RootWindowOfScreen(XtScreen(shellWidget)),
5539 (bw_width - w) / 2, 0 - h / 2, &xx, &yy, &junk);
5543 if (y < 0) y = 0; /*avoid positioning top offscreen*/
5546 XtSetArg(args[j], XtNheight, h); j++;
5547 XtSetArg(args[j], XtNwidth, w); j++;
5548 XtSetArg(args[j], XtNx, x); j++;
5549 XtSetArg(args[j], XtNy, y); j++;
5550 XtSetValues(shell, args, j);
5556 static int savedIndex; /* gross that this is global */
5558 void EditCommentPopUp(index, title, text)
5567 if (text == NULL) text = "";
5569 if (editShell == NULL) {
5571 CommentCreate(title, text, True, EditCommentCallback, 4);
5572 XtRealizeWidget(editShell);
5573 CatchDeleteWindow(editShell, "EditCommentPopDown");
5575 edit = XtNameToWidget(editShell, "*form.text");
5577 XtSetArg(args[j], XtNstring, text); j++;
5578 XtSetValues(edit, args, j);
5580 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5581 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5582 XtSetValues(editShell, args, j);
5585 XtPopup(editShell, XtGrabNone);
5589 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
5590 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
5594 void EditCommentCallback(w, client_data, call_data)
5596 XtPointer client_data, call_data;
5604 XtSetArg(args[j], XtNlabel, &name); j++;
5605 XtGetValues(w, args, j);
5607 if (strcmp(name, _("ok")) == 0) {
5608 edit = XtNameToWidget(editShell, "*form.text");
5610 XtSetArg(args[j], XtNstring, &val); j++;
5611 XtGetValues(edit, args, j);
5612 ReplaceComment(savedIndex, val);
5613 EditCommentPopDown();
5614 } else if (strcmp(name, _("cancel")) == 0) {
5615 EditCommentPopDown();
5616 } else if (strcmp(name, _("clear")) == 0) {
5617 edit = XtNameToWidget(editShell, "*form.text");
5618 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
5619 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
5623 void EditCommentPopDown()
5628 if (!editUp) return;
5630 XtSetArg(args[j], XtNx, &commentX); j++;
5631 XtSetArg(args[j], XtNy, &commentY); j++;
5632 XtSetArg(args[j], XtNheight, &commentH); j++;
5633 XtSetArg(args[j], XtNwidth, &commentW); j++;
5634 XtGetValues(editShell, args, j);
5635 XtPopdown(editShell);
5638 XtSetArg(args[j], XtNleftBitmap, None); j++;
5639 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
5643 void ICSInputBoxPopUp()
5648 char *title = _("ICS Input");
5651 if (ICSInputShell == NULL) {
5652 ICSInputShell = MiscCreate(title, "", True, NULL, 1);
5653 tr = XtParseTranslationTable(ICSInputTranslations);
5654 edit = XtNameToWidget(ICSInputShell, "*form.text");
5655 XtOverrideTranslations(edit, tr);
5656 XtRealizeWidget(ICSInputShell);
5657 CatchDeleteWindow(ICSInputShell, "ICSInputBoxPopDown");
5660 edit = XtNameToWidget(ICSInputShell, "*form.text");
5662 XtSetArg(args[j], XtNstring, ""); j++;
5663 XtSetValues(edit, args, j);
5665 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5666 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5667 XtSetValues(ICSInputShell, args, j);
5670 XtPopup(ICSInputShell, XtGrabNone);
5671 XtSetKeyboardFocus(ICSInputShell, edit);
5673 ICSInputBoxUp = True;
5675 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
5676 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
5680 void ICSInputSendText()
5687 edit = XtNameToWidget(ICSInputShell, "*form.text");
5689 XtSetArg(args[j], XtNstring, &val); j++;
5690 XtGetValues(edit, args, j);
5691 SendMultiLineToICS(val);
5692 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
5693 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
5696 void ICSInputBoxPopDown()
5701 if (!ICSInputBoxUp) return;
5703 XtPopdown(ICSInputShell);
5704 ICSInputBoxUp = False;
5706 XtSetArg(args[j], XtNleftBitmap, None); j++;
5707 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
5711 void CommentPopUp(title, text)
5718 if (commentShell == NULL) {
5720 CommentCreate(title, text, False, CommentCallback, 4);
5721 XtRealizeWidget(commentShell);
5722 CatchDeleteWindow(commentShell, "CommentPopDown");
5724 edit = XtNameToWidget(commentShell, "*form.text");
5726 XtSetArg(args[j], XtNstring, text); j++;
5727 XtSetValues(edit, args, j);
5729 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5730 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5731 XtSetValues(commentShell, args, j);
5734 XtPopup(commentShell, XtGrabNone);
5735 XSync(xDisplay, False);
5740 void AnalysisPopUp(title, text)
5747 if (analysisShell == NULL) {
5748 analysisShell = MiscCreate(title, text, False, NULL, 4);
5749 XtRealizeWidget(analysisShell);
5750 CatchDeleteWindow(analysisShell, "AnalysisPopDown");
5753 edit = XtNameToWidget(analysisShell, "*form.text");
5755 XtSetArg(args[j], XtNstring, text); j++;
5756 XtSetValues(edit, args, j);
5758 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5759 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5760 XtSetValues(analysisShell, args, j);
5764 XtPopup(analysisShell, XtGrabNone);
5766 XSync(xDisplay, False);
5771 void CommentCallback(w, client_data, call_data)
5773 XtPointer client_data, call_data;
5780 XtSetArg(args[j], XtNlabel, &name); j++;
5781 XtGetValues(w, args, j);
5783 if (strcmp(name, _("close")) == 0) {
5785 } else if (strcmp(name, _("edit")) == 0) {
5792 void CommentPopDown()
5797 if (!commentUp) return;
5799 XtSetArg(args[j], XtNx, &commentX); j++;
5800 XtSetArg(args[j], XtNy, &commentY); j++;
5801 XtSetArg(args[j], XtNwidth, &commentW); j++;
5802 XtSetArg(args[j], XtNheight, &commentH); j++;
5803 XtGetValues(commentShell, args, j);
5804 XtPopdown(commentShell);
5805 XSync(xDisplay, False);
5809 void AnalysisPopDown()
5811 if (!analysisUp) return;
5812 XtPopdown(analysisShell);
5813 XSync(xDisplay, False);
5815 if (appData.icsEngineAnalyze) ExitAnalyzeMode(); /* [DM] icsEngineAnalyze */
5819 void FileNamePopUp(label, def, proc, openMode)
5826 Widget popup, layout, dialog, edit;
5832 fileProc = proc; /* I can't see a way not */
5833 fileOpenMode = openMode; /* to use globals here */
5836 XtSetArg(args[i], XtNresizable, True); i++;
5837 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
5838 XtSetArg(args[i], XtNtitle, XtNewString(_("File name prompt"))); i++;
5839 fileNameShell = popup =
5840 XtCreatePopupShell("File name prompt", transientShellWidgetClass,
5841 shellWidget, args, i);
5844 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
5845 layoutArgs, XtNumber(layoutArgs));
5848 XtSetArg(args[i], XtNlabel, label); i++;
5849 XtSetArg(args[i], XtNvalue, def); i++;
5850 XtSetArg(args[i], XtNborderWidth, 0); i++;
5851 dialog = XtCreateManagedWidget("fileName", dialogWidgetClass,
5854 XawDialogAddButton(dialog, _("ok"), FileNameCallback, (XtPointer) dialog);
5855 XawDialogAddButton(dialog, _("cancel"), FileNameCallback,
5856 (XtPointer) dialog);
5858 XtRealizeWidget(popup);
5859 CatchDeleteWindow(popup, "FileNamePopDown");
5861 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
5862 &x, &y, &win_x, &win_y, &mask);
5864 XtSetArg(args[0], XtNx, x - 10);
5865 XtSetArg(args[1], XtNy, y - 30);
5866 XtSetValues(popup, args, 2);
5868 XtPopup(popup, XtGrabExclusive);
5871 edit = XtNameToWidget(dialog, "*value");
5872 XtSetKeyboardFocus(popup, edit);
5875 void FileNamePopDown()
5877 if (!filenameUp) return;
5878 XtPopdown(fileNameShell);
5879 XtDestroyWidget(fileNameShell);
5884 void FileNameCallback(w, client_data, call_data)
5886 XtPointer client_data, call_data;
5891 XtSetArg(args[0], XtNlabel, &name);
5892 XtGetValues(w, args, 1);
5894 if (strcmp(name, _("cancel")) == 0) {
5899 FileNameAction(w, NULL, NULL, NULL);
5902 void FileNameAction(w, event, prms, nprms)
5914 name = XawDialogGetValueString(w = XtParent(w));
5916 if ((name != NULL) && (*name != NULLCHAR)) {
5918 XtPopdown(w = XtParent(XtParent(w)));
5922 p = strrchr(buf, ' ');
5929 fullname = ExpandPathName(buf);
5931 ErrorPopUp(_("Error"), _("Can't open file"), FALSE);
5934 f = fopen(fullname, fileOpenMode);
5936 DisplayError(_("Failed to open file"), errno);
5938 (void) (*fileProc)(f, index, buf);
5945 XtPopdown(w = XtParent(XtParent(w)));
5951 void PromotionPopUp()
5954 Widget dialog, layout;
5956 Dimension bw_width, pw_width;
5960 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5961 XtGetValues(boardWidget, args, j);
5964 XtSetArg(args[j], XtNresizable, True); j++;
5965 XtSetArg(args[j], XtNtitle, XtNewString(_("Promotion"))); j++;
5967 XtCreatePopupShell("Promotion", transientShellWidgetClass,
5968 shellWidget, args, j);
5970 XtCreateManagedWidget(layoutName, formWidgetClass, promotionShell,
5971 layoutArgs, XtNumber(layoutArgs));
5974 XtSetArg(args[j], XtNlabel, _("Promote to what?")); j++;
5975 XtSetArg(args[j], XtNborderWidth, 0); j++;
5976 dialog = XtCreateManagedWidget("promotion", dialogWidgetClass,
5979 if(gameInfo.variant != VariantShogi) {
5980 XawDialogAddButton(dialog, _("Queen"), PromotionCallback,
5981 (XtPointer) dialog);
5982 XawDialogAddButton(dialog, _("Rook"), PromotionCallback,
5983 (XtPointer) dialog);
5984 XawDialogAddButton(dialog, _("Bishop"), PromotionCallback,
5985 (XtPointer) dialog);
5986 XawDialogAddButton(dialog, _("Knight"), PromotionCallback,
5987 (XtPointer) dialog);
5988 if (!appData.testLegality || gameInfo.variant == VariantSuicide ||
5989 gameInfo.variant == VariantGiveaway) {
5990 XawDialogAddButton(dialog, _("King"), PromotionCallback,
5991 (XtPointer) dialog);
5993 if(gameInfo.variant == VariantCapablanca ||
5994 gameInfo.variant == VariantGothic ||
5995 gameInfo.variant == VariantCapaRandom) {
5996 XawDialogAddButton(dialog, _("Archbishop"), PromotionCallback,
5997 (XtPointer) dialog);
5998 XawDialogAddButton(dialog, _("Chancellor"), PromotionCallback,
5999 (XtPointer) dialog);
6001 } else // [HGM] shogi
6003 XawDialogAddButton(dialog, _("Promote"), PromotionCallback,
6004 (XtPointer) dialog);
6005 XawDialogAddButton(dialog, _("Defer"), PromotionCallback,
6006 (XtPointer) dialog);
6008 XawDialogAddButton(dialog, _("cancel"), PromotionCallback,
6009 (XtPointer) dialog);
6011 XtRealizeWidget(promotionShell);
6012 CatchDeleteWindow(promotionShell, "PromotionPopDown");
6015 XtSetArg(args[j], XtNwidth, &pw_width); j++;
6016 XtGetValues(promotionShell, args, j);
6018 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
6019 lineGap + squareSize/3 +
6020 ((toY == BOARD_HEIGHT-1) ^ (flipView) ?
6021 0 : 6*(squareSize + lineGap)), &x, &y);
6024 XtSetArg(args[j], XtNx, x); j++;
6025 XtSetArg(args[j], XtNy, y); j++;
6026 XtSetValues(promotionShell, args, j);
6028 XtPopup(promotionShell, XtGrabNone);
6033 void PromotionPopDown()
6035 if (!promotionUp) return;
6036 XtPopdown(promotionShell);
6037 XtDestroyWidget(promotionShell);
6038 promotionUp = False;
6041 void PromotionCallback(w, client_data, call_data)
6043 XtPointer client_data, call_data;
6049 XtSetArg(args[0], XtNlabel, &name);
6050 XtGetValues(w, args, 1);
6054 if (fromX == -1) return;
6056 if (strcmp(name, _("cancel")) == 0) {
6060 } else if (strcmp(name, _("Knight")) == 0) {
6062 } else if (strcmp(name, _("Promote")) == 0) {
6064 } else if (strcmp(name, _("Defer")) == 0) {
6067 promoChar = ToLower(name[0]);
6070 FinishMove(NormalMove, fromX, fromY, toX, toY, promoChar);
6072 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
6073 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
6078 void ErrorCallback(w, client_data, call_data)
6080 XtPointer client_data, call_data;
6083 XtPopdown(w = XtParent(XtParent(XtParent(w))));
6085 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
6091 if (!errorUp) return;
6093 XtPopdown(errorShell);
6094 XtDestroyWidget(errorShell);
6095 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
6098 void ErrorPopUp(title, label, modal)
6099 char *title, *label;
6103 Widget dialog, layout;
6107 Dimension bw_width, pw_width;
6108 Dimension pw_height;
6112 XtSetArg(args[i], XtNresizable, True); i++;
6113 XtSetArg(args[i], XtNtitle, title); i++;
6115 XtCreatePopupShell("errorpopup", transientShellWidgetClass,
6116 shellWidget, args, i);
6118 XtCreateManagedWidget(layoutName, formWidgetClass, errorShell,
6119 layoutArgs, XtNumber(layoutArgs));
6122 XtSetArg(args[i], XtNlabel, label); i++;
6123 XtSetArg(args[i], XtNborderWidth, 0); i++;
6124 dialog = XtCreateManagedWidget("dialog", dialogWidgetClass,
6127 XawDialogAddButton(dialog, _("ok"), ErrorCallback, (XtPointer) dialog);
6129 XtRealizeWidget(errorShell);
6130 CatchDeleteWindow(errorShell, "ErrorPopDown");
6133 XtSetArg(args[i], XtNwidth, &bw_width); i++;
6134 XtGetValues(boardWidget, args, i);
6136 XtSetArg(args[i], XtNwidth, &pw_width); i++;
6137 XtSetArg(args[i], XtNheight, &pw_height); i++;
6138 XtGetValues(errorShell, args, i);
6141 /* This code seems to tickle an X bug if it is executed too soon
6142 after xboard starts up. The coordinates get transformed as if
6143 the main window was positioned at (0, 0).
6145 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
6146 0 - pw_height + squareSize / 3, &x, &y);
6148 XTranslateCoordinates(xDisplay, XtWindow(boardWidget),
6149 RootWindowOfScreen(XtScreen(boardWidget)),
6150 (bw_width - pw_width) / 2,
6151 0 - pw_height + squareSize / 3, &xx, &yy, &junk);
6155 if (y < 0) y = 0; /*avoid positioning top offscreen*/
6158 XtSetArg(args[i], XtNx, x); i++;
6159 XtSetArg(args[i], XtNy, y); i++;
6160 XtSetValues(errorShell, args, i);
6163 XtPopup(errorShell, modal ? XtGrabExclusive : XtGrabNone);
6166 /* Disable all user input other than deleting the window */
6167 static int frozen = 0;
6171 /* Grab by a widget that doesn't accept input */
6172 XtAddGrab(messageWidget, TRUE, FALSE);
6176 /* Undo a FreezeUI */
6179 if (!frozen) return;
6180 XtRemoveGrab(messageWidget);
6184 char *ModeToWidgetName(mode)
6188 case BeginningOfGame:
6189 if (appData.icsActive)
6190 return "menuMode.ICS Client";
6191 else if (appData.noChessProgram ||
6192 *appData.cmailGameName != NULLCHAR)
6193 return "menuMode.Edit Game";
6195 return "menuMode.Machine Black";
6196 case MachinePlaysBlack:
6197 return "menuMode.Machine Black";
6198 case MachinePlaysWhite:
6199 return "menuMode.Machine White";
6201 return "menuMode.Analysis Mode";
6203 return "menuMode.Analyze File";
6204 case TwoMachinesPlay:
6205 return "menuMode.Two Machines";
6207 return "menuMode.Edit Game";
6208 case PlayFromGameFile:
6209 return "menuFile.Load Game";
6211 return "menuMode.Edit Position";
6213 return "menuMode.Training";
6214 case IcsPlayingWhite:
6215 case IcsPlayingBlack:
6219 return "menuMode.ICS Client";
6226 void ModeHighlight()
6229 static int oldPausing = FALSE;
6230 static GameMode oldmode = (GameMode) -1;
6233 if (!boardWidget || !XtIsRealized(boardWidget)) return;
6235 if (pausing != oldPausing) {
6236 oldPausing = pausing;
6238 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6240 XtSetArg(args[0], XtNleftBitmap, None);
6242 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Pause"),
6245 if (appData.showButtonBar) {
6246 /* Always toggle, don't set. Previous code messes up when
6247 invoked while the button is pressed, as releasing it
6248 toggles the state again. */
6251 XtSetArg(args[0], XtNbackground, &oldbg);
6252 XtSetArg(args[1], XtNforeground, &oldfg);
6253 XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON),
6255 XtSetArg(args[0], XtNbackground, oldfg);
6256 XtSetArg(args[1], XtNforeground, oldbg);
6258 XtSetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
6262 wname = ModeToWidgetName(oldmode);
6263 if (wname != NULL) {
6264 XtSetArg(args[0], XtNleftBitmap, None);
6265 XtSetValues(XtNameToWidget(menuBarWidget, wname), args, 1);
6267 wname = ModeToWidgetName(gameMode);
6268 if (wname != NULL) {
6269 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6270 XtSetValues(XtNameToWidget(menuBarWidget, wname), args, 1);
6274 /* Maybe all the enables should be handled here, not just this one */
6275 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Training"),
6276 gameMode == Training || gameMode == PlayFromGameFile);
6281 * Button/menu procedures
6283 void ResetProc(w, event, prms, nprms)
6293 int LoadGamePopUp(f, gameNumber, title)
6298 cmailMsgLoaded = FALSE;
6299 if (gameNumber == 0) {
6300 int error = GameListBuild(f);
6302 DisplayError(_("Cannot build game list"), error);
6303 } else if (!ListEmpty(&gameList) &&
6304 ((ListGame *) gameList.tailPred)->number > 1) {
6305 GameListPopUp(f, title);
6311 return LoadGame(f, gameNumber, title, FALSE);
6314 void LoadGameProc(w, event, prms, nprms)
6320 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
6323 FileNamePopUp(_("Load game file name?"), "", LoadGamePopUp, "rb");
6326 void LoadNextGameProc(w, event, prms, nprms)
6335 void LoadPrevGameProc(w, event, prms, nprms)
6344 void ReloadGameProc(w, event, prms, nprms)
6353 void LoadNextPositionProc(w, event, prms, nprms)
6362 void LoadPrevPositionProc(w, event, prms, nprms)
6371 void ReloadPositionProc(w, event, prms, nprms)
6380 void LoadPositionProc(w, event, prms, nprms)
6386 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
6389 FileNamePopUp(_("Load position file name?"), "", LoadPosition, "rb");
6392 void SaveGameProc(w, event, prms, nprms)
6398 FileNamePopUp(_("Save game file name?"),
6399 DefaultFileName(appData.oldSaveStyle ? "game" : "pgn"),
6403 void SavePositionProc(w, event, prms, nprms)
6409 FileNamePopUp(_("Save position file name?"),
6410 DefaultFileName(appData.oldSaveStyle ? "pos" : "fen"),
6414 void ReloadCmailMsgProc(w, event, prms, nprms)
6420 ReloadCmailMsgEvent(FALSE);
6423 void MailMoveProc(w, event, prms, nprms)
6432 /* this variable is shared between CopyPositionProc and SendPositionSelection */
6433 static char *selected_fen_position=NULL;
6436 SendPositionSelection(Widget w, Atom *selection, Atom *target,
6437 Atom *type_return, XtPointer *value_return,
6438 unsigned long *length_return, int *format_return)
6440 char *selection_tmp;
6442 if (!selected_fen_position) return False; /* should never happen */
6443 if (*target == XA_STRING){
6444 /* note: since no XtSelectionDoneProc was registered, Xt will
6445 * automatically call XtFree on the value returned. So have to
6446 * make a copy of it allocated with XtMalloc */
6447 selection_tmp= XtMalloc(strlen(selected_fen_position)+16);
6448 strcpy(selection_tmp, selected_fen_position);
6450 *value_return=selection_tmp;
6451 *length_return=strlen(selection_tmp);
6452 *type_return=XA_STRING;
6453 *format_return = 8; /* bits per byte */
6460 /* note: when called from menu all parameters are NULL, so no clue what the
6461 * Widget which was clicked on was, or what the click event was
6463 void CopyPositionProc(w, event, prms, nprms)
6471 if (selected_fen_position) free(selected_fen_position);
6472 selected_fen_position = (char *)PositionToFEN(currentMove, NULL);
6473 if (!selected_fen_position) return;
6474 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
6476 SendPositionSelection,
6477 NULL/* lose_ownership_proc */ ,
6478 NULL/* transfer_done_proc */);
6480 free(selected_fen_position);
6481 selected_fen_position=NULL;
6485 /* function called when the data to Paste is ready */
6487 PastePositionCB(Widget w, XtPointer client_data, Atom *selection,
6488 Atom *type, XtPointer value, unsigned long *len, int *format)
6491 if (value==NULL || *len==0) return; /* nothing had been selected to copy */
6492 fenstr[*len]='\0'; /* normally this string is terminated, but be safe */
6493 EditPositionPasteFEN(fenstr);
6497 /* called when Paste Position button is pressed,
6498 * all parameters will be NULL */
6499 void PastePositionProc(w, event, prms, nprms)
6505 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
6506 /* (XtSelectionCallbackProc) */ PastePositionCB,
6507 NULL, /* client_data passed to PastePositionCB */
6509 /* better to use the time field from the event that triggered the
6510 * call to this function, but that isn't trivial to get
6518 SendGameSelection(Widget w, Atom *selection, Atom *target,
6519 Atom *type_return, XtPointer *value_return,
6520 unsigned long *length_return, int *format_return)
6522 char *selection_tmp;
6524 if (*target == XA_STRING){
6525 FILE* f = fopen(gameCopyFilename, "r");
6528 if (f == NULL) return False;
6532 selection_tmp = XtMalloc(len + 1);
6533 count = fread(selection_tmp, 1, len, f);
6535 XtFree(selection_tmp);
6538 selection_tmp[len] = NULLCHAR;
6539 *value_return = selection_tmp;
6540 *length_return = len;
6541 *type_return = XA_STRING;
6542 *format_return = 8; /* bits per byte */
6549 /* note: when called from menu all parameters are NULL, so no clue what the
6550 * Widget which was clicked on was, or what the click event was
6552 void CopyGameProc(w, event, prms, nprms)
6560 ret = SaveGameToFile(gameCopyFilename, FALSE);
6563 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
6566 NULL/* lose_ownership_proc */ ,
6567 NULL/* transfer_done_proc */);
6570 /* function called when the data to Paste is ready */
6572 PasteGameCB(Widget w, XtPointer client_data, Atom *selection,
6573 Atom *type, XtPointer value, unsigned long *len, int *format)
6576 if (value == NULL || *len == 0) {
6577 return; /* nothing had been selected to copy */
6579 f = fopen(gamePasteFilename, "w");
6581 DisplayError(_("Can't open temp file"), errno);
6584 fwrite(value, 1, *len, f);
6587 LoadGameFromFile(gamePasteFilename, 0, gamePasteFilename, TRUE);
6590 /* called when Paste Game button is pressed,
6591 * all parameters will be NULL */
6592 void PasteGameProc(w, event, prms, nprms)
6598 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
6599 /* (XtSelectionCallbackProc) */ PasteGameCB,
6600 NULL, /* client_data passed to PasteGameCB */
6602 /* better to use the time field from the event that triggered the
6603 * call to this function, but that isn't trivial to get
6613 SaveGameProc(NULL, NULL, NULL, NULL);
6617 void QuitProc(w, event, prms, nprms)
6626 void PauseProc(w, event, prms, nprms)
6636 void MachineBlackProc(w, event, prms, nprms)
6642 MachineBlackEvent();
6645 void MachineWhiteProc(w, event, prms, nprms)
6651 MachineWhiteEvent();
6654 void AnalyzeModeProc(w, event, prms, nprms)
6662 if (!first.analysisSupport) {
6663 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
6664 DisplayError(buf, 0);
6667 /* [DM] icsEngineAnalyze [HGM] This is horrible code; reverse the gameMode and isEngineAnalyze tests! */
6668 if (appData.icsActive) {
6669 if (gameMode != IcsObserving) {
6670 sprintf(buf,_("You are not observing a game"));
6671 DisplayError(buf, 0);
6673 if (appData.icsEngineAnalyze) {
6674 if (appData.debugMode)
6675 fprintf(debugFP, _("Found unexpected active ICS engine analyze \n"));
6681 /* if enable, use want disable icsEngineAnalyze */
6682 if (appData.icsEngineAnalyze) {
6687 appData.icsEngineAnalyze = TRUE;
6688 if (appData.debugMode)
6689 fprintf(debugFP, _("ICS engine analyze starting... \n"));
6691 if (!appData.showThinking)
6692 ShowThinkingProc(w,event,prms,nprms);
6697 void AnalyzeFileProc(w, event, prms, nprms)
6703 if (!first.analysisSupport) {
6705 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
6706 DisplayError(buf, 0);
6711 if (!appData.showThinking)
6712 ShowThinkingProc(w,event,prms,nprms);
6715 FileNamePopUp(_("File to analyze"), "", LoadGamePopUp, "rb");
6716 AnalysisPeriodicEvent(1);
6719 void TwoMachinesProc(w, event, prms, nprms)
6728 void IcsClientProc(w, event, prms, nprms)
6737 void EditGameProc(w, event, prms, nprms)
6746 void EditPositionProc(w, event, prms, nprms)
6752 EditPositionEvent();
6755 void TrainingProc(w, event, prms, nprms)
6764 void EditCommentProc(w, event, prms, nprms)
6771 EditCommentPopDown();
6777 void IcsInputBoxProc(w, event, prms, nprms)
6783 if (ICSInputBoxUp) {
6784 ICSInputBoxPopDown();
6790 void AcceptProc(w, event, prms, nprms)
6799 void DeclineProc(w, event, prms, nprms)
6808 void RematchProc(w, event, prms, nprms)
6817 void CallFlagProc(w, event, prms, nprms)
6826 void DrawProc(w, event, prms, nprms)
6835 void AbortProc(w, event, prms, nprms)
6844 void AdjournProc(w, event, prms, nprms)
6853 void ResignProc(w, event, prms, nprms)
6862 void AdjuWhiteProc(w, event, prms, nprms)
6868 UserAdjudicationEvent(+1);
6871 void AdjuBlackProc(w, event, prms, nprms)
6877 UserAdjudicationEvent(-1);
6880 void AdjuDrawProc(w, event, prms, nprms)
6886 UserAdjudicationEvent(0);
6889 void EnterKeyProc(w, event, prms, nprms)
6895 if (ICSInputBoxUp == True)
6899 void StopObservingProc(w, event, prms, nprms)
6905 StopObservingEvent();
6908 void StopExaminingProc(w, event, prms, nprms)
6914 StopExaminingEvent();
6918 void ForwardProc(w, event, prms, nprms)
6928 void BackwardProc(w, event, prms, nprms)
6937 void ToStartProc(w, event, prms, nprms)
6946 void ToEndProc(w, event, prms, nprms)
6955 void RevertProc(w, event, prms, nprms)
6964 void TruncateGameProc(w, event, prms, nprms)
6970 TruncateGameEvent();
6972 void RetractMoveProc(w, event, prms, nprms)
6981 void MoveNowProc(w, event, prms, nprms)
6991 void AlwaysQueenProc(w, event, prms, nprms)
6999 appData.alwaysPromoteToQueen = !appData.alwaysPromoteToQueen;
7001 if (appData.alwaysPromoteToQueen) {
7002 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7004 XtSetArg(args[0], XtNleftBitmap, None);
7006 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
7010 void AnimateDraggingProc(w, event, prms, nprms)
7018 appData.animateDragging = !appData.animateDragging;
7020 if (appData.animateDragging) {
7021 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7024 XtSetArg(args[0], XtNleftBitmap, None);
7026 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Dragging"),
7030 void AnimateMovingProc(w, event, prms, nprms)
7038 appData.animate = !appData.animate;
7040 if (appData.animate) {
7041 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7044 XtSetArg(args[0], XtNleftBitmap, None);
7046 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
7050 void AutocommProc(w, event, prms, nprms)
7058 appData.autoComment = !appData.autoComment;
7060 if (appData.autoComment) {
7061 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7063 XtSetArg(args[0], XtNleftBitmap, None);
7065 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
7070 void AutoflagProc(w, event, prms, nprms)
7078 appData.autoCallFlag = !appData.autoCallFlag;
7080 if (appData.autoCallFlag) {
7081 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7083 XtSetArg(args[0], XtNleftBitmap, None);
7085 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
7089 void AutoflipProc(w, event, prms, nprms)
7097 appData.autoFlipView = !appData.autoFlipView;
7099 if (appData.autoFlipView) {
7100 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7102 XtSetArg(args[0], XtNleftBitmap, None);
7104 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flip View"),
7108 void AutobsProc(w, event, prms, nprms)
7116 appData.autoObserve = !appData.autoObserve;
7118 if (appData.autoObserve) {
7119 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7121 XtSetArg(args[0], XtNleftBitmap, None);
7123 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
7127 void AutoraiseProc(w, event, prms, nprms)
7135 appData.autoRaiseBoard = !appData.autoRaiseBoard;
7137 if (appData.autoRaiseBoard) {
7138 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7140 XtSetArg(args[0], XtNleftBitmap, None);
7142 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Raise Board"),
7146 void AutosaveProc(w, event, prms, nprms)
7154 appData.autoSaveGames = !appData.autoSaveGames;
7156 if (appData.autoSaveGames) {
7157 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7159 XtSetArg(args[0], XtNleftBitmap, None);
7161 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
7165 void BlindfoldProc(w, event, prms, nprms)
7173 appData.blindfold = !appData.blindfold;
7175 if (appData.blindfold) {
7176 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7178 XtSetArg(args[0], XtNleftBitmap, None);
7180 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Blindfold"),
7183 DrawPosition(True, NULL);
7186 void TestLegalityProc(w, event, prms, nprms)
7194 appData.testLegality = !appData.testLegality;
7196 if (appData.testLegality) {
7197 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7199 XtSetArg(args[0], XtNleftBitmap, None);
7201 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Test Legality"),
7206 void FlashMovesProc(w, event, prms, nprms)
7214 if (appData.flashCount == 0) {
7215 appData.flashCount = 3;
7217 appData.flashCount = -appData.flashCount;
7220 if (appData.flashCount > 0) {
7221 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7223 XtSetArg(args[0], XtNleftBitmap, None);
7225 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flash Moves"),
7229 void FlipViewProc(w, event, prms, nprms)
7235 flipView = !flipView;
7236 DrawPosition(True, NULL);
7239 void GetMoveListProc(w, event, prms, nprms)
7247 appData.getMoveList = !appData.getMoveList;
7249 if (appData.getMoveList) {
7250 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7253 XtSetArg(args[0], XtNleftBitmap, None);
7255 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
7260 void HighlightDraggingProc(w, event, prms, nprms)
7268 appData.highlightDragging = !appData.highlightDragging;
7270 if (appData.highlightDragging) {
7271 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7273 XtSetArg(args[0], XtNleftBitmap, None);
7275 XtSetValues(XtNameToWidget(menuBarWidget,
7276 "menuOptions.Highlight Dragging"), args, 1);
7280 void HighlightLastMoveProc(w, event, prms, nprms)
7288 appData.highlightLastMove = !appData.highlightLastMove;
7290 if (appData.highlightLastMove) {
7291 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7293 XtSetArg(args[0], XtNleftBitmap, None);
7295 XtSetValues(XtNameToWidget(menuBarWidget,
7296 "menuOptions.Highlight Last Move"), args, 1);
7299 void IcsAlarmProc(w, event, prms, nprms)
7307 appData.icsAlarm = !appData.icsAlarm;
7309 if (appData.icsAlarm) {
7310 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7312 XtSetArg(args[0], XtNleftBitmap, None);
7314 XtSetValues(XtNameToWidget(menuBarWidget,
7315 "menuOptions.ICS Alarm"), args, 1);
7318 void MoveSoundProc(w, event, prms, nprms)
7326 appData.ringBellAfterMoves = !appData.ringBellAfterMoves;
7328 if (appData.ringBellAfterMoves) {
7329 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7331 XtSetArg(args[0], XtNleftBitmap, None);
7333 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
7338 void OldSaveStyleProc(w, event, prms, nprms)
7346 appData.oldSaveStyle = !appData.oldSaveStyle;
7348 if (appData.oldSaveStyle) {
7349 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7351 XtSetArg(args[0], XtNleftBitmap, None);
7353 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Old Save Style"),
7357 void PeriodicUpdatesProc(w, event, prms, nprms)
7365 PeriodicUpdatesEvent(!appData.periodicUpdates);
7367 if (appData.periodicUpdates) {
7368 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7370 XtSetArg(args[0], XtNleftBitmap, None);
7372 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Periodic Updates"),
7376 void PonderNextMoveProc(w, event, prms, nprms)
7384 PonderNextMoveEvent(!appData.ponderNextMove);
7386 if (appData.ponderNextMove) {
7387 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7389 XtSetArg(args[0], XtNleftBitmap, None);
7391 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Ponder Next Move"),
7395 void PopupExitMessageProc(w, event, prms, nprms)
7403 appData.popupExitMessage = !appData.popupExitMessage;
7405 if (appData.popupExitMessage) {
7406 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7408 XtSetArg(args[0], XtNleftBitmap, None);
7410 XtSetValues(XtNameToWidget(menuBarWidget,
7411 "menuOptions.Popup Exit Message"), args, 1);
7414 void PopupMoveErrorsProc(w, event, prms, nprms)
7422 appData.popupMoveErrors = !appData.popupMoveErrors;
7424 if (appData.popupMoveErrors) {
7425 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7427 XtSetArg(args[0], XtNleftBitmap, None);
7429 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Popup Move Errors"),
7433 void PremoveProc(w, event, prms, nprms)
7441 appData.premove = !appData.premove;
7443 if (appData.premove) {
7444 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7446 XtSetArg(args[0], XtNleftBitmap, None);
7448 XtSetValues(XtNameToWidget(menuBarWidget,
7449 "menuOptions.Premove"), args, 1);
7452 void QuietPlayProc(w, event, prms, nprms)
7460 appData.quietPlay = !appData.quietPlay;
7462 if (appData.quietPlay) {
7463 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7465 XtSetArg(args[0], XtNleftBitmap, None);
7467 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Quiet Play"),
7471 void ShowCoordsProc(w, event, prms, nprms)
7479 appData.showCoords = !appData.showCoords;
7481 if (appData.showCoords) {
7482 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7484 XtSetArg(args[0], XtNleftBitmap, None);
7486 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
7489 DrawPosition(True, NULL);
7492 void ShowThinkingProc(w, event, prms, nprms)
7500 appData.showThinking = !appData.showThinking; // [HGM] thinking: tken out of ShowThinkingEvent
7501 ShowThinkingEvent();
7504 void HideThinkingProc(w, event, prms, nprms)
7512 appData.hideThinkingFromHuman = !appData.hideThinkingFromHuman; // [HGM] thinking: tken out of ShowThinkingEvent
7513 ShowThinkingEvent();
7515 if (appData.hideThinkingFromHuman) {
7516 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7518 XtSetArg(args[0], XtNleftBitmap, None);
7520 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
7524 void InfoProc(w, event, prms, nprms)
7531 snprintf(buf, sizeof(buf), "xterm -e info --directory %s --directory . -f %s &",
7536 void ManProc(w, event, prms, nprms)
7544 if (nprms && *nprms > 0)
7548 snprintf(buf, sizeof(buf), "xterm -e man %s &", name);
7552 void HintProc(w, event, prms, nprms)
7561 void BookProc(w, event, prms, nprms)
7570 void AboutProc(w, event, prms, nprms)
7578 char *zippy = " (with Zippy code)";
7582 snprintf(buf, sizeof(buf), "%s%s\n\n%s\n%s\n%s\n\n%s%s\n%s",
7583 programVersion, zippy,
7584 "Copyright 1991 Digital Equipment Corporation",
7585 "Enhancements Copyright 1992-2009 Free Software Foundation",
7586 "Enhancements Copyright 2005 Alessandro Scotti",
7587 PACKAGE, " is free software and carries NO WARRANTY;",
7588 "see the file COPYING for more information.");
7589 ErrorPopUp(_("About XBoard"), buf, FALSE);
7592 void DebugProc(w, event, prms, nprms)
7598 appData.debugMode = !appData.debugMode;
7601 void AboutGameProc(w, event, prms, nprms)
7610 void NothingProc(w, event, prms, nprms)
7619 void Iconify(w, event, prms, nprms)
7628 XtSetArg(args[0], XtNiconic, True);
7629 XtSetValues(shellWidget, args, 1);
7632 void DisplayMessage(message, extMessage)
7633 char *message, *extMessage;
7635 /* display a message in the message widget */
7644 snprintf(buf, sizeof(buf), "%s %s", message, extMessage);
7649 message = extMessage;
7653 /* need to test if messageWidget already exists, since this function
7654 can also be called during the startup, if for example a Xresource
7655 is not set up correctly */
7658 XtSetArg(arg, XtNlabel, message);
7659 XtSetValues(messageWidget, &arg, 1);
7665 void DisplayTitle(text)
7670 char title[MSG_SIZ];
7673 if (text == NULL) text = "";
7675 if (appData.titleInWindow) {
7677 XtSetArg(args[i], XtNlabel, text); i++;
7678 XtSetValues(titleWidget, args, i);
7681 if (*text != NULLCHAR) {
7683 strcpy(title, text);
7684 } else if (appData.icsActive) {
7685 snprintf(icon, sizeof(icon), "%s", appData.icsHost);
7686 snprintf(title, sizeof(title), "%s: %s", programName, appData.icsHost);
7687 } else if (appData.cmailGameName[0] != NULLCHAR) {
7688 snprintf(icon, sizeof(icon), "%s", "CMail");
7689 snprintf(title,sizeof(title), "%s: %s", programName, "CMail");
7691 // [HGM] license: This stuff should really be done in back-end, but WinBoard already had a pop-up for it
7692 } else if (gameInfo.variant == VariantGothic) {
7693 strcpy(icon, programName);
7694 strcpy(title, GOTHIC);
7697 } else if (gameInfo.variant == VariantFalcon) {
7698 strcpy(icon, programName);
7699 strcpy(title, FALCON);
7701 } else if (appData.noChessProgram) {
7702 strcpy(icon, programName);
7703 strcpy(title, programName);
7705 strcpy(icon, first.tidy);
7706 snprintf(title,sizeof(title), "%s: %s", programName, first.tidy);
7709 XtSetArg(args[i], XtNiconName, (XtArgVal) icon); i++;
7710 XtSetArg(args[i], XtNtitle, (XtArgVal) title); i++;
7711 XtSetValues(shellWidget, args, i);
7715 void DisplayError(message, error)
7722 if (appData.debugMode || appData.matchMode) {
7723 fprintf(stderr, "%s: %s\n", programName, message);
7726 if (appData.debugMode || appData.matchMode) {
7727 fprintf(stderr, "%s: %s: %s\n",
7728 programName, message, strerror(error));
7730 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
7733 ErrorPopUp(_("Error"), message, FALSE);
7737 void DisplayMoveError(message)
7742 DrawPosition(FALSE, NULL);
7743 if (appData.debugMode || appData.matchMode) {
7744 fprintf(stderr, "%s: %s\n", programName, message);
7746 if (appData.popupMoveErrors) {
7747 ErrorPopUp(_("Error"), message, FALSE);
7749 DisplayMessage(message, "");
7754 void DisplayFatalError(message, error, status)
7760 errorExitStatus = status;
7762 fprintf(stderr, "%s: %s\n", programName, message);
7764 fprintf(stderr, "%s: %s: %s\n",
7765 programName, message, strerror(error));
7766 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
7769 if (appData.popupExitMessage && boardWidget && XtIsRealized(boardWidget)) {
7770 ErrorPopUp(status ? _("Fatal Error") : _("Exiting"), message, TRUE);
7776 void DisplayInformation(message)
7780 ErrorPopUp(_("Information"), message, TRUE);
7783 void DisplayNote(message)
7787 ErrorPopUp(_("Note"), message, FALSE);
7791 NullXErrorCheck(dpy, error_event)
7793 XErrorEvent *error_event;
7798 void DisplayIcsInteractionTitle(message)
7801 if (oldICSInteractionTitle == NULL) {
7802 /* Magic to find the old window title, adapted from vim */
7803 char *wina = getenv("WINDOWID");
7805 Window win = (Window) atoi(wina);
7806 Window root, parent, *children;
7807 unsigned int nchildren;
7808 int (*oldHandler)() = XSetErrorHandler(NullXErrorCheck);
7810 if (XFetchName(xDisplay, win, &oldICSInteractionTitle)) break;
7811 if (!XQueryTree(xDisplay, win, &root, &parent,
7812 &children, &nchildren)) break;
7813 if (children) XFree((void *)children);
7814 if (parent == root || parent == 0) break;
7817 XSetErrorHandler(oldHandler);
7819 if (oldICSInteractionTitle == NULL) {
7820 oldICSInteractionTitle = "xterm";
7823 printf("\033]0;%s\007", message);
7827 char pendingReplyPrefix[MSG_SIZ];
7828 ProcRef pendingReplyPR;
7830 void AskQuestionProc(w, event, prms, nprms)
7837 fprintf(stderr, _("AskQuestionProc needed 4 parameters, got %d\n"),
7841 AskQuestionEvent(prms[0], prms[1], prms[2], prms[3]);
7844 void AskQuestionPopDown()
7846 if (!askQuestionUp) return;
7847 XtPopdown(askQuestionShell);
7848 XtDestroyWidget(askQuestionShell);
7849 askQuestionUp = False;
7852 void AskQuestionReplyAction(w, event, prms, nprms)
7862 reply = XawDialogGetValueString(w = XtParent(w));
7863 strcpy(buf, pendingReplyPrefix);
7864 if (*buf) strcat(buf, " ");
7867 OutputToProcess(pendingReplyPR, buf, strlen(buf), &err);
7868 AskQuestionPopDown();
7870 if (err) DisplayFatalError(_("Error writing to chess program"), err, 0);
7873 void AskQuestionCallback(w, client_data, call_data)
7875 XtPointer client_data, call_data;
7880 XtSetArg(args[0], XtNlabel, &name);
7881 XtGetValues(w, args, 1);
7883 if (strcmp(name, _("cancel")) == 0) {
7884 AskQuestionPopDown();
7886 AskQuestionReplyAction(w, NULL, NULL, NULL);
7890 void AskQuestion(title, question, replyPrefix, pr)
7891 char *title, *question, *replyPrefix;
7895 Widget popup, layout, dialog, edit;
7901 strcpy(pendingReplyPrefix, replyPrefix);
7902 pendingReplyPR = pr;
7905 XtSetArg(args[i], XtNresizable, True); i++;
7906 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
7907 askQuestionShell = popup =
7908 XtCreatePopupShell(title, transientShellWidgetClass,
7909 shellWidget, args, i);
7912 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
7913 layoutArgs, XtNumber(layoutArgs));
7916 XtSetArg(args[i], XtNlabel, question); i++;
7917 XtSetArg(args[i], XtNvalue, ""); i++;
7918 XtSetArg(args[i], XtNborderWidth, 0); i++;
7919 dialog = XtCreateManagedWidget("question", dialogWidgetClass,
7922 XawDialogAddButton(dialog, _("enter"), AskQuestionCallback,
7923 (XtPointer) dialog);
7924 XawDialogAddButton(dialog, _("cancel"), AskQuestionCallback,
7925 (XtPointer) dialog);
7927 XtRealizeWidget(popup);
7928 CatchDeleteWindow(popup, "AskQuestionPopDown");
7930 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
7931 &x, &y, &win_x, &win_y, &mask);
7933 XtSetArg(args[0], XtNx, x - 10);
7934 XtSetArg(args[1], XtNy, y - 30);
7935 XtSetValues(popup, args, 2);
7937 XtPopup(popup, XtGrabExclusive);
7938 askQuestionUp = True;
7940 edit = XtNameToWidget(dialog, "*value");
7941 XtSetKeyboardFocus(popup, edit);
7949 if (*name == NULLCHAR) {
7951 } else if (strcmp(name, "$") == 0) {
7952 putc(BELLCHAR, stderr);
7955 snprintf(buf, sizeof(buf), "%s '%s' &", appData.soundProgram, name);
7963 PlaySound(appData.soundMove);
7969 PlaySound(appData.soundIcsWin);
7975 PlaySound(appData.soundIcsLoss);
7981 PlaySound(appData.soundIcsDraw);
7985 PlayIcsUnfinishedSound()
7987 PlaySound(appData.soundIcsUnfinished);
7993 PlaySound(appData.soundIcsAlarm);
7999 system("stty echo");
8005 system("stty -echo");
8009 Colorize(cc, continuation)
8014 int count, outCount, error;
8016 if (textColors[(int)cc].bg > 0) {
8017 if (textColors[(int)cc].fg > 0) {
8018 sprintf(buf, "\033[0;%d;%d;%dm", textColors[(int)cc].attr,
8019 textColors[(int)cc].fg, textColors[(int)cc].bg);
8021 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
8022 textColors[(int)cc].bg);
8025 if (textColors[(int)cc].fg > 0) {
8026 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
8027 textColors[(int)cc].fg);
8029 sprintf(buf, "\033[0;%dm", textColors[(int)cc].attr);
8032 count = strlen(buf);
8033 outCount = OutputToProcess(NoProc, buf, count, &error);
8034 if (outCount < count) {
8035 DisplayFatalError(_("Error writing to display"), error, 1);
8038 if (continuation) return;
8041 PlaySound(appData.soundShout);
8044 PlaySound(appData.soundSShout);
8047 PlaySound(appData.soundChannel1);
8050 PlaySound(appData.soundChannel);
8053 PlaySound(appData.soundKibitz);
8056 PlaySound(appData.soundTell);
8058 case ColorChallenge:
8059 PlaySound(appData.soundChallenge);
8062 PlaySound(appData.soundRequest);
8065 PlaySound(appData.soundSeek);
8076 return getpwuid(getuid())->pw_name;
8079 static char *ExpandPathName(path)
8082 static char static_buf[2000];
8083 char *d, *s, buf[2000];
8089 while (*s && isspace(*s))
8098 if (*(s+1) == '/') {
8099 strcpy(d, getpwuid(getuid())->pw_dir);
8104 *strchr(buf, '/') = 0;
8105 pwd = getpwnam(buf);
8108 fprintf(stderr, _("ERROR: Unknown user %s (in path %s)\n"),
8112 strcpy(d, pwd->pw_dir);
8113 strcat(d, strchr(s+1, '/'));
8124 static char host_name[MSG_SIZ];
8126 #if HAVE_GETHOSTNAME
8127 gethostname(host_name, MSG_SIZ);
8129 #else /* not HAVE_GETHOSTNAME */
8130 # if HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H
8131 sysinfo(SI_HOSTNAME, host_name, MSG_SIZ);
8133 # else /* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
8135 # endif/* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
8136 #endif /* not HAVE_GETHOSTNAME */
8139 XtIntervalId delayedEventTimerXID = 0;
8140 DelayedEventCallback delayedEventCallback = 0;
8145 delayedEventTimerXID = 0;
8146 delayedEventCallback();
8150 ScheduleDelayedEvent(cb, millisec)
8151 DelayedEventCallback cb; long millisec;
8153 if(delayedEventTimerXID && delayedEventCallback == cb)
8154 // [HGM] alive: replace, rather than add or flush identical event
8155 XtRemoveTimeOut(delayedEventTimerXID);
8156 delayedEventCallback = cb;
8157 delayedEventTimerXID =
8158 XtAppAddTimeOut(appContext, millisec,
8159 (XtTimerCallbackProc) FireDelayedEvent, (XtPointer) 0);
8162 DelayedEventCallback
8165 if (delayedEventTimerXID) {
8166 return delayedEventCallback;
8173 CancelDelayedEvent()
8175 if (delayedEventTimerXID) {
8176 XtRemoveTimeOut(delayedEventTimerXID);
8177 delayedEventTimerXID = 0;
8181 XtIntervalId loadGameTimerXID = 0;
8183 int LoadGameTimerRunning()
8185 return loadGameTimerXID != 0;
8188 int StopLoadGameTimer()
8190 if (loadGameTimerXID != 0) {
8191 XtRemoveTimeOut(loadGameTimerXID);
8192 loadGameTimerXID = 0;
8200 LoadGameTimerCallback(arg, id)
8204 loadGameTimerXID = 0;
8209 StartLoadGameTimer(millisec)
8213 XtAppAddTimeOut(appContext, millisec,
8214 (XtTimerCallbackProc) LoadGameTimerCallback,
8218 XtIntervalId analysisClockXID = 0;
8221 AnalysisClockCallback(arg, id)
8225 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile
8226 || appData.icsEngineAnalyze) { // [DM]
8227 AnalysisPeriodicEvent(0);
8228 StartAnalysisClock();
8233 StartAnalysisClock()
8236 XtAppAddTimeOut(appContext, 2000,
8237 (XtTimerCallbackProc) AnalysisClockCallback,
8241 XtIntervalId clockTimerXID = 0;
8243 int ClockTimerRunning()
8245 return clockTimerXID != 0;
8248 int StopClockTimer()
8250 if (clockTimerXID != 0) {
8251 XtRemoveTimeOut(clockTimerXID);
8260 ClockTimerCallback(arg, id)
8269 StartClockTimer(millisec)
8273 XtAppAddTimeOut(appContext, millisec,
8274 (XtTimerCallbackProc) ClockTimerCallback,
8279 DisplayTimerLabel(w, color, timer, highlight)
8288 /* check for low time warning */
8289 Pixel foregroundOrWarningColor = timerForegroundPixel;
8292 appData.lowTimeWarning &&
8293 (timer / 1000) < appData.icsAlarmTime)
8294 foregroundOrWarningColor = lowTimeWarningColor;
8296 if (appData.clockMode) {
8297 sprintf(buf, "%s: %s", color, TimeString(timer));
8298 XtSetArg(args[0], XtNlabel, buf);
8300 sprintf(buf, "%s ", color);
8301 XtSetArg(args[0], XtNlabel, buf);
8306 XtSetArg(args[1], XtNbackground, foregroundOrWarningColor);
8307 XtSetArg(args[2], XtNforeground, timerBackgroundPixel);
8309 XtSetArg(args[1], XtNbackground, timerBackgroundPixel);
8310 XtSetArg(args[2], XtNforeground, foregroundOrWarningColor);
8313 XtSetValues(w, args, 3);
8317 DisplayWhiteClock(timeRemaining, highlight)
8323 if(appData.noGUI) return;
8324 DisplayTimerLabel(whiteTimerWidget, _("White"), timeRemaining, highlight);
8325 if (highlight && iconPixmap == bIconPixmap) {
8326 iconPixmap = wIconPixmap;
8327 XtSetArg(args[0], XtNiconPixmap, iconPixmap);
8328 XtSetValues(shellWidget, args, 1);
8333 DisplayBlackClock(timeRemaining, highlight)
8339 if(appData.noGUI) return;
8340 DisplayTimerLabel(blackTimerWidget, _("Black"), timeRemaining, highlight);
8341 if (highlight && iconPixmap == wIconPixmap) {
8342 iconPixmap = bIconPixmap;
8343 XtSetArg(args[0], XtNiconPixmap, iconPixmap);
8344 XtSetValues(shellWidget, args, 1);
8362 int StartChildProcess(cmdLine, dir, pr)
8369 int to_prog[2], from_prog[2];
8373 if (appData.debugMode) {
8374 fprintf(stderr, "StartChildProcess (dir=\"%s\") %s\n",dir, cmdLine);
8377 /* We do NOT feed the cmdLine to the shell; we just
8378 parse it into blank-separated arguments in the
8379 most simple-minded way possible.
8382 strcpy(buf, cmdLine);
8387 if (p == NULL) break;
8392 SetUpChildIO(to_prog, from_prog);
8394 if ((pid = fork()) == 0) {
8396 // [HGM] PSWBTM: made order resistant against case where fd of created pipe was 0 or 1
8397 close(to_prog[1]); // first close the unused pipe ends
8398 close(from_prog[0]);
8399 dup2(to_prog[0], 0); // to_prog was created first, nd is the only one to use 0 or 1
8400 dup2(from_prog[1], 1);
8401 if(to_prog[0] >= 2) close(to_prog[0]); // if 0 or 1, the dup2 already cosed the original
8402 close(from_prog[1]); // and closing again loses one of the pipes!
8403 if(fileno(stderr) >= 2) // better safe than sorry...
8404 dup2(1, fileno(stderr)); /* force stderr to the pipe */
8406 if (dir[0] != NULLCHAR && chdir(dir) != 0) {
8411 nice(appData.niceEngines); // [HGM] nice: adjust priority of engine proc
8413 execvp(argv[0], argv);
8415 /* If we get here, exec failed */
8420 /* Parent process */
8422 close(from_prog[1]);
8424 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8427 cp->fdFrom = from_prog[0];
8428 cp->fdTo = to_prog[1];
8433 // [HGM] kill: implement the 'hard killing' of AS's Winboard_x
8434 static RETSIGTYPE AlarmCallBack(int n)
8440 DestroyChildProcess(pr, signalType)
8444 ChildProc *cp = (ChildProc *) pr;
8446 if (cp->kind != CPReal) return;
8448 if (signalType == 10) { // [HGM] kill: if it does not terminate in 3 sec, kill
8449 signal(SIGALRM, AlarmCallBack);
8451 if(wait((int *) 0) == -1) { // process does not terminate on its own accord
8452 kill(cp->pid, SIGKILL); // kill it forcefully
8453 wait((int *) 0); // and wait again
8457 kill(cp->pid, signalType == 9 ? SIGKILL : SIGTERM); // [HGM] kill: use hard kill if so requested
8459 /* Process is exiting either because of the kill or because of
8460 a quit command sent by the backend; either way, wait for it to die.
8469 InterruptChildProcess(pr)
8472 ChildProc *cp = (ChildProc *) pr;
8474 if (cp->kind != CPReal) return;
8475 (void) kill(cp->pid, SIGINT); /* stop it thinking */
8478 int OpenTelnet(host, port, pr)
8483 char cmdLine[MSG_SIZ];
8485 if (port[0] == NULLCHAR) {
8486 snprintf(cmdLine, sizeof(cmdLine), "%s %s", appData.telnetProgram, host);
8488 snprintf(cmdLine, sizeof(cmdLine), "%s %s %s", appData.telnetProgram, host, port);
8490 return StartChildProcess(cmdLine, "", pr);
8493 int OpenTCP(host, port, pr)
8499 DisplayFatalError(_("Socket support is not configured in"), 0, 2);
8500 #else /* !OMIT_SOCKETS */
8502 struct sockaddr_in sa;
8504 unsigned short uport;
8507 if ((s = socket(AF_INET, SOCK_STREAM, 6)) < 0) {
8511 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
8512 sa.sin_family = AF_INET;
8513 sa.sin_addr.s_addr = INADDR_ANY;
8514 uport = (unsigned short) 0;
8515 sa.sin_port = htons(uport);
8516 if (bind(s, (struct sockaddr *) &sa, sizeof(struct sockaddr_in)) < 0) {
8520 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
8521 if (!(hp = gethostbyname(host))) {
8523 if (sscanf(host, "%d.%d.%d.%d", &b0, &b1, &b2, &b3) == 4) {
8524 hp = (struct hostent *) calloc(1, sizeof(struct hostent));
8525 hp->h_addrtype = AF_INET;
8527 hp->h_addr_list = (char **) calloc(2, sizeof(char *));
8528 hp->h_addr_list[0] = (char *) malloc(4);
8529 hp->h_addr_list[0][0] = b0;
8530 hp->h_addr_list[0][1] = b1;
8531 hp->h_addr_list[0][2] = b2;
8532 hp->h_addr_list[0][3] = b3;
8537 sa.sin_family = hp->h_addrtype;
8538 uport = (unsigned short) atoi(port);
8539 sa.sin_port = htons(uport);
8540 memcpy((char *) &sa.sin_addr, hp->h_addr, hp->h_length);
8542 if (connect(s, (struct sockaddr *) &sa,
8543 sizeof(struct sockaddr_in)) < 0) {
8547 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8554 #endif /* !OMIT_SOCKETS */
8559 int OpenCommPort(name, pr)
8566 fd = open(name, 2, 0);
8567 if (fd < 0) return errno;
8569 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8579 int OpenLoopback(pr)
8585 SetUpChildIO(to, from);
8587 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8590 cp->fdFrom = to[0]; /* note not from[0]; we are doing a loopback */
8597 int OpenRcmd(host, user, cmd, pr)
8598 char *host, *user, *cmd;
8601 DisplayFatalError(_("internal rcmd not implemented for Unix"), 0, 1);
8605 #define INPUT_SOURCE_BUF_SIZE 8192
8614 char buf[INPUT_SOURCE_BUF_SIZE];
8619 DoInputCallback(closure, source, xid)
8624 InputSource *is = (InputSource *) closure;
8629 if (is->lineByLine) {
8630 count = read(is->fd, is->unused,
8631 INPUT_SOURCE_BUF_SIZE - (is->unused - is->buf));
8633 (is->func)(is, is->closure, is->buf, count, count ? errno : 0);
8636 is->unused += count;
8638 while (p < is->unused) {
8639 q = memchr(p, '\n', is->unused - p);
8640 if (q == NULL) break;
8642 (is->func)(is, is->closure, p, q - p, 0);
8646 while (p < is->unused) {
8651 count = read(is->fd, is->buf, INPUT_SOURCE_BUF_SIZE);
8656 (is->func)(is, is->closure, is->buf, count, error);
8660 InputSourceRef AddInputSource(pr, lineByLine, func, closure)
8667 ChildProc *cp = (ChildProc *) pr;
8669 is = (InputSource *) calloc(1, sizeof(InputSource));
8670 is->lineByLine = lineByLine;
8674 is->fd = fileno(stdin);
8676 is->kind = cp->kind;
8677 is->fd = cp->fdFrom;
8680 is->unused = is->buf;
8683 is->xid = XtAppAddInput(appContext, is->fd,
8684 (XtPointer) (XtInputReadMask),
8685 (XtInputCallbackProc) DoInputCallback,
8687 is->closure = closure;
8688 return (InputSourceRef) is;
8692 RemoveInputSource(isr)
8695 InputSource *is = (InputSource *) isr;
8697 if (is->xid == 0) return;
8698 XtRemoveInput(is->xid);
8702 int OutputToProcess(pr, message, count, outError)
8708 ChildProc *cp = (ChildProc *) pr;
8712 outCount = fwrite(message, 1, count, stdout);
8714 outCount = write(cp->fdTo, message, count);
8724 /* Output message to process, with "ms" milliseconds of delay
8725 between each character. This is needed when sending the logon
8726 script to ICC, which for some reason doesn't like the
8727 instantaneous send. */
8728 int OutputToProcessDelayed(pr, message, count, outError, msdelay)
8735 ChildProc *cp = (ChildProc *) pr;
8740 r = write(cp->fdTo, message++, 1);
8753 /**** Animation code by Hugh Fisher, DCS, ANU.
8755 Known problem: if a window overlapping the board is
8756 moved away while a piece is being animated underneath,
8757 the newly exposed area won't be updated properly.
8758 I can live with this.
8760 Known problem: if you look carefully at the animation
8761 of pieces in mono mode, they are being drawn as solid
8762 shapes without interior detail while moving. Fixing
8763 this would be a major complication for minimal return.
8766 /* Masks for XPM pieces. Black and white pieces can have
8767 different shapes, but in the interest of retaining my
8768 sanity pieces must have the same outline on both light
8769 and dark squares, and all pieces must use the same
8770 background square colors/images. */
8772 static int xpmDone = 0;
8775 CreateAnimMasks (pieceDepth)
8782 unsigned long plane;
8785 /* Need a bitmap just to get a GC with right depth */
8786 buf = XCreatePixmap(xDisplay, xBoardWindow,
8788 values.foreground = 1;
8789 values.background = 0;
8790 /* Don't use XtGetGC, not read only */
8791 maskGC = XCreateGC(xDisplay, buf,
8792 GCForeground | GCBackground, &values);
8793 XFreePixmap(xDisplay, buf);
8795 buf = XCreatePixmap(xDisplay, xBoardWindow,
8796 squareSize, squareSize, pieceDepth);
8797 values.foreground = XBlackPixel(xDisplay, xScreen);
8798 values.background = XWhitePixel(xDisplay, xScreen);
8799 bufGC = XCreateGC(xDisplay, buf,
8800 GCForeground | GCBackground, &values);
8802 for (piece = WhitePawn; piece <= BlackKing; piece++) {
8803 /* Begin with empty mask */
8804 if(!xpmDone) // [HGM] pieces: keep using existing
8805 xpmMask[piece] = XCreatePixmap(xDisplay, xBoardWindow,
8806 squareSize, squareSize, 1);
8807 XSetFunction(xDisplay, maskGC, GXclear);
8808 XFillRectangle(xDisplay, xpmMask[piece], maskGC,
8809 0, 0, squareSize, squareSize);
8811 /* Take a copy of the piece */
8816 XSetFunction(xDisplay, bufGC, GXcopy);
8817 XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % (int)BlackPawn],
8819 0, 0, squareSize, squareSize, 0, 0);
8821 /* XOR the background (light) over the piece */
8822 XSetFunction(xDisplay, bufGC, GXxor);
8824 XCopyArea(xDisplay, xpmLightSquare, buf, bufGC,
8825 0, 0, squareSize, squareSize, 0, 0);
8827 XSetForeground(xDisplay, bufGC, lightSquareColor);
8828 XFillRectangle(xDisplay, buf, bufGC, 0, 0, squareSize, squareSize);
8831 /* We now have an inverted piece image with the background
8832 erased. Construct mask by just selecting all the non-zero
8833 pixels - no need to reconstruct the original image. */
8834 XSetFunction(xDisplay, maskGC, GXor);
8836 /* Might be quicker to download an XImage and create bitmap
8837 data from it rather than this N copies per piece, but it
8838 only takes a fraction of a second and there is a much
8839 longer delay for loading the pieces. */
8840 for (n = 0; n < pieceDepth; n ++) {
8841 XCopyPlane(xDisplay, buf, xpmMask[piece], maskGC,
8842 0, 0, squareSize, squareSize,
8848 XFreePixmap(xDisplay, buf);
8849 XFreeGC(xDisplay, bufGC);
8850 XFreeGC(xDisplay, maskGC);
8854 InitAnimState (anim, info)
8856 XWindowAttributes * info;
8861 /* Each buffer is square size, same depth as window */
8862 anim->saveBuf = XCreatePixmap(xDisplay, xBoardWindow,
8863 squareSize, squareSize, info->depth);
8864 anim->newBuf = XCreatePixmap(xDisplay, xBoardWindow,
8865 squareSize, squareSize, info->depth);
8867 /* Create a plain GC for blitting */
8868 mask = GCForeground | GCBackground | GCFunction |
8869 GCPlaneMask | GCGraphicsExposures;
8870 values.foreground = XBlackPixel(xDisplay, xScreen);
8871 values.background = XWhitePixel(xDisplay, xScreen);
8872 values.function = GXcopy;
8873 values.plane_mask = AllPlanes;
8874 values.graphics_exposures = False;
8875 anim->blitGC = XCreateGC(xDisplay, xBoardWindow, mask, &values);
8877 /* Piece will be copied from an existing context at
8878 the start of each new animation/drag. */
8879 anim->pieceGC = XCreateGC(xDisplay, xBoardWindow, 0, &values);
8881 /* Outline will be a read-only copy of an existing */
8882 anim->outlineGC = None;
8888 static VariantClass old = (VariantClass) -1; // [HGM] pieces: redo every time variant changes
8889 XWindowAttributes info;
8891 if (xpmDone && gameInfo.variant == old) return;
8892 if(xpmDone) old = gameInfo.variant; // first time pieces might not be created yet
8893 XGetWindowAttributes(xDisplay, xBoardWindow, &info);
8895 InitAnimState(&game, &info);
8896 InitAnimState(&player, &info);
8898 /* For XPM pieces, we need bitmaps to use as masks. */
8900 CreateAnimMasks(info.depth);
8906 static Boolean frameWaiting;
8908 static RETSIGTYPE FrameAlarm (sig)
8911 frameWaiting = False;
8912 /* In case System-V style signals. Needed?? */
8913 signal(SIGALRM, FrameAlarm);
8920 struct itimerval delay;
8922 XSync(xDisplay, False);
8925 frameWaiting = True;
8926 signal(SIGALRM, FrameAlarm);
8927 delay.it_interval.tv_sec =
8928 delay.it_value.tv_sec = time / 1000;
8929 delay.it_interval.tv_usec =
8930 delay.it_value.tv_usec = (time % 1000) * 1000;
8931 setitimer(ITIMER_REAL, &delay, NULL);
8932 while (frameWaiting) pause();
8933 delay.it_interval.tv_sec = delay.it_value.tv_sec = 0;
8934 delay.it_interval.tv_usec = delay.it_value.tv_usec = 0;
8935 setitimer(ITIMER_REAL, &delay, NULL);
8945 XSync(xDisplay, False);
8947 usleep(time * 1000);
8952 /* Convert board position to corner of screen rect and color */
8955 ScreenSquare(column, row, pt, color)
8956 int column; int row; XPoint * pt; int * color;
8959 pt->x = lineGap + ((BOARD_WIDTH-1)-column) * (squareSize + lineGap);
8960 pt->y = lineGap + row * (squareSize + lineGap);
8962 pt->x = lineGap + column * (squareSize + lineGap);
8963 pt->y = lineGap + ((BOARD_HEIGHT-1)-row) * (squareSize + lineGap);
8965 *color = SquareColor(row, column);
8968 /* Convert window coords to square */
8971 BoardSquare(x, y, column, row)
8972 int x; int y; int * column; int * row;
8974 *column = EventToSquare(x, BOARD_WIDTH);
8975 if (flipView && *column >= 0)
8976 *column = BOARD_WIDTH - 1 - *column;
8977 *row = EventToSquare(y, BOARD_HEIGHT);
8978 if (!flipView && *row >= 0)
8979 *row = BOARD_HEIGHT - 1 - *row;
8984 #undef Max /* just in case */
8986 #define Max(a, b) ((a) > (b) ? (a) : (b))
8987 #define Min(a, b) ((a) < (b) ? (a) : (b))
8990 SetRect(rect, x, y, width, height)
8991 XRectangle * rect; int x; int y; int width; int height;
8995 rect->width = width;
8996 rect->height = height;
8999 /* Test if two frames overlap. If they do, return
9000 intersection rect within old and location of
9001 that rect within new. */
9004 Intersect(old, new, size, area, pt)
9005 XPoint * old; XPoint * new;
9006 int size; XRectangle * area; XPoint * pt;
9008 if (old->x > new->x + size || new->x > old->x + size ||
9009 old->y > new->y + size || new->y > old->y + size) {
9012 SetRect(area, Max(new->x - old->x, 0), Max(new->y - old->y, 0),
9013 size - abs(old->x - new->x), size - abs(old->y - new->y));
9014 pt->x = Max(old->x - new->x, 0);
9015 pt->y = Max(old->y - new->y, 0);
9020 /* For two overlapping frames, return the rect(s)
9021 in the old that do not intersect with the new. */
9024 CalcUpdateRects(old, new, size, update, nUpdates)
9025 XPoint * old; XPoint * new; int size;
9026 XRectangle update[]; int * nUpdates;
9030 /* If old = new (shouldn't happen) then nothing to draw */
9031 if (old->x == new->x && old->y == new->y) {
9035 /* Work out what bits overlap. Since we know the rects
9036 are the same size we don't need a full intersect calc. */
9038 /* Top or bottom edge? */
9039 if (new->y > old->y) {
9040 SetRect(&(update[count]), old->x, old->y, size, new->y - old->y);
9042 } else if (old->y > new->y) {
9043 SetRect(&(update[count]), old->x, old->y + size - (old->y - new->y),
9044 size, old->y - new->y);
9047 /* Left or right edge - don't overlap any update calculated above. */
9048 if (new->x > old->x) {
9049 SetRect(&(update[count]), old->x, Max(new->y, old->y),
9050 new->x - old->x, size - abs(new->y - old->y));
9052 } else if (old->x > new->x) {
9053 SetRect(&(update[count]), new->x + size, Max(new->y, old->y),
9054 old->x - new->x, size - abs(new->y - old->y));
9061 /* Generate a series of frame coords from start->mid->finish.
9062 The movement rate doubles until the half way point is
9063 reached, then halves back down to the final destination,
9064 which gives a nice slow in/out effect. The algorithmn
9065 may seem to generate too many intermediates for short
9066 moves, but remember that the purpose is to attract the
9067 viewers attention to the piece about to be moved and
9068 then to where it ends up. Too few frames would be less
9072 Tween(start, mid, finish, factor, frames, nFrames)
9073 XPoint * start; XPoint * mid;
9074 XPoint * finish; int factor;
9075 XPoint frames[]; int * nFrames;
9077 int fraction, n, count;
9081 /* Slow in, stepping 1/16th, then 1/8th, ... */
9083 for (n = 0; n < factor; n++)
9085 for (n = 0; n < factor; n++) {
9086 frames[count].x = start->x + (mid->x - start->x) / fraction;
9087 frames[count].y = start->y + (mid->y - start->y) / fraction;
9089 fraction = fraction / 2;
9093 frames[count] = *mid;
9096 /* Slow out, stepping 1/2, then 1/4, ... */
9098 for (n = 0; n < factor; n++) {
9099 frames[count].x = finish->x - (finish->x - mid->x) / fraction;
9100 frames[count].y = finish->y - (finish->y - mid->y) / fraction;
9102 fraction = fraction * 2;
9107 /* Draw a piece on the screen without disturbing what's there */
9110 SelectGCMask(piece, clip, outline, mask)
9111 ChessSquare piece; GC * clip; GC * outline; Pixmap * mask;
9115 /* Bitmap for piece being moved. */
9116 if (appData.monoMode) {
9117 *mask = *pieceToSolid(piece);
9118 } else if (useImages) {
9120 *mask = xpmMask[piece];
9122 *mask = ximMaskPm[piece];
9125 *mask = *pieceToSolid(piece);
9128 /* GC for piece being moved. Square color doesn't matter, but
9129 since it gets modified we make a copy of the original. */
9131 if (appData.monoMode)
9136 if (appData.monoMode)
9141 XCopyGC(xDisplay, source, 0xFFFFFFFF, *clip);
9143 /* Outline only used in mono mode and is not modified */
9145 *outline = bwPieceGC;
9147 *outline = wbPieceGC;
9151 OverlayPiece(piece, clip, outline, dest)
9152 ChessSquare piece; GC clip; GC outline; Drawable dest;
9157 /* Draw solid rectangle which will be clipped to shape of piece */
9158 XFillRectangle(xDisplay, dest, clip,
9159 0, 0, squareSize, squareSize);
9160 if (appData.monoMode)
9161 /* Also draw outline in contrasting color for black
9162 on black / white on white cases */
9163 XCopyPlane(xDisplay, *pieceToOutline(piece), dest, outline,
9164 0, 0, squareSize, squareSize, 0, 0, 1);
9166 /* Copy the piece */
9171 XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
9173 0, 0, squareSize, squareSize,
9178 /* Animate the movement of a single piece */
9181 BeginAnimation(anim, piece, startColor, start)
9189 /* The old buffer is initialised with the start square (empty) */
9190 BlankSquare(0, 0, startColor, EmptySquare, anim->saveBuf);
9191 anim->prevFrame = *start;
9193 /* The piece will be drawn using its own bitmap as a matte */
9194 SelectGCMask(piece, &anim->pieceGC, &anim->outlineGC, &mask);
9195 XSetClipMask(xDisplay, anim->pieceGC, mask);
9199 AnimationFrame(anim, frame, piece)
9204 XRectangle updates[4];
9209 /* Save what we are about to draw into the new buffer */
9210 XCopyArea(xDisplay, xBoardWindow, anim->newBuf, anim->blitGC,
9211 frame->x, frame->y, squareSize, squareSize,
9214 /* Erase bits of the previous frame */
9215 if (Intersect(&anim->prevFrame, frame, squareSize, &overlap, &pt)) {
9216 /* Where the new frame overlapped the previous,
9217 the contents in newBuf are wrong. */
9218 XCopyArea(xDisplay, anim->saveBuf, anim->newBuf, anim->blitGC,
9219 overlap.x, overlap.y,
9220 overlap.width, overlap.height,
9222 /* Repaint the areas in the old that don't overlap new */
9223 CalcUpdateRects(&anim->prevFrame, frame, squareSize, updates, &count);
9224 for (i = 0; i < count; i++)
9225 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9226 updates[i].x - anim->prevFrame.x,
9227 updates[i].y - anim->prevFrame.y,
9228 updates[i].width, updates[i].height,
9229 updates[i].x, updates[i].y);
9231 /* Easy when no overlap */
9232 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9233 0, 0, squareSize, squareSize,
9234 anim->prevFrame.x, anim->prevFrame.y);
9237 /* Save this frame for next time round */
9238 XCopyArea(xDisplay, anim->newBuf, anim->saveBuf, anim->blitGC,
9239 0, 0, squareSize, squareSize,
9241 anim->prevFrame = *frame;
9243 /* Draw piece over original screen contents, not current,
9244 and copy entire rect. Wipes out overlapping piece images. */
9245 OverlayPiece(piece, anim->pieceGC, anim->outlineGC, anim->newBuf);
9246 XCopyArea(xDisplay, anim->newBuf, xBoardWindow, anim->blitGC,
9247 0, 0, squareSize, squareSize,
9248 frame->x, frame->y);
9252 EndAnimation (anim, finish)
9256 XRectangle updates[4];
9261 /* The main code will redraw the final square, so we
9262 only need to erase the bits that don't overlap. */
9263 if (Intersect(&anim->prevFrame, finish, squareSize, &overlap, &pt)) {
9264 CalcUpdateRects(&anim->prevFrame, finish, squareSize, updates, &count);
9265 for (i = 0; i < count; i++)
9266 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9267 updates[i].x - anim->prevFrame.x,
9268 updates[i].y - anim->prevFrame.y,
9269 updates[i].width, updates[i].height,
9270 updates[i].x, updates[i].y);
9272 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9273 0, 0, squareSize, squareSize,
9274 anim->prevFrame.x, anim->prevFrame.y);
9279 FrameSequence(anim, piece, startColor, start, finish, frames, nFrames)
9281 ChessSquare piece; int startColor;
9282 XPoint * start; XPoint * finish;
9283 XPoint frames[]; int nFrames;
9287 BeginAnimation(anim, piece, startColor, start);
9288 for (n = 0; n < nFrames; n++) {
9289 AnimationFrame(anim, &(frames[n]), piece);
9290 FrameDelay(appData.animSpeed);
9292 EndAnimation(anim, finish);
9295 /* Main control logic for deciding what to animate and how */
9298 AnimateMove(board, fromX, fromY, toX, toY)
9307 XPoint start, finish, mid;
9308 XPoint frames[kFactor * 2 + 1];
9309 int nFrames, startColor, endColor;
9311 /* Are we animating? */
9312 if (!appData.animate || appData.blindfold)
9315 if(board[toY][toX] == WhiteRook && board[fromY][fromX] == WhiteKing ||
9316 board[toY][toX] == BlackRook && board[fromY][fromX] == BlackKing)
9317 return; // [HGM] FRC: no animtion of FRC castlings, as to-square is not true to-square
9319 if (fromY < 0 || fromX < 0 || toX < 0 || toY < 0) return;
9320 piece = board[fromY][fromX];
9321 if (piece >= EmptySquare) return;
9326 hop = (piece == WhiteKnight || piece == BlackKnight);
9329 if (appData.debugMode) {
9330 fprintf(debugFP, hop ? _("AnimateMove: piece %d hops from %d,%d to %d,%d \n") :
9331 _("AnimateMove: piece %d slides from %d,%d to %d,%d \n"),
9332 piece, fromX, fromY, toX, toY); }
9334 ScreenSquare(fromX, fromY, &start, &startColor);
9335 ScreenSquare(toX, toY, &finish, &endColor);
9338 /* Knight: make diagonal movement then straight */
9339 if (abs(toY - fromY) < abs(toX - fromX)) {
9340 mid.x = start.x + (finish.x - start.x) / 2;
9344 mid.y = start.y + (finish.y - start.y) / 2;
9347 mid.x = start.x + (finish.x - start.x) / 2;
9348 mid.y = start.y + (finish.y - start.y) / 2;
9351 /* Don't use as many frames for very short moves */
9352 if (abs(toY - fromY) + abs(toX - fromX) <= 2)
9353 Tween(&start, &mid, &finish, kFactor - 1, frames, &nFrames);
9355 Tween(&start, &mid, &finish, kFactor, frames, &nFrames);
9356 FrameSequence(&game, piece, startColor, &start, &finish, frames, nFrames);
9358 /* Be sure end square is redrawn */
9359 damage[toY][toX] = True;
9363 DragPieceBegin(x, y)
9366 int boardX, boardY, color;
9369 /* Are we animating? */
9370 if (!appData.animateDragging || appData.blindfold)
9373 /* Figure out which square we start in and the
9374 mouse position relative to top left corner. */
9375 BoardSquare(x, y, &boardX, &boardY);
9376 player.startBoardX = boardX;
9377 player.startBoardY = boardY;
9378 ScreenSquare(boardX, boardY, &corner, &color);
9379 player.startSquare = corner;
9380 player.startColor = color;
9381 /* As soon as we start dragging, the piece will jump slightly to
9382 be centered over the mouse pointer. */
9383 player.mouseDelta.x = squareSize/2;
9384 player.mouseDelta.y = squareSize/2;
9385 /* Initialise animation */
9386 player.dragPiece = PieceForSquare(boardX, boardY);
9388 if (player.dragPiece >= 0 && player.dragPiece < EmptySquare) {
9389 player.dragActive = True;
9390 BeginAnimation(&player, player.dragPiece, color, &corner);
9391 /* Mark this square as needing to be redrawn. Note that
9392 we don't remove the piece though, since logically (ie
9393 as seen by opponent) the move hasn't been made yet. */
9394 if(boardX == BOARD_RGHT+1 && PieceForSquare(boardX-1, boardY) > 1 ||
9395 boardX == BOARD_LEFT-2 && PieceForSquare(boardX+1, boardY) > 1)
9396 XCopyArea(xDisplay, xBoardWindow, player.saveBuf, player.blitGC,
9397 corner.x, corner.y, squareSize, squareSize,
9398 0, 0); // [HGM] zh: unstack in stead of grab
9399 damage[boardY][boardX] = True;
9401 player.dragActive = False;
9411 /* Are we animating? */
9412 if (!appData.animateDragging || appData.blindfold)
9416 if (! player.dragActive)
9418 /* Move piece, maintaining same relative position
9419 of mouse within square */
9420 corner.x = x - player.mouseDelta.x;
9421 corner.y = y - player.mouseDelta.y;
9422 AnimationFrame(&player, &corner, player.dragPiece);
9424 if (appData.highlightDragging) {
9426 BoardSquare(x, y, &boardX, &boardY);
9427 SetHighlights(fromX, fromY, boardX, boardY);
9436 int boardX, boardY, color;
9439 /* Are we animating? */
9440 if (!appData.animateDragging || appData.blindfold)
9444 if (! player.dragActive)
9446 /* Last frame in sequence is square piece is
9447 placed on, which may not match mouse exactly. */
9448 BoardSquare(x, y, &boardX, &boardY);
9449 ScreenSquare(boardX, boardY, &corner, &color);
9450 EndAnimation(&player, &corner);
9452 /* Be sure end square is redrawn */
9453 damage[boardY][boardX] = True;
9455 /* This prevents weird things happening with fast successive
9456 clicks which on my Sun at least can cause motion events
9457 without corresponding press/release. */
9458 player.dragActive = False;
9461 /* Handle expose event while piece being dragged */
9466 if (!player.dragActive || appData.blindfold)
9469 /* What we're doing: logically, the move hasn't been made yet,
9470 so the piece is still in it's original square. But visually
9471 it's being dragged around the board. So we erase the square
9472 that the piece is on and draw it at the last known drag point. */
9473 BlankSquare(player.startSquare.x, player.startSquare.y,
9474 player.startColor, EmptySquare, xBoardWindow);
9475 AnimationFrame(&player, &player.prevFrame, player.dragPiece);
9476 damage[player.startBoardY][player.startBoardX] = TRUE;
9480 SetProgramStats( FrontEndProgramStats * stats )
9483 // [HGM] done, but perhaps backend should call this directly?
9484 EngineOutputUpdate( stats );