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 RETSIGTYPE TermSizeSigHandler P((int sig));
236 void CreateGCs P((void));
237 void CreateXIMPieces P((void));
238 void CreateXPMPieces P((void));
239 void CreatePieces P((void));
240 void CreatePieceMenus P((void));
241 Widget CreateMenuBar P((Menu *mb));
242 Widget CreateButtonBar P ((MenuItem *mi));
243 char *FindFont P((char *pattern, int targetPxlSize));
244 void PieceMenuPopup P((Widget w, XEvent *event,
245 String *params, Cardinal *num_params));
246 static void PieceMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
247 static void DropMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
248 void ReadBitmap P((Pixmap *pm, String name, unsigned char bits[],
249 u_int wreq, u_int hreq));
250 void CreateGrid P((void));
251 int EventToSquare P((int x, int limit));
252 void DrawSquare P((int row, int column, ChessSquare piece, int do_flash));
253 void EventProc P((Widget widget, caddr_t unused, XEvent *event));
254 void HandleUserMove P((Widget w, XEvent *event,
255 String *prms, Cardinal *nprms));
256 void AnimateUserMove P((Widget w, XEvent * event,
257 String * params, Cardinal * nParams));
258 void WhiteClock P((Widget w, XEvent *event,
259 String *prms, Cardinal *nprms));
260 void BlackClock P((Widget w, XEvent *event,
261 String *prms, Cardinal *nprms));
262 void DrawPositionProc P((Widget w, XEvent *event,
263 String *prms, Cardinal *nprms));
264 void XDrawPosition P((Widget w, /*Boolean*/int repaint,
266 void CommentPopUp P((char *title, char *label));
267 void CommentPopDown P((void));
268 void CommentCallback P((Widget w, XtPointer client_data,
269 XtPointer call_data));
270 void ICSInputBoxPopUp P((void));
271 void ICSInputBoxPopDown P((void));
272 void FileNamePopUp P((char *label, char *def,
273 FileProc proc, char *openMode));
274 void FileNamePopDown P((void));
275 void FileNameCallback P((Widget w, XtPointer client_data,
276 XtPointer call_data));
277 void FileNameAction P((Widget w, XEvent *event,
278 String *prms, Cardinal *nprms));
279 void AskQuestionReplyAction P((Widget w, XEvent *event,
280 String *prms, Cardinal *nprms));
281 void AskQuestionProc P((Widget w, XEvent *event,
282 String *prms, Cardinal *nprms));
283 void AskQuestionPopDown 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 DragPieceMove P((int x, int y));
431 static void DrawDragPiece P((void));
432 char *ModeToWidgetName P((GameMode mode));
433 void EngineOutputUpdate( FrontEndProgramStats * stats );
434 void ShuffleMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
435 void EngineMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
436 void UciMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
437 void TimeControlProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
438 void NewVariantProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
439 void FirstSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
440 void SecondSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
441 void ShufflePopDown P(());
442 void EnginePopDown P(());
443 void UciPopDown P(());
444 void TimeControlPopDown P(());
445 void NewVariantPopDown P(());
446 void SettingsPopDown P(());
447 void update_ics_width P(());
448 int get_term_width P(());
450 * XBoard depends on Xt R4 or higher
452 int xtVersion = XtSpecificationRelease;
457 Pixel lightSquareColor, darkSquareColor, whitePieceColor, blackPieceColor,
458 jailSquareColor, highlightSquareColor, premoveHighlightColor;
459 Pixel lowTimeWarningColor;
460 GC lightSquareGC, darkSquareGC, jailSquareGC, lineGC, wdPieceGC, wlPieceGC,
461 bdPieceGC, blPieceGC, wbPieceGC, bwPieceGC, coordGC, highlineGC,
462 wjPieceGC, bjPieceGC, prelineGC, countGC;
463 Pixmap iconPixmap, wIconPixmap, bIconPixmap, xMarkPixmap;
464 Widget shellWidget, layoutWidget, formWidget, boardWidget, messageWidget,
465 whiteTimerWidget, blackTimerWidget, titleWidget, widgetList[16],
466 commentShell, promotionShell, whitePieceMenu, blackPieceMenu, dropMenu,
467 menuBarWidget, buttonBarWidget, editShell, errorShell, analysisShell,
468 ICSInputShell, fileNameShell, askQuestionShell;
469 XSegment gridSegments[(BOARD_SIZE + 1) * 2];
470 XSegment jailGridSegments[(BOARD_SIZE + 3) * 2];
471 Font clockFontID, coordFontID, countFontID;
472 XFontStruct *clockFontStruct, *coordFontStruct, *countFontStruct;
473 XtAppContext appContext;
475 char *oldICSInteractionTitle;
479 char installDir[] = "."; // [HGM] UCI: needed for UCI; probably needs run-time initializtion
481 Position commentX = -1, commentY = -1;
482 Dimension commentW, commentH;
484 int squareSize, smallLayout = 0, tinyLayout = 0,
485 marginW, marginH, // [HGM] for run-time resizing
486 fromX = -1, fromY = -1, toX, toY, commentUp = False, analysisUp = False,
487 ICSInputBoxUp = False, askQuestionUp = False,
488 filenameUp = False, promotionUp = False, pmFromX = -1, pmFromY = -1,
489 editUp = False, errorUp = False, errorExitStatus = -1, lineGap;
490 Pixel timerForegroundPixel, timerBackgroundPixel;
491 Pixel buttonForegroundPixel, buttonBackgroundPixel;
492 char *chessDir, *programName, *programVersion,
493 *gameCopyFilename, *gamePasteFilename;
497 Pixmap pieceBitmap[2][(int)BlackPawn];
498 Pixmap pieceBitmap2[2][(int)BlackPawn+4]; /* [HGM] pieces */
499 Pixmap xpmPieceBitmap[4][(int)BlackPawn]; /* LL, LD, DL, DD actually used*/
500 Pixmap xpmPieceBitmap2[4][(int)BlackPawn+4]; /* LL, LD, DL, DD set to select from */
501 Pixmap xpmLightSquare, xpmDarkSquare, xpmJailSquare;
502 int useImages, useImageSqs;
503 XImage *ximPieceBitmap[4][(int)BlackPawn+4]; /* LL, LD, DL, DD */
504 Pixmap ximMaskPm[(int)BlackPawn]; /* clipmasks, used for XIM pieces */
505 Pixmap ximMaskPm2[(int)BlackPawn+4]; /* clipmasks, used for XIM pieces */
506 XImage *ximLightSquare, *ximDarkSquare;
509 #define pieceToSolid(piece) &pieceBitmap[SOLID][(piece) % (int)BlackPawn]
510 #define pieceToOutline(piece) &pieceBitmap[OUTLINE][(piece) % (int)BlackPawn]
512 #define White(piece) ((int)(piece) < (int)BlackPawn)
514 /* Variables for doing smooth animation. This whole thing
515 would be much easier if the board was double-buffered,
516 but that would require a fairly major rewrite. */
521 GC blitGC, pieceGC, outlineGC;
522 XPoint startSquare, prevFrame, mouseDelta;
526 int startBoardX, startBoardY;
529 /* There can be two pieces being animated at once: a player
530 can begin dragging a piece before the remote opponent has moved. */
532 static AnimState game, player;
534 /* Bitmaps for use as masks when drawing XPM pieces.
535 Need one for each black and white piece. */
536 static Pixmap xpmMask[BlackKing + 1];
538 /* This magic number is the number of intermediate frames used
539 in each half of the animation. For short moves it's reduced
540 by 1. The total number of frames will be factor * 2 + 1. */
543 SizeDefaults sizeDefaults[] = SIZE_DEFAULTS;
545 MenuItem fileMenu[] = {
546 {N_("New Game"), ResetProc},
547 {N_("New Shuffle Game ..."), ShuffleMenuProc},
548 {N_("New Variant ..."), NewVariantProc}, // [HGM] variant: not functional yet
549 {"----", NothingProc},
550 {N_("Load Game"), LoadGameProc},
551 {N_("Load Next Game"), LoadNextGameProc},
552 {N_("Load Previous Game"), LoadPrevGameProc},
553 {N_("Reload Same Game"), ReloadGameProc},
554 {N_("Save Game"), SaveGameProc},
555 {"----", NothingProc},
556 {N_("Copy Game"), CopyGameProc},
557 {N_("Paste Game"), PasteGameProc},
558 {"----", NothingProc},
559 {N_("Load Position"), LoadPositionProc},
560 {N_("Load Next Position"), LoadNextPositionProc},
561 {N_("Load Previous Position"), LoadPrevPositionProc},
562 {N_("Reload Same Position"), ReloadPositionProc},
563 {N_("Save Position"), SavePositionProc},
564 {"----", NothingProc},
565 {N_("Copy Position"), CopyPositionProc},
566 {N_("Paste Position"), PastePositionProc},
567 {"----", NothingProc},
568 {N_("Mail Move"), MailMoveProc},
569 {N_("Reload CMail Message"), ReloadCmailMsgProc},
570 {"----", NothingProc},
571 {N_("Exit"), QuitProc},
575 MenuItem modeMenu[] = {
576 {N_("Machine White"), MachineWhiteProc},
577 {N_("Machine Black"), MachineBlackProc},
578 {N_("Two Machines"), TwoMachinesProc},
579 {N_("Analysis Mode"), AnalyzeModeProc},
580 {N_("Analyze File"), AnalyzeFileProc },
581 {N_("ICS Client"), IcsClientProc},
582 {N_("Edit Game"), EditGameProc},
583 {N_("Edit Position"), EditPositionProc},
584 {N_("Training"), TrainingProc},
585 {"----", NothingProc},
586 {N_("Show Engine Output"), EngineOutputProc},
587 {N_("Show Evaluation Graph"), NothingProc}, // [HGM] evalgr: not functional yet
588 {N_("Show Game List"), ShowGameListProc},
589 {"Show Move History", HistoryShowProc}, // [HGM] hist: activate 4.2.7 code
590 {"----", NothingProc},
591 {N_("Edit Tags"), EditTagsProc},
592 {N_("Edit Comment"), EditCommentProc},
593 {N_("ICS Input Box"), IcsInputBoxProc},
594 {N_("Pause"), PauseProc},
598 MenuItem actionMenu[] = {
599 {N_("Accept"), AcceptProc},
600 {N_("Decline"), DeclineProc},
601 {N_("Rematch"), RematchProc},
602 {"----", NothingProc},
603 {N_("Call Flag"), CallFlagProc},
604 {N_("Draw"), DrawProc},
605 {N_("Adjourn"), AdjournProc},
606 {N_("Abort"), AbortProc},
607 {N_("Resign"), ResignProc},
608 {"----", NothingProc},
609 {N_("Stop Observing"), StopObservingProc},
610 {N_("Stop Examining"), StopExaminingProc},
611 {"----", NothingProc},
612 {N_("Adjudicate to White"), AdjuWhiteProc},
613 {N_("Adjudicate to Black"), AdjuBlackProc},
614 {N_("Adjudicate Draw"), AdjuDrawProc},
618 MenuItem stepMenu[] = {
619 {N_("Backward"), BackwardProc},
620 {N_("Forward"), ForwardProc},
621 {N_("Back to Start"), ToStartProc},
622 {N_("Forward to End"), ToEndProc},
623 {N_("Revert"), RevertProc},
624 {N_("Truncate Game"), TruncateGameProc},
625 {"----", NothingProc},
626 {N_("Move Now"), MoveNowProc},
627 {N_("Retract Move"), RetractMoveProc},
631 MenuItem optionsMenu[] = {
632 {N_("Flip View"), FlipViewProc},
633 {"----", NothingProc},
634 {N_("Adjudications ..."), EngineMenuProc},
635 {N_("General Settings ..."), UciMenuProc},
636 {N_("Engine #1 Settings ..."), FirstSettingsProc},
637 {N_("Engine #2 Settings ..."), SecondSettingsProc},
638 {N_("Time Control ..."), TimeControlProc},
639 {"----", NothingProc},
640 {N_("Always Queen"), AlwaysQueenProc},
641 {N_("Animate Dragging"), AnimateDraggingProc},
642 {N_("Animate Moving"), AnimateMovingProc},
643 {N_("Auto Comment"), AutocommProc},
644 {N_("Auto Flag"), AutoflagProc},
645 {N_("Auto Flip View"), AutoflipProc},
646 {N_("Auto Observe"), AutobsProc},
647 {N_("Auto Raise Board"), AutoraiseProc},
648 {N_("Auto Save"), AutosaveProc},
649 {N_("Blindfold"), BlindfoldProc},
650 {N_("Flash Moves"), FlashMovesProc},
651 {N_("Get Move List"), GetMoveListProc},
653 {N_("Highlight Dragging"), HighlightDraggingProc},
655 {N_("Highlight Last Move"), HighlightLastMoveProc},
656 {N_("Move Sound"), MoveSoundProc},
657 {N_("ICS Alarm"), IcsAlarmProc},
658 {N_("Old Save Style"), OldSaveStyleProc},
659 {N_("Periodic Updates"), PeriodicUpdatesProc},
660 {N_("Ponder Next Move"), PonderNextMoveProc},
661 {N_("Popup Exit Message"), PopupExitMessageProc},
662 {N_("Popup Move Errors"), PopupMoveErrorsProc},
663 {N_("Premove"), PremoveProc},
664 {N_("Quiet Play"), QuietPlayProc},
665 {N_("Show Coords"), ShowCoordsProc},
666 {N_("Hide Thinking"), HideThinkingProc},
667 {N_("Test Legality"), TestLegalityProc},
671 MenuItem helpMenu[] = {
672 {N_("Info XBoard"), InfoProc},
673 {N_("Man XBoard"), ManProc},
674 {"----", NothingProc},
675 {N_("Hint"), HintProc},
676 {N_("Book"), BookProc},
677 {"----", NothingProc},
678 {N_("About XBoard"), AboutProc},
683 {N_("File"), fileMenu},
684 {N_("Mode"), modeMenu},
685 {N_("Action"), actionMenu},
686 {N_("Step"), stepMenu},
687 {N_("Options"), optionsMenu},
688 {N_("Help"), helpMenu},
692 #define PAUSE_BUTTON N_("P")
693 MenuItem buttonBar[] = {
696 {PAUSE_BUTTON, PauseProc},
702 #define PIECE_MENU_SIZE 18
703 String pieceMenuStrings[2][PIECE_MENU_SIZE] = {
704 { N_("White"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
705 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
706 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
707 N_("Empty square"), N_("Clear board") },
708 { N_("Black"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
709 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
710 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
711 N_("Empty square"), N_("Clear board") }
713 /* must be in same order as PieceMenuStrings! */
714 ChessSquare pieceMenuTranslation[2][PIECE_MENU_SIZE] = {
715 { WhitePlay, (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
716 WhiteRook, WhiteQueen, WhiteKing, (ChessSquare) 0, WhiteAlfil,
717 WhiteCannon, WhiteAngel, WhiteMarshall, (ChessSquare) 0,
718 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
719 { BlackPlay, (ChessSquare) 0, BlackPawn, BlackKnight, BlackBishop,
720 BlackRook, BlackQueen, BlackKing, (ChessSquare) 0, BlackAlfil,
721 BlackCannon, BlackAngel, BlackMarshall, (ChessSquare) 0,
722 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
725 #define DROP_MENU_SIZE 6
726 String dropMenuStrings[DROP_MENU_SIZE] = {
727 "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"), N_("Queen")
729 /* must be in same order as PieceMenuStrings! */
730 ChessSquare dropMenuTranslation[DROP_MENU_SIZE] = {
731 (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
732 WhiteRook, WhiteQueen
740 DropMenuEnables dmEnables[] = {
758 { XtNborderWidth, 0 },
759 { XtNdefaultDistance, 0 },
763 { XtNborderWidth, 0 },
764 { XtNresizable, (XtArgVal) True },
768 { XtNborderWidth, 0 },
774 { XtNjustify, (XtArgVal) XtJustifyRight },
775 { XtNlabel, (XtArgVal) "..." },
776 { XtNresizable, (XtArgVal) True },
777 { XtNresize, (XtArgVal) False }
780 Arg messageArgs[] = {
781 { XtNjustify, (XtArgVal) XtJustifyLeft },
782 { XtNlabel, (XtArgVal) "..." },
783 { XtNresizable, (XtArgVal) True },
784 { XtNresize, (XtArgVal) False }
788 { XtNborderWidth, 0 },
789 { XtNjustify, (XtArgVal) XtJustifyLeft }
792 XtResource clientResources[] = {
793 { "whitePieceColor", "whitePieceColor", XtRString, sizeof(String),
794 XtOffset(AppDataPtr, whitePieceColor), XtRString,
796 { "blackPieceColor", "blackPieceColor", XtRString, sizeof(String),
797 XtOffset(AppDataPtr, blackPieceColor), XtRString,
799 { "lightSquareColor", "lightSquareColor", XtRString,
800 sizeof(String), XtOffset(AppDataPtr, lightSquareColor),
801 XtRString, LIGHT_SQUARE_COLOR },
802 { "darkSquareColor", "darkSquareColor", XtRString, sizeof(String),
803 XtOffset(AppDataPtr, darkSquareColor), XtRString,
805 { "highlightSquareColor", "highlightSquareColor", XtRString,
806 sizeof(String), XtOffset(AppDataPtr, highlightSquareColor),
807 XtRString, HIGHLIGHT_SQUARE_COLOR },
808 { "premoveHighlightColor", "premoveHighlightColor", XtRString,
809 sizeof(String), XtOffset(AppDataPtr, premoveHighlightColor),
810 XtRString, PREMOVE_HIGHLIGHT_COLOR },
811 { "movesPerSession", "movesPerSession", XtRInt, sizeof(int),
812 XtOffset(AppDataPtr, movesPerSession), XtRImmediate,
813 (XtPointer) MOVES_PER_SESSION },
814 { "timeIncrement", "timeIncrement", XtRInt, sizeof(int),
815 XtOffset(AppDataPtr, timeIncrement), XtRImmediate,
816 (XtPointer) TIME_INCREMENT },
817 { "initString", "initString", XtRString, sizeof(String),
818 XtOffset(AppDataPtr, initString), XtRString, INIT_STRING },
819 { "secondInitString", "secondInitString", XtRString, sizeof(String),
820 XtOffset(AppDataPtr, secondInitString), XtRString, INIT_STRING },
821 { "firstComputerString", "firstComputerString", XtRString,
822 sizeof(String), XtOffset(AppDataPtr, firstComputerString), XtRString,
824 { "secondComputerString", "secondComputerString", XtRString,
825 sizeof(String), XtOffset(AppDataPtr, secondComputerString), XtRString,
827 { "firstChessProgram", "firstChessProgram", XtRString,
828 sizeof(String), XtOffset(AppDataPtr, firstChessProgram),
829 XtRString, FIRST_CHESS_PROGRAM },
830 { "secondChessProgram", "secondChessProgram", XtRString,
831 sizeof(String), XtOffset(AppDataPtr, secondChessProgram),
832 XtRString, SECOND_CHESS_PROGRAM },
833 { "firstPlaysBlack", "firstPlaysBlack", XtRBoolean,
834 sizeof(Boolean), XtOffset(AppDataPtr, firstPlaysBlack),
835 XtRImmediate, (XtPointer) False },
836 { "noChessProgram", "noChessProgram", XtRBoolean,
837 sizeof(Boolean), XtOffset(AppDataPtr, noChessProgram),
838 XtRImmediate, (XtPointer) False },
839 { "firstHost", "firstHost", XtRString, sizeof(String),
840 XtOffset(AppDataPtr, firstHost), XtRString, FIRST_HOST },
841 { "secondHost", "secondHost", XtRString, sizeof(String),
842 XtOffset(AppDataPtr, secondHost), XtRString, SECOND_HOST },
843 { "firstDirectory", "firstDirectory", XtRString, sizeof(String),
844 XtOffset(AppDataPtr, firstDirectory), XtRString, "." },
845 { "secondDirectory", "secondDirectory", XtRString, sizeof(String),
846 XtOffset(AppDataPtr, secondDirectory), XtRString, "." },
847 { "bitmapDirectory", "bitmapDirectory", XtRString,
848 sizeof(String), XtOffset(AppDataPtr, bitmapDirectory),
850 { "remoteShell", "remoteShell", XtRString, sizeof(String),
851 XtOffset(AppDataPtr, remoteShell), XtRString, REMOTE_SHELL },
852 { "remoteUser", "remoteUser", XtRString, sizeof(String),
853 XtOffset(AppDataPtr, remoteUser), XtRString, "" },
854 { "timeDelay", "timeDelay", XtRFloat, sizeof(float),
855 XtOffset(AppDataPtr, timeDelay), XtRString,
856 (XtPointer) TIME_DELAY_QUOTE },
857 { "timeControl", "timeControl", XtRString, sizeof(String),
858 XtOffset(AppDataPtr, timeControl), XtRString,
859 (XtPointer) TIME_CONTROL },
860 { "internetChessServerMode", "internetChessServerMode",
861 XtRBoolean, sizeof(Boolean),
862 XtOffset(AppDataPtr, icsActive), XtRImmediate,
864 { "internetChessServerHost", "internetChessServerHost",
865 XtRString, sizeof(String),
866 XtOffset(AppDataPtr, icsHost),
867 XtRString, (XtPointer) ICS_HOST },
868 { "internetChessServerPort", "internetChessServerPort",
869 XtRString, sizeof(String),
870 XtOffset(AppDataPtr, icsPort), XtRString,
871 (XtPointer) ICS_PORT },
872 { "internetChessServerCommPort", "internetChessServerCommPort",
873 XtRString, sizeof(String),
874 XtOffset(AppDataPtr, icsCommPort), XtRString,
876 { "internetChessServerLogonScript", "internetChessServerLogonScript",
877 XtRString, sizeof(String),
878 XtOffset(AppDataPtr, icsLogon), XtRString,
880 { "internetChessServerHelper", "internetChessServerHelper",
881 XtRString, sizeof(String),
882 XtOffset(AppDataPtr, icsHelper), XtRString, "" },
883 { "internetChessServerInputBox", "internetChessServerInputBox",
884 XtRBoolean, sizeof(Boolean),
885 XtOffset(AppDataPtr, icsInputBox), XtRImmediate,
887 { "icsAlarm", "icsAlarm",
888 XtRBoolean, sizeof(Boolean),
889 XtOffset(AppDataPtr, icsAlarm), XtRImmediate,
891 { "icsAlarmTime", "icsAlarmTime",
893 XtOffset(AppDataPtr, icsAlarmTime), XtRImmediate,
895 { "useTelnet", "useTelnet", XtRBoolean, sizeof(Boolean),
896 XtOffset(AppDataPtr, useTelnet), XtRImmediate,
898 { "telnetProgram", "telnetProgram", XtRString, sizeof(String),
899 XtOffset(AppDataPtr, telnetProgram), XtRString, TELNET_PROGRAM },
900 { "gateway", "gateway", XtRString, sizeof(String),
901 XtOffset(AppDataPtr, gateway), XtRString, "" },
902 { "loadGameFile", "loadGameFile", XtRString, sizeof(String),
903 XtOffset(AppDataPtr, loadGameFile), XtRString, "" },
904 { "loadGameIndex", "loadGameIndex",
906 XtOffset(AppDataPtr, loadGameIndex), XtRImmediate,
908 { "saveGameFile", "saveGameFile", XtRString, sizeof(String),
909 XtOffset(AppDataPtr, saveGameFile), XtRString, "" },
910 { "autoRaiseBoard", "autoRaiseBoard", XtRBoolean,
911 sizeof(Boolean), XtOffset(AppDataPtr, autoRaiseBoard),
912 XtRImmediate, (XtPointer) True },
913 { "autoSaveGames", "autoSaveGames", XtRBoolean,
914 sizeof(Boolean), XtOffset(AppDataPtr, autoSaveGames),
915 XtRImmediate, (XtPointer) False },
916 { "blindfold", "blindfold", XtRBoolean,
917 sizeof(Boolean), XtOffset(AppDataPtr, blindfold),
918 XtRImmediate, (XtPointer) False },
919 { "loadPositionFile", "loadPositionFile", XtRString,
920 sizeof(String), XtOffset(AppDataPtr, loadPositionFile),
922 { "loadPositionIndex", "loadPositionIndex",
924 XtOffset(AppDataPtr, loadPositionIndex), XtRImmediate,
926 { "savePositionFile", "savePositionFile", XtRString,
927 sizeof(String), XtOffset(AppDataPtr, savePositionFile),
929 { "matchMode", "matchMode", XtRBoolean, sizeof(Boolean),
930 XtOffset(AppDataPtr, matchMode), XtRImmediate, (XtPointer) False },
931 { "matchGames", "matchGames", XtRInt, sizeof(int),
932 XtOffset(AppDataPtr, matchGames), XtRImmediate,
934 { "monoMode", "monoMode", XtRBoolean, sizeof(Boolean),
935 XtOffset(AppDataPtr, monoMode), XtRImmediate,
937 { "debugMode", "debugMode", XtRBoolean, sizeof(Boolean),
938 XtOffset(AppDataPtr, debugMode), XtRImmediate,
940 { "clockMode", "clockMode", XtRBoolean, sizeof(Boolean),
941 XtOffset(AppDataPtr, clockMode), XtRImmediate,
943 { "boardSize", "boardSize", XtRString, sizeof(String),
944 XtOffset(AppDataPtr, boardSize), XtRString, "" },
945 { "searchTime", "searchTime", XtRString, sizeof(String),
946 XtOffset(AppDataPtr, searchTime), XtRString,
948 { "searchDepth", "searchDepth", XtRInt, sizeof(int),
949 XtOffset(AppDataPtr, searchDepth), XtRImmediate,
951 { "showCoords", "showCoords", XtRBoolean, sizeof(Boolean),
952 XtOffset(AppDataPtr, showCoords), XtRImmediate,
954 { "showJail", "showJail", XtRInt, sizeof(int),
955 XtOffset(AppDataPtr, showJail), XtRImmediate,
957 { "showThinking", "showThinking", XtRBoolean, sizeof(Boolean),
958 XtOffset(AppDataPtr, showThinking), XtRImmediate,
960 { "ponderNextMove", "ponderNextMove", XtRBoolean, sizeof(Boolean),
961 XtOffset(AppDataPtr, ponderNextMove), XtRImmediate,
963 { "periodicUpdates", "periodicUpdates", XtRBoolean, sizeof(Boolean),
964 XtOffset(AppDataPtr, periodicUpdates), XtRImmediate,
966 { "clockFont", "clockFont", XtRString, sizeof(String),
967 XtOffset(AppDataPtr, clockFont), XtRString, CLOCK_FONT },
968 { "coordFont", "coordFont", XtRString, sizeof(String),
969 XtOffset(AppDataPtr, coordFont), XtRString, COORD_FONT },
970 { "font", "font", XtRString, sizeof(String),
971 XtOffset(AppDataPtr, font), XtRString, DEFAULT_FONT },
972 { "ringBellAfterMoves", "ringBellAfterMoves",
973 XtRBoolean, sizeof(Boolean),
974 XtOffset(AppDataPtr, ringBellAfterMoves),
975 XtRImmediate, (XtPointer) False },
976 { "autoCallFlag", "autoCallFlag", XtRBoolean,
977 sizeof(Boolean), XtOffset(AppDataPtr, autoCallFlag),
978 XtRImmediate, (XtPointer) False },
979 { "autoFlipView", "autoFlipView", XtRBoolean,
980 sizeof(Boolean), XtOffset(AppDataPtr, autoFlipView),
981 XtRImmediate, (XtPointer) True },
982 { "autoObserve", "autoObserve", XtRBoolean,
983 sizeof(Boolean), XtOffset(AppDataPtr, autoObserve),
984 XtRImmediate, (XtPointer) False },
985 { "autoComment", "autoComment", XtRBoolean,
986 sizeof(Boolean), XtOffset(AppDataPtr, autoComment),
987 XtRImmediate, (XtPointer) False },
988 { "getMoveList", "getMoveList", XtRBoolean,
989 sizeof(Boolean), XtOffset(AppDataPtr, getMoveList),
990 XtRImmediate, (XtPointer) True },
992 { "highlightDragging", "highlightDragging", XtRBoolean,
993 sizeof(Boolean), XtOffset(AppDataPtr, highlightDragging),
994 XtRImmediate, (XtPointer) False },
996 { "highlightLastMove", "highlightLastMove", XtRBoolean,
997 sizeof(Boolean), XtOffset(AppDataPtr, highlightLastMove),
998 XtRImmediate, (XtPointer) False },
999 { "premove", "premove", XtRBoolean,
1000 sizeof(Boolean), XtOffset(AppDataPtr, premove),
1001 XtRImmediate, (XtPointer) True },
1002 { "testLegality", "testLegality", XtRBoolean,
1003 sizeof(Boolean), XtOffset(AppDataPtr, testLegality),
1004 XtRImmediate, (XtPointer) True },
1005 { "flipView", "flipView", XtRBoolean,
1006 sizeof(Boolean), XtOffset(AppDataPtr, flipView),
1007 XtRImmediate, (XtPointer) False },
1008 { "cmail", "cmailGameName", XtRString, sizeof(String),
1009 XtOffset(AppDataPtr, cmailGameName), XtRString, "" },
1010 { "alwaysPromoteToQueen", "alwaysPromoteToQueen", XtRBoolean,
1011 sizeof(Boolean), XtOffset(AppDataPtr, alwaysPromoteToQueen),
1012 XtRImmediate, (XtPointer) False },
1013 { "oldSaveStyle", "oldSaveStyle", XtRBoolean,
1014 sizeof(Boolean), XtOffset(AppDataPtr, oldSaveStyle),
1015 XtRImmediate, (XtPointer) False },
1016 { "quietPlay", "quietPlay", XtRBoolean,
1017 sizeof(Boolean), XtOffset(AppDataPtr, quietPlay),
1018 XtRImmediate, (XtPointer) False },
1019 { "titleInWindow", "titleInWindow", XtRBoolean,
1020 sizeof(Boolean), XtOffset(AppDataPtr, titleInWindow),
1021 XtRImmediate, (XtPointer) False },
1022 { "localLineEditing", "localLineEditing", XtRBoolean,
1023 sizeof(Boolean), XtOffset(AppDataPtr, localLineEditing),
1024 XtRImmediate, (XtPointer) True }, /* not implemented, must be True */
1026 { "zippyTalk", "zippyTalk", XtRBoolean,
1027 sizeof(Boolean), XtOffset(AppDataPtr, zippyTalk),
1028 XtRImmediate, (XtPointer) ZIPPY_TALK },
1029 { "zippyPlay", "zippyPlay", XtRBoolean,
1030 sizeof(Boolean), XtOffset(AppDataPtr, zippyPlay),
1031 XtRImmediate, (XtPointer) ZIPPY_PLAY },
1032 { "zippyLines", "zippyLines", XtRString, sizeof(String),
1033 XtOffset(AppDataPtr, zippyLines), XtRString, ZIPPY_LINES },
1034 { "zippyPinhead", "zippyPinhead", XtRString, sizeof(String),
1035 XtOffset(AppDataPtr, zippyPinhead), XtRString, ZIPPY_PINHEAD },
1036 { "zippyPassword", "zippyPassword", XtRString, sizeof(String),
1037 XtOffset(AppDataPtr, zippyPassword), XtRString, ZIPPY_PASSWORD },
1038 { "zippyPassword2", "zippyPassword2", XtRString, sizeof(String),
1039 XtOffset(AppDataPtr, zippyPassword2), XtRString, ZIPPY_PASSWORD2 },
1040 { "zippyWrongPassword", "zippyWrongPassword", XtRString, sizeof(String),
1041 XtOffset(AppDataPtr, zippyWrongPassword), XtRString,
1042 ZIPPY_WRONG_PASSWORD },
1043 { "zippyAcceptOnly", "zippyAcceptOnly", XtRString, sizeof(String),
1044 XtOffset(AppDataPtr, zippyAcceptOnly), XtRString, ZIPPY_ACCEPT_ONLY },
1045 { "zippyUseI", "zippyUseI", XtRBoolean,
1046 sizeof(Boolean), XtOffset(AppDataPtr, zippyUseI),
1047 XtRImmediate, (XtPointer) ZIPPY_USE_I },
1048 { "zippyBughouse", "zippyBughouse", XtRInt,
1049 sizeof(int), XtOffset(AppDataPtr, zippyBughouse),
1050 XtRImmediate, (XtPointer) ZIPPY_BUGHOUSE },
1051 { "zippyNoplayCrafty", "zippyNoplayCrafty", XtRBoolean,
1052 sizeof(Boolean), XtOffset(AppDataPtr, zippyNoplayCrafty),
1053 XtRImmediate, (XtPointer) ZIPPY_NOPLAY_CRAFTY },
1054 { "zippyGameEnd", "zippyGameEnd", XtRString, sizeof(String),
1055 XtOffset(AppDataPtr, zippyGameEnd), XtRString, ZIPPY_GAME_END },
1056 { "zippyGameStart", "zippyGameStart", XtRString, sizeof(String),
1057 XtOffset(AppDataPtr, zippyGameStart), XtRString, ZIPPY_GAME_START },
1058 { "zippyAdjourn", "zippyAdjourn", XtRBoolean,
1059 sizeof(Boolean), XtOffset(AppDataPtr, zippyAdjourn),
1060 XtRImmediate, (XtPointer) ZIPPY_ADJOURN },
1061 { "zippyAbort", "zippyAbort", XtRBoolean,
1062 sizeof(Boolean), XtOffset(AppDataPtr, zippyAbort),
1063 XtRImmediate, (XtPointer) ZIPPY_ABORT },
1064 { "zippyVariants", "zippyVariants", XtRString, sizeof(String),
1065 XtOffset(AppDataPtr, zippyVariants), XtRString, ZIPPY_VARIANTS },
1066 { "zippyMaxGames", "zippyMaxGames", XtRInt, sizeof(int),
1067 XtOffset(AppDataPtr, zippyMaxGames), XtRImmediate,
1068 (XtPointer) ZIPPY_MAX_GAMES },
1069 { "zippyReplayTimeout", "zippyReplayTimeout", XtRInt, sizeof(int),
1070 XtOffset(AppDataPtr, zippyReplayTimeout), XtRImmediate,
1071 (XtPointer) ZIPPY_REPLAY_TIMEOUT },
1072 { "zippyShortGame", "zippyShortGame", XtRInt, sizeof(int),
1073 XtOffset(AppDataPtr, zippyShortGame), XtRImmediate,
1076 { "flashCount", "flashCount", XtRInt, sizeof(int),
1077 XtOffset(AppDataPtr, flashCount), XtRImmediate,
1078 (XtPointer) FLASH_COUNT },
1079 { "flashRate", "flashRate", XtRInt, sizeof(int),
1080 XtOffset(AppDataPtr, flashRate), XtRImmediate,
1081 (XtPointer) FLASH_RATE },
1082 { "pixmapDirectory", "pixmapDirectory", XtRString,
1083 sizeof(String), XtOffset(AppDataPtr, pixmapDirectory),
1085 { "msLoginDelay", "msLoginDelay", XtRInt, sizeof(int),
1086 XtOffset(AppDataPtr, msLoginDelay), XtRImmediate,
1087 (XtPointer) MS_LOGIN_DELAY },
1088 { "colorizeMessages", "colorizeMessages", XtRBoolean,
1089 sizeof(Boolean), XtOffset(AppDataPtr, colorize),
1090 XtRImmediate, (XtPointer) False },
1091 { "colorShout", "colorShout", XtRString,
1092 sizeof(String), XtOffset(AppDataPtr, colorShout),
1093 XtRString, COLOR_SHOUT },
1094 { "colorSShout", "colorSShout", XtRString,
1095 sizeof(String), XtOffset(AppDataPtr, colorSShout),
1096 XtRString, COLOR_SSHOUT },
1097 { "colorChannel1", "colorChannel1", XtRString,
1098 sizeof(String), XtOffset(AppDataPtr, colorChannel1),
1099 XtRString, COLOR_CHANNEL1 },
1100 { "colorChannel", "colorChannel", XtRString,
1101 sizeof(String), XtOffset(AppDataPtr, colorChannel),
1102 XtRString, COLOR_CHANNEL },
1103 { "colorKibitz", "colorKibitz", XtRString,
1104 sizeof(String), XtOffset(AppDataPtr, colorKibitz),
1105 XtRString, COLOR_KIBITZ },
1106 { "colorTell", "colorTell", XtRString,
1107 sizeof(String), XtOffset(AppDataPtr, colorTell),
1108 XtRString, COLOR_TELL },
1109 { "colorChallenge", "colorChallenge", XtRString,
1110 sizeof(String), XtOffset(AppDataPtr, colorChallenge),
1111 XtRString, COLOR_CHALLENGE },
1112 { "colorRequest", "colorRequest", XtRString,
1113 sizeof(String), XtOffset(AppDataPtr, colorRequest),
1114 XtRString, COLOR_REQUEST },
1115 { "colorSeek", "colorSeek", XtRString,
1116 sizeof(String), XtOffset(AppDataPtr, colorSeek),
1117 XtRString, COLOR_SEEK },
1118 { "colorNormal", "colorNormal", XtRString,
1119 sizeof(String), XtOffset(AppDataPtr, colorNormal),
1120 XtRString, COLOR_NORMAL },
1121 { "soundProgram", "soundProgram", XtRString,
1122 sizeof(String), XtOffset(AppDataPtr, soundProgram),
1123 XtRString, "play" },
1124 { "soundShout", "soundShout", XtRString,
1125 sizeof(String), XtOffset(AppDataPtr, soundShout),
1127 { "soundSShout", "soundSShout", XtRString,
1128 sizeof(String), XtOffset(AppDataPtr, soundSShout),
1130 { "soundChannel1", "soundChannel1", XtRString,
1131 sizeof(String), XtOffset(AppDataPtr, soundChannel1),
1133 { "soundChannel", "soundChannel", XtRString,
1134 sizeof(String), XtOffset(AppDataPtr, soundChannel),
1136 { "soundKibitz", "soundKibitz", XtRString,
1137 sizeof(String), XtOffset(AppDataPtr, soundKibitz),
1139 { "soundTell", "soundTell", XtRString,
1140 sizeof(String), XtOffset(AppDataPtr, soundTell),
1142 { "soundChallenge", "soundChallenge", XtRString,
1143 sizeof(String), XtOffset(AppDataPtr, soundChallenge),
1145 { "soundRequest", "soundRequest", XtRString,
1146 sizeof(String), XtOffset(AppDataPtr, soundRequest),
1148 { "soundSeek", "soundSeek", XtRString,
1149 sizeof(String), XtOffset(AppDataPtr, soundSeek),
1151 { "soundMove", "soundMove", XtRString,
1152 sizeof(String), XtOffset(AppDataPtr, soundMove),
1154 { "soundIcsWin", "soundIcsWin", XtRString,
1155 sizeof(String), XtOffset(AppDataPtr, soundIcsWin),
1157 { "soundIcsLoss", "soundIcsLoss", XtRString,
1158 sizeof(String), XtOffset(AppDataPtr, soundIcsLoss),
1160 { "soundIcsDraw", "soundIcsDraw", XtRString,
1161 sizeof(String), XtOffset(AppDataPtr, soundIcsDraw),
1163 { "soundIcsUnfinished", "soundIcsUnfinished", XtRString,
1164 sizeof(String), XtOffset(AppDataPtr, soundIcsUnfinished),
1166 { "soundIcsAlarm", "soundIcsAlarm", XtRString,
1167 sizeof(String), XtOffset(AppDataPtr, soundIcsAlarm),
1169 { "reuseFirst", "reuseFirst", XtRBoolean,
1170 sizeof(Boolean), XtOffset(AppDataPtr, reuseFirst),
1171 XtRImmediate, (XtPointer) True },
1172 { "reuseSecond", "reuseSecond", XtRBoolean,
1173 sizeof(Boolean), XtOffset(AppDataPtr, reuseSecond),
1174 XtRImmediate, (XtPointer) True },
1175 { "animateDragging", "animateDragging", XtRBoolean,
1176 sizeof(Boolean), XtOffset(AppDataPtr, animateDragging),
1177 XtRImmediate, (XtPointer) True },
1178 { "animateMoving", "animateMoving", XtRBoolean,
1179 sizeof(Boolean), XtOffset(AppDataPtr, animate),
1180 XtRImmediate, (XtPointer) True },
1181 { "animateSpeed", "animateSpeed", XtRInt,
1182 sizeof(int), XtOffset(AppDataPtr, animSpeed),
1183 XtRImmediate, (XtPointer)10 },
1184 { "popupExitMessage", "popupExitMessage", XtRBoolean,
1185 sizeof(Boolean), XtOffset(AppDataPtr, popupExitMessage),
1186 XtRImmediate, (XtPointer) True },
1187 { "popupMoveErrors", "popupMoveErrors", XtRBoolean,
1188 sizeof(Boolean), XtOffset(AppDataPtr, popupMoveErrors),
1189 XtRImmediate, (XtPointer) False },
1190 { "fontSizeTolerance", "fontSizeTolerance", XtRInt,
1191 sizeof(int), XtOffset(AppDataPtr, fontSizeTolerance),
1192 XtRImmediate, (XtPointer)4 },
1193 { "initialMode", "initialMode", XtRString,
1194 sizeof(String), XtOffset(AppDataPtr, initialMode),
1195 XtRImmediate, (XtPointer) "" },
1196 { "variant", "variant", XtRString,
1197 sizeof(String), XtOffset(AppDataPtr, variant),
1198 XtRImmediate, (XtPointer) "normal" },
1199 { "firstProtocolVersion", "firstProtocolVersion", XtRInt,
1200 sizeof(int), XtOffset(AppDataPtr, firstProtocolVersion),
1201 XtRImmediate, (XtPointer)PROTOVER },
1202 { "secondProtocolVersion", "secondProtocolVersion", XtRInt,
1203 sizeof(int), XtOffset(AppDataPtr, secondProtocolVersion),
1204 XtRImmediate, (XtPointer)PROTOVER },
1205 { "showButtonBar", "showButtonBar", XtRBoolean,
1206 sizeof(Boolean), XtOffset(AppDataPtr, showButtonBar),
1207 XtRImmediate, (XtPointer) True },
1208 { "lowTimeWarningColor", "lowTimeWarningColor", XtRString,
1209 sizeof(String), XtOffset(AppDataPtr, lowTimeWarningColor),
1210 XtRString, COLOR_LOWTIMEWARNING },
1211 { "lowTimeWarning", "lowTimeWarning", XtRBoolean,
1212 sizeof(Boolean), XtOffset(AppDataPtr, lowTimeWarning),
1213 XtRImmediate, (XtPointer) False },
1214 {"icsEngineAnalyze", "icsEngineAnalyze", XtRBoolean, /* [DM] icsEngineAnalyze */
1215 sizeof(Boolean), XtOffset(AppDataPtr, icsEngineAnalyze),
1216 XtRImmediate, (XtPointer) False },
1217 { "firstScoreAbs", "firstScoreAbs", XtRBoolean,
1218 sizeof(Boolean), XtOffset(AppDataPtr, firstScoreIsAbsolute),
1219 XtRImmediate, (XtPointer) False },
1220 { "secondScoreAbs", "secondScoreAbs", XtRBoolean,
1221 sizeof(Boolean), XtOffset(AppDataPtr, secondScoreIsAbsolute),
1222 XtRImmediate, (XtPointer) False },
1223 { "pgnExtendedInfo", "pgnExtendedInfo", XtRBoolean,
1224 sizeof(Boolean), XtOffset(AppDataPtr, saveExtendedInfoInPGN),
1225 XtRImmediate, (XtPointer) False },
1226 { "hideThinkingFromHuman", "hideThinkingFromHuman", XtRBoolean,
1227 sizeof(Boolean), XtOffset(AppDataPtr, hideThinkingFromHuman),
1228 XtRImmediate, (XtPointer) True },
1229 { "adjudicateLossThreshold", "adjudicateLossThreshold", XtRInt,
1230 sizeof(int), XtOffset(AppDataPtr, adjudicateLossThreshold),
1231 XtRImmediate, (XtPointer) 0},
1232 { "adjudicateDrawMoves", "adjudicateDrawMoves", XtRInt,
1233 sizeof(int), XtOffset(AppDataPtr, adjudicateDrawMoves),
1234 XtRImmediate, (XtPointer) 0},
1235 { "pgnEventHeader", "pgnEventHeader", XtRString,
1236 sizeof(String), XtOffset(AppDataPtr, pgnEventHeader),
1237 XtRImmediate, (XtPointer) "Computer Chess Game" },
1238 { "defaultFrcPosition", "defaultFrcPositon", XtRInt,
1239 sizeof(int), XtOffset(AppDataPtr, defaultFrcPosition),
1240 XtRImmediate, (XtPointer) -1},
1241 { "gameListTags", "gameListTags", XtRString,
1242 sizeof(String), XtOffset(AppDataPtr, gameListTags),
1243 XtRImmediate, (XtPointer) GLT_DEFAULT_TAGS },
1245 // [HGM] 4.3.xx options
1246 { "boardWidth", "boardWidth", XtRInt,
1247 sizeof(int), XtOffset(AppDataPtr, NrFiles),
1248 XtRImmediate, (XtPointer) -1},
1249 { "boardHeight", "boardHeight", XtRInt,
1250 sizeof(int), XtOffset(AppDataPtr, NrRanks),
1251 XtRImmediate, (XtPointer) -1},
1252 { "matchPause", "matchPause", XtRInt,
1253 sizeof(int), XtOffset(AppDataPtr, matchPause),
1254 XtRImmediate, (XtPointer) 10000},
1255 { "holdingsSize", "holdingsSize", XtRInt,
1256 sizeof(int), XtOffset(AppDataPtr, holdingsSize),
1257 XtRImmediate, (XtPointer) -1},
1258 { "flipBlack", "flipBlack", XtRBoolean,
1259 sizeof(Boolean), XtOffset(AppDataPtr, upsideDown),
1260 XtRImmediate, (XtPointer) False},
1261 { "allWhite", "allWhite", XtRBoolean,
1262 sizeof(Boolean), XtOffset(AppDataPtr, allWhite),
1263 XtRImmediate, (XtPointer) False},
1264 { "pieceToCharTable", "pieceToCharTable", XtRString,
1265 sizeof(String), XtOffset(AppDataPtr, pieceToCharTable),
1266 XtRImmediate, (XtPointer) 0},
1267 { "alphaRank", "alphaRank", XtRBoolean,
1268 sizeof(Boolean), XtOffset(AppDataPtr, alphaRank),
1269 XtRImmediate, (XtPointer) False},
1270 { "testClaims", "testClaims", XtRBoolean,
1271 sizeof(Boolean), XtOffset(AppDataPtr, testClaims),
1272 XtRImmediate, (XtPointer) True},
1273 { "checkMates", "checkMates", XtRBoolean,
1274 sizeof(Boolean), XtOffset(AppDataPtr, checkMates),
1275 XtRImmediate, (XtPointer) True},
1276 { "materialDraws", "materialDraws", XtRBoolean,
1277 sizeof(Boolean), XtOffset(AppDataPtr, materialDraws),
1278 XtRImmediate, (XtPointer) True},
1279 { "trivialDraws", "trivialDraws", XtRBoolean,
1280 sizeof(Boolean), XtOffset(AppDataPtr, trivialDraws),
1281 XtRImmediate, (XtPointer) False},
1282 { "ruleMoves", "ruleMoves", XtRInt,
1283 sizeof(int), XtOffset(AppDataPtr, ruleMoves),
1284 XtRImmediate, (XtPointer) 51},
1285 { "repeatsToDraw", "repeatsToDraw", XtRInt,
1286 sizeof(int), XtOffset(AppDataPtr, drawRepeats),
1287 XtRImmediate, (XtPointer) 6},
1288 { "engineDebugOutput", "engineDebugOutput", XtRInt,
1289 sizeof(int), XtOffset(AppDataPtr, engineComments),
1290 XtRImmediate, (XtPointer) 1},
1291 { "userName", "userName", XtRString,
1292 sizeof(int), XtOffset(AppDataPtr, userName),
1293 XtRImmediate, (XtPointer) 0},
1294 { "autoKibitz", "autoKibitz", XtRBoolean,
1295 sizeof(Boolean), XtOffset(AppDataPtr, autoKibitz),
1296 XtRImmediate, (XtPointer) False},
1297 { "firstTimeOdds", "firstTimeOdds", XtRInt,
1298 sizeof(int), XtOffset(AppDataPtr, firstTimeOdds),
1299 XtRImmediate, (XtPointer) 1},
1300 { "secondTimeOdds", "secondTimeOdds", XtRInt,
1301 sizeof(int), XtOffset(AppDataPtr, secondTimeOdds),
1302 XtRImmediate, (XtPointer) 1},
1303 { "timeOddsMode", "timeOddsMode", XtRInt,
1304 sizeof(int), XtOffset(AppDataPtr, timeOddsMode),
1305 XtRImmediate, (XtPointer) 0},
1306 { "firstAccumulateTC", "firstAccumulateTC", XtRInt,
1307 sizeof(int), XtOffset(AppDataPtr, firstAccumulateTC),
1308 XtRImmediate, (XtPointer) 1},
1309 { "secondAccumulateTC", "secondAccumulateTC", XtRInt,
1310 sizeof(int), XtOffset(AppDataPtr, secondAccumulateTC),
1311 XtRImmediate, (XtPointer) 1},
1312 { "firstNPS", "firstNPS", XtRInt,
1313 sizeof(int), XtOffset(AppDataPtr, firstNPS),
1314 XtRImmediate, (XtPointer) -1},
1315 { "secondNPS", "secondNPS", XtRInt,
1316 sizeof(int), XtOffset(AppDataPtr, secondNPS),
1317 XtRImmediate, (XtPointer) -1},
1318 { "serverMoves", "serverMoves", XtRString,
1319 sizeof(String), XtOffset(AppDataPtr, serverMovesName),
1320 XtRImmediate, (XtPointer) 0},
1321 { "serverPause", "serverPause", XtRInt,
1322 sizeof(int), XtOffset(AppDataPtr, serverPause),
1323 XtRImmediate, (XtPointer) 0},
1324 { "suppressLoadMoves", "suppressLoadMoves", XtRBoolean,
1325 sizeof(Boolean), XtOffset(AppDataPtr, suppressLoadMoves),
1326 XtRImmediate, (XtPointer) False},
1327 { "userName", "userName", XtRString,
1328 sizeof(String), XtOffset(AppDataPtr, userName),
1329 XtRImmediate, (XtPointer) 0},
1330 { "egtFormats", "egtFormats", XtRString,
1331 sizeof(String), XtOffset(AppDataPtr, egtFormats),
1332 XtRImmediate, (XtPointer) 0},
1333 { "rewindIndex", "rewindIndex", XtRInt,
1334 sizeof(int), XtOffset(AppDataPtr, rewindIndex),
1335 XtRImmediate, (XtPointer) 0},
1336 { "sameColorGames", "sameColorGames", XtRInt,
1337 sizeof(int), XtOffset(AppDataPtr, sameColorGames),
1338 XtRImmediate, (XtPointer) 0},
1339 { "smpCores", "smpCores", XtRInt,
1340 sizeof(int), XtOffset(AppDataPtr, smpCores),
1341 XtRImmediate, (XtPointer) 1},
1342 { "niceEngines", "niceEngines", XtRInt,
1343 sizeof(int), XtOffset(AppDataPtr, niceEngines),
1344 XtRImmediate, (XtPointer) 0},
1345 { "nameOfDebugFile", "nameOfDebugFile", XtRString,
1346 sizeof(String), XtOffset(AppDataPtr, nameOfDebugFile),
1347 XtRImmediate, (XtPointer) "xboard.debug"},
1348 { "engineDebugOutput", "engineDebugOutput", XtRInt,
1349 sizeof(int), XtOffset(AppDataPtr, engineComments),
1350 XtRImmediate, (XtPointer) 1},
1351 { "noGUI", "noGUI", XtRBoolean,
1352 sizeof(Boolean), XtOffset(AppDataPtr, noGUI),
1353 XtRImmediate, (XtPointer) 0},
1354 { "firstOptions", "firstOptions", XtRString,
1355 sizeof(String), XtOffset(AppDataPtr, firstOptions),
1356 XtRImmediate, (XtPointer) "" },
1357 { "secondOptions", "secondOptions", XtRString,
1358 sizeof(String), XtOffset(AppDataPtr, secondOptions),
1359 XtRImmediate, (XtPointer) "" },
1360 { "firstNeedsNoncompliantFEN", "firstNeedsNoncompliantFEN", XtRString,
1361 sizeof(String), XtOffset(AppDataPtr, fenOverride1),
1362 XtRImmediate, (XtPointer) 0 },
1363 { "secondNeedsNoncompliantFEN", "secondNeedsNoncompliantFEN", XtRString,
1364 sizeof(String), XtOffset(AppDataPtr, fenOverride2),
1365 XtRImmediate, (XtPointer) 0 },
1367 // [HGM] Winboard_x UCI options
1368 { "firstIsUCI", "firstIsUCI", XtRBoolean,
1369 sizeof(Boolean), XtOffset(AppDataPtr, firstIsUCI),
1370 XtRImmediate, (XtPointer) False},
1371 { "secondIsUCI", "secondIsUCI", XtRBoolean,
1372 sizeof(Boolean), XtOffset(AppDataPtr, secondIsUCI),
1373 XtRImmediate, (XtPointer) False},
1374 { "firstHasOwnBookUCI", "firstHasOwnBookUCI", XtRBoolean,
1375 sizeof(Boolean), XtOffset(AppDataPtr, firstHasOwnBookUCI),
1376 XtRImmediate, (XtPointer) True},
1377 { "secondHasOwnBookUCI", "secondHasOwnBookUCI", XtRBoolean,
1378 sizeof(Boolean), XtOffset(AppDataPtr, secondHasOwnBookUCI),
1379 XtRImmediate, (XtPointer) True},
1380 { "usePolyglotBook", "usePolyglotBook", XtRBoolean,
1381 sizeof(Boolean), XtOffset(AppDataPtr, usePolyglotBook),
1382 XtRImmediate, (XtPointer) False},
1383 { "defaultHashSize", "defaultHashSize", XtRInt,
1384 sizeof(int), XtOffset(AppDataPtr, defaultHashSize),
1385 XtRImmediate, (XtPointer) 64},
1386 { "defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XtRInt,
1387 sizeof(int), XtOffset(AppDataPtr, defaultCacheSizeEGTB),
1388 XtRImmediate, (XtPointer) 4},
1389 { "polyglotDir", "polyglotDir", XtRString,
1390 sizeof(String), XtOffset(AppDataPtr, polyglotDir),
1391 XtRImmediate, (XtPointer) "." },
1392 { "polyglotBook", "polyglotBook", XtRString,
1393 sizeof(String), XtOffset(AppDataPtr, polyglotBook),
1394 XtRImmediate, (XtPointer) "" },
1395 { "defaultPathEGTB", "defaultPathEGTB", XtRString,
1396 sizeof(String), XtOffset(AppDataPtr, defaultPathEGTB),
1397 XtRImmediate, (XtPointer) "/usr/local/share/egtb"},
1398 { "delayBeforeQuit", "delayBeforeQuit", XtRInt,
1399 sizeof(int), XtOffset(AppDataPtr, delayBeforeQuit),
1400 XtRImmediate, (XtPointer) 0},
1401 { "delayAfterQuit", "delayAfterQuit", XtRInt,
1402 sizeof(int), XtOffset(AppDataPtr, delayAfterQuit),
1403 XtRImmediate, (XtPointer) 0},
1404 { "keepAlive", "keepAlive", XtRInt,
1405 sizeof(int), XtOffset(AppDataPtr, keepAlive),
1406 XtRImmediate, (XtPointer) 0},
1407 { "forceIllegalMoves", "forceIllegalMoves", XtRBoolean,
1408 sizeof(Boolean), XtOffset(AppDataPtr, forceIllegal),
1409 XtRImmediate, (XtPointer) False},
1410 { "keepLineBreaksICS", "keepLineBreaksICS", XtRBoolean,
1411 sizeof(Boolean), XtOffset(AppDataPtr, noJoin),
1412 XtRImmediate, (XtPointer) True},
1415 XrmOptionDescRec shellOptions[] = {
1416 { "-whitePieceColor", "whitePieceColor", XrmoptionSepArg, NULL },
1417 { "-blackPieceColor", "blackPieceColor", XrmoptionSepArg, NULL },
1418 { "-lightSquareColor", "lightSquareColor", XrmoptionSepArg, NULL },
1419 { "-darkSquareColor", "darkSquareColor", XrmoptionSepArg, NULL },
1420 { "-highlightSquareColor", "highlightSquareColor", XrmoptionSepArg, NULL },
1421 { "-premoveHighlightColor", "premoveHighlightColor", XrmoptionSepArg,NULL},
1422 { "-movesPerSession", "movesPerSession", XrmoptionSepArg, NULL },
1423 { "-mps", "movesPerSession", XrmoptionSepArg, NULL },
1424 { "-timeIncrement", "timeIncrement", XrmoptionSepArg, NULL },
1425 { "-inc", "timeIncrement", XrmoptionSepArg, NULL },
1426 { "-initString", "initString", XrmoptionSepArg, NULL },
1427 { "-firstInitString", "initString", XrmoptionSepArg, NULL },
1428 { "-secondInitString", "secondInitString", XrmoptionSepArg, NULL },
1429 { "-firstComputerString", "firstComputerString", XrmoptionSepArg, NULL },
1430 { "-secondComputerString", "secondComputerString", XrmoptionSepArg, NULL },
1431 { "-firstChessProgram", "firstChessProgram", XrmoptionSepArg, NULL },
1432 { "-fcp", "firstChessProgram", XrmoptionSepArg, NULL },
1433 { "-secondChessProgram", "secondChessProgram", XrmoptionSepArg, NULL },
1434 { "-scp", "secondChessProgram", XrmoptionSepArg, NULL },
1435 { "-firstPlaysBlack", "firstPlaysBlack", XrmoptionSepArg, NULL },
1436 { "-fb", "firstPlaysBlack", XrmoptionNoArg, "True" },
1437 { "-xfb", "firstPlaysBlack", XrmoptionNoArg, "False" },
1438 { "-noChessProgram", "noChessProgram", XrmoptionSepArg, NULL },
1439 { "-ncp", "noChessProgram", XrmoptionNoArg, "True" },
1440 { "-xncp", "noChessProgram", XrmoptionNoArg, "False" },
1441 { "-firstHost", "firstHost", XrmoptionSepArg, NULL },
1442 { "-fh", "firstHost", XrmoptionSepArg, NULL },
1443 { "-secondHost", "secondHost", XrmoptionSepArg, NULL },
1444 { "-sh", "secondHost", XrmoptionSepArg, NULL },
1445 { "-firstDirectory", "firstDirectory", XrmoptionSepArg, NULL },
1446 { "-fd", "firstDirectory", XrmoptionSepArg, NULL },
1447 { "-secondDirectory", "secondDirectory", XrmoptionSepArg, NULL },
1448 { "-sd", "secondDirectory", XrmoptionSepArg, NULL },
1449 { "-bitmapDirectory", "bitmapDirectory", XrmoptionSepArg, NULL },
1450 { "-bm", "bitmapDirectory", XrmoptionSepArg, NULL },
1451 { "-remoteShell", "remoteShell", XrmoptionSepArg, NULL },
1452 { "-rsh", "remoteShell", XrmoptionSepArg, NULL },
1453 { "-remoteUser", "remoteUser", XrmoptionSepArg, NULL },
1454 { "-ruser", "remoteUser", XrmoptionSepArg, NULL },
1455 { "-timeDelay", "timeDelay", XrmoptionSepArg, NULL },
1456 { "-td", "timeDelay", XrmoptionSepArg, NULL },
1457 { "-timeControl", "timeControl", XrmoptionSepArg, NULL },
1458 { "-tc", "timeControl", XrmoptionSepArg, NULL },
1459 { "-internetChessServerMode", "internetChessServerMode",
1460 XrmoptionSepArg, NULL },
1461 { "-ics", "internetChessServerMode", XrmoptionNoArg, "True" },
1462 { "-xics", "internetChessServerMode", XrmoptionNoArg, "False" },
1463 { "-internetChessServerHost", "internetChessServerHost",
1464 XrmoptionSepArg, NULL },
1465 { "-icshost", "internetChessServerHost", XrmoptionSepArg, NULL },
1466 { "-internetChessServerPort", "internetChessServerPort",
1467 XrmoptionSepArg, NULL },
1468 { "-icsport", "internetChessServerPort", XrmoptionSepArg, NULL },
1469 { "-internetChessServerCommPort", "internetChessServerCommPort",
1470 XrmoptionSepArg, NULL },
1471 { "-icscomm", "internetChessServerCommPort", XrmoptionSepArg, NULL },
1472 { "-internetChessServerLogonScript", "internetChessServerLogonScript",
1473 XrmoptionSepArg, NULL },
1474 { "-icslogon", "internetChessServerLogonScript", XrmoptionSepArg, NULL },
1475 { "-internetChessServerHelper", "internetChessServerHelper",
1476 XrmoptionSepArg, NULL },
1477 { "-icshelper", "internetChessServerHelper", XrmoptionSepArg, NULL },
1478 { "-internetChessServerInputBox", "internetChessServerInputBox",
1479 XrmoptionSepArg, NULL },
1480 { "-icsinput", "internetChessServerInputBox", XrmoptionNoArg, "True" },
1481 { "-xicsinput", "internetChessServerInputBox", XrmoptionNoArg, "False" },
1482 { "-icsAlarm", "icsAlarm", XrmoptionSepArg, NULL },
1483 { "-alarm", "icsAlarm", XrmoptionNoArg, "True" },
1484 { "-xalarm", "icsAlarm", XrmoptionNoArg, "False" },
1485 { "-icsAlarmTime", "icsAlarmTime", XrmoptionSepArg, NULL },
1486 { "-useTelnet", "useTelnet", XrmoptionSepArg, NULL },
1487 { "-telnet", "useTelnet", XrmoptionNoArg, "True" },
1488 { "-xtelnet", "useTelnet", XrmoptionNoArg, "False" },
1489 { "-telnetProgram", "telnetProgram", XrmoptionSepArg, NULL },
1490 { "-gateway", "gateway", XrmoptionSepArg, NULL },
1491 { "-loadGameFile", "loadGameFile", XrmoptionSepArg, NULL },
1492 { "-lgf", "loadGameFile", XrmoptionSepArg, NULL },
1493 { "-loadGameIndex", "loadGameIndex", XrmoptionSepArg, NULL },
1494 { "-lgi", "loadGameIndex", XrmoptionSepArg, NULL },
1495 { "-saveGameFile", "saveGameFile", XrmoptionSepArg, NULL },
1496 { "-sgf", "saveGameFile", XrmoptionSepArg, NULL },
1497 { "-autoSaveGames", "autoSaveGames", XrmoptionSepArg, NULL },
1498 { "-autosave", "autoSaveGames", XrmoptionNoArg, "True" },
1499 { "-xautosave", "autoSaveGames", XrmoptionNoArg, "False" },
1500 { "-autoRaiseBoard", "autoRaiseBoard", XrmoptionSepArg, NULL },
1501 { "-autoraise", "autoRaiseBoard", XrmoptionNoArg, "True" },
1502 { "-xautoraise", "autoRaiseBoard", XrmoptionNoArg, "False" },
1503 { "-blindfold", "blindfold", XrmoptionSepArg, NULL },
1504 { "-blind", "blindfold", XrmoptionNoArg, "True" },
1505 { "-xblind", "blindfold", XrmoptionNoArg, "False" },
1506 { "-loadPositionFile", "loadPositionFile", XrmoptionSepArg, NULL },
1507 { "-lpf", "loadPositionFile", XrmoptionSepArg, NULL },
1508 { "-loadPositionIndex", "loadPositionIndex", XrmoptionSepArg, NULL },
1509 { "-lpi", "loadPositionIndex", XrmoptionSepArg, NULL },
1510 { "-savePositionFile", "savePositionFile", XrmoptionSepArg, NULL },
1511 { "-spf", "savePositionFile", XrmoptionSepArg, NULL },
1512 { "-matchMode", "matchMode", XrmoptionSepArg, NULL },
1513 { "-mm", "matchMode", XrmoptionNoArg, "True" },
1514 { "-xmm", "matchMode", XrmoptionNoArg, "False" },
1515 { "-matchGames", "matchGames", XrmoptionSepArg, NULL },
1516 { "-mg", "matchGames", XrmoptionSepArg, NULL },
1517 { "-monoMode", "monoMode", XrmoptionSepArg, NULL },
1518 { "-mono", "monoMode", XrmoptionNoArg, "True" },
1519 { "-xmono", "monoMode", XrmoptionNoArg, "False" },
1520 { "-debugMode", "debugMode", XrmoptionSepArg, NULL },
1521 { "-debug", "debugMode", XrmoptionNoArg, "True" },
1522 { "-xdebug", "debugMode", XrmoptionNoArg, "False" },
1523 { "-clockMode", "clockMode", XrmoptionSepArg, NULL },
1524 { "-clock", "clockMode", XrmoptionNoArg, "True" },
1525 { "-xclock", "clockMode", XrmoptionNoArg, "False" },
1526 { "-boardSize", "boardSize", XrmoptionSepArg, NULL },
1527 { "-size", "boardSize", XrmoptionSepArg, NULL },
1528 { "-searchTime", "searchTime", XrmoptionSepArg, NULL },
1529 { "-st", "searchTime", XrmoptionSepArg, NULL },
1530 { "-searchDepth", "searchDepth", XrmoptionSepArg, NULL },
1531 { "-depth", "searchDepth", XrmoptionSepArg, NULL },
1532 { "-showCoords", "showCoords", XrmoptionSepArg, NULL },
1533 { "-coords", "showCoords", XrmoptionNoArg, "True" },
1534 { "-xcoords", "showCoords", XrmoptionNoArg, "False" },
1536 { "-showJail", "showJail", XrmoptionSepArg, NULL },
1537 { "-jail", "showJail", XrmoptionNoArg, "1" },
1538 { "-sidejail", "showJail", XrmoptionNoArg, "2" },
1539 { "-xjail", "showJail", XrmoptionNoArg, "0" },
1541 { "-showThinking", "showThinking", XrmoptionSepArg, NULL },
1542 { "-thinking", "showThinking", XrmoptionNoArg, "True" },
1543 { "-xthinking", "showThinking", XrmoptionNoArg, "False" },
1544 { "-ponderNextMove", "ponderNextMove", XrmoptionSepArg, NULL },
1545 { "-ponder", "ponderNextMove", XrmoptionNoArg, "True" },
1546 { "-xponder", "ponderNextMove", XrmoptionNoArg, "False" },
1547 { "-periodicUpdates", "periodicUpdates", XrmoptionSepArg, NULL },
1548 { "-periodic", "periodicUpdates", XrmoptionNoArg, "True" },
1549 { "-xperiodic", "periodicUpdates", XrmoptionNoArg, "False" },
1550 { "-clockFont", "clockFont", XrmoptionSepArg, NULL },
1551 { "-coordFont", "coordFont", XrmoptionSepArg, NULL },
1552 { "-font", "font", XrmoptionSepArg, NULL },
1553 { "-ringBellAfterMoves", "ringBellAfterMoves", XrmoptionSepArg, NULL },
1554 { "-bell", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1555 { "-xbell", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1556 { "-movesound", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1557 { "-xmovesound", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1558 { "-autoCallFlag", "autoCallFlag", XrmoptionSepArg, NULL },
1559 { "-autoflag", "autoCallFlag", XrmoptionNoArg, "True" },
1560 { "-xautoflag", "autoCallFlag", XrmoptionNoArg, "False" },
1561 { "-autoFlipView", "autoFlipView", XrmoptionSepArg, NULL },
1562 { "-autoflip", "autoFlipView", XrmoptionNoArg, "True" },
1563 { "-xautoflip", "autoFlipView", XrmoptionNoArg, "False" },
1564 { "-autoObserve", "autoObserve", XrmoptionSepArg, NULL },
1565 { "-autobs", "autoObserve", XrmoptionNoArg, "True" },
1566 { "-xautobs", "autoObserve", XrmoptionNoArg, "False" },
1567 { "-autoComment", "autoComment", XrmoptionSepArg, NULL },
1568 { "-autocomm", "autoComment", XrmoptionNoArg, "True" },
1569 { "-xautocomm", "autoComment", XrmoptionNoArg, "False" },
1570 { "-getMoveList", "getMoveList", XrmoptionSepArg, NULL },
1571 { "-moves", "getMoveList", XrmoptionNoArg, "True" },
1572 { "-xmoves", "getMoveList", XrmoptionNoArg, "False" },
1574 { "-highlightDragging", "highlightDragging", XrmoptionSepArg, NULL },
1575 { "-highdrag", "highlightDragging", XrmoptionNoArg, "True" },
1576 { "-xhighdrag", "highlightDragging", XrmoptionNoArg, "False" },
1578 { "-highlightLastMove", "highlightLastMove", XrmoptionSepArg, NULL },
1579 { "-highlight", "highlightLastMove", XrmoptionNoArg, "True" },
1580 { "-xhighlight", "highlightLastMove", XrmoptionNoArg, "False" },
1581 { "-premove", "premove", XrmoptionSepArg, NULL },
1582 { "-pre", "premove", XrmoptionNoArg, "True" },
1583 { "-xpre", "premove", XrmoptionNoArg, "False" },
1584 { "-testLegality", "testLegality", XrmoptionSepArg, NULL },
1585 { "-legal", "testLegality", XrmoptionNoArg, "True" },
1586 { "-xlegal", "testLegality", XrmoptionNoArg, "False" },
1587 { "-flipView", "flipView", XrmoptionSepArg, NULL },
1588 { "-flip", "flipView", XrmoptionNoArg, "True" },
1589 { "-xflip", "flipView", XrmoptionNoArg, "False" },
1590 { "-cmail", "cmailGameName", XrmoptionSepArg, NULL },
1591 { "-alwaysPromoteToQueen", "alwaysPromoteToQueen",
1592 XrmoptionSepArg, NULL },
1593 { "-queen", "alwaysPromoteToQueen", XrmoptionNoArg, "True" },
1594 { "-xqueen", "alwaysPromoteToQueen", XrmoptionNoArg, "False" },
1595 { "-oldSaveStyle", "oldSaveStyle", XrmoptionSepArg, NULL },
1596 { "-oldsave", "oldSaveStyle", XrmoptionNoArg, "True" },
1597 { "-xoldsave", "oldSaveStyle", XrmoptionNoArg, "False" },
1598 { "-quietPlay", "quietPlay", XrmoptionSepArg, NULL },
1599 { "-quiet", "quietPlay", XrmoptionNoArg, "True" },
1600 { "-xquiet", "quietPlay", XrmoptionNoArg, "False" },
1601 { "-titleInWindow", "titleInWindow", XrmoptionSepArg, NULL },
1602 { "-title", "titleInWindow", XrmoptionNoArg, "True" },
1603 { "-xtitle", "titleInWindow", XrmoptionNoArg, "False" },
1605 { "-zippyTalk", "zippyTalk", XrmoptionSepArg, NULL },
1606 { "-zt", "zippyTalk", XrmoptionNoArg, "True" },
1607 { "-xzt", "zippyTalk", XrmoptionNoArg, "False" },
1608 { "-zippyPlay", "zippyPlay", XrmoptionSepArg, NULL },
1609 { "-zp", "zippyPlay", XrmoptionNoArg, "True" },
1610 { "-xzp", "zippyPlay", XrmoptionNoArg, "False" },
1611 { "-zippyLines", "zippyLines", XrmoptionSepArg, NULL },
1612 { "-zippyPinhead", "zippyPinhead", XrmoptionSepArg, NULL },
1613 { "-zippyPassword", "zippyPassword", XrmoptionSepArg, NULL },
1614 { "-zippyPassword2", "zippyPassword2", XrmoptionSepArg, NULL },
1615 { "-zippyWrongPassword", "zippyWrongPassword", XrmoptionSepArg, NULL },
1616 { "-zippyAcceptOnly", "zippyAcceptOnly", XrmoptionSepArg, NULL },
1617 { "-zippyUseI", "zippyUseI", XrmoptionSepArg, NULL },
1618 { "-zui", "zippyUseI", XrmoptionNoArg, "True" },
1619 { "-xzui", "zippyUseI", XrmoptionNoArg, "False" },
1620 { "-zippyBughouse", "zippyBughouse", XrmoptionSepArg, NULL },
1621 { "-zippyNoplayCrafty", "zippyNoplayCrafty", XrmoptionSepArg, NULL },
1622 { "-znc", "zippyNoplayCrafty", XrmoptionNoArg, "True" },
1623 { "-xznc", "zippyNoplayCrafty", XrmoptionNoArg, "False" },
1624 { "-zippyGameEnd", "zippyGameEnd", XrmoptionSepArg, NULL },
1625 { "-zippyGameStart", "zippyGameStart", XrmoptionSepArg, NULL },
1626 { "-zippyAdjourn", "zippyAdjourn", XrmoptionSepArg, NULL },
1627 { "-zadj", "zippyAdjourn", XrmoptionNoArg, "True" },
1628 { "-xzadj", "zippyAdjourn", XrmoptionNoArg, "False" },
1629 { "-zippyAbort", "zippyAbort", XrmoptionSepArg, NULL },
1630 { "-zab", "zippyAbort", XrmoptionNoArg, "True" },
1631 { "-xzab", "zippyAbort", XrmoptionNoArg, "False" },
1632 { "-zippyVariants", "zippyVariants", XrmoptionSepArg, NULL },
1633 { "-zippyMaxGames", "zippyMaxGames", XrmoptionSepArg, NULL },
1634 { "-zippyReplayTimeout", "zippyReplayTimeout", XrmoptionSepArg, NULL },
1635 { "-zippyShortGame", "zippyShortGame", XrmoptionSepArg, NULL },
1637 { "-flashCount", "flashCount", XrmoptionSepArg, NULL },
1638 { "-flash", "flashCount", XrmoptionNoArg, "3" },
1639 { "-xflash", "flashCount", XrmoptionNoArg, "0" },
1640 { "-flashRate", "flashRate", XrmoptionSepArg, NULL },
1641 { "-pixmapDirectory", "pixmapDirectory", XrmoptionSepArg, NULL },
1642 { "-msLoginDelay", "msLoginDelay", XrmoptionSepArg, NULL },
1643 { "-pixmap", "pixmapDirectory", XrmoptionSepArg, NULL },
1644 { "-colorizeMessages", "colorizeMessages", XrmoptionSepArg, NULL },
1645 { "-colorize", "colorizeMessages", XrmoptionNoArg, "True" },
1646 { "-xcolorize", "colorizeMessages", XrmoptionNoArg, "False" },
1647 { "-colorShout", "colorShout", XrmoptionSepArg, NULL },
1648 { "-colorSShout", "colorSShout", XrmoptionSepArg, NULL },
1649 { "-colorCShout", "colorSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1650 { "-colorChannel1", "colorChannel1", XrmoptionSepArg, NULL },
1651 { "-colorChannel", "colorChannel", XrmoptionSepArg, NULL },
1652 { "-colorKibitz", "colorKibitz", XrmoptionSepArg, NULL },
1653 { "-colorTell", "colorTell", XrmoptionSepArg, NULL },
1654 { "-colorChallenge", "colorChallenge", XrmoptionSepArg, NULL },
1655 { "-colorRequest", "colorRequest", XrmoptionSepArg, NULL },
1656 { "-colorSeek", "colorSeek", XrmoptionSepArg, NULL },
1657 { "-colorNormal", "colorNormal", XrmoptionSepArg, NULL },
1658 { "-soundProgram", "soundProgram", XrmoptionSepArg, NULL },
1659 { "-soundShout", "soundShout", XrmoptionSepArg, NULL },
1660 { "-soundSShout", "soundSShout", XrmoptionSepArg, NULL },
1661 { "-soundCShout", "soundSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1662 { "-soundChannel1", "soundChannel1", XrmoptionSepArg, NULL },
1663 { "-soundChannel", "soundChannel", XrmoptionSepArg, NULL },
1664 { "-soundKibitz", "soundKibitz", XrmoptionSepArg, NULL },
1665 { "-soundTell", "soundTell", XrmoptionSepArg, NULL },
1666 { "-soundChallenge", "soundChallenge", XrmoptionSepArg, NULL },
1667 { "-soundRequest", "soundRequest", XrmoptionSepArg, NULL },
1668 { "-soundSeek", "soundSeek", XrmoptionSepArg, NULL },
1669 { "-soundMove", "soundMove", XrmoptionSepArg, NULL },
1670 { "-soundIcsWin", "soundIcsWin", XrmoptionSepArg, NULL },
1671 { "-soundIcsLoss", "soundIcsLoss", XrmoptionSepArg, NULL },
1672 { "-soundIcsDraw", "soundIcsDraw", XrmoptionSepArg, NULL },
1673 { "-soundIcsUnfinished", "soundIcsUnfinished", XrmoptionSepArg, NULL },
1674 { "-soundIcsAlarm", "soundIcsAlarm", XrmoptionSepArg, NULL },
1675 { "-reuseFirst", "reuseFirst", XrmoptionSepArg, NULL },
1676 { "-reuseChessPrograms", "reuseFirst", XrmoptionSepArg, NULL }, /*compat*/
1677 { "-reuse", "reuseFirst", XrmoptionNoArg, "True" },
1678 { "-xreuse", "reuseFirst", XrmoptionNoArg, "False" },
1679 { "-reuseSecond", "reuseSecond", XrmoptionSepArg, NULL },
1680 { "-reuse2", "reuseSecond", XrmoptionNoArg, "True" },
1681 { "-xreuse2", "reuseSecond", XrmoptionNoArg, "False" },
1682 { "-animateMoving", "animateMoving", XrmoptionSepArg, NULL },
1683 { "-animate", "animateMoving", XrmoptionNoArg, "True" },
1684 { "-xanimate", "animateMoving", XrmoptionNoArg, "False" },
1685 { "-animateDragging", "animateDragging", XrmoptionSepArg, NULL },
1686 { "-drag", "animateDragging", XrmoptionNoArg, "True" },
1687 { "-xdrag", "animateDragging", XrmoptionNoArg, "False" },
1688 { "-animateSpeed", "animateSpeed", XrmoptionSepArg, NULL },
1689 { "-popupExitMessage", "popupExitMessage", XrmoptionSepArg, NULL },
1690 { "-exit", "popupExitMessage", XrmoptionNoArg, "True" },
1691 { "-xexit", "popupExitMessage", XrmoptionNoArg, "False" },
1692 { "-popupMoveErrors", "popupMoveErrors", XrmoptionSepArg, NULL },
1693 { "-popup", "popupMoveErrors", XrmoptionNoArg, "True" },
1694 { "-xpopup", "popupMoveErrors", XrmoptionNoArg, "False" },
1695 { "-fontSizeTolerance", "fontSizeTolerance", XrmoptionSepArg, NULL },
1696 { "-initialMode", "initialMode", XrmoptionSepArg, NULL },
1697 { "-mode", "initialMode", XrmoptionSepArg, NULL },
1698 { "-variant", "variant", XrmoptionSepArg, NULL },
1699 { "-firstProtocolVersion", "firstProtocolVersion", XrmoptionSepArg, NULL },
1700 { "-secondProtocolVersion","secondProtocolVersion",XrmoptionSepArg, NULL },
1701 { "-showButtonBar", "showButtonBar", XrmoptionSepArg, NULL },
1702 { "-buttons", "showButtonBar", XrmoptionNoArg, "True" },
1703 { "-xbuttons", "showButtonBar", XrmoptionNoArg, "False" },
1704 { "-lowTimeWarningColor", "lowTimeWarningColor", XrmoptionSepArg, NULL },
1705 { "-lowTimeWarning", "lowTimeWarning", XrmoptionSepArg, NULL },
1706 /* [AS,HR] New features */
1707 { "-firstScoreAbs", "firstScoreAbs", XrmoptionSepArg, NULL },
1708 { "-secondScoreAbs", "secondScoreAbs", XrmoptionSepArg, NULL },
1709 { "-pgnExtendedInfo", "pgnExtendedInfo", XrmoptionSepArg, NULL },
1710 { "-hideThinkingFromHuman", "hideThinkingFromHuman", XrmoptionSepArg, NULL },
1711 { "-adjudicateLossThreshold", "adjudicateLossThreshold", XrmoptionSepArg, NULL },
1712 { "-adjudicateDrawMoves", "adjudicateDrawMoves", XrmoptionSepArg, NULL },
1713 { "-pgnEventHeader", "pgnEventHeader", XrmoptionSepArg, NULL },
1714 { "-firstIsUCI", "firstIsUCI", XrmoptionSepArg, NULL },
1715 { "-secondIsUCI", "secondIsUCI", XrmoptionSepArg, NULL },
1716 { "-fUCI", "firstIsUCI", XrmoptionNoArg, "True" },
1717 { "-sUCI", "secondIsUCI", XrmoptionNoArg, "True" },
1718 { "-firstHasOwnBookUCI", "firstHasOwnBookUCI", XrmoptionSepArg, NULL },
1719 { "-secondHasOwnBookUCI", "secondHasOwnBookUCI", XrmoptionSepArg, NULL },
1720 { "-fNoOwnBookUCI", "firstHasOwnBookUCI", XrmoptionNoArg, "False" },
1721 { "-sNoOwnBookUCI", "secondHasOwnBookUCI", XrmoptionNoArg, "False" },
1722 { "-firstXBook", "firstHasOwnBookUCI", XrmoptionNoArg, "False" },
1723 { "-secondXBook", "secondHasOwnBookUCI", XrmoptionNoArg, "False" },
1724 { "-polyglotDir", "polyglotDir", XrmoptionSepArg, NULL },
1725 { "-usePolyglotBook", "usePolyglotBook", XrmoptionSepArg, NULL },
1726 { "-polyglotBook", "polyglotBook", XrmoptionSepArg, NULL },
1727 { "-defaultHashSize", "defaultHashSize", XrmoptionSepArg, NULL },
1728 { "-defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XrmoptionSepArg, NULL },
1729 { "-defaultPathEGTB", "defaultPathEGTB", XrmoptionSepArg, NULL },
1730 { "-defaultFrcPosition", "defaultFrcPosition", XrmoptionSepArg, NULL },
1731 { "-gameListTags", "gameListTags", XrmoptionSepArg, NULL },
1732 // [HGM] I am sure AS added many more options, but we have to fish them out, from the list in winboard.c
1734 /* [HGM,HR] User-selectable board size */
1735 { "-boardWidth", "boardWidth", XrmoptionSepArg, NULL },
1736 { "-boardHeight", "boardHeight", XrmoptionSepArg, NULL },
1737 { "-matchPause", "matchPause", XrmoptionSepArg, NULL },
1739 /* [HGM] new arguments of 4.3.xx. All except first three are back-end options, which should work immediately */
1740 { "-holdingsSize", "holdingsSize", XrmoptionSepArg, NULL }, // requires extensive front-end changes to work
1741 { "-flipBlack", "flipBlack", XrmoptionSepArg, NULL }, // requires front-end changes to work
1742 { "-allWhite", "allWhite", XrmoptionSepArg, NULL }, // requires front-end changes to work
1743 { "-pieceToCharTable", "pieceToCharTable", XrmoptionSepArg, NULL },
1744 { "-alphaRank", "alphaRank", XrmoptionSepArg, NULL },
1745 { "-testClaims", "testClaims", XrmoptionSepArg, NULL },
1746 { "-checkMates", "checkMates", XrmoptionSepArg, NULL },
1747 { "-materialDraws", "materialDraws", XrmoptionSepArg, NULL },
1748 { "-trivialDraws", "trivialDraws", XrmoptionSepArg, NULL },
1749 { "-ruleMoves", "ruleMoves", XrmoptionSepArg, NULL },
1750 { "-repeatsToDraw", "repeatsToDraw", XrmoptionSepArg, NULL },
1751 { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL },
1752 { "-userName", "userName", XrmoptionSepArg, NULL },
1753 { "-autoKibitz", "autoKibitz", XrmoptionNoArg, "True" },
1754 { "-firstTimeOdds", "firstTimeOdds", XrmoptionSepArg, NULL },
1755 { "-secondTimeOdds", "secondTimeOdds", XrmoptionSepArg, NULL },
1756 { "-timeOddsMode", "timeOddsMode", XrmoptionSepArg, NULL },
1757 { "-firstAccumulateTC", "firstAccumulateTC", XrmoptionSepArg, NULL },
1758 { "-secondAccumulateTC", "secondAccumulateTC", XrmoptionSepArg, NULL },
1759 { "-firstNPS", "firstNPS", XrmoptionSepArg, NULL },
1760 { "-secondNPS", "secondNPS", XrmoptionSepArg, NULL },
1761 { "-serverMoves", "serverMoves", XrmoptionSepArg, NULL },
1762 { "-serverPause", "serverPause", XrmoptionSepArg, NULL },
1763 { "-suppressLoadMoves", "suppressLoadMoves", XrmoptionSepArg, NULL },
1764 { "-egtFormats", "egtFormats", XrmoptionSepArg, NULL },
1765 { "-userName", "userName", XrmoptionSepArg, NULL },
1766 { "-smpCores", "smpCores", XrmoptionSepArg, NULL },
1767 { "-sameColorGames", "sameColorGames", XrmoptionSepArg, NULL },
1768 { "-rewindIndex", "rewindIndex", XrmoptionSepArg, NULL },
1769 { "-niceEngines", "niceEngines", XrmoptionSepArg, NULL },
1770 { "-delayBeforeQuit", "delayBeforeQuit", XrmoptionSepArg, NULL },
1771 { "-delayAfterQuit", "delayAfterQuit", XrmoptionSepArg, NULL },
1772 { "-nameOfDebugFile", "nameOfDebugFile", XrmoptionSepArg, NULL },
1773 { "-debugFile", "nameOfDebugFile", XrmoptionSepArg, NULL },
1774 { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL },
1775 { "-noGUI", "noGUI", XrmoptionNoArg, "True" },
1776 { "-firstOptions", "firstOptions", XrmoptionSepArg, NULL },
1777 { "-secondOptions", "secondOptions", XrmoptionSepArg, NULL },
1778 { "-firstNeedsNoncompliantFEN", "firstNeedsNoncompliantFEN", XrmoptionSepArg, NULL },
1779 { "-secondNeedsNoncompliantFEN", "secondNeedsNoncompliantFEN", XrmoptionSepArg, NULL },
1780 { "-keepAlive", "keepAlive", XrmoptionSepArg, NULL },
1781 { "-forceIllegalMoves", "forceIllegalMoves", XrmoptionNoArg, "True" },
1782 { "-keepLineBreaksICS", "keepLineBreaksICS", XrmoptionSepArg, NULL },
1786 XtActionsRec boardActions[] = {
1787 { "DrawPosition", DrawPositionProc },
1788 { "HandleUserMove", HandleUserMove },
1789 { "AnimateUserMove", AnimateUserMove },
1790 { "FileNameAction", FileNameAction },
1791 { "AskQuestionProc", AskQuestionProc },
1792 { "AskQuestionReplyAction", AskQuestionReplyAction },
1793 { "PieceMenuPopup", PieceMenuPopup },
1794 { "WhiteClock", WhiteClock },
1795 { "BlackClock", BlackClock },
1796 { "Iconify", Iconify },
1797 { "ResetProc", ResetProc },
1798 { "LoadGameProc", LoadGameProc },
1799 { "LoadNextGameProc", LoadNextGameProc },
1800 { "LoadPrevGameProc", LoadPrevGameProc },
1801 { "LoadSelectedProc", LoadSelectedProc },
1802 { "ReloadGameProc", ReloadGameProc },
1803 { "LoadPositionProc", LoadPositionProc },
1804 { "LoadNextPositionProc", LoadNextPositionProc },
1805 { "LoadPrevPositionProc", LoadPrevPositionProc },
1806 { "ReloadPositionProc", ReloadPositionProc },
1807 { "CopyPositionProc", CopyPositionProc },
1808 { "PastePositionProc", PastePositionProc },
1809 { "CopyGameProc", CopyGameProc },
1810 { "PasteGameProc", PasteGameProc },
1811 { "SaveGameProc", SaveGameProc },
1812 { "SavePositionProc", SavePositionProc },
1813 { "MailMoveProc", MailMoveProc },
1814 { "ReloadCmailMsgProc", ReloadCmailMsgProc },
1815 { "QuitProc", QuitProc },
1816 { "MachineWhiteProc", MachineWhiteProc },
1817 { "MachineBlackProc", MachineBlackProc },
1818 { "AnalysisModeProc", AnalyzeModeProc },
1819 { "AnalyzeFileProc", AnalyzeFileProc },
1820 { "TwoMachinesProc", TwoMachinesProc },
1821 { "IcsClientProc", IcsClientProc },
1822 { "EditGameProc", EditGameProc },
1823 { "EditPositionProc", EditPositionProc },
1824 { "TrainingProc", EditPositionProc },
1825 { "EngineOutputProc", EngineOutputProc}, // [HGM] Winboard_x engine-output window
1826 { "ShowGameListProc", ShowGameListProc },
1827 { "ShowMoveListProc", HistoryShowProc},
1828 { "EditTagsProc", EditCommentProc },
1829 { "EditCommentProc", EditCommentProc },
1830 { "IcsAlarmProc", IcsAlarmProc },
1831 { "IcsInputBoxProc", IcsInputBoxProc },
1832 { "PauseProc", PauseProc },
1833 { "AcceptProc", AcceptProc },
1834 { "DeclineProc", DeclineProc },
1835 { "RematchProc", RematchProc },
1836 { "CallFlagProc", CallFlagProc },
1837 { "DrawProc", DrawProc },
1838 { "AdjournProc", AdjournProc },
1839 { "AbortProc", AbortProc },
1840 { "ResignProc", ResignProc },
1841 { "AdjuWhiteProc", AdjuWhiteProc },
1842 { "AdjuBlackProc", AdjuBlackProc },
1843 { "AdjuDrawProc", AdjuDrawProc },
1844 { "EnterKeyProc", EnterKeyProc },
1845 { "StopObservingProc", StopObservingProc },
1846 { "StopExaminingProc", StopExaminingProc },
1847 { "BackwardProc", BackwardProc },
1848 { "ForwardProc", ForwardProc },
1849 { "ToStartProc", ToStartProc },
1850 { "ToEndProc", ToEndProc },
1851 { "RevertProc", RevertProc },
1852 { "TruncateGameProc", TruncateGameProc },
1853 { "MoveNowProc", MoveNowProc },
1854 { "RetractMoveProc", RetractMoveProc },
1855 { "AlwaysQueenProc", AlwaysQueenProc },
1856 { "AnimateDraggingProc", AnimateDraggingProc },
1857 { "AnimateMovingProc", AnimateMovingProc },
1858 { "AutoflagProc", AutoflagProc },
1859 { "AutoflipProc", AutoflipProc },
1860 { "AutobsProc", AutobsProc },
1861 { "AutoraiseProc", AutoraiseProc },
1862 { "AutosaveProc", AutosaveProc },
1863 { "BlindfoldProc", BlindfoldProc },
1864 { "FlashMovesProc", FlashMovesProc },
1865 { "FlipViewProc", FlipViewProc },
1866 { "GetMoveListProc", GetMoveListProc },
1868 { "HighlightDraggingProc", HighlightDraggingProc },
1870 { "HighlightLastMoveProc", HighlightLastMoveProc },
1871 { "IcsAlarmProc", IcsAlarmProc },
1872 { "MoveSoundProc", MoveSoundProc },
1873 { "OldSaveStyleProc", OldSaveStyleProc },
1874 { "PeriodicUpdatesProc", PeriodicUpdatesProc },
1875 { "PonderNextMoveProc", PonderNextMoveProc },
1876 { "PopupExitMessageProc", PopupExitMessageProc },
1877 { "PopupMoveErrorsProc", PopupMoveErrorsProc },
1878 { "PremoveProc", PremoveProc },
1879 { "QuietPlayProc", QuietPlayProc },
1880 { "ShowCoordsProc", ShowCoordsProc },
1881 { "ShowThinkingProc", ShowThinkingProc },
1882 { "HideThinkingProc", HideThinkingProc },
1883 { "TestLegalityProc", TestLegalityProc },
1884 { "InfoProc", InfoProc },
1885 { "ManProc", ManProc },
1886 { "HintProc", HintProc },
1887 { "BookProc", BookProc },
1888 { "AboutGameProc", AboutGameProc },
1889 { "AboutProc", AboutProc },
1890 { "DebugProc", DebugProc },
1891 { "NothingProc", NothingProc },
1892 { "CommentPopDown", (XtActionProc) CommentPopDown },
1893 { "EditCommentPopDown", (XtActionProc) EditCommentPopDown },
1894 { "TagsPopDown", (XtActionProc) TagsPopDown },
1895 { "ErrorPopDown", (XtActionProc) ErrorPopDown },
1896 { "ICSInputBoxPopDown", (XtActionProc) ICSInputBoxPopDown },
1897 { "FileNamePopDown", (XtActionProc) FileNamePopDown },
1898 { "AskQuestionPopDown", (XtActionProc) AskQuestionPopDown },
1899 { "GameListPopDown", (XtActionProc) GameListPopDown },
1900 { "PromotionPopDown", (XtActionProc) PromotionPopDown },
1901 { "HistoryPopDown", (XtActionProc) HistoryPopDown },
1902 { "EngineOutputPopDown", (XtActionProc) EngineOutputPopDown },
1903 { "ShufflePopDown", (XtActionProc) ShufflePopDown },
1904 { "EnginePopDown", (XtActionProc) EnginePopDown },
1905 { "UciPopDown", (XtActionProc) UciPopDown },
1906 { "TimeControlPopDown", (XtActionProc) TimeControlPopDown },
1907 { "NewVariantPopDown", (XtActionProc) NewVariantPopDown },
1908 { "SettingsPopDown", (XtActionProc) SettingsPopDown },
1911 char globalTranslations[] =
1912 ":<Key>R: ResignProc() \n \
1913 :<Key>r: ResetProc() \n \
1914 :<Key>g: LoadGameProc() \n \
1915 :<Key>N: LoadNextGameProc() \n \
1916 :<Key>P: LoadPrevGameProc() \n \
1917 :<Key>Q: QuitProc() \n \
1918 :<Key>F: ToEndProc() \n \
1919 :<Key>f: ForwardProc() \n \
1920 :<Key>B: ToStartProc() \n \
1921 :<Key>b: BackwardProc() \n \
1922 :<Key>p: PauseProc() \n \
1923 :<Key>d: DrawProc() \n \
1924 :<Key>t: CallFlagProc() \n \
1925 :<Key>i: Iconify() \n \
1926 :<Key>c: Iconify() \n \
1927 :<Key>v: FlipViewProc() \n \
1928 <KeyDown>Control_L: BackwardProc() \n \
1929 <KeyUp>Control_L: ForwardProc() \n \
1930 <KeyDown>Control_R: BackwardProc() \n \
1931 <KeyUp>Control_R: ForwardProc() \n \
1932 Shift<Key>1: AskQuestionProc(\"Direct command\",\
1933 \"Send to chess program:\",,1) \n \
1934 Shift<Key>2: AskQuestionProc(\"Direct command\",\
1935 \"Send to second chess program:\",,2) \n";
1937 char boardTranslations[] =
1938 "<Btn1Down>: HandleUserMove() \n \
1939 <Btn1Up>: HandleUserMove() \n \
1940 <Btn1Motion>: AnimateUserMove() \n \
1941 Shift<Btn2Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD)\
1942 PieceMenuPopup(menuB) \n \
1943 Any<Btn2Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD) \
1944 PieceMenuPopup(menuW) \n \
1945 Shift<Btn3Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD)\
1946 PieceMenuPopup(menuW) \n \
1947 Any<Btn3Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD) \
1948 PieceMenuPopup(menuB) \n";
1950 char whiteTranslations[] = "<BtnDown>: WhiteClock()\n";
1951 char blackTranslations[] = "<BtnDown>: BlackClock()\n";
1953 char ICSInputTranslations[] =
1954 "<Key>Return: EnterKeyProc() \n";
1956 String xboardResources[] = {
1957 "*fileName*value.translations: #override\\n <Key>Return: FileNameAction()",
1958 "*question*value.translations: #override\\n <Key>Return: AskQuestionReplyAction()",
1959 "*errorpopup*translations: #override\\n <Key>Return: ErrorPopDown()",
1964 /* Max possible square size */
1965 #define MAXSQSIZE 256
1967 static int xpm_avail[MAXSQSIZE];
1969 #ifdef HAVE_DIR_STRUCT
1971 /* Extract piece size from filename */
1973 xpm_getsize(name, len, ext)
1984 if ((p=strchr(name, '.')) == NULL ||
1985 StrCaseCmp(p+1, ext) != 0)
1991 while (*p && isdigit(*p))
1998 /* Setup xpm_avail */
2000 xpm_getavail(dirname, ext)
2008 for (i=0; i<MAXSQSIZE; ++i)
2011 if (appData.debugMode)
2012 fprintf(stderr, "XPM dir:%s:ext:%s:\n", dirname, ext);
2014 dir = opendir(dirname);
2017 fprintf(stderr, _("%s: Can't access XPM directory %s\n"),
2018 programName, dirname);
2022 while ((ent=readdir(dir)) != NULL) {
2023 i = xpm_getsize(ent->d_name, NAMLEN(ent), ext);
2024 if (i > 0 && i < MAXSQSIZE)
2034 xpm_print_avail(fp, ext)
2040 fprintf(fp, _("Available `%s' sizes:\n"), ext);
2041 for (i=1; i<MAXSQSIZE; ++i) {
2047 /* Return XPM piecesize closest to size */
2049 xpm_closest_to(dirname, size, ext)
2055 int sm_diff = MAXSQSIZE;
2059 xpm_getavail(dirname, ext);
2061 if (appData.debugMode)
2062 xpm_print_avail(stderr, ext);
2064 for (i=1; i<MAXSQSIZE; ++i) {
2067 diff = (diff<0) ? -diff : diff;
2068 if (diff < sm_diff) {
2076 fprintf(stderr, _("Error: No `%s' files!\n"), ext);
2082 #else /* !HAVE_DIR_STRUCT */
2083 /* If we are on a system without a DIR struct, we can't
2084 read the directory, so we can't collect a list of
2085 filenames, etc., so we can't do any size-fitting. */
2087 xpm_closest_to(dirname, size, ext)
2092 fprintf(stderr, _("\
2093 Warning: No DIR structure found on this system --\n\
2094 Unable to autosize for XPM/XIM pieces.\n\
2095 Please report this error to frankm@hiwaay.net.\n\
2096 Include system type & operating system in message.\n"));
2099 #endif /* HAVE_DIR_STRUCT */
2101 static char *cnames[9] = { "black", "red", "green", "yellow", "blue",
2102 "magenta", "cyan", "white" };
2106 TextColors textColors[(int)NColorClasses];
2108 /* String is: "fg, bg, attr". Which is 0, 1, 2 */
2110 parse_color(str, which)
2114 char *p, buf[100], *d;
2117 if (strlen(str) > 99) /* watch bounds on buf */
2122 for (i=0; i<which; ++i) {
2129 /* Could be looking at something like:
2131 .. in which case we want to stop on a comma also */
2132 while (*p && *p != ',' && !isalpha(*p) && !isdigit(*p))
2136 return -1; /* Use default for empty field */
2139 if (which == 2 || isdigit(*p))
2142 while (*p && isalpha(*p))
2147 for (i=0; i<8; ++i) {
2148 if (!StrCaseCmp(buf, cnames[i]))
2149 return which? (i+40) : (i+30);
2151 if (!StrCaseCmp(buf, "default")) return -1;
2153 fprintf(stderr, _("%s: unrecognized color %s\n"), programName, buf);
2158 parse_cpair(cc, str)
2162 if ((textColors[(int)cc].fg=parse_color(str, 0)) == -2) {
2163 fprintf(stderr, _("%s: can't parse foreground color in `%s'\n"),
2168 /* bg and attr are optional */
2169 textColors[(int)cc].bg = parse_color(str, 1);
2170 if ((textColors[(int)cc].attr = parse_color(str, 2)) < 0) {
2171 textColors[(int)cc].attr = 0;
2177 /* Arrange to catch delete-window events */
2178 Atom wm_delete_window;
2180 CatchDeleteWindow(Widget w, String procname)
2183 XSetWMProtocols(xDisplay, XtWindow(w), &wm_delete_window, 1);
2184 snprintf(buf, sizeof(buf), "<Message>WM_PROTOCOLS: %s() \n", procname);
2185 XtAugmentTranslations(w, XtParseTranslationTable(buf));
2192 XtSetArg(args[0], XtNiconic, False);
2193 XtSetValues(shellWidget, args, 1);
2195 XtPopup(shellWidget, XtGrabNone); /* Raise if lowered */
2199 // eventually, all layout determining code should go into a subroutine, but until then IDSIZE remains undefined
2201 #define BoardSize int
2202 void InitDrawingSizes(BoardSize boardSize, int flags)
2203 { // [HGM] resize is functional now, but for board format changes only (nr of ranks, files)
2204 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
2206 XtGeometryResult gres;
2209 if(!formWidget) return;
2212 * Enable shell resizing.
2214 shellArgs[0].value = (XtArgVal) &w;
2215 shellArgs[1].value = (XtArgVal) &h;
2216 XtGetValues(shellWidget, shellArgs, 2);
2218 shellArgs[4].value = 2*w; shellArgs[2].value = 10;
2219 shellArgs[5].value = 2*h; shellArgs[3].value = 10;
2220 XtSetValues(shellWidget, &shellArgs[2], 4);
2222 XtSetArg(args[0], XtNdefaultDistance, &sep);
2223 XtGetValues(formWidget, args, 1);
2225 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2226 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2229 XtSetArg(args[0], XtNwidth, boardWidth);
2230 XtSetArg(args[1], XtNheight, boardHeight);
2231 XtSetValues(boardWidget, args, 2);
2233 timerWidth = (boardWidth - sep) / 2;
2234 XtSetArg(args[0], XtNwidth, timerWidth);
2235 XtSetValues(whiteTimerWidget, args, 1);
2236 XtSetValues(blackTimerWidget, args, 1);
2238 XawFormDoLayout(formWidget, False);
2240 if (appData.titleInWindow) {
2242 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2243 XtSetArg(args[i], XtNheight, &h); i++;
2244 XtGetValues(titleWidget, args, i);
2246 w = boardWidth - 2*bor;
2248 XtSetArg(args[0], XtNwidth, &w);
2249 XtGetValues(menuBarWidget, args, 1);
2250 w = boardWidth - w - sep - 2*bor - 2; // WIDTH_FUDGE
2253 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
2254 if (gres != XtGeometryYes && appData.debugMode) {
2256 _("%s: titleWidget geometry error %d %d %d %d %d\n"),
2257 programName, gres, w, h, wr, hr);
2261 XawFormDoLayout(formWidget, True);
2264 * Inhibit shell resizing.
2266 shellArgs[0].value = w = (XtArgVal) boardWidth + marginW;
2267 shellArgs[1].value = h = (XtArgVal) boardHeight + marginH;
2268 shellArgs[4].value = shellArgs[2].value = w;
2269 shellArgs[5].value = shellArgs[3].value = h;
2270 XtSetValues(shellWidget, &shellArgs[0], 6);
2272 // [HGM] pieces: tailor piece bitmaps to needs of specific variant
2275 for(i=0; i<4; i++) {
2277 for(p=0; p<=(int)WhiteKing; p++)
2278 xpmPieceBitmap[i][p] = xpmPieceBitmap2[i][p]; // defaults
2279 if(gameInfo.variant == VariantShogi) {
2280 xpmPieceBitmap[i][(int)WhiteCannon] = xpmPieceBitmap2[i][(int)WhiteKing+1];
2281 xpmPieceBitmap[i][(int)WhiteNightrider] = xpmPieceBitmap2[i][(int)WhiteKing+2];
2282 xpmPieceBitmap[i][(int)WhiteSilver] = xpmPieceBitmap2[i][(int)WhiteKing+3];
2283 xpmPieceBitmap[i][(int)WhiteGrasshopper] = xpmPieceBitmap2[i][(int)WhiteKing+4];
2284 xpmPieceBitmap[i][(int)WhiteQueen] = xpmPieceBitmap2[i][(int)WhiteLance];
2287 if(gameInfo.variant == VariantGothic) {
2288 xpmPieceBitmap[i][(int)WhiteMarshall] = xpmPieceBitmap2[i][(int)WhiteSilver];
2292 // [HGM] why are thee ximMasks used at all? the ximPieceBitmaps seem to be never used!
2293 for(p=0; p<=(int)WhiteKing; p++)
2294 ximMaskPm[p] = ximMaskPm2[p]; // defaults
2295 if(gameInfo.variant == VariantShogi) {
2296 ximMaskPm[(int)WhiteCannon] = ximMaskPm2[(int)WhiteKing+1];
2297 ximMaskPm[(int)WhiteNightrider] = ximMaskPm2[(int)WhiteKing+2];
2298 ximMaskPm[(int)WhiteSilver] = ximMaskPm2[(int)WhiteKing+3];
2299 ximMaskPm[(int)WhiteGrasshopper] = ximMaskPm2[(int)WhiteKing+4];
2300 ximMaskPm[(int)WhiteQueen] = ximMaskPm2[(int)WhiteLance];
2303 if(gameInfo.variant == VariantGothic) {
2304 ximMaskPm[(int)WhiteMarshall] = ximMaskPm2[(int)WhiteSilver];
2310 for(i=0; i<2; i++) {
2312 for(p=0; p<=(int)WhiteKing; p++)
2313 pieceBitmap[i][p] = pieceBitmap2[i][p]; // defaults
2314 if(gameInfo.variant == VariantShogi) {
2315 pieceBitmap[i][(int)WhiteCannon] = pieceBitmap2[i][(int)WhiteKing+1];
2316 pieceBitmap[i][(int)WhiteNightrider] = pieceBitmap2[i][(int)WhiteKing+2];
2317 pieceBitmap[i][(int)WhiteSilver] = pieceBitmap2[i][(int)WhiteKing+3];
2318 pieceBitmap[i][(int)WhiteGrasshopper] = pieceBitmap2[i][(int)WhiteKing+4];
2319 pieceBitmap[i][(int)WhiteQueen] = pieceBitmap2[i][(int)WhiteLance];
2322 if(gameInfo.variant == VariantGothic) {
2323 pieceBitmap[i][(int)WhiteMarshall] = pieceBitmap2[i][(int)WhiteSilver];
2334 void EscapeExpand(char *p, char *q)
2335 { // [HGM] initstring: routine to shape up string arguments
2336 while(*p++ = *q++) if(p[-1] == '\\')
2338 case 'n': p[-1] = '\n'; break;
2339 case 'r': p[-1] = '\r'; break;
2340 case 't': p[-1] = '\t'; break;
2341 case '\\': p[-1] = '\\'; break;
2342 case 0: *p = 0; return;
2343 default: p[-1] = q[-1]; break;
2352 int i, j, clockFontPxlSize, coordFontPxlSize, fontPxlSize;
2353 XSetWindowAttributes window_attributes;
2355 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
2356 XrmValue vFrom, vTo;
2357 XtGeometryResult gres;
2360 int forceMono = False;
2363 // [HGM] before anything else, expand any indirection files amongst options
2364 char *argvCopy[1000]; // 1000 seems enough
2365 char newArgs[10000]; // holds actual characters
2368 srandom(time(0)); // [HGM] book: make random truly random
2371 for(i=0; i<argc; i++) {
2372 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2373 //fprintf(stderr, "arg %s\n", argv[i]);
2374 if(argv[i][0] != '@') argvCopy[j++] = argv[i]; else {
2376 FILE *f = fopen(argv[i]+1, "rb");
2377 if(f == NULL) { fprintf(stderr, _("ignore %s\n"), argv[i]); continue; } // do not expand non-existing
2378 argvCopy[j++] = newArgs + k; // get ready for first argument from file
2379 while((c = fgetc(f)) != EOF) { // each line of file inserts 1 argument in the list
2381 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2382 newArgs[k++] = 0; // terminate current arg
2383 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2384 argvCopy[j++] = newArgs + k; // get ready for next
2386 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2400 setbuf(stdout, NULL);
2401 setbuf(stderr, NULL);
2404 programName = strrchr(argv[0], '/');
2405 if (programName == NULL)
2406 programName = argv[0];
2411 XtSetLanguageProc(NULL, NULL, NULL);
2412 bindtextdomain(PACKAGE, LOCALEDIR);
2413 textdomain(PACKAGE);
2417 XtAppInitialize(&appContext, "XBoard", shellOptions,
2418 XtNumber(shellOptions),
2419 &argc, argv, xboardResources, NULL, 0);
2421 { /* left over command line arguments, print out help and exit.
2422 * Use two columns to print help
2424 fprintf(stderr, _("%s: unrecognized argument %s\n"),
2425 programName, argv[1]);
2427 fprintf(stderr, "Recognized options:\n");
2428 for(i = 0; i < XtNumber(shellOptions); i++)
2430 /* print first column */
2431 j = fprintf(stderr, " %s%s", shellOptions[i].option,
2432 (shellOptions[i].argKind == XrmoptionSepArg
2434 /* print second column and end line */
2435 if (++i < XtNumber(shellOptions))
2437 fprintf(stderr, "%*c%s%s\n", 40 - j, ' ',
2438 shellOptions[i].option,
2439 (shellOptions[i].argKind == XrmoptionSepArg
2444 fprintf(stderr, "\n");
2451 if (p == NULL) p = "/tmp";
2452 i = strlen(p) + strlen("/.xboardXXXXXx.pgn") + 1;
2453 gameCopyFilename = (char*) malloc(i);
2454 gamePasteFilename = (char*) malloc(i);
2455 snprintf(gameCopyFilename,i, "%s/.xboard%05uc.pgn", p, getpid());
2456 snprintf(gamePasteFilename,i, "%s/.xboard%05up.pgn", p, getpid());
2458 XtGetApplicationResources(shellWidget, (XtPointer) &appData,
2459 clientResources, XtNumber(clientResources),
2462 { // [HGM] initstring: kludge to fix bad bug. expand '\n' characters in init string and computer string.
2463 static char buf[MSG_SIZ];
2464 EscapeExpand(buf, appData.initString);
2465 appData.initString = strdup(buf);
2466 EscapeExpand(buf, appData.secondInitString);
2467 appData.secondInitString = strdup(buf);
2468 EscapeExpand(buf, appData.firstComputerString);
2469 appData.firstComputerString = strdup(buf);
2470 EscapeExpand(buf, appData.secondComputerString);
2471 appData.secondComputerString = strdup(buf);
2474 if ((chessDir = (char *) getenv("CHESSDIR")) == NULL) {
2477 if (chdir(chessDir) != 0) {
2478 fprintf(stderr, _("%s: can't cd to CHESSDIR: "), programName);
2484 if (appData.debugMode && appData.nameOfDebugFile && strcmp(appData.nameOfDebugFile, "stderr")) {
2485 /* [DM] debug info to file [HGM] make the filename a command-line option, and allow it to remain stderr */
2486 if ((debugFP = fopen(appData.nameOfDebugFile, "w")) == NULL) {
2487 printf(_("Failed to open file '%s'\n"), appData.nameOfDebugFile);
2490 setbuf(debugFP, NULL);
2493 /* [HGM,HR] make sure board size is acceptable */
2494 if(appData.NrFiles > BOARD_SIZE ||
2495 appData.NrRanks > BOARD_SIZE )
2496 DisplayFatalError(_("Recompile with BOARD_SIZE > 12, to support this size"), 0, 2);
2499 /* This feature does not work; animation needs a rewrite */
2500 appData.highlightDragging = FALSE;
2504 xDisplay = XtDisplay(shellWidget);
2505 xScreen = DefaultScreen(xDisplay);
2506 wm_delete_window = XInternAtom(xDisplay, "WM_DELETE_WINDOW", True);
2508 gameInfo.variant = StringToVariant(appData.variant);
2509 InitPosition(FALSE);
2512 InitDrawingSizes(-1, 0); // [HGM] initsize: make this into a subroutine
2514 if (isdigit(appData.boardSize[0])) {
2515 i = sscanf(appData.boardSize, "%d,%d,%d,%d,%d,%d,%d", &squareSize,
2516 &lineGap, &clockFontPxlSize, &coordFontPxlSize,
2517 &fontPxlSize, &smallLayout, &tinyLayout);
2519 fprintf(stderr, _("%s: bad boardSize syntax %s\n"),
2520 programName, appData.boardSize);
2524 /* Find some defaults; use the nearest known size */
2525 SizeDefaults *szd, *nearest;
2526 int distance = 99999;
2527 nearest = szd = sizeDefaults;
2528 while (szd->name != NULL) {
2529 if (abs(szd->squareSize - squareSize) < distance) {
2531 distance = abs(szd->squareSize - squareSize);
2532 if (distance == 0) break;
2536 if (i < 2) lineGap = nearest->lineGap;
2537 if (i < 3) clockFontPxlSize = nearest->clockFontPxlSize;
2538 if (i < 4) coordFontPxlSize = nearest->coordFontPxlSize;
2539 if (i < 5) fontPxlSize = nearest->fontPxlSize;
2540 if (i < 6) smallLayout = nearest->smallLayout;
2541 if (i < 7) tinyLayout = nearest->tinyLayout;
2544 SizeDefaults *szd = sizeDefaults;
2545 if (*appData.boardSize == NULLCHAR) {
2546 while (DisplayWidth(xDisplay, xScreen) < szd->minScreenSize ||
2547 DisplayHeight(xDisplay, xScreen) < szd->minScreenSize) {
2550 if (szd->name == NULL) szd--;
2552 while (szd->name != NULL &&
2553 StrCaseCmp(szd->name, appData.boardSize) != 0) szd++;
2554 if (szd->name == NULL) {
2555 fprintf(stderr, _("%s: unrecognized boardSize name %s\n"),
2556 programName, appData.boardSize);
2560 squareSize = szd->squareSize;
2561 lineGap = szd->lineGap;
2562 clockFontPxlSize = szd->clockFontPxlSize;
2563 coordFontPxlSize = szd->coordFontPxlSize;
2564 fontPxlSize = szd->fontPxlSize;
2565 smallLayout = szd->smallLayout;
2566 tinyLayout = szd->tinyLayout;
2569 /* Now, using squareSize as a hint, find a good XPM/XIM set size */
2570 if (strlen(appData.pixmapDirectory) > 0) {
2571 p = ExpandPathName(appData.pixmapDirectory);
2573 fprintf(stderr, _("Error expanding path name \"%s\"\n"),
2574 appData.pixmapDirectory);
2577 if (appData.debugMode) {
2578 fprintf(stderr, _("\
2579 XBoard square size (hint): %d\n\
2580 %s fulldir:%s:\n"), squareSize, IMAGE_EXT, p);
2582 squareSize = xpm_closest_to(p, squareSize, IMAGE_EXT);
2583 if (appData.debugMode) {
2584 fprintf(stderr, _("Closest %s size: %d\n"), IMAGE_EXT, squareSize);
2588 /* [HR] height treated separately (hacked) */
2589 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2590 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2591 if (appData.showJail == 1) {
2592 /* Jail on top and bottom */
2593 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2594 XtSetArg(boardArgs[2], XtNheight,
2595 boardHeight + 2*(lineGap + squareSize));
2596 } else if (appData.showJail == 2) {
2598 XtSetArg(boardArgs[1], XtNwidth,
2599 boardWidth + 2*(lineGap + squareSize));
2600 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2603 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2604 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2608 * Determine what fonts to use.
2610 appData.clockFont = FindFont(appData.clockFont, clockFontPxlSize);
2611 clockFontID = XLoadFont(xDisplay, appData.clockFont);
2612 clockFontStruct = XQueryFont(xDisplay, clockFontID);
2613 appData.coordFont = FindFont(appData.coordFont, coordFontPxlSize);
2614 coordFontID = XLoadFont(xDisplay, appData.coordFont);
2615 coordFontStruct = XQueryFont(xDisplay, coordFontID);
2616 appData.font = FindFont(appData.font, fontPxlSize);
2617 countFontID = XLoadFont(xDisplay, appData.coordFont); // [HGM] holdings
2618 countFontStruct = XQueryFont(xDisplay, countFontID);
2619 // appData.font = FindFont(appData.font, fontPxlSize);
2621 xdb = XtDatabase(xDisplay);
2622 XrmPutStringResource(&xdb, "*font", appData.font);
2625 * Detect if there are not enough colors available and adapt.
2627 if (DefaultDepth(xDisplay, xScreen) <= 2) {
2628 appData.monoMode = True;
2631 if (!appData.monoMode) {
2632 vFrom.addr = (caddr_t) appData.lightSquareColor;
2633 vFrom.size = strlen(appData.lightSquareColor);
2634 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2635 if (vTo.addr == NULL) {
2636 appData.monoMode = True;
2639 lightSquareColor = *(Pixel *) vTo.addr;
2642 if (!appData.monoMode) {
2643 vFrom.addr = (caddr_t) appData.darkSquareColor;
2644 vFrom.size = strlen(appData.darkSquareColor);
2645 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2646 if (vTo.addr == NULL) {
2647 appData.monoMode = True;
2650 darkSquareColor = *(Pixel *) vTo.addr;
2653 if (!appData.monoMode) {
2654 vFrom.addr = (caddr_t) appData.whitePieceColor;
2655 vFrom.size = strlen(appData.whitePieceColor);
2656 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2657 if (vTo.addr == NULL) {
2658 appData.monoMode = True;
2661 whitePieceColor = *(Pixel *) vTo.addr;
2664 if (!appData.monoMode) {
2665 vFrom.addr = (caddr_t) appData.blackPieceColor;
2666 vFrom.size = strlen(appData.blackPieceColor);
2667 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2668 if (vTo.addr == NULL) {
2669 appData.monoMode = True;
2672 blackPieceColor = *(Pixel *) vTo.addr;
2676 if (!appData.monoMode) {
2677 vFrom.addr = (caddr_t) appData.highlightSquareColor;
2678 vFrom.size = strlen(appData.highlightSquareColor);
2679 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2680 if (vTo.addr == NULL) {
2681 appData.monoMode = True;
2684 highlightSquareColor = *(Pixel *) vTo.addr;
2688 if (!appData.monoMode) {
2689 vFrom.addr = (caddr_t) appData.premoveHighlightColor;
2690 vFrom.size = strlen(appData.premoveHighlightColor);
2691 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2692 if (vTo.addr == NULL) {
2693 appData.monoMode = True;
2696 premoveHighlightColor = *(Pixel *) vTo.addr;
2701 fprintf(stderr, _("%s: too few colors available; trying monochrome mode\n"),
2704 if (appData.bitmapDirectory == NULL ||
2705 appData.bitmapDirectory[0] == NULLCHAR)
2706 appData.bitmapDirectory = DEF_BITMAP_DIR;
2709 if (appData.lowTimeWarning && !appData.monoMode) {
2710 vFrom.addr = (caddr_t) appData.lowTimeWarningColor;
2711 vFrom.size = strlen(appData.lowTimeWarningColor);
2712 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2713 if (vTo.addr == NULL)
2714 appData.monoMode = True;
2716 lowTimeWarningColor = *(Pixel *) vTo.addr;
2719 if (appData.monoMode && appData.debugMode) {
2720 fprintf(stderr, _("white pixel = 0x%lx, black pixel = 0x%lx\n"),
2721 (unsigned long) XWhitePixel(xDisplay, xScreen),
2722 (unsigned long) XBlackPixel(xDisplay, xScreen));
2725 if (parse_cpair(ColorShout, appData.colorShout) < 0 ||
2726 parse_cpair(ColorSShout, appData.colorSShout) < 0 ||
2727 parse_cpair(ColorChannel1, appData.colorChannel1) < 0 ||
2728 parse_cpair(ColorChannel, appData.colorChannel) < 0 ||
2729 parse_cpair(ColorKibitz, appData.colorKibitz) < 0 ||
2730 parse_cpair(ColorTell, appData.colorTell) < 0 ||
2731 parse_cpair(ColorChallenge, appData.colorChallenge) < 0 ||
2732 parse_cpair(ColorRequest, appData.colorRequest) < 0 ||
2733 parse_cpair(ColorSeek, appData.colorSeek) < 0 ||
2734 parse_cpair(ColorNormal, appData.colorNormal) < 0)
2736 if (appData.colorize) {
2738 _("%s: can't parse color names; disabling colorization\n"),
2741 appData.colorize = FALSE;
2743 textColors[ColorNone].fg = textColors[ColorNone].bg = -1;
2744 textColors[ColorNone].attr = 0;
2746 XtAppAddActions(appContext, boardActions, XtNumber(boardActions));
2752 layoutName = "tinyLayout";
2753 } else if (smallLayout) {
2754 layoutName = "smallLayout";
2756 layoutName = "normalLayout";
2758 /* Outer layoutWidget is there only to provide a name for use in
2759 resources that depend on the layout style */
2761 XtCreateManagedWidget(layoutName, formWidgetClass, shellWidget,
2762 layoutArgs, XtNumber(layoutArgs));
2764 XtCreateManagedWidget("form", formWidgetClass, layoutWidget,
2765 formArgs, XtNumber(formArgs));
2766 XtSetArg(args[0], XtNdefaultDistance, &sep);
2767 XtGetValues(formWidget, args, 1);
2770 widgetList[j++] = menuBarWidget = CreateMenuBar(menuBar);
2771 XtSetArg(args[0], XtNtop, XtChainTop);
2772 XtSetArg(args[1], XtNbottom, XtChainTop);
2773 XtSetValues(menuBarWidget, args, 2);
2775 widgetList[j++] = whiteTimerWidget =
2776 XtCreateWidget("whiteTime", labelWidgetClass,
2777 formWidget, timerArgs, XtNumber(timerArgs));
2778 XtSetArg(args[0], XtNfont, clockFontStruct);
2779 XtSetArg(args[1], XtNtop, XtChainTop);
2780 XtSetArg(args[2], XtNbottom, XtChainTop);
2781 XtSetValues(whiteTimerWidget, args, 3);
2783 widgetList[j++] = blackTimerWidget =
2784 XtCreateWidget("blackTime", labelWidgetClass,
2785 formWidget, timerArgs, XtNumber(timerArgs));
2786 XtSetArg(args[0], XtNfont, clockFontStruct);
2787 XtSetArg(args[1], XtNtop, XtChainTop);
2788 XtSetArg(args[2], XtNbottom, XtChainTop);
2789 XtSetValues(blackTimerWidget, args, 3);
2791 if (appData.titleInWindow) {
2792 widgetList[j++] = titleWidget =
2793 XtCreateWidget("title", labelWidgetClass, formWidget,
2794 titleArgs, XtNumber(titleArgs));
2795 XtSetArg(args[0], XtNtop, XtChainTop);
2796 XtSetArg(args[1], XtNbottom, XtChainTop);
2797 XtSetValues(titleWidget, args, 2);
2800 if (appData.showButtonBar) {
2801 widgetList[j++] = buttonBarWidget = CreateButtonBar(buttonBar);
2802 XtSetArg(args[0], XtNleft, XtChainRight); // [HGM] glue to right window edge
2803 XtSetArg(args[1], XtNright, XtChainRight); // for good run-time sizing
2804 XtSetArg(args[2], XtNtop, XtChainTop);
2805 XtSetArg(args[3], XtNbottom, XtChainTop);
2806 XtSetValues(buttonBarWidget, args, 4);
2809 widgetList[j++] = messageWidget =
2810 XtCreateWidget("message", labelWidgetClass, formWidget,
2811 messageArgs, XtNumber(messageArgs));
2812 XtSetArg(args[0], XtNtop, XtChainTop);
2813 XtSetArg(args[1], XtNbottom, XtChainTop);
2814 XtSetValues(messageWidget, args, 2);
2816 widgetList[j++] = boardWidget =
2817 XtCreateWidget("board", widgetClass, formWidget, boardArgs,
2818 XtNumber(boardArgs));
2820 XtManageChildren(widgetList, j);
2822 timerWidth = (boardWidth - sep) / 2;
2823 XtSetArg(args[0], XtNwidth, timerWidth);
2824 XtSetValues(whiteTimerWidget, args, 1);
2825 XtSetValues(blackTimerWidget, args, 1);
2827 XtSetArg(args[0], XtNbackground, &timerBackgroundPixel);
2828 XtSetArg(args[1], XtNforeground, &timerForegroundPixel);
2829 XtGetValues(whiteTimerWidget, args, 2);
2831 if (appData.showButtonBar) {
2832 XtSetArg(args[0], XtNbackground, &buttonBackgroundPixel);
2833 XtSetArg(args[1], XtNforeground, &buttonForegroundPixel);
2834 XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
2838 * formWidget uses these constraints but they are stored
2842 XtSetArg(args[i], XtNfromHoriz, 0); i++;
2843 XtSetValues(menuBarWidget, args, i);
2844 if (appData.titleInWindow) {
2847 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2848 XtSetValues(whiteTimerWidget, args, i);
2850 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2851 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2852 XtSetValues(blackTimerWidget, args, i);
2854 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2855 XtSetArg(args[i], XtNjustify, XtJustifyLeft); i++;
2856 XtSetValues(titleWidget, args, i);
2858 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2859 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2860 XtSetValues(messageWidget, args, i);
2861 if (appData.showButtonBar) {
2863 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2864 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2865 XtSetValues(buttonBarWidget, args, i);
2869 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2870 XtSetValues(whiteTimerWidget, args, i);
2872 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2873 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2874 XtSetValues(blackTimerWidget, args, i);
2876 XtSetArg(args[i], XtNfromHoriz, menuBarWidget); i++;
2877 XtSetValues(titleWidget, args, i);
2879 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2880 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2881 XtSetValues(messageWidget, args, i);
2882 if (appData.showButtonBar) {
2884 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2885 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2886 XtSetValues(buttonBarWidget, args, i);
2891 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2892 XtSetValues(whiteTimerWidget, args, i);
2894 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2895 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2896 XtSetValues(blackTimerWidget, args, i);
2898 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2899 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2900 XtSetValues(messageWidget, args, i);
2901 if (appData.showButtonBar) {
2903 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2904 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2905 XtSetValues(buttonBarWidget, args, i);
2909 XtSetArg(args[0], XtNfromVert, messageWidget);
2910 XtSetArg(args[1], XtNtop, XtChainTop);
2911 XtSetArg(args[2], XtNbottom, XtChainBottom);
2912 XtSetArg(args[3], XtNleft, XtChainLeft);
2913 XtSetArg(args[4], XtNright, XtChainRight);
2914 XtSetValues(boardWidget, args, 5);
2916 XtRealizeWidget(shellWidget);
2919 * Correct the width of the message and title widgets.
2920 * It is not known why some systems need the extra fudge term.
2921 * The value "2" is probably larger than needed.
2923 XawFormDoLayout(formWidget, False);
2925 #define WIDTH_FUDGE 2
2927 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2928 XtSetArg(args[i], XtNheight, &h); i++;
2929 XtGetValues(messageWidget, args, i);
2930 if (appData.showButtonBar) {
2932 XtSetArg(args[i], XtNwidth, &w); i++;
2933 XtGetValues(buttonBarWidget, args, i);
2934 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2936 w = boardWidth - 2*bor + 1; /*!! +1 compensates for kludge below */
2939 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2940 if (gres != XtGeometryYes && appData.debugMode) {
2941 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2942 programName, gres, w, h, wr, hr);
2945 /* !! Horrible hack to work around bug in XFree86 4.0.1 (X11R6.4.3) */
2946 /* The size used for the child widget in layout lags one resize behind
2947 its true size, so we resize a second time, 1 pixel smaller. Yeech! */
2949 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2950 if (gres != XtGeometryYes && appData.debugMode) {
2951 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2952 programName, gres, w, h, wr, hr);
2955 XtSetArg(args[0], XtNleft, XtChainLeft); // [HGM] glue ends for good run-time sizing
2956 XtSetArg(args[1], XtNright, XtChainRight);
2957 XtSetValues(messageWidget, args, 2);
2959 if (appData.titleInWindow) {
2961 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2962 XtSetArg(args[i], XtNheight, &h); i++;
2963 XtGetValues(titleWidget, args, i);
2965 w = boardWidth - 2*bor;
2967 XtSetArg(args[0], XtNwidth, &w);
2968 XtGetValues(menuBarWidget, args, 1);
2969 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2972 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
2973 if (gres != XtGeometryYes && appData.debugMode) {
2975 _("%s: titleWidget geometry error %d %d %d %d %d\n"),
2976 programName, gres, w, h, wr, hr);
2979 XawFormDoLayout(formWidget, True);
2981 xBoardWindow = XtWindow(boardWidget);
2983 // [HGM] it seems the layout code ends here, but perhaps the color stuff is size independent and would
2984 // not need to go into InitDrawingSizes().
2988 * Create X checkmark bitmap and initialize option menu checks.
2990 ReadBitmap(&xMarkPixmap, "checkmark.bm",
2991 checkmark_bits, checkmark_width, checkmark_height);
2992 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
2993 if (appData.alwaysPromoteToQueen) {
2994 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
2997 if (appData.animateDragging) {
2998 XtSetValues(XtNameToWidget(menuBarWidget,
2999 "menuOptions.Animate Dragging"),
3002 if (appData.animate) {
3003 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
3006 if (appData.autoComment) {
3007 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
3010 if (appData.autoCallFlag) {
3011 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
3014 if (appData.autoFlipView) {
3015 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Auto Flip View"),
3018 if (appData.autoObserve) {
3019 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
3022 if (appData.autoRaiseBoard) {
3023 XtSetValues(XtNameToWidget(menuBarWidget,
3024 "menuOptions.Auto Raise Board"), args, 1);
3026 if (appData.autoSaveGames) {
3027 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
3030 if (appData.saveGameFile[0] != NULLCHAR) {
3031 /* Can't turn this off from menu */
3032 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
3034 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
3038 if (appData.blindfold) {
3039 XtSetValues(XtNameToWidget(menuBarWidget,
3040 "menuOptions.Blindfold"), args, 1);
3042 if (appData.flashCount > 0) {
3043 XtSetValues(XtNameToWidget(menuBarWidget,
3044 "menuOptions.Flash Moves"),
3047 if (appData.getMoveList) {
3048 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
3052 if (appData.highlightDragging) {
3053 XtSetValues(XtNameToWidget(menuBarWidget,
3054 "menuOptions.Highlight Dragging"),
3058 if (appData.highlightLastMove) {
3059 XtSetValues(XtNameToWidget(menuBarWidget,
3060 "menuOptions.Highlight Last Move"),
3063 if (appData.icsAlarm) {
3064 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.ICS Alarm"),
3067 if (appData.ringBellAfterMoves) {
3068 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
3071 if (appData.oldSaveStyle) {
3072 XtSetValues(XtNameToWidget(menuBarWidget,
3073 "menuOptions.Old Save Style"), args, 1);
3075 if (appData.periodicUpdates) {
3076 XtSetValues(XtNameToWidget(menuBarWidget,
3077 "menuOptions.Periodic Updates"), args, 1);
3079 if (appData.ponderNextMove) {
3080 XtSetValues(XtNameToWidget(menuBarWidget,
3081 "menuOptions.Ponder Next Move"), args, 1);
3083 if (appData.popupExitMessage) {
3084 XtSetValues(XtNameToWidget(menuBarWidget,
3085 "menuOptions.Popup Exit Message"), args, 1);
3087 if (appData.popupMoveErrors) {
3088 XtSetValues(XtNameToWidget(menuBarWidget,
3089 "menuOptions.Popup Move Errors"), args, 1);
3091 if (appData.premove) {
3092 XtSetValues(XtNameToWidget(menuBarWidget,
3093 "menuOptions.Premove"), args, 1);
3095 if (appData.quietPlay) {
3096 XtSetValues(XtNameToWidget(menuBarWidget,
3097 "menuOptions.Quiet Play"), args, 1);
3099 if (appData.showCoords) {
3100 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
3103 if (appData.hideThinkingFromHuman) {
3104 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
3107 if (appData.testLegality) {
3108 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Test Legality"),
3115 ReadBitmap(&wIconPixmap, "icon_white.bm",
3116 icon_white_bits, icon_white_width, icon_white_height);
3117 ReadBitmap(&bIconPixmap, "icon_black.bm",
3118 icon_black_bits, icon_black_width, icon_black_height);
3119 iconPixmap = wIconPixmap;
3121 XtSetArg(args[i], XtNiconPixmap, iconPixmap); i++;
3122 XtSetValues(shellWidget, args, i);
3125 * Create a cursor for the board widget.
3127 window_attributes.cursor = XCreateFontCursor(xDisplay, XC_hand2);
3128 XChangeWindowAttributes(xDisplay, xBoardWindow,
3129 CWCursor, &window_attributes);
3132 * Inhibit shell resizing.
3134 shellArgs[0].value = (XtArgVal) &w;
3135 shellArgs[1].value = (XtArgVal) &h;
3136 XtGetValues(shellWidget, shellArgs, 2);
3137 shellArgs[4].value = shellArgs[2].value = w;
3138 shellArgs[5].value = shellArgs[3].value = h;
3139 XtSetValues(shellWidget, &shellArgs[2], 4);
3140 marginW = w - boardWidth; // [HGM] needed to set new shellWidget size when we resize board
3141 marginH = h - boardHeight;
3143 CatchDeleteWindow(shellWidget, "QuitProc");
3148 if (appData.bitmapDirectory[0] != NULLCHAR) {
3155 /* Create regular pieces */
3156 if (!useImages) CreatePieces();
3161 if (appData.animate || appData.animateDragging)
3164 XtAugmentTranslations(formWidget,
3165 XtParseTranslationTable(globalTranslations));
3166 XtAugmentTranslations(boardWidget,
3167 XtParseTranslationTable(boardTranslations));
3168 XtAugmentTranslations(whiteTimerWidget,
3169 XtParseTranslationTable(whiteTranslations));
3170 XtAugmentTranslations(blackTimerWidget,
3171 XtParseTranslationTable(blackTranslations));
3173 /* Why is the following needed on some versions of X instead
3174 * of a translation? */
3175 XtAddEventHandler(boardWidget, ExposureMask, False,
3176 (XtEventHandler) EventProc, NULL);
3181 if (errorExitStatus == -1) {
3182 if (appData.icsActive) {
3183 /* We now wait until we see "login:" from the ICS before
3184 sending the logon script (problems with timestamp otherwise) */
3185 /*ICSInitScript();*/
3186 if (appData.icsInputBox) ICSInputBoxPopUp();
3189 signal(SIGINT, IntSigHandler);
3190 signal(SIGTERM, IntSigHandler);
3191 if (*appData.cmailGameName != NULLCHAR) {
3192 signal(SIGUSR1, CmailSigHandler);
3195 gameInfo.boardWidth = 0; // [HGM] pieces: kludge to ensure InitPosition() calls InitDrawingSizes()
3198 XtAppMainLoop(appContext);
3199 if (appData.debugMode) fclose(debugFP); // [DM] debug
3206 if (appData.icsActive && oldICSInteractionTitle != NULL) {
3207 DisplayIcsInteractionTitle(oldICSInteractionTitle);
3209 unlink(gameCopyFilename);
3210 unlink(gamePasteFilename);
3213 RETSIGTYPE TermSizeSigHandler(int sig)
3226 CmailSigHandler(sig)
3232 signal(SIGUSR1, SIG_IGN); /* suspend handler */
3234 /* Activate call-back function CmailSigHandlerCallBack() */
3235 OutputToProcess(cmailPR, (char *)(&dummy), sizeof(int), &error);
3237 signal(SIGUSR1, CmailSigHandler); /* re-activate handler */
3241 CmailSigHandlerCallBack(isr, closure, message, count, error)
3249 ReloadCmailMsgEvent(TRUE); /* Reload cmail msg */
3251 /**** end signal code ****/
3261 f = fopen(appData.icsLogon, "r");
3267 strcat(buf, appData.icsLogon);
3268 f = fopen(buf, "r");
3272 ProcessICSInitScript(f);
3279 EditCommentPopDown();
3290 SetMenuEnables(enab)
3294 if (!menuBarWidget) return;
3295 while (enab->name != NULL) {
3296 w = XtNameToWidget(menuBarWidget, enab->name);
3298 DisplayError(enab->name, 0);
3300 XtSetSensitive(w, enab->value);
3306 Enables icsEnables[] = {
3307 { "menuFile.Mail Move", False },
3308 { "menuFile.Reload CMail Message", False },
3309 { "menuMode.Machine Black", False },
3310 { "menuMode.Machine White", False },
3311 { "menuMode.Analysis Mode", False },
3312 { "menuMode.Analyze File", False },
3313 { "menuMode.Two Machines", False },
3315 { "menuHelp.Hint", False },
3316 { "menuHelp.Book", False },
3317 { "menuStep.Move Now", False },
3318 { "menuOptions.Periodic Updates", False },
3319 { "menuOptions.Hide Thinking", False },
3320 { "menuOptions.Ponder Next Move", False },
3325 Enables ncpEnables[] = {
3326 { "menuFile.Mail Move", False },
3327 { "menuFile.Reload CMail Message", False },
3328 { "menuMode.Machine White", False },
3329 { "menuMode.Machine Black", False },
3330 { "menuMode.Analysis Mode", False },
3331 { "menuMode.Analyze File", False },
3332 { "menuMode.Two Machines", False },
3333 { "menuMode.ICS Client", False },
3334 { "menuMode.ICS Input Box", False },
3335 { "Action", False },
3336 { "menuStep.Revert", False },
3337 { "menuStep.Move Now", False },
3338 { "menuStep.Retract Move", False },
3339 { "menuOptions.Auto Comment", False },
3340 { "menuOptions.Auto Flag", False },
3341 { "menuOptions.Auto Flip View", False },
3342 { "menuOptions.Auto Observe", False },
3343 { "menuOptions.Auto Raise Board", False },
3344 { "menuOptions.Get Move List", False },
3345 { "menuOptions.ICS Alarm", False },
3346 { "menuOptions.Move Sound", False },
3347 { "menuOptions.Quiet Play", False },
3348 { "menuOptions.Hide Thinking", False },
3349 { "menuOptions.Periodic Updates", False },
3350 { "menuOptions.Ponder Next Move", False },
3351 { "menuHelp.Hint", False },
3352 { "menuHelp.Book", False },
3356 Enables gnuEnables[] = {
3357 { "menuMode.ICS Client", False },
3358 { "menuMode.ICS Input Box", False },
3359 { "menuAction.Accept", False },
3360 { "menuAction.Decline", False },
3361 { "menuAction.Rematch", False },
3362 { "menuAction.Adjourn", False },
3363 { "menuAction.Stop Examining", False },
3364 { "menuAction.Stop Observing", False },
3365 { "menuStep.Revert", False },
3366 { "menuOptions.Auto Comment", False },
3367 { "menuOptions.Auto Observe", False },
3368 { "menuOptions.Auto Raise Board", False },
3369 { "menuOptions.Get Move List", False },
3370 { "menuOptions.Premove", False },
3371 { "menuOptions.Quiet Play", False },
3373 /* The next two options rely on SetCmailMode being called *after* */
3374 /* SetGNUMode so that when GNU is being used to give hints these */
3375 /* menu options are still available */
3377 { "menuFile.Mail Move", False },
3378 { "menuFile.Reload CMail Message", False },
3382 Enables cmailEnables[] = {
3384 { "menuAction.Call Flag", False },
3385 { "menuAction.Draw", True },
3386 { "menuAction.Adjourn", False },
3387 { "menuAction.Abort", False },
3388 { "menuAction.Stop Observing", False },
3389 { "menuAction.Stop Examining", False },
3390 { "menuFile.Mail Move", True },
3391 { "menuFile.Reload CMail Message", True },
3395 Enables trainingOnEnables[] = {
3396 { "menuMode.Edit Comment", False },
3397 { "menuMode.Pause", False },
3398 { "menuStep.Forward", False },
3399 { "menuStep.Backward", False },
3400 { "menuStep.Forward to End", False },
3401 { "menuStep.Back to Start", False },
3402 { "menuStep.Move Now", False },
3403 { "menuStep.Truncate Game", False },
3407 Enables trainingOffEnables[] = {
3408 { "menuMode.Edit Comment", True },
3409 { "menuMode.Pause", True },
3410 { "menuStep.Forward", True },
3411 { "menuStep.Backward", True },
3412 { "menuStep.Forward to End", True },
3413 { "menuStep.Back to Start", True },
3414 { "menuStep.Move Now", True },
3415 { "menuStep.Truncate Game", True },
3419 Enables machineThinkingEnables[] = {
3420 { "menuFile.Load Game", False },
3421 { "menuFile.Load Next Game", False },
3422 { "menuFile.Load Previous Game", False },
3423 { "menuFile.Reload Same Game", False },
3424 { "menuFile.Paste Game", False },
3425 { "menuFile.Load Position", False },
3426 { "menuFile.Load Next Position", False },
3427 { "menuFile.Load Previous Position", False },
3428 { "menuFile.Reload Same Position", False },
3429 { "menuFile.Paste Position", False },
3430 { "menuMode.Machine White", False },
3431 { "menuMode.Machine Black", False },
3432 { "menuMode.Two Machines", False },
3433 { "menuStep.Retract Move", False },
3437 Enables userThinkingEnables[] = {
3438 { "menuFile.Load Game", True },
3439 { "menuFile.Load Next Game", True },
3440 { "menuFile.Load Previous Game", True },
3441 { "menuFile.Reload Same Game", True },
3442 { "menuFile.Paste Game", True },
3443 { "menuFile.Load Position", True },
3444 { "menuFile.Load Next Position", True },
3445 { "menuFile.Load Previous Position", True },
3446 { "menuFile.Reload Same Position", True },
3447 { "menuFile.Paste Position", True },
3448 { "menuMode.Machine White", True },
3449 { "menuMode.Machine Black", True },
3450 { "menuMode.Two Machines", True },
3451 { "menuStep.Retract Move", True },
3457 SetMenuEnables(icsEnables);
3460 if (appData.zippyPlay && !appData.noChessProgram) /* [DM] icsEngineAnalyze */
3461 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Analysis Mode"), True);
3468 SetMenuEnables(ncpEnables);
3474 SetMenuEnables(gnuEnables);
3480 SetMenuEnables(cmailEnables);
3486 SetMenuEnables(trainingOnEnables);
3487 if (appData.showButtonBar) {
3488 XtSetSensitive(buttonBarWidget, False);
3494 SetTrainingModeOff()
3496 SetMenuEnables(trainingOffEnables);
3497 if (appData.showButtonBar) {
3498 XtSetSensitive(buttonBarWidget, True);
3503 SetUserThinkingEnables()
3505 if (appData.noChessProgram) return;
3506 SetMenuEnables(userThinkingEnables);
3510 SetMachineThinkingEnables()
3512 if (appData.noChessProgram) return;
3513 SetMenuEnables(machineThinkingEnables);
3515 case MachinePlaysBlack:
3516 case MachinePlaysWhite:
3517 case TwoMachinesPlay:
3518 XtSetSensitive(XtNameToWidget(menuBarWidget,
3519 ModeToWidgetName(gameMode)), True);
3526 #define Abs(n) ((n)<0 ? -(n) : (n))
3529 * Find a font that matches "pattern" that is as close as
3530 * possible to the targetPxlSize. Prefer fonts that are k
3531 * pixels smaller to fonts that are k pixels larger. The
3532 * pattern must be in the X Consortium standard format,
3533 * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".
3534 * The return value should be freed with XtFree when no
3537 char *FindFont(pattern, targetPxlSize)
3541 char **fonts, *p, *best, *scalable, *scalableTail;
3542 int i, j, nfonts, minerr, err, pxlSize;
3545 char **missing_list;
3547 char *def_string, *base_fnt_lst, strInt[3];
3549 XFontStruct **fnt_list;
3551 base_fnt_lst = calloc(1, strlen(pattern) + 3);
3552 sprintf(strInt, "%d", targetPxlSize);
3553 p = strstr(pattern, "--");
3554 strncpy(base_fnt_lst, pattern, p - pattern + 2);
3555 strcat(base_fnt_lst, strInt);
3556 strcat(base_fnt_lst, strchr(p + 2, '-'));
3558 if ((fntSet = XCreateFontSet(xDisplay,
3562 &def_string)) == NULL) {
3564 fprintf(stderr, _("Unable to create font set.\n"));
3568 nfonts = XFontsOfFontSet(fntSet, &fnt_list, &fonts);
3570 fonts = XListFonts(xDisplay, pattern, 999999, &nfonts);
3572 fprintf(stderr, _("%s: no fonts match pattern %s\n"),
3573 programName, pattern);
3581 for (i=0; i<nfonts; i++) {
3584 if (*p != '-') continue;
3586 if (*p == NULLCHAR) break;
3587 if (*p++ == '-') j++;
3589 if (j < 7) continue;
3592 scalable = fonts[i];
3595 err = pxlSize - targetPxlSize;
3596 if (Abs(err) < Abs(minerr) ||
3597 (minerr > 0 && err < 0 && -err == minerr)) {
3603 if (scalable && Abs(minerr) > appData.fontSizeTolerance) {
3604 /* If the error is too big and there is a scalable font,
3605 use the scalable font. */
3606 int headlen = scalableTail - scalable;
3607 p = (char *) XtMalloc(strlen(scalable) + 10);
3608 while (isdigit(*scalableTail)) scalableTail++;
3609 sprintf(p, "%.*s%d%s", headlen, scalable, targetPxlSize, scalableTail);
3611 p = (char *) XtMalloc(strlen(best) + 1);
3614 if (appData.debugMode) {
3615 fprintf(debugFP, _("resolved %s at pixel size %d\n to %s\n"),
3616 pattern, targetPxlSize, p);
3619 if (missing_count > 0)
3620 XFreeStringList(missing_list);
3621 XFreeFontSet(xDisplay, fntSet);
3623 XFreeFontNames(fonts);
3630 XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
3631 | GCBackground | GCFunction | GCPlaneMask;
3632 XGCValues gc_values;
3635 gc_values.plane_mask = AllPlanes;
3636 gc_values.line_width = lineGap;
3637 gc_values.line_style = LineSolid;
3638 gc_values.function = GXcopy;
3640 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3641 gc_values.background = XBlackPixel(xDisplay, xScreen);
3642 lineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3644 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3645 gc_values.background = XWhitePixel(xDisplay, xScreen);
3646 coordGC = XtGetGC(shellWidget, value_mask, &gc_values);
3647 XSetFont(xDisplay, coordGC, coordFontID);
3649 // [HGM] make font for holdings counts (white on black0
3650 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3651 gc_values.background = XBlackPixel(xDisplay, xScreen);
3652 countGC = XtGetGC(shellWidget, value_mask, &gc_values);
3653 XSetFont(xDisplay, countGC, countFontID);
3655 if (appData.monoMode) {
3656 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3657 gc_values.background = XWhitePixel(xDisplay, xScreen);
3658 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3660 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3661 gc_values.background = XBlackPixel(xDisplay, xScreen);
3662 lightSquareGC = wbPieceGC
3663 = XtGetGC(shellWidget, value_mask, &gc_values);
3665 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3666 gc_values.background = XWhitePixel(xDisplay, xScreen);
3667 darkSquareGC = bwPieceGC
3668 = XtGetGC(shellWidget, value_mask, &gc_values);
3670 if (DefaultDepth(xDisplay, xScreen) == 1) {
3671 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
3672 gc_values.function = GXcopyInverted;
3673 copyInvertedGC = XtGetGC(shellWidget, value_mask, &gc_values);
3674 gc_values.function = GXcopy;
3675 if (XBlackPixel(xDisplay, xScreen) == 1) {
3676 bwPieceGC = darkSquareGC;
3677 wbPieceGC = copyInvertedGC;
3679 bwPieceGC = copyInvertedGC;
3680 wbPieceGC = lightSquareGC;
3684 gc_values.foreground = highlightSquareColor;
3685 gc_values.background = highlightSquareColor;
3686 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3688 gc_values.foreground = premoveHighlightColor;
3689 gc_values.background = premoveHighlightColor;
3690 prelineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3692 gc_values.foreground = lightSquareColor;
3693 gc_values.background = darkSquareColor;
3694 lightSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3696 gc_values.foreground = darkSquareColor;
3697 gc_values.background = lightSquareColor;
3698 darkSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3700 gc_values.foreground = jailSquareColor;
3701 gc_values.background = jailSquareColor;
3702 jailSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3704 gc_values.foreground = whitePieceColor;
3705 gc_values.background = darkSquareColor;
3706 wdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3708 gc_values.foreground = whitePieceColor;
3709 gc_values.background = lightSquareColor;
3710 wlPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3712 gc_values.foreground = whitePieceColor;
3713 gc_values.background = jailSquareColor;
3714 wjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3716 gc_values.foreground = blackPieceColor;
3717 gc_values.background = darkSquareColor;
3718 bdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3720 gc_values.foreground = blackPieceColor;
3721 gc_values.background = lightSquareColor;
3722 blPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3724 gc_values.foreground = blackPieceColor;
3725 gc_values.background = jailSquareColor;
3726 bjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3730 void loadXIM(xim, xmask, filename, dest, mask)
3743 fp = fopen(filename, "rb");
3745 fprintf(stderr, _("%s: error loading XIM!\n"), programName);
3752 for (y=0; y<h; ++y) {
3753 for (x=0; x<h; ++x) {
3758 XPutPixel(xim, x, y, blackPieceColor);
3760 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3763 XPutPixel(xim, x, y, darkSquareColor);
3765 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3768 XPutPixel(xim, x, y, whitePieceColor);
3770 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3773 XPutPixel(xim, x, y, lightSquareColor);
3775 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3781 /* create Pixmap of piece */
3782 *dest = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3784 XPutImage(xDisplay, *dest, lightSquareGC, xim,
3787 /* create Pixmap of clipmask
3788 Note: We assume the white/black pieces have the same
3789 outline, so we make only 6 masks. This is okay
3790 since the XPM clipmask routines do the same. */
3792 temp = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3794 XPutImage(xDisplay, temp, lightSquareGC, xmask,
3797 /* now create the 1-bit version */
3798 *mask = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3801 values.foreground = 1;
3802 values.background = 0;
3804 /* Don't use XtGetGC, not read only */
3805 maskGC = XCreateGC(xDisplay, *mask,
3806 GCForeground | GCBackground, &values);
3807 XCopyPlane(xDisplay, temp, *mask, maskGC,
3808 0, 0, squareSize, squareSize, 0, 0, 1);
3809 XFreePixmap(xDisplay, temp);
3814 char pieceBitmapNames[] = "pnbrqfeacwmohijgdvlsukpnsl";
3816 void CreateXIMPieces()
3821 static char *ximkind[] = { "ll", "ld", "dl", "dd" };
3826 /* The XSynchronize calls were copied from CreatePieces.
3827 Not sure if needed, but can't hurt */
3828 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3831 /* temp needed by loadXIM() */
3832 ximtemp = XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3833 0, 0, ss, ss, AllPlanes, XYPixmap);
3835 if (strlen(appData.pixmapDirectory) == 0) {
3839 if (appData.monoMode) {
3840 DisplayFatalError(_("XIM pieces cannot be used in monochrome mode"),
3844 fprintf(stderr, _("\nLoading XIMs...\n"));
3846 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3847 fprintf(stderr, "%d", piece+1);
3848 for (kind=0; kind<4; kind++) {
3849 fprintf(stderr, ".");
3850 snprintf(buf, sizeof(buf), "%s/%s%c%s%u.xim",
3851 ExpandPathName(appData.pixmapDirectory),
3852 piece <= (int) WhiteKing ? "" : "w",
3853 pieceBitmapNames[piece],
3855 ximPieceBitmap[kind][piece] =
3856 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3857 0, 0, ss, ss, AllPlanes, XYPixmap);
3858 if (appData.debugMode)
3859 fprintf(stderr, _("(File:%s:) "), buf);
3860 loadXIM(ximPieceBitmap[kind][piece],
3862 &(xpmPieceBitmap2[kind][piece]),
3863 &(ximMaskPm2[piece]));
3864 if(piece <= (int)WhiteKing)
3865 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3867 fprintf(stderr," ");
3869 /* Load light and dark squares */
3870 /* If the LSQ and DSQ pieces don't exist, we will
3871 draw them with solid squares. */
3872 snprintf(buf,sizeof(buf), "%s/lsq%u.xim", ExpandPathName(appData.pixmapDirectory), ss);
3873 if (access(buf, 0) != 0) {
3877 fprintf(stderr, _("light square "));
3879 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3880 0, 0, ss, ss, AllPlanes, XYPixmap);
3881 if (appData.debugMode)
3882 fprintf(stderr, _("(File:%s:) "), buf);
3884 loadXIM(ximLightSquare, NULL, buf, &xpmLightSquare, NULL);
3885 fprintf(stderr, _("dark square "));
3886 snprintf(buf,sizeof(buf), "%s/dsq%u.xim",
3887 ExpandPathName(appData.pixmapDirectory), ss);
3888 if (appData.debugMode)
3889 fprintf(stderr, _("(File:%s:) "), buf);
3891 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3892 0, 0, ss, ss, AllPlanes, XYPixmap);
3893 loadXIM(ximDarkSquare, NULL, buf, &xpmDarkSquare, NULL);
3894 xpmJailSquare = xpmLightSquare;
3896 fprintf(stderr, _("Done.\n"));
3898 XSynchronize(xDisplay, False); /* Work-around for xlib/xt buffering bug */
3902 void CreateXPMPieces()
3906 u_int ss = squareSize;
3908 static char *xpmkind[] = { "ll", "ld", "dl", "dd" };
3909 XpmColorSymbol symbols[4];
3911 /* The XSynchronize calls were copied from CreatePieces.
3912 Not sure if needed, but can't hurt */
3913 XSynchronize(xDisplay, True); /* Work-around for xlib/xt buffering bug */
3915 /* Setup translations so piece colors match square colors */
3916 symbols[0].name = "light_piece";
3917 symbols[0].value = appData.whitePieceColor;
3918 symbols[1].name = "dark_piece";
3919 symbols[1].value = appData.blackPieceColor;
3920 symbols[2].name = "light_square";
3921 symbols[2].value = appData.lightSquareColor;
3922 symbols[3].name = "dark_square";
3923 symbols[3].value = appData.darkSquareColor;
3925 attr.valuemask = XpmColorSymbols;
3926 attr.colorsymbols = symbols;
3927 attr.numsymbols = 4;
3929 if (appData.monoMode) {
3930 DisplayFatalError(_("XPM pieces cannot be used in monochrome mode"),
3934 if (strlen(appData.pixmapDirectory) == 0) {
3935 XpmPieces* pieces = builtInXpms;
3938 while (pieces->size != squareSize && pieces->size) pieces++;
3939 if (!pieces->size) {
3940 fprintf(stderr, _("No builtin XPM pieces of size %d\n"), squareSize);
3943 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3944 for (kind=0; kind<4; kind++) {
3946 if ((r=XpmCreatePixmapFromData(xDisplay, xBoardWindow,
3947 pieces->xpm[piece][kind],
3948 &(xpmPieceBitmap2[kind][piece]),
3949 NULL, &attr)) != 0) {
3950 fprintf(stderr, _("Error %d loading XPM image \"%s\"\n"),
3954 if(piece <= (int) WhiteKing)
3955 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3959 xpmJailSquare = xpmLightSquare;
3963 fprintf(stderr, _("\nLoading XPMs...\n"));
3966 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3967 fprintf(stderr, "%d ", piece+1);
3968 for (kind=0; kind<4; kind++) {
3969 snprintf(buf, sizeof(buf), "%s/%s%c%s%u.xpm",
3970 ExpandPathName(appData.pixmapDirectory),
3971 piece > (int) WhiteKing ? "w" : "",
3972 pieceBitmapNames[piece],
3974 if (appData.debugMode) {
3975 fprintf(stderr, _("(File:%s:) "), buf);
3977 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3978 &(xpmPieceBitmap2[kind][piece]),
3979 NULL, &attr)) != 0) {
3980 if(piece != (int)WhiteKing && piece > (int)WhiteQueen) {
3981 // [HGM] missing: read of unorthodox piece failed; substitute King.
3982 snprintf(buf, sizeof(buf), "%s/k%s%u.xpm",
3983 ExpandPathName(appData.pixmapDirectory),
3985 if (appData.debugMode) {
3986 fprintf(stderr, _("(Replace by File:%s:) "), buf);
3988 r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3989 &(xpmPieceBitmap2[kind][piece]),
3993 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"),
3998 if(piece <= (int) WhiteKing)
3999 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
4002 /* Load light and dark squares */
4003 /* If the LSQ and DSQ pieces don't exist, we will
4004 draw them with solid squares. */
4005 fprintf(stderr, _("light square "));
4006 snprintf(buf, sizeof(buf), "%s/lsq%u.xpm", ExpandPathName(appData.pixmapDirectory), ss);
4007 if (access(buf, 0) != 0) {
4011 if (appData.debugMode)
4012 fprintf(stderr, _("(File:%s:) "), buf);
4014 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
4015 &xpmLightSquare, NULL, &attr)) != 0) {
4016 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
4019 fprintf(stderr, _("dark square "));
4020 snprintf(buf, sizeof(buf), "%s/dsq%u.xpm",
4021 ExpandPathName(appData.pixmapDirectory), ss);
4022 if (appData.debugMode) {
4023 fprintf(stderr, _("(File:%s:) "), buf);
4025 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
4026 &xpmDarkSquare, NULL, &attr)) != 0) {
4027 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
4031 xpmJailSquare = xpmLightSquare;
4032 fprintf(stderr, _("Done.\n"));
4034 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
4037 #endif /* HAVE_LIBXPM */
4040 /* No built-in bitmaps */
4045 u_int ss = squareSize;
4047 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
4050 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
4051 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
4052 sprintf(buf, "%s%c%u%c.bm", piece > (int)WhiteKing ? "w" : "",
4053 pieceBitmapNames[piece],
4054 ss, kind == SOLID ? 's' : 'o');
4055 ReadBitmap(&pieceBitmap2[kind][piece], buf, NULL, ss, ss);
4056 if(piece <= (int)WhiteKing)
4057 pieceBitmap[kind][piece] = pieceBitmap2[kind][piece];
4061 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
4065 /* With built-in bitmaps */
4068 BuiltInBits* bib = builtInBits;
4071 u_int ss = squareSize;
4073 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
4076 while (bib->squareSize != ss && bib->squareSize != 0) bib++;
4078 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
4079 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
4080 sprintf(buf, "%s%c%u%c.bm", piece > (int)WhiteKing ? "w" : "",
4081 pieceBitmapNames[piece],
4082 ss, kind == SOLID ? 's' : 'o');
4083 ReadBitmap(&pieceBitmap2[kind][piece], buf,
4084 bib->bits[kind][piece], ss, ss);
4085 if(piece <= (int)WhiteKing)
4086 pieceBitmap[kind][piece] = pieceBitmap2[kind][piece];
4090 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
4095 void ReadBitmap(pm, name, bits, wreq, hreq)
4098 unsigned char bits[];
4104 char msg[MSG_SIZ], fullname[MSG_SIZ];
4106 if (*appData.bitmapDirectory != NULLCHAR) {
4107 strcpy(fullname, appData.bitmapDirectory);
4108 strcat(fullname, "/");
4109 strcat(fullname, name);
4110 errcode = XReadBitmapFile(xDisplay, xBoardWindow, fullname,
4111 &w, &h, pm, &x_hot, &y_hot);
4112 fprintf(stderr, "load %s\n", name);
4113 if (errcode != BitmapSuccess) {
4115 case BitmapOpenFailed:
4116 snprintf(msg, sizeof(msg), _("Can't open bitmap file %s"), fullname);
4118 case BitmapFileInvalid:
4119 snprintf(msg, sizeof(msg), _("Invalid bitmap in file %s"), fullname);
4121 case BitmapNoMemory:
4122 snprintf(msg, sizeof(msg), _("Ran out of memory reading bitmap file %s"),
4126 snprintf(msg, sizeof(msg), _("Unknown XReadBitmapFile error %d on file %s"),
4130 fprintf(stderr, _("%s: %s...using built-in\n"),
4132 } else if (w != wreq || h != hreq) {
4134 _("%s: Bitmap %s is %dx%d, not %dx%d...using built-in\n"),
4135 programName, fullname, w, h, wreq, hreq);
4141 *pm = XCreateBitmapFromData(xDisplay, xBoardWindow, (char *) bits,
4150 if (lineGap == 0) return;
4152 /* [HR] Split this into 2 loops for non-square boards. */
4154 for (i = 0; i < BOARD_HEIGHT + 1; i++) {
4155 gridSegments[i].x1 = 0;
4156 gridSegments[i].x2 =
4157 lineGap + BOARD_WIDTH * (squareSize + lineGap);
4158 gridSegments[i].y1 = gridSegments[i].y2
4159 = lineGap / 2 + (i * (squareSize + lineGap));
4162 for (j = 0; j < BOARD_WIDTH + 1; j++) {
4163 gridSegments[j + i].y1 = 0;
4164 gridSegments[j + i].y2 =
4165 lineGap + BOARD_HEIGHT * (squareSize + lineGap);
4166 gridSegments[j + i].x1 = gridSegments[j + i].x2
4167 = lineGap / 2 + (j * (squareSize + lineGap));
4171 static void MenuBarSelect(w, addr, index)
4176 XtActionProc proc = (XtActionProc) addr;
4178 (proc)(NULL, NULL, NULL, NULL);
4181 void CreateMenuBarPopup(parent, name, mb)
4191 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
4194 XtSetArg(args[j], XtNleftMargin, 20); j++;
4195 XtSetArg(args[j], XtNrightMargin, 20); j++;
4197 while (mi->string != NULL) {
4198 if (strcmp(mi->string, "----") == 0) {
4199 entry = XtCreateManagedWidget(mi->string, smeLineObjectClass,
4202 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string)));
4203 entry = XtCreateManagedWidget(mi->string, smeBSBObjectClass,
4205 XtAddCallback(entry, XtNcallback,
4206 (XtCallbackProc) MenuBarSelect,
4207 (caddr_t) mi->proc);
4213 Widget CreateMenuBar(mb)
4217 Widget anchor, menuBar;
4219 char menuName[MSG_SIZ];
4222 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
4223 XtSetArg(args[j], XtNvSpace, 0); j++;
4224 XtSetArg(args[j], XtNborderWidth, 0); j++;
4225 menuBar = XtCreateWidget("menuBar", boxWidgetClass,
4226 formWidget, args, j);
4228 while (mb->name != NULL) {
4229 strcpy(menuName, "menu");
4230 strcat(menuName, mb->name);
4232 XtSetArg(args[j], XtNmenuName, XtNewString(menuName)); j++;
4235 shortName[0] = _(mb->name)[0];
4236 shortName[1] = NULLCHAR;
4237 XtSetArg(args[j], XtNlabel, XtNewString(shortName)); j++;
4240 XtSetArg(args[j], XtNlabel, XtNewString(_(mb->name))); j++;
4243 XtSetArg(args[j], XtNborderWidth, 0); j++;
4244 anchor = XtCreateManagedWidget(mb->name, menuButtonWidgetClass,
4246 CreateMenuBarPopup(menuBar, menuName, mb);
4252 Widget CreateButtonBar(mi)
4256 Widget button, buttonBar;
4260 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
4262 XtSetArg(args[j], XtNhSpace, 0); j++;
4264 XtSetArg(args[j], XtNborderWidth, 0); j++;
4265 XtSetArg(args[j], XtNvSpace, 0); j++;
4266 buttonBar = XtCreateWidget("buttonBar", boxWidgetClass,
4267 formWidget, args, j);
4269 while (mi->string != NULL) {
4272 XtSetArg(args[j], XtNinternalWidth, 2); j++;
4273 XtSetArg(args[j], XtNborderWidth, 0); j++;
4275 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string))); j++;
4276 button = XtCreateManagedWidget(mi->string, commandWidgetClass,
4277 buttonBar, args, j);
4278 XtAddCallback(button, XtNcallback,
4279 (XtCallbackProc) MenuBarSelect,
4280 (caddr_t) mi->proc);
4287 CreatePieceMenu(name, color)
4294 ChessSquare selection;
4296 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
4297 boardWidget, args, 0);
4299 for (i = 0; i < PIECE_MENU_SIZE; i++) {
4300 String item = pieceMenuStrings[color][i];
4302 if (strcmp(item, "----") == 0) {
4303 entry = XtCreateManagedWidget(item, smeLineObjectClass,
4306 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
4307 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
4309 selection = pieceMenuTranslation[color][i];
4310 XtAddCallback(entry, XtNcallback,
4311 (XtCallbackProc) PieceMenuSelect,
4312 (caddr_t) selection);
4313 if (selection == WhitePawn || selection == BlackPawn) {
4314 XtSetArg(args[0], XtNpopupOnEntry, entry);
4315 XtSetValues(menu, args, 1);
4328 ChessSquare selection;
4330 whitePieceMenu = CreatePieceMenu("menuW", 0);
4331 blackPieceMenu = CreatePieceMenu("menuB", 1);
4333 XtRegisterGrabAction(PieceMenuPopup, True,
4334 (unsigned)(ButtonPressMask|ButtonReleaseMask),
4335 GrabModeAsync, GrabModeAsync);
4337 XtSetArg(args[0], XtNlabel, _("Drop"));
4338 dropMenu = XtCreatePopupShell("menuD", simpleMenuWidgetClass,
4339 boardWidget, args, 1);
4340 for (i = 0; i < DROP_MENU_SIZE; i++) {
4341 String item = dropMenuStrings[i];
4343 if (strcmp(item, "----") == 0) {
4344 entry = XtCreateManagedWidget(item, smeLineObjectClass,
4347 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
4348 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
4350 selection = dropMenuTranslation[i];
4351 XtAddCallback(entry, XtNcallback,
4352 (XtCallbackProc) DropMenuSelect,
4353 (caddr_t) selection);
4358 void SetupDropMenu()
4366 for (i=0; i<sizeof(dmEnables)/sizeof(DropMenuEnables); i++) {
4367 entry = XtNameToWidget(dropMenu, dmEnables[i].widget);
4368 p = strchr(gameMode == IcsPlayingWhite ? white_holding : black_holding,
4369 dmEnables[i].piece);
4370 XtSetSensitive(entry, p != NULL || !appData.testLegality
4371 /*!!temp:*/ || (gameInfo.variant == VariantCrazyhouse
4372 && !appData.icsActive));
4374 while (p && *p++ == dmEnables[i].piece) count++;
4375 snprintf(label, sizeof(label), "%s %d", dmEnables[i].widget, count);
4377 XtSetArg(args[j], XtNlabel, label); j++;
4378 XtSetValues(entry, args, j);
4382 void PieceMenuPopup(w, event, params, num_params)
4386 Cardinal *num_params;
4389 if (event->type != ButtonPress) return;
4390 if (errorUp) ErrorPopDown();
4394 whichMenu = params[0];
4396 case IcsPlayingWhite:
4397 case IcsPlayingBlack:
4399 case MachinePlaysWhite:
4400 case MachinePlaysBlack:
4401 if (appData.testLegality &&
4402 gameInfo.variant != VariantBughouse &&
4403 gameInfo.variant != VariantCrazyhouse) return;
4405 whichMenu = "menuD";
4411 if (((pmFromX = EventToSquare(event->xbutton.x, BOARD_WIDTH)) < 0) ||
4412 ((pmFromY = EventToSquare(event->xbutton.y, BOARD_HEIGHT)) < 0)) {
4413 pmFromX = pmFromY = -1;
4417 pmFromX = BOARD_WIDTH - 1 - pmFromX;
4419 pmFromY = BOARD_HEIGHT - 1 - pmFromY;
4421 XtPopupSpringLoaded(XtNameToWidget(boardWidget, whichMenu));
4424 static void PieceMenuSelect(w, piece, junk)
4429 if (pmFromX < 0 || pmFromY < 0) return;
4430 EditPositionMenuEvent(piece, pmFromX, pmFromY);
4433 static void DropMenuSelect(w, piece, junk)
4438 if (pmFromX < 0 || pmFromY < 0) return;
4439 DropMenuEvent(piece, pmFromX, pmFromY);
4442 void WhiteClock(w, event, prms, nprms)
4448 if (gameMode == EditPosition || gameMode == IcsExamining) {
4449 SetWhiteToPlayEvent();
4450 } else if (gameMode == IcsPlayingBlack || gameMode == MachinePlaysWhite) {
4455 void BlackClock(w, event, prms, nprms)
4461 if (gameMode == EditPosition || gameMode == IcsExamining) {
4462 SetBlackToPlayEvent();
4463 } else if (gameMode == IcsPlayingWhite || gameMode == MachinePlaysBlack) {
4470 * If the user selects on a border boundary, return -1; if off the board,
4471 * return -2. Otherwise map the event coordinate to the square.
4473 int EventToSquare(x, limit)
4481 if ((x % (squareSize + lineGap)) >= squareSize)
4483 x /= (squareSize + lineGap);
4489 static void do_flash_delay(msec)
4495 static void drawHighlight(file, rank, gc)
4501 if (lineGap == 0 || appData.blindfold) return;
4504 x = lineGap/2 + ((BOARD_WIDTH-1)-file) *
4505 (squareSize + lineGap);
4506 y = lineGap/2 + rank * (squareSize + lineGap);
4508 x = lineGap/2 + file * (squareSize + lineGap);
4509 y = lineGap/2 + ((BOARD_HEIGHT-1)-rank) *
4510 (squareSize + lineGap);
4513 XDrawRectangle(xDisplay, xBoardWindow, gc, x, y,
4514 squareSize+lineGap, squareSize+lineGap);
4517 int hi1X = -1, hi1Y = -1, hi2X = -1, hi2Y = -1;
4518 int pm1X = -1, pm1Y = -1, pm2X = -1, pm2Y = -1;
4521 SetHighlights(fromX, fromY, toX, toY)
4522 int fromX, fromY, toX, toY;
4524 if (hi1X != fromX || hi1Y != fromY) {
4525 if (hi1X >= 0 && hi1Y >= 0) {
4526 drawHighlight(hi1X, hi1Y, lineGC);
4528 if (fromX >= 0 && fromY >= 0) {
4529 drawHighlight(fromX, fromY, highlineGC);
4532 if (hi2X != toX || hi2Y != toY) {
4533 if (hi2X >= 0 && hi2Y >= 0) {
4534 drawHighlight(hi2X, hi2Y, lineGC);
4536 if (toX >= 0 && toY >= 0) {
4537 drawHighlight(toX, toY, highlineGC);
4549 SetHighlights(-1, -1, -1, -1);
4554 SetPremoveHighlights(fromX, fromY, toX, toY)
4555 int fromX, fromY, toX, toY;
4557 if (pm1X != fromX || pm1Y != fromY) {
4558 if (pm1X >= 0 && pm1Y >= 0) {
4559 drawHighlight(pm1X, pm1Y, lineGC);
4561 if (fromX >= 0 && fromY >= 0) {
4562 drawHighlight(fromX, fromY, prelineGC);
4565 if (pm2X != toX || pm2Y != toY) {
4566 if (pm2X >= 0 && pm2Y >= 0) {
4567 drawHighlight(pm2X, pm2Y, lineGC);
4569 if (toX >= 0 && toY >= 0) {
4570 drawHighlight(toX, toY, prelineGC);
4580 ClearPremoveHighlights()
4582 SetPremoveHighlights(-1, -1, -1, -1);
4585 static void BlankSquare(x, y, color, piece, dest)
4590 if (useImages && useImageSqs) {
4594 pm = xpmLightSquare;
4599 case 2: /* neutral */
4604 XCopyArea(xDisplay, pm, dest, wlPieceGC, 0, 0,
4605 squareSize, squareSize, x, y);
4615 case 2: /* neutral */
4620 XFillRectangle(xDisplay, dest, gc, x, y, squareSize, squareSize);
4625 I split out the routines to draw a piece so that I could
4626 make a generic flash routine.
4628 static void monoDrawPiece_1bit(piece, square_color, x, y, dest)
4630 int square_color, x, y;
4633 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
4634 switch (square_color) {
4636 case 2: /* neutral */
4638 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
4639 ? *pieceToOutline(piece)
4640 : *pieceToSolid(piece),
4641 dest, bwPieceGC, 0, 0,
4642 squareSize, squareSize, x, y);
4645 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
4646 ? *pieceToSolid(piece)
4647 : *pieceToOutline(piece),
4648 dest, wbPieceGC, 0, 0,
4649 squareSize, squareSize, x, y);
4654 static void monoDrawPiece(piece, square_color, x, y, dest)
4656 int square_color, x, y;
4659 switch (square_color) {
4661 case 2: /* neutral */
4663 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
4664 ? *pieceToOutline(piece)
4665 : *pieceToSolid(piece),
4666 dest, bwPieceGC, 0, 0,
4667 squareSize, squareSize, x, y, 1);
4670 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
4671 ? *pieceToSolid(piece)
4672 : *pieceToOutline(piece),
4673 dest, wbPieceGC, 0, 0,
4674 squareSize, squareSize, x, y, 1);
4679 static void colorDrawPiece(piece, square_color, x, y, dest)
4681 int square_color, x, y;
4684 if(pieceToSolid(piece) == NULL) return; // [HGM] bitmaps: make it non-fatal if we have no bitmap;
4685 switch (square_color) {
4687 XCopyPlane(xDisplay, *pieceToSolid(piece),
4688 dest, (int) piece < (int) BlackPawn
4689 ? wlPieceGC : blPieceGC, 0, 0,
4690 squareSize, squareSize, x, y, 1);
4693 XCopyPlane(xDisplay, *pieceToSolid(piece),
4694 dest, (int) piece < (int) BlackPawn
4695 ? wdPieceGC : bdPieceGC, 0, 0,
4696 squareSize, squareSize, x, y, 1);
4698 case 2: /* neutral */
4700 XCopyPlane(xDisplay, *pieceToSolid(piece),
4701 dest, (int) piece < (int) BlackPawn
4702 ? wjPieceGC : bjPieceGC, 0, 0,
4703 squareSize, squareSize, x, y, 1);
4708 static void colorDrawPieceImage(piece, square_color, x, y, dest)
4710 int square_color, x, y;
4715 switch (square_color) {
4717 case 2: /* neutral */
4719 if ((int)piece < (int) BlackPawn) {
4727 if ((int)piece < (int) BlackPawn) {
4735 XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
4736 dest, wlPieceGC, 0, 0,
4737 squareSize, squareSize, x, y);
4740 typedef void (*DrawFunc)();
4742 DrawFunc ChooseDrawFunc()
4744 if (appData.monoMode) {
4745 if (DefaultDepth(xDisplay, xScreen) == 1) {
4746 return monoDrawPiece_1bit;
4748 return monoDrawPiece;
4752 return colorDrawPieceImage;
4754 return colorDrawPiece;
4758 /* [HR] determine square color depending on chess variant. */
4759 static int SquareColor(row, column)
4764 if (gameInfo.variant == VariantXiangqi) {
4765 if (column >= 3 && column <= 5 && row >= 0 && row <= 2) {
4767 } else if (column >= 3 && column <= 5 && row >= 7 && row <= 9) {
4769 } else if (row <= 4) {
4775 square_color = ((column + row) % 2) == 1;
4778 /* [hgm] holdings: next line makes all holdings squares light */
4779 if(column < BOARD_LEFT || column >= BOARD_RGHT) square_color = 1;
4781 return square_color;
4784 void DrawSquare(row, column, piece, do_flash)
4785 int row, column, do_flash;
4788 int square_color, x, y, direction, font_ascent, font_descent;
4791 XCharStruct overall;
4795 /* Calculate delay in milliseconds (2-delays per complete flash) */
4796 flash_delay = 500 / appData.flashRate;
4799 x = lineGap + ((BOARD_WIDTH-1)-column) *
4800 (squareSize + lineGap);
4801 y = lineGap + row * (squareSize + lineGap);
4803 x = lineGap + column * (squareSize + lineGap);
4804 y = lineGap + ((BOARD_HEIGHT-1)-row) *
4805 (squareSize + lineGap);
4808 square_color = SquareColor(row, column);
4810 if ( // [HGM] holdings: blank out area between board and holdings
4811 column == BOARD_LEFT-1 || column == BOARD_RGHT
4812 || (column == BOARD_LEFT-2 && row < BOARD_HEIGHT-gameInfo.holdingsSize)
4813 || (column == BOARD_RGHT+1 && row >= gameInfo.holdingsSize) ) {
4814 BlankSquare(x, y, 2, EmptySquare, xBoardWindow);
4816 // [HGM] print piece counts next to holdings
4817 string[1] = NULLCHAR;
4818 if (column == (flipView ? BOARD_LEFT-1 : BOARD_RGHT) && piece > 1 ) {
4819 string[0] = '0' + piece;
4820 XTextExtents(countFontStruct, string, 1, &direction,
4821 &font_ascent, &font_descent, &overall);
4822 if (appData.monoMode) {
4823 XDrawImageString(xDisplay, xBoardWindow, countGC,
4824 x + squareSize - overall.width - 2,
4825 y + font_ascent + 1, string, 1);
4827 XDrawString(xDisplay, xBoardWindow, countGC,
4828 x + squareSize - overall.width - 2,
4829 y + font_ascent + 1, string, 1);
4832 if (column == (flipView ? BOARD_RGHT : BOARD_LEFT-1) && piece > 1) {
4833 string[0] = '0' + piece;
4834 XTextExtents(countFontStruct, string, 1, &direction,
4835 &font_ascent, &font_descent, &overall);
4836 if (appData.monoMode) {
4837 XDrawImageString(xDisplay, xBoardWindow, countGC,
4838 x + 2, y + font_ascent + 1, string, 1);
4840 XDrawString(xDisplay, xBoardWindow, countGC,
4841 x + 2, y + font_ascent + 1, string, 1);
4845 if (piece == EmptySquare || appData.blindfold) {
4846 BlankSquare(x, y, square_color, piece, xBoardWindow);
4848 drawfunc = ChooseDrawFunc();
4849 if (do_flash && appData.flashCount > 0) {
4850 for (i=0; i<appData.flashCount; ++i) {
4852 drawfunc(piece, square_color, x, y, xBoardWindow);
4853 XSync(xDisplay, False);
4854 do_flash_delay(flash_delay);
4856 BlankSquare(x, y, square_color, piece, xBoardWindow);
4857 XSync(xDisplay, False);
4858 do_flash_delay(flash_delay);
4861 drawfunc(piece, square_color, x, y, xBoardWindow);
4865 string[1] = NULLCHAR;
4866 if (appData.showCoords && row == (flipView ? BOARD_HEIGHT-1 : 0)
4867 && column >= BOARD_LEFT && column < BOARD_RGHT) {
4868 string[0] = 'a' + column - BOARD_LEFT;
4869 XTextExtents(coordFontStruct, string, 1, &direction,
4870 &font_ascent, &font_descent, &overall);
4871 if (appData.monoMode) {
4872 XDrawImageString(xDisplay, xBoardWindow, coordGC,
4873 x + squareSize - overall.width - 2,
4874 y + squareSize - font_descent - 1, string, 1);
4876 XDrawString(xDisplay, xBoardWindow, coordGC,
4877 x + squareSize - overall.width - 2,
4878 y + squareSize - font_descent - 1, string, 1);
4881 if (appData.showCoords && column == (flipView ? BOARD_RGHT-1 : BOARD_LEFT)) {
4882 string[0] = ONE + row;
4883 XTextExtents(coordFontStruct, string, 1, &direction,
4884 &font_ascent, &font_descent, &overall);
4885 if (appData.monoMode) {
4886 XDrawImageString(xDisplay, xBoardWindow, coordGC,
4887 x + 2, y + font_ascent + 1, string, 1);
4889 XDrawString(xDisplay, xBoardWindow, coordGC,
4890 x + 2, y + font_ascent + 1, string, 1);
4896 /* Why is this needed on some versions of X? */
4897 void EventProc(widget, unused, event)
4902 if (!XtIsRealized(widget))
4905 switch (event->type) {
4907 if (event->xexpose.count > 0) return; /* no clipping is done */
4908 XDrawPosition(widget, True, NULL);
4916 void DrawPosition(fullRedraw, board)
4917 /*Boolean*/int fullRedraw;
4920 XDrawPosition(boardWidget, fullRedraw, board);
4923 /* Returns 1 if there are "too many" differences between b1 and b2
4924 (i.e. more than 1 move was made) */
4925 static int too_many_diffs(b1, b2)
4931 for (i=0; i<BOARD_HEIGHT; ++i) {
4932 for (j=0; j<BOARD_WIDTH; ++j) {
4933 if (b1[i][j] != b2[i][j]) {
4934 if (++c > 4) /* Castling causes 4 diffs */
4943 /* Matrix describing castling maneuvers */
4944 /* Row, ColRookFrom, ColKingFrom, ColRookTo, ColKingTo */
4945 static int castling_matrix[4][5] = {
4946 { 0, 0, 4, 3, 2 }, /* 0-0-0, white */
4947 { 0, 7, 4, 5, 6 }, /* 0-0, white */
4948 { 7, 0, 4, 3, 2 }, /* 0-0-0, black */
4949 { 7, 7, 4, 5, 6 } /* 0-0, black */
4952 /* Checks whether castling occurred. If it did, *rrow and *rcol
4953 are set to the destination (row,col) of the rook that moved.
4955 Returns 1 if castling occurred, 0 if not.
4957 Note: Only handles a max of 1 castling move, so be sure
4958 to call too_many_diffs() first.
4960 static int check_castle_draw(newb, oldb, rrow, rcol)
4967 /* For each type of castling... */
4968 for (i=0; i<4; ++i) {
4969 r = castling_matrix[i];
4971 /* Check the 4 squares involved in the castling move */
4973 for (j=1; j<=4; ++j) {
4974 if (newb[r[0]][r[j]] == oldb[r[0]][r[j]]) {
4981 /* All 4 changed, so it must be a castling move */
4990 static int damage[BOARD_SIZE][BOARD_SIZE];
4993 * event handler for redrawing the board
4995 void XDrawPosition(w, repaint, board)
4997 /*Boolean*/int repaint;
5001 static int lastFlipView = 0;
5002 static int lastBoardValid = 0;
5003 static Board lastBoard;
5007 if (board == NULL) {
5008 if (!lastBoardValid) return;
5011 if (!lastBoardValid || lastFlipView != flipView) {
5012 XtSetArg(args[0], XtNleftBitmap, (flipView ? xMarkPixmap : None));
5013 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flip View"),
5018 * It would be simpler to clear the window with XClearWindow()
5019 * but this causes a very distracting flicker.
5022 if (!repaint && lastBoardValid && lastFlipView == flipView) {
5024 /* If too much changes (begin observing new game, etc.), don't
5026 do_flash = too_many_diffs(board, lastBoard) ? 0 : 1;
5028 /* Special check for castling so we don't flash both the king
5029 and the rook (just flash the king). */
5031 if (check_castle_draw(board, lastBoard, &rrow, &rcol)) {
5032 /* Draw rook with NO flashing. King will be drawn flashing later */
5033 DrawSquare(rrow, rcol, board[rrow][rcol], 0);
5034 lastBoard[rrow][rcol] = board[rrow][rcol];
5038 /* First pass -- Draw (newly) empty squares and repair damage.
5039 This prevents you from having a piece show up twice while it
5040 is flashing on its new square */
5041 for (i = 0; i < BOARD_HEIGHT; i++)
5042 for (j = 0; j < BOARD_WIDTH; j++)
5043 if ((board[i][j] != lastBoard[i][j] && board[i][j] == EmptySquare)
5045 DrawSquare(i, j, board[i][j], 0);
5046 damage[i][j] = False;
5049 /* Second pass -- Draw piece(s) in new position and flash them */
5050 for (i = 0; i < BOARD_HEIGHT; i++)
5051 for (j = 0; j < BOARD_WIDTH; j++)
5052 if (board[i][j] != lastBoard[i][j]) {
5053 DrawSquare(i, j, board[i][j], do_flash);
5057 XDrawSegments(xDisplay, xBoardWindow, lineGC,
5058 gridSegments, BOARD_HEIGHT + BOARD_WIDTH + 2);
5060 for (i = 0; i < BOARD_HEIGHT; i++)
5061 for (j = 0; j < BOARD_WIDTH; j++) {
5062 DrawSquare(i, j, board[i][j], 0);
5063 damage[i][j] = False;
5067 CopyBoard(lastBoard, board);
5069 lastFlipView = flipView;
5071 /* Draw highlights */
5072 if (pm1X >= 0 && pm1Y >= 0) {
5073 drawHighlight(pm1X, pm1Y, prelineGC);
5075 if (pm2X >= 0 && pm2Y >= 0) {
5076 drawHighlight(pm2X, pm2Y, prelineGC);
5078 if (hi1X >= 0 && hi1Y >= 0) {
5079 drawHighlight(hi1X, hi1Y, highlineGC);
5081 if (hi2X >= 0 && hi2Y >= 0) {
5082 drawHighlight(hi2X, hi2Y, highlineGC);
5085 /* If piece being dragged around board, must redraw that too */
5088 XSync(xDisplay, False);
5093 * event handler for redrawing the board
5095 void DrawPositionProc(w, event, prms, nprms)
5101 XDrawPosition(w, True, NULL);
5106 * event handler for parsing user moves
5108 // [HGM] This routine will need quite some reworking. Although the backend still supports the old
5109 // way of doing things, by calling UserMoveEvent() to test the legality of the move and then perform
5110 // it at the end, and doing all kind of preliminary tests here (e.g. to weed out self-captures), it
5111 // should be made to use the new way, of calling UserMoveTest early to determine the legality of the
5112 // move, (which will weed out the illegal selfcaptures and moves into the holdings, and flag promotions),
5113 // and at the end FinishMove() to perform the move after optional promotion popups.
5114 // For now I patched it to allow self-capture with King, and suppress clicks between board and holdings.
5115 void HandleUserMove(w, event, prms, nprms)
5121 if (w != boardWidget || errorExitStatus != -1) return;
5124 if (event->type == ButtonPress) {
5125 XtPopdown(promotionShell);
5126 XtDestroyWidget(promotionShell);
5127 promotionUp = False;
5135 // [HGM] mouse: the rest of the mouse handler is moved to the backend, and called here
5136 if(event->type == ButtonPress) LeftClick(Press, event->xbutton.x, event->xbutton.y);
5137 if(event->type == ButtonRelease) LeftClick(Release, event->xbutton.x, event->xbutton.y);
5140 void AnimateUserMove (Widget w, XEvent * event,
5141 String * params, Cardinal * nParams)
5143 DragPieceMove(event->xmotion.x, event->xmotion.y);
5146 Widget CommentCreate(name, text, mutable, callback, lines)
5148 int /*Boolean*/ mutable;
5149 XtCallbackProc callback;
5153 Widget shell, layout, form, edit, b_ok, b_cancel, b_clear, b_close, b_edit;
5158 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5159 XtGetValues(boardWidget, args, j);
5162 XtSetArg(args[j], XtNresizable, True); j++;
5165 XtCreatePopupShell(name, topLevelShellWidgetClass,
5166 shellWidget, args, j);
5169 XtCreatePopupShell(name, transientShellWidgetClass,
5170 shellWidget, args, j);
5173 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
5174 layoutArgs, XtNumber(layoutArgs));
5176 XtCreateManagedWidget("form", formWidgetClass, layout,
5177 formArgs, XtNumber(formArgs));
5181 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
5182 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
5184 XtSetArg(args[j], XtNstring, text); j++;
5185 XtSetArg(args[j], XtNtop, XtChainTop); j++;
5186 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5187 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5188 XtSetArg(args[j], XtNright, XtChainRight); j++;
5189 XtSetArg(args[j], XtNresizable, True); j++;
5190 XtSetArg(args[j], XtNwidth, bw_width); j++; /*force wider than buttons*/
5191 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
5192 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
5193 XtSetArg(args[j], XtNautoFill, True); j++;
5194 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
5196 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
5200 XtSetArg(args[j], XtNfromVert, edit); j++;
5201 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5202 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5203 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5204 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5206 XtCreateManagedWidget(_("ok"), commandWidgetClass, form, args, j);
5207 XtAddCallback(b_ok, XtNcallback, callback, (XtPointer) 0);
5210 XtSetArg(args[j], XtNfromVert, edit); j++;
5211 XtSetArg(args[j], XtNfromHoriz, b_ok); j++;
5212 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5213 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5214 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5215 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5217 XtCreateManagedWidget(_("cancel"), commandWidgetClass, form, args, j);
5218 XtAddCallback(b_cancel, XtNcallback, callback, (XtPointer) 0);
5221 XtSetArg(args[j], XtNfromVert, edit); j++;
5222 XtSetArg(args[j], XtNfromHoriz, b_cancel); j++;
5223 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5224 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5225 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5226 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5228 XtCreateManagedWidget(_("clear"), commandWidgetClass, form, args, j);
5229 XtAddCallback(b_clear, XtNcallback, callback, (XtPointer) 0);
5232 XtSetArg(args[j], XtNfromVert, edit); j++;
5233 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5234 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5235 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5236 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5238 XtCreateManagedWidget(_("close"), commandWidgetClass, form, args, j);
5239 XtAddCallback(b_close, XtNcallback, callback, (XtPointer) 0);
5242 XtSetArg(args[j], XtNfromVert, edit); j++;
5243 XtSetArg(args[j], XtNfromHoriz, b_close); j++;
5244 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5245 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5246 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5247 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5249 XtCreateManagedWidget(_("edit"), commandWidgetClass, form, args, j);
5250 XtAddCallback(b_edit, XtNcallback, callback, (XtPointer) 0);
5253 XtRealizeWidget(shell);
5255 if (commentX == -1) {
5258 Dimension pw_height;
5259 Dimension ew_height;
5262 XtSetArg(args[j], XtNheight, &ew_height); j++;
5263 XtGetValues(edit, args, j);
5266 XtSetArg(args[j], XtNheight, &pw_height); j++;
5267 XtGetValues(shell, args, j);
5268 commentH = pw_height + (lines - 1) * ew_height;
5269 commentW = bw_width - 16;
5271 XSync(xDisplay, False);
5273 /* This code seems to tickle an X bug if it is executed too soon
5274 after xboard starts up. The coordinates get transformed as if
5275 the main window was positioned at (0, 0).
5277 XtTranslateCoords(shellWidget,
5278 (bw_width - commentW) / 2, 0 - commentH / 2,
5279 &commentX, &commentY);
5281 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
5282 RootWindowOfScreen(XtScreen(shellWidget)),
5283 (bw_width - commentW) / 2, 0 - commentH / 2,
5288 if (commentY < 0) commentY = 0; /*avoid positioning top offscreen*/
5291 XtSetArg(args[j], XtNheight, commentH); j++;
5292 XtSetArg(args[j], XtNwidth, commentW); j++;
5293 XtSetArg(args[j], XtNx, commentX); j++;
5294 XtSetArg(args[j], XtNy, commentY); j++;
5295 XtSetValues(shell, args, j);
5296 XtSetKeyboardFocus(shell, edit);
5301 /* Used for analysis window and ICS input window */
5302 Widget MiscCreate(name, text, mutable, callback, lines)
5304 int /*Boolean*/ mutable;
5305 XtCallbackProc callback;
5309 Widget shell, layout, form, edit;
5311 Dimension bw_width, pw_height, ew_height, w, h;
5317 XtSetArg(args[j], XtNresizable, True); j++;
5320 XtCreatePopupShell(name, topLevelShellWidgetClass,
5321 shellWidget, args, j);
5324 XtCreatePopupShell(name, transientShellWidgetClass,
5325 shellWidget, args, j);
5328 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
5329 layoutArgs, XtNumber(layoutArgs));
5331 XtCreateManagedWidget("form", formWidgetClass, layout,
5332 formArgs, XtNumber(formArgs));
5336 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
5337 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
5339 XtSetArg(args[j], XtNstring, text); j++;
5340 XtSetArg(args[j], XtNtop, XtChainTop); j++;
5341 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5342 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5343 XtSetArg(args[j], XtNright, XtChainRight); j++;
5344 XtSetArg(args[j], XtNresizable, True); j++;
5345 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
5346 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
5347 XtSetArg(args[j], XtNautoFill, True); j++;
5348 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
5350 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
5352 XtRealizeWidget(shell);
5355 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5356 XtGetValues(boardWidget, args, j);
5359 XtSetArg(args[j], XtNheight, &ew_height); j++;
5360 XtGetValues(edit, args, j);
5363 XtSetArg(args[j], XtNheight, &pw_height); j++;
5364 XtGetValues(shell, args, j);
5365 h = pw_height + (lines - 1) * ew_height;
5368 XSync(xDisplay, False);
5370 /* This code seems to tickle an X bug if it is executed too soon
5371 after xboard starts up. The coordinates get transformed as if
5372 the main window was positioned at (0, 0).
5374 XtTranslateCoords(shellWidget, (bw_width - w) / 2, 0 - h / 2, &x, &y);
5376 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
5377 RootWindowOfScreen(XtScreen(shellWidget)),
5378 (bw_width - w) / 2, 0 - h / 2, &xx, &yy, &junk);
5382 if (y < 0) y = 0; /*avoid positioning top offscreen*/
5385 XtSetArg(args[j], XtNheight, h); j++;
5386 XtSetArg(args[j], XtNwidth, w); j++;
5387 XtSetArg(args[j], XtNx, x); j++;
5388 XtSetArg(args[j], XtNy, y); j++;
5389 XtSetValues(shell, args, j);
5395 static int savedIndex; /* gross that this is global */
5397 void EditCommentPopUp(index, title, text)
5406 if (text == NULL) text = "";
5408 if (editShell == NULL) {
5410 CommentCreate(title, text, True, EditCommentCallback, 4);
5411 XtRealizeWidget(editShell);
5412 CatchDeleteWindow(editShell, "EditCommentPopDown");
5414 edit = XtNameToWidget(editShell, "*form.text");
5416 XtSetArg(args[j], XtNstring, text); j++;
5417 XtSetValues(edit, args, j);
5419 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5420 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5421 XtSetValues(editShell, args, j);
5424 XtPopup(editShell, XtGrabNone);
5428 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
5429 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
5433 void EditCommentCallback(w, client_data, call_data)
5435 XtPointer client_data, call_data;
5443 XtSetArg(args[j], XtNlabel, &name); j++;
5444 XtGetValues(w, args, j);
5446 if (strcmp(name, _("ok")) == 0) {
5447 edit = XtNameToWidget(editShell, "*form.text");
5449 XtSetArg(args[j], XtNstring, &val); j++;
5450 XtGetValues(edit, args, j);
5451 ReplaceComment(savedIndex, val);
5452 EditCommentPopDown();
5453 } else if (strcmp(name, _("cancel")) == 0) {
5454 EditCommentPopDown();
5455 } else if (strcmp(name, _("clear")) == 0) {
5456 edit = XtNameToWidget(editShell, "*form.text");
5457 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
5458 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
5462 void EditCommentPopDown()
5467 if (!editUp) return;
5469 XtSetArg(args[j], XtNx, &commentX); j++;
5470 XtSetArg(args[j], XtNy, &commentY); j++;
5471 XtSetArg(args[j], XtNheight, &commentH); j++;
5472 XtSetArg(args[j], XtNwidth, &commentW); j++;
5473 XtGetValues(editShell, args, j);
5474 XtPopdown(editShell);
5477 XtSetArg(args[j], XtNleftBitmap, None); j++;
5478 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
5482 void ICSInputBoxPopUp()
5487 char *title = _("ICS Input");
5490 if (ICSInputShell == NULL) {
5491 ICSInputShell = MiscCreate(title, "", True, NULL, 1);
5492 tr = XtParseTranslationTable(ICSInputTranslations);
5493 edit = XtNameToWidget(ICSInputShell, "*form.text");
5494 XtOverrideTranslations(edit, tr);
5495 XtRealizeWidget(ICSInputShell);
5496 CatchDeleteWindow(ICSInputShell, "ICSInputBoxPopDown");
5499 edit = XtNameToWidget(ICSInputShell, "*form.text");
5501 XtSetArg(args[j], XtNstring, ""); j++;
5502 XtSetValues(edit, args, j);
5504 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5505 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5506 XtSetValues(ICSInputShell, args, j);
5509 XtPopup(ICSInputShell, XtGrabNone);
5510 XtSetKeyboardFocus(ICSInputShell, edit);
5512 ICSInputBoxUp = True;
5514 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
5515 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
5519 void ICSInputSendText()
5526 edit = XtNameToWidget(ICSInputShell, "*form.text");
5528 XtSetArg(args[j], XtNstring, &val); j++;
5529 XtGetValues(edit, args, j);
5530 SendMultiLineToICS(val);
5531 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
5532 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
5535 void ICSInputBoxPopDown()
5540 if (!ICSInputBoxUp) return;
5542 XtPopdown(ICSInputShell);
5543 ICSInputBoxUp = False;
5545 XtSetArg(args[j], XtNleftBitmap, None); j++;
5546 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
5550 void CommentPopUp(title, text)
5557 if (commentShell == NULL) {
5559 CommentCreate(title, text, False, CommentCallback, 4);
5560 XtRealizeWidget(commentShell);
5561 CatchDeleteWindow(commentShell, "CommentPopDown");
5563 edit = XtNameToWidget(commentShell, "*form.text");
5565 XtSetArg(args[j], XtNstring, text); j++;
5566 XtSetValues(edit, args, j);
5568 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5569 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5570 XtSetValues(commentShell, args, j);
5573 XtPopup(commentShell, XtGrabNone);
5574 XSync(xDisplay, False);
5579 void CommentCallback(w, client_data, call_data)
5581 XtPointer client_data, call_data;
5588 XtSetArg(args[j], XtNlabel, &name); j++;
5589 XtGetValues(w, args, j);
5591 if (strcmp(name, _("close")) == 0) {
5593 } else if (strcmp(name, _("edit")) == 0) {
5600 void CommentPopDown()
5605 if (!commentUp) return;
5607 XtSetArg(args[j], XtNx, &commentX); j++;
5608 XtSetArg(args[j], XtNy, &commentY); j++;
5609 XtSetArg(args[j], XtNwidth, &commentW); j++;
5610 XtSetArg(args[j], XtNheight, &commentH); j++;
5611 XtGetValues(commentShell, args, j);
5612 XtPopdown(commentShell);
5613 XSync(xDisplay, False);
5617 void FileNamePopUp(label, def, proc, openMode)
5624 Widget popup, layout, dialog, edit;
5630 fileProc = proc; /* I can't see a way not */
5631 fileOpenMode = openMode; /* to use globals here */
5634 XtSetArg(args[i], XtNresizable, True); i++;
5635 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
5636 XtSetArg(args[i], XtNtitle, XtNewString(_("File name prompt"))); i++;
5637 fileNameShell = popup =
5638 XtCreatePopupShell("File name prompt", transientShellWidgetClass,
5639 shellWidget, args, i);
5642 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
5643 layoutArgs, XtNumber(layoutArgs));
5646 XtSetArg(args[i], XtNlabel, label); i++;
5647 XtSetArg(args[i], XtNvalue, def); i++;
5648 XtSetArg(args[i], XtNborderWidth, 0); i++;
5649 dialog = XtCreateManagedWidget("fileName", dialogWidgetClass,
5652 XawDialogAddButton(dialog, _("ok"), FileNameCallback, (XtPointer) dialog);
5653 XawDialogAddButton(dialog, _("cancel"), FileNameCallback,
5654 (XtPointer) dialog);
5656 XtRealizeWidget(popup);
5657 CatchDeleteWindow(popup, "FileNamePopDown");
5659 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
5660 &x, &y, &win_x, &win_y, &mask);
5662 XtSetArg(args[0], XtNx, x - 10);
5663 XtSetArg(args[1], XtNy, y - 30);
5664 XtSetValues(popup, args, 2);
5666 XtPopup(popup, XtGrabExclusive);
5669 edit = XtNameToWidget(dialog, "*value");
5670 XtSetKeyboardFocus(popup, edit);
5673 void FileNamePopDown()
5675 if (!filenameUp) return;
5676 XtPopdown(fileNameShell);
5677 XtDestroyWidget(fileNameShell);
5682 void FileNameCallback(w, client_data, call_data)
5684 XtPointer client_data, call_data;
5689 XtSetArg(args[0], XtNlabel, &name);
5690 XtGetValues(w, args, 1);
5692 if (strcmp(name, _("cancel")) == 0) {
5697 FileNameAction(w, NULL, NULL, NULL);
5700 void FileNameAction(w, event, prms, nprms)
5712 name = XawDialogGetValueString(w = XtParent(w));
5714 if ((name != NULL) && (*name != NULLCHAR)) {
5716 XtPopdown(w = XtParent(XtParent(w)));
5720 p = strrchr(buf, ' ');
5727 fullname = ExpandPathName(buf);
5729 ErrorPopUp(_("Error"), _("Can't open file"), FALSE);
5732 f = fopen(fullname, fileOpenMode);
5734 DisplayError(_("Failed to open file"), errno);
5736 (void) (*fileProc)(f, index, buf);
5743 XtPopdown(w = XtParent(XtParent(w)));
5749 void PromotionPopUp()
5752 Widget dialog, layout;
5754 Dimension bw_width, pw_width;
5758 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5759 XtGetValues(boardWidget, args, j);
5762 XtSetArg(args[j], XtNresizable, True); j++;
5763 XtSetArg(args[j], XtNtitle, XtNewString(_("Promotion"))); j++;
5765 XtCreatePopupShell("Promotion", transientShellWidgetClass,
5766 shellWidget, args, j);
5768 XtCreateManagedWidget(layoutName, formWidgetClass, promotionShell,
5769 layoutArgs, XtNumber(layoutArgs));
5772 XtSetArg(args[j], XtNlabel, _("Promote to what?")); j++;
5773 XtSetArg(args[j], XtNborderWidth, 0); j++;
5774 dialog = XtCreateManagedWidget("promotion", dialogWidgetClass,
5777 if(gameInfo.variant != VariantShogi) {
5778 XawDialogAddButton(dialog, _("Queen"), PromotionCallback,
5779 (XtPointer) dialog);
5780 XawDialogAddButton(dialog, _("Rook"), PromotionCallback,
5781 (XtPointer) dialog);
5782 XawDialogAddButton(dialog, _("Bishop"), PromotionCallback,
5783 (XtPointer) dialog);
5784 XawDialogAddButton(dialog, _("Knight"), PromotionCallback,
5785 (XtPointer) dialog);
5786 if (!appData.testLegality || gameInfo.variant == VariantSuicide ||
5787 gameInfo.variant == VariantGiveaway) {
5788 XawDialogAddButton(dialog, _("King"), PromotionCallback,
5789 (XtPointer) dialog);
5791 if(gameInfo.variant == VariantCapablanca ||
5792 gameInfo.variant == VariantGothic ||
5793 gameInfo.variant == VariantCapaRandom) {
5794 XawDialogAddButton(dialog, _("Archbishop"), PromotionCallback,
5795 (XtPointer) dialog);
5796 XawDialogAddButton(dialog, _("Chancellor"), PromotionCallback,
5797 (XtPointer) dialog);
5799 } else // [HGM] shogi
5801 XawDialogAddButton(dialog, _("Promote"), PromotionCallback,
5802 (XtPointer) dialog);
5803 XawDialogAddButton(dialog, _("Defer"), PromotionCallback,
5804 (XtPointer) dialog);
5806 XawDialogAddButton(dialog, _("cancel"), PromotionCallback,
5807 (XtPointer) dialog);
5809 XtRealizeWidget(promotionShell);
5810 CatchDeleteWindow(promotionShell, "PromotionPopDown");
5813 XtSetArg(args[j], XtNwidth, &pw_width); j++;
5814 XtGetValues(promotionShell, args, j);
5816 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
5817 lineGap + squareSize/3 +
5818 ((toY == BOARD_HEIGHT-1) ^ (flipView) ?
5819 0 : 6*(squareSize + lineGap)), &x, &y);
5822 XtSetArg(args[j], XtNx, x); j++;
5823 XtSetArg(args[j], XtNy, y); j++;
5824 XtSetValues(promotionShell, args, j);
5826 XtPopup(promotionShell, XtGrabNone);
5831 void PromotionPopDown()
5833 if (!promotionUp) return;
5834 XtPopdown(promotionShell);
5835 XtDestroyWidget(promotionShell);
5836 promotionUp = False;
5839 void PromotionCallback(w, client_data, call_data)
5841 XtPointer client_data, call_data;
5847 XtSetArg(args[0], XtNlabel, &name);
5848 XtGetValues(w, args, 1);
5852 if (fromX == -1) return;
5854 if (strcmp(name, _("cancel")) == 0) {
5858 } else if (strcmp(name, _("Knight")) == 0) {
5860 } else if (strcmp(name, _("Promote")) == 0) {
5862 } else if (strcmp(name, _("Defer")) == 0) {
5865 promoChar = ToLower(name[0]);
5868 UserMoveEvent(fromX, fromY, toX, toY, promoChar);
5870 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
5871 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
5876 void ErrorCallback(w, client_data, call_data)
5878 XtPointer client_data, call_data;
5881 XtPopdown(w = XtParent(XtParent(XtParent(w))));
5883 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
5889 if (!errorUp) return;
5891 XtPopdown(errorShell);
5892 XtDestroyWidget(errorShell);
5893 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
5896 void ErrorPopUp(title, label, modal)
5897 char *title, *label;
5901 Widget dialog, layout;
5905 Dimension bw_width, pw_width;
5906 Dimension pw_height;
5910 XtSetArg(args[i], XtNresizable, True); i++;
5911 XtSetArg(args[i], XtNtitle, title); i++;
5913 XtCreatePopupShell("errorpopup", transientShellWidgetClass,
5914 shellWidget, args, i);
5916 XtCreateManagedWidget(layoutName, formWidgetClass, errorShell,
5917 layoutArgs, XtNumber(layoutArgs));
5920 XtSetArg(args[i], XtNlabel, label); i++;
5921 XtSetArg(args[i], XtNborderWidth, 0); i++;
5922 dialog = XtCreateManagedWidget("dialog", dialogWidgetClass,
5925 XawDialogAddButton(dialog, _("ok"), ErrorCallback, (XtPointer) dialog);
5927 XtRealizeWidget(errorShell);
5928 CatchDeleteWindow(errorShell, "ErrorPopDown");
5931 XtSetArg(args[i], XtNwidth, &bw_width); i++;
5932 XtGetValues(boardWidget, args, i);
5934 XtSetArg(args[i], XtNwidth, &pw_width); i++;
5935 XtSetArg(args[i], XtNheight, &pw_height); i++;
5936 XtGetValues(errorShell, args, i);
5939 /* This code seems to tickle an X bug if it is executed too soon
5940 after xboard starts up. The coordinates get transformed as if
5941 the main window was positioned at (0, 0).
5943 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
5944 0 - pw_height + squareSize / 3, &x, &y);
5946 XTranslateCoordinates(xDisplay, XtWindow(boardWidget),
5947 RootWindowOfScreen(XtScreen(boardWidget)),
5948 (bw_width - pw_width) / 2,
5949 0 - pw_height + squareSize / 3, &xx, &yy, &junk);
5953 if (y < 0) y = 0; /*avoid positioning top offscreen*/
5956 XtSetArg(args[i], XtNx, x); i++;
5957 XtSetArg(args[i], XtNy, y); i++;
5958 XtSetValues(errorShell, args, i);
5961 XtPopup(errorShell, modal ? XtGrabExclusive : XtGrabNone);
5964 /* Disable all user input other than deleting the window */
5965 static int frozen = 0;
5969 /* Grab by a widget that doesn't accept input */
5970 XtAddGrab(messageWidget, TRUE, FALSE);
5974 /* Undo a FreezeUI */
5977 if (!frozen) return;
5978 XtRemoveGrab(messageWidget);
5982 char *ModeToWidgetName(mode)
5986 case BeginningOfGame:
5987 if (appData.icsActive)
5988 return "menuMode.ICS Client";
5989 else if (appData.noChessProgram ||
5990 *appData.cmailGameName != NULLCHAR)
5991 return "menuMode.Edit Game";
5993 return "menuMode.Machine Black";
5994 case MachinePlaysBlack:
5995 return "menuMode.Machine Black";
5996 case MachinePlaysWhite:
5997 return "menuMode.Machine White";
5999 return "menuMode.Analysis Mode";
6001 return "menuMode.Analyze File";
6002 case TwoMachinesPlay:
6003 return "menuMode.Two Machines";
6005 return "menuMode.Edit Game";
6006 case PlayFromGameFile:
6007 return "menuFile.Load Game";
6009 return "menuMode.Edit Position";
6011 return "menuMode.Training";
6012 case IcsPlayingWhite:
6013 case IcsPlayingBlack:
6017 return "menuMode.ICS Client";
6024 void ModeHighlight()
6027 static int oldPausing = FALSE;
6028 static GameMode oldmode = (GameMode) -1;
6031 if (!boardWidget || !XtIsRealized(boardWidget)) return;
6033 if (pausing != oldPausing) {
6034 oldPausing = pausing;
6036 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6038 XtSetArg(args[0], XtNleftBitmap, None);
6040 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Pause"),
6043 if (appData.showButtonBar) {
6044 /* Always toggle, don't set. Previous code messes up when
6045 invoked while the button is pressed, as releasing it
6046 toggles the state again. */
6049 XtSetArg(args[0], XtNbackground, &oldbg);
6050 XtSetArg(args[1], XtNforeground, &oldfg);
6051 XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON),
6053 XtSetArg(args[0], XtNbackground, oldfg);
6054 XtSetArg(args[1], XtNforeground, oldbg);
6056 XtSetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
6060 wname = ModeToWidgetName(oldmode);
6061 if (wname != NULL) {
6062 XtSetArg(args[0], XtNleftBitmap, None);
6063 XtSetValues(XtNameToWidget(menuBarWidget, wname), args, 1);
6065 wname = ModeToWidgetName(gameMode);
6066 if (wname != NULL) {
6067 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6068 XtSetValues(XtNameToWidget(menuBarWidget, wname), args, 1);
6072 /* Maybe all the enables should be handled here, not just this one */
6073 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Training"),
6074 gameMode == Training || gameMode == PlayFromGameFile);
6079 * Button/menu procedures
6081 void ResetProc(w, event, prms, nprms)
6090 int LoadGamePopUp(f, gameNumber, title)
6095 cmailMsgLoaded = FALSE;
6096 if (gameNumber == 0) {
6097 int error = GameListBuild(f);
6099 DisplayError(_("Cannot build game list"), error);
6100 } else if (!ListEmpty(&gameList) &&
6101 ((ListGame *) gameList.tailPred)->number > 1) {
6102 GameListPopUp(f, title);
6108 return LoadGame(f, gameNumber, title, FALSE);
6111 void LoadGameProc(w, event, prms, nprms)
6117 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
6120 FileNamePopUp(_("Load game file name?"), "", LoadGamePopUp, "rb");
6123 void LoadNextGameProc(w, event, prms, nprms)
6132 void LoadPrevGameProc(w, event, prms, nprms)
6141 void ReloadGameProc(w, event, prms, nprms)
6150 void LoadNextPositionProc(w, event, prms, nprms)
6159 void LoadPrevPositionProc(w, event, prms, nprms)
6168 void ReloadPositionProc(w, event, prms, nprms)
6177 void LoadPositionProc(w, event, prms, nprms)
6183 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
6186 FileNamePopUp(_("Load position file name?"), "", LoadPosition, "rb");
6189 void SaveGameProc(w, event, prms, nprms)
6195 FileNamePopUp(_("Save game file name?"),
6196 DefaultFileName(appData.oldSaveStyle ? "game" : "pgn"),
6200 void SavePositionProc(w, event, prms, nprms)
6206 FileNamePopUp(_("Save position file name?"),
6207 DefaultFileName(appData.oldSaveStyle ? "pos" : "fen"),
6211 void ReloadCmailMsgProc(w, event, prms, nprms)
6217 ReloadCmailMsgEvent(FALSE);
6220 void MailMoveProc(w, event, prms, nprms)
6229 /* this variable is shared between CopyPositionProc and SendPositionSelection */
6230 static char *selected_fen_position=NULL;
6233 SendPositionSelection(Widget w, Atom *selection, Atom *target,
6234 Atom *type_return, XtPointer *value_return,
6235 unsigned long *length_return, int *format_return)
6237 char *selection_tmp;
6239 if (!selected_fen_position) return False; /* should never happen */
6240 if (*target == XA_STRING){
6241 /* note: since no XtSelectionDoneProc was registered, Xt will
6242 * automatically call XtFree on the value returned. So have to
6243 * make a copy of it allocated with XtMalloc */
6244 selection_tmp= XtMalloc(strlen(selected_fen_position)+16);
6245 strcpy(selection_tmp, selected_fen_position);
6247 *value_return=selection_tmp;
6248 *length_return=strlen(selection_tmp);
6249 *type_return=XA_STRING;
6250 *format_return = 8; /* bits per byte */
6257 /* note: when called from menu all parameters are NULL, so no clue what the
6258 * Widget which was clicked on was, or what the click event was
6260 void CopyPositionProc(w, event, prms, nprms)
6268 if (selected_fen_position) free(selected_fen_position);
6269 selected_fen_position = (char *)PositionToFEN(currentMove, NULL);
6270 if (!selected_fen_position) return;
6271 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
6273 SendPositionSelection,
6274 NULL/* lose_ownership_proc */ ,
6275 NULL/* transfer_done_proc */);
6277 free(selected_fen_position);
6278 selected_fen_position=NULL;
6282 /* function called when the data to Paste is ready */
6284 PastePositionCB(Widget w, XtPointer client_data, Atom *selection,
6285 Atom *type, XtPointer value, unsigned long *len, int *format)
6288 if (value==NULL || *len==0) return; /* nothing had been selected to copy */
6289 fenstr[*len]='\0'; /* normally this string is terminated, but be safe */
6290 EditPositionPasteFEN(fenstr);
6294 /* called when Paste Position button is pressed,
6295 * all parameters will be NULL */
6296 void PastePositionProc(w, event, prms, nprms)
6302 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
6303 /* (XtSelectionCallbackProc) */ PastePositionCB,
6304 NULL, /* client_data passed to PastePositionCB */
6306 /* better to use the time field from the event that triggered the
6307 * call to this function, but that isn't trivial to get
6315 SendGameSelection(Widget w, Atom *selection, Atom *target,
6316 Atom *type_return, XtPointer *value_return,
6317 unsigned long *length_return, int *format_return)
6319 char *selection_tmp;
6321 if (*target == XA_STRING){
6322 FILE* f = fopen(gameCopyFilename, "r");
6325 if (f == NULL) return False;
6329 selection_tmp = XtMalloc(len + 1);
6330 count = fread(selection_tmp, 1, len, f);
6332 XtFree(selection_tmp);
6335 selection_tmp[len] = NULLCHAR;
6336 *value_return = selection_tmp;
6337 *length_return = len;
6338 *type_return = XA_STRING;
6339 *format_return = 8; /* bits per byte */
6346 /* note: when called from menu all parameters are NULL, so no clue what the
6347 * Widget which was clicked on was, or what the click event was
6349 void CopyGameProc(w, event, prms, nprms)
6357 ret = SaveGameToFile(gameCopyFilename, FALSE);
6360 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
6363 NULL/* lose_ownership_proc */ ,
6364 NULL/* transfer_done_proc */);
6367 /* function called when the data to Paste is ready */
6369 PasteGameCB(Widget w, XtPointer client_data, Atom *selection,
6370 Atom *type, XtPointer value, unsigned long *len, int *format)
6373 if (value == NULL || *len == 0) {
6374 return; /* nothing had been selected to copy */
6376 f = fopen(gamePasteFilename, "w");
6378 DisplayError(_("Can't open temp file"), errno);
6381 fwrite(value, 1, *len, f);
6384 LoadGameFromFile(gamePasteFilename, 0, gamePasteFilename, TRUE);
6387 /* called when Paste Game button is pressed,
6388 * all parameters will be NULL */
6389 void PasteGameProc(w, event, prms, nprms)
6395 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
6396 /* (XtSelectionCallbackProc) */ PasteGameCB,
6397 NULL, /* client_data passed to PasteGameCB */
6399 /* better to use the time field from the event that triggered the
6400 * call to this function, but that isn't trivial to get
6410 SaveGameProc(NULL, NULL, NULL, NULL);
6414 void QuitProc(w, event, prms, nprms)
6423 void PauseProc(w, event, prms, nprms)
6433 void MachineBlackProc(w, event, prms, nprms)
6439 MachineBlackEvent();
6442 void MachineWhiteProc(w, event, prms, nprms)
6448 MachineWhiteEvent();
6451 void AnalyzeModeProc(w, event, prms, nprms)
6459 if (!first.analysisSupport) {
6460 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
6461 DisplayError(buf, 0);
6464 /* [DM] icsEngineAnalyze [HGM] This is horrible code; reverse the gameMode and isEngineAnalyze tests! */
6465 if (appData.icsActive) {
6466 if (gameMode != IcsObserving) {
6467 sprintf(buf,_("You are not observing a game"));
6468 DisplayError(buf, 0);
6470 if (appData.icsEngineAnalyze) {
6471 if (appData.debugMode)
6472 fprintf(debugFP, _("Found unexpected active ICS engine analyze \n"));
6478 /* if enable, use want disable icsEngineAnalyze */
6479 if (appData.icsEngineAnalyze) {
6484 appData.icsEngineAnalyze = TRUE;
6485 if (appData.debugMode)
6486 fprintf(debugFP, _("ICS engine analyze starting... \n"));
6488 if (!appData.showThinking)
6489 ShowThinkingProc(w,event,prms,nprms);
6494 void AnalyzeFileProc(w, event, prms, nprms)
6500 if (!first.analysisSupport) {
6502 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
6503 DisplayError(buf, 0);
6508 if (!appData.showThinking)
6509 ShowThinkingProc(w,event,prms,nprms);
6512 FileNamePopUp(_("File to analyze"), "", LoadGamePopUp, "rb");
6513 AnalysisPeriodicEvent(1);
6516 void TwoMachinesProc(w, event, prms, nprms)
6525 void IcsClientProc(w, event, prms, nprms)
6534 void EditGameProc(w, event, prms, nprms)
6543 void EditPositionProc(w, event, prms, nprms)
6549 EditPositionEvent();
6552 void TrainingProc(w, event, prms, nprms)
6561 void EditCommentProc(w, event, prms, nprms)
6568 EditCommentPopDown();
6574 void IcsInputBoxProc(w, event, prms, nprms)
6580 if (ICSInputBoxUp) {
6581 ICSInputBoxPopDown();
6587 void AcceptProc(w, event, prms, nprms)
6596 void DeclineProc(w, event, prms, nprms)
6605 void RematchProc(w, event, prms, nprms)
6614 void CallFlagProc(w, event, prms, nprms)
6623 void DrawProc(w, event, prms, nprms)
6632 void AbortProc(w, event, prms, nprms)
6641 void AdjournProc(w, event, prms, nprms)
6650 void ResignProc(w, event, prms, nprms)
6659 void AdjuWhiteProc(w, event, prms, nprms)
6665 UserAdjudicationEvent(+1);
6668 void AdjuBlackProc(w, event, prms, nprms)
6674 UserAdjudicationEvent(-1);
6677 void AdjuDrawProc(w, event, prms, nprms)
6683 UserAdjudicationEvent(0);
6686 void EnterKeyProc(w, event, prms, nprms)
6692 if (ICSInputBoxUp == True)
6696 void StopObservingProc(w, event, prms, nprms)
6702 StopObservingEvent();
6705 void StopExaminingProc(w, event, prms, nprms)
6711 StopExaminingEvent();
6715 void ForwardProc(w, event, prms, nprms)
6725 void BackwardProc(w, event, prms, nprms)
6734 void ToStartProc(w, event, prms, nprms)
6743 void ToEndProc(w, event, prms, nprms)
6752 void RevertProc(w, event, prms, nprms)
6761 void TruncateGameProc(w, event, prms, nprms)
6767 TruncateGameEvent();
6769 void RetractMoveProc(w, event, prms, nprms)
6778 void MoveNowProc(w, event, prms, nprms)
6788 void AlwaysQueenProc(w, event, prms, nprms)
6796 appData.alwaysPromoteToQueen = !appData.alwaysPromoteToQueen;
6798 if (appData.alwaysPromoteToQueen) {
6799 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6801 XtSetArg(args[0], XtNleftBitmap, None);
6803 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
6807 void AnimateDraggingProc(w, event, prms, nprms)
6815 appData.animateDragging = !appData.animateDragging;
6817 if (appData.animateDragging) {
6818 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6821 XtSetArg(args[0], XtNleftBitmap, None);
6823 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Dragging"),
6827 void AnimateMovingProc(w, event, prms, nprms)
6835 appData.animate = !appData.animate;
6837 if (appData.animate) {
6838 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6841 XtSetArg(args[0], XtNleftBitmap, None);
6843 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
6847 void AutocommProc(w, event, prms, nprms)
6855 appData.autoComment = !appData.autoComment;
6857 if (appData.autoComment) {
6858 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6860 XtSetArg(args[0], XtNleftBitmap, None);
6862 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
6867 void AutoflagProc(w, event, prms, nprms)
6875 appData.autoCallFlag = !appData.autoCallFlag;
6877 if (appData.autoCallFlag) {
6878 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6880 XtSetArg(args[0], XtNleftBitmap, None);
6882 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
6886 void AutoflipProc(w, event, prms, nprms)
6894 appData.autoFlipView = !appData.autoFlipView;
6896 if (appData.autoFlipView) {
6897 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6899 XtSetArg(args[0], XtNleftBitmap, None);
6901 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flip View"),
6905 void AutobsProc(w, event, prms, nprms)
6913 appData.autoObserve = !appData.autoObserve;
6915 if (appData.autoObserve) {
6916 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6918 XtSetArg(args[0], XtNleftBitmap, None);
6920 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
6924 void AutoraiseProc(w, event, prms, nprms)
6932 appData.autoRaiseBoard = !appData.autoRaiseBoard;
6934 if (appData.autoRaiseBoard) {
6935 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6937 XtSetArg(args[0], XtNleftBitmap, None);
6939 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Raise Board"),
6943 void AutosaveProc(w, event, prms, nprms)
6951 appData.autoSaveGames = !appData.autoSaveGames;
6953 if (appData.autoSaveGames) {
6954 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6956 XtSetArg(args[0], XtNleftBitmap, None);
6958 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
6962 void BlindfoldProc(w, event, prms, nprms)
6970 appData.blindfold = !appData.blindfold;
6972 if (appData.blindfold) {
6973 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6975 XtSetArg(args[0], XtNleftBitmap, None);
6977 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Blindfold"),
6980 DrawPosition(True, NULL);
6983 void TestLegalityProc(w, event, prms, nprms)
6991 appData.testLegality = !appData.testLegality;
6993 if (appData.testLegality) {
6994 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6996 XtSetArg(args[0], XtNleftBitmap, None);
6998 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Test Legality"),
7003 void FlashMovesProc(w, event, prms, nprms)
7011 if (appData.flashCount == 0) {
7012 appData.flashCount = 3;
7014 appData.flashCount = -appData.flashCount;
7017 if (appData.flashCount > 0) {
7018 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7020 XtSetArg(args[0], XtNleftBitmap, None);
7022 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flash Moves"),
7026 void FlipViewProc(w, event, prms, nprms)
7032 flipView = !flipView;
7033 DrawPosition(True, NULL);
7036 void GetMoveListProc(w, event, prms, nprms)
7044 appData.getMoveList = !appData.getMoveList;
7046 if (appData.getMoveList) {
7047 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7050 XtSetArg(args[0], XtNleftBitmap, None);
7052 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
7057 void HighlightDraggingProc(w, event, prms, nprms)
7065 appData.highlightDragging = !appData.highlightDragging;
7067 if (appData.highlightDragging) {
7068 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7070 XtSetArg(args[0], XtNleftBitmap, None);
7072 XtSetValues(XtNameToWidget(menuBarWidget,
7073 "menuOptions.Highlight Dragging"), args, 1);
7077 void HighlightLastMoveProc(w, event, prms, nprms)
7085 appData.highlightLastMove = !appData.highlightLastMove;
7087 if (appData.highlightLastMove) {
7088 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7090 XtSetArg(args[0], XtNleftBitmap, None);
7092 XtSetValues(XtNameToWidget(menuBarWidget,
7093 "menuOptions.Highlight Last Move"), args, 1);
7096 void IcsAlarmProc(w, event, prms, nprms)
7104 appData.icsAlarm = !appData.icsAlarm;
7106 if (appData.icsAlarm) {
7107 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7109 XtSetArg(args[0], XtNleftBitmap, None);
7111 XtSetValues(XtNameToWidget(menuBarWidget,
7112 "menuOptions.ICS Alarm"), args, 1);
7115 void MoveSoundProc(w, event, prms, nprms)
7123 appData.ringBellAfterMoves = !appData.ringBellAfterMoves;
7125 if (appData.ringBellAfterMoves) {
7126 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7128 XtSetArg(args[0], XtNleftBitmap, None);
7130 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
7135 void OldSaveStyleProc(w, event, prms, nprms)
7143 appData.oldSaveStyle = !appData.oldSaveStyle;
7145 if (appData.oldSaveStyle) {
7146 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7148 XtSetArg(args[0], XtNleftBitmap, None);
7150 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Old Save Style"),
7154 void PeriodicUpdatesProc(w, event, prms, nprms)
7162 PeriodicUpdatesEvent(!appData.periodicUpdates);
7164 if (appData.periodicUpdates) {
7165 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7167 XtSetArg(args[0], XtNleftBitmap, None);
7169 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Periodic Updates"),
7173 void PonderNextMoveProc(w, event, prms, nprms)
7181 PonderNextMoveEvent(!appData.ponderNextMove);
7183 if (appData.ponderNextMove) {
7184 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7186 XtSetArg(args[0], XtNleftBitmap, None);
7188 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Ponder Next Move"),
7192 void PopupExitMessageProc(w, event, prms, nprms)
7200 appData.popupExitMessage = !appData.popupExitMessage;
7202 if (appData.popupExitMessage) {
7203 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7205 XtSetArg(args[0], XtNleftBitmap, None);
7207 XtSetValues(XtNameToWidget(menuBarWidget,
7208 "menuOptions.Popup Exit Message"), args, 1);
7211 void PopupMoveErrorsProc(w, event, prms, nprms)
7219 appData.popupMoveErrors = !appData.popupMoveErrors;
7221 if (appData.popupMoveErrors) {
7222 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7224 XtSetArg(args[0], XtNleftBitmap, None);
7226 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Popup Move Errors"),
7230 void PremoveProc(w, event, prms, nprms)
7238 appData.premove = !appData.premove;
7240 if (appData.premove) {
7241 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7243 XtSetArg(args[0], XtNleftBitmap, None);
7245 XtSetValues(XtNameToWidget(menuBarWidget,
7246 "menuOptions.Premove"), args, 1);
7249 void QuietPlayProc(w, event, prms, nprms)
7257 appData.quietPlay = !appData.quietPlay;
7259 if (appData.quietPlay) {
7260 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7262 XtSetArg(args[0], XtNleftBitmap, None);
7264 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Quiet Play"),
7268 void ShowCoordsProc(w, event, prms, nprms)
7276 appData.showCoords = !appData.showCoords;
7278 if (appData.showCoords) {
7279 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7281 XtSetArg(args[0], XtNleftBitmap, None);
7283 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
7286 DrawPosition(True, NULL);
7289 void ShowThinkingProc(w, event, prms, nprms)
7297 appData.showThinking = !appData.showThinking; // [HGM] thinking: tken out of ShowThinkingEvent
7298 ShowThinkingEvent();
7301 void HideThinkingProc(w, event, prms, nprms)
7309 appData.hideThinkingFromHuman = !appData.hideThinkingFromHuman; // [HGM] thinking: tken out of ShowThinkingEvent
7310 ShowThinkingEvent();
7312 if (appData.hideThinkingFromHuman) {
7313 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7315 XtSetArg(args[0], XtNleftBitmap, None);
7317 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
7321 void InfoProc(w, event, prms, nprms)
7328 snprintf(buf, sizeof(buf), "xterm -e info --directory %s --directory . -f %s &",
7333 void ManProc(w, event, prms, nprms)
7341 if (nprms && *nprms > 0)
7345 snprintf(buf, sizeof(buf), "xterm -e man %s &", name);
7349 void HintProc(w, event, prms, nprms)
7358 void BookProc(w, event, prms, nprms)
7367 void AboutProc(w, event, prms, nprms)
7375 char *zippy = " (with Zippy code)";
7379 snprintf(buf, sizeof(buf), "%s%s\n\n%s\n%s\n%s\n\n%s%s\n%s",
7380 programVersion, zippy,
7381 "Copyright 1991 Digital Equipment Corporation",
7382 "Enhancements Copyright 1992-2009 Free Software Foundation",
7383 "Enhancements Copyright 2005 Alessandro Scotti",
7384 PACKAGE, " is free software and carries NO WARRANTY;",
7385 "see the file COPYING for more information.");
7386 ErrorPopUp(_("About XBoard"), buf, FALSE);
7389 void DebugProc(w, event, prms, nprms)
7395 appData.debugMode = !appData.debugMode;
7398 void AboutGameProc(w, event, prms, nprms)
7407 void NothingProc(w, event, prms, nprms)
7416 void Iconify(w, event, prms, nprms)
7425 XtSetArg(args[0], XtNiconic, True);
7426 XtSetValues(shellWidget, args, 1);
7429 void DisplayMessage(message, extMessage)
7430 char *message, *extMessage;
7432 /* display a message in the message widget */
7441 snprintf(buf, sizeof(buf), "%s %s", message, extMessage);
7446 message = extMessage;
7450 /* need to test if messageWidget already exists, since this function
7451 can also be called during the startup, if for example a Xresource
7452 is not set up correctly */
7455 XtSetArg(arg, XtNlabel, message);
7456 XtSetValues(messageWidget, &arg, 1);
7462 void DisplayTitle(text)
7467 char title[MSG_SIZ];
7470 if (text == NULL) text = "";
7472 if (appData.titleInWindow) {
7474 XtSetArg(args[i], XtNlabel, text); i++;
7475 XtSetValues(titleWidget, args, i);
7478 if (*text != NULLCHAR) {
7480 strcpy(title, text);
7481 } else if (appData.icsActive) {
7482 snprintf(icon, sizeof(icon), "%s", appData.icsHost);
7483 snprintf(title, sizeof(title), "%s: %s", programName, appData.icsHost);
7484 } else if (appData.cmailGameName[0] != NULLCHAR) {
7485 snprintf(icon, sizeof(icon), "%s", "CMail");
7486 snprintf(title,sizeof(title), "%s: %s", programName, "CMail");
7488 // [HGM] license: This stuff should really be done in back-end, but WinBoard already had a pop-up for it
7489 } else if (gameInfo.variant == VariantGothic) {
7490 strcpy(icon, programName);
7491 strcpy(title, GOTHIC);
7494 } else if (gameInfo.variant == VariantFalcon) {
7495 strcpy(icon, programName);
7496 strcpy(title, FALCON);
7498 } else if (appData.noChessProgram) {
7499 strcpy(icon, programName);
7500 strcpy(title, programName);
7502 strcpy(icon, first.tidy);
7503 snprintf(title,sizeof(title), "%s: %s", programName, first.tidy);
7506 XtSetArg(args[i], XtNiconName, (XtArgVal) icon); i++;
7507 XtSetArg(args[i], XtNtitle, (XtArgVal) title); i++;
7508 XtSetValues(shellWidget, args, i);
7512 void DisplayError(message, error)
7519 if (appData.debugMode || appData.matchMode) {
7520 fprintf(stderr, "%s: %s\n", programName, message);
7523 if (appData.debugMode || appData.matchMode) {
7524 fprintf(stderr, "%s: %s: %s\n",
7525 programName, message, strerror(error));
7527 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
7530 ErrorPopUp(_("Error"), message, FALSE);
7534 void DisplayMoveError(message)
7539 DrawPosition(FALSE, NULL);
7540 if (appData.debugMode || appData.matchMode) {
7541 fprintf(stderr, "%s: %s\n", programName, message);
7543 if (appData.popupMoveErrors) {
7544 ErrorPopUp(_("Error"), message, FALSE);
7546 DisplayMessage(message, "");
7551 void DisplayFatalError(message, error, status)
7557 errorExitStatus = status;
7559 fprintf(stderr, "%s: %s\n", programName, message);
7561 fprintf(stderr, "%s: %s: %s\n",
7562 programName, message, strerror(error));
7563 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
7566 if (appData.popupExitMessage && boardWidget && XtIsRealized(boardWidget)) {
7567 ErrorPopUp(status ? _("Fatal Error") : _("Exiting"), message, TRUE);
7573 void DisplayInformation(message)
7577 ErrorPopUp(_("Information"), message, TRUE);
7580 void DisplayNote(message)
7584 ErrorPopUp(_("Note"), message, FALSE);
7588 NullXErrorCheck(dpy, error_event)
7590 XErrorEvent *error_event;
7595 void DisplayIcsInteractionTitle(message)
7598 if (oldICSInteractionTitle == NULL) {
7599 /* Magic to find the old window title, adapted from vim */
7600 char *wina = getenv("WINDOWID");
7602 Window win = (Window) atoi(wina);
7603 Window root, parent, *children;
7604 unsigned int nchildren;
7605 int (*oldHandler)() = XSetErrorHandler(NullXErrorCheck);
7607 if (XFetchName(xDisplay, win, &oldICSInteractionTitle)) break;
7608 if (!XQueryTree(xDisplay, win, &root, &parent,
7609 &children, &nchildren)) break;
7610 if (children) XFree((void *)children);
7611 if (parent == root || parent == 0) break;
7614 XSetErrorHandler(oldHandler);
7616 if (oldICSInteractionTitle == NULL) {
7617 oldICSInteractionTitle = "xterm";
7620 printf("\033]0;%s\007", message);
7624 char pendingReplyPrefix[MSG_SIZ];
7625 ProcRef pendingReplyPR;
7627 void AskQuestionProc(w, event, prms, nprms)
7634 fprintf(stderr, _("AskQuestionProc needed 4 parameters, got %d\n"),
7638 AskQuestionEvent(prms[0], prms[1], prms[2], prms[3]);
7641 void AskQuestionPopDown()
7643 if (!askQuestionUp) return;
7644 XtPopdown(askQuestionShell);
7645 XtDestroyWidget(askQuestionShell);
7646 askQuestionUp = False;
7649 void AskQuestionReplyAction(w, event, prms, nprms)
7659 reply = XawDialogGetValueString(w = XtParent(w));
7660 strcpy(buf, pendingReplyPrefix);
7661 if (*buf) strcat(buf, " ");
7664 OutputToProcess(pendingReplyPR, buf, strlen(buf), &err);
7665 AskQuestionPopDown();
7667 if (err) DisplayFatalError(_("Error writing to chess program"), err, 0);
7670 void AskQuestionCallback(w, client_data, call_data)
7672 XtPointer client_data, call_data;
7677 XtSetArg(args[0], XtNlabel, &name);
7678 XtGetValues(w, args, 1);
7680 if (strcmp(name, _("cancel")) == 0) {
7681 AskQuestionPopDown();
7683 AskQuestionReplyAction(w, NULL, NULL, NULL);
7687 void AskQuestion(title, question, replyPrefix, pr)
7688 char *title, *question, *replyPrefix;
7692 Widget popup, layout, dialog, edit;
7698 strcpy(pendingReplyPrefix, replyPrefix);
7699 pendingReplyPR = pr;
7702 XtSetArg(args[i], XtNresizable, True); i++;
7703 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
7704 askQuestionShell = popup =
7705 XtCreatePopupShell(title, transientShellWidgetClass,
7706 shellWidget, args, i);
7709 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
7710 layoutArgs, XtNumber(layoutArgs));
7713 XtSetArg(args[i], XtNlabel, question); i++;
7714 XtSetArg(args[i], XtNvalue, ""); i++;
7715 XtSetArg(args[i], XtNborderWidth, 0); i++;
7716 dialog = XtCreateManagedWidget("question", dialogWidgetClass,
7719 XawDialogAddButton(dialog, _("enter"), AskQuestionCallback,
7720 (XtPointer) dialog);
7721 XawDialogAddButton(dialog, _("cancel"), AskQuestionCallback,
7722 (XtPointer) dialog);
7724 XtRealizeWidget(popup);
7725 CatchDeleteWindow(popup, "AskQuestionPopDown");
7727 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
7728 &x, &y, &win_x, &win_y, &mask);
7730 XtSetArg(args[0], XtNx, x - 10);
7731 XtSetArg(args[1], XtNy, y - 30);
7732 XtSetValues(popup, args, 2);
7734 XtPopup(popup, XtGrabExclusive);
7735 askQuestionUp = True;
7737 edit = XtNameToWidget(dialog, "*value");
7738 XtSetKeyboardFocus(popup, edit);
7746 if (*name == NULLCHAR) {
7748 } else if (strcmp(name, "$") == 0) {
7749 putc(BELLCHAR, stderr);
7752 snprintf(buf, sizeof(buf), "%s '%s' &", appData.soundProgram, name);
7760 PlaySound(appData.soundMove);
7766 PlaySound(appData.soundIcsWin);
7772 PlaySound(appData.soundIcsLoss);
7778 PlaySound(appData.soundIcsDraw);
7782 PlayIcsUnfinishedSound()
7784 PlaySound(appData.soundIcsUnfinished);
7790 PlaySound(appData.soundIcsAlarm);
7796 system("stty echo");
7802 system("stty -echo");
7806 Colorize(cc, continuation)
7811 int count, outCount, error;
7813 if (textColors[(int)cc].bg > 0) {
7814 if (textColors[(int)cc].fg > 0) {
7815 sprintf(buf, "\033[0;%d;%d;%dm", textColors[(int)cc].attr,
7816 textColors[(int)cc].fg, textColors[(int)cc].bg);
7818 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
7819 textColors[(int)cc].bg);
7822 if (textColors[(int)cc].fg > 0) {
7823 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
7824 textColors[(int)cc].fg);
7826 sprintf(buf, "\033[0;%dm", textColors[(int)cc].attr);
7829 count = strlen(buf);
7830 outCount = OutputToProcess(NoProc, buf, count, &error);
7831 if (outCount < count) {
7832 DisplayFatalError(_("Error writing to display"), error, 1);
7835 if (continuation) return;
7838 PlaySound(appData.soundShout);
7841 PlaySound(appData.soundSShout);
7844 PlaySound(appData.soundChannel1);
7847 PlaySound(appData.soundChannel);
7850 PlaySound(appData.soundKibitz);
7853 PlaySound(appData.soundTell);
7855 case ColorChallenge:
7856 PlaySound(appData.soundChallenge);
7859 PlaySound(appData.soundRequest);
7862 PlaySound(appData.soundSeek);
7873 return getpwuid(getuid())->pw_name;
7876 static char *ExpandPathName(path)
7879 static char static_buf[2000];
7880 char *d, *s, buf[2000];
7886 while (*s && isspace(*s))
7895 if (*(s+1) == '/') {
7896 strcpy(d, getpwuid(getuid())->pw_dir);
7901 *strchr(buf, '/') = 0;
7902 pwd = getpwnam(buf);
7905 fprintf(stderr, _("ERROR: Unknown user %s (in path %s)\n"),
7909 strcpy(d, pwd->pw_dir);
7910 strcat(d, strchr(s+1, '/'));
7921 static char host_name[MSG_SIZ];
7923 #if HAVE_GETHOSTNAME
7924 gethostname(host_name, MSG_SIZ);
7926 #else /* not HAVE_GETHOSTNAME */
7927 # if HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H
7928 sysinfo(SI_HOSTNAME, host_name, MSG_SIZ);
7930 # else /* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
7932 # endif/* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
7933 #endif /* not HAVE_GETHOSTNAME */
7936 XtIntervalId delayedEventTimerXID = 0;
7937 DelayedEventCallback delayedEventCallback = 0;
7942 delayedEventTimerXID = 0;
7943 delayedEventCallback();
7947 ScheduleDelayedEvent(cb, millisec)
7948 DelayedEventCallback cb; long millisec;
7950 if(delayedEventTimerXID && delayedEventCallback == cb)
7951 // [HGM] alive: replace, rather than add or flush identical event
7952 XtRemoveTimeOut(delayedEventTimerXID);
7953 delayedEventCallback = cb;
7954 delayedEventTimerXID =
7955 XtAppAddTimeOut(appContext, millisec,
7956 (XtTimerCallbackProc) FireDelayedEvent, (XtPointer) 0);
7959 DelayedEventCallback
7962 if (delayedEventTimerXID) {
7963 return delayedEventCallback;
7970 CancelDelayedEvent()
7972 if (delayedEventTimerXID) {
7973 XtRemoveTimeOut(delayedEventTimerXID);
7974 delayedEventTimerXID = 0;
7978 XtIntervalId loadGameTimerXID = 0;
7980 int LoadGameTimerRunning()
7982 return loadGameTimerXID != 0;
7985 int StopLoadGameTimer()
7987 if (loadGameTimerXID != 0) {
7988 XtRemoveTimeOut(loadGameTimerXID);
7989 loadGameTimerXID = 0;
7997 LoadGameTimerCallback(arg, id)
8001 loadGameTimerXID = 0;
8006 StartLoadGameTimer(millisec)
8010 XtAppAddTimeOut(appContext, millisec,
8011 (XtTimerCallbackProc) LoadGameTimerCallback,
8015 XtIntervalId analysisClockXID = 0;
8018 AnalysisClockCallback(arg, id)
8022 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile
8023 || appData.icsEngineAnalyze) { // [DM]
8024 AnalysisPeriodicEvent(0);
8025 StartAnalysisClock();
8030 StartAnalysisClock()
8033 XtAppAddTimeOut(appContext, 2000,
8034 (XtTimerCallbackProc) AnalysisClockCallback,
8038 XtIntervalId clockTimerXID = 0;
8040 int ClockTimerRunning()
8042 return clockTimerXID != 0;
8045 int StopClockTimer()
8047 if (clockTimerXID != 0) {
8048 XtRemoveTimeOut(clockTimerXID);
8057 ClockTimerCallback(arg, id)
8066 StartClockTimer(millisec)
8070 XtAppAddTimeOut(appContext, millisec,
8071 (XtTimerCallbackProc) ClockTimerCallback,
8076 DisplayTimerLabel(w, color, timer, highlight)
8085 /* check for low time warning */
8086 Pixel foregroundOrWarningColor = timerForegroundPixel;
8089 appData.lowTimeWarning &&
8090 (timer / 1000) < appData.icsAlarmTime)
8091 foregroundOrWarningColor = lowTimeWarningColor;
8093 if (appData.clockMode) {
8094 sprintf(buf, "%s: %s", color, TimeString(timer));
8095 XtSetArg(args[0], XtNlabel, buf);
8097 sprintf(buf, "%s ", color);
8098 XtSetArg(args[0], XtNlabel, buf);
8103 XtSetArg(args[1], XtNbackground, foregroundOrWarningColor);
8104 XtSetArg(args[2], XtNforeground, timerBackgroundPixel);
8106 XtSetArg(args[1], XtNbackground, timerBackgroundPixel);
8107 XtSetArg(args[2], XtNforeground, foregroundOrWarningColor);
8110 XtSetValues(w, args, 3);
8114 DisplayWhiteClock(timeRemaining, highlight)
8120 if(appData.noGUI) return;
8121 DisplayTimerLabel(whiteTimerWidget, _("White"), timeRemaining, highlight);
8122 if (highlight && iconPixmap == bIconPixmap) {
8123 iconPixmap = wIconPixmap;
8124 XtSetArg(args[0], XtNiconPixmap, iconPixmap);
8125 XtSetValues(shellWidget, args, 1);
8130 DisplayBlackClock(timeRemaining, highlight)
8136 if(appData.noGUI) return;
8137 DisplayTimerLabel(blackTimerWidget, _("Black"), timeRemaining, highlight);
8138 if (highlight && iconPixmap == wIconPixmap) {
8139 iconPixmap = bIconPixmap;
8140 XtSetArg(args[0], XtNiconPixmap, iconPixmap);
8141 XtSetValues(shellWidget, args, 1);
8159 int StartChildProcess(cmdLine, dir, pr)
8166 int to_prog[2], from_prog[2];
8170 if (appData.debugMode) {
8171 fprintf(stderr, "StartChildProcess (dir=\"%s\") %s\n",dir, cmdLine);
8174 /* We do NOT feed the cmdLine to the shell; we just
8175 parse it into blank-separated arguments in the
8176 most simple-minded way possible.
8179 strcpy(buf, cmdLine);
8184 if (p == NULL) break;
8189 SetUpChildIO(to_prog, from_prog);
8192 signal(SIGWINCH, TermSizeSigHandler);
8195 if ((pid = fork()) == 0) {
8197 // [HGM] PSWBTM: made order resistant against case where fd of created pipe was 0 or 1
8198 close(to_prog[1]); // first close the unused pipe ends
8199 close(from_prog[0]);
8200 dup2(to_prog[0], 0); // to_prog was created first, nd is the only one to use 0 or 1
8201 dup2(from_prog[1], 1);
8202 if(to_prog[0] >= 2) close(to_prog[0]); // if 0 or 1, the dup2 already cosed the original
8203 close(from_prog[1]); // and closing again loses one of the pipes!
8204 if(fileno(stderr) >= 2) // better safe than sorry...
8205 dup2(1, fileno(stderr)); /* force stderr to the pipe */
8207 if (dir[0] != NULLCHAR && chdir(dir) != 0) {
8212 nice(appData.niceEngines); // [HGM] nice: adjust priority of engine proc
8214 execvp(argv[0], argv);
8216 /* If we get here, exec failed */
8221 /* Parent process */
8223 close(from_prog[1]);
8225 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8228 cp->fdFrom = from_prog[0];
8229 cp->fdTo = to_prog[1];
8234 // [HGM] kill: implement the 'hard killing' of AS's Winboard_x
8235 static RETSIGTYPE AlarmCallBack(int n)
8241 DestroyChildProcess(pr, signalType)
8245 ChildProc *cp = (ChildProc *) pr;
8247 if (cp->kind != CPReal) return;
8249 if (signalType == 10) { // [HGM] kill: if it does not terminate in 3 sec, kill
8250 signal(SIGALRM, AlarmCallBack);
8252 if(wait((int *) 0) == -1) { // process does not terminate on its own accord
8253 kill(cp->pid, SIGKILL); // kill it forcefully
8254 wait((int *) 0); // and wait again
8258 kill(cp->pid, signalType == 9 ? SIGKILL : SIGTERM); // [HGM] kill: use hard kill if so requested
8260 /* Process is exiting either because of the kill or because of
8261 a quit command sent by the backend; either way, wait for it to die.
8270 InterruptChildProcess(pr)
8273 ChildProc *cp = (ChildProc *) pr;
8275 if (cp->kind != CPReal) return;
8276 (void) kill(cp->pid, SIGINT); /* stop it thinking */
8279 int OpenTelnet(host, port, pr)
8284 char cmdLine[MSG_SIZ];
8286 if (port[0] == NULLCHAR) {
8287 snprintf(cmdLine, sizeof(cmdLine), "%s %s", appData.telnetProgram, host);
8289 snprintf(cmdLine, sizeof(cmdLine), "%s %s %s", appData.telnetProgram, host, port);
8291 return StartChildProcess(cmdLine, "", pr);
8294 int OpenTCP(host, port, pr)
8300 DisplayFatalError(_("Socket support is not configured in"), 0, 2);
8301 #else /* !OMIT_SOCKETS */
8303 struct sockaddr_in sa;
8305 unsigned short uport;
8308 if ((s = socket(AF_INET, SOCK_STREAM, 6)) < 0) {
8312 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
8313 sa.sin_family = AF_INET;
8314 sa.sin_addr.s_addr = INADDR_ANY;
8315 uport = (unsigned short) 0;
8316 sa.sin_port = htons(uport);
8317 if (bind(s, (struct sockaddr *) &sa, sizeof(struct sockaddr_in)) < 0) {
8321 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
8322 if (!(hp = gethostbyname(host))) {
8324 if (sscanf(host, "%d.%d.%d.%d", &b0, &b1, &b2, &b3) == 4) {
8325 hp = (struct hostent *) calloc(1, sizeof(struct hostent));
8326 hp->h_addrtype = AF_INET;
8328 hp->h_addr_list = (char **) calloc(2, sizeof(char *));
8329 hp->h_addr_list[0] = (char *) malloc(4);
8330 hp->h_addr_list[0][0] = b0;
8331 hp->h_addr_list[0][1] = b1;
8332 hp->h_addr_list[0][2] = b2;
8333 hp->h_addr_list[0][3] = b3;
8338 sa.sin_family = hp->h_addrtype;
8339 uport = (unsigned short) atoi(port);
8340 sa.sin_port = htons(uport);
8341 memcpy((char *) &sa.sin_addr, hp->h_addr, hp->h_length);
8343 if (connect(s, (struct sockaddr *) &sa,
8344 sizeof(struct sockaddr_in)) < 0) {
8348 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8355 #endif /* !OMIT_SOCKETS */
8360 int OpenCommPort(name, pr)
8367 fd = open(name, 2, 0);
8368 if (fd < 0) return errno;
8370 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8380 int OpenLoopback(pr)
8386 SetUpChildIO(to, from);
8388 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8391 cp->fdFrom = to[0]; /* note not from[0]; we are doing a loopback */
8398 int OpenRcmd(host, user, cmd, pr)
8399 char *host, *user, *cmd;
8402 DisplayFatalError(_("internal rcmd not implemented for Unix"), 0, 1);
8406 #define INPUT_SOURCE_BUF_SIZE 8192
8415 char buf[INPUT_SOURCE_BUF_SIZE];
8420 DoInputCallback(closure, source, xid)
8425 InputSource *is = (InputSource *) closure;
8430 if (is->lineByLine) {
8431 count = read(is->fd, is->unused,
8432 INPUT_SOURCE_BUF_SIZE - (is->unused - is->buf));
8434 (is->func)(is, is->closure, is->buf, count, count ? errno : 0);
8437 is->unused += count;
8439 while (p < is->unused) {
8440 q = memchr(p, '\n', is->unused - p);
8441 if (q == NULL) break;
8443 (is->func)(is, is->closure, p, q - p, 0);
8447 while (p < is->unused) {
8452 count = read(is->fd, is->buf, INPUT_SOURCE_BUF_SIZE);
8457 (is->func)(is, is->closure, is->buf, count, error);
8461 InputSourceRef AddInputSource(pr, lineByLine, func, closure)
8468 ChildProc *cp = (ChildProc *) pr;
8470 is = (InputSource *) calloc(1, sizeof(InputSource));
8471 is->lineByLine = lineByLine;
8475 is->fd = fileno(stdin);
8477 is->kind = cp->kind;
8478 is->fd = cp->fdFrom;
8481 is->unused = is->buf;
8484 is->xid = XtAppAddInput(appContext, is->fd,
8485 (XtPointer) (XtInputReadMask),
8486 (XtInputCallbackProc) DoInputCallback,
8488 is->closure = closure;
8489 return (InputSourceRef) is;
8493 RemoveInputSource(isr)
8496 InputSource *is = (InputSource *) isr;
8498 if (is->xid == 0) return;
8499 XtRemoveInput(is->xid);
8503 int OutputToProcess(pr, message, count, outError)
8509 ChildProc *cp = (ChildProc *) pr;
8513 outCount = fwrite(message, 1, count, stdout);
8515 outCount = write(cp->fdTo, message, count);
8525 /* Output message to process, with "ms" milliseconds of delay
8526 between each character. This is needed when sending the logon
8527 script to ICC, which for some reason doesn't like the
8528 instantaneous send. */
8529 int OutputToProcessDelayed(pr, message, count, outError, msdelay)
8536 ChildProc *cp = (ChildProc *) pr;
8541 r = write(cp->fdTo, message++, 1);
8554 /**** Animation code by Hugh Fisher, DCS, ANU.
8556 Known problem: if a window overlapping the board is
8557 moved away while a piece is being animated underneath,
8558 the newly exposed area won't be updated properly.
8559 I can live with this.
8561 Known problem: if you look carefully at the animation
8562 of pieces in mono mode, they are being drawn as solid
8563 shapes without interior detail while moving. Fixing
8564 this would be a major complication for minimal return.
8567 /* Masks for XPM pieces. Black and white pieces can have
8568 different shapes, but in the interest of retaining my
8569 sanity pieces must have the same outline on both light
8570 and dark squares, and all pieces must use the same
8571 background square colors/images. */
8573 static int xpmDone = 0;
8576 CreateAnimMasks (pieceDepth)
8583 unsigned long plane;
8586 /* Need a bitmap just to get a GC with right depth */
8587 buf = XCreatePixmap(xDisplay, xBoardWindow,
8589 values.foreground = 1;
8590 values.background = 0;
8591 /* Don't use XtGetGC, not read only */
8592 maskGC = XCreateGC(xDisplay, buf,
8593 GCForeground | GCBackground, &values);
8594 XFreePixmap(xDisplay, buf);
8596 buf = XCreatePixmap(xDisplay, xBoardWindow,
8597 squareSize, squareSize, pieceDepth);
8598 values.foreground = XBlackPixel(xDisplay, xScreen);
8599 values.background = XWhitePixel(xDisplay, xScreen);
8600 bufGC = XCreateGC(xDisplay, buf,
8601 GCForeground | GCBackground, &values);
8603 for (piece = WhitePawn; piece <= BlackKing; piece++) {
8604 /* Begin with empty mask */
8605 if(!xpmDone) // [HGM] pieces: keep using existing
8606 xpmMask[piece] = XCreatePixmap(xDisplay, xBoardWindow,
8607 squareSize, squareSize, 1);
8608 XSetFunction(xDisplay, maskGC, GXclear);
8609 XFillRectangle(xDisplay, xpmMask[piece], maskGC,
8610 0, 0, squareSize, squareSize);
8612 /* Take a copy of the piece */
8617 XSetFunction(xDisplay, bufGC, GXcopy);
8618 XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % (int)BlackPawn],
8620 0, 0, squareSize, squareSize, 0, 0);
8622 /* XOR the background (light) over the piece */
8623 XSetFunction(xDisplay, bufGC, GXxor);
8625 XCopyArea(xDisplay, xpmLightSquare, buf, bufGC,
8626 0, 0, squareSize, squareSize, 0, 0);
8628 XSetForeground(xDisplay, bufGC, lightSquareColor);
8629 XFillRectangle(xDisplay, buf, bufGC, 0, 0, squareSize, squareSize);
8632 /* We now have an inverted piece image with the background
8633 erased. Construct mask by just selecting all the non-zero
8634 pixels - no need to reconstruct the original image. */
8635 XSetFunction(xDisplay, maskGC, GXor);
8637 /* Might be quicker to download an XImage and create bitmap
8638 data from it rather than this N copies per piece, but it
8639 only takes a fraction of a second and there is a much
8640 longer delay for loading the pieces. */
8641 for (n = 0; n < pieceDepth; n ++) {
8642 XCopyPlane(xDisplay, buf, xpmMask[piece], maskGC,
8643 0, 0, squareSize, squareSize,
8649 XFreePixmap(xDisplay, buf);
8650 XFreeGC(xDisplay, bufGC);
8651 XFreeGC(xDisplay, maskGC);
8655 InitAnimState (anim, info)
8657 XWindowAttributes * info;
8662 /* Each buffer is square size, same depth as window */
8663 anim->saveBuf = XCreatePixmap(xDisplay, xBoardWindow,
8664 squareSize, squareSize, info->depth);
8665 anim->newBuf = XCreatePixmap(xDisplay, xBoardWindow,
8666 squareSize, squareSize, info->depth);
8668 /* Create a plain GC for blitting */
8669 mask = GCForeground | GCBackground | GCFunction |
8670 GCPlaneMask | GCGraphicsExposures;
8671 values.foreground = XBlackPixel(xDisplay, xScreen);
8672 values.background = XWhitePixel(xDisplay, xScreen);
8673 values.function = GXcopy;
8674 values.plane_mask = AllPlanes;
8675 values.graphics_exposures = False;
8676 anim->blitGC = XCreateGC(xDisplay, xBoardWindow, mask, &values);
8678 /* Piece will be copied from an existing context at
8679 the start of each new animation/drag. */
8680 anim->pieceGC = XCreateGC(xDisplay, xBoardWindow, 0, &values);
8682 /* Outline will be a read-only copy of an existing */
8683 anim->outlineGC = None;
8689 static VariantClass old = (VariantClass) -1; // [HGM] pieces: redo every time variant changes
8690 XWindowAttributes info;
8692 if (xpmDone && gameInfo.variant == old) return;
8693 if(xpmDone) old = gameInfo.variant; // first time pieces might not be created yet
8694 XGetWindowAttributes(xDisplay, xBoardWindow, &info);
8696 InitAnimState(&game, &info);
8697 InitAnimState(&player, &info);
8699 /* For XPM pieces, we need bitmaps to use as masks. */
8701 CreateAnimMasks(info.depth);
8707 static Boolean frameWaiting;
8709 static RETSIGTYPE FrameAlarm (sig)
8712 frameWaiting = False;
8713 /* In case System-V style signals. Needed?? */
8714 signal(SIGALRM, FrameAlarm);
8721 struct itimerval delay;
8723 XSync(xDisplay, False);
8726 frameWaiting = True;
8727 signal(SIGALRM, FrameAlarm);
8728 delay.it_interval.tv_sec =
8729 delay.it_value.tv_sec = time / 1000;
8730 delay.it_interval.tv_usec =
8731 delay.it_value.tv_usec = (time % 1000) * 1000;
8732 setitimer(ITIMER_REAL, &delay, NULL);
8733 while (frameWaiting) pause();
8734 delay.it_interval.tv_sec = delay.it_value.tv_sec = 0;
8735 delay.it_interval.tv_usec = delay.it_value.tv_usec = 0;
8736 setitimer(ITIMER_REAL, &delay, NULL);
8746 XSync(xDisplay, False);
8748 usleep(time * 1000);
8753 /* Convert board position to corner of screen rect and color */
8756 ScreenSquare(column, row, pt, color)
8757 int column; int row; XPoint * pt; int * color;
8760 pt->x = lineGap + ((BOARD_WIDTH-1)-column) * (squareSize + lineGap);
8761 pt->y = lineGap + row * (squareSize + lineGap);
8763 pt->x = lineGap + column * (squareSize + lineGap);
8764 pt->y = lineGap + ((BOARD_HEIGHT-1)-row) * (squareSize + lineGap);
8766 *color = SquareColor(row, column);
8769 /* Convert window coords to square */
8772 BoardSquare(x, y, column, row)
8773 int x; int y; int * column; int * row;
8775 *column = EventToSquare(x, BOARD_WIDTH);
8776 if (flipView && *column >= 0)
8777 *column = BOARD_WIDTH - 1 - *column;
8778 *row = EventToSquare(y, BOARD_HEIGHT);
8779 if (!flipView && *row >= 0)
8780 *row = BOARD_HEIGHT - 1 - *row;
8785 #undef Max /* just in case */
8787 #define Max(a, b) ((a) > (b) ? (a) : (b))
8788 #define Min(a, b) ((a) < (b) ? (a) : (b))
8791 SetRect(rect, x, y, width, height)
8792 XRectangle * rect; int x; int y; int width; int height;
8796 rect->width = width;
8797 rect->height = height;
8800 /* Test if two frames overlap. If they do, return
8801 intersection rect within old and location of
8802 that rect within new. */
8805 Intersect(old, new, size, area, pt)
8806 XPoint * old; XPoint * new;
8807 int size; XRectangle * area; XPoint * pt;
8809 if (old->x > new->x + size || new->x > old->x + size ||
8810 old->y > new->y + size || new->y > old->y + size) {
8813 SetRect(area, Max(new->x - old->x, 0), Max(new->y - old->y, 0),
8814 size - abs(old->x - new->x), size - abs(old->y - new->y));
8815 pt->x = Max(old->x - new->x, 0);
8816 pt->y = Max(old->y - new->y, 0);
8821 /* For two overlapping frames, return the rect(s)
8822 in the old that do not intersect with the new. */
8825 CalcUpdateRects(old, new, size, update, nUpdates)
8826 XPoint * old; XPoint * new; int size;
8827 XRectangle update[]; int * nUpdates;
8831 /* If old = new (shouldn't happen) then nothing to draw */
8832 if (old->x == new->x && old->y == new->y) {
8836 /* Work out what bits overlap. Since we know the rects
8837 are the same size we don't need a full intersect calc. */
8839 /* Top or bottom edge? */
8840 if (new->y > old->y) {
8841 SetRect(&(update[count]), old->x, old->y, size, new->y - old->y);
8843 } else if (old->y > new->y) {
8844 SetRect(&(update[count]), old->x, old->y + size - (old->y - new->y),
8845 size, old->y - new->y);
8848 /* Left or right edge - don't overlap any update calculated above. */
8849 if (new->x > old->x) {
8850 SetRect(&(update[count]), old->x, Max(new->y, old->y),
8851 new->x - old->x, size - abs(new->y - old->y));
8853 } else if (old->x > new->x) {
8854 SetRect(&(update[count]), new->x + size, Max(new->y, old->y),
8855 old->x - new->x, size - abs(new->y - old->y));
8862 /* Generate a series of frame coords from start->mid->finish.
8863 The movement rate doubles until the half way point is
8864 reached, then halves back down to the final destination,
8865 which gives a nice slow in/out effect. The algorithmn
8866 may seem to generate too many intermediates for short
8867 moves, but remember that the purpose is to attract the
8868 viewers attention to the piece about to be moved and
8869 then to where it ends up. Too few frames would be less
8873 Tween(start, mid, finish, factor, frames, nFrames)
8874 XPoint * start; XPoint * mid;
8875 XPoint * finish; int factor;
8876 XPoint frames[]; int * nFrames;
8878 int fraction, n, count;
8882 /* Slow in, stepping 1/16th, then 1/8th, ... */
8884 for (n = 0; n < factor; n++)
8886 for (n = 0; n < factor; n++) {
8887 frames[count].x = start->x + (mid->x - start->x) / fraction;
8888 frames[count].y = start->y + (mid->y - start->y) / fraction;
8890 fraction = fraction / 2;
8894 frames[count] = *mid;
8897 /* Slow out, stepping 1/2, then 1/4, ... */
8899 for (n = 0; n < factor; n++) {
8900 frames[count].x = finish->x - (finish->x - mid->x) / fraction;
8901 frames[count].y = finish->y - (finish->y - mid->y) / fraction;
8903 fraction = fraction * 2;
8908 /* Draw a piece on the screen without disturbing what's there */
8911 SelectGCMask(piece, clip, outline, mask)
8912 ChessSquare piece; GC * clip; GC * outline; Pixmap * mask;
8916 /* Bitmap for piece being moved. */
8917 if (appData.monoMode) {
8918 *mask = *pieceToSolid(piece);
8919 } else if (useImages) {
8921 *mask = xpmMask[piece];
8923 *mask = ximMaskPm[piece];
8926 *mask = *pieceToSolid(piece);
8929 /* GC for piece being moved. Square color doesn't matter, but
8930 since it gets modified we make a copy of the original. */
8932 if (appData.monoMode)
8937 if (appData.monoMode)
8942 XCopyGC(xDisplay, source, 0xFFFFFFFF, *clip);
8944 /* Outline only used in mono mode and is not modified */
8946 *outline = bwPieceGC;
8948 *outline = wbPieceGC;
8952 OverlayPiece(piece, clip, outline, dest)
8953 ChessSquare piece; GC clip; GC outline; Drawable dest;
8958 /* Draw solid rectangle which will be clipped to shape of piece */
8959 XFillRectangle(xDisplay, dest, clip,
8960 0, 0, squareSize, squareSize);
8961 if (appData.monoMode)
8962 /* Also draw outline in contrasting color for black
8963 on black / white on white cases */
8964 XCopyPlane(xDisplay, *pieceToOutline(piece), dest, outline,
8965 0, 0, squareSize, squareSize, 0, 0, 1);
8967 /* Copy the piece */
8972 XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
8974 0, 0, squareSize, squareSize,
8979 /* Animate the movement of a single piece */
8982 BeginAnimation(anim, piece, startColor, start)
8990 /* The old buffer is initialised with the start square (empty) */
8991 BlankSquare(0, 0, startColor, EmptySquare, anim->saveBuf);
8992 anim->prevFrame = *start;
8994 /* The piece will be drawn using its own bitmap as a matte */
8995 SelectGCMask(piece, &anim->pieceGC, &anim->outlineGC, &mask);
8996 XSetClipMask(xDisplay, anim->pieceGC, mask);
9000 AnimationFrame(anim, frame, piece)
9005 XRectangle updates[4];
9010 /* Save what we are about to draw into the new buffer */
9011 XCopyArea(xDisplay, xBoardWindow, anim->newBuf, anim->blitGC,
9012 frame->x, frame->y, squareSize, squareSize,
9015 /* Erase bits of the previous frame */
9016 if (Intersect(&anim->prevFrame, frame, squareSize, &overlap, &pt)) {
9017 /* Where the new frame overlapped the previous,
9018 the contents in newBuf are wrong. */
9019 XCopyArea(xDisplay, anim->saveBuf, anim->newBuf, anim->blitGC,
9020 overlap.x, overlap.y,
9021 overlap.width, overlap.height,
9023 /* Repaint the areas in the old that don't overlap new */
9024 CalcUpdateRects(&anim->prevFrame, frame, squareSize, updates, &count);
9025 for (i = 0; i < count; i++)
9026 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9027 updates[i].x - anim->prevFrame.x,
9028 updates[i].y - anim->prevFrame.y,
9029 updates[i].width, updates[i].height,
9030 updates[i].x, updates[i].y);
9032 /* Easy when no overlap */
9033 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9034 0, 0, squareSize, squareSize,
9035 anim->prevFrame.x, anim->prevFrame.y);
9038 /* Save this frame for next time round */
9039 XCopyArea(xDisplay, anim->newBuf, anim->saveBuf, anim->blitGC,
9040 0, 0, squareSize, squareSize,
9042 anim->prevFrame = *frame;
9044 /* Draw piece over original screen contents, not current,
9045 and copy entire rect. Wipes out overlapping piece images. */
9046 OverlayPiece(piece, anim->pieceGC, anim->outlineGC, anim->newBuf);
9047 XCopyArea(xDisplay, anim->newBuf, xBoardWindow, anim->blitGC,
9048 0, 0, squareSize, squareSize,
9049 frame->x, frame->y);
9053 EndAnimation (anim, finish)
9057 XRectangle updates[4];
9062 /* The main code will redraw the final square, so we
9063 only need to erase the bits that don't overlap. */
9064 if (Intersect(&anim->prevFrame, finish, squareSize, &overlap, &pt)) {
9065 CalcUpdateRects(&anim->prevFrame, finish, squareSize, updates, &count);
9066 for (i = 0; i < count; i++)
9067 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9068 updates[i].x - anim->prevFrame.x,
9069 updates[i].y - anim->prevFrame.y,
9070 updates[i].width, updates[i].height,
9071 updates[i].x, updates[i].y);
9073 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9074 0, 0, squareSize, squareSize,
9075 anim->prevFrame.x, anim->prevFrame.y);
9080 FrameSequence(anim, piece, startColor, start, finish, frames, nFrames)
9082 ChessSquare piece; int startColor;
9083 XPoint * start; XPoint * finish;
9084 XPoint frames[]; int nFrames;
9088 BeginAnimation(anim, piece, startColor, start);
9089 for (n = 0; n < nFrames; n++) {
9090 AnimationFrame(anim, &(frames[n]), piece);
9091 FrameDelay(appData.animSpeed);
9093 EndAnimation(anim, finish);
9096 /* Main control logic for deciding what to animate and how */
9099 AnimateMove(board, fromX, fromY, toX, toY)
9108 XPoint start, finish, mid;
9109 XPoint frames[kFactor * 2 + 1];
9110 int nFrames, startColor, endColor;
9112 /* Are we animating? */
9113 if (!appData.animate || appData.blindfold)
9116 if(board[toY][toX] == WhiteRook && board[fromY][fromX] == WhiteKing ||
9117 board[toY][toX] == BlackRook && board[fromY][fromX] == BlackKing)
9118 return; // [HGM] FRC: no animtion of FRC castlings, as to-square is not true to-square
9120 if (fromY < 0 || fromX < 0 || toX < 0 || toY < 0) return;
9121 piece = board[fromY][fromX];
9122 if (piece >= EmptySquare) return;
9127 hop = (piece == WhiteKnight || piece == BlackKnight);
9130 if (appData.debugMode) {
9131 fprintf(debugFP, hop ? _("AnimateMove: piece %d hops from %d,%d to %d,%d \n") :
9132 _("AnimateMove: piece %d slides from %d,%d to %d,%d \n"),
9133 piece, fromX, fromY, toX, toY); }
9135 ScreenSquare(fromX, fromY, &start, &startColor);
9136 ScreenSquare(toX, toY, &finish, &endColor);
9139 /* Knight: make diagonal movement then straight */
9140 if (abs(toY - fromY) < abs(toX - fromX)) {
9141 mid.x = start.x + (finish.x - start.x) / 2;
9145 mid.y = start.y + (finish.y - start.y) / 2;
9148 mid.x = start.x + (finish.x - start.x) / 2;
9149 mid.y = start.y + (finish.y - start.y) / 2;
9152 /* Don't use as many frames for very short moves */
9153 if (abs(toY - fromY) + abs(toX - fromX) <= 2)
9154 Tween(&start, &mid, &finish, kFactor - 1, frames, &nFrames);
9156 Tween(&start, &mid, &finish, kFactor, frames, &nFrames);
9157 FrameSequence(&game, piece, startColor, &start, &finish, frames, nFrames);
9159 /* Be sure end square is redrawn */
9160 damage[toY][toX] = True;
9164 DragPieceBegin(x, y)
9167 int boardX, boardY, color;
9170 /* Are we animating? */
9171 if (!appData.animateDragging || appData.blindfold)
9174 /* Figure out which square we start in and the
9175 mouse position relative to top left corner. */
9176 BoardSquare(x, y, &boardX, &boardY);
9177 player.startBoardX = boardX;
9178 player.startBoardY = boardY;
9179 ScreenSquare(boardX, boardY, &corner, &color);
9180 player.startSquare = corner;
9181 player.startColor = color;
9182 /* As soon as we start dragging, the piece will jump slightly to
9183 be centered over the mouse pointer. */
9184 player.mouseDelta.x = squareSize/2;
9185 player.mouseDelta.y = squareSize/2;
9186 /* Initialise animation */
9187 player.dragPiece = PieceForSquare(boardX, boardY);
9189 if (player.dragPiece >= 0 && player.dragPiece < EmptySquare) {
9190 player.dragActive = True;
9191 BeginAnimation(&player, player.dragPiece, color, &corner);
9192 /* Mark this square as needing to be redrawn. Note that
9193 we don't remove the piece though, since logically (ie
9194 as seen by opponent) the move hasn't been made yet. */
9195 if(boardX == BOARD_RGHT+1 && PieceForSquare(boardX-1, boardY) > 1 ||
9196 boardX == BOARD_LEFT-2 && PieceForSquare(boardX+1, boardY) > 1)
9197 XCopyArea(xDisplay, xBoardWindow, player.saveBuf, player.blitGC,
9198 corner.x, corner.y, squareSize, squareSize,
9199 0, 0); // [HGM] zh: unstack in stead of grab
9200 damage[boardY][boardX] = True;
9202 player.dragActive = False;
9212 /* Are we animating? */
9213 if (!appData.animateDragging || appData.blindfold)
9217 if (! player.dragActive)
9219 /* Move piece, maintaining same relative position
9220 of mouse within square */
9221 corner.x = x - player.mouseDelta.x;
9222 corner.y = y - player.mouseDelta.y;
9223 AnimationFrame(&player, &corner, player.dragPiece);
9225 if (appData.highlightDragging) {
9227 BoardSquare(x, y, &boardX, &boardY);
9228 SetHighlights(fromX, fromY, boardX, boardY);
9237 int boardX, boardY, color;
9240 /* Are we animating? */
9241 if (!appData.animateDragging || appData.blindfold)
9245 if (! player.dragActive)
9247 /* Last frame in sequence is square piece is
9248 placed on, which may not match mouse exactly. */
9249 BoardSquare(x, y, &boardX, &boardY);
9250 ScreenSquare(boardX, boardY, &corner, &color);
9251 EndAnimation(&player, &corner);
9253 /* Be sure end square is redrawn */
9254 damage[boardY][boardX] = True;
9256 /* This prevents weird things happening with fast successive
9257 clicks which on my Sun at least can cause motion events
9258 without corresponding press/release. */
9259 player.dragActive = False;
9262 /* Handle expose event while piece being dragged */
9267 if (!player.dragActive || appData.blindfold)
9270 /* What we're doing: logically, the move hasn't been made yet,
9271 so the piece is still in it's original square. But visually
9272 it's being dragged around the board. So we erase the square
9273 that the piece is on and draw it at the last known drag point. */
9274 BlankSquare(player.startSquare.x, player.startSquare.y,
9275 player.startColor, EmptySquare, xBoardWindow);
9276 AnimationFrame(&player, &player.prevFrame, player.dragPiece);
9277 damage[player.startBoardY][player.startBoardX] = TRUE;
9281 SetProgramStats( FrontEndProgramStats * stats )
9284 // [HGM] done, but perhaps backend should call this directly?
9285 EngineOutputUpdate( stats );
9288 #include <sys/ioctl.h>
9289 int get_term_width()
9291 int fd, default_width;
9294 default_width = 79; // this is FICS default anyway...
9296 #if !defined(TIOCGWINSZ) && defined(TIOCGSIZE)
9298 if (!ioctl(fd, TIOCGSIZE, &win))
9299 default_width = win.ts_cols;
9300 #elif defined(TIOCGWINSZ)
9302 if (!ioctl(fd, TIOCGWINSZ, &win))
9303 default_width = win.ws_col;
9305 return default_width;
9308 void update_ics_width()
9310 static int old_width = 0;
9311 int new_width = get_term_width();
9313 if (old_width != new_width)
9314 ics_printf("set width %d\n", new_width);
9315 old_width = new_width;
9318 void NotifyFrontendLogin()