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) False},
1413 { "wrapContinuationSequence", "wrapContinuationSequence", XtRString,
1414 sizeof(String), XtOffset(AppDataPtr, wrapContSeq),
1416 { "useInternalWrap", "useInternalWrap", XtRBoolean,
1417 sizeof(Boolean), XtOffset(AppDataPtr, useInternalWrap),
1418 XtRImmediate, (XtPointer) True},
1421 XrmOptionDescRec shellOptions[] = {
1422 { "-whitePieceColor", "whitePieceColor", XrmoptionSepArg, NULL },
1423 { "-blackPieceColor", "blackPieceColor", XrmoptionSepArg, NULL },
1424 { "-lightSquareColor", "lightSquareColor", XrmoptionSepArg, NULL },
1425 { "-darkSquareColor", "darkSquareColor", XrmoptionSepArg, NULL },
1426 { "-highlightSquareColor", "highlightSquareColor", XrmoptionSepArg, NULL },
1427 { "-premoveHighlightColor", "premoveHighlightColor", XrmoptionSepArg,NULL},
1428 { "-movesPerSession", "movesPerSession", XrmoptionSepArg, NULL },
1429 { "-mps", "movesPerSession", XrmoptionSepArg, NULL },
1430 { "-timeIncrement", "timeIncrement", XrmoptionSepArg, NULL },
1431 { "-inc", "timeIncrement", XrmoptionSepArg, NULL },
1432 { "-initString", "initString", XrmoptionSepArg, NULL },
1433 { "-firstInitString", "initString", XrmoptionSepArg, NULL },
1434 { "-secondInitString", "secondInitString", XrmoptionSepArg, NULL },
1435 { "-firstComputerString", "firstComputerString", XrmoptionSepArg, NULL },
1436 { "-secondComputerString", "secondComputerString", XrmoptionSepArg, NULL },
1437 { "-firstChessProgram", "firstChessProgram", XrmoptionSepArg, NULL },
1438 { "-fcp", "firstChessProgram", XrmoptionSepArg, NULL },
1439 { "-secondChessProgram", "secondChessProgram", XrmoptionSepArg, NULL },
1440 { "-scp", "secondChessProgram", XrmoptionSepArg, NULL },
1441 { "-firstPlaysBlack", "firstPlaysBlack", XrmoptionSepArg, NULL },
1442 { "-fb", "firstPlaysBlack", XrmoptionNoArg, "True" },
1443 { "-xfb", "firstPlaysBlack", XrmoptionNoArg, "False" },
1444 { "-noChessProgram", "noChessProgram", XrmoptionSepArg, NULL },
1445 { "-ncp", "noChessProgram", XrmoptionNoArg, "True" },
1446 { "-xncp", "noChessProgram", XrmoptionNoArg, "False" },
1447 { "-firstHost", "firstHost", XrmoptionSepArg, NULL },
1448 { "-fh", "firstHost", XrmoptionSepArg, NULL },
1449 { "-secondHost", "secondHost", XrmoptionSepArg, NULL },
1450 { "-sh", "secondHost", XrmoptionSepArg, NULL },
1451 { "-firstDirectory", "firstDirectory", XrmoptionSepArg, NULL },
1452 { "-fd", "firstDirectory", XrmoptionSepArg, NULL },
1453 { "-secondDirectory", "secondDirectory", XrmoptionSepArg, NULL },
1454 { "-sd", "secondDirectory", XrmoptionSepArg, NULL },
1455 { "-bitmapDirectory", "bitmapDirectory", XrmoptionSepArg, NULL },
1456 { "-bm", "bitmapDirectory", XrmoptionSepArg, NULL },
1457 { "-remoteShell", "remoteShell", XrmoptionSepArg, NULL },
1458 { "-rsh", "remoteShell", XrmoptionSepArg, NULL },
1459 { "-remoteUser", "remoteUser", XrmoptionSepArg, NULL },
1460 { "-ruser", "remoteUser", XrmoptionSepArg, NULL },
1461 { "-timeDelay", "timeDelay", XrmoptionSepArg, NULL },
1462 { "-td", "timeDelay", XrmoptionSepArg, NULL },
1463 { "-timeControl", "timeControl", XrmoptionSepArg, NULL },
1464 { "-tc", "timeControl", XrmoptionSepArg, NULL },
1465 { "-internetChessServerMode", "internetChessServerMode",
1466 XrmoptionSepArg, NULL },
1467 { "-ics", "internetChessServerMode", XrmoptionNoArg, "True" },
1468 { "-xics", "internetChessServerMode", XrmoptionNoArg, "False" },
1469 { "-internetChessServerHost", "internetChessServerHost",
1470 XrmoptionSepArg, NULL },
1471 { "-icshost", "internetChessServerHost", XrmoptionSepArg, NULL },
1472 { "-internetChessServerPort", "internetChessServerPort",
1473 XrmoptionSepArg, NULL },
1474 { "-icsport", "internetChessServerPort", XrmoptionSepArg, NULL },
1475 { "-internetChessServerCommPort", "internetChessServerCommPort",
1476 XrmoptionSepArg, NULL },
1477 { "-icscomm", "internetChessServerCommPort", XrmoptionSepArg, NULL },
1478 { "-internetChessServerLogonScript", "internetChessServerLogonScript",
1479 XrmoptionSepArg, NULL },
1480 { "-icslogon", "internetChessServerLogonScript", XrmoptionSepArg, NULL },
1481 { "-internetChessServerHelper", "internetChessServerHelper",
1482 XrmoptionSepArg, NULL },
1483 { "-icshelper", "internetChessServerHelper", XrmoptionSepArg, NULL },
1484 { "-internetChessServerInputBox", "internetChessServerInputBox",
1485 XrmoptionSepArg, NULL },
1486 { "-icsinput", "internetChessServerInputBox", XrmoptionNoArg, "True" },
1487 { "-xicsinput", "internetChessServerInputBox", XrmoptionNoArg, "False" },
1488 { "-icsAlarm", "icsAlarm", XrmoptionSepArg, NULL },
1489 { "-alarm", "icsAlarm", XrmoptionNoArg, "True" },
1490 { "-xalarm", "icsAlarm", XrmoptionNoArg, "False" },
1491 { "-icsAlarmTime", "icsAlarmTime", XrmoptionSepArg, NULL },
1492 { "-useTelnet", "useTelnet", XrmoptionSepArg, NULL },
1493 { "-telnet", "useTelnet", XrmoptionNoArg, "True" },
1494 { "-xtelnet", "useTelnet", XrmoptionNoArg, "False" },
1495 { "-telnetProgram", "telnetProgram", XrmoptionSepArg, NULL },
1496 { "-gateway", "gateway", XrmoptionSepArg, NULL },
1497 { "-loadGameFile", "loadGameFile", XrmoptionSepArg, NULL },
1498 { "-lgf", "loadGameFile", XrmoptionSepArg, NULL },
1499 { "-loadGameIndex", "loadGameIndex", XrmoptionSepArg, NULL },
1500 { "-lgi", "loadGameIndex", XrmoptionSepArg, NULL },
1501 { "-saveGameFile", "saveGameFile", XrmoptionSepArg, NULL },
1502 { "-sgf", "saveGameFile", XrmoptionSepArg, NULL },
1503 { "-autoSaveGames", "autoSaveGames", XrmoptionSepArg, NULL },
1504 { "-autosave", "autoSaveGames", XrmoptionNoArg, "True" },
1505 { "-xautosave", "autoSaveGames", XrmoptionNoArg, "False" },
1506 { "-autoRaiseBoard", "autoRaiseBoard", XrmoptionSepArg, NULL },
1507 { "-autoraise", "autoRaiseBoard", XrmoptionNoArg, "True" },
1508 { "-xautoraise", "autoRaiseBoard", XrmoptionNoArg, "False" },
1509 { "-blindfold", "blindfold", XrmoptionSepArg, NULL },
1510 { "-blind", "blindfold", XrmoptionNoArg, "True" },
1511 { "-xblind", "blindfold", XrmoptionNoArg, "False" },
1512 { "-loadPositionFile", "loadPositionFile", XrmoptionSepArg, NULL },
1513 { "-lpf", "loadPositionFile", XrmoptionSepArg, NULL },
1514 { "-loadPositionIndex", "loadPositionIndex", XrmoptionSepArg, NULL },
1515 { "-lpi", "loadPositionIndex", XrmoptionSepArg, NULL },
1516 { "-savePositionFile", "savePositionFile", XrmoptionSepArg, NULL },
1517 { "-spf", "savePositionFile", XrmoptionSepArg, NULL },
1518 { "-matchMode", "matchMode", XrmoptionSepArg, NULL },
1519 { "-mm", "matchMode", XrmoptionNoArg, "True" },
1520 { "-xmm", "matchMode", XrmoptionNoArg, "False" },
1521 { "-matchGames", "matchGames", XrmoptionSepArg, NULL },
1522 { "-mg", "matchGames", XrmoptionSepArg, NULL },
1523 { "-monoMode", "monoMode", XrmoptionSepArg, NULL },
1524 { "-mono", "monoMode", XrmoptionNoArg, "True" },
1525 { "-xmono", "monoMode", XrmoptionNoArg, "False" },
1526 { "-debugMode", "debugMode", XrmoptionSepArg, NULL },
1527 { "-debug", "debugMode", XrmoptionNoArg, "True" },
1528 { "-xdebug", "debugMode", XrmoptionNoArg, "False" },
1529 { "-clockMode", "clockMode", XrmoptionSepArg, NULL },
1530 { "-clock", "clockMode", XrmoptionNoArg, "True" },
1531 { "-xclock", "clockMode", XrmoptionNoArg, "False" },
1532 { "-boardSize", "boardSize", XrmoptionSepArg, NULL },
1533 { "-size", "boardSize", XrmoptionSepArg, NULL },
1534 { "-searchTime", "searchTime", XrmoptionSepArg, NULL },
1535 { "-st", "searchTime", XrmoptionSepArg, NULL },
1536 { "-searchDepth", "searchDepth", XrmoptionSepArg, NULL },
1537 { "-depth", "searchDepth", XrmoptionSepArg, NULL },
1538 { "-showCoords", "showCoords", XrmoptionSepArg, NULL },
1539 { "-coords", "showCoords", XrmoptionNoArg, "True" },
1540 { "-xcoords", "showCoords", XrmoptionNoArg, "False" },
1542 { "-showJail", "showJail", XrmoptionSepArg, NULL },
1543 { "-jail", "showJail", XrmoptionNoArg, "1" },
1544 { "-sidejail", "showJail", XrmoptionNoArg, "2" },
1545 { "-xjail", "showJail", XrmoptionNoArg, "0" },
1547 { "-showThinking", "showThinking", XrmoptionSepArg, NULL },
1548 { "-thinking", "showThinking", XrmoptionNoArg, "True" },
1549 { "-xthinking", "showThinking", XrmoptionNoArg, "False" },
1550 { "-ponderNextMove", "ponderNextMove", XrmoptionSepArg, NULL },
1551 { "-ponder", "ponderNextMove", XrmoptionNoArg, "True" },
1552 { "-xponder", "ponderNextMove", XrmoptionNoArg, "False" },
1553 { "-periodicUpdates", "periodicUpdates", XrmoptionSepArg, NULL },
1554 { "-periodic", "periodicUpdates", XrmoptionNoArg, "True" },
1555 { "-xperiodic", "periodicUpdates", XrmoptionNoArg, "False" },
1556 { "-clockFont", "clockFont", XrmoptionSepArg, NULL },
1557 { "-coordFont", "coordFont", XrmoptionSepArg, NULL },
1558 { "-font", "font", XrmoptionSepArg, NULL },
1559 { "-ringBellAfterMoves", "ringBellAfterMoves", XrmoptionSepArg, NULL },
1560 { "-bell", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1561 { "-xbell", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1562 { "-movesound", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1563 { "-xmovesound", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1564 { "-autoCallFlag", "autoCallFlag", XrmoptionSepArg, NULL },
1565 { "-autoflag", "autoCallFlag", XrmoptionNoArg, "True" },
1566 { "-xautoflag", "autoCallFlag", XrmoptionNoArg, "False" },
1567 { "-autoFlipView", "autoFlipView", XrmoptionSepArg, NULL },
1568 { "-autoflip", "autoFlipView", XrmoptionNoArg, "True" },
1569 { "-xautoflip", "autoFlipView", XrmoptionNoArg, "False" },
1570 { "-autoObserve", "autoObserve", XrmoptionSepArg, NULL },
1571 { "-autobs", "autoObserve", XrmoptionNoArg, "True" },
1572 { "-xautobs", "autoObserve", XrmoptionNoArg, "False" },
1573 { "-autoComment", "autoComment", XrmoptionSepArg, NULL },
1574 { "-autocomm", "autoComment", XrmoptionNoArg, "True" },
1575 { "-xautocomm", "autoComment", XrmoptionNoArg, "False" },
1576 { "-getMoveList", "getMoveList", XrmoptionSepArg, NULL },
1577 { "-moves", "getMoveList", XrmoptionNoArg, "True" },
1578 { "-xmoves", "getMoveList", XrmoptionNoArg, "False" },
1580 { "-highlightDragging", "highlightDragging", XrmoptionSepArg, NULL },
1581 { "-highdrag", "highlightDragging", XrmoptionNoArg, "True" },
1582 { "-xhighdrag", "highlightDragging", XrmoptionNoArg, "False" },
1584 { "-highlightLastMove", "highlightLastMove", XrmoptionSepArg, NULL },
1585 { "-highlight", "highlightLastMove", XrmoptionNoArg, "True" },
1586 { "-xhighlight", "highlightLastMove", XrmoptionNoArg, "False" },
1587 { "-premove", "premove", XrmoptionSepArg, NULL },
1588 { "-pre", "premove", XrmoptionNoArg, "True" },
1589 { "-xpre", "premove", XrmoptionNoArg, "False" },
1590 { "-testLegality", "testLegality", XrmoptionSepArg, NULL },
1591 { "-legal", "testLegality", XrmoptionNoArg, "True" },
1592 { "-xlegal", "testLegality", XrmoptionNoArg, "False" },
1593 { "-flipView", "flipView", XrmoptionSepArg, NULL },
1594 { "-flip", "flipView", XrmoptionNoArg, "True" },
1595 { "-xflip", "flipView", XrmoptionNoArg, "False" },
1596 { "-cmail", "cmailGameName", XrmoptionSepArg, NULL },
1597 { "-alwaysPromoteToQueen", "alwaysPromoteToQueen",
1598 XrmoptionSepArg, NULL },
1599 { "-queen", "alwaysPromoteToQueen", XrmoptionNoArg, "True" },
1600 { "-xqueen", "alwaysPromoteToQueen", XrmoptionNoArg, "False" },
1601 { "-oldSaveStyle", "oldSaveStyle", XrmoptionSepArg, NULL },
1602 { "-oldsave", "oldSaveStyle", XrmoptionNoArg, "True" },
1603 { "-xoldsave", "oldSaveStyle", XrmoptionNoArg, "False" },
1604 { "-quietPlay", "quietPlay", XrmoptionSepArg, NULL },
1605 { "-quiet", "quietPlay", XrmoptionNoArg, "True" },
1606 { "-xquiet", "quietPlay", XrmoptionNoArg, "False" },
1607 { "-titleInWindow", "titleInWindow", XrmoptionSepArg, NULL },
1608 { "-title", "titleInWindow", XrmoptionNoArg, "True" },
1609 { "-xtitle", "titleInWindow", XrmoptionNoArg, "False" },
1611 { "-zippyTalk", "zippyTalk", XrmoptionSepArg, NULL },
1612 { "-zt", "zippyTalk", XrmoptionNoArg, "True" },
1613 { "-xzt", "zippyTalk", XrmoptionNoArg, "False" },
1614 { "-zippyPlay", "zippyPlay", XrmoptionSepArg, NULL },
1615 { "-zp", "zippyPlay", XrmoptionNoArg, "True" },
1616 { "-xzp", "zippyPlay", XrmoptionNoArg, "False" },
1617 { "-zippyLines", "zippyLines", XrmoptionSepArg, NULL },
1618 { "-zippyPinhead", "zippyPinhead", XrmoptionSepArg, NULL },
1619 { "-zippyPassword", "zippyPassword", XrmoptionSepArg, NULL },
1620 { "-zippyPassword2", "zippyPassword2", XrmoptionSepArg, NULL },
1621 { "-zippyWrongPassword", "zippyWrongPassword", XrmoptionSepArg, NULL },
1622 { "-zippyAcceptOnly", "zippyAcceptOnly", XrmoptionSepArg, NULL },
1623 { "-zippyUseI", "zippyUseI", XrmoptionSepArg, NULL },
1624 { "-zui", "zippyUseI", XrmoptionNoArg, "True" },
1625 { "-xzui", "zippyUseI", XrmoptionNoArg, "False" },
1626 { "-zippyBughouse", "zippyBughouse", XrmoptionSepArg, NULL },
1627 { "-zippyNoplayCrafty", "zippyNoplayCrafty", XrmoptionSepArg, NULL },
1628 { "-znc", "zippyNoplayCrafty", XrmoptionNoArg, "True" },
1629 { "-xznc", "zippyNoplayCrafty", XrmoptionNoArg, "False" },
1630 { "-zippyGameEnd", "zippyGameEnd", XrmoptionSepArg, NULL },
1631 { "-zippyGameStart", "zippyGameStart", XrmoptionSepArg, NULL },
1632 { "-zippyAdjourn", "zippyAdjourn", XrmoptionSepArg, NULL },
1633 { "-zadj", "zippyAdjourn", XrmoptionNoArg, "True" },
1634 { "-xzadj", "zippyAdjourn", XrmoptionNoArg, "False" },
1635 { "-zippyAbort", "zippyAbort", XrmoptionSepArg, NULL },
1636 { "-zab", "zippyAbort", XrmoptionNoArg, "True" },
1637 { "-xzab", "zippyAbort", XrmoptionNoArg, "False" },
1638 { "-zippyVariants", "zippyVariants", XrmoptionSepArg, NULL },
1639 { "-zippyMaxGames", "zippyMaxGames", XrmoptionSepArg, NULL },
1640 { "-zippyReplayTimeout", "zippyReplayTimeout", XrmoptionSepArg, NULL },
1641 { "-zippyShortGame", "zippyShortGame", XrmoptionSepArg, NULL },
1643 { "-flashCount", "flashCount", XrmoptionSepArg, NULL },
1644 { "-flash", "flashCount", XrmoptionNoArg, "3" },
1645 { "-xflash", "flashCount", XrmoptionNoArg, "0" },
1646 { "-flashRate", "flashRate", XrmoptionSepArg, NULL },
1647 { "-pixmapDirectory", "pixmapDirectory", XrmoptionSepArg, NULL },
1648 { "-msLoginDelay", "msLoginDelay", XrmoptionSepArg, NULL },
1649 { "-pixmap", "pixmapDirectory", XrmoptionSepArg, NULL },
1650 { "-colorizeMessages", "colorizeMessages", XrmoptionSepArg, NULL },
1651 { "-colorize", "colorizeMessages", XrmoptionNoArg, "True" },
1652 { "-xcolorize", "colorizeMessages", XrmoptionNoArg, "False" },
1653 { "-colorShout", "colorShout", XrmoptionSepArg, NULL },
1654 { "-colorSShout", "colorSShout", XrmoptionSepArg, NULL },
1655 { "-colorCShout", "colorSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1656 { "-colorChannel1", "colorChannel1", XrmoptionSepArg, NULL },
1657 { "-colorChannel", "colorChannel", XrmoptionSepArg, NULL },
1658 { "-colorKibitz", "colorKibitz", XrmoptionSepArg, NULL },
1659 { "-colorTell", "colorTell", XrmoptionSepArg, NULL },
1660 { "-colorChallenge", "colorChallenge", XrmoptionSepArg, NULL },
1661 { "-colorRequest", "colorRequest", XrmoptionSepArg, NULL },
1662 { "-colorSeek", "colorSeek", XrmoptionSepArg, NULL },
1663 { "-colorNormal", "colorNormal", XrmoptionSepArg, NULL },
1664 { "-soundProgram", "soundProgram", XrmoptionSepArg, NULL },
1665 { "-soundShout", "soundShout", XrmoptionSepArg, NULL },
1666 { "-soundSShout", "soundSShout", XrmoptionSepArg, NULL },
1667 { "-soundCShout", "soundSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1668 { "-soundChannel1", "soundChannel1", XrmoptionSepArg, NULL },
1669 { "-soundChannel", "soundChannel", XrmoptionSepArg, NULL },
1670 { "-soundKibitz", "soundKibitz", XrmoptionSepArg, NULL },
1671 { "-soundTell", "soundTell", XrmoptionSepArg, NULL },
1672 { "-soundChallenge", "soundChallenge", XrmoptionSepArg, NULL },
1673 { "-soundRequest", "soundRequest", XrmoptionSepArg, NULL },
1674 { "-soundSeek", "soundSeek", XrmoptionSepArg, NULL },
1675 { "-soundMove", "soundMove", XrmoptionSepArg, NULL },
1676 { "-soundIcsWin", "soundIcsWin", XrmoptionSepArg, NULL },
1677 { "-soundIcsLoss", "soundIcsLoss", XrmoptionSepArg, NULL },
1678 { "-soundIcsDraw", "soundIcsDraw", XrmoptionSepArg, NULL },
1679 { "-soundIcsUnfinished", "soundIcsUnfinished", XrmoptionSepArg, NULL },
1680 { "-soundIcsAlarm", "soundIcsAlarm", XrmoptionSepArg, NULL },
1681 { "-reuseFirst", "reuseFirst", XrmoptionSepArg, NULL },
1682 { "-reuseChessPrograms", "reuseFirst", XrmoptionSepArg, NULL }, /*compat*/
1683 { "-reuse", "reuseFirst", XrmoptionNoArg, "True" },
1684 { "-xreuse", "reuseFirst", XrmoptionNoArg, "False" },
1685 { "-reuseSecond", "reuseSecond", XrmoptionSepArg, NULL },
1686 { "-reuse2", "reuseSecond", XrmoptionNoArg, "True" },
1687 { "-xreuse2", "reuseSecond", XrmoptionNoArg, "False" },
1688 { "-animateMoving", "animateMoving", XrmoptionSepArg, NULL },
1689 { "-animate", "animateMoving", XrmoptionNoArg, "True" },
1690 { "-xanimate", "animateMoving", XrmoptionNoArg, "False" },
1691 { "-animateDragging", "animateDragging", XrmoptionSepArg, NULL },
1692 { "-drag", "animateDragging", XrmoptionNoArg, "True" },
1693 { "-xdrag", "animateDragging", XrmoptionNoArg, "False" },
1694 { "-animateSpeed", "animateSpeed", XrmoptionSepArg, NULL },
1695 { "-popupExitMessage", "popupExitMessage", XrmoptionSepArg, NULL },
1696 { "-exit", "popupExitMessage", XrmoptionNoArg, "True" },
1697 { "-xexit", "popupExitMessage", XrmoptionNoArg, "False" },
1698 { "-popupMoveErrors", "popupMoveErrors", XrmoptionSepArg, NULL },
1699 { "-popup", "popupMoveErrors", XrmoptionNoArg, "True" },
1700 { "-xpopup", "popupMoveErrors", XrmoptionNoArg, "False" },
1701 { "-fontSizeTolerance", "fontSizeTolerance", XrmoptionSepArg, NULL },
1702 { "-initialMode", "initialMode", XrmoptionSepArg, NULL },
1703 { "-mode", "initialMode", XrmoptionSepArg, NULL },
1704 { "-variant", "variant", XrmoptionSepArg, NULL },
1705 { "-firstProtocolVersion", "firstProtocolVersion", XrmoptionSepArg, NULL },
1706 { "-secondProtocolVersion","secondProtocolVersion",XrmoptionSepArg, NULL },
1707 { "-showButtonBar", "showButtonBar", XrmoptionSepArg, NULL },
1708 { "-buttons", "showButtonBar", XrmoptionNoArg, "True" },
1709 { "-xbuttons", "showButtonBar", XrmoptionNoArg, "False" },
1710 { "-lowTimeWarningColor", "lowTimeWarningColor", XrmoptionSepArg, NULL },
1711 { "-lowTimeWarning", "lowTimeWarning", XrmoptionSepArg, NULL },
1712 /* [AS,HR] New features */
1713 { "-firstScoreAbs", "firstScoreAbs", XrmoptionSepArg, NULL },
1714 { "-secondScoreAbs", "secondScoreAbs", XrmoptionSepArg, NULL },
1715 { "-pgnExtendedInfo", "pgnExtendedInfo", XrmoptionSepArg, NULL },
1716 { "-hideThinkingFromHuman", "hideThinkingFromHuman", XrmoptionSepArg, NULL },
1717 { "-adjudicateLossThreshold", "adjudicateLossThreshold", XrmoptionSepArg, NULL },
1718 { "-adjudicateDrawMoves", "adjudicateDrawMoves", XrmoptionSepArg, NULL },
1719 { "-pgnEventHeader", "pgnEventHeader", XrmoptionSepArg, NULL },
1720 { "-firstIsUCI", "firstIsUCI", XrmoptionSepArg, NULL },
1721 { "-secondIsUCI", "secondIsUCI", XrmoptionSepArg, NULL },
1722 { "-fUCI", "firstIsUCI", XrmoptionNoArg, "True" },
1723 { "-sUCI", "secondIsUCI", XrmoptionNoArg, "True" },
1724 { "-firstHasOwnBookUCI", "firstHasOwnBookUCI", XrmoptionSepArg, NULL },
1725 { "-secondHasOwnBookUCI", "secondHasOwnBookUCI", XrmoptionSepArg, NULL },
1726 { "-fNoOwnBookUCI", "firstHasOwnBookUCI", XrmoptionNoArg, "False" },
1727 { "-sNoOwnBookUCI", "secondHasOwnBookUCI", XrmoptionNoArg, "False" },
1728 { "-firstXBook", "firstHasOwnBookUCI", XrmoptionNoArg, "False" },
1729 { "-secondXBook", "secondHasOwnBookUCI", XrmoptionNoArg, "False" },
1730 { "-polyglotDir", "polyglotDir", XrmoptionSepArg, NULL },
1731 { "-usePolyglotBook", "usePolyglotBook", XrmoptionSepArg, NULL },
1732 { "-polyglotBook", "polyglotBook", XrmoptionSepArg, NULL },
1733 { "-defaultHashSize", "defaultHashSize", XrmoptionSepArg, NULL },
1734 { "-defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XrmoptionSepArg, NULL },
1735 { "-defaultPathEGTB", "defaultPathEGTB", XrmoptionSepArg, NULL },
1736 { "-defaultFrcPosition", "defaultFrcPosition", XrmoptionSepArg, NULL },
1737 { "-gameListTags", "gameListTags", XrmoptionSepArg, NULL },
1738 // [HGM] I am sure AS added many more options, but we have to fish them out, from the list in winboard.c
1740 /* [HGM,HR] User-selectable board size */
1741 { "-boardWidth", "boardWidth", XrmoptionSepArg, NULL },
1742 { "-boardHeight", "boardHeight", XrmoptionSepArg, NULL },
1743 { "-matchPause", "matchPause", XrmoptionSepArg, NULL },
1745 /* [HGM] new arguments of 4.3.xx. All except first three are back-end options, which should work immediately */
1746 { "-holdingsSize", "holdingsSize", XrmoptionSepArg, NULL }, // requires extensive front-end changes to work
1747 { "-flipBlack", "flipBlack", XrmoptionSepArg, NULL }, // requires front-end changes to work
1748 { "-allWhite", "allWhite", XrmoptionSepArg, NULL }, // requires front-end changes to work
1749 { "-pieceToCharTable", "pieceToCharTable", XrmoptionSepArg, NULL },
1750 { "-alphaRank", "alphaRank", XrmoptionSepArg, NULL },
1751 { "-testClaims", "testClaims", XrmoptionSepArg, NULL },
1752 { "-checkMates", "checkMates", XrmoptionSepArg, NULL },
1753 { "-materialDraws", "materialDraws", XrmoptionSepArg, NULL },
1754 { "-trivialDraws", "trivialDraws", XrmoptionSepArg, NULL },
1755 { "-ruleMoves", "ruleMoves", XrmoptionSepArg, NULL },
1756 { "-repeatsToDraw", "repeatsToDraw", XrmoptionSepArg, NULL },
1757 { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL },
1758 { "-userName", "userName", XrmoptionSepArg, NULL },
1759 { "-autoKibitz", "autoKibitz", XrmoptionNoArg, "True" },
1760 { "-firstTimeOdds", "firstTimeOdds", XrmoptionSepArg, NULL },
1761 { "-secondTimeOdds", "secondTimeOdds", XrmoptionSepArg, NULL },
1762 { "-timeOddsMode", "timeOddsMode", XrmoptionSepArg, NULL },
1763 { "-firstAccumulateTC", "firstAccumulateTC", XrmoptionSepArg, NULL },
1764 { "-secondAccumulateTC", "secondAccumulateTC", XrmoptionSepArg, NULL },
1765 { "-firstNPS", "firstNPS", XrmoptionSepArg, NULL },
1766 { "-secondNPS", "secondNPS", XrmoptionSepArg, NULL },
1767 { "-serverMoves", "serverMoves", XrmoptionSepArg, NULL },
1768 { "-serverPause", "serverPause", XrmoptionSepArg, NULL },
1769 { "-suppressLoadMoves", "suppressLoadMoves", XrmoptionSepArg, NULL },
1770 { "-egtFormats", "egtFormats", XrmoptionSepArg, NULL },
1771 { "-userName", "userName", XrmoptionSepArg, NULL },
1772 { "-smpCores", "smpCores", XrmoptionSepArg, NULL },
1773 { "-sameColorGames", "sameColorGames", XrmoptionSepArg, NULL },
1774 { "-rewindIndex", "rewindIndex", XrmoptionSepArg, NULL },
1775 { "-niceEngines", "niceEngines", XrmoptionSepArg, NULL },
1776 { "-delayBeforeQuit", "delayBeforeQuit", XrmoptionSepArg, NULL },
1777 { "-delayAfterQuit", "delayAfterQuit", XrmoptionSepArg, NULL },
1778 { "-nameOfDebugFile", "nameOfDebugFile", XrmoptionSepArg, NULL },
1779 { "-debugFile", "nameOfDebugFile", XrmoptionSepArg, NULL },
1780 { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL },
1781 { "-noGUI", "noGUI", XrmoptionNoArg, "True" },
1782 { "-firstOptions", "firstOptions", XrmoptionSepArg, NULL },
1783 { "-secondOptions", "secondOptions", XrmoptionSepArg, NULL },
1784 { "-firstNeedsNoncompliantFEN", "firstNeedsNoncompliantFEN", XrmoptionSepArg, NULL },
1785 { "-secondNeedsNoncompliantFEN", "secondNeedsNoncompliantFEN", XrmoptionSepArg, NULL },
1786 { "-keepAlive", "keepAlive", XrmoptionSepArg, NULL },
1787 { "-forceIllegalMoves", "forceIllegalMoves", XrmoptionNoArg, "True" },
1788 { "-keepLineBreaksICS", "keepLineBreaksICS", XrmoptionSepArg, NULL },
1789 { "-wrapContinuationSequence", "wrapContinuationSequence", XrmoptionSepArg, NULL },
1790 { "-useInternalWrap", "useInternalWrap", XrmoptionSepArg, NULL },
1793 XtActionsRec boardActions[] = {
1794 { "DrawPosition", DrawPositionProc },
1795 { "HandleUserMove", HandleUserMove },
1796 { "AnimateUserMove", AnimateUserMove },
1797 { "FileNameAction", FileNameAction },
1798 { "AskQuestionProc", AskQuestionProc },
1799 { "AskQuestionReplyAction", AskQuestionReplyAction },
1800 { "PieceMenuPopup", PieceMenuPopup },
1801 { "WhiteClock", WhiteClock },
1802 { "BlackClock", BlackClock },
1803 { "Iconify", Iconify },
1804 { "ResetProc", ResetProc },
1805 { "LoadGameProc", LoadGameProc },
1806 { "LoadNextGameProc", LoadNextGameProc },
1807 { "LoadPrevGameProc", LoadPrevGameProc },
1808 { "LoadSelectedProc", LoadSelectedProc },
1809 { "ReloadGameProc", ReloadGameProc },
1810 { "LoadPositionProc", LoadPositionProc },
1811 { "LoadNextPositionProc", LoadNextPositionProc },
1812 { "LoadPrevPositionProc", LoadPrevPositionProc },
1813 { "ReloadPositionProc", ReloadPositionProc },
1814 { "CopyPositionProc", CopyPositionProc },
1815 { "PastePositionProc", PastePositionProc },
1816 { "CopyGameProc", CopyGameProc },
1817 { "PasteGameProc", PasteGameProc },
1818 { "SaveGameProc", SaveGameProc },
1819 { "SavePositionProc", SavePositionProc },
1820 { "MailMoveProc", MailMoveProc },
1821 { "ReloadCmailMsgProc", ReloadCmailMsgProc },
1822 { "QuitProc", QuitProc },
1823 { "MachineWhiteProc", MachineWhiteProc },
1824 { "MachineBlackProc", MachineBlackProc },
1825 { "AnalysisModeProc", AnalyzeModeProc },
1826 { "AnalyzeFileProc", AnalyzeFileProc },
1827 { "TwoMachinesProc", TwoMachinesProc },
1828 { "IcsClientProc", IcsClientProc },
1829 { "EditGameProc", EditGameProc },
1830 { "EditPositionProc", EditPositionProc },
1831 { "TrainingProc", EditPositionProc },
1832 { "EngineOutputProc", EngineOutputProc}, // [HGM] Winboard_x engine-output window
1833 { "ShowGameListProc", ShowGameListProc },
1834 { "ShowMoveListProc", HistoryShowProc},
1835 { "EditTagsProc", EditCommentProc },
1836 { "EditCommentProc", EditCommentProc },
1837 { "IcsAlarmProc", IcsAlarmProc },
1838 { "IcsInputBoxProc", IcsInputBoxProc },
1839 { "PauseProc", PauseProc },
1840 { "AcceptProc", AcceptProc },
1841 { "DeclineProc", DeclineProc },
1842 { "RematchProc", RematchProc },
1843 { "CallFlagProc", CallFlagProc },
1844 { "DrawProc", DrawProc },
1845 { "AdjournProc", AdjournProc },
1846 { "AbortProc", AbortProc },
1847 { "ResignProc", ResignProc },
1848 { "AdjuWhiteProc", AdjuWhiteProc },
1849 { "AdjuBlackProc", AdjuBlackProc },
1850 { "AdjuDrawProc", AdjuDrawProc },
1851 { "EnterKeyProc", EnterKeyProc },
1852 { "StopObservingProc", StopObservingProc },
1853 { "StopExaminingProc", StopExaminingProc },
1854 { "BackwardProc", BackwardProc },
1855 { "ForwardProc", ForwardProc },
1856 { "ToStartProc", ToStartProc },
1857 { "ToEndProc", ToEndProc },
1858 { "RevertProc", RevertProc },
1859 { "TruncateGameProc", TruncateGameProc },
1860 { "MoveNowProc", MoveNowProc },
1861 { "RetractMoveProc", RetractMoveProc },
1862 { "AlwaysQueenProc", AlwaysQueenProc },
1863 { "AnimateDraggingProc", AnimateDraggingProc },
1864 { "AnimateMovingProc", AnimateMovingProc },
1865 { "AutoflagProc", AutoflagProc },
1866 { "AutoflipProc", AutoflipProc },
1867 { "AutobsProc", AutobsProc },
1868 { "AutoraiseProc", AutoraiseProc },
1869 { "AutosaveProc", AutosaveProc },
1870 { "BlindfoldProc", BlindfoldProc },
1871 { "FlashMovesProc", FlashMovesProc },
1872 { "FlipViewProc", FlipViewProc },
1873 { "GetMoveListProc", GetMoveListProc },
1875 { "HighlightDraggingProc", HighlightDraggingProc },
1877 { "HighlightLastMoveProc", HighlightLastMoveProc },
1878 { "IcsAlarmProc", IcsAlarmProc },
1879 { "MoveSoundProc", MoveSoundProc },
1880 { "OldSaveStyleProc", OldSaveStyleProc },
1881 { "PeriodicUpdatesProc", PeriodicUpdatesProc },
1882 { "PonderNextMoveProc", PonderNextMoveProc },
1883 { "PopupExitMessageProc", PopupExitMessageProc },
1884 { "PopupMoveErrorsProc", PopupMoveErrorsProc },
1885 { "PremoveProc", PremoveProc },
1886 { "QuietPlayProc", QuietPlayProc },
1887 { "ShowCoordsProc", ShowCoordsProc },
1888 { "ShowThinkingProc", ShowThinkingProc },
1889 { "HideThinkingProc", HideThinkingProc },
1890 { "TestLegalityProc", TestLegalityProc },
1891 { "InfoProc", InfoProc },
1892 { "ManProc", ManProc },
1893 { "HintProc", HintProc },
1894 { "BookProc", BookProc },
1895 { "AboutGameProc", AboutGameProc },
1896 { "AboutProc", AboutProc },
1897 { "DebugProc", DebugProc },
1898 { "NothingProc", NothingProc },
1899 { "CommentPopDown", (XtActionProc) CommentPopDown },
1900 { "EditCommentPopDown", (XtActionProc) EditCommentPopDown },
1901 { "TagsPopDown", (XtActionProc) TagsPopDown },
1902 { "ErrorPopDown", (XtActionProc) ErrorPopDown },
1903 { "ICSInputBoxPopDown", (XtActionProc) ICSInputBoxPopDown },
1904 { "FileNamePopDown", (XtActionProc) FileNamePopDown },
1905 { "AskQuestionPopDown", (XtActionProc) AskQuestionPopDown },
1906 { "GameListPopDown", (XtActionProc) GameListPopDown },
1907 { "PromotionPopDown", (XtActionProc) PromotionPopDown },
1908 { "HistoryPopDown", (XtActionProc) HistoryPopDown },
1909 { "EngineOutputPopDown", (XtActionProc) EngineOutputPopDown },
1910 { "ShufflePopDown", (XtActionProc) ShufflePopDown },
1911 { "EnginePopDown", (XtActionProc) EnginePopDown },
1912 { "UciPopDown", (XtActionProc) UciPopDown },
1913 { "TimeControlPopDown", (XtActionProc) TimeControlPopDown },
1914 { "NewVariantPopDown", (XtActionProc) NewVariantPopDown },
1915 { "SettingsPopDown", (XtActionProc) SettingsPopDown },
1918 char globalTranslations[] =
1919 ":<Key>R: ResignProc() \n \
1920 :<Key>r: ResetProc() \n \
1921 :<Key>g: LoadGameProc() \n \
1922 :<Key>N: LoadNextGameProc() \n \
1923 :<Key>P: LoadPrevGameProc() \n \
1924 :<Key>Q: QuitProc() \n \
1925 :<Key>F: ToEndProc() \n \
1926 :<Key>f: ForwardProc() \n \
1927 :<Key>B: ToStartProc() \n \
1928 :<Key>b: BackwardProc() \n \
1929 :<Key>p: PauseProc() \n \
1930 :<Key>d: DrawProc() \n \
1931 :<Key>t: CallFlagProc() \n \
1932 :<Key>i: Iconify() \n \
1933 :<Key>c: Iconify() \n \
1934 :<Key>v: FlipViewProc() \n \
1935 <KeyDown>Control_L: BackwardProc() \n \
1936 <KeyUp>Control_L: ForwardProc() \n \
1937 <KeyDown>Control_R: BackwardProc() \n \
1938 <KeyUp>Control_R: ForwardProc() \n \
1939 Shift<Key>1: AskQuestionProc(\"Direct command\",\
1940 \"Send to chess program:\",,1) \n \
1941 Shift<Key>2: AskQuestionProc(\"Direct command\",\
1942 \"Send to second chess program:\",,2) \n";
1944 char boardTranslations[] =
1945 "<Btn1Down>: HandleUserMove() \n \
1946 <Btn1Up>: HandleUserMove() \n \
1947 <Btn1Motion>: AnimateUserMove() \n \
1948 Shift<Btn2Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD)\
1949 PieceMenuPopup(menuB) \n \
1950 Any<Btn2Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD) \
1951 PieceMenuPopup(menuW) \n \
1952 Shift<Btn3Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD)\
1953 PieceMenuPopup(menuW) \n \
1954 Any<Btn3Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD) \
1955 PieceMenuPopup(menuB) \n";
1957 char whiteTranslations[] = "<BtnDown>: WhiteClock()\n";
1958 char blackTranslations[] = "<BtnDown>: BlackClock()\n";
1960 char ICSInputTranslations[] =
1961 "<Key>Return: EnterKeyProc() \n";
1963 String xboardResources[] = {
1964 "*fileName*value.translations: #override\\n <Key>Return: FileNameAction()",
1965 "*question*value.translations: #override\\n <Key>Return: AskQuestionReplyAction()",
1966 "*errorpopup*translations: #override\\n <Key>Return: ErrorPopDown()",
1971 /* Max possible square size */
1972 #define MAXSQSIZE 256
1974 static int xpm_avail[MAXSQSIZE];
1976 #ifdef HAVE_DIR_STRUCT
1978 /* Extract piece size from filename */
1980 xpm_getsize(name, len, ext)
1991 if ((p=strchr(name, '.')) == NULL ||
1992 StrCaseCmp(p+1, ext) != 0)
1998 while (*p && isdigit(*p))
2005 /* Setup xpm_avail */
2007 xpm_getavail(dirname, ext)
2015 for (i=0; i<MAXSQSIZE; ++i)
2018 if (appData.debugMode)
2019 fprintf(stderr, "XPM dir:%s:ext:%s:\n", dirname, ext);
2021 dir = opendir(dirname);
2024 fprintf(stderr, _("%s: Can't access XPM directory %s\n"),
2025 programName, dirname);
2029 while ((ent=readdir(dir)) != NULL) {
2030 i = xpm_getsize(ent->d_name, NAMLEN(ent), ext);
2031 if (i > 0 && i < MAXSQSIZE)
2041 xpm_print_avail(fp, ext)
2047 fprintf(fp, _("Available `%s' sizes:\n"), ext);
2048 for (i=1; i<MAXSQSIZE; ++i) {
2054 /* Return XPM piecesize closest to size */
2056 xpm_closest_to(dirname, size, ext)
2062 int sm_diff = MAXSQSIZE;
2066 xpm_getavail(dirname, ext);
2068 if (appData.debugMode)
2069 xpm_print_avail(stderr, ext);
2071 for (i=1; i<MAXSQSIZE; ++i) {
2074 diff = (diff<0) ? -diff : diff;
2075 if (diff < sm_diff) {
2083 fprintf(stderr, _("Error: No `%s' files!\n"), ext);
2089 #else /* !HAVE_DIR_STRUCT */
2090 /* If we are on a system without a DIR struct, we can't
2091 read the directory, so we can't collect a list of
2092 filenames, etc., so we can't do any size-fitting. */
2094 xpm_closest_to(dirname, size, ext)
2099 fprintf(stderr, _("\
2100 Warning: No DIR structure found on this system --\n\
2101 Unable to autosize for XPM/XIM pieces.\n\
2102 Please report this error to frankm@hiwaay.net.\n\
2103 Include system type & operating system in message.\n"));
2106 #endif /* HAVE_DIR_STRUCT */
2108 static char *cnames[9] = { "black", "red", "green", "yellow", "blue",
2109 "magenta", "cyan", "white" };
2113 TextColors textColors[(int)NColorClasses];
2115 /* String is: "fg, bg, attr". Which is 0, 1, 2 */
2117 parse_color(str, which)
2121 char *p, buf[100], *d;
2124 if (strlen(str) > 99) /* watch bounds on buf */
2129 for (i=0; i<which; ++i) {
2136 /* Could be looking at something like:
2138 .. in which case we want to stop on a comma also */
2139 while (*p && *p != ',' && !isalpha(*p) && !isdigit(*p))
2143 return -1; /* Use default for empty field */
2146 if (which == 2 || isdigit(*p))
2149 while (*p && isalpha(*p))
2154 for (i=0; i<8; ++i) {
2155 if (!StrCaseCmp(buf, cnames[i]))
2156 return which? (i+40) : (i+30);
2158 if (!StrCaseCmp(buf, "default")) return -1;
2160 fprintf(stderr, _("%s: unrecognized color %s\n"), programName, buf);
2165 parse_cpair(cc, str)
2169 if ((textColors[(int)cc].fg=parse_color(str, 0)) == -2) {
2170 fprintf(stderr, _("%s: can't parse foreground color in `%s'\n"),
2175 /* bg and attr are optional */
2176 textColors[(int)cc].bg = parse_color(str, 1);
2177 if ((textColors[(int)cc].attr = parse_color(str, 2)) < 0) {
2178 textColors[(int)cc].attr = 0;
2184 /* Arrange to catch delete-window events */
2185 Atom wm_delete_window;
2187 CatchDeleteWindow(Widget w, String procname)
2190 XSetWMProtocols(xDisplay, XtWindow(w), &wm_delete_window, 1);
2191 snprintf(buf, sizeof(buf), "<Message>WM_PROTOCOLS: %s() \n", procname);
2192 XtAugmentTranslations(w, XtParseTranslationTable(buf));
2199 XtSetArg(args[0], XtNiconic, False);
2200 XtSetValues(shellWidget, args, 1);
2202 XtPopup(shellWidget, XtGrabNone); /* Raise if lowered */
2206 // eventually, all layout determining code should go into a subroutine, but until then IDSIZE remains undefined
2208 #define BoardSize int
2209 void InitDrawingSizes(BoardSize boardSize, int flags)
2210 { // [HGM] resize is functional now, but for board format changes only (nr of ranks, files)
2211 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
2213 XtGeometryResult gres;
2216 if(!formWidget) return;
2219 * Enable shell resizing.
2221 shellArgs[0].value = (XtArgVal) &w;
2222 shellArgs[1].value = (XtArgVal) &h;
2223 XtGetValues(shellWidget, shellArgs, 2);
2225 shellArgs[4].value = 2*w; shellArgs[2].value = 10;
2226 shellArgs[5].value = 2*h; shellArgs[3].value = 10;
2227 XtSetValues(shellWidget, &shellArgs[2], 4);
2229 XtSetArg(args[0], XtNdefaultDistance, &sep);
2230 XtGetValues(formWidget, args, 1);
2232 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2233 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2236 XtSetArg(args[0], XtNwidth, boardWidth);
2237 XtSetArg(args[1], XtNheight, boardHeight);
2238 XtSetValues(boardWidget, args, 2);
2240 timerWidth = (boardWidth - sep) / 2;
2241 XtSetArg(args[0], XtNwidth, timerWidth);
2242 XtSetValues(whiteTimerWidget, args, 1);
2243 XtSetValues(blackTimerWidget, args, 1);
2245 XawFormDoLayout(formWidget, False);
2247 if (appData.titleInWindow) {
2249 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2250 XtSetArg(args[i], XtNheight, &h); i++;
2251 XtGetValues(titleWidget, args, i);
2253 w = boardWidth - 2*bor;
2255 XtSetArg(args[0], XtNwidth, &w);
2256 XtGetValues(menuBarWidget, args, 1);
2257 w = boardWidth - w - sep - 2*bor - 2; // WIDTH_FUDGE
2260 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
2261 if (gres != XtGeometryYes && appData.debugMode) {
2263 _("%s: titleWidget geometry error %d %d %d %d %d\n"),
2264 programName, gres, w, h, wr, hr);
2268 XawFormDoLayout(formWidget, True);
2271 * Inhibit shell resizing.
2273 shellArgs[0].value = w = (XtArgVal) boardWidth + marginW;
2274 shellArgs[1].value = h = (XtArgVal) boardHeight + marginH;
2275 shellArgs[4].value = shellArgs[2].value = w;
2276 shellArgs[5].value = shellArgs[3].value = h;
2277 XtSetValues(shellWidget, &shellArgs[0], 6);
2279 // [HGM] pieces: tailor piece bitmaps to needs of specific variant
2282 for(i=0; i<4; i++) {
2284 for(p=0; p<=(int)WhiteKing; p++)
2285 xpmPieceBitmap[i][p] = xpmPieceBitmap2[i][p]; // defaults
2286 if(gameInfo.variant == VariantShogi) {
2287 xpmPieceBitmap[i][(int)WhiteCannon] = xpmPieceBitmap2[i][(int)WhiteKing+1];
2288 xpmPieceBitmap[i][(int)WhiteNightrider] = xpmPieceBitmap2[i][(int)WhiteKing+2];
2289 xpmPieceBitmap[i][(int)WhiteSilver] = xpmPieceBitmap2[i][(int)WhiteKing+3];
2290 xpmPieceBitmap[i][(int)WhiteGrasshopper] = xpmPieceBitmap2[i][(int)WhiteKing+4];
2291 xpmPieceBitmap[i][(int)WhiteQueen] = xpmPieceBitmap2[i][(int)WhiteLance];
2294 if(gameInfo.variant == VariantGothic) {
2295 xpmPieceBitmap[i][(int)WhiteMarshall] = xpmPieceBitmap2[i][(int)WhiteSilver];
2299 // [HGM] why are thee ximMasks used at all? the ximPieceBitmaps seem to be never used!
2300 for(p=0; p<=(int)WhiteKing; p++)
2301 ximMaskPm[p] = ximMaskPm2[p]; // defaults
2302 if(gameInfo.variant == VariantShogi) {
2303 ximMaskPm[(int)WhiteCannon] = ximMaskPm2[(int)WhiteKing+1];
2304 ximMaskPm[(int)WhiteNightrider] = ximMaskPm2[(int)WhiteKing+2];
2305 ximMaskPm[(int)WhiteSilver] = ximMaskPm2[(int)WhiteKing+3];
2306 ximMaskPm[(int)WhiteGrasshopper] = ximMaskPm2[(int)WhiteKing+4];
2307 ximMaskPm[(int)WhiteQueen] = ximMaskPm2[(int)WhiteLance];
2310 if(gameInfo.variant == VariantGothic) {
2311 ximMaskPm[(int)WhiteMarshall] = ximMaskPm2[(int)WhiteSilver];
2317 for(i=0; i<2; i++) {
2319 for(p=0; p<=(int)WhiteKing; p++)
2320 pieceBitmap[i][p] = pieceBitmap2[i][p]; // defaults
2321 if(gameInfo.variant == VariantShogi) {
2322 pieceBitmap[i][(int)WhiteCannon] = pieceBitmap2[i][(int)WhiteKing+1];
2323 pieceBitmap[i][(int)WhiteNightrider] = pieceBitmap2[i][(int)WhiteKing+2];
2324 pieceBitmap[i][(int)WhiteSilver] = pieceBitmap2[i][(int)WhiteKing+3];
2325 pieceBitmap[i][(int)WhiteGrasshopper] = pieceBitmap2[i][(int)WhiteKing+4];
2326 pieceBitmap[i][(int)WhiteQueen] = pieceBitmap2[i][(int)WhiteLance];
2329 if(gameInfo.variant == VariantGothic) {
2330 pieceBitmap[i][(int)WhiteMarshall] = pieceBitmap2[i][(int)WhiteSilver];
2341 void EscapeExpand(char *p, char *q)
2342 { // [HGM] initstring: routine to shape up string arguments
2343 while(*p++ = *q++) if(p[-1] == '\\')
2345 case 'n': p[-1] = '\n'; break;
2346 case 'r': p[-1] = '\r'; break;
2347 case 't': p[-1] = '\t'; break;
2348 case '\\': p[-1] = '\\'; break;
2349 case 0: *p = 0; return;
2350 default: p[-1] = q[-1]; break;
2359 int i, j, clockFontPxlSize, coordFontPxlSize, fontPxlSize;
2360 XSetWindowAttributes window_attributes;
2362 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
2363 XrmValue vFrom, vTo;
2364 XtGeometryResult gres;
2367 int forceMono = False;
2370 // [HGM] before anything else, expand any indirection files amongst options
2371 char *argvCopy[1000]; // 1000 seems enough
2372 char newArgs[10000]; // holds actual characters
2375 srandom(time(0)); // [HGM] book: make random truly random
2378 for(i=0; i<argc; i++) {
2379 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2380 //fprintf(stderr, "arg %s\n", argv[i]);
2381 if(argv[i][0] != '@') argvCopy[j++] = argv[i]; else {
2383 FILE *f = fopen(argv[i]+1, "rb");
2384 if(f == NULL) { fprintf(stderr, _("ignore %s\n"), argv[i]); continue; } // do not expand non-existing
2385 argvCopy[j++] = newArgs + k; // get ready for first argument from file
2386 while((c = fgetc(f)) != EOF) { // each line of file inserts 1 argument in the list
2388 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2389 newArgs[k++] = 0; // terminate current arg
2390 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2391 argvCopy[j++] = newArgs + k; // get ready for next
2393 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2407 setbuf(stdout, NULL);
2408 setbuf(stderr, NULL);
2411 programName = strrchr(argv[0], '/');
2412 if (programName == NULL)
2413 programName = argv[0];
2418 XtSetLanguageProc(NULL, NULL, NULL);
2419 bindtextdomain(PACKAGE, LOCALEDIR);
2420 textdomain(PACKAGE);
2424 XtAppInitialize(&appContext, "XBoard", shellOptions,
2425 XtNumber(shellOptions),
2426 &argc, argv, xboardResources, NULL, 0);
2428 { /* left over command line arguments, print out help and exit.
2429 * Use two columns to print help
2431 fprintf(stderr, _("%s: unrecognized argument %s\n"),
2432 programName, argv[1]);
2434 fprintf(stderr, "Recognized options:\n");
2435 for(i = 0; i < XtNumber(shellOptions); i++)
2437 /* print first column */
2438 j = fprintf(stderr, " %s%s", shellOptions[i].option,
2439 (shellOptions[i].argKind == XrmoptionSepArg
2441 /* print second column and end line */
2442 if (++i < XtNumber(shellOptions))
2444 fprintf(stderr, "%*c%s%s\n", 40 - j, ' ',
2445 shellOptions[i].option,
2446 (shellOptions[i].argKind == XrmoptionSepArg
2451 fprintf(stderr, "\n");
2458 if (p == NULL) p = "/tmp";
2459 i = strlen(p) + strlen("/.xboardXXXXXx.pgn") + 1;
2460 gameCopyFilename = (char*) malloc(i);
2461 gamePasteFilename = (char*) malloc(i);
2462 snprintf(gameCopyFilename,i, "%s/.xboard%05uc.pgn", p, getpid());
2463 snprintf(gamePasteFilename,i, "%s/.xboard%05up.pgn", p, getpid());
2465 XtGetApplicationResources(shellWidget, (XtPointer) &appData,
2466 clientResources, XtNumber(clientResources),
2469 { // [HGM] initstring: kludge to fix bad bug. expand '\n' characters in init string and computer string.
2470 static char buf[MSG_SIZ];
2471 EscapeExpand(buf, appData.initString);
2472 appData.initString = strdup(buf);
2473 EscapeExpand(buf, appData.secondInitString);
2474 appData.secondInitString = strdup(buf);
2475 EscapeExpand(buf, appData.firstComputerString);
2476 appData.firstComputerString = strdup(buf);
2477 EscapeExpand(buf, appData.secondComputerString);
2478 appData.secondComputerString = strdup(buf);
2481 if ((chessDir = (char *) getenv("CHESSDIR")) == NULL) {
2484 if (chdir(chessDir) != 0) {
2485 fprintf(stderr, _("%s: can't cd to CHESSDIR: "), programName);
2491 if (appData.debugMode && appData.nameOfDebugFile && strcmp(appData.nameOfDebugFile, "stderr")) {
2492 /* [DM] debug info to file [HGM] make the filename a command-line option, and allow it to remain stderr */
2493 if ((debugFP = fopen(appData.nameOfDebugFile, "w")) == NULL) {
2494 printf(_("Failed to open file '%s'\n"), appData.nameOfDebugFile);
2497 setbuf(debugFP, NULL);
2500 /* [HGM,HR] make sure board size is acceptable */
2501 if(appData.NrFiles > BOARD_SIZE ||
2502 appData.NrRanks > BOARD_SIZE )
2503 DisplayFatalError(_("Recompile with BOARD_SIZE > 12, to support this size"), 0, 2);
2506 /* This feature does not work; animation needs a rewrite */
2507 appData.highlightDragging = FALSE;
2511 xDisplay = XtDisplay(shellWidget);
2512 xScreen = DefaultScreen(xDisplay);
2513 wm_delete_window = XInternAtom(xDisplay, "WM_DELETE_WINDOW", True);
2515 gameInfo.variant = StringToVariant(appData.variant);
2516 InitPosition(FALSE);
2519 InitDrawingSizes(-1, 0); // [HGM] initsize: make this into a subroutine
2521 if (isdigit(appData.boardSize[0])) {
2522 i = sscanf(appData.boardSize, "%d,%d,%d,%d,%d,%d,%d", &squareSize,
2523 &lineGap, &clockFontPxlSize, &coordFontPxlSize,
2524 &fontPxlSize, &smallLayout, &tinyLayout);
2526 fprintf(stderr, _("%s: bad boardSize syntax %s\n"),
2527 programName, appData.boardSize);
2531 /* Find some defaults; use the nearest known size */
2532 SizeDefaults *szd, *nearest;
2533 int distance = 99999;
2534 nearest = szd = sizeDefaults;
2535 while (szd->name != NULL) {
2536 if (abs(szd->squareSize - squareSize) < distance) {
2538 distance = abs(szd->squareSize - squareSize);
2539 if (distance == 0) break;
2543 if (i < 2) lineGap = nearest->lineGap;
2544 if (i < 3) clockFontPxlSize = nearest->clockFontPxlSize;
2545 if (i < 4) coordFontPxlSize = nearest->coordFontPxlSize;
2546 if (i < 5) fontPxlSize = nearest->fontPxlSize;
2547 if (i < 6) smallLayout = nearest->smallLayout;
2548 if (i < 7) tinyLayout = nearest->tinyLayout;
2551 SizeDefaults *szd = sizeDefaults;
2552 if (*appData.boardSize == NULLCHAR) {
2553 while (DisplayWidth(xDisplay, xScreen) < szd->minScreenSize ||
2554 DisplayHeight(xDisplay, xScreen) < szd->minScreenSize) {
2557 if (szd->name == NULL) szd--;
2559 while (szd->name != NULL &&
2560 StrCaseCmp(szd->name, appData.boardSize) != 0) szd++;
2561 if (szd->name == NULL) {
2562 fprintf(stderr, _("%s: unrecognized boardSize name %s\n"),
2563 programName, appData.boardSize);
2567 squareSize = szd->squareSize;
2568 lineGap = szd->lineGap;
2569 clockFontPxlSize = szd->clockFontPxlSize;
2570 coordFontPxlSize = szd->coordFontPxlSize;
2571 fontPxlSize = szd->fontPxlSize;
2572 smallLayout = szd->smallLayout;
2573 tinyLayout = szd->tinyLayout;
2576 /* Now, using squareSize as a hint, find a good XPM/XIM set size */
2577 if (strlen(appData.pixmapDirectory) > 0) {
2578 p = ExpandPathName(appData.pixmapDirectory);
2580 fprintf(stderr, _("Error expanding path name \"%s\"\n"),
2581 appData.pixmapDirectory);
2584 if (appData.debugMode) {
2585 fprintf(stderr, _("\
2586 XBoard square size (hint): %d\n\
2587 %s fulldir:%s:\n"), squareSize, IMAGE_EXT, p);
2589 squareSize = xpm_closest_to(p, squareSize, IMAGE_EXT);
2590 if (appData.debugMode) {
2591 fprintf(stderr, _("Closest %s size: %d\n"), IMAGE_EXT, squareSize);
2595 /* [HR] height treated separately (hacked) */
2596 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2597 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2598 if (appData.showJail == 1) {
2599 /* Jail on top and bottom */
2600 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2601 XtSetArg(boardArgs[2], XtNheight,
2602 boardHeight + 2*(lineGap + squareSize));
2603 } else if (appData.showJail == 2) {
2605 XtSetArg(boardArgs[1], XtNwidth,
2606 boardWidth + 2*(lineGap + squareSize));
2607 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2610 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2611 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2615 * Determine what fonts to use.
2617 appData.clockFont = FindFont(appData.clockFont, clockFontPxlSize);
2618 clockFontID = XLoadFont(xDisplay, appData.clockFont);
2619 clockFontStruct = XQueryFont(xDisplay, clockFontID);
2620 appData.coordFont = FindFont(appData.coordFont, coordFontPxlSize);
2621 coordFontID = XLoadFont(xDisplay, appData.coordFont);
2622 coordFontStruct = XQueryFont(xDisplay, coordFontID);
2623 appData.font = FindFont(appData.font, fontPxlSize);
2624 countFontID = XLoadFont(xDisplay, appData.coordFont); // [HGM] holdings
2625 countFontStruct = XQueryFont(xDisplay, countFontID);
2626 // appData.font = FindFont(appData.font, fontPxlSize);
2628 xdb = XtDatabase(xDisplay);
2629 XrmPutStringResource(&xdb, "*font", appData.font);
2632 * Detect if there are not enough colors available and adapt.
2634 if (DefaultDepth(xDisplay, xScreen) <= 2) {
2635 appData.monoMode = True;
2638 if (!appData.monoMode) {
2639 vFrom.addr = (caddr_t) appData.lightSquareColor;
2640 vFrom.size = strlen(appData.lightSquareColor);
2641 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2642 if (vTo.addr == NULL) {
2643 appData.monoMode = True;
2646 lightSquareColor = *(Pixel *) vTo.addr;
2649 if (!appData.monoMode) {
2650 vFrom.addr = (caddr_t) appData.darkSquareColor;
2651 vFrom.size = strlen(appData.darkSquareColor);
2652 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2653 if (vTo.addr == NULL) {
2654 appData.monoMode = True;
2657 darkSquareColor = *(Pixel *) vTo.addr;
2660 if (!appData.monoMode) {
2661 vFrom.addr = (caddr_t) appData.whitePieceColor;
2662 vFrom.size = strlen(appData.whitePieceColor);
2663 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2664 if (vTo.addr == NULL) {
2665 appData.monoMode = True;
2668 whitePieceColor = *(Pixel *) vTo.addr;
2671 if (!appData.monoMode) {
2672 vFrom.addr = (caddr_t) appData.blackPieceColor;
2673 vFrom.size = strlen(appData.blackPieceColor);
2674 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2675 if (vTo.addr == NULL) {
2676 appData.monoMode = True;
2679 blackPieceColor = *(Pixel *) vTo.addr;
2683 if (!appData.monoMode) {
2684 vFrom.addr = (caddr_t) appData.highlightSquareColor;
2685 vFrom.size = strlen(appData.highlightSquareColor);
2686 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2687 if (vTo.addr == NULL) {
2688 appData.monoMode = True;
2691 highlightSquareColor = *(Pixel *) vTo.addr;
2695 if (!appData.monoMode) {
2696 vFrom.addr = (caddr_t) appData.premoveHighlightColor;
2697 vFrom.size = strlen(appData.premoveHighlightColor);
2698 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2699 if (vTo.addr == NULL) {
2700 appData.monoMode = True;
2703 premoveHighlightColor = *(Pixel *) vTo.addr;
2708 fprintf(stderr, _("%s: too few colors available; trying monochrome mode\n"),
2711 if (appData.bitmapDirectory == NULL ||
2712 appData.bitmapDirectory[0] == NULLCHAR)
2713 appData.bitmapDirectory = DEF_BITMAP_DIR;
2716 if (appData.lowTimeWarning && !appData.monoMode) {
2717 vFrom.addr = (caddr_t) appData.lowTimeWarningColor;
2718 vFrom.size = strlen(appData.lowTimeWarningColor);
2719 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2720 if (vTo.addr == NULL)
2721 appData.monoMode = True;
2723 lowTimeWarningColor = *(Pixel *) vTo.addr;
2726 if (appData.monoMode && appData.debugMode) {
2727 fprintf(stderr, _("white pixel = 0x%lx, black pixel = 0x%lx\n"),
2728 (unsigned long) XWhitePixel(xDisplay, xScreen),
2729 (unsigned long) XBlackPixel(xDisplay, xScreen));
2732 if (parse_cpair(ColorShout, appData.colorShout) < 0 ||
2733 parse_cpair(ColorSShout, appData.colorSShout) < 0 ||
2734 parse_cpair(ColorChannel1, appData.colorChannel1) < 0 ||
2735 parse_cpair(ColorChannel, appData.colorChannel) < 0 ||
2736 parse_cpair(ColorKibitz, appData.colorKibitz) < 0 ||
2737 parse_cpair(ColorTell, appData.colorTell) < 0 ||
2738 parse_cpair(ColorChallenge, appData.colorChallenge) < 0 ||
2739 parse_cpair(ColorRequest, appData.colorRequest) < 0 ||
2740 parse_cpair(ColorSeek, appData.colorSeek) < 0 ||
2741 parse_cpair(ColorNormal, appData.colorNormal) < 0)
2743 if (appData.colorize) {
2745 _("%s: can't parse color names; disabling colorization\n"),
2748 appData.colorize = FALSE;
2750 textColors[ColorNone].fg = textColors[ColorNone].bg = -1;
2751 textColors[ColorNone].attr = 0;
2753 XtAppAddActions(appContext, boardActions, XtNumber(boardActions));
2759 layoutName = "tinyLayout";
2760 } else if (smallLayout) {
2761 layoutName = "smallLayout";
2763 layoutName = "normalLayout";
2765 /* Outer layoutWidget is there only to provide a name for use in
2766 resources that depend on the layout style */
2768 XtCreateManagedWidget(layoutName, formWidgetClass, shellWidget,
2769 layoutArgs, XtNumber(layoutArgs));
2771 XtCreateManagedWidget("form", formWidgetClass, layoutWidget,
2772 formArgs, XtNumber(formArgs));
2773 XtSetArg(args[0], XtNdefaultDistance, &sep);
2774 XtGetValues(formWidget, args, 1);
2777 widgetList[j++] = menuBarWidget = CreateMenuBar(menuBar);
2778 XtSetArg(args[0], XtNtop, XtChainTop);
2779 XtSetArg(args[1], XtNbottom, XtChainTop);
2780 XtSetArg(args[2], XtNright, XtChainLeft);
2781 XtSetValues(menuBarWidget, args, 3);
2783 widgetList[j++] = whiteTimerWidget =
2784 XtCreateWidget("whiteTime", 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(whiteTimerWidget, args, 3);
2791 widgetList[j++] = blackTimerWidget =
2792 XtCreateWidget("blackTime", labelWidgetClass,
2793 formWidget, timerArgs, XtNumber(timerArgs));
2794 XtSetArg(args[0], XtNfont, clockFontStruct);
2795 XtSetArg(args[1], XtNtop, XtChainTop);
2796 XtSetArg(args[2], XtNbottom, XtChainTop);
2797 XtSetValues(blackTimerWidget, args, 3);
2799 if (appData.titleInWindow) {
2800 widgetList[j++] = titleWidget =
2801 XtCreateWidget("title", labelWidgetClass, formWidget,
2802 titleArgs, XtNumber(titleArgs));
2803 XtSetArg(args[0], XtNtop, XtChainTop);
2804 XtSetArg(args[1], XtNbottom, XtChainTop);
2805 XtSetValues(titleWidget, args, 2);
2808 if (appData.showButtonBar) {
2809 widgetList[j++] = buttonBarWidget = CreateButtonBar(buttonBar);
2810 XtSetArg(args[0], XtNleft, XtChainRight); // [HGM] glue to right window edge
2811 XtSetArg(args[1], XtNright, XtChainRight); // for good run-time sizing
2812 XtSetArg(args[2], XtNtop, XtChainTop);
2813 XtSetArg(args[3], XtNbottom, XtChainTop);
2814 XtSetValues(buttonBarWidget, args, 4);
2817 widgetList[j++] = messageWidget =
2818 XtCreateWidget("message", labelWidgetClass, formWidget,
2819 messageArgs, XtNumber(messageArgs));
2820 XtSetArg(args[0], XtNtop, XtChainTop);
2821 XtSetArg(args[1], XtNbottom, XtChainTop);
2822 XtSetValues(messageWidget, args, 2);
2824 widgetList[j++] = boardWidget =
2825 XtCreateWidget("board", widgetClass, formWidget, boardArgs,
2826 XtNumber(boardArgs));
2828 XtManageChildren(widgetList, j);
2830 timerWidth = (boardWidth - sep) / 2;
2831 XtSetArg(args[0], XtNwidth, timerWidth);
2832 XtSetValues(whiteTimerWidget, args, 1);
2833 XtSetValues(blackTimerWidget, args, 1);
2835 XtSetArg(args[0], XtNbackground, &timerBackgroundPixel);
2836 XtSetArg(args[1], XtNforeground, &timerForegroundPixel);
2837 XtGetValues(whiteTimerWidget, args, 2);
2839 if (appData.showButtonBar) {
2840 XtSetArg(args[0], XtNbackground, &buttonBackgroundPixel);
2841 XtSetArg(args[1], XtNforeground, &buttonForegroundPixel);
2842 XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
2846 * formWidget uses these constraints but they are stored
2850 XtSetArg(args[i], XtNfromHoriz, 0); i++;
2851 XtSetValues(menuBarWidget, args, i);
2852 if (appData.titleInWindow) {
2855 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2856 XtSetValues(whiteTimerWidget, args, i);
2858 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2859 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2860 XtSetValues(blackTimerWidget, args, i);
2862 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2863 XtSetArg(args[i], XtNjustify, XtJustifyLeft); i++;
2864 XtSetValues(titleWidget, args, i);
2866 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2867 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2868 XtSetValues(messageWidget, args, i);
2869 if (appData.showButtonBar) {
2871 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2872 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2873 XtSetValues(buttonBarWidget, args, i);
2877 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2878 XtSetValues(whiteTimerWidget, args, i);
2880 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2881 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2882 XtSetValues(blackTimerWidget, args, i);
2884 XtSetArg(args[i], XtNfromHoriz, menuBarWidget); i++;
2885 XtSetValues(titleWidget, args, i);
2887 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2888 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2889 XtSetValues(messageWidget, args, i);
2890 if (appData.showButtonBar) {
2892 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2893 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2894 XtSetValues(buttonBarWidget, args, i);
2899 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2900 XtSetValues(whiteTimerWidget, args, i);
2902 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2903 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2904 XtSetValues(blackTimerWidget, args, i);
2906 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2907 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2908 XtSetValues(messageWidget, args, i);
2909 if (appData.showButtonBar) {
2911 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2912 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2913 XtSetValues(buttonBarWidget, args, i);
2917 XtSetArg(args[0], XtNfromVert, messageWidget);
2918 XtSetArg(args[1], XtNtop, XtChainTop);
2919 XtSetArg(args[2], XtNbottom, XtChainBottom);
2920 XtSetArg(args[3], XtNleft, XtChainLeft);
2921 XtSetArg(args[4], XtNright, XtChainRight);
2922 XtSetValues(boardWidget, args, 5);
2924 XtRealizeWidget(shellWidget);
2927 * Correct the width of the message and title widgets.
2928 * It is not known why some systems need the extra fudge term.
2929 * The value "2" is probably larger than needed.
2931 XawFormDoLayout(formWidget, False);
2933 #define WIDTH_FUDGE 2
2935 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2936 XtSetArg(args[i], XtNheight, &h); i++;
2937 XtGetValues(messageWidget, args, i);
2938 if (appData.showButtonBar) {
2940 XtSetArg(args[i], XtNwidth, &w); i++;
2941 XtGetValues(buttonBarWidget, args, i);
2942 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2944 w = boardWidth - 2*bor + 1; /*!! +1 compensates for kludge below */
2947 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2948 if (gres != XtGeometryYes && appData.debugMode) {
2949 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2950 programName, gres, w, h, wr, hr);
2953 /* !! Horrible hack to work around bug in XFree86 4.0.1 (X11R6.4.3) */
2954 /* The size used for the child widget in layout lags one resize behind
2955 its true size, so we resize a second time, 1 pixel smaller. Yeech! */
2957 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2958 if (gres != XtGeometryYes && appData.debugMode) {
2959 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2960 programName, gres, w, h, wr, hr);
2963 XtSetArg(args[0], XtNleft, XtChainLeft); // [HGM] glue ends for good run-time sizing
2964 XtSetArg(args[1], XtNright, XtChainRight);
2965 XtSetValues(messageWidget, args, 2);
2967 if (appData.titleInWindow) {
2969 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2970 XtSetArg(args[i], XtNheight, &h); i++;
2971 XtGetValues(titleWidget, args, i);
2973 w = boardWidth - 2*bor;
2975 XtSetArg(args[0], XtNwidth, &w);
2976 XtGetValues(menuBarWidget, args, 1);
2977 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2980 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
2981 if (gres != XtGeometryYes && appData.debugMode) {
2983 _("%s: titleWidget geometry error %d %d %d %d %d\n"),
2984 programName, gres, w, h, wr, hr);
2987 XawFormDoLayout(formWidget, True);
2989 xBoardWindow = XtWindow(boardWidget);
2991 // [HGM] it seems the layout code ends here, but perhaps the color stuff is size independent and would
2992 // not need to go into InitDrawingSizes().
2996 * Create X checkmark bitmap and initialize option menu checks.
2998 ReadBitmap(&xMarkPixmap, "checkmark.bm",
2999 checkmark_bits, checkmark_width, checkmark_height);
3000 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
3001 if (appData.alwaysPromoteToQueen) {
3002 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
3005 if (appData.animateDragging) {
3006 XtSetValues(XtNameToWidget(menuBarWidget,
3007 "menuOptions.Animate Dragging"),
3010 if (appData.animate) {
3011 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
3014 if (appData.autoComment) {
3015 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
3018 if (appData.autoCallFlag) {
3019 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
3022 if (appData.autoFlipView) {
3023 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Auto Flip View"),
3026 if (appData.autoObserve) {
3027 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
3030 if (appData.autoRaiseBoard) {
3031 XtSetValues(XtNameToWidget(menuBarWidget,
3032 "menuOptions.Auto Raise Board"), args, 1);
3034 if (appData.autoSaveGames) {
3035 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
3038 if (appData.saveGameFile[0] != NULLCHAR) {
3039 /* Can't turn this off from menu */
3040 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
3042 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
3046 if (appData.blindfold) {
3047 XtSetValues(XtNameToWidget(menuBarWidget,
3048 "menuOptions.Blindfold"), args, 1);
3050 if (appData.flashCount > 0) {
3051 XtSetValues(XtNameToWidget(menuBarWidget,
3052 "menuOptions.Flash Moves"),
3055 if (appData.getMoveList) {
3056 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
3060 if (appData.highlightDragging) {
3061 XtSetValues(XtNameToWidget(menuBarWidget,
3062 "menuOptions.Highlight Dragging"),
3066 if (appData.highlightLastMove) {
3067 XtSetValues(XtNameToWidget(menuBarWidget,
3068 "menuOptions.Highlight Last Move"),
3071 if (appData.icsAlarm) {
3072 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.ICS Alarm"),
3075 if (appData.ringBellAfterMoves) {
3076 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
3079 if (appData.oldSaveStyle) {
3080 XtSetValues(XtNameToWidget(menuBarWidget,
3081 "menuOptions.Old Save Style"), args, 1);
3083 if (appData.periodicUpdates) {
3084 XtSetValues(XtNameToWidget(menuBarWidget,
3085 "menuOptions.Periodic Updates"), args, 1);
3087 if (appData.ponderNextMove) {
3088 XtSetValues(XtNameToWidget(menuBarWidget,
3089 "menuOptions.Ponder Next Move"), args, 1);
3091 if (appData.popupExitMessage) {
3092 XtSetValues(XtNameToWidget(menuBarWidget,
3093 "menuOptions.Popup Exit Message"), args, 1);
3095 if (appData.popupMoveErrors) {
3096 XtSetValues(XtNameToWidget(menuBarWidget,
3097 "menuOptions.Popup Move Errors"), args, 1);
3099 if (appData.premove) {
3100 XtSetValues(XtNameToWidget(menuBarWidget,
3101 "menuOptions.Premove"), args, 1);
3103 if (appData.quietPlay) {
3104 XtSetValues(XtNameToWidget(menuBarWidget,
3105 "menuOptions.Quiet Play"), args, 1);
3107 if (appData.showCoords) {
3108 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
3111 if (appData.hideThinkingFromHuman) {
3112 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
3115 if (appData.testLegality) {
3116 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Test Legality"),
3123 ReadBitmap(&wIconPixmap, "icon_white.bm",
3124 icon_white_bits, icon_white_width, icon_white_height);
3125 ReadBitmap(&bIconPixmap, "icon_black.bm",
3126 icon_black_bits, icon_black_width, icon_black_height);
3127 iconPixmap = wIconPixmap;
3129 XtSetArg(args[i], XtNiconPixmap, iconPixmap); i++;
3130 XtSetValues(shellWidget, args, i);
3133 * Create a cursor for the board widget.
3135 window_attributes.cursor = XCreateFontCursor(xDisplay, XC_hand2);
3136 XChangeWindowAttributes(xDisplay, xBoardWindow,
3137 CWCursor, &window_attributes);
3140 * Inhibit shell resizing.
3142 shellArgs[0].value = (XtArgVal) &w;
3143 shellArgs[1].value = (XtArgVal) &h;
3144 XtGetValues(shellWidget, shellArgs, 2);
3145 shellArgs[4].value = shellArgs[2].value = w;
3146 shellArgs[5].value = shellArgs[3].value = h;
3147 XtSetValues(shellWidget, &shellArgs[2], 4);
3148 marginW = w - boardWidth; // [HGM] needed to set new shellWidget size when we resize board
3149 marginH = h - boardHeight;
3151 CatchDeleteWindow(shellWidget, "QuitProc");
3156 if (appData.bitmapDirectory[0] != NULLCHAR) {
3163 /* Create regular pieces */
3164 if (!useImages) CreatePieces();
3169 if (appData.animate || appData.animateDragging)
3172 XtAugmentTranslations(formWidget,
3173 XtParseTranslationTable(globalTranslations));
3174 XtAugmentTranslations(boardWidget,
3175 XtParseTranslationTable(boardTranslations));
3176 XtAugmentTranslations(whiteTimerWidget,
3177 XtParseTranslationTable(whiteTranslations));
3178 XtAugmentTranslations(blackTimerWidget,
3179 XtParseTranslationTable(blackTranslations));
3181 /* Why is the following needed on some versions of X instead
3182 * of a translation? */
3183 XtAddEventHandler(boardWidget, ExposureMask, False,
3184 (XtEventHandler) EventProc, NULL);
3189 if (errorExitStatus == -1) {
3190 if (appData.icsActive) {
3191 /* We now wait until we see "login:" from the ICS before
3192 sending the logon script (problems with timestamp otherwise) */
3193 /*ICSInitScript();*/
3194 if (appData.icsInputBox) ICSInputBoxPopUp();
3198 signal(SIGWINCH, TermSizeSigHandler);
3200 signal(SIGINT, IntSigHandler);
3201 signal(SIGTERM, IntSigHandler);
3202 if (*appData.cmailGameName != NULLCHAR) {
3203 signal(SIGUSR1, CmailSigHandler);
3206 gameInfo.boardWidth = 0; // [HGM] pieces: kludge to ensure InitPosition() calls InitDrawingSizes()
3209 XtAppMainLoop(appContext);
3210 if (appData.debugMode) fclose(debugFP); // [DM] debug
3217 if (appData.icsActive && oldICSInteractionTitle != NULL) {
3218 DisplayIcsInteractionTitle(oldICSInteractionTitle);
3220 unlink(gameCopyFilename);
3221 unlink(gamePasteFilename);
3224 RETSIGTYPE TermSizeSigHandler(int sig)
3237 CmailSigHandler(sig)
3243 signal(SIGUSR1, SIG_IGN); /* suspend handler */
3245 /* Activate call-back function CmailSigHandlerCallBack() */
3246 OutputToProcess(cmailPR, (char *)(&dummy), sizeof(int), &error);
3248 signal(SIGUSR1, CmailSigHandler); /* re-activate handler */
3252 CmailSigHandlerCallBack(isr, closure, message, count, error)
3260 ReloadCmailMsgEvent(TRUE); /* Reload cmail msg */
3262 /**** end signal code ****/
3272 f = fopen(appData.icsLogon, "r");
3278 strcat(buf, appData.icsLogon);
3279 f = fopen(buf, "r");
3283 ProcessICSInitScript(f);
3290 EditCommentPopDown();
3301 SetMenuEnables(enab)
3305 if (!menuBarWidget) return;
3306 while (enab->name != NULL) {
3307 w = XtNameToWidget(menuBarWidget, enab->name);
3309 DisplayError(enab->name, 0);
3311 XtSetSensitive(w, enab->value);
3317 Enables icsEnables[] = {
3318 { "menuFile.Mail Move", False },
3319 { "menuFile.Reload CMail Message", False },
3320 { "menuMode.Machine Black", False },
3321 { "menuMode.Machine White", False },
3322 { "menuMode.Analysis Mode", False },
3323 { "menuMode.Analyze File", False },
3324 { "menuMode.Two Machines", False },
3326 { "menuHelp.Hint", False },
3327 { "menuHelp.Book", False },
3328 { "menuStep.Move Now", False },
3329 { "menuOptions.Periodic Updates", False },
3330 { "menuOptions.Hide Thinking", False },
3331 { "menuOptions.Ponder Next Move", False },
3336 Enables ncpEnables[] = {
3337 { "menuFile.Mail Move", False },
3338 { "menuFile.Reload CMail Message", False },
3339 { "menuMode.Machine White", False },
3340 { "menuMode.Machine Black", False },
3341 { "menuMode.Analysis Mode", False },
3342 { "menuMode.Analyze File", False },
3343 { "menuMode.Two Machines", False },
3344 { "menuMode.ICS Client", False },
3345 { "menuMode.ICS Input Box", False },
3346 { "Action", False },
3347 { "menuStep.Revert", False },
3348 { "menuStep.Move Now", False },
3349 { "menuStep.Retract Move", False },
3350 { "menuOptions.Auto Comment", False },
3351 { "menuOptions.Auto Flag", False },
3352 { "menuOptions.Auto Flip View", False },
3353 { "menuOptions.Auto Observe", False },
3354 { "menuOptions.Auto Raise Board", False },
3355 { "menuOptions.Get Move List", False },
3356 { "menuOptions.ICS Alarm", False },
3357 { "menuOptions.Move Sound", False },
3358 { "menuOptions.Quiet Play", False },
3359 { "menuOptions.Hide Thinking", False },
3360 { "menuOptions.Periodic Updates", False },
3361 { "menuOptions.Ponder Next Move", False },
3362 { "menuHelp.Hint", False },
3363 { "menuHelp.Book", False },
3367 Enables gnuEnables[] = {
3368 { "menuMode.ICS Client", False },
3369 { "menuMode.ICS Input Box", False },
3370 { "menuAction.Accept", False },
3371 { "menuAction.Decline", False },
3372 { "menuAction.Rematch", False },
3373 { "menuAction.Adjourn", False },
3374 { "menuAction.Stop Examining", False },
3375 { "menuAction.Stop Observing", False },
3376 { "menuStep.Revert", False },
3377 { "menuOptions.Auto Comment", False },
3378 { "menuOptions.Auto Observe", False },
3379 { "menuOptions.Auto Raise Board", False },
3380 { "menuOptions.Get Move List", False },
3381 { "menuOptions.Premove", False },
3382 { "menuOptions.Quiet Play", False },
3384 /* The next two options rely on SetCmailMode being called *after* */
3385 /* SetGNUMode so that when GNU is being used to give hints these */
3386 /* menu options are still available */
3388 { "menuFile.Mail Move", False },
3389 { "menuFile.Reload CMail Message", False },
3393 Enables cmailEnables[] = {
3395 { "menuAction.Call Flag", False },
3396 { "menuAction.Draw", True },
3397 { "menuAction.Adjourn", False },
3398 { "menuAction.Abort", False },
3399 { "menuAction.Stop Observing", False },
3400 { "menuAction.Stop Examining", False },
3401 { "menuFile.Mail Move", True },
3402 { "menuFile.Reload CMail Message", True },
3406 Enables trainingOnEnables[] = {
3407 { "menuMode.Edit Comment", False },
3408 { "menuMode.Pause", False },
3409 { "menuStep.Forward", False },
3410 { "menuStep.Backward", False },
3411 { "menuStep.Forward to End", False },
3412 { "menuStep.Back to Start", False },
3413 { "menuStep.Move Now", False },
3414 { "menuStep.Truncate Game", False },
3418 Enables trainingOffEnables[] = {
3419 { "menuMode.Edit Comment", True },
3420 { "menuMode.Pause", True },
3421 { "menuStep.Forward", True },
3422 { "menuStep.Backward", True },
3423 { "menuStep.Forward to End", True },
3424 { "menuStep.Back to Start", True },
3425 { "menuStep.Move Now", True },
3426 { "menuStep.Truncate Game", True },
3430 Enables machineThinkingEnables[] = {
3431 { "menuFile.Load Game", False },
3432 { "menuFile.Load Next Game", False },
3433 { "menuFile.Load Previous Game", False },
3434 { "menuFile.Reload Same Game", False },
3435 { "menuFile.Paste Game", False },
3436 { "menuFile.Load Position", False },
3437 { "menuFile.Load Next Position", False },
3438 { "menuFile.Load Previous Position", False },
3439 { "menuFile.Reload Same Position", False },
3440 { "menuFile.Paste Position", False },
3441 { "menuMode.Machine White", False },
3442 { "menuMode.Machine Black", False },
3443 { "menuMode.Two Machines", False },
3444 { "menuStep.Retract Move", False },
3448 Enables userThinkingEnables[] = {
3449 { "menuFile.Load Game", True },
3450 { "menuFile.Load Next Game", True },
3451 { "menuFile.Load Previous Game", True },
3452 { "menuFile.Reload Same Game", True },
3453 { "menuFile.Paste Game", True },
3454 { "menuFile.Load Position", True },
3455 { "menuFile.Load Next Position", True },
3456 { "menuFile.Load Previous Position", True },
3457 { "menuFile.Reload Same Position", True },
3458 { "menuFile.Paste Position", True },
3459 { "menuMode.Machine White", True },
3460 { "menuMode.Machine Black", True },
3461 { "menuMode.Two Machines", True },
3462 { "menuStep.Retract Move", True },
3468 SetMenuEnables(icsEnables);
3471 if (appData.zippyPlay && !appData.noChessProgram) /* [DM] icsEngineAnalyze */
3472 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Analysis Mode"), True);
3479 SetMenuEnables(ncpEnables);
3485 SetMenuEnables(gnuEnables);
3491 SetMenuEnables(cmailEnables);
3497 SetMenuEnables(trainingOnEnables);
3498 if (appData.showButtonBar) {
3499 XtSetSensitive(buttonBarWidget, False);
3505 SetTrainingModeOff()
3507 SetMenuEnables(trainingOffEnables);
3508 if (appData.showButtonBar) {
3509 XtSetSensitive(buttonBarWidget, True);
3514 SetUserThinkingEnables()
3516 if (appData.noChessProgram) return;
3517 SetMenuEnables(userThinkingEnables);
3521 SetMachineThinkingEnables()
3523 if (appData.noChessProgram) return;
3524 SetMenuEnables(machineThinkingEnables);
3526 case MachinePlaysBlack:
3527 case MachinePlaysWhite:
3528 case TwoMachinesPlay:
3529 XtSetSensitive(XtNameToWidget(menuBarWidget,
3530 ModeToWidgetName(gameMode)), True);
3537 #define Abs(n) ((n)<0 ? -(n) : (n))
3540 * Find a font that matches "pattern" that is as close as
3541 * possible to the targetPxlSize. Prefer fonts that are k
3542 * pixels smaller to fonts that are k pixels larger. The
3543 * pattern must be in the X Consortium standard format,
3544 * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".
3545 * The return value should be freed with XtFree when no
3548 char *FindFont(pattern, targetPxlSize)
3552 char **fonts, *p, *best, *scalable, *scalableTail;
3553 int i, j, nfonts, minerr, err, pxlSize;
3556 char **missing_list;
3558 char *def_string, *base_fnt_lst, strInt[3];
3560 XFontStruct **fnt_list;
3562 base_fnt_lst = calloc(1, strlen(pattern) + 3);
3563 sprintf(strInt, "%d", targetPxlSize);
3564 p = strstr(pattern, "--");
3565 strncpy(base_fnt_lst, pattern, p - pattern + 2);
3566 strcat(base_fnt_lst, strInt);
3567 strcat(base_fnt_lst, strchr(p + 2, '-'));
3569 if ((fntSet = XCreateFontSet(xDisplay,
3573 &def_string)) == NULL) {
3575 fprintf(stderr, _("Unable to create font set.\n"));
3579 nfonts = XFontsOfFontSet(fntSet, &fnt_list, &fonts);
3581 fonts = XListFonts(xDisplay, pattern, 999999, &nfonts);
3583 fprintf(stderr, _("%s: no fonts match pattern %s\n"),
3584 programName, pattern);
3592 for (i=0; i<nfonts; i++) {
3595 if (*p != '-') continue;
3597 if (*p == NULLCHAR) break;
3598 if (*p++ == '-') j++;
3600 if (j < 7) continue;
3603 scalable = fonts[i];
3606 err = pxlSize - targetPxlSize;
3607 if (Abs(err) < Abs(minerr) ||
3608 (minerr > 0 && err < 0 && -err == minerr)) {
3614 if (scalable && Abs(minerr) > appData.fontSizeTolerance) {
3615 /* If the error is too big and there is a scalable font,
3616 use the scalable font. */
3617 int headlen = scalableTail - scalable;
3618 p = (char *) XtMalloc(strlen(scalable) + 10);
3619 while (isdigit(*scalableTail)) scalableTail++;
3620 sprintf(p, "%.*s%d%s", headlen, scalable, targetPxlSize, scalableTail);
3622 p = (char *) XtMalloc(strlen(best) + 1);
3625 if (appData.debugMode) {
3626 fprintf(debugFP, _("resolved %s at pixel size %d\n to %s\n"),
3627 pattern, targetPxlSize, p);
3630 if (missing_count > 0)
3631 XFreeStringList(missing_list);
3632 XFreeFontSet(xDisplay, fntSet);
3634 XFreeFontNames(fonts);
3641 XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
3642 | GCBackground | GCFunction | GCPlaneMask;
3643 XGCValues gc_values;
3646 gc_values.plane_mask = AllPlanes;
3647 gc_values.line_width = lineGap;
3648 gc_values.line_style = LineSolid;
3649 gc_values.function = GXcopy;
3651 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3652 gc_values.background = XBlackPixel(xDisplay, xScreen);
3653 lineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3655 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3656 gc_values.background = XWhitePixel(xDisplay, xScreen);
3657 coordGC = XtGetGC(shellWidget, value_mask, &gc_values);
3658 XSetFont(xDisplay, coordGC, coordFontID);
3660 // [HGM] make font for holdings counts (white on black0
3661 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3662 gc_values.background = XBlackPixel(xDisplay, xScreen);
3663 countGC = XtGetGC(shellWidget, value_mask, &gc_values);
3664 XSetFont(xDisplay, countGC, countFontID);
3666 if (appData.monoMode) {
3667 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3668 gc_values.background = XWhitePixel(xDisplay, xScreen);
3669 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3671 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3672 gc_values.background = XBlackPixel(xDisplay, xScreen);
3673 lightSquareGC = wbPieceGC
3674 = XtGetGC(shellWidget, value_mask, &gc_values);
3676 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3677 gc_values.background = XWhitePixel(xDisplay, xScreen);
3678 darkSquareGC = bwPieceGC
3679 = XtGetGC(shellWidget, value_mask, &gc_values);
3681 if (DefaultDepth(xDisplay, xScreen) == 1) {
3682 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
3683 gc_values.function = GXcopyInverted;
3684 copyInvertedGC = XtGetGC(shellWidget, value_mask, &gc_values);
3685 gc_values.function = GXcopy;
3686 if (XBlackPixel(xDisplay, xScreen) == 1) {
3687 bwPieceGC = darkSquareGC;
3688 wbPieceGC = copyInvertedGC;
3690 bwPieceGC = copyInvertedGC;
3691 wbPieceGC = lightSquareGC;
3695 gc_values.foreground = highlightSquareColor;
3696 gc_values.background = highlightSquareColor;
3697 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3699 gc_values.foreground = premoveHighlightColor;
3700 gc_values.background = premoveHighlightColor;
3701 prelineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3703 gc_values.foreground = lightSquareColor;
3704 gc_values.background = darkSquareColor;
3705 lightSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3707 gc_values.foreground = darkSquareColor;
3708 gc_values.background = lightSquareColor;
3709 darkSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3711 gc_values.foreground = jailSquareColor;
3712 gc_values.background = jailSquareColor;
3713 jailSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3715 gc_values.foreground = whitePieceColor;
3716 gc_values.background = darkSquareColor;
3717 wdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3719 gc_values.foreground = whitePieceColor;
3720 gc_values.background = lightSquareColor;
3721 wlPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3723 gc_values.foreground = whitePieceColor;
3724 gc_values.background = jailSquareColor;
3725 wjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3727 gc_values.foreground = blackPieceColor;
3728 gc_values.background = darkSquareColor;
3729 bdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3731 gc_values.foreground = blackPieceColor;
3732 gc_values.background = lightSquareColor;
3733 blPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3735 gc_values.foreground = blackPieceColor;
3736 gc_values.background = jailSquareColor;
3737 bjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3741 void loadXIM(xim, xmask, filename, dest, mask)
3754 fp = fopen(filename, "rb");
3756 fprintf(stderr, _("%s: error loading XIM!\n"), programName);
3763 for (y=0; y<h; ++y) {
3764 for (x=0; x<h; ++x) {
3769 XPutPixel(xim, x, y, blackPieceColor);
3771 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3774 XPutPixel(xim, x, y, darkSquareColor);
3776 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3779 XPutPixel(xim, x, y, whitePieceColor);
3781 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3784 XPutPixel(xim, x, y, lightSquareColor);
3786 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3792 /* create Pixmap of piece */
3793 *dest = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3795 XPutImage(xDisplay, *dest, lightSquareGC, xim,
3798 /* create Pixmap of clipmask
3799 Note: We assume the white/black pieces have the same
3800 outline, so we make only 6 masks. This is okay
3801 since the XPM clipmask routines do the same. */
3803 temp = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3805 XPutImage(xDisplay, temp, lightSquareGC, xmask,
3808 /* now create the 1-bit version */
3809 *mask = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3812 values.foreground = 1;
3813 values.background = 0;
3815 /* Don't use XtGetGC, not read only */
3816 maskGC = XCreateGC(xDisplay, *mask,
3817 GCForeground | GCBackground, &values);
3818 XCopyPlane(xDisplay, temp, *mask, maskGC,
3819 0, 0, squareSize, squareSize, 0, 0, 1);
3820 XFreePixmap(xDisplay, temp);
3825 char pieceBitmapNames[] = "pnbrqfeacwmohijgdvlsukpnsl";
3827 void CreateXIMPieces()
3832 static char *ximkind[] = { "ll", "ld", "dl", "dd" };
3837 /* The XSynchronize calls were copied from CreatePieces.
3838 Not sure if needed, but can't hurt */
3839 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3842 /* temp needed by loadXIM() */
3843 ximtemp = XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3844 0, 0, ss, ss, AllPlanes, XYPixmap);
3846 if (strlen(appData.pixmapDirectory) == 0) {
3850 if (appData.monoMode) {
3851 DisplayFatalError(_("XIM pieces cannot be used in monochrome mode"),
3855 fprintf(stderr, _("\nLoading XIMs...\n"));
3857 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3858 fprintf(stderr, "%d", piece+1);
3859 for (kind=0; kind<4; kind++) {
3860 fprintf(stderr, ".");
3861 snprintf(buf, sizeof(buf), "%s/%s%c%s%u.xim",
3862 ExpandPathName(appData.pixmapDirectory),
3863 piece <= (int) WhiteKing ? "" : "w",
3864 pieceBitmapNames[piece],
3866 ximPieceBitmap[kind][piece] =
3867 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3868 0, 0, ss, ss, AllPlanes, XYPixmap);
3869 if (appData.debugMode)
3870 fprintf(stderr, _("(File:%s:) "), buf);
3871 loadXIM(ximPieceBitmap[kind][piece],
3873 &(xpmPieceBitmap2[kind][piece]),
3874 &(ximMaskPm2[piece]));
3875 if(piece <= (int)WhiteKing)
3876 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3878 fprintf(stderr," ");
3880 /* Load light and dark squares */
3881 /* If the LSQ and DSQ pieces don't exist, we will
3882 draw them with solid squares. */
3883 snprintf(buf,sizeof(buf), "%s/lsq%u.xim", ExpandPathName(appData.pixmapDirectory), ss);
3884 if (access(buf, 0) != 0) {
3888 fprintf(stderr, _("light square "));
3890 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3891 0, 0, ss, ss, AllPlanes, XYPixmap);
3892 if (appData.debugMode)
3893 fprintf(stderr, _("(File:%s:) "), buf);
3895 loadXIM(ximLightSquare, NULL, buf, &xpmLightSquare, NULL);
3896 fprintf(stderr, _("dark square "));
3897 snprintf(buf,sizeof(buf), "%s/dsq%u.xim",
3898 ExpandPathName(appData.pixmapDirectory), ss);
3899 if (appData.debugMode)
3900 fprintf(stderr, _("(File:%s:) "), buf);
3902 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3903 0, 0, ss, ss, AllPlanes, XYPixmap);
3904 loadXIM(ximDarkSquare, NULL, buf, &xpmDarkSquare, NULL);
3905 xpmJailSquare = xpmLightSquare;
3907 fprintf(stderr, _("Done.\n"));
3909 XSynchronize(xDisplay, False); /* Work-around for xlib/xt buffering bug */
3913 void CreateXPMPieces()
3917 u_int ss = squareSize;
3919 static char *xpmkind[] = { "ll", "ld", "dl", "dd" };
3920 XpmColorSymbol symbols[4];
3922 /* The XSynchronize calls were copied from CreatePieces.
3923 Not sure if needed, but can't hurt */
3924 XSynchronize(xDisplay, True); /* Work-around for xlib/xt buffering bug */
3926 /* Setup translations so piece colors match square colors */
3927 symbols[0].name = "light_piece";
3928 symbols[0].value = appData.whitePieceColor;
3929 symbols[1].name = "dark_piece";
3930 symbols[1].value = appData.blackPieceColor;
3931 symbols[2].name = "light_square";
3932 symbols[2].value = appData.lightSquareColor;
3933 symbols[3].name = "dark_square";
3934 symbols[3].value = appData.darkSquareColor;
3936 attr.valuemask = XpmColorSymbols;
3937 attr.colorsymbols = symbols;
3938 attr.numsymbols = 4;
3940 if (appData.monoMode) {
3941 DisplayFatalError(_("XPM pieces cannot be used in monochrome mode"),
3945 if (strlen(appData.pixmapDirectory) == 0) {
3946 XpmPieces* pieces = builtInXpms;
3949 while (pieces->size != squareSize && pieces->size) pieces++;
3950 if (!pieces->size) {
3951 fprintf(stderr, _("No builtin XPM pieces of size %d\n"), squareSize);
3954 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3955 for (kind=0; kind<4; kind++) {
3957 if ((r=XpmCreatePixmapFromData(xDisplay, xBoardWindow,
3958 pieces->xpm[piece][kind],
3959 &(xpmPieceBitmap2[kind][piece]),
3960 NULL, &attr)) != 0) {
3961 fprintf(stderr, _("Error %d loading XPM image \"%s\"\n"),
3965 if(piece <= (int) WhiteKing)
3966 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3970 xpmJailSquare = xpmLightSquare;
3974 fprintf(stderr, _("\nLoading XPMs...\n"));
3977 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3978 fprintf(stderr, "%d ", piece+1);
3979 for (kind=0; kind<4; kind++) {
3980 snprintf(buf, sizeof(buf), "%s/%s%c%s%u.xpm",
3981 ExpandPathName(appData.pixmapDirectory),
3982 piece > (int) WhiteKing ? "w" : "",
3983 pieceBitmapNames[piece],
3985 if (appData.debugMode) {
3986 fprintf(stderr, _("(File:%s:) "), buf);
3988 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3989 &(xpmPieceBitmap2[kind][piece]),
3990 NULL, &attr)) != 0) {
3991 if(piece != (int)WhiteKing && piece > (int)WhiteQueen) {
3992 // [HGM] missing: read of unorthodox piece failed; substitute King.
3993 snprintf(buf, sizeof(buf), "%s/k%s%u.xpm",
3994 ExpandPathName(appData.pixmapDirectory),
3996 if (appData.debugMode) {
3997 fprintf(stderr, _("(Replace by File:%s:) "), buf);
3999 r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
4000 &(xpmPieceBitmap2[kind][piece]),
4004 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"),
4009 if(piece <= (int) WhiteKing)
4010 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
4013 /* Load light and dark squares */
4014 /* If the LSQ and DSQ pieces don't exist, we will
4015 draw them with solid squares. */
4016 fprintf(stderr, _("light square "));
4017 snprintf(buf, sizeof(buf), "%s/lsq%u.xpm", ExpandPathName(appData.pixmapDirectory), ss);
4018 if (access(buf, 0) != 0) {
4022 if (appData.debugMode)
4023 fprintf(stderr, _("(File:%s:) "), buf);
4025 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
4026 &xpmLightSquare, NULL, &attr)) != 0) {
4027 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
4030 fprintf(stderr, _("dark square "));
4031 snprintf(buf, sizeof(buf), "%s/dsq%u.xpm",
4032 ExpandPathName(appData.pixmapDirectory), ss);
4033 if (appData.debugMode) {
4034 fprintf(stderr, _("(File:%s:) "), buf);
4036 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
4037 &xpmDarkSquare, NULL, &attr)) != 0) {
4038 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
4042 xpmJailSquare = xpmLightSquare;
4043 fprintf(stderr, _("Done.\n"));
4045 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
4048 #endif /* HAVE_LIBXPM */
4051 /* No built-in bitmaps */
4056 u_int ss = squareSize;
4058 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
4061 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
4062 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
4063 sprintf(buf, "%s%c%u%c.bm", piece > (int)WhiteKing ? "w" : "",
4064 pieceBitmapNames[piece],
4065 ss, kind == SOLID ? 's' : 'o');
4066 ReadBitmap(&pieceBitmap2[kind][piece], buf, NULL, ss, ss);
4067 if(piece <= (int)WhiteKing)
4068 pieceBitmap[kind][piece] = pieceBitmap2[kind][piece];
4072 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
4076 /* With built-in bitmaps */
4079 BuiltInBits* bib = builtInBits;
4082 u_int ss = squareSize;
4084 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
4087 while (bib->squareSize != ss && bib->squareSize != 0) bib++;
4089 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
4090 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
4091 sprintf(buf, "%s%c%u%c.bm", piece > (int)WhiteKing ? "w" : "",
4092 pieceBitmapNames[piece],
4093 ss, kind == SOLID ? 's' : 'o');
4094 ReadBitmap(&pieceBitmap2[kind][piece], buf,
4095 bib->bits[kind][piece], ss, ss);
4096 if(piece <= (int)WhiteKing)
4097 pieceBitmap[kind][piece] = pieceBitmap2[kind][piece];
4101 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
4106 void ReadBitmap(pm, name, bits, wreq, hreq)
4109 unsigned char bits[];
4115 char msg[MSG_SIZ], fullname[MSG_SIZ];
4117 if (*appData.bitmapDirectory != NULLCHAR) {
4118 strcpy(fullname, appData.bitmapDirectory);
4119 strcat(fullname, "/");
4120 strcat(fullname, name);
4121 errcode = XReadBitmapFile(xDisplay, xBoardWindow, fullname,
4122 &w, &h, pm, &x_hot, &y_hot);
4123 fprintf(stderr, "load %s\n", name);
4124 if (errcode != BitmapSuccess) {
4126 case BitmapOpenFailed:
4127 snprintf(msg, sizeof(msg), _("Can't open bitmap file %s"), fullname);
4129 case BitmapFileInvalid:
4130 snprintf(msg, sizeof(msg), _("Invalid bitmap in file %s"), fullname);
4132 case BitmapNoMemory:
4133 snprintf(msg, sizeof(msg), _("Ran out of memory reading bitmap file %s"),
4137 snprintf(msg, sizeof(msg), _("Unknown XReadBitmapFile error %d on file %s"),
4141 fprintf(stderr, _("%s: %s...using built-in\n"),
4143 } else if (w != wreq || h != hreq) {
4145 _("%s: Bitmap %s is %dx%d, not %dx%d...using built-in\n"),
4146 programName, fullname, w, h, wreq, hreq);
4152 *pm = XCreateBitmapFromData(xDisplay, xBoardWindow, (char *) bits,
4161 if (lineGap == 0) return;
4163 /* [HR] Split this into 2 loops for non-square boards. */
4165 for (i = 0; i < BOARD_HEIGHT + 1; i++) {
4166 gridSegments[i].x1 = 0;
4167 gridSegments[i].x2 =
4168 lineGap + BOARD_WIDTH * (squareSize + lineGap);
4169 gridSegments[i].y1 = gridSegments[i].y2
4170 = lineGap / 2 + (i * (squareSize + lineGap));
4173 for (j = 0; j < BOARD_WIDTH + 1; j++) {
4174 gridSegments[j + i].y1 = 0;
4175 gridSegments[j + i].y2 =
4176 lineGap + BOARD_HEIGHT * (squareSize + lineGap);
4177 gridSegments[j + i].x1 = gridSegments[j + i].x2
4178 = lineGap / 2 + (j * (squareSize + lineGap));
4182 static void MenuBarSelect(w, addr, index)
4187 XtActionProc proc = (XtActionProc) addr;
4189 (proc)(NULL, NULL, NULL, NULL);
4192 void CreateMenuBarPopup(parent, name, mb)
4202 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
4205 XtSetArg(args[j], XtNleftMargin, 20); j++;
4206 XtSetArg(args[j], XtNrightMargin, 20); j++;
4208 while (mi->string != NULL) {
4209 if (strcmp(mi->string, "----") == 0) {
4210 entry = XtCreateManagedWidget(mi->string, smeLineObjectClass,
4213 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string)));
4214 entry = XtCreateManagedWidget(mi->string, smeBSBObjectClass,
4216 XtAddCallback(entry, XtNcallback,
4217 (XtCallbackProc) MenuBarSelect,
4218 (caddr_t) mi->proc);
4224 Widget CreateMenuBar(mb)
4228 Widget anchor, menuBar;
4230 char menuName[MSG_SIZ];
4233 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
4234 XtSetArg(args[j], XtNvSpace, 0); j++;
4235 XtSetArg(args[j], XtNborderWidth, 0); j++;
4236 menuBar = XtCreateWidget("menuBar", boxWidgetClass,
4237 formWidget, args, j);
4239 while (mb->name != NULL) {
4240 strcpy(menuName, "menu");
4241 strcat(menuName, mb->name);
4243 XtSetArg(args[j], XtNmenuName, XtNewString(menuName)); j++;
4246 shortName[0] = _(mb->name)[0];
4247 shortName[1] = NULLCHAR;
4248 XtSetArg(args[j], XtNlabel, XtNewString(shortName)); j++;
4251 XtSetArg(args[j], XtNlabel, XtNewString(_(mb->name))); j++;
4254 XtSetArg(args[j], XtNborderWidth, 0); j++;
4255 anchor = XtCreateManagedWidget(mb->name, menuButtonWidgetClass,
4257 CreateMenuBarPopup(menuBar, menuName, mb);
4263 Widget CreateButtonBar(mi)
4267 Widget button, buttonBar;
4271 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
4273 XtSetArg(args[j], XtNhSpace, 0); j++;
4275 XtSetArg(args[j], XtNborderWidth, 0); j++;
4276 XtSetArg(args[j], XtNvSpace, 0); j++;
4277 buttonBar = XtCreateWidget("buttonBar", boxWidgetClass,
4278 formWidget, args, j);
4280 while (mi->string != NULL) {
4283 XtSetArg(args[j], XtNinternalWidth, 2); j++;
4284 XtSetArg(args[j], XtNborderWidth, 0); j++;
4286 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string))); j++;
4287 button = XtCreateManagedWidget(mi->string, commandWidgetClass,
4288 buttonBar, args, j);
4289 XtAddCallback(button, XtNcallback,
4290 (XtCallbackProc) MenuBarSelect,
4291 (caddr_t) mi->proc);
4298 CreatePieceMenu(name, color)
4305 ChessSquare selection;
4307 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
4308 boardWidget, args, 0);
4310 for (i = 0; i < PIECE_MENU_SIZE; i++) {
4311 String item = pieceMenuStrings[color][i];
4313 if (strcmp(item, "----") == 0) {
4314 entry = XtCreateManagedWidget(item, smeLineObjectClass,
4317 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
4318 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
4320 selection = pieceMenuTranslation[color][i];
4321 XtAddCallback(entry, XtNcallback,
4322 (XtCallbackProc) PieceMenuSelect,
4323 (caddr_t) selection);
4324 if (selection == WhitePawn || selection == BlackPawn) {
4325 XtSetArg(args[0], XtNpopupOnEntry, entry);
4326 XtSetValues(menu, args, 1);
4339 ChessSquare selection;
4341 whitePieceMenu = CreatePieceMenu("menuW", 0);
4342 blackPieceMenu = CreatePieceMenu("menuB", 1);
4344 XtRegisterGrabAction(PieceMenuPopup, True,
4345 (unsigned)(ButtonPressMask|ButtonReleaseMask),
4346 GrabModeAsync, GrabModeAsync);
4348 XtSetArg(args[0], XtNlabel, _("Drop"));
4349 dropMenu = XtCreatePopupShell("menuD", simpleMenuWidgetClass,
4350 boardWidget, args, 1);
4351 for (i = 0; i < DROP_MENU_SIZE; i++) {
4352 String item = dropMenuStrings[i];
4354 if (strcmp(item, "----") == 0) {
4355 entry = XtCreateManagedWidget(item, smeLineObjectClass,
4358 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
4359 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
4361 selection = dropMenuTranslation[i];
4362 XtAddCallback(entry, XtNcallback,
4363 (XtCallbackProc) DropMenuSelect,
4364 (caddr_t) selection);
4369 void SetupDropMenu()
4377 for (i=0; i<sizeof(dmEnables)/sizeof(DropMenuEnables); i++) {
4378 entry = XtNameToWidget(dropMenu, dmEnables[i].widget);
4379 p = strchr(gameMode == IcsPlayingWhite ? white_holding : black_holding,
4380 dmEnables[i].piece);
4381 XtSetSensitive(entry, p != NULL || !appData.testLegality
4382 /*!!temp:*/ || (gameInfo.variant == VariantCrazyhouse
4383 && !appData.icsActive));
4385 while (p && *p++ == dmEnables[i].piece) count++;
4386 snprintf(label, sizeof(label), "%s %d", dmEnables[i].widget, count);
4388 XtSetArg(args[j], XtNlabel, label); j++;
4389 XtSetValues(entry, args, j);
4393 void PieceMenuPopup(w, event, params, num_params)
4397 Cardinal *num_params;
4400 if (event->type != ButtonPress) return;
4401 if (errorUp) ErrorPopDown();
4405 whichMenu = params[0];
4407 case IcsPlayingWhite:
4408 case IcsPlayingBlack:
4410 case MachinePlaysWhite:
4411 case MachinePlaysBlack:
4412 if (appData.testLegality &&
4413 gameInfo.variant != VariantBughouse &&
4414 gameInfo.variant != VariantCrazyhouse) return;
4416 whichMenu = "menuD";
4422 if (((pmFromX = EventToSquare(event->xbutton.x, BOARD_WIDTH)) < 0) ||
4423 ((pmFromY = EventToSquare(event->xbutton.y, BOARD_HEIGHT)) < 0)) {
4424 pmFromX = pmFromY = -1;
4428 pmFromX = BOARD_WIDTH - 1 - pmFromX;
4430 pmFromY = BOARD_HEIGHT - 1 - pmFromY;
4432 XtPopupSpringLoaded(XtNameToWidget(boardWidget, whichMenu));
4435 static void PieceMenuSelect(w, piece, junk)
4440 if (pmFromX < 0 || pmFromY < 0) return;
4441 EditPositionMenuEvent(piece, pmFromX, pmFromY);
4444 static void DropMenuSelect(w, piece, junk)
4449 if (pmFromX < 0 || pmFromY < 0) return;
4450 DropMenuEvent(piece, pmFromX, pmFromY);
4453 void WhiteClock(w, event, prms, nprms)
4459 if (gameMode == EditPosition || gameMode == IcsExamining) {
4460 SetWhiteToPlayEvent();
4461 } else if (gameMode == IcsPlayingBlack || gameMode == MachinePlaysWhite) {
4466 void BlackClock(w, event, prms, nprms)
4472 if (gameMode == EditPosition || gameMode == IcsExamining) {
4473 SetBlackToPlayEvent();
4474 } else if (gameMode == IcsPlayingWhite || gameMode == MachinePlaysBlack) {
4481 * If the user selects on a border boundary, return -1; if off the board,
4482 * return -2. Otherwise map the event coordinate to the square.
4484 int EventToSquare(x, limit)
4492 if ((x % (squareSize + lineGap)) >= squareSize)
4494 x /= (squareSize + lineGap);
4500 static void do_flash_delay(msec)
4506 static void drawHighlight(file, rank, gc)
4512 if (lineGap == 0 || appData.blindfold) return;
4515 x = lineGap/2 + ((BOARD_WIDTH-1)-file) *
4516 (squareSize + lineGap);
4517 y = lineGap/2 + rank * (squareSize + lineGap);
4519 x = lineGap/2 + file * (squareSize + lineGap);
4520 y = lineGap/2 + ((BOARD_HEIGHT-1)-rank) *
4521 (squareSize + lineGap);
4524 XDrawRectangle(xDisplay, xBoardWindow, gc, x, y,
4525 squareSize+lineGap, squareSize+lineGap);
4528 int hi1X = -1, hi1Y = -1, hi2X = -1, hi2Y = -1;
4529 int pm1X = -1, pm1Y = -1, pm2X = -1, pm2Y = -1;
4532 SetHighlights(fromX, fromY, toX, toY)
4533 int fromX, fromY, toX, toY;
4535 if (hi1X != fromX || hi1Y != fromY) {
4536 if (hi1X >= 0 && hi1Y >= 0) {
4537 drawHighlight(hi1X, hi1Y, lineGC);
4539 if (fromX >= 0 && fromY >= 0) {
4540 drawHighlight(fromX, fromY, highlineGC);
4543 if (hi2X != toX || hi2Y != toY) {
4544 if (hi2X >= 0 && hi2Y >= 0) {
4545 drawHighlight(hi2X, hi2Y, lineGC);
4547 if (toX >= 0 && toY >= 0) {
4548 drawHighlight(toX, toY, highlineGC);
4560 SetHighlights(-1, -1, -1, -1);
4565 SetPremoveHighlights(fromX, fromY, toX, toY)
4566 int fromX, fromY, toX, toY;
4568 if (pm1X != fromX || pm1Y != fromY) {
4569 if (pm1X >= 0 && pm1Y >= 0) {
4570 drawHighlight(pm1X, pm1Y, lineGC);
4572 if (fromX >= 0 && fromY >= 0) {
4573 drawHighlight(fromX, fromY, prelineGC);
4576 if (pm2X != toX || pm2Y != toY) {
4577 if (pm2X >= 0 && pm2Y >= 0) {
4578 drawHighlight(pm2X, pm2Y, lineGC);
4580 if (toX >= 0 && toY >= 0) {
4581 drawHighlight(toX, toY, prelineGC);
4591 ClearPremoveHighlights()
4593 SetPremoveHighlights(-1, -1, -1, -1);
4596 static void BlankSquare(x, y, color, piece, dest)
4601 if (useImages && useImageSqs) {
4605 pm = xpmLightSquare;
4610 case 2: /* neutral */
4615 XCopyArea(xDisplay, pm, dest, wlPieceGC, 0, 0,
4616 squareSize, squareSize, x, y);
4626 case 2: /* neutral */
4631 XFillRectangle(xDisplay, dest, gc, x, y, squareSize, squareSize);
4636 I split out the routines to draw a piece so that I could
4637 make a generic flash routine.
4639 static void monoDrawPiece_1bit(piece, square_color, x, y, dest)
4641 int square_color, x, y;
4644 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
4645 switch (square_color) {
4647 case 2: /* neutral */
4649 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
4650 ? *pieceToOutline(piece)
4651 : *pieceToSolid(piece),
4652 dest, bwPieceGC, 0, 0,
4653 squareSize, squareSize, x, y);
4656 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
4657 ? *pieceToSolid(piece)
4658 : *pieceToOutline(piece),
4659 dest, wbPieceGC, 0, 0,
4660 squareSize, squareSize, x, y);
4665 static void monoDrawPiece(piece, square_color, x, y, dest)
4667 int square_color, x, y;
4670 switch (square_color) {
4672 case 2: /* neutral */
4674 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
4675 ? *pieceToOutline(piece)
4676 : *pieceToSolid(piece),
4677 dest, bwPieceGC, 0, 0,
4678 squareSize, squareSize, x, y, 1);
4681 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
4682 ? *pieceToSolid(piece)
4683 : *pieceToOutline(piece),
4684 dest, wbPieceGC, 0, 0,
4685 squareSize, squareSize, x, y, 1);
4690 static void colorDrawPiece(piece, square_color, x, y, dest)
4692 int square_color, x, y;
4695 if(pieceToSolid(piece) == NULL) return; // [HGM] bitmaps: make it non-fatal if we have no bitmap;
4696 switch (square_color) {
4698 XCopyPlane(xDisplay, *pieceToSolid(piece),
4699 dest, (int) piece < (int) BlackPawn
4700 ? wlPieceGC : blPieceGC, 0, 0,
4701 squareSize, squareSize, x, y, 1);
4704 XCopyPlane(xDisplay, *pieceToSolid(piece),
4705 dest, (int) piece < (int) BlackPawn
4706 ? wdPieceGC : bdPieceGC, 0, 0,
4707 squareSize, squareSize, x, y, 1);
4709 case 2: /* neutral */
4711 XCopyPlane(xDisplay, *pieceToSolid(piece),
4712 dest, (int) piece < (int) BlackPawn
4713 ? wjPieceGC : bjPieceGC, 0, 0,
4714 squareSize, squareSize, x, y, 1);
4719 static void colorDrawPieceImage(piece, square_color, x, y, dest)
4721 int square_color, x, y;
4726 switch (square_color) {
4728 case 2: /* neutral */
4730 if ((int)piece < (int) BlackPawn) {
4738 if ((int)piece < (int) BlackPawn) {
4746 XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
4747 dest, wlPieceGC, 0, 0,
4748 squareSize, squareSize, x, y);
4751 typedef void (*DrawFunc)();
4753 DrawFunc ChooseDrawFunc()
4755 if (appData.monoMode) {
4756 if (DefaultDepth(xDisplay, xScreen) == 1) {
4757 return monoDrawPiece_1bit;
4759 return monoDrawPiece;
4763 return colorDrawPieceImage;
4765 return colorDrawPiece;
4769 /* [HR] determine square color depending on chess variant. */
4770 static int SquareColor(row, column)
4775 if (gameInfo.variant == VariantXiangqi) {
4776 if (column >= 3 && column <= 5 && row >= 0 && row <= 2) {
4778 } else if (column >= 3 && column <= 5 && row >= 7 && row <= 9) {
4780 } else if (row <= 4) {
4786 square_color = ((column + row) % 2) == 1;
4789 /* [hgm] holdings: next line makes all holdings squares light */
4790 if(column < BOARD_LEFT || column >= BOARD_RGHT) square_color = 1;
4792 return square_color;
4795 void DrawSquare(row, column, piece, do_flash)
4796 int row, column, do_flash;
4799 int square_color, x, y, direction, font_ascent, font_descent;
4802 XCharStruct overall;
4806 /* Calculate delay in milliseconds (2-delays per complete flash) */
4807 flash_delay = 500 / appData.flashRate;
4810 x = lineGap + ((BOARD_WIDTH-1)-column) *
4811 (squareSize + lineGap);
4812 y = lineGap + row * (squareSize + lineGap);
4814 x = lineGap + column * (squareSize + lineGap);
4815 y = lineGap + ((BOARD_HEIGHT-1)-row) *
4816 (squareSize + lineGap);
4819 square_color = SquareColor(row, column);
4821 if ( // [HGM] holdings: blank out area between board and holdings
4822 column == BOARD_LEFT-1 || column == BOARD_RGHT
4823 || (column == BOARD_LEFT-2 && row < BOARD_HEIGHT-gameInfo.holdingsSize)
4824 || (column == BOARD_RGHT+1 && row >= gameInfo.holdingsSize) ) {
4825 BlankSquare(x, y, 2, EmptySquare, xBoardWindow);
4827 // [HGM] print piece counts next to holdings
4828 string[1] = NULLCHAR;
4829 if (column == (flipView ? BOARD_LEFT-1 : BOARD_RGHT) && piece > 1 ) {
4830 string[0] = '0' + piece;
4831 XTextExtents(countFontStruct, string, 1, &direction,
4832 &font_ascent, &font_descent, &overall);
4833 if (appData.monoMode) {
4834 XDrawImageString(xDisplay, xBoardWindow, countGC,
4835 x + squareSize - overall.width - 2,
4836 y + font_ascent + 1, string, 1);
4838 XDrawString(xDisplay, xBoardWindow, countGC,
4839 x + squareSize - overall.width - 2,
4840 y + font_ascent + 1, string, 1);
4843 if (column == (flipView ? BOARD_RGHT : BOARD_LEFT-1) && piece > 1) {
4844 string[0] = '0' + piece;
4845 XTextExtents(countFontStruct, string, 1, &direction,
4846 &font_ascent, &font_descent, &overall);
4847 if (appData.monoMode) {
4848 XDrawImageString(xDisplay, xBoardWindow, countGC,
4849 x + 2, y + font_ascent + 1, string, 1);
4851 XDrawString(xDisplay, xBoardWindow, countGC,
4852 x + 2, y + font_ascent + 1, string, 1);
4856 if (piece == EmptySquare || appData.blindfold) {
4857 BlankSquare(x, y, square_color, piece, xBoardWindow);
4859 drawfunc = ChooseDrawFunc();
4860 if (do_flash && appData.flashCount > 0) {
4861 for (i=0; i<appData.flashCount; ++i) {
4863 drawfunc(piece, square_color, x, y, xBoardWindow);
4864 XSync(xDisplay, False);
4865 do_flash_delay(flash_delay);
4867 BlankSquare(x, y, square_color, piece, xBoardWindow);
4868 XSync(xDisplay, False);
4869 do_flash_delay(flash_delay);
4872 drawfunc(piece, square_color, x, y, xBoardWindow);
4876 string[1] = NULLCHAR;
4877 if (appData.showCoords && row == (flipView ? BOARD_HEIGHT-1 : 0)
4878 && column >= BOARD_LEFT && column < BOARD_RGHT) {
4879 string[0] = 'a' + column - BOARD_LEFT;
4880 XTextExtents(coordFontStruct, string, 1, &direction,
4881 &font_ascent, &font_descent, &overall);
4882 if (appData.monoMode) {
4883 XDrawImageString(xDisplay, xBoardWindow, coordGC,
4884 x + squareSize - overall.width - 2,
4885 y + squareSize - font_descent - 1, string, 1);
4887 XDrawString(xDisplay, xBoardWindow, coordGC,
4888 x + squareSize - overall.width - 2,
4889 y + squareSize - font_descent - 1, string, 1);
4892 if (appData.showCoords && column == (flipView ? BOARD_RGHT-1 : BOARD_LEFT)) {
4893 string[0] = ONE + row;
4894 XTextExtents(coordFontStruct, string, 1, &direction,
4895 &font_ascent, &font_descent, &overall);
4896 if (appData.monoMode) {
4897 XDrawImageString(xDisplay, xBoardWindow, coordGC,
4898 x + 2, y + font_ascent + 1, string, 1);
4900 XDrawString(xDisplay, xBoardWindow, coordGC,
4901 x + 2, y + font_ascent + 1, string, 1);
4907 /* Why is this needed on some versions of X? */
4908 void EventProc(widget, unused, event)
4913 if (!XtIsRealized(widget))
4916 switch (event->type) {
4918 if (event->xexpose.count > 0) return; /* no clipping is done */
4919 XDrawPosition(widget, True, NULL);
4927 void DrawPosition(fullRedraw, board)
4928 /*Boolean*/int fullRedraw;
4931 XDrawPosition(boardWidget, fullRedraw, board);
4934 /* Returns 1 if there are "too many" differences between b1 and b2
4935 (i.e. more than 1 move was made) */
4936 static int too_many_diffs(b1, b2)
4942 for (i=0; i<BOARD_HEIGHT; ++i) {
4943 for (j=0; j<BOARD_WIDTH; ++j) {
4944 if (b1[i][j] != b2[i][j]) {
4945 if (++c > 4) /* Castling causes 4 diffs */
4954 /* Matrix describing castling maneuvers */
4955 /* Row, ColRookFrom, ColKingFrom, ColRookTo, ColKingTo */
4956 static int castling_matrix[4][5] = {
4957 { 0, 0, 4, 3, 2 }, /* 0-0-0, white */
4958 { 0, 7, 4, 5, 6 }, /* 0-0, white */
4959 { 7, 0, 4, 3, 2 }, /* 0-0-0, black */
4960 { 7, 7, 4, 5, 6 } /* 0-0, black */
4963 /* Checks whether castling occurred. If it did, *rrow and *rcol
4964 are set to the destination (row,col) of the rook that moved.
4966 Returns 1 if castling occurred, 0 if not.
4968 Note: Only handles a max of 1 castling move, so be sure
4969 to call too_many_diffs() first.
4971 static int check_castle_draw(newb, oldb, rrow, rcol)
4978 /* For each type of castling... */
4979 for (i=0; i<4; ++i) {
4980 r = castling_matrix[i];
4982 /* Check the 4 squares involved in the castling move */
4984 for (j=1; j<=4; ++j) {
4985 if (newb[r[0]][r[j]] == oldb[r[0]][r[j]]) {
4992 /* All 4 changed, so it must be a castling move */
5001 static int damage[BOARD_SIZE][BOARD_SIZE];
5004 * event handler for redrawing the board
5006 void XDrawPosition(w, repaint, board)
5008 /*Boolean*/int repaint;
5012 static int lastFlipView = 0;
5013 static int lastBoardValid = 0;
5014 static Board lastBoard;
5018 if (board == NULL) {
5019 if (!lastBoardValid) return;
5022 if (!lastBoardValid || lastFlipView != flipView) {
5023 XtSetArg(args[0], XtNleftBitmap, (flipView ? xMarkPixmap : None));
5024 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flip View"),
5029 * It would be simpler to clear the window with XClearWindow()
5030 * but this causes a very distracting flicker.
5033 if (!repaint && lastBoardValid && lastFlipView == flipView) {
5035 /* If too much changes (begin observing new game, etc.), don't
5037 do_flash = too_many_diffs(board, lastBoard) ? 0 : 1;
5039 /* Special check for castling so we don't flash both the king
5040 and the rook (just flash the king). */
5042 if (check_castle_draw(board, lastBoard, &rrow, &rcol)) {
5043 /* Draw rook with NO flashing. King will be drawn flashing later */
5044 DrawSquare(rrow, rcol, board[rrow][rcol], 0);
5045 lastBoard[rrow][rcol] = board[rrow][rcol];
5049 /* First pass -- Draw (newly) empty squares and repair damage.
5050 This prevents you from having a piece show up twice while it
5051 is flashing on its new square */
5052 for (i = 0; i < BOARD_HEIGHT; i++)
5053 for (j = 0; j < BOARD_WIDTH; j++)
5054 if ((board[i][j] != lastBoard[i][j] && board[i][j] == EmptySquare)
5056 DrawSquare(i, j, board[i][j], 0);
5057 damage[i][j] = False;
5060 /* Second pass -- Draw piece(s) in new position and flash them */
5061 for (i = 0; i < BOARD_HEIGHT; i++)
5062 for (j = 0; j < BOARD_WIDTH; j++)
5063 if (board[i][j] != lastBoard[i][j]) {
5064 DrawSquare(i, j, board[i][j], do_flash);
5068 XDrawSegments(xDisplay, xBoardWindow, lineGC,
5069 gridSegments, BOARD_HEIGHT + BOARD_WIDTH + 2);
5071 for (i = 0; i < BOARD_HEIGHT; i++)
5072 for (j = 0; j < BOARD_WIDTH; j++) {
5073 DrawSquare(i, j, board[i][j], 0);
5074 damage[i][j] = False;
5078 CopyBoard(lastBoard, board);
5080 lastFlipView = flipView;
5082 /* Draw highlights */
5083 if (pm1X >= 0 && pm1Y >= 0) {
5084 drawHighlight(pm1X, pm1Y, prelineGC);
5086 if (pm2X >= 0 && pm2Y >= 0) {
5087 drawHighlight(pm2X, pm2Y, prelineGC);
5089 if (hi1X >= 0 && hi1Y >= 0) {
5090 drawHighlight(hi1X, hi1Y, highlineGC);
5092 if (hi2X >= 0 && hi2Y >= 0) {
5093 drawHighlight(hi2X, hi2Y, highlineGC);
5096 /* If piece being dragged around board, must redraw that too */
5099 XSync(xDisplay, False);
5104 * event handler for redrawing the board
5106 void DrawPositionProc(w, event, prms, nprms)
5112 XDrawPosition(w, True, NULL);
5117 * event handler for parsing user moves
5119 // [HGM] This routine will need quite some reworking. Although the backend still supports the old
5120 // way of doing things, by calling UserMoveEvent() to test the legality of the move and then perform
5121 // it at the end, and doing all kind of preliminary tests here (e.g. to weed out self-captures), it
5122 // should be made to use the new way, of calling UserMoveTest early to determine the legality of the
5123 // move, (which will weed out the illegal selfcaptures and moves into the holdings, and flag promotions),
5124 // and at the end FinishMove() to perform the move after optional promotion popups.
5125 // For now I patched it to allow self-capture with King, and suppress clicks between board and holdings.
5126 void HandleUserMove(w, event, prms, nprms)
5132 if (w != boardWidget || errorExitStatus != -1) return;
5135 if (event->type == ButtonPress) {
5136 XtPopdown(promotionShell);
5137 XtDestroyWidget(promotionShell);
5138 promotionUp = False;
5146 // [HGM] mouse: the rest of the mouse handler is moved to the backend, and called here
5147 if(event->type == ButtonPress) LeftClick(Press, event->xbutton.x, event->xbutton.y);
5148 if(event->type == ButtonRelease) LeftClick(Release, event->xbutton.x, event->xbutton.y);
5151 void AnimateUserMove (Widget w, XEvent * event,
5152 String * params, Cardinal * nParams)
5154 DragPieceMove(event->xmotion.x, event->xmotion.y);
5157 Widget CommentCreate(name, text, mutable, callback, lines)
5159 int /*Boolean*/ mutable;
5160 XtCallbackProc callback;
5164 Widget shell, layout, form, edit, b_ok, b_cancel, b_clear, b_close, b_edit;
5169 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5170 XtGetValues(boardWidget, args, j);
5173 XtSetArg(args[j], XtNresizable, True); j++;
5176 XtCreatePopupShell(name, topLevelShellWidgetClass,
5177 shellWidget, args, j);
5180 XtCreatePopupShell(name, transientShellWidgetClass,
5181 shellWidget, args, j);
5184 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
5185 layoutArgs, XtNumber(layoutArgs));
5187 XtCreateManagedWidget("form", formWidgetClass, layout,
5188 formArgs, XtNumber(formArgs));
5192 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
5193 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
5195 XtSetArg(args[j], XtNstring, text); j++;
5196 XtSetArg(args[j], XtNtop, XtChainTop); j++;
5197 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5198 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5199 XtSetArg(args[j], XtNright, XtChainRight); j++;
5200 XtSetArg(args[j], XtNresizable, True); j++;
5201 XtSetArg(args[j], XtNwidth, bw_width); j++; /*force wider than buttons*/
5202 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
5203 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
5204 XtSetArg(args[j], XtNautoFill, True); j++;
5205 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
5207 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
5211 XtSetArg(args[j], XtNfromVert, edit); 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(_("ok"), commandWidgetClass, form, args, j);
5218 XtAddCallback(b_ok, XtNcallback, callback, (XtPointer) 0);
5221 XtSetArg(args[j], XtNfromVert, edit); j++;
5222 XtSetArg(args[j], XtNfromHoriz, b_ok); 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(_("cancel"), commandWidgetClass, form, args, j);
5229 XtAddCallback(b_cancel, XtNcallback, callback, (XtPointer) 0);
5232 XtSetArg(args[j], XtNfromVert, edit); j++;
5233 XtSetArg(args[j], XtNfromHoriz, b_cancel); j++;
5234 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5235 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5236 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5237 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5239 XtCreateManagedWidget(_("clear"), commandWidgetClass, form, args, j);
5240 XtAddCallback(b_clear, XtNcallback, callback, (XtPointer) 0);
5243 XtSetArg(args[j], XtNfromVert, edit); 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(_("close"), commandWidgetClass, form, args, j);
5250 XtAddCallback(b_close, XtNcallback, callback, (XtPointer) 0);
5253 XtSetArg(args[j], XtNfromVert, edit); j++;
5254 XtSetArg(args[j], XtNfromHoriz, b_close); j++;
5255 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5256 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5257 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5258 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5260 XtCreateManagedWidget(_("edit"), commandWidgetClass, form, args, j);
5261 XtAddCallback(b_edit, XtNcallback, callback, (XtPointer) 0);
5264 XtRealizeWidget(shell);
5266 if (commentX == -1) {
5269 Dimension pw_height;
5270 Dimension ew_height;
5273 XtSetArg(args[j], XtNheight, &ew_height); j++;
5274 XtGetValues(edit, args, j);
5277 XtSetArg(args[j], XtNheight, &pw_height); j++;
5278 XtGetValues(shell, args, j);
5279 commentH = pw_height + (lines - 1) * ew_height;
5280 commentW = bw_width - 16;
5282 XSync(xDisplay, False);
5284 /* This code seems to tickle an X bug if it is executed too soon
5285 after xboard starts up. The coordinates get transformed as if
5286 the main window was positioned at (0, 0).
5288 XtTranslateCoords(shellWidget,
5289 (bw_width - commentW) / 2, 0 - commentH / 2,
5290 &commentX, &commentY);
5292 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
5293 RootWindowOfScreen(XtScreen(shellWidget)),
5294 (bw_width - commentW) / 2, 0 - commentH / 2,
5299 if (commentY < 0) commentY = 0; /*avoid positioning top offscreen*/
5302 XtSetArg(args[j], XtNheight, commentH); j++;
5303 XtSetArg(args[j], XtNwidth, commentW); j++;
5304 XtSetArg(args[j], XtNx, commentX); j++;
5305 XtSetArg(args[j], XtNy, commentY); j++;
5306 XtSetValues(shell, args, j);
5307 XtSetKeyboardFocus(shell, edit);
5312 /* Used for analysis window and ICS input window */
5313 Widget MiscCreate(name, text, mutable, callback, lines)
5315 int /*Boolean*/ mutable;
5316 XtCallbackProc callback;
5320 Widget shell, layout, form, edit;
5322 Dimension bw_width, pw_height, ew_height, w, h;
5328 XtSetArg(args[j], XtNresizable, True); j++;
5331 XtCreatePopupShell(name, topLevelShellWidgetClass,
5332 shellWidget, args, j);
5335 XtCreatePopupShell(name, transientShellWidgetClass,
5336 shellWidget, args, j);
5339 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
5340 layoutArgs, XtNumber(layoutArgs));
5342 XtCreateManagedWidget("form", formWidgetClass, layout,
5343 formArgs, XtNumber(formArgs));
5347 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
5348 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
5350 XtSetArg(args[j], XtNstring, text); j++;
5351 XtSetArg(args[j], XtNtop, XtChainTop); j++;
5352 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5353 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5354 XtSetArg(args[j], XtNright, XtChainRight); j++;
5355 XtSetArg(args[j], XtNresizable, True); j++;
5356 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
5357 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
5358 XtSetArg(args[j], XtNautoFill, True); j++;
5359 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
5361 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
5363 XtRealizeWidget(shell);
5366 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5367 XtGetValues(boardWidget, args, j);
5370 XtSetArg(args[j], XtNheight, &ew_height); j++;
5371 XtGetValues(edit, args, j);
5374 XtSetArg(args[j], XtNheight, &pw_height); j++;
5375 XtGetValues(shell, args, j);
5376 h = pw_height + (lines - 1) * ew_height;
5379 XSync(xDisplay, False);
5381 /* This code seems to tickle an X bug if it is executed too soon
5382 after xboard starts up. The coordinates get transformed as if
5383 the main window was positioned at (0, 0).
5385 XtTranslateCoords(shellWidget, (bw_width - w) / 2, 0 - h / 2, &x, &y);
5387 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
5388 RootWindowOfScreen(XtScreen(shellWidget)),
5389 (bw_width - w) / 2, 0 - h / 2, &xx, &yy, &junk);
5393 if (y < 0) y = 0; /*avoid positioning top offscreen*/
5396 XtSetArg(args[j], XtNheight, h); j++;
5397 XtSetArg(args[j], XtNwidth, w); j++;
5398 XtSetArg(args[j], XtNx, x); j++;
5399 XtSetArg(args[j], XtNy, y); j++;
5400 XtSetValues(shell, args, j);
5406 static int savedIndex; /* gross that this is global */
5408 void EditCommentPopUp(index, title, text)
5417 if (text == NULL) text = "";
5419 if (editShell == NULL) {
5421 CommentCreate(title, text, True, EditCommentCallback, 4);
5422 XtRealizeWidget(editShell);
5423 CatchDeleteWindow(editShell, "EditCommentPopDown");
5425 edit = XtNameToWidget(editShell, "*form.text");
5427 XtSetArg(args[j], XtNstring, text); j++;
5428 XtSetValues(edit, args, j);
5430 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5431 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5432 XtSetValues(editShell, args, j);
5435 XtPopup(editShell, XtGrabNone);
5439 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
5440 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
5444 void EditCommentCallback(w, client_data, call_data)
5446 XtPointer client_data, call_data;
5454 XtSetArg(args[j], XtNlabel, &name); j++;
5455 XtGetValues(w, args, j);
5457 if (strcmp(name, _("ok")) == 0) {
5458 edit = XtNameToWidget(editShell, "*form.text");
5460 XtSetArg(args[j], XtNstring, &val); j++;
5461 XtGetValues(edit, args, j);
5462 ReplaceComment(savedIndex, val);
5463 EditCommentPopDown();
5464 } else if (strcmp(name, _("cancel")) == 0) {
5465 EditCommentPopDown();
5466 } else if (strcmp(name, _("clear")) == 0) {
5467 edit = XtNameToWidget(editShell, "*form.text");
5468 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
5469 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
5473 void EditCommentPopDown()
5478 if (!editUp) return;
5480 XtSetArg(args[j], XtNx, &commentX); j++;
5481 XtSetArg(args[j], XtNy, &commentY); j++;
5482 XtSetArg(args[j], XtNheight, &commentH); j++;
5483 XtSetArg(args[j], XtNwidth, &commentW); j++;
5484 XtGetValues(editShell, args, j);
5485 XtPopdown(editShell);
5488 XtSetArg(args[j], XtNleftBitmap, None); j++;
5489 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
5493 void ICSInputBoxPopUp()
5498 char *title = _("ICS Input");
5501 if (ICSInputShell == NULL) {
5502 ICSInputShell = MiscCreate(title, "", True, NULL, 1);
5503 tr = XtParseTranslationTable(ICSInputTranslations);
5504 edit = XtNameToWidget(ICSInputShell, "*form.text");
5505 XtOverrideTranslations(edit, tr);
5506 XtRealizeWidget(ICSInputShell);
5507 CatchDeleteWindow(ICSInputShell, "ICSInputBoxPopDown");
5510 edit = XtNameToWidget(ICSInputShell, "*form.text");
5512 XtSetArg(args[j], XtNstring, ""); j++;
5513 XtSetValues(edit, args, j);
5515 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5516 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5517 XtSetValues(ICSInputShell, args, j);
5520 XtPopup(ICSInputShell, XtGrabNone);
5521 XtSetKeyboardFocus(ICSInputShell, edit);
5523 ICSInputBoxUp = True;
5525 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
5526 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
5530 void ICSInputSendText()
5537 edit = XtNameToWidget(ICSInputShell, "*form.text");
5539 XtSetArg(args[j], XtNstring, &val); j++;
5540 XtGetValues(edit, args, j);
5541 SendMultiLineToICS(val);
5542 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
5543 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
5546 void ICSInputBoxPopDown()
5551 if (!ICSInputBoxUp) return;
5553 XtPopdown(ICSInputShell);
5554 ICSInputBoxUp = False;
5556 XtSetArg(args[j], XtNleftBitmap, None); j++;
5557 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
5561 void CommentPopUp(title, text)
5568 if (commentShell == NULL) {
5570 CommentCreate(title, text, False, CommentCallback, 4);
5571 XtRealizeWidget(commentShell);
5572 CatchDeleteWindow(commentShell, "CommentPopDown");
5574 edit = XtNameToWidget(commentShell, "*form.text");
5576 XtSetArg(args[j], XtNstring, text); j++;
5577 XtSetValues(edit, args, j);
5579 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5580 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5581 XtSetValues(commentShell, args, j);
5584 XtPopup(commentShell, XtGrabNone);
5585 XSync(xDisplay, False);
5590 void CommentCallback(w, client_data, call_data)
5592 XtPointer client_data, call_data;
5599 XtSetArg(args[j], XtNlabel, &name); j++;
5600 XtGetValues(w, args, j);
5602 if (strcmp(name, _("close")) == 0) {
5604 } else if (strcmp(name, _("edit")) == 0) {
5611 void CommentPopDown()
5616 if (!commentUp) return;
5618 XtSetArg(args[j], XtNx, &commentX); j++;
5619 XtSetArg(args[j], XtNy, &commentY); j++;
5620 XtSetArg(args[j], XtNwidth, &commentW); j++;
5621 XtSetArg(args[j], XtNheight, &commentH); j++;
5622 XtGetValues(commentShell, args, j);
5623 XtPopdown(commentShell);
5624 XSync(xDisplay, False);
5628 void FileNamePopUp(label, def, proc, openMode)
5635 Widget popup, layout, dialog, edit;
5641 fileProc = proc; /* I can't see a way not */
5642 fileOpenMode = openMode; /* to use globals here */
5645 XtSetArg(args[i], XtNresizable, True); i++;
5646 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
5647 XtSetArg(args[i], XtNtitle, XtNewString(_("File name prompt"))); i++;
5648 fileNameShell = popup =
5649 XtCreatePopupShell("File name prompt", transientShellWidgetClass,
5650 shellWidget, args, i);
5653 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
5654 layoutArgs, XtNumber(layoutArgs));
5657 XtSetArg(args[i], XtNlabel, label); i++;
5658 XtSetArg(args[i], XtNvalue, def); i++;
5659 XtSetArg(args[i], XtNborderWidth, 0); i++;
5660 dialog = XtCreateManagedWidget("fileName", dialogWidgetClass,
5663 XawDialogAddButton(dialog, _("ok"), FileNameCallback, (XtPointer) dialog);
5664 XawDialogAddButton(dialog, _("cancel"), FileNameCallback,
5665 (XtPointer) dialog);
5667 XtRealizeWidget(popup);
5668 CatchDeleteWindow(popup, "FileNamePopDown");
5670 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
5671 &x, &y, &win_x, &win_y, &mask);
5673 XtSetArg(args[0], XtNx, x - 10);
5674 XtSetArg(args[1], XtNy, y - 30);
5675 XtSetValues(popup, args, 2);
5677 XtPopup(popup, XtGrabExclusive);
5680 edit = XtNameToWidget(dialog, "*value");
5681 XtSetKeyboardFocus(popup, edit);
5684 void FileNamePopDown()
5686 if (!filenameUp) return;
5687 XtPopdown(fileNameShell);
5688 XtDestroyWidget(fileNameShell);
5693 void FileNameCallback(w, client_data, call_data)
5695 XtPointer client_data, call_data;
5700 XtSetArg(args[0], XtNlabel, &name);
5701 XtGetValues(w, args, 1);
5703 if (strcmp(name, _("cancel")) == 0) {
5708 FileNameAction(w, NULL, NULL, NULL);
5711 void FileNameAction(w, event, prms, nprms)
5723 name = XawDialogGetValueString(w = XtParent(w));
5725 if ((name != NULL) && (*name != NULLCHAR)) {
5727 XtPopdown(w = XtParent(XtParent(w)));
5731 p = strrchr(buf, ' ');
5738 fullname = ExpandPathName(buf);
5740 ErrorPopUp(_("Error"), _("Can't open file"), FALSE);
5743 f = fopen(fullname, fileOpenMode);
5745 DisplayError(_("Failed to open file"), errno);
5747 (void) (*fileProc)(f, index, buf);
5754 XtPopdown(w = XtParent(XtParent(w)));
5760 void PromotionPopUp()
5763 Widget dialog, layout;
5765 Dimension bw_width, pw_width;
5769 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5770 XtGetValues(boardWidget, args, j);
5773 XtSetArg(args[j], XtNresizable, True); j++;
5774 XtSetArg(args[j], XtNtitle, XtNewString(_("Promotion"))); j++;
5776 XtCreatePopupShell("Promotion", transientShellWidgetClass,
5777 shellWidget, args, j);
5779 XtCreateManagedWidget(layoutName, formWidgetClass, promotionShell,
5780 layoutArgs, XtNumber(layoutArgs));
5783 XtSetArg(args[j], XtNlabel, _("Promote to what?")); j++;
5784 XtSetArg(args[j], XtNborderWidth, 0); j++;
5785 dialog = XtCreateManagedWidget("promotion", dialogWidgetClass,
5788 if(gameInfo.variant != VariantShogi) {
5789 XawDialogAddButton(dialog, _("Queen"), PromotionCallback,
5790 (XtPointer) dialog);
5791 XawDialogAddButton(dialog, _("Rook"), PromotionCallback,
5792 (XtPointer) dialog);
5793 XawDialogAddButton(dialog, _("Bishop"), PromotionCallback,
5794 (XtPointer) dialog);
5795 XawDialogAddButton(dialog, _("Knight"), PromotionCallback,
5796 (XtPointer) dialog);
5797 if (!appData.testLegality || gameInfo.variant == VariantSuicide ||
5798 gameInfo.variant == VariantGiveaway) {
5799 XawDialogAddButton(dialog, _("King"), PromotionCallback,
5800 (XtPointer) dialog);
5802 if(gameInfo.variant == VariantCapablanca ||
5803 gameInfo.variant == VariantGothic ||
5804 gameInfo.variant == VariantCapaRandom) {
5805 XawDialogAddButton(dialog, _("Archbishop"), PromotionCallback,
5806 (XtPointer) dialog);
5807 XawDialogAddButton(dialog, _("Chancellor"), PromotionCallback,
5808 (XtPointer) dialog);
5810 } else // [HGM] shogi
5812 XawDialogAddButton(dialog, _("Promote"), PromotionCallback,
5813 (XtPointer) dialog);
5814 XawDialogAddButton(dialog, _("Defer"), PromotionCallback,
5815 (XtPointer) dialog);
5817 XawDialogAddButton(dialog, _("cancel"), PromotionCallback,
5818 (XtPointer) dialog);
5820 XtRealizeWidget(promotionShell);
5821 CatchDeleteWindow(promotionShell, "PromotionPopDown");
5824 XtSetArg(args[j], XtNwidth, &pw_width); j++;
5825 XtGetValues(promotionShell, args, j);
5827 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
5828 lineGap + squareSize/3 +
5829 ((toY == BOARD_HEIGHT-1) ^ (flipView) ?
5830 0 : 6*(squareSize + lineGap)), &x, &y);
5833 XtSetArg(args[j], XtNx, x); j++;
5834 XtSetArg(args[j], XtNy, y); j++;
5835 XtSetValues(promotionShell, args, j);
5837 XtPopup(promotionShell, XtGrabNone);
5842 void PromotionPopDown()
5844 if (!promotionUp) return;
5845 XtPopdown(promotionShell);
5846 XtDestroyWidget(promotionShell);
5847 promotionUp = False;
5850 void PromotionCallback(w, client_data, call_data)
5852 XtPointer client_data, call_data;
5858 XtSetArg(args[0], XtNlabel, &name);
5859 XtGetValues(w, args, 1);
5863 if (fromX == -1) return;
5865 if (strcmp(name, _("cancel")) == 0) {
5869 } else if (strcmp(name, _("Knight")) == 0) {
5871 } else if (strcmp(name, _("Promote")) == 0) {
5873 } else if (strcmp(name, _("Defer")) == 0) {
5876 promoChar = ToLower(name[0]);
5879 UserMoveEvent(fromX, fromY, toX, toY, promoChar);
5881 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
5882 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
5887 void ErrorCallback(w, client_data, call_data)
5889 XtPointer client_data, call_data;
5892 XtPopdown(w = XtParent(XtParent(XtParent(w))));
5894 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
5900 if (!errorUp) return;
5902 XtPopdown(errorShell);
5903 XtDestroyWidget(errorShell);
5904 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
5907 void ErrorPopUp(title, label, modal)
5908 char *title, *label;
5912 Widget dialog, layout;
5916 Dimension bw_width, pw_width;
5917 Dimension pw_height;
5921 XtSetArg(args[i], XtNresizable, True); i++;
5922 XtSetArg(args[i], XtNtitle, title); i++;
5924 XtCreatePopupShell("errorpopup", transientShellWidgetClass,
5925 shellWidget, args, i);
5927 XtCreateManagedWidget(layoutName, formWidgetClass, errorShell,
5928 layoutArgs, XtNumber(layoutArgs));
5931 XtSetArg(args[i], XtNlabel, label); i++;
5932 XtSetArg(args[i], XtNborderWidth, 0); i++;
5933 dialog = XtCreateManagedWidget("dialog", dialogWidgetClass,
5936 XawDialogAddButton(dialog, _("ok"), ErrorCallback, (XtPointer) dialog);
5938 XtRealizeWidget(errorShell);
5939 CatchDeleteWindow(errorShell, "ErrorPopDown");
5942 XtSetArg(args[i], XtNwidth, &bw_width); i++;
5943 XtGetValues(boardWidget, args, i);
5945 XtSetArg(args[i], XtNwidth, &pw_width); i++;
5946 XtSetArg(args[i], XtNheight, &pw_height); i++;
5947 XtGetValues(errorShell, args, i);
5950 /* This code seems to tickle an X bug if it is executed too soon
5951 after xboard starts up. The coordinates get transformed as if
5952 the main window was positioned at (0, 0).
5954 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
5955 0 - pw_height + squareSize / 3, &x, &y);
5957 XTranslateCoordinates(xDisplay, XtWindow(boardWidget),
5958 RootWindowOfScreen(XtScreen(boardWidget)),
5959 (bw_width - pw_width) / 2,
5960 0 - pw_height + squareSize / 3, &xx, &yy, &junk);
5964 if (y < 0) y = 0; /*avoid positioning top offscreen*/
5967 XtSetArg(args[i], XtNx, x); i++;
5968 XtSetArg(args[i], XtNy, y); i++;
5969 XtSetValues(errorShell, args, i);
5972 XtPopup(errorShell, modal ? XtGrabExclusive : XtGrabNone);
5975 /* Disable all user input other than deleting the window */
5976 static int frozen = 0;
5980 /* Grab by a widget that doesn't accept input */
5981 XtAddGrab(messageWidget, TRUE, FALSE);
5985 /* Undo a FreezeUI */
5988 if (!frozen) return;
5989 XtRemoveGrab(messageWidget);
5993 char *ModeToWidgetName(mode)
5997 case BeginningOfGame:
5998 if (appData.icsActive)
5999 return "menuMode.ICS Client";
6000 else if (appData.noChessProgram ||
6001 *appData.cmailGameName != NULLCHAR)
6002 return "menuMode.Edit Game";
6004 return "menuMode.Machine Black";
6005 case MachinePlaysBlack:
6006 return "menuMode.Machine Black";
6007 case MachinePlaysWhite:
6008 return "menuMode.Machine White";
6010 return "menuMode.Analysis Mode";
6012 return "menuMode.Analyze File";
6013 case TwoMachinesPlay:
6014 return "menuMode.Two Machines";
6016 return "menuMode.Edit Game";
6017 case PlayFromGameFile:
6018 return "menuFile.Load Game";
6020 return "menuMode.Edit Position";
6022 return "menuMode.Training";
6023 case IcsPlayingWhite:
6024 case IcsPlayingBlack:
6028 return "menuMode.ICS Client";
6035 void ModeHighlight()
6038 static int oldPausing = FALSE;
6039 static GameMode oldmode = (GameMode) -1;
6042 if (!boardWidget || !XtIsRealized(boardWidget)) return;
6044 if (pausing != oldPausing) {
6045 oldPausing = pausing;
6047 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6049 XtSetArg(args[0], XtNleftBitmap, None);
6051 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Pause"),
6054 if (appData.showButtonBar) {
6055 /* Always toggle, don't set. Previous code messes up when
6056 invoked while the button is pressed, as releasing it
6057 toggles the state again. */
6060 XtSetArg(args[0], XtNbackground, &oldbg);
6061 XtSetArg(args[1], XtNforeground, &oldfg);
6062 XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON),
6064 XtSetArg(args[0], XtNbackground, oldfg);
6065 XtSetArg(args[1], XtNforeground, oldbg);
6067 XtSetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
6071 wname = ModeToWidgetName(oldmode);
6072 if (wname != NULL) {
6073 XtSetArg(args[0], XtNleftBitmap, None);
6074 XtSetValues(XtNameToWidget(menuBarWidget, wname), args, 1);
6076 wname = ModeToWidgetName(gameMode);
6077 if (wname != NULL) {
6078 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6079 XtSetValues(XtNameToWidget(menuBarWidget, wname), args, 1);
6083 /* Maybe all the enables should be handled here, not just this one */
6084 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Training"),
6085 gameMode == Training || gameMode == PlayFromGameFile);
6090 * Button/menu procedures
6092 void ResetProc(w, event, prms, nprms)
6101 int LoadGamePopUp(f, gameNumber, title)
6106 cmailMsgLoaded = FALSE;
6107 if (gameNumber == 0) {
6108 int error = GameListBuild(f);
6110 DisplayError(_("Cannot build game list"), error);
6111 } else if (!ListEmpty(&gameList) &&
6112 ((ListGame *) gameList.tailPred)->number > 1) {
6113 GameListPopUp(f, title);
6119 return LoadGame(f, gameNumber, title, FALSE);
6122 void LoadGameProc(w, event, prms, nprms)
6128 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
6131 FileNamePopUp(_("Load game file name?"), "", LoadGamePopUp, "rb");
6134 void LoadNextGameProc(w, event, prms, nprms)
6143 void LoadPrevGameProc(w, event, prms, nprms)
6152 void ReloadGameProc(w, event, prms, nprms)
6161 void LoadNextPositionProc(w, event, prms, nprms)
6170 void LoadPrevPositionProc(w, event, prms, nprms)
6179 void ReloadPositionProc(w, event, prms, nprms)
6188 void LoadPositionProc(w, event, prms, nprms)
6194 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
6197 FileNamePopUp(_("Load position file name?"), "", LoadPosition, "rb");
6200 void SaveGameProc(w, event, prms, nprms)
6206 FileNamePopUp(_("Save game file name?"),
6207 DefaultFileName(appData.oldSaveStyle ? "game" : "pgn"),
6211 void SavePositionProc(w, event, prms, nprms)
6217 FileNamePopUp(_("Save position file name?"),
6218 DefaultFileName(appData.oldSaveStyle ? "pos" : "fen"),
6222 void ReloadCmailMsgProc(w, event, prms, nprms)
6228 ReloadCmailMsgEvent(FALSE);
6231 void MailMoveProc(w, event, prms, nprms)
6240 /* this variable is shared between CopyPositionProc and SendPositionSelection */
6241 static char *selected_fen_position=NULL;
6244 SendPositionSelection(Widget w, Atom *selection, Atom *target,
6245 Atom *type_return, XtPointer *value_return,
6246 unsigned long *length_return, int *format_return)
6248 char *selection_tmp;
6250 if (!selected_fen_position) return False; /* should never happen */
6251 if (*target == XA_STRING){
6252 /* note: since no XtSelectionDoneProc was registered, Xt will
6253 * automatically call XtFree on the value returned. So have to
6254 * make a copy of it allocated with XtMalloc */
6255 selection_tmp= XtMalloc(strlen(selected_fen_position)+16);
6256 strcpy(selection_tmp, selected_fen_position);
6258 *value_return=selection_tmp;
6259 *length_return=strlen(selection_tmp);
6260 *type_return=XA_STRING;
6261 *format_return = 8; /* bits per byte */
6268 /* note: when called from menu all parameters are NULL, so no clue what the
6269 * Widget which was clicked on was, or what the click event was
6271 void CopyPositionProc(w, event, prms, nprms)
6279 if (selected_fen_position) free(selected_fen_position);
6280 selected_fen_position = (char *)PositionToFEN(currentMove, NULL);
6281 if (!selected_fen_position) return;
6282 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
6284 SendPositionSelection,
6285 NULL/* lose_ownership_proc */ ,
6286 NULL/* transfer_done_proc */);
6288 free(selected_fen_position);
6289 selected_fen_position=NULL;
6293 /* function called when the data to Paste is ready */
6295 PastePositionCB(Widget w, XtPointer client_data, Atom *selection,
6296 Atom *type, XtPointer value, unsigned long *len, int *format)
6299 if (value==NULL || *len==0) return; /* nothing had been selected to copy */
6300 fenstr[*len]='\0'; /* normally this string is terminated, but be safe */
6301 EditPositionPasteFEN(fenstr);
6305 /* called when Paste Position button is pressed,
6306 * all parameters will be NULL */
6307 void PastePositionProc(w, event, prms, nprms)
6313 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
6314 /* (XtSelectionCallbackProc) */ PastePositionCB,
6315 NULL, /* client_data passed to PastePositionCB */
6317 /* better to use the time field from the event that triggered the
6318 * call to this function, but that isn't trivial to get
6326 SendGameSelection(Widget w, Atom *selection, Atom *target,
6327 Atom *type_return, XtPointer *value_return,
6328 unsigned long *length_return, int *format_return)
6330 char *selection_tmp;
6332 if (*target == XA_STRING){
6333 FILE* f = fopen(gameCopyFilename, "r");
6336 if (f == NULL) return False;
6340 selection_tmp = XtMalloc(len + 1);
6341 count = fread(selection_tmp, 1, len, f);
6343 XtFree(selection_tmp);
6346 selection_tmp[len] = NULLCHAR;
6347 *value_return = selection_tmp;
6348 *length_return = len;
6349 *type_return = XA_STRING;
6350 *format_return = 8; /* bits per byte */
6357 /* note: when called from menu all parameters are NULL, so no clue what the
6358 * Widget which was clicked on was, or what the click event was
6360 void CopyGameProc(w, event, prms, nprms)
6368 ret = SaveGameToFile(gameCopyFilename, FALSE);
6371 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
6374 NULL/* lose_ownership_proc */ ,
6375 NULL/* transfer_done_proc */);
6378 /* function called when the data to Paste is ready */
6380 PasteGameCB(Widget w, XtPointer client_data, Atom *selection,
6381 Atom *type, XtPointer value, unsigned long *len, int *format)
6384 if (value == NULL || *len == 0) {
6385 return; /* nothing had been selected to copy */
6387 f = fopen(gamePasteFilename, "w");
6389 DisplayError(_("Can't open temp file"), errno);
6392 fwrite(value, 1, *len, f);
6395 LoadGameFromFile(gamePasteFilename, 0, gamePasteFilename, TRUE);
6398 /* called when Paste Game button is pressed,
6399 * all parameters will be NULL */
6400 void PasteGameProc(w, event, prms, nprms)
6406 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
6407 /* (XtSelectionCallbackProc) */ PasteGameCB,
6408 NULL, /* client_data passed to PasteGameCB */
6410 /* better to use the time field from the event that triggered the
6411 * call to this function, but that isn't trivial to get
6421 SaveGameProc(NULL, NULL, NULL, NULL);
6425 void QuitProc(w, event, prms, nprms)
6434 void PauseProc(w, event, prms, nprms)
6444 void MachineBlackProc(w, event, prms, nprms)
6450 MachineBlackEvent();
6453 void MachineWhiteProc(w, event, prms, nprms)
6459 MachineWhiteEvent();
6462 void AnalyzeModeProc(w, event, prms, nprms)
6470 if (!first.analysisSupport) {
6471 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
6472 DisplayError(buf, 0);
6475 /* [DM] icsEngineAnalyze [HGM] This is horrible code; reverse the gameMode and isEngineAnalyze tests! */
6476 if (appData.icsActive) {
6477 if (gameMode != IcsObserving) {
6478 sprintf(buf,_("You are not observing a game"));
6479 DisplayError(buf, 0);
6481 if (appData.icsEngineAnalyze) {
6482 if (appData.debugMode)
6483 fprintf(debugFP, _("Found unexpected active ICS engine analyze \n"));
6489 /* if enable, use want disable icsEngineAnalyze */
6490 if (appData.icsEngineAnalyze) {
6495 appData.icsEngineAnalyze = TRUE;
6496 if (appData.debugMode)
6497 fprintf(debugFP, _("ICS engine analyze starting... \n"));
6499 if (!appData.showThinking)
6500 ShowThinkingProc(w,event,prms,nprms);
6505 void AnalyzeFileProc(w, event, prms, nprms)
6511 if (!first.analysisSupport) {
6513 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
6514 DisplayError(buf, 0);
6519 if (!appData.showThinking)
6520 ShowThinkingProc(w,event,prms,nprms);
6523 FileNamePopUp(_("File to analyze"), "", LoadGamePopUp, "rb");
6524 AnalysisPeriodicEvent(1);
6527 void TwoMachinesProc(w, event, prms, nprms)
6536 void IcsClientProc(w, event, prms, nprms)
6545 void EditGameProc(w, event, prms, nprms)
6554 void EditPositionProc(w, event, prms, nprms)
6560 EditPositionEvent();
6563 void TrainingProc(w, event, prms, nprms)
6572 void EditCommentProc(w, event, prms, nprms)
6579 EditCommentPopDown();
6585 void IcsInputBoxProc(w, event, prms, nprms)
6591 if (ICSInputBoxUp) {
6592 ICSInputBoxPopDown();
6598 void AcceptProc(w, event, prms, nprms)
6607 void DeclineProc(w, event, prms, nprms)
6616 void RematchProc(w, event, prms, nprms)
6625 void CallFlagProc(w, event, prms, nprms)
6634 void DrawProc(w, event, prms, nprms)
6643 void AbortProc(w, event, prms, nprms)
6652 void AdjournProc(w, event, prms, nprms)
6661 void ResignProc(w, event, prms, nprms)
6670 void AdjuWhiteProc(w, event, prms, nprms)
6676 UserAdjudicationEvent(+1);
6679 void AdjuBlackProc(w, event, prms, nprms)
6685 UserAdjudicationEvent(-1);
6688 void AdjuDrawProc(w, event, prms, nprms)
6694 UserAdjudicationEvent(0);
6697 void EnterKeyProc(w, event, prms, nprms)
6703 if (ICSInputBoxUp == True)
6707 void StopObservingProc(w, event, prms, nprms)
6713 StopObservingEvent();
6716 void StopExaminingProc(w, event, prms, nprms)
6722 StopExaminingEvent();
6726 void ForwardProc(w, event, prms, nprms)
6736 void BackwardProc(w, event, prms, nprms)
6745 void ToStartProc(w, event, prms, nprms)
6754 void ToEndProc(w, event, prms, nprms)
6763 void RevertProc(w, event, prms, nprms)
6772 void TruncateGameProc(w, event, prms, nprms)
6778 TruncateGameEvent();
6780 void RetractMoveProc(w, event, prms, nprms)
6789 void MoveNowProc(w, event, prms, nprms)
6799 void AlwaysQueenProc(w, event, prms, nprms)
6807 appData.alwaysPromoteToQueen = !appData.alwaysPromoteToQueen;
6809 if (appData.alwaysPromoteToQueen) {
6810 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6812 XtSetArg(args[0], XtNleftBitmap, None);
6814 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
6818 void AnimateDraggingProc(w, event, prms, nprms)
6826 appData.animateDragging = !appData.animateDragging;
6828 if (appData.animateDragging) {
6829 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6832 XtSetArg(args[0], XtNleftBitmap, None);
6834 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Dragging"),
6838 void AnimateMovingProc(w, event, prms, nprms)
6846 appData.animate = !appData.animate;
6848 if (appData.animate) {
6849 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6852 XtSetArg(args[0], XtNleftBitmap, None);
6854 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
6858 void AutocommProc(w, event, prms, nprms)
6866 appData.autoComment = !appData.autoComment;
6868 if (appData.autoComment) {
6869 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6871 XtSetArg(args[0], XtNleftBitmap, None);
6873 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
6878 void AutoflagProc(w, event, prms, nprms)
6886 appData.autoCallFlag = !appData.autoCallFlag;
6888 if (appData.autoCallFlag) {
6889 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6891 XtSetArg(args[0], XtNleftBitmap, None);
6893 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
6897 void AutoflipProc(w, event, prms, nprms)
6905 appData.autoFlipView = !appData.autoFlipView;
6907 if (appData.autoFlipView) {
6908 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6910 XtSetArg(args[0], XtNleftBitmap, None);
6912 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flip View"),
6916 void AutobsProc(w, event, prms, nprms)
6924 appData.autoObserve = !appData.autoObserve;
6926 if (appData.autoObserve) {
6927 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6929 XtSetArg(args[0], XtNleftBitmap, None);
6931 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
6935 void AutoraiseProc(w, event, prms, nprms)
6943 appData.autoRaiseBoard = !appData.autoRaiseBoard;
6945 if (appData.autoRaiseBoard) {
6946 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6948 XtSetArg(args[0], XtNleftBitmap, None);
6950 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Raise Board"),
6954 void AutosaveProc(w, event, prms, nprms)
6962 appData.autoSaveGames = !appData.autoSaveGames;
6964 if (appData.autoSaveGames) {
6965 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6967 XtSetArg(args[0], XtNleftBitmap, None);
6969 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
6973 void BlindfoldProc(w, event, prms, nprms)
6981 appData.blindfold = !appData.blindfold;
6983 if (appData.blindfold) {
6984 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6986 XtSetArg(args[0], XtNleftBitmap, None);
6988 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Blindfold"),
6991 DrawPosition(True, NULL);
6994 void TestLegalityProc(w, event, prms, nprms)
7002 appData.testLegality = !appData.testLegality;
7004 if (appData.testLegality) {
7005 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7007 XtSetArg(args[0], XtNleftBitmap, None);
7009 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Test Legality"),
7014 void FlashMovesProc(w, event, prms, nprms)
7022 if (appData.flashCount == 0) {
7023 appData.flashCount = 3;
7025 appData.flashCount = -appData.flashCount;
7028 if (appData.flashCount > 0) {
7029 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7031 XtSetArg(args[0], XtNleftBitmap, None);
7033 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flash Moves"),
7037 void FlipViewProc(w, event, prms, nprms)
7043 flipView = !flipView;
7044 DrawPosition(True, NULL);
7047 void GetMoveListProc(w, event, prms, nprms)
7055 appData.getMoveList = !appData.getMoveList;
7057 if (appData.getMoveList) {
7058 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7061 XtSetArg(args[0], XtNleftBitmap, None);
7063 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
7068 void HighlightDraggingProc(w, event, prms, nprms)
7076 appData.highlightDragging = !appData.highlightDragging;
7078 if (appData.highlightDragging) {
7079 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7081 XtSetArg(args[0], XtNleftBitmap, None);
7083 XtSetValues(XtNameToWidget(menuBarWidget,
7084 "menuOptions.Highlight Dragging"), args, 1);
7088 void HighlightLastMoveProc(w, event, prms, nprms)
7096 appData.highlightLastMove = !appData.highlightLastMove;
7098 if (appData.highlightLastMove) {
7099 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7101 XtSetArg(args[0], XtNleftBitmap, None);
7103 XtSetValues(XtNameToWidget(menuBarWidget,
7104 "menuOptions.Highlight Last Move"), args, 1);
7107 void IcsAlarmProc(w, event, prms, nprms)
7115 appData.icsAlarm = !appData.icsAlarm;
7117 if (appData.icsAlarm) {
7118 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7120 XtSetArg(args[0], XtNleftBitmap, None);
7122 XtSetValues(XtNameToWidget(menuBarWidget,
7123 "menuOptions.ICS Alarm"), args, 1);
7126 void MoveSoundProc(w, event, prms, nprms)
7134 appData.ringBellAfterMoves = !appData.ringBellAfterMoves;
7136 if (appData.ringBellAfterMoves) {
7137 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7139 XtSetArg(args[0], XtNleftBitmap, None);
7141 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
7146 void OldSaveStyleProc(w, event, prms, nprms)
7154 appData.oldSaveStyle = !appData.oldSaveStyle;
7156 if (appData.oldSaveStyle) {
7157 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7159 XtSetArg(args[0], XtNleftBitmap, None);
7161 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Old Save Style"),
7165 void PeriodicUpdatesProc(w, event, prms, nprms)
7173 PeriodicUpdatesEvent(!appData.periodicUpdates);
7175 if (appData.periodicUpdates) {
7176 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7178 XtSetArg(args[0], XtNleftBitmap, None);
7180 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Periodic Updates"),
7184 void PonderNextMoveProc(w, event, prms, nprms)
7192 PonderNextMoveEvent(!appData.ponderNextMove);
7194 if (appData.ponderNextMove) {
7195 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7197 XtSetArg(args[0], XtNleftBitmap, None);
7199 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Ponder Next Move"),
7203 void PopupExitMessageProc(w, event, prms, nprms)
7211 appData.popupExitMessage = !appData.popupExitMessage;
7213 if (appData.popupExitMessage) {
7214 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7216 XtSetArg(args[0], XtNleftBitmap, None);
7218 XtSetValues(XtNameToWidget(menuBarWidget,
7219 "menuOptions.Popup Exit Message"), args, 1);
7222 void PopupMoveErrorsProc(w, event, prms, nprms)
7230 appData.popupMoveErrors = !appData.popupMoveErrors;
7232 if (appData.popupMoveErrors) {
7233 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7235 XtSetArg(args[0], XtNleftBitmap, None);
7237 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Popup Move Errors"),
7241 void PremoveProc(w, event, prms, nprms)
7249 appData.premove = !appData.premove;
7251 if (appData.premove) {
7252 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7254 XtSetArg(args[0], XtNleftBitmap, None);
7256 XtSetValues(XtNameToWidget(menuBarWidget,
7257 "menuOptions.Premove"), args, 1);
7260 void QuietPlayProc(w, event, prms, nprms)
7268 appData.quietPlay = !appData.quietPlay;
7270 if (appData.quietPlay) {
7271 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7273 XtSetArg(args[0], XtNleftBitmap, None);
7275 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Quiet Play"),
7279 void ShowCoordsProc(w, event, prms, nprms)
7287 appData.showCoords = !appData.showCoords;
7289 if (appData.showCoords) {
7290 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7292 XtSetArg(args[0], XtNleftBitmap, None);
7294 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
7297 DrawPosition(True, NULL);
7300 void ShowThinkingProc(w, event, prms, nprms)
7308 appData.showThinking = !appData.showThinking; // [HGM] thinking: tken out of ShowThinkingEvent
7309 ShowThinkingEvent();
7312 void HideThinkingProc(w, event, prms, nprms)
7320 appData.hideThinkingFromHuman = !appData.hideThinkingFromHuman; // [HGM] thinking: tken out of ShowThinkingEvent
7321 ShowThinkingEvent();
7323 if (appData.hideThinkingFromHuman) {
7324 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7326 XtSetArg(args[0], XtNleftBitmap, None);
7328 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
7332 void InfoProc(w, event, prms, nprms)
7339 snprintf(buf, sizeof(buf), "xterm -e info --directory %s --directory . -f %s &",
7344 void ManProc(w, event, prms, nprms)
7352 if (nprms && *nprms > 0)
7356 snprintf(buf, sizeof(buf), "xterm -e man %s &", name);
7360 void HintProc(w, event, prms, nprms)
7369 void BookProc(w, event, prms, nprms)
7378 void AboutProc(w, event, prms, nprms)
7386 char *zippy = " (with Zippy code)";
7390 snprintf(buf, sizeof(buf), "%s%s\n\n%s\n%s\n%s\n\n%s%s\n%s",
7391 programVersion, zippy,
7392 "Copyright 1991 Digital Equipment Corporation",
7393 "Enhancements Copyright 1992-2009 Free Software Foundation",
7394 "Enhancements Copyright 2005 Alessandro Scotti",
7395 PACKAGE, " is free software and carries NO WARRANTY;",
7396 "see the file COPYING for more information.");
7397 ErrorPopUp(_("About XBoard"), buf, FALSE);
7400 void DebugProc(w, event, prms, nprms)
7406 appData.debugMode = !appData.debugMode;
7409 void AboutGameProc(w, event, prms, nprms)
7418 void NothingProc(w, event, prms, nprms)
7427 void Iconify(w, event, prms, nprms)
7436 XtSetArg(args[0], XtNiconic, True);
7437 XtSetValues(shellWidget, args, 1);
7440 void DisplayMessage(message, extMessage)
7441 char *message, *extMessage;
7443 /* display a message in the message widget */
7452 snprintf(buf, sizeof(buf), "%s %s", message, extMessage);
7457 message = extMessage;
7461 /* need to test if messageWidget already exists, since this function
7462 can also be called during the startup, if for example a Xresource
7463 is not set up correctly */
7466 XtSetArg(arg, XtNlabel, message);
7467 XtSetValues(messageWidget, &arg, 1);
7473 void DisplayTitle(text)
7478 char title[MSG_SIZ];
7481 if (text == NULL) text = "";
7483 if (appData.titleInWindow) {
7485 XtSetArg(args[i], XtNlabel, text); i++;
7486 XtSetValues(titleWidget, args, i);
7489 if (*text != NULLCHAR) {
7491 strcpy(title, text);
7492 } else if (appData.icsActive) {
7493 snprintf(icon, sizeof(icon), "%s", appData.icsHost);
7494 snprintf(title, sizeof(title), "%s: %s", programName, appData.icsHost);
7495 } else if (appData.cmailGameName[0] != NULLCHAR) {
7496 snprintf(icon, sizeof(icon), "%s", "CMail");
7497 snprintf(title,sizeof(title), "%s: %s", programName, "CMail");
7499 // [HGM] license: This stuff should really be done in back-end, but WinBoard already had a pop-up for it
7500 } else if (gameInfo.variant == VariantGothic) {
7501 strcpy(icon, programName);
7502 strcpy(title, GOTHIC);
7505 } else if (gameInfo.variant == VariantFalcon) {
7506 strcpy(icon, programName);
7507 strcpy(title, FALCON);
7509 } else if (appData.noChessProgram) {
7510 strcpy(icon, programName);
7511 strcpy(title, programName);
7513 strcpy(icon, first.tidy);
7514 snprintf(title,sizeof(title), "%s: %s", programName, first.tidy);
7517 XtSetArg(args[i], XtNiconName, (XtArgVal) icon); i++;
7518 XtSetArg(args[i], XtNtitle, (XtArgVal) title); i++;
7519 XtSetValues(shellWidget, args, i);
7523 void DisplayError(message, error)
7530 if (appData.debugMode || appData.matchMode) {
7531 fprintf(stderr, "%s: %s\n", programName, message);
7534 if (appData.debugMode || appData.matchMode) {
7535 fprintf(stderr, "%s: %s: %s\n",
7536 programName, message, strerror(error));
7538 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
7541 ErrorPopUp(_("Error"), message, FALSE);
7545 void DisplayMoveError(message)
7550 DrawPosition(FALSE, NULL);
7551 if (appData.debugMode || appData.matchMode) {
7552 fprintf(stderr, "%s: %s\n", programName, message);
7554 if (appData.popupMoveErrors) {
7555 ErrorPopUp(_("Error"), message, FALSE);
7557 DisplayMessage(message, "");
7562 void DisplayFatalError(message, error, status)
7568 errorExitStatus = status;
7570 fprintf(stderr, "%s: %s\n", programName, message);
7572 fprintf(stderr, "%s: %s: %s\n",
7573 programName, message, strerror(error));
7574 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
7577 if (appData.popupExitMessage && boardWidget && XtIsRealized(boardWidget)) {
7578 ErrorPopUp(status ? _("Fatal Error") : _("Exiting"), message, TRUE);
7584 void DisplayInformation(message)
7588 ErrorPopUp(_("Information"), message, TRUE);
7591 void DisplayNote(message)
7595 ErrorPopUp(_("Note"), message, FALSE);
7599 NullXErrorCheck(dpy, error_event)
7601 XErrorEvent *error_event;
7606 void DisplayIcsInteractionTitle(message)
7609 if (oldICSInteractionTitle == NULL) {
7610 /* Magic to find the old window title, adapted from vim */
7611 char *wina = getenv("WINDOWID");
7613 Window win = (Window) atoi(wina);
7614 Window root, parent, *children;
7615 unsigned int nchildren;
7616 int (*oldHandler)() = XSetErrorHandler(NullXErrorCheck);
7618 if (XFetchName(xDisplay, win, &oldICSInteractionTitle)) break;
7619 if (!XQueryTree(xDisplay, win, &root, &parent,
7620 &children, &nchildren)) break;
7621 if (children) XFree((void *)children);
7622 if (parent == root || parent == 0) break;
7625 XSetErrorHandler(oldHandler);
7627 if (oldICSInteractionTitle == NULL) {
7628 oldICSInteractionTitle = "xterm";
7631 printf("\033]0;%s\007", message);
7635 char pendingReplyPrefix[MSG_SIZ];
7636 ProcRef pendingReplyPR;
7638 void AskQuestionProc(w, event, prms, nprms)
7645 fprintf(stderr, _("AskQuestionProc needed 4 parameters, got %d\n"),
7649 AskQuestionEvent(prms[0], prms[1], prms[2], prms[3]);
7652 void AskQuestionPopDown()
7654 if (!askQuestionUp) return;
7655 XtPopdown(askQuestionShell);
7656 XtDestroyWidget(askQuestionShell);
7657 askQuestionUp = False;
7660 void AskQuestionReplyAction(w, event, prms, nprms)
7670 reply = XawDialogGetValueString(w = XtParent(w));
7671 strcpy(buf, pendingReplyPrefix);
7672 if (*buf) strcat(buf, " ");
7675 OutputToProcess(pendingReplyPR, buf, strlen(buf), &err);
7676 AskQuestionPopDown();
7678 if (err) DisplayFatalError(_("Error writing to chess program"), err, 0);
7681 void AskQuestionCallback(w, client_data, call_data)
7683 XtPointer client_data, call_data;
7688 XtSetArg(args[0], XtNlabel, &name);
7689 XtGetValues(w, args, 1);
7691 if (strcmp(name, _("cancel")) == 0) {
7692 AskQuestionPopDown();
7694 AskQuestionReplyAction(w, NULL, NULL, NULL);
7698 void AskQuestion(title, question, replyPrefix, pr)
7699 char *title, *question, *replyPrefix;
7703 Widget popup, layout, dialog, edit;
7709 strcpy(pendingReplyPrefix, replyPrefix);
7710 pendingReplyPR = pr;
7713 XtSetArg(args[i], XtNresizable, True); i++;
7714 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
7715 askQuestionShell = popup =
7716 XtCreatePopupShell(title, transientShellWidgetClass,
7717 shellWidget, args, i);
7720 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
7721 layoutArgs, XtNumber(layoutArgs));
7724 XtSetArg(args[i], XtNlabel, question); i++;
7725 XtSetArg(args[i], XtNvalue, ""); i++;
7726 XtSetArg(args[i], XtNborderWidth, 0); i++;
7727 dialog = XtCreateManagedWidget("question", dialogWidgetClass,
7730 XawDialogAddButton(dialog, _("enter"), AskQuestionCallback,
7731 (XtPointer) dialog);
7732 XawDialogAddButton(dialog, _("cancel"), AskQuestionCallback,
7733 (XtPointer) dialog);
7735 XtRealizeWidget(popup);
7736 CatchDeleteWindow(popup, "AskQuestionPopDown");
7738 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
7739 &x, &y, &win_x, &win_y, &mask);
7741 XtSetArg(args[0], XtNx, x - 10);
7742 XtSetArg(args[1], XtNy, y - 30);
7743 XtSetValues(popup, args, 2);
7745 XtPopup(popup, XtGrabExclusive);
7746 askQuestionUp = True;
7748 edit = XtNameToWidget(dialog, "*value");
7749 XtSetKeyboardFocus(popup, edit);
7757 if (*name == NULLCHAR) {
7759 } else if (strcmp(name, "$") == 0) {
7760 putc(BELLCHAR, stderr);
7763 snprintf(buf, sizeof(buf), "%s '%s' &", appData.soundProgram, name);
7771 PlaySound(appData.soundMove);
7777 PlaySound(appData.soundIcsWin);
7783 PlaySound(appData.soundIcsLoss);
7789 PlaySound(appData.soundIcsDraw);
7793 PlayIcsUnfinishedSound()
7795 PlaySound(appData.soundIcsUnfinished);
7801 PlaySound(appData.soundIcsAlarm);
7807 system("stty echo");
7813 system("stty -echo");
7817 Colorize(cc, continuation)
7822 int count, outCount, error;
7824 if (textColors[(int)cc].bg > 0) {
7825 if (textColors[(int)cc].fg > 0) {
7826 sprintf(buf, "\033[0;%d;%d;%dm", textColors[(int)cc].attr,
7827 textColors[(int)cc].fg, textColors[(int)cc].bg);
7829 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
7830 textColors[(int)cc].bg);
7833 if (textColors[(int)cc].fg > 0) {
7834 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
7835 textColors[(int)cc].fg);
7837 sprintf(buf, "\033[0;%dm", textColors[(int)cc].attr);
7840 count = strlen(buf);
7841 outCount = OutputToProcess(NoProc, buf, count, &error);
7842 if (outCount < count) {
7843 DisplayFatalError(_("Error writing to display"), error, 1);
7846 if (continuation) return;
7849 PlaySound(appData.soundShout);
7852 PlaySound(appData.soundSShout);
7855 PlaySound(appData.soundChannel1);
7858 PlaySound(appData.soundChannel);
7861 PlaySound(appData.soundKibitz);
7864 PlaySound(appData.soundTell);
7866 case ColorChallenge:
7867 PlaySound(appData.soundChallenge);
7870 PlaySound(appData.soundRequest);
7873 PlaySound(appData.soundSeek);
7884 return getpwuid(getuid())->pw_name;
7887 static char *ExpandPathName(path)
7890 static char static_buf[2000];
7891 char *d, *s, buf[2000];
7897 while (*s && isspace(*s))
7906 if (*(s+1) == '/') {
7907 strcpy(d, getpwuid(getuid())->pw_dir);
7912 *strchr(buf, '/') = 0;
7913 pwd = getpwnam(buf);
7916 fprintf(stderr, _("ERROR: Unknown user %s (in path %s)\n"),
7920 strcpy(d, pwd->pw_dir);
7921 strcat(d, strchr(s+1, '/'));
7932 static char host_name[MSG_SIZ];
7934 #if HAVE_GETHOSTNAME
7935 gethostname(host_name, MSG_SIZ);
7937 #else /* not HAVE_GETHOSTNAME */
7938 # if HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H
7939 sysinfo(SI_HOSTNAME, host_name, MSG_SIZ);
7941 # else /* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
7943 # endif/* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
7944 #endif /* not HAVE_GETHOSTNAME */
7947 XtIntervalId delayedEventTimerXID = 0;
7948 DelayedEventCallback delayedEventCallback = 0;
7953 delayedEventTimerXID = 0;
7954 delayedEventCallback();
7958 ScheduleDelayedEvent(cb, millisec)
7959 DelayedEventCallback cb; long millisec;
7961 if(delayedEventTimerXID && delayedEventCallback == cb)
7962 // [HGM] alive: replace, rather than add or flush identical event
7963 XtRemoveTimeOut(delayedEventTimerXID);
7964 delayedEventCallback = cb;
7965 delayedEventTimerXID =
7966 XtAppAddTimeOut(appContext, millisec,
7967 (XtTimerCallbackProc) FireDelayedEvent, (XtPointer) 0);
7970 DelayedEventCallback
7973 if (delayedEventTimerXID) {
7974 return delayedEventCallback;
7981 CancelDelayedEvent()
7983 if (delayedEventTimerXID) {
7984 XtRemoveTimeOut(delayedEventTimerXID);
7985 delayedEventTimerXID = 0;
7989 XtIntervalId loadGameTimerXID = 0;
7991 int LoadGameTimerRunning()
7993 return loadGameTimerXID != 0;
7996 int StopLoadGameTimer()
7998 if (loadGameTimerXID != 0) {
7999 XtRemoveTimeOut(loadGameTimerXID);
8000 loadGameTimerXID = 0;
8008 LoadGameTimerCallback(arg, id)
8012 loadGameTimerXID = 0;
8017 StartLoadGameTimer(millisec)
8021 XtAppAddTimeOut(appContext, millisec,
8022 (XtTimerCallbackProc) LoadGameTimerCallback,
8026 XtIntervalId analysisClockXID = 0;
8029 AnalysisClockCallback(arg, id)
8033 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile
8034 || appData.icsEngineAnalyze) { // [DM]
8035 AnalysisPeriodicEvent(0);
8036 StartAnalysisClock();
8041 StartAnalysisClock()
8044 XtAppAddTimeOut(appContext, 2000,
8045 (XtTimerCallbackProc) AnalysisClockCallback,
8049 XtIntervalId clockTimerXID = 0;
8051 int ClockTimerRunning()
8053 return clockTimerXID != 0;
8056 int StopClockTimer()
8058 if (clockTimerXID != 0) {
8059 XtRemoveTimeOut(clockTimerXID);
8068 ClockTimerCallback(arg, id)
8077 StartClockTimer(millisec)
8081 XtAppAddTimeOut(appContext, millisec,
8082 (XtTimerCallbackProc) ClockTimerCallback,
8087 DisplayTimerLabel(w, color, timer, highlight)
8096 /* check for low time warning */
8097 Pixel foregroundOrWarningColor = timerForegroundPixel;
8100 appData.lowTimeWarning &&
8101 (timer / 1000) < appData.icsAlarmTime)
8102 foregroundOrWarningColor = lowTimeWarningColor;
8104 if (appData.clockMode) {
8105 sprintf(buf, "%s: %s", color, TimeString(timer));
8106 XtSetArg(args[0], XtNlabel, buf);
8108 sprintf(buf, "%s ", color);
8109 XtSetArg(args[0], XtNlabel, buf);
8114 XtSetArg(args[1], XtNbackground, foregroundOrWarningColor);
8115 XtSetArg(args[2], XtNforeground, timerBackgroundPixel);
8117 XtSetArg(args[1], XtNbackground, timerBackgroundPixel);
8118 XtSetArg(args[2], XtNforeground, foregroundOrWarningColor);
8121 XtSetValues(w, args, 3);
8125 DisplayWhiteClock(timeRemaining, highlight)
8131 if(appData.noGUI) return;
8132 DisplayTimerLabel(whiteTimerWidget, _("White"), timeRemaining, highlight);
8133 if (highlight && iconPixmap == bIconPixmap) {
8134 iconPixmap = wIconPixmap;
8135 XtSetArg(args[0], XtNiconPixmap, iconPixmap);
8136 XtSetValues(shellWidget, args, 1);
8141 DisplayBlackClock(timeRemaining, highlight)
8147 if(appData.noGUI) return;
8148 DisplayTimerLabel(blackTimerWidget, _("Black"), timeRemaining, highlight);
8149 if (highlight && iconPixmap == wIconPixmap) {
8150 iconPixmap = bIconPixmap;
8151 XtSetArg(args[0], XtNiconPixmap, iconPixmap);
8152 XtSetValues(shellWidget, args, 1);
8170 int StartChildProcess(cmdLine, dir, pr)
8177 int to_prog[2], from_prog[2];
8181 if (appData.debugMode) {
8182 fprintf(stderr, "StartChildProcess (dir=\"%s\") %s\n",dir, cmdLine);
8185 /* We do NOT feed the cmdLine to the shell; we just
8186 parse it into blank-separated arguments in the
8187 most simple-minded way possible.
8190 strcpy(buf, cmdLine);
8195 if (p == NULL) break;
8200 SetUpChildIO(to_prog, from_prog);
8202 if ((pid = fork()) == 0) {
8204 // [HGM] PSWBTM: made order resistant against case where fd of created pipe was 0 or 1
8205 close(to_prog[1]); // first close the unused pipe ends
8206 close(from_prog[0]);
8207 dup2(to_prog[0], 0); // to_prog was created first, nd is the only one to use 0 or 1
8208 dup2(from_prog[1], 1);
8209 if(to_prog[0] >= 2) close(to_prog[0]); // if 0 or 1, the dup2 already cosed the original
8210 close(from_prog[1]); // and closing again loses one of the pipes!
8211 if(fileno(stderr) >= 2) // better safe than sorry...
8212 dup2(1, fileno(stderr)); /* force stderr to the pipe */
8214 if (dir[0] != NULLCHAR && chdir(dir) != 0) {
8219 nice(appData.niceEngines); // [HGM] nice: adjust priority of engine proc
8221 execvp(argv[0], argv);
8223 /* If we get here, exec failed */
8228 /* Parent process */
8230 close(from_prog[1]);
8232 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8235 cp->fdFrom = from_prog[0];
8236 cp->fdTo = to_prog[1];
8241 // [HGM] kill: implement the 'hard killing' of AS's Winboard_x
8242 static RETSIGTYPE AlarmCallBack(int n)
8248 DestroyChildProcess(pr, signalType)
8252 ChildProc *cp = (ChildProc *) pr;
8254 if (cp->kind != CPReal) return;
8256 if (signalType == 10) { // [HGM] kill: if it does not terminate in 3 sec, kill
8257 signal(SIGALRM, AlarmCallBack);
8259 if(wait((int *) 0) == -1) { // process does not terminate on its own accord
8260 kill(cp->pid, SIGKILL); // kill it forcefully
8261 wait((int *) 0); // and wait again
8265 kill(cp->pid, signalType == 9 ? SIGKILL : SIGTERM); // [HGM] kill: use hard kill if so requested
8267 /* Process is exiting either because of the kill or because of
8268 a quit command sent by the backend; either way, wait for it to die.
8277 InterruptChildProcess(pr)
8280 ChildProc *cp = (ChildProc *) pr;
8282 if (cp->kind != CPReal) return;
8283 (void) kill(cp->pid, SIGINT); /* stop it thinking */
8286 int OpenTelnet(host, port, pr)
8291 char cmdLine[MSG_SIZ];
8293 if (port[0] == NULLCHAR) {
8294 snprintf(cmdLine, sizeof(cmdLine), "%s %s", appData.telnetProgram, host);
8296 snprintf(cmdLine, sizeof(cmdLine), "%s %s %s", appData.telnetProgram, host, port);
8298 return StartChildProcess(cmdLine, "", pr);
8301 int OpenTCP(host, port, pr)
8307 DisplayFatalError(_("Socket support is not configured in"), 0, 2);
8308 #else /* !OMIT_SOCKETS */
8310 struct sockaddr_in sa;
8312 unsigned short uport;
8315 if ((s = socket(AF_INET, SOCK_STREAM, 6)) < 0) {
8319 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
8320 sa.sin_family = AF_INET;
8321 sa.sin_addr.s_addr = INADDR_ANY;
8322 uport = (unsigned short) 0;
8323 sa.sin_port = htons(uport);
8324 if (bind(s, (struct sockaddr *) &sa, sizeof(struct sockaddr_in)) < 0) {
8328 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
8329 if (!(hp = gethostbyname(host))) {
8331 if (sscanf(host, "%d.%d.%d.%d", &b0, &b1, &b2, &b3) == 4) {
8332 hp = (struct hostent *) calloc(1, sizeof(struct hostent));
8333 hp->h_addrtype = AF_INET;
8335 hp->h_addr_list = (char **) calloc(2, sizeof(char *));
8336 hp->h_addr_list[0] = (char *) malloc(4);
8337 hp->h_addr_list[0][0] = b0;
8338 hp->h_addr_list[0][1] = b1;
8339 hp->h_addr_list[0][2] = b2;
8340 hp->h_addr_list[0][3] = b3;
8345 sa.sin_family = hp->h_addrtype;
8346 uport = (unsigned short) atoi(port);
8347 sa.sin_port = htons(uport);
8348 memcpy((char *) &sa.sin_addr, hp->h_addr, hp->h_length);
8350 if (connect(s, (struct sockaddr *) &sa,
8351 sizeof(struct sockaddr_in)) < 0) {
8355 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8362 #endif /* !OMIT_SOCKETS */
8367 int OpenCommPort(name, pr)
8374 fd = open(name, 2, 0);
8375 if (fd < 0) return errno;
8377 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8387 int OpenLoopback(pr)
8393 SetUpChildIO(to, from);
8395 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8398 cp->fdFrom = to[0]; /* note not from[0]; we are doing a loopback */
8405 int OpenRcmd(host, user, cmd, pr)
8406 char *host, *user, *cmd;
8409 DisplayFatalError(_("internal rcmd not implemented for Unix"), 0, 1);
8413 #define INPUT_SOURCE_BUF_SIZE 8192
8422 char buf[INPUT_SOURCE_BUF_SIZE];
8427 DoInputCallback(closure, source, xid)
8432 InputSource *is = (InputSource *) closure;
8437 if (is->lineByLine) {
8438 count = read(is->fd, is->unused,
8439 INPUT_SOURCE_BUF_SIZE - (is->unused - is->buf));
8441 (is->func)(is, is->closure, is->buf, count, count ? errno : 0);
8444 is->unused += count;
8446 while (p < is->unused) {
8447 q = memchr(p, '\n', is->unused - p);
8448 if (q == NULL) break;
8450 (is->func)(is, is->closure, p, q - p, 0);
8454 while (p < is->unused) {
8459 count = read(is->fd, is->buf, INPUT_SOURCE_BUF_SIZE);
8464 (is->func)(is, is->closure, is->buf, count, error);
8468 InputSourceRef AddInputSource(pr, lineByLine, func, closure)
8475 ChildProc *cp = (ChildProc *) pr;
8477 is = (InputSource *) calloc(1, sizeof(InputSource));
8478 is->lineByLine = lineByLine;
8482 is->fd = fileno(stdin);
8484 is->kind = cp->kind;
8485 is->fd = cp->fdFrom;
8488 is->unused = is->buf;
8491 is->xid = XtAppAddInput(appContext, is->fd,
8492 (XtPointer) (XtInputReadMask),
8493 (XtInputCallbackProc) DoInputCallback,
8495 is->closure = closure;
8496 return (InputSourceRef) is;
8500 RemoveInputSource(isr)
8503 InputSource *is = (InputSource *) isr;
8505 if (is->xid == 0) return;
8506 XtRemoveInput(is->xid);
8510 int OutputToProcess(pr, message, count, outError)
8516 static int line = 0;
8517 ChildProc *cp = (ChildProc *) pr;
8522 if (appData.noJoin || !appData.useInternalWrap)
8523 outCount = fwrite(message, 1, count, stdout);
8526 int width = get_term_width();
8527 int len = wrap(NULL, message, count, width, &line);
8528 char *msg = malloc(len);
8532 outCount = fwrite(message, 1, count, stdout);
8535 dbgchk = wrap(msg, message, count, width, &line);
8536 if (dbgchk != len && appData.debugMode)
8537 fprintf(debugFP, "wrap(): dbgchk(%d) != len(%d)\n", dbgchk, len);
8538 outCount = fwrite(msg, 1, dbgchk, stdout);
8544 outCount = write(cp->fdTo, message, count);
8554 /* Output message to process, with "ms" milliseconds of delay
8555 between each character. This is needed when sending the logon
8556 script to ICC, which for some reason doesn't like the
8557 instantaneous send. */
8558 int OutputToProcessDelayed(pr, message, count, outError, msdelay)
8565 ChildProc *cp = (ChildProc *) pr;
8570 r = write(cp->fdTo, message++, 1);
8583 /**** Animation code by Hugh Fisher, DCS, ANU.
8585 Known problem: if a window overlapping the board is
8586 moved away while a piece is being animated underneath,
8587 the newly exposed area won't be updated properly.
8588 I can live with this.
8590 Known problem: if you look carefully at the animation
8591 of pieces in mono mode, they are being drawn as solid
8592 shapes without interior detail while moving. Fixing
8593 this would be a major complication for minimal return.
8596 /* Masks for XPM pieces. Black and white pieces can have
8597 different shapes, but in the interest of retaining my
8598 sanity pieces must have the same outline on both light
8599 and dark squares, and all pieces must use the same
8600 background square colors/images. */
8602 static int xpmDone = 0;
8605 CreateAnimMasks (pieceDepth)
8612 unsigned long plane;
8615 /* Need a bitmap just to get a GC with right depth */
8616 buf = XCreatePixmap(xDisplay, xBoardWindow,
8618 values.foreground = 1;
8619 values.background = 0;
8620 /* Don't use XtGetGC, not read only */
8621 maskGC = XCreateGC(xDisplay, buf,
8622 GCForeground | GCBackground, &values);
8623 XFreePixmap(xDisplay, buf);
8625 buf = XCreatePixmap(xDisplay, xBoardWindow,
8626 squareSize, squareSize, pieceDepth);
8627 values.foreground = XBlackPixel(xDisplay, xScreen);
8628 values.background = XWhitePixel(xDisplay, xScreen);
8629 bufGC = XCreateGC(xDisplay, buf,
8630 GCForeground | GCBackground, &values);
8632 for (piece = WhitePawn; piece <= BlackKing; piece++) {
8633 /* Begin with empty mask */
8634 if(!xpmDone) // [HGM] pieces: keep using existing
8635 xpmMask[piece] = XCreatePixmap(xDisplay, xBoardWindow,
8636 squareSize, squareSize, 1);
8637 XSetFunction(xDisplay, maskGC, GXclear);
8638 XFillRectangle(xDisplay, xpmMask[piece], maskGC,
8639 0, 0, squareSize, squareSize);
8641 /* Take a copy of the piece */
8646 XSetFunction(xDisplay, bufGC, GXcopy);
8647 XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % (int)BlackPawn],
8649 0, 0, squareSize, squareSize, 0, 0);
8651 /* XOR the background (light) over the piece */
8652 XSetFunction(xDisplay, bufGC, GXxor);
8654 XCopyArea(xDisplay, xpmLightSquare, buf, bufGC,
8655 0, 0, squareSize, squareSize, 0, 0);
8657 XSetForeground(xDisplay, bufGC, lightSquareColor);
8658 XFillRectangle(xDisplay, buf, bufGC, 0, 0, squareSize, squareSize);
8661 /* We now have an inverted piece image with the background
8662 erased. Construct mask by just selecting all the non-zero
8663 pixels - no need to reconstruct the original image. */
8664 XSetFunction(xDisplay, maskGC, GXor);
8666 /* Might be quicker to download an XImage and create bitmap
8667 data from it rather than this N copies per piece, but it
8668 only takes a fraction of a second and there is a much
8669 longer delay for loading the pieces. */
8670 for (n = 0; n < pieceDepth; n ++) {
8671 XCopyPlane(xDisplay, buf, xpmMask[piece], maskGC,
8672 0, 0, squareSize, squareSize,
8678 XFreePixmap(xDisplay, buf);
8679 XFreeGC(xDisplay, bufGC);
8680 XFreeGC(xDisplay, maskGC);
8684 InitAnimState (anim, info)
8686 XWindowAttributes * info;
8691 /* Each buffer is square size, same depth as window */
8692 anim->saveBuf = XCreatePixmap(xDisplay, xBoardWindow,
8693 squareSize, squareSize, info->depth);
8694 anim->newBuf = XCreatePixmap(xDisplay, xBoardWindow,
8695 squareSize, squareSize, info->depth);
8697 /* Create a plain GC for blitting */
8698 mask = GCForeground | GCBackground | GCFunction |
8699 GCPlaneMask | GCGraphicsExposures;
8700 values.foreground = XBlackPixel(xDisplay, xScreen);
8701 values.background = XWhitePixel(xDisplay, xScreen);
8702 values.function = GXcopy;
8703 values.plane_mask = AllPlanes;
8704 values.graphics_exposures = False;
8705 anim->blitGC = XCreateGC(xDisplay, xBoardWindow, mask, &values);
8707 /* Piece will be copied from an existing context at
8708 the start of each new animation/drag. */
8709 anim->pieceGC = XCreateGC(xDisplay, xBoardWindow, 0, &values);
8711 /* Outline will be a read-only copy of an existing */
8712 anim->outlineGC = None;
8718 static VariantClass old = (VariantClass) -1; // [HGM] pieces: redo every time variant changes
8719 XWindowAttributes info;
8721 if (xpmDone && gameInfo.variant == old) return;
8722 if(xpmDone) old = gameInfo.variant; // first time pieces might not be created yet
8723 XGetWindowAttributes(xDisplay, xBoardWindow, &info);
8725 InitAnimState(&game, &info);
8726 InitAnimState(&player, &info);
8728 /* For XPM pieces, we need bitmaps to use as masks. */
8730 CreateAnimMasks(info.depth);
8736 static Boolean frameWaiting;
8738 static RETSIGTYPE FrameAlarm (sig)
8741 frameWaiting = False;
8742 /* In case System-V style signals. Needed?? */
8743 signal(SIGALRM, FrameAlarm);
8750 struct itimerval delay;
8752 XSync(xDisplay, False);
8755 frameWaiting = True;
8756 signal(SIGALRM, FrameAlarm);
8757 delay.it_interval.tv_sec =
8758 delay.it_value.tv_sec = time / 1000;
8759 delay.it_interval.tv_usec =
8760 delay.it_value.tv_usec = (time % 1000) * 1000;
8761 setitimer(ITIMER_REAL, &delay, NULL);
8762 while (frameWaiting) pause();
8763 delay.it_interval.tv_sec = delay.it_value.tv_sec = 0;
8764 delay.it_interval.tv_usec = delay.it_value.tv_usec = 0;
8765 setitimer(ITIMER_REAL, &delay, NULL);
8775 XSync(xDisplay, False);
8777 usleep(time * 1000);
8782 /* Convert board position to corner of screen rect and color */
8785 ScreenSquare(column, row, pt, color)
8786 int column; int row; XPoint * pt; int * color;
8789 pt->x = lineGap + ((BOARD_WIDTH-1)-column) * (squareSize + lineGap);
8790 pt->y = lineGap + row * (squareSize + lineGap);
8792 pt->x = lineGap + column * (squareSize + lineGap);
8793 pt->y = lineGap + ((BOARD_HEIGHT-1)-row) * (squareSize + lineGap);
8795 *color = SquareColor(row, column);
8798 /* Convert window coords to square */
8801 BoardSquare(x, y, column, row)
8802 int x; int y; int * column; int * row;
8804 *column = EventToSquare(x, BOARD_WIDTH);
8805 if (flipView && *column >= 0)
8806 *column = BOARD_WIDTH - 1 - *column;
8807 *row = EventToSquare(y, BOARD_HEIGHT);
8808 if (!flipView && *row >= 0)
8809 *row = BOARD_HEIGHT - 1 - *row;
8814 #undef Max /* just in case */
8816 #define Max(a, b) ((a) > (b) ? (a) : (b))
8817 #define Min(a, b) ((a) < (b) ? (a) : (b))
8820 SetRect(rect, x, y, width, height)
8821 XRectangle * rect; int x; int y; int width; int height;
8825 rect->width = width;
8826 rect->height = height;
8829 /* Test if two frames overlap. If they do, return
8830 intersection rect within old and location of
8831 that rect within new. */
8834 Intersect(old, new, size, area, pt)
8835 XPoint * old; XPoint * new;
8836 int size; XRectangle * area; XPoint * pt;
8838 if (old->x > new->x + size || new->x > old->x + size ||
8839 old->y > new->y + size || new->y > old->y + size) {
8842 SetRect(area, Max(new->x - old->x, 0), Max(new->y - old->y, 0),
8843 size - abs(old->x - new->x), size - abs(old->y - new->y));
8844 pt->x = Max(old->x - new->x, 0);
8845 pt->y = Max(old->y - new->y, 0);
8850 /* For two overlapping frames, return the rect(s)
8851 in the old that do not intersect with the new. */
8854 CalcUpdateRects(old, new, size, update, nUpdates)
8855 XPoint * old; XPoint * new; int size;
8856 XRectangle update[]; int * nUpdates;
8860 /* If old = new (shouldn't happen) then nothing to draw */
8861 if (old->x == new->x && old->y == new->y) {
8865 /* Work out what bits overlap. Since we know the rects
8866 are the same size we don't need a full intersect calc. */
8868 /* Top or bottom edge? */
8869 if (new->y > old->y) {
8870 SetRect(&(update[count]), old->x, old->y, size, new->y - old->y);
8872 } else if (old->y > new->y) {
8873 SetRect(&(update[count]), old->x, old->y + size - (old->y - new->y),
8874 size, old->y - new->y);
8877 /* Left or right edge - don't overlap any update calculated above. */
8878 if (new->x > old->x) {
8879 SetRect(&(update[count]), old->x, Max(new->y, old->y),
8880 new->x - old->x, size - abs(new->y - old->y));
8882 } else if (old->x > new->x) {
8883 SetRect(&(update[count]), new->x + size, Max(new->y, old->y),
8884 old->x - new->x, size - abs(new->y - old->y));
8891 /* Generate a series of frame coords from start->mid->finish.
8892 The movement rate doubles until the half way point is
8893 reached, then halves back down to the final destination,
8894 which gives a nice slow in/out effect. The algorithmn
8895 may seem to generate too many intermediates for short
8896 moves, but remember that the purpose is to attract the
8897 viewers attention to the piece about to be moved and
8898 then to where it ends up. Too few frames would be less
8902 Tween(start, mid, finish, factor, frames, nFrames)
8903 XPoint * start; XPoint * mid;
8904 XPoint * finish; int factor;
8905 XPoint frames[]; int * nFrames;
8907 int fraction, n, count;
8911 /* Slow in, stepping 1/16th, then 1/8th, ... */
8913 for (n = 0; n < factor; n++)
8915 for (n = 0; n < factor; n++) {
8916 frames[count].x = start->x + (mid->x - start->x) / fraction;
8917 frames[count].y = start->y + (mid->y - start->y) / fraction;
8919 fraction = fraction / 2;
8923 frames[count] = *mid;
8926 /* Slow out, stepping 1/2, then 1/4, ... */
8928 for (n = 0; n < factor; n++) {
8929 frames[count].x = finish->x - (finish->x - mid->x) / fraction;
8930 frames[count].y = finish->y - (finish->y - mid->y) / fraction;
8932 fraction = fraction * 2;
8937 /* Draw a piece on the screen without disturbing what's there */
8940 SelectGCMask(piece, clip, outline, mask)
8941 ChessSquare piece; GC * clip; GC * outline; Pixmap * mask;
8945 /* Bitmap for piece being moved. */
8946 if (appData.monoMode) {
8947 *mask = *pieceToSolid(piece);
8948 } else if (useImages) {
8950 *mask = xpmMask[piece];
8952 *mask = ximMaskPm[piece];
8955 *mask = *pieceToSolid(piece);
8958 /* GC for piece being moved. Square color doesn't matter, but
8959 since it gets modified we make a copy of the original. */
8961 if (appData.monoMode)
8966 if (appData.monoMode)
8971 XCopyGC(xDisplay, source, 0xFFFFFFFF, *clip);
8973 /* Outline only used in mono mode and is not modified */
8975 *outline = bwPieceGC;
8977 *outline = wbPieceGC;
8981 OverlayPiece(piece, clip, outline, dest)
8982 ChessSquare piece; GC clip; GC outline; Drawable dest;
8987 /* Draw solid rectangle which will be clipped to shape of piece */
8988 XFillRectangle(xDisplay, dest, clip,
8989 0, 0, squareSize, squareSize);
8990 if (appData.monoMode)
8991 /* Also draw outline in contrasting color for black
8992 on black / white on white cases */
8993 XCopyPlane(xDisplay, *pieceToOutline(piece), dest, outline,
8994 0, 0, squareSize, squareSize, 0, 0, 1);
8996 /* Copy the piece */
9001 XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
9003 0, 0, squareSize, squareSize,
9008 /* Animate the movement of a single piece */
9011 BeginAnimation(anim, piece, startColor, start)
9019 /* The old buffer is initialised with the start square (empty) */
9020 BlankSquare(0, 0, startColor, EmptySquare, anim->saveBuf);
9021 anim->prevFrame = *start;
9023 /* The piece will be drawn using its own bitmap as a matte */
9024 SelectGCMask(piece, &anim->pieceGC, &anim->outlineGC, &mask);
9025 XSetClipMask(xDisplay, anim->pieceGC, mask);
9029 AnimationFrame(anim, frame, piece)
9034 XRectangle updates[4];
9039 /* Save what we are about to draw into the new buffer */
9040 XCopyArea(xDisplay, xBoardWindow, anim->newBuf, anim->blitGC,
9041 frame->x, frame->y, squareSize, squareSize,
9044 /* Erase bits of the previous frame */
9045 if (Intersect(&anim->prevFrame, frame, squareSize, &overlap, &pt)) {
9046 /* Where the new frame overlapped the previous,
9047 the contents in newBuf are wrong. */
9048 XCopyArea(xDisplay, anim->saveBuf, anim->newBuf, anim->blitGC,
9049 overlap.x, overlap.y,
9050 overlap.width, overlap.height,
9052 /* Repaint the areas in the old that don't overlap new */
9053 CalcUpdateRects(&anim->prevFrame, frame, squareSize, updates, &count);
9054 for (i = 0; i < count; i++)
9055 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9056 updates[i].x - anim->prevFrame.x,
9057 updates[i].y - anim->prevFrame.y,
9058 updates[i].width, updates[i].height,
9059 updates[i].x, updates[i].y);
9061 /* Easy when no overlap */
9062 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9063 0, 0, squareSize, squareSize,
9064 anim->prevFrame.x, anim->prevFrame.y);
9067 /* Save this frame for next time round */
9068 XCopyArea(xDisplay, anim->newBuf, anim->saveBuf, anim->blitGC,
9069 0, 0, squareSize, squareSize,
9071 anim->prevFrame = *frame;
9073 /* Draw piece over original screen contents, not current,
9074 and copy entire rect. Wipes out overlapping piece images. */
9075 OverlayPiece(piece, anim->pieceGC, anim->outlineGC, anim->newBuf);
9076 XCopyArea(xDisplay, anim->newBuf, xBoardWindow, anim->blitGC,
9077 0, 0, squareSize, squareSize,
9078 frame->x, frame->y);
9082 EndAnimation (anim, finish)
9086 XRectangle updates[4];
9091 /* The main code will redraw the final square, so we
9092 only need to erase the bits that don't overlap. */
9093 if (Intersect(&anim->prevFrame, finish, squareSize, &overlap, &pt)) {
9094 CalcUpdateRects(&anim->prevFrame, finish, squareSize, updates, &count);
9095 for (i = 0; i < count; i++)
9096 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9097 updates[i].x - anim->prevFrame.x,
9098 updates[i].y - anim->prevFrame.y,
9099 updates[i].width, updates[i].height,
9100 updates[i].x, updates[i].y);
9102 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9103 0, 0, squareSize, squareSize,
9104 anim->prevFrame.x, anim->prevFrame.y);
9109 FrameSequence(anim, piece, startColor, start, finish, frames, nFrames)
9111 ChessSquare piece; int startColor;
9112 XPoint * start; XPoint * finish;
9113 XPoint frames[]; int nFrames;
9117 BeginAnimation(anim, piece, startColor, start);
9118 for (n = 0; n < nFrames; n++) {
9119 AnimationFrame(anim, &(frames[n]), piece);
9120 FrameDelay(appData.animSpeed);
9122 EndAnimation(anim, finish);
9125 /* Main control logic for deciding what to animate and how */
9128 AnimateMove(board, fromX, fromY, toX, toY)
9137 XPoint start, finish, mid;
9138 XPoint frames[kFactor * 2 + 1];
9139 int nFrames, startColor, endColor;
9141 /* Are we animating? */
9142 if (!appData.animate || appData.blindfold)
9145 if(board[toY][toX] == WhiteRook && board[fromY][fromX] == WhiteKing ||
9146 board[toY][toX] == BlackRook && board[fromY][fromX] == BlackKing)
9147 return; // [HGM] FRC: no animtion of FRC castlings, as to-square is not true to-square
9149 if (fromY < 0 || fromX < 0 || toX < 0 || toY < 0) return;
9150 piece = board[fromY][fromX];
9151 if (piece >= EmptySquare) return;
9156 hop = (piece == WhiteKnight || piece == BlackKnight);
9159 if (appData.debugMode) {
9160 fprintf(debugFP, hop ? _("AnimateMove: piece %d hops from %d,%d to %d,%d \n") :
9161 _("AnimateMove: piece %d slides from %d,%d to %d,%d \n"),
9162 piece, fromX, fromY, toX, toY); }
9164 ScreenSquare(fromX, fromY, &start, &startColor);
9165 ScreenSquare(toX, toY, &finish, &endColor);
9168 /* Knight: make diagonal movement then straight */
9169 if (abs(toY - fromY) < abs(toX - fromX)) {
9170 mid.x = start.x + (finish.x - start.x) / 2;
9174 mid.y = start.y + (finish.y - start.y) / 2;
9177 mid.x = start.x + (finish.x - start.x) / 2;
9178 mid.y = start.y + (finish.y - start.y) / 2;
9181 /* Don't use as many frames for very short moves */
9182 if (abs(toY - fromY) + abs(toX - fromX) <= 2)
9183 Tween(&start, &mid, &finish, kFactor - 1, frames, &nFrames);
9185 Tween(&start, &mid, &finish, kFactor, frames, &nFrames);
9186 FrameSequence(&game, piece, startColor, &start, &finish, frames, nFrames);
9188 /* Be sure end square is redrawn */
9189 damage[toY][toX] = True;
9193 DragPieceBegin(x, y)
9196 int boardX, boardY, color;
9199 /* Are we animating? */
9200 if (!appData.animateDragging || appData.blindfold)
9203 /* Figure out which square we start in and the
9204 mouse position relative to top left corner. */
9205 BoardSquare(x, y, &boardX, &boardY);
9206 player.startBoardX = boardX;
9207 player.startBoardY = boardY;
9208 ScreenSquare(boardX, boardY, &corner, &color);
9209 player.startSquare = corner;
9210 player.startColor = color;
9211 /* As soon as we start dragging, the piece will jump slightly to
9212 be centered over the mouse pointer. */
9213 player.mouseDelta.x = squareSize/2;
9214 player.mouseDelta.y = squareSize/2;
9215 /* Initialise animation */
9216 player.dragPiece = PieceForSquare(boardX, boardY);
9218 if (player.dragPiece >= 0 && player.dragPiece < EmptySquare) {
9219 player.dragActive = True;
9220 BeginAnimation(&player, player.dragPiece, color, &corner);
9221 /* Mark this square as needing to be redrawn. Note that
9222 we don't remove the piece though, since logically (ie
9223 as seen by opponent) the move hasn't been made yet. */
9224 if(boardX == BOARD_RGHT+1 && PieceForSquare(boardX-1, boardY) > 1 ||
9225 boardX == BOARD_LEFT-2 && PieceForSquare(boardX+1, boardY) > 1)
9226 XCopyArea(xDisplay, xBoardWindow, player.saveBuf, player.blitGC,
9227 corner.x, corner.y, squareSize, squareSize,
9228 0, 0); // [HGM] zh: unstack in stead of grab
9229 damage[boardY][boardX] = True;
9231 player.dragActive = False;
9241 /* Are we animating? */
9242 if (!appData.animateDragging || appData.blindfold)
9246 if (! player.dragActive)
9248 /* Move piece, maintaining same relative position
9249 of mouse within square */
9250 corner.x = x - player.mouseDelta.x;
9251 corner.y = y - player.mouseDelta.y;
9252 AnimationFrame(&player, &corner, player.dragPiece);
9254 if (appData.highlightDragging) {
9256 BoardSquare(x, y, &boardX, &boardY);
9257 SetHighlights(fromX, fromY, boardX, boardY);
9266 int boardX, boardY, color;
9269 /* Are we animating? */
9270 if (!appData.animateDragging || appData.blindfold)
9274 if (! player.dragActive)
9276 /* Last frame in sequence is square piece is
9277 placed on, which may not match mouse exactly. */
9278 BoardSquare(x, y, &boardX, &boardY);
9279 ScreenSquare(boardX, boardY, &corner, &color);
9280 EndAnimation(&player, &corner);
9282 /* Be sure end square is redrawn */
9283 damage[boardY][boardX] = True;
9285 /* This prevents weird things happening with fast successive
9286 clicks which on my Sun at least can cause motion events
9287 without corresponding press/release. */
9288 player.dragActive = False;
9291 /* Handle expose event while piece being dragged */
9296 if (!player.dragActive || appData.blindfold)
9299 /* What we're doing: logically, the move hasn't been made yet,
9300 so the piece is still in it's original square. But visually
9301 it's being dragged around the board. So we erase the square
9302 that the piece is on and draw it at the last known drag point. */
9303 BlankSquare(player.startSquare.x, player.startSquare.y,
9304 player.startColor, EmptySquare, xBoardWindow);
9305 AnimationFrame(&player, &player.prevFrame, player.dragPiece);
9306 damage[player.startBoardY][player.startBoardX] = TRUE;
9310 SetProgramStats( FrontEndProgramStats * stats )
9313 // [HGM] done, but perhaps backend should call this directly?
9314 EngineOutputUpdate( stats );
9317 #include <sys/ioctl.h>
9318 int get_term_width()
9320 int fd, default_width;
9323 default_width = 79; // this is FICS default anyway...
9325 #if !defined(TIOCGWINSZ) && defined(TIOCGSIZE)
9327 if (!ioctl(fd, TIOCGSIZE, &win))
9328 default_width = win.ts_cols;
9329 #elif defined(TIOCGWINSZ)
9331 if (!ioctl(fd, TIOCGWINSZ, &win))
9332 default_width = win.ws_col;
9334 return default_width;
9337 void update_ics_width()
9339 static int old_width = 0;
9340 int new_width = get_term_width();
9342 if (old_width != new_width)
9343 ics_printf("set width %d\n", new_width);
9344 old_width = new_width;
9347 void NotifyFrontendLogin()